public Emit <Func <int> > EmitByteCode(CompilerContext context, Emit <Func <int> > emiter) { var thenLabel = emiter.DefineLabel(); var elseLabel = emiter.DefineLabel(); var endLabel = emiter.DefineLabel(); Condition.EmitByteCode(context, emiter); emiter.BranchIfTrue(thenLabel); emiter.Branch(elseLabel); emiter.MarkLabel(thenLabel); ThenStmt.EmitByteCode(context, emiter); emiter.Branch(endLabel); emiter.MarkLabel(elseLabel); ElseStmt.EmitByteCode(context, emiter); emiter.Branch(endLabel); emiter.MarkLabel(endLabel); return(emiter); }
public void EmitSerialize(Emit emiter, Local value) { var elementType = value.LocalType.GetElementType(); using (var length = emiter.DeclareLocal <int>("length")) { // length = value.Length emiter.LoadLocal(value); emiter.Call(value.LocalType.GetProperty(nameof(Array.Length)).GetMethod); emiter.StoreLocal(length); emiter.CallSerializerForType(length.LocalType, length); var loop = emiter.DefineLabel(); var loopCheck = emiter.DefineLabel(); using (var element = emiter.DeclareLocal(elementType, "element")) using (var i = emiter.DeclareLocal <int>("i")) { emiter.Branch(loopCheck); emiter.MarkLabel(loop); // element = value[i] emiter.LoadLocal(value); emiter.LoadLocal(i); emiter.LoadElement(elementType); emiter.StoreLocal(element); if (_compiler != null) { _compiler.EmitSerialize(emiter, element); } else if (_serializer != null) { emiter.CallSerializer(_serializer, element); } else { emiter.CallSerializerForType(elementType, element); } // ++i emiter.LoadLocal(i); emiter.LoadConstant(1); emiter.Add(); emiter.StoreLocal(i); // i < length emiter.MarkLabel(loopCheck); emiter.LoadLocal(i); emiter.LoadLocal(length); emiter.BranchIfLess(loop); } } }
public Emit <Func <int> > EmitByteCode(CompilerContext context, Emit <Func <int> > emiter) { var loopLabel = emiter.DefineLabel(); var outLabel = emiter.DefineLabel(); emiter.MarkLabel(loopLabel); Condition.EmitByteCode(context, emiter); emiter.BranchIfFalse(outLabel); BlockStmt.EmitByteCode(context, emiter); emiter.Branch(loopLabel); emiter.MarkLabel(outLabel); return(emiter); }
public void EmitSerialize(Emit emiter, Local value) { var elementType = value.LocalType.GetElementType(); using (var length = emiter.DeclareLocal <int>("length")) { // length = value.Length emiter.LoadLocal(value); emiter.Call(value.LocalType.GetProperty(nameof(Array.Length)).GetMethod); emiter.StoreLocal(length); emiter.CallSerializerForType(length.LocalType, length); var loop = emiter.DefineLabel(); var loopCheck = emiter.DefineLabel(); using (var element = emiter.DeclareLocal(elementType, "element")) using (var i = emiter.DeclareLocal <int>("i")) { emiter.Branch(loopCheck); emiter.MarkLabel(loop); // element = value[i] emiter.LoadLocal(value); emiter.LoadLocal(i); emiter.LoadElement(elementType); emiter.StoreLocal(element); // writer.Write((byte)i) emiter.LoadArgument(1); emiter.LoadLocal(i); emiter.Convert <byte>(); emiter.CallVirtual(typeof(BinaryWriter).GetMethod(nameof(BinaryWriter.Write), new[] { typeof(byte) })); emiter.CallSerializerForType(elementType, element); // ++i emiter.LoadLocal(i); emiter.LoadConstant(1); emiter.Add(); emiter.StoreLocal(i); // i < length emiter.MarkLabel(loopCheck); emiter.LoadLocal(i); emiter.LoadLocal(length); emiter.BranchIfLess(loop); } } }
public void EmitSerialize(Emit emiter, Local value) { // ToDo check for null var elementType = value.LocalType.GetElementType(); using (var length = emiter.DeclareLocal <int>("length")) { // length = value.Length emiter.LoadLocal(value); emiter.Call(value.LocalType.GetProperty(nameof(Array.Length)).GetMethod); emiter.StoreLocal(length); // ProudNetBinaryWriterExtensions.WriteScalar(writer, length) emiter.LoadArgument(1); emiter.LoadLocal(length); emiter.Call(ReflectionHelper.GetMethod((BinaryWriter x) => x.WriteScalar(default(int)))); var loop = emiter.DefineLabel(); var loopCheck = emiter.DefineLabel(); using (var element = emiter.DeclareLocal(elementType, "element")) using (var i = emiter.DeclareLocal <int>("i")) { emiter.Branch(loopCheck); emiter.MarkLabel(loop); // element = value[i] emiter.LoadLocal(value); emiter.LoadLocal(i); emiter.LoadElement(elementType); emiter.StoreLocal(element); emiter.CallSerializerForType(elementType, element); // ++i emiter.LoadLocal(i); emiter.LoadConstant(1); emiter.Add(); emiter.StoreLocal(i); // i < length emiter.MarkLabel(loopCheck); emiter.LoadLocal(i); emiter.LoadLocal(length); emiter.BranchIfLess(loop); } } }
public void EmitSerialize(Emit emiter, Local value) { using (var address = emiter.DeclareLocal <string>("str")) using (var port = emiter.DeclareLocal <ushort>("port")) { var isNull = emiter.DefineLabel(); var write = emiter.DefineLabel(); // if (value == null) goto isNull emiter.LoadLocal(value); emiter.LoadNull(); emiter.BranchIfEqual(isNull); // address = value.Address.ToString() emiter.LoadLocal(value); emiter.Call(typeof(IPEndPoint).GetProperty(nameof(IPEndPoint.Address)).GetMethod); emiter.CallVirtual(typeof(IPAddress).GetMethod(nameof(IPAddress.ToString))); emiter.StoreLocal(address); // port = (ushort)value.Port emiter.LoadLocal(value); emiter.Call(typeof(IPEndPoint).GetProperty(nameof(IPEndPoint.Port)).GetMethod); emiter.Convert <ushort>(); emiter.StoreLocal(port); emiter.Branch(write); emiter.MarkLabel(isNull); // address = "255.255.255.255" emiter.LoadConstant("255.255.255.255"); emiter.StoreLocal(address); emiter.MarkLabel(write); // ProudNetSrcBinaryWriterExtensions.WriteProudString(writer, address, false) emiter.LoadArgument(1); emiter.LoadLocal(address); emiter.LoadConstant(false); emiter.Call(ReflectionHelper.GetMethod((BinaryWriter x) => x.WriteProudString(default(string), default(bool)))); // writer.Write(port) emiter.CallSerializerForType(typeof(ushort), port); } }
public void EmitSerialize(Emit emiter, Local value) { var elementType = value.LocalType.GetElementType(); using (var length = emiter.DeclareLocal <short>("length")) { // length = value.Length emiter.LoadLocal(value); emiter.Call(value.LocalType.GetProperty(nameof(Array.Length)).GetMethod); emiter.StoreLocal(length); emiter.CallSerializerForType(length.LocalType, length); var loop = emiter.DefineLabel(nameof(ArrayWithScalarSerializer) + "Loop" + Guid.NewGuid()); var loopCheck = emiter.DefineLabel(nameof(ArrayWithScalarSerializer) + "LoopCheck" + Guid.NewGuid()); using (var element = emiter.DeclareLocal(elementType, "element")) using (var i = emiter.DeclareLocal <int>("i")) { emiter.Branch(loopCheck); emiter.MarkLabel(loop); // element = value[i] emiter.LoadLocal(value); emiter.LoadLocal(i); emiter.LoadElement(elementType); emiter.StoreLocal(element); emiter.CallSerializerForType(elementType, element); // ++i emiter.LoadLocal(i); emiter.LoadConstant(1); emiter.Add(); emiter.StoreLocal(i); // i < length emiter.MarkLabel(loopCheck); emiter.LoadLocal(i); emiter.LoadLocal(length); emiter.BranchIfLess(loop); } } }
public void EmitSerialize(Emit <Action <BinaryWriter, object> > emiter, Local value) { var elementType = value.LocalType.GetElementType(); if (_length <= 0) { return; } var loop = emiter.DefineLabel(nameof(ArrayWithScalarSerializer) + "Loop" + Guid.NewGuid()); var loopCheck = emiter.DefineLabel(nameof(ArrayWithScalarSerializer) + "LoopCheck" + Guid.NewGuid()); using (var element = emiter.DeclareLocal(elementType, "element")) using (var i = emiter.DeclareLocal <int>("i")) { emiter.Branch(loopCheck); emiter.MarkLabel(loop); // element = value[i] emiter.LoadLocal(value); emiter.LoadLocal(i); emiter.LoadElement(elementType); emiter.StoreLocal(element); emiter.CallSerializerForType(elementType, element); // ++i emiter.LoadLocal(i); emiter.LoadConstant(1); emiter.Add(); emiter.StoreLocal(i); // i < length emiter.MarkLabel(loopCheck); emiter.LoadLocal(i); emiter.LoadConstant(_length); emiter.BranchIfLess(loop); } }
public void EmitDeserialize(Emit <Func <BinaryReader, object> > emiter, Local value) { var elementType = value.LocalType.GetElementType(); var emptyArray = emiter.DefineLabel(nameof(ArrayWithIntPrefixAndIndexSerializer) + "EmptyArray" + Guid.NewGuid()); var end = emiter.DefineLabel(nameof(ArrayWithIntPrefixAndIndexSerializer) + "End" + Guid.NewGuid()); using (var length = emiter.DeclareLocal <int>("length")) { emiter.CallDeserializerForType(length.LocalType, length); // if(length < 1) { // value = Array.Empty<>() // return // } emiter.LoadLocal(length); emiter.LoadConstant(1); emiter.BranchIfLess(emptyArray); // value = new [length] emiter.LoadLocal(length); emiter.NewArray(elementType); emiter.StoreLocal(value); var loop = emiter.DefineLabel(nameof(ArrayWithIntPrefixAndIndexSerializer) + "Loop" + Guid.NewGuid()); var loopCheck = emiter.DefineLabel(nameof(ArrayWithIntPrefixAndIndexSerializer) + "LoopCheck" + Guid.NewGuid()); using (var element = emiter.DeclareLocal(elementType, "element")) using (var i = emiter.DeclareLocal <int>("i")) { emiter.MarkLabel(loop); // reader.ReadByte() -> index emiter.LoadArgument(1); emiter.CallVirtual(typeof(BinaryReader).GetMethod(nameof(BinaryReader.ReadByte))); emiter.Pop(); emiter.CallDeserializerForType(elementType, element); // value[i] = element emiter.LoadLocal(value); emiter.LoadLocal(i); emiter.LoadLocal(element); emiter.StoreElement(elementType); // ++i emiter.LoadLocal(i); emiter.LoadConstant(1); emiter.Add(); emiter.StoreLocal(i); // i < length emiter.MarkLabel(loopCheck); emiter.LoadLocal(i); emiter.LoadLocal(length); emiter.BranchIfLess(loop); } emiter.Branch(end); } // value = Array.Empty<>() emiter.MarkLabel(emptyArray); emiter.Call(typeof(Array) .GetMethod(nameof(Array.Empty)) .GetGenericMethodDefinition() .MakeGenericMethod(elementType)); emiter.StoreLocal(value); emiter.MarkLabel(end); }
public void EmitDeserialize(Emit emiter, Local value) { var elementType = value.LocalType.GetElementType(); var emptyArray = emiter.DefineLabel(); var end = emiter.DefineLabel(); using (var length = emiter.DeclareLocal <short>("length")) { emiter.CallDeserializerForType(length.LocalType, length); // if(length < 1) { // value = Array.Empty<>() // return // } emiter.LoadLocal(length); emiter.LoadConstant(1); emiter.BranchIfLess(emptyArray); // value = new [length] emiter.LoadLocal(length); emiter.NewArray(elementType); emiter.StoreLocal(value); var loop = emiter.DefineLabel(); var loopCheck = emiter.DefineLabel(); // Little optimization for byte arrays if (elementType == typeof(byte)) { // value = reader.ReadBytes(length); emiter.LoadArgument(1); emiter.LoadLocal(length); emiter.CallVirtual(typeof(BinaryReader).GetMethod(nameof(BinaryReader.ReadBytes))); emiter.StoreLocal(value); emiter.Branch(end); } else { using (var element = emiter.DeclareLocal(elementType, "element")) using (var i = emiter.DeclareLocal <int>("i")) { emiter.MarkLabel(loop); emiter.CallDeserializerForType(elementType, element); // value[i] = element emiter.LoadLocal(value); emiter.LoadLocal(i); emiter.LoadLocal(element); emiter.StoreElement(elementType); // ++i emiter.LoadLocal(i); emiter.LoadConstant(1); emiter.Add(); emiter.StoreLocal(i); // i < length emiter.MarkLabel(loopCheck); emiter.LoadLocal(i); emiter.LoadLocal(length); emiter.BranchIfLess(loop); } } emiter.Branch(end); } // value = Array.Empty<>() emiter.MarkLabel(emptyArray); emiter.Call(typeof(Array) .GetMethod(nameof(Array.Empty)) .GetGenericMethodDefinition() .MakeGenericMethod(elementType)); emiter.StoreLocal(value); emiter.MarkLabel(end); }
public override void Emit <T>(Emit <T> emitter) { emitter.Branch(_label); }
private static void SerializeValueArray(PropertyInfo propInfo, Emit <Action <T, StringBuilder, StringBuilder> > serializationEmitter) { var loopBodyLabel = serializationEmitter.DefineLabel(); var loopConditionLabel = serializationEmitter.DefineLabel(); var elementType = propInfo.PropertyType.GetElementType(); var isString = elementType == typeof(string); using (var stringLocal = serializationEmitter.DeclareLocal <string>()) using (var iterationLocal = serializationEmitter.DeclareLocal <int>()) { serializationEmitter.LoadConstant(0); serializationEmitter.StoreLocal(iterationLocal); serializationEmitter.Branch(loopConditionLabel); serializationEmitter.MarkLabel(loopBodyLabel); serializationEmitter.LoadConstant(isString ? @"'{0}', " : "{0}, "); serializationEmitter.LoadArgument(0); // instance serializationEmitter.CallVirtual(propInfo.GetGetMethod()); serializationEmitter.LoadLocal(iterationLocal); serializationEmitter.LoadElement(elementType); if (isString) { serializationEmitter.Call(stringEscape); serializationEmitter.LoadConstant(Environment.NewLine); serializationEmitter.LoadConstant(@"\n"); serializationEmitter.CallVirtual(stringReplace); } else { serializationEmitter.Box(elementType); } serializationEmitter.Call(stringFormat); serializationEmitter.StoreLocal(stringLocal); // Append to hotfix builder serializationEmitter.LoadArgument(1); // hotfixBuilder serializationEmitter.LoadLocal(stringLocal); serializationEmitter.Call(stringBuilderAppend); serializationEmitter.Pop(); if (isString) { // Append to locale builder if (localeBuilder != null) var localeBuilderMarker = serializationEmitter.DefineLabel(); serializationEmitter.LoadArgument(2); // instanceBuilder serializationEmitter.LoadNull(); serializationEmitter.CompareEqual(); serializationEmitter.BranchIfTrue(localeBuilderMarker); serializationEmitter.LoadArgument(2); // instanceBuilder serializationEmitter.LoadLocal(stringLocal); serializationEmitter.Call(stringBuilderAppend); serializationEmitter.Pop(); serializationEmitter.MarkLabel(localeBuilderMarker); } serializationEmitter.LoadLocal(iterationLocal); serializationEmitter.LoadConstant(1); serializationEmitter.Add(); serializationEmitter.StoreLocal(iterationLocal); serializationEmitter.MarkLabel(loopConditionLabel); serializationEmitter.LoadLocal(iterationLocal); serializationEmitter.LoadArgument(0); // instance serializationEmitter.CallVirtual(propInfo.GetGetMethod()); serializationEmitter.LoadLength(elementType); serializationEmitter.Convert <int>(); serializationEmitter.CompareLessThan(); serializationEmitter.BranchIfTrue(loopBodyLabel); } }
void ExpectRawCharOrNull(char c, Action ifChar, Action ifNull) { var gotQuote = Emit.DefineLabel(); var gotN = Emit.DefineLabel(); var done = Emit.DefineLabel(); RawReadChar(() => ThrowExpected("\"", "null")); // int Emit.Duplicate(); // int int Emit.LoadConstant((int)c); // int int int Emit.BranchIfEqual(gotQuote); // int Emit.LoadConstant((int)'n'); // int n Emit.BranchIfEqual(gotN); // --empty-- ThrowExpected("\"", "null"); // --empty-- Emit.MarkLabel(gotQuote); // int Emit.Pop(); // --empty-- ifChar(); // ??? Emit.Branch(done); // ??? Emit.MarkLabel(gotN); // --empty-- ExpectChar('u'); // --empty-- ExpectChar('l'); // --empty-- ExpectChar('l'); // --empty-- ifNull(); // ??? Emit.MarkLabel(done); // --empty-- }
private void GenerateFunctionInner(Emit<MuftecFunction> funcDef, Queue<MuftecStackItem> execStack, Local runtimeStack, MuftecStackItem lastItem = default(MuftecStackItem)) { DebugMsg("- Call stack -> {0}", String.Join(", ", execStack.ToArray())); var stackPush = typeof (Stack<MuftecStackItem>).GetMethod("Push"); while (execStack.Count > 0) { var currStackItem = execStack.Dequeue(); DebugMsg("- Popping stack item: " + currStackItem.ToDebugString()); switch (currStackItem.Type) { // Run a user defined function case MuftecType.Function: // Find the function and create an IL call var funcName = currStackItem.Item.ToString(); DebugMsg(" -- Call function {0}", funcName); var func = _funcCache[funcName]; funcDef.LoadArgument(0); // Load OpCodeData into stack funcDef.Call(func); break; // Execute a library opcode case MuftecType.OpCode: // Translate opcode into direct call var opCodeName = currStackItem.Item.ToString(); DebugMsg(" >> Call opcode {0}", opCodeName); var opCode = _system.FindOpCode(opCodeName); // If this is an internal opcode, we need to handle it at this level if (opCode.Attribute.Extern) { switch (opCode.Attribute.OpCodeName) { case "!": case "@": throw new MuftecCompilerException("Variables not supported in the fabricator at line " + currStackItem.LineNumber); case "loadlibdll": funcDef.LoadLocal(runtimeStack); funcDef.Call(typeof (Shared).GetMethod("PopStr")); _system.AddLibrary(lastItem.ToString()); break; } } else { funcDef.LoadArgument(0); // Load OpCodeData into the stack funcDef.Call(opCode.Pointer.Method); // Call OpCode function } // Handle post-execution magic var magic = opCode.Attribute.Magic; switch (magic) { case MagicOpcodes.Abort: // End exeuction DebugMsg(" ---- Abort"); funcDef.LoadConstant(0); funcDef.Call(typeof (Environment).GetMethod("Exit")); return; case MagicOpcodes.Exit: DebugMsg(" ---- Exit"); // Exit out of this loop return; } break; // Handle a conditional container case MuftecType.Conditional: var container = currStackItem.Item as ConditionalContainer; if (container == null) throw new MuftecCompilerException("Unable to process conditional statement at line " + currStackItem.LineNumber); DebugMsg(" -- Container"); var ltLabel = funcDef.DefineLabel(); var endLabel = funcDef.DefineLabel(); funcDef.LoadLocal(runtimeStack); // Get the RuntimeStack funcDef.Call(typeof (Shared).GetMethod("PopInt")); // Call PopInt on RuntimeStack funcDef.BranchIfFalse(ltLabel); // GT operations DebugMsg(" -- Starting true condition"); GenerateFunctionInner(funcDef, container.TrueQueue, runtimeStack, lastItem); funcDef.Branch(endLabel); // LT operations funcDef.MarkLabel(ltLabel); DebugMsg(" -- Starting false condition"); GenerateFunctionInner(funcDef, container.FalseQueue, runtimeStack, lastItem); funcDef.MarkLabel(endLabel); DebugMsg(" -- Conditions done"); break; // Add item to the runtime stack case MuftecType.Integer: DebugMsg(" -- Pushing int {0} to RS", currStackItem.ToString()); funcDef.LoadLocal(runtimeStack); // Get the RuntimeStack funcDef.LoadConstant((int)currStackItem.Item); funcDef.LoadConstant(currStackItem.LineNumber); funcDef.NewObject<MuftecStackItem, int, int>(); funcDef.Call(stackPush); break; case MuftecType.Float: DebugMsg(" -- Pushing float {0} to RS", currStackItem.ToString()); funcDef.LoadLocal(runtimeStack); // Get the RuntimeStack funcDef.LoadConstant((double)currStackItem.Item); funcDef.LoadConstant(currStackItem.LineNumber); funcDef.NewObject<MuftecStackItem, double, int>(); funcDef.Call(stackPush); break; case MuftecType.String: DebugMsg(" -- Pushing string {0} to RS", currStackItem.ToString()); funcDef.LoadLocal(runtimeStack); // Get the RuntimeStackp = funcDef.LoadConstant((string)currStackItem.Item); funcDef.LoadConstant(currStackItem.LineNumber); funcDef.NewObject<MuftecStackItem, string, int>(); funcDef.Call(stackPush); break; case MuftecType.ArrayMarker: DebugMsg(" -- Pushing array marker to RS"); funcDef.LoadLocal(runtimeStack); // Get the RuntimeStack funcDef.LoadConstant((int)currStackItem.Item); funcDef.Call(typeof(MuftecStackItem).GetMethod("CreateArrayMarker")); funcDef.Call(stackPush); break; } lastItem = currStackItem; } }
public static Emit <Func <IEnumerable <object>, IEnumerable <T> > > GenerateMapper <T>() { Type type = typeof(T); Emit <Func <IEnumerable <object>, IEnumerable <T> > > emit = null; if (_mappers.ContainsKey(type.FullName)) { emit = (Emit <Func <IEnumerable <object>, IEnumerable <T> > >)_mappers[type.FullName]; } else { ConstructorInfo listConstructor = typeof(List <T>).GetConstructor(new Type[] { }); MethodInfo listAdd = typeof(List <T>).GetMethod("Add", new Type[] { typeof(T) }); Emit <Func <IEnumerable <object>, IEnumerable <T> > > emiter = Emit <Func <IEnumerable <object>, IEnumerable <T> > > .NewDynamicMethod(type.Name + "Mapper"); var enumeratorLocal = emiter.DeclareLocal <IEnumerator <object> >("enumerator"); var listLocal = emiter.DeclareLocal <List <T> >("list"); var cacheLocal = emiter.DeclareLocal <IDictionary <object, object> >("cache"); var loopFinishedLabel = emiter.DefineLabel("loopFinished"); var loopCheckLabel = emiter.DefineLabel("loopCheck"); var loopBeginLabel = emiter.DefineLabel("loopBegin"); var finallyFinishedLabel = emiter.DefineLabel("finallyFinished"); var isNullLabel = emiter.DefineLabel("isNull"); emiter.NewObject(listConstructor); emiter.StoreLocal(listLocal); emiter.NewObject(DictionaryConstructor_Object_Object); emiter.StoreLocal(cacheLocal); emiter.LoadArgument(0); emiter.CallVirtual(IEnumerable_Object_GetEnumerator); emiter.StoreLocal(enumeratorLocal); //try { var exceptionBlock = emiter.BeginExceptionBlock(); emiter.Branch(loopCheckLabel); emiter.MarkLabel(loopBeginLabel); emiter.LoadLocal(listLocal); emiter.LoadLocal(enumeratorLocal); emiter.CallVirtual(IEnumerator_Object_GetCurrent); emiter.CastClass <IDictionary <string, object> >(); emiter.LoadLocal(cacheLocal); emiter.LoadConstant(""); emiter.Call(GenerateRowMapper(type)); // var rowResult = rowMapper ( row, cache, depthString = "" ); emiter.Duplicate(); emiter.LoadNull(); emiter.BranchIfEqual(isNullLabel); emiter.CastClass(typeof(T)); emiter.Call(listAdd); // listLocal.Add((T)rowResult); emiter.Branch(loopCheckLabel); emiter.MarkLabel(isNullLabel); emiter.Pop(); emiter.Pop(); emiter.MarkLabel(loopCheckLabel); emiter.LoadLocal(enumeratorLocal); emiter.CallVirtual(IEnumerator_MoveNext); emiter.BranchIfTrue(loopBeginLabel); emiter.Leave(loopFinishedLabel); //} //finallY { var finallyBlock = emiter.BeginFinallyBlock(exceptionBlock); emiter.LoadNull(); emiter.LoadLocal(enumeratorLocal); emiter.CompareEqual(); emiter.BranchIfTrue(finallyFinishedLabel); emiter.LoadLocal(enumeratorLocal); emiter.CallVirtual(IEnumerator_Dispose); emiter.MarkLabel(finallyFinishedLabel); emiter.EndFinallyBlock(finallyBlock); emiter.EndExceptionBlock(exceptionBlock); //} emiter.MarkLabel(loopFinishedLabel); emiter.LoadLocal(listLocal); emiter.Return(); // return listLocal; _mapperDelegates.Add(type.FullName, emiter.CreateDelegate()); _mappers.Add(type.FullName, emiter); emit = emiter; } return(emit); }
public void EmitDeserialize(Emit emiter, Local value) { var elementType = value.LocalType.GetElementType(); var emptyArray = emiter.DefineLabel(); var end = emiter.DefineLabel(); using (var length = emiter.DeclareLocal <T>("length")) { emiter.CallDeserializerForType(length.LocalType, length); // if(length < 1) { // value = Array.Empty<>() // return // } emiter.LoadLocal(length); emiter.LoadConstant(1); emiter.BranchIfLess(emptyArray); // value = new [length] emiter.LoadLocal(length); emiter.NewArray(elementType); emiter.StoreLocal(value); var loop = emiter.DefineLabel(); var loopCheck = emiter.DefineLabel(); using (var element = emiter.DeclareLocal(elementType, "element")) using (var i = emiter.DeclareLocal <T>("i")) { emiter.MarkLabel(loop); if (_compiler != null) { _compiler.EmitDeserialize(emiter, element); } else if (_serializer != null) { emiter.CallDeserializer(_serializer, element); } else { emiter.CallDeserializerForType(elementType, element); } // value[i] = element emiter.LoadLocal(value); emiter.LoadLocal(i); emiter.LoadLocal(element); emiter.StoreElement(elementType); // ++i emiter.LoadLocal(i); emiter.LoadConstant(1); emiter.Add(); emiter.StoreLocal(i); // i < length emiter.MarkLabel(loopCheck); emiter.LoadLocal(i); emiter.LoadLocal(length); emiter.BranchIfLess(loop); } emiter.Branch(end); } // value = Array.Empty<>() emiter.MarkLabel(emptyArray); emiter.Call(typeof(Array) .GetMethod(nameof(Array.Empty)) .GetGenericMethodDefinition() .MakeGenericMethod(elementType)); emiter.StoreLocal(value); emiter.MarkLabel(end); }