示例#1
0
        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);
        }
示例#2
0
文件: IWriter.cs 项目: lanicon/Enzyme
        public void EmitWrite(WriterEmitContext context)
        {
            context.LoadBuffer();
            context.LoadValue();

            EmitWriteImpl(context);
        }
示例#3
0
        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
            }
        }
示例#4
0
        void EmitClassWriter(WriterEmitContext ctx)
        {
            var il      = ctx.Il;
            var nullLbl = il.DefineLabel();
            var end     = il.DefineLabel();

            ctx.LoadValue();
            il.Emit(OpCodes.Brfalse, nullLbl);

            EmitNonNullWriter(ctx);
            il.Emit(OpCodes.Br, end);

            // writing null
            il.MarkLabel(nullLbl);
            if (ctx.HasManifestToWrite == false)
            {
                ctx.LoadBuffer();
                il.LoadIntValue(NullLength);
                il.StoreIndirectLittleEndian(typeof(short));
                il.LoadIntValue(2); // used only 2 bytes for writing null
                ctx.AddToCurrentOffset();
            }
            else
            {
                // no value, nothing to write
            }

            il.MarkLabel(end);
        }
示例#5
0
 public void EmitWrite(WriterEmitContext context)
 {
     context.LoadBuffer();
     context.LoadValue();
     context.CallWriteStringUnsafe();
     context.AddToCurrentOffset();
 }
示例#6
0
            public void WriteManifest()
            {
                if (HasManifestToWrite)
                {
                    context.LoadBuffer();
                    context.Il.LoadIntValue(manifest.Value);
                    context.Il.StoreIndirectLittleEndian(typeof(short));

                    context.Il.LoadIntValue(2);
                    context.AddToCurrentOffset();
                }
                else
                {
                    throw new Exception("No manifest to write");
                }
            }
示例#7
0
        public void EmitWrite(WriterEmitContext context)
        {
            var il = context.Il;

            using (context.GetLocal <int>(out var length))
            {
                context.LoadValue();
                il.EmitCall(OpCodes.Call, typeof(Span <byte>).GetProperty(nameof(Span <byte> .Length)).GetGetMethod(), null);
                il.Store(length);

                context.LoadValue();                                                                                                // stack: span

                context.LoadBuffer();                                                                                               // stack: span, buffer
                il.Load(length);                                                                                                    // stack: span, buffer, length

                il.Emit(OpCodes.Newobj, typeof(Span <byte>).GetConstructor(new[] { typeof(void).MakePointerType(), typeof(int) })); //stack: span-source, span-dest

                il.EmitCall(OpCodes.Call, typeof(Span <byte>).GetMethod(nameof(Span <byte> .CopyTo)), null);
                il.Load(length);
                context.AddToCurrentOffset();
            }
        }