void EmitNonNullWriter(WriterEmitContext ctx) { var il = ctx.Il; if (ctx.HasManifestToWrite) { ctx.WriteManifest(); } using (ctx.GetLocal <int>(out var offset)) { ctx.LoadCurrentOffset(); il.Store(offset); // add 2 for the length of variable il.LoadIntValue(2); ctx.AddToCurrentOffset(); Writer.EmitWrite(ctx); // stack empty, value written directly to the buffer ctx.LoadBuffer(offset); // stack: byte* ctx.LoadCurrentOffset(); il.Load(offset); il.Emit(OpCodes.Sub); // stack: byte*, value il.LoadIntValue(2); il.Emit(OpCodes.Sub); // -2 for length il.StoreIndirectLittleEndian(typeof(short)); // save length } }
public void EmitWrite(WriterEmitContext context) { var il = context.Il; foreach (var field in fields) { var writer = AllWriters.GetWriter(field); var manifest = GetManifestValue(field); void LoadValue() { il.Emit(writer.RequiresAddress ? OpCodes.Ldflda : OpCodes.Ldfld, field); } using (context.Scope(LoadValue, manifest: manifest)) { // if the writer does not write manifest, this will write manifest for the writer if (writer is IWriteManifest == false) { context.WriteManifest(); } writer.EmitWrite(context); } if (writer is IUpdateOffset == false) { context.AddToCurrentOffset(); } } }
public void EmitWrite(WriterEmitContext context) { var nullable = typeof(TPrimitive?); var il = context.Il; var hasValue = il.DefineLabel(); var end = il.DefineLabel(); context.LoadValue(); il.EmitCall(OpCodes.Call, nullable.GetProperty(nameof(Nullable <int> .HasValue)).GetGetMethod(), null); il.Emit(OpCodes.Brtrue_S, hasValue); // no value, just store 0 and return length = 1 if (context.HasManifestToWrite == false) { context.LoadBuffer(); il.LoadIntValue(0); il.Emit(OpCodes.Stind_I1); il.LoadIntValue(1); il.Emit(OpCodes.Br, end); // jump to the end of writing } else { il.LoadIntValue(0); il.Emit(OpCodes.Br, end); // jump to the end of writing } // has value, store 1, then store value il.MarkLabel(hasValue); if (context.HasManifestToWrite == false) { context.LoadBuffer(); il.LoadIntValue(1); il.Emit(OpCodes.Stind_I1); il.LoadIntValue(1); context.AddToCurrentOffset(); } else { context.WriteManifest(); } // load shifted buffer and value context.LoadBuffer(); context.LoadValue(); il.EmitCall(OpCodes.Call, nullable.GetProperty(nameof(Nullable <int> .Value)).GetGetMethod(), null); // emit regular Emit(context); il.MarkLabel(end); }