示例#1
0
        public void Ctor()
        {
            var code = new BlobBuilder();
            var flow = new ControlFlowBuilder();
            var ie = new InstructionEncoder(code, flow);
            Assert.Same(ie.CodeBuilder, code);
            Assert.Same(ie.ControlFlowBuilder, flow);

            Assert.Throws<ArgumentNullException>(() => new InstructionEncoder(null));
        }
示例#2
0
        public void TokenInstructions()
        {
            var builder = new BlobBuilder();
            var il = new InstructionEncoder(builder);
            Assert.Equal(0, il.Offset);

            il.Token(MetadataTokens.TypeDefinitionHandle(0x123456));
            Assert.Equal(4, il.Offset);

            il.Token(0x7F7E7D7C);
            Assert.Equal(8, il.Offset);

            il.LoadString(MetadataTokens.UserStringHandle(0x010203));
            Assert.Equal(13, il.Offset);

            il.Call(MetadataTokens.MethodDefinitionHandle(0xA0A1A2));
            Assert.Equal(18, il.Offset);

            il.Call(MetadataTokens.MethodSpecificationHandle(0xB0B1B2));
            Assert.Equal(23, il.Offset);

            il.Call(MetadataTokens.MemberReferenceHandle(0xC0C1C2));
            Assert.Equal(28, il.Offset);

            il.Call((EntityHandle)MetadataTokens.MethodDefinitionHandle(0xD0D1D2));
            Assert.Equal(33, il.Offset);

            il.Call((EntityHandle)MetadataTokens.MethodSpecificationHandle(0xE0E1E2));
            Assert.Equal(38, il.Offset);

            il.Call((EntityHandle)MetadataTokens.MemberReferenceHandle(0xF0F1F2));
            Assert.Equal(43, il.Offset);

            il.CallIndirect(MetadataTokens.StandaloneSignatureHandle(0x001122));
            Assert.Equal(48, il.Offset);

            AssertEx.Equal(new byte[]
            {
                0x56, 0x34, 0x12, 0x02,
                0x7C, 0x7D, 0x7E, 0x7F,
                (byte)ILOpCode.Ldstr, 0x03, 0x02, 0x01, 0x70,
                (byte)ILOpCode.Call, 0xA2, 0xA1, 0xA0, 0x06,
                (byte)ILOpCode.Call, 0xB2, 0xB1, 0xB0, 0x2B,
                (byte)ILOpCode.Call, 0xC2, 0xC1, 0xC0, 0x0A,
                (byte)ILOpCode.Call, 0xD2, 0xD1, 0xD0, 0x06,
                (byte)ILOpCode.Call, 0xE2, 0xE1, 0xE0, 0x2B,
                (byte)ILOpCode.Call, 0xF2, 0xF1, 0xF0, 0x0A,
                (byte)ILOpCode.Calli, 0x22, 0x11, 0x00, 0x11
            }, builder.ToArray());
        }
        public void AddMethodBody_Errors()
        {
            var streamBuilder = new BlobBuilder();
            var il = new InstructionEncoder(new BlobBuilder());

            Assert.Throws<ArgumentNullException>(() => new MethodBodyStreamEncoder(streamBuilder).AddMethodBody(default(InstructionEncoder)));
            Assert.Throws<ArgumentOutOfRangeException>(() => new MethodBodyStreamEncoder(streamBuilder).AddMethodBody(il, -1));
            Assert.Throws<ArgumentOutOfRangeException>(() => new MethodBodyStreamEncoder(streamBuilder).AddMethodBody(il, ushort.MaxValue + 1));

            Assert.Throws<ArgumentOutOfRangeException>(() => new MethodBodyStreamEncoder(streamBuilder).AddMethodBody(codeSize: -1));
            Assert.Throws<ArgumentOutOfRangeException>(() => new MethodBodyStreamEncoder(streamBuilder).AddMethodBody(codeSize: 1, maxStack: -1));
            Assert.Throws<ArgumentOutOfRangeException>(() => new MethodBodyStreamEncoder(streamBuilder).AddMethodBody(codeSize: 1, maxStack: ushort.MaxValue + 1));
            Assert.Throws<ArgumentOutOfRangeException>(() => new MethodBodyStreamEncoder(streamBuilder).AddMethodBody(codeSize: 1, exceptionRegionCount: -1));
            Assert.Throws<ArgumentOutOfRangeException>(() => new MethodBodyStreamEncoder(streamBuilder).AddMethodBody(codeSize: 1, exceptionRegionCount: 699051));
        }
示例#4
0
        public void OpCode()
        {
            var builder = new BlobBuilder();
            builder.WriteByte(0xff);

            var il = new InstructionEncoder(builder);
            Assert.Equal(1, il.Offset);

            il.OpCode(ILOpCode.Add);
            Assert.Equal(2, il.Offset);

            builder.WriteByte(0xee);
            Assert.Equal(3, il.Offset);

            il.OpCode(ILOpCode.Arglist);
            Assert.Equal(5, il.Offset);

            builder.WriteByte(0xdd);
            Assert.Equal(6, il.Offset);

            il.OpCode(ILOpCode.Readonly);
            Assert.Equal(8, il.Offset);

            builder.WriteByte(0xcc);
            Assert.Equal(9, il.Offset);

            AssertEx.Equal(new byte[]
            {
                0xFF,
                0x58,
                0xEE,
                0xFE, 0x00,
                0xDD,
                0xFE, 0x1E,
                0xCC
            }, builder.ToArray());
        }
        public void Branch_LongInstruction_LongDistance()
        {
            var code = new BlobBuilder();
            var flow = new ControlFlowBuilder();
            var il   = new InstructionEncoder(code, flow);

            var l1 = il.DefineLabel();

            il.Branch(ILOpCode.Br, l1);

            for (int i = 0; i < 256 / 5 + 1; i++)
            {
                il.Call(MetadataTokens.MethodDefinitionHandle(1));
            }

            il.MarkLabel(l1);
            il.OpCode(ILOpCode.Ret);

            var builder = new BlobBuilder();
            var encoder = new MethodBodyStreamEncoder(builder).AddMethodBody(il);

            AssertEx.Equal(new byte[]
            {
                0x13, 0x30, 0x08, 0x00, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,// header
                (byte)ILOpCode.Br, 0x04, 0x01, 0x00, 0x00,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Call, 0x01, 0x00, 0x00, 0x06,
                (byte)ILOpCode.Ret
            }, builder.ToArray());
        }
        public void BranchErrors()
        {
            var codeBuilder = new BlobBuilder();

            var il = new InstructionEncoder(codeBuilder);
            Assert.Throws<InvalidOperationException>(() => il.DefineLabel());

            il = new InstructionEncoder(codeBuilder, new BranchBuilder());
            il.DefineLabel();
            il.DefineLabel();
            var l2 = il.DefineLabel();

            var branchBuilder = new BranchBuilder();
            il = new InstructionEncoder(codeBuilder, branchBuilder);
            var l0 = il.DefineLabel();

            Assert.Throws<ArgumentException>(() => il.Branch(ILOpCode.Nop, l0));
            Assert.Throws<ArgumentNullException>(() => il.Branch(ILOpCode.Br, default(LabelHandle)));
            Assert.Throws<ArgumentException>(() => il.Branch(ILOpCode.Br, l2));
        }
        /// <summary>
        /// Encodes a method body and adds it to the method body stream.
        /// </summary>
        /// <param name="instructionEncoder">Instruction encoder.</param>
        /// <param name="maxStack">Max stack.</param>
        /// <param name="localVariablesSignature">Local variables signature handle.</param>
        /// <param name="attributes">Attributes.</param>
        /// <returns>The offset of the encoded body within the method body stream.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="instructionEncoder"/> has default value.</exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="maxStack"/> is out of range [0, <see cref="ushort.MaxValue"/>].</exception>
        /// <exception cref="InvalidOperationException">
        /// A label targeted by a branch in the instruction stream has not been marked,
        /// or the distance between a branch instruction and the target label is doesn't fit the size of the instruction operand.
        /// </exception>
        public int AddMethodBody(
            InstructionEncoder instructionEncoder, 
            int maxStack = 8,
            StandaloneSignatureHandle localVariablesSignature = default(StandaloneSignatureHandle),
            MethodBodyAttributes attributes = MethodBodyAttributes.InitLocals)
        {
            if (unchecked((uint)maxStack) > ushort.MaxValue)
            {
                Throw.ArgumentOutOfRange(nameof(maxStack));
            }

            // The branch fixup code expects the operands of branch instructions in the code builder to be contiguous.
            // That's true when we emit thru InstructionEncoder. Taking it as a parameter instead of separate 
            // code and flow builder parameters ensures they match each other.
            var codeBuilder = instructionEncoder.CodeBuilder;
            var flowBuilder = instructionEncoder.ControlFlowBuilder;

            if (codeBuilder == null)
            {
                Throw.ArgumentNull(nameof(instructionEncoder));
            }

            int exceptionRegionCount = flowBuilder?.ExceptionHandlerCount ?? 0;
            if (!ExceptionRegionEncoder.IsExceptionRegionCountInBounds(exceptionRegionCount))
            {
                Throw.ArgumentOutOfRange(nameof(instructionEncoder), SR.TooManyExceptionRegions);
            }

            int bodyOffset = SerializeHeader(codeBuilder.Count, (ushort)maxStack, exceptionRegionCount, attributes, localVariablesSignature);

            if (flowBuilder?.BranchCount > 0)
            {
                flowBuilder.CopyCodeAndFixupBranches(codeBuilder, Builder);
            }
            else
            {
                codeBuilder.WriteContentTo(Builder);
            }

            flowBuilder?.SerializeExceptionTable(Builder);
            
            return bodyOffset;
        }
示例#8
0
        private static MethodDefinitionHandle ComplexEmit(MetadataBuilder metadata, BlobBuilder ilBuilder)
        {
            metadata.AddModule(
                0,
                metadata.GetOrAddString("ConsoleApplication.exe"),
                metadata.GetOrAddGuid(Guid.NewGuid()),
                default(GuidHandle),
                default(GuidHandle));

            metadata.AddAssembly(
                metadata.GetOrAddString("ConsoleApplication"),
                version: new Version(0, 0, 0, 0),
                culture: default(StringHandle),
                publicKey: default(BlobHandle),
                flags: default(AssemblyFlags),
                hashAlgorithm: AssemblyHashAlgorithm.Sha1);

            var mscorlibAssemblyRef = metadata.AddAssemblyReference(
                name: metadata.GetOrAddString("mscorlib"),
                version: new Version(4, 0, 0, 0),
                culture: default(StringHandle),
                publicKeyOrToken: metadata.GetOrAddBlob(ImmutableArray.Create<byte>(0xB7, 0x7A, 0x5C, 0x56, 0x19, 0x34, 0xE0, 0x89)),
                flags: default(AssemblyFlags),
                hashValue: default(BlobHandle));

            // TypeRefs:

            var systemObjectTypeRef = metadata.AddTypeReference(mscorlibAssemblyRef, metadata.GetOrAddString("System"), metadata.GetOrAddString("Object"));
            var dictionaryTypeRef = metadata.AddTypeReference(mscorlibAssemblyRef, metadata.GetOrAddString("System.Collections.Generic"), metadata.GetOrAddString("Dictionary`2"));
            var strignBuilderTypeRef = metadata.AddTypeReference(mscorlibAssemblyRef, metadata.GetOrAddString("System.Text"), metadata.GetOrAddString("StringBuilder"));
            var typeTypeRef = metadata.AddTypeReference(mscorlibAssemblyRef, metadata.GetOrAddString("System"), metadata.GetOrAddString("Type"));
            var int32TypeRef = metadata.AddTypeReference(mscorlibAssemblyRef, metadata.GetOrAddString("System"), metadata.GetOrAddString("Int32"));
            var runtimeTypeHandleRef = metadata.AddTypeReference(mscorlibAssemblyRef, metadata.GetOrAddString("System"), metadata.GetOrAddString("RuntimeTypeHandle"));
            var invalidOperationExceptionTypeRef = metadata.AddTypeReference(mscorlibAssemblyRef, metadata.GetOrAddString("System"), metadata.GetOrAddString("InvalidOperationException"));

            // TypeDefs:

            metadata.AddTypeDefinition(
               default(TypeAttributes),
               default(StringHandle),
               metadata.GetOrAddString("<Module>"),
               baseType: default(EntityHandle),
               fieldList: MetadataTokens.FieldDefinitionHandle(1),
               methodList: MetadataTokens.MethodDefinitionHandle(1));

            var baseClassTypeDef = metadata.AddTypeDefinition(
                TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.AutoLayout | TypeAttributes.BeforeFieldInit | TypeAttributes.Abstract,
                metadata.GetOrAddString("Lib"),
                metadata.GetOrAddString("BaseClass"),
                systemObjectTypeRef,
                fieldList: MetadataTokens.FieldDefinitionHandle(1),
                methodList: MetadataTokens.MethodDefinitionHandle(1));

            var derivedClassTypeDef = metadata.AddTypeDefinition(
                TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.AutoLayout | TypeAttributes.BeforeFieldInit,
                metadata.GetOrAddString("Lib"),
                metadata.GetOrAddString("DerivedClass"),
                baseClassTypeDef,
                fieldList: MetadataTokens.FieldDefinitionHandle(4),
                methodList: MetadataTokens.MethodDefinitionHandle(1));

            // FieldDefs:

            // Field1
            var baseClassNumberFieldDef = metadata.AddFieldDefinition(
                FieldAttributes.Private,
                metadata.GetOrAddString("_number"),
                metadata.GetOrAddBlob(BuildSignature(e => e.FieldSignature().Int32())));

            // Field2
            var baseClassNegativeFieldDef = metadata.AddFieldDefinition(
                FieldAttributes.Assembly,
                metadata.GetOrAddString("negative"),
                metadata.GetOrAddBlob(BuildSignature(e => e.FieldSignature().Boolean())));

            // Field3
            var derivedClassSumCacheFieldDef = metadata.AddFieldDefinition(
                FieldAttributes.Assembly,
                metadata.GetOrAddString("_sumCache"),
                metadata.GetOrAddBlob(BuildSignature(e =>
                {
                    var inst = e.FieldSignature().GenericInstantiation(isValueType: false, typeRefDefSpec: dictionaryTypeRef, genericArgumentCount: 2);
                    inst.AddArgument().Int32();
                    inst.AddArgument().Object();
                })));

            // Field4
            var derivedClassCountFieldDef = metadata.AddFieldDefinition(
                FieldAttributes.Assembly,
                metadata.GetOrAddString("_count"),
                metadata.GetOrAddBlob(BuildSignature(e => e.FieldSignature().SZArray().Int32())));

            // Field5
            var derivedClassBCFieldDef = metadata.AddFieldDefinition(
              FieldAttributes.Assembly,
              metadata.GetOrAddString("_bc"),
              metadata.GetOrAddBlob(BuildSignature(e => e.FieldSignature().TypeDefOrRefOrSpec(isValueType: false, typeRefDefSpec: baseClassTypeDef))));

            var methodBodies = new MethodBodiesEncoder(ilBuilder);

            var buffer = new BlobBuilder();
            InstructionEncoder il;

            //
            // Foo
            //
            int fooBodyOffset;
            il = new InstructionEncoder(buffer);

            il.LoadString(metadata.GetOrAddUserString("asdsad"));
            il.OpCode(ILOpCode.Newobj);
            il.Token(invalidOperationExceptionTypeRef);
            il.OpCode(ILOpCode.Throw);

            methodBodies.AddMethodBody().WriteInstructions(buffer, out fooBodyOffset);
            buffer.Clear();

            // Method1
            var derivedClassFooMethodDef = metadata.AddMethodDefinition(
                MethodAttributes.PrivateScope | MethodAttributes.Private | MethodAttributes.HideBySig,
                MethodImplAttributes.IL,
                metadata.GetOrAddString("Foo"),
                metadata.GetOrAddBlob(BuildSignature(e =>
                    e.MethodSignature(isInstanceMethod: true).Parameters(0, returnType => returnType.Void(), parameters => parameters.EndParameters()))),
                fooBodyOffset,
                default(ParameterHandle));

            return default(MethodDefinitionHandle);
        }
示例#9
0
        public void MarkLabel()
        {
            var code = new BlobBuilder();
            var il = new InstructionEncoder(code, new ControlFlowBuilder());

            var l = il.DefineLabel();

            il.Branch(ILOpCode.Br_s, l);

            il.MarkLabel(l);
            il.OpCode(ILOpCode.Nop);
            il.OpCode(ILOpCode.Nop);

            il.MarkLabel(l);
            il.OpCode(ILOpCode.Ret);

            var builder = new BlobBuilder();
            new MethodBodyStreamEncoder(builder).AddMethodBody(il);

            AssertEx.Equal(new byte[]
            {
                0x16, // header
                (byte)ILOpCode.Br_s, 0x02,
                (byte)ILOpCode.Nop,
                (byte)ILOpCode.Nop,
                (byte)ILOpCode.Ret,
            }, builder.ToArray());
        }
示例#10
0
        public void Branch()
        {
            var builder = new BlobBuilder();
            var il = new InstructionEncoder(builder, new ControlFlowBuilder());
            var l = il.DefineLabel();

            il.Branch(ILOpCode.Br_s, l);
            il.Branch(ILOpCode.Brfalse_s, l);
            il.Branch(ILOpCode.Brtrue_s, l);
            il.Branch(ILOpCode.Beq_s, l);
            il.Branch(ILOpCode.Bge_s, l);
            il.Branch(ILOpCode.Bgt_s, l);
            il.Branch(ILOpCode.Ble_s, l);
            il.Branch(ILOpCode.Blt_s, l);
            il.Branch(ILOpCode.Bne_un_s, l);
            il.Branch(ILOpCode.Bge_un_s, l);
            il.Branch(ILOpCode.Bgt_un_s, l);
            il.Branch(ILOpCode.Ble_un_s, l);
            il.Branch(ILOpCode.Blt_un_s, l);
            il.Branch(ILOpCode.Leave_s, l);
            il.Branch(ILOpCode.Br, l);
            il.Branch(ILOpCode.Brfalse, l);
            il.Branch(ILOpCode.Brtrue, l);
            il.Branch(ILOpCode.Beq, l);
            il.Branch(ILOpCode.Bge, l);
            il.Branch(ILOpCode.Bgt, l);
            il.Branch(ILOpCode.Ble, l);
            il.Branch(ILOpCode.Blt, l);
            il.Branch(ILOpCode.Bne_un, l);
            il.Branch(ILOpCode.Bge_un, l);
            il.Branch(ILOpCode.Bgt_un, l);
            il.Branch(ILOpCode.Ble_un, l);
            il.Branch(ILOpCode.Blt_un, l);
            il.Branch(ILOpCode.Leave, l);

            AssertEx.Equal(new byte[]
            {
                (byte)ILOpCode.Br_s,      0xff,
                (byte)ILOpCode.Brfalse_s, 0xff,
                (byte)ILOpCode.Brtrue_s,  0xff,
                (byte)ILOpCode.Beq_s,     0xff,
                (byte)ILOpCode.Bge_s,     0xff,
                (byte)ILOpCode.Bgt_s,     0xff,
                (byte)ILOpCode.Ble_s,     0xff,
                (byte)ILOpCode.Blt_s,     0xff,
                (byte)ILOpCode.Bne_un_s,  0xff,
                (byte)ILOpCode.Bge_un_s,  0xff,
                (byte)ILOpCode.Bgt_un_s,  0xff,
                (byte)ILOpCode.Ble_un_s,  0xff,
                (byte)ILOpCode.Blt_un_s,  0xff,
                (byte)ILOpCode.Leave_s,   0xff,
                (byte)ILOpCode.Br,        0xff, 0xff, 0xff, 0xff,
                (byte)ILOpCode.Brfalse,   0xff, 0xff, 0xff, 0xff,
                (byte)ILOpCode.Brtrue,    0xff, 0xff, 0xff, 0xff,
                (byte)ILOpCode.Beq,       0xff, 0xff, 0xff, 0xff,
                (byte)ILOpCode.Bge,       0xff, 0xff, 0xff, 0xff,
                (byte)ILOpCode.Bgt,       0xff, 0xff, 0xff, 0xff,
                (byte)ILOpCode.Ble,       0xff, 0xff, 0xff, 0xff,
                (byte)ILOpCode.Blt,       0xff, 0xff, 0xff, 0xff,
                (byte)ILOpCode.Bne_un,    0xff, 0xff, 0xff, 0xff,
                (byte)ILOpCode.Bge_un,    0xff, 0xff, 0xff, 0xff,
                (byte)ILOpCode.Bgt_un,    0xff, 0xff, 0xff, 0xff,
                (byte)ILOpCode.Ble_un,    0xff, 0xff, 0xff, 0xff,
                (byte)ILOpCode.Blt_un,    0xff, 0xff, 0xff, 0xff,
                (byte)ILOpCode.Leave,     0xff, 0xff, 0xff, 0xff,
            }, builder.ToArray());
        }
 /// <summary>
 /// Encodes a method body and adds it to the method body stream.
 /// </summary>
 /// <param name="instructionEncoder">Instruction encoder.</param>
 /// <param name="maxStack">Max stack.</param>
 /// <param name="localVariablesSignature">Local variables signature handle.</param>
 /// <param name="attributes">Attributes.</param>
 /// <returns>The offset of the encoded body within the method body stream.</returns>
 /// <exception cref="ArgumentNullException"><paramref name="instructionEncoder"/> has default value.</exception>
 /// <exception cref="ArgumentOutOfRangeException"><paramref name="maxStack"/> is out of range [0, <see cref="ushort.MaxValue"/>].</exception>
 /// <exception cref="InvalidOperationException">
 /// A label targeted by a branch in the instruction stream has not been marked,
 /// or the distance between a branch instruction and the target label doesn't fit the size of the instruction operand.
 /// </exception>
 public int AddMethodBody(
     InstructionEncoder instructionEncoder,
     int maxStack,
     StandaloneSignatureHandle localVariablesSignature,
     MethodBodyAttributes attributes)
 => AddMethodBody(instructionEncoder, maxStack, localVariablesSignature, attributes, hasDynamicStackAllocation: false);
示例#12
0
        public static int GenerateMibcFile(TypeSystemContext tsc, FileInfo outputFileName, IEnumerable <MethodProfileData> methodsToAttemptToPlaceIntoProfileData, bool validate, bool uncompressed)
        {
            TypeSystemMetadataEmitter emitter = new TypeSystemMetadataEmitter(new AssemblyName(outputFileName.Name), tsc);

            SortedDictionary <string, MIbcGroup> groups     = new SortedDictionary <string, MIbcGroup>();
            StringBuilder    mibcGroupNameBuilder           = new StringBuilder();
            HashSet <string> assembliesAssociatedWithMethod = new HashSet <string>();

            foreach (var entry in methodsToAttemptToPlaceIntoProfileData)
            {
                MethodDesc method = entry.Method;
                assembliesAssociatedWithMethod.Clear();
                AddAssembliesAssociatedWithMethod(method, assembliesAssociatedWithMethod, out string definingAssembly);

                string[] assemblyNames = new string[assembliesAssociatedWithMethod.Count];
                int      i             = 1;
                assemblyNames[0] = definingAssembly;

                foreach (string s in assembliesAssociatedWithMethod)
                {
                    if (s.Equals(definingAssembly))
                    {
                        continue;
                    }
                    assemblyNames[i++] = s;
                }

                // Always keep the defining assembly as the first name
                Array.Sort(assemblyNames, 1, assemblyNames.Length - 1);
                mibcGroupNameBuilder.Clear();
                foreach (string s in assemblyNames)
                {
                    mibcGroupNameBuilder.Append(s);
                    mibcGroupNameBuilder.Append(';');
                }

                string mibcGroupName = mibcGroupNameBuilder.ToString();
                if (!groups.TryGetValue(mibcGroupName, out MIbcGroup mibcGroup))
                {
                    mibcGroup = new MIbcGroup(mibcGroupName, emitter);
                    groups.Add(mibcGroupName, mibcGroup);
                }
                mibcGroup.AddProcessedMethodData(entry);
            }

            var buffer = new BlobBuilder();
            var il     = new InstructionEncoder(buffer);

            foreach (var entry in groups)
            {
                il.LoadString(emitter.GetUserStringHandle(entry.Key));
                il.OpCode(ILOpCode.Ldtoken);
                il.Token(entry.Value.EmitMethod());
                il.OpCode(ILOpCode.Pop);
            }

            emitter.AddGlobalMethod("AssemblyDictionary", il, 8);
            MemoryStream peFile = new MemoryStream();

            emitter.SerializeToStream(peFile);
            peFile.Position = 0;

            if (outputFileName.Exists)
            {
                outputFileName.Delete();
            }

            if (uncompressed)
            {
                using (FileStream file = new FileStream(outputFileName.FullName, FileMode.Create))
                {
                    peFile.CopyTo(file);
                }
            }
            else
            {
                using (ZipArchive file = ZipFile.Open(outputFileName.FullName, ZipArchiveMode.Create))
                {
                    var entry = file.CreateEntry(outputFileName.Name + ".dll", CompressionLevel.Optimal);
                    using (Stream archiveStream = entry.Open())
                    {
                        peFile.CopyTo(archiveStream);
                    }
                }
            }

            Program.PrintMessage($"Generated {outputFileName.FullName}");

            if (validate)
            {
                return(ValidateMIbcData(tsc, outputFileName, peFile.ToArray(), methodsToAttemptToPlaceIntoProfileData));
            }
            else
            {
                return(0);
            }
        }
示例#13
0
        private static MethodDefinitionHandle ComplexEmit(MetadataBuilder metadata, BlobBuilder ilBuilder, out Blob mvidFixup)
        {
            var mvid = metadata.ReserveGuid();

            mvidFixup = mvid.Content;

            metadata.AddModule(
                0,
                metadata.GetOrAddString("ConsoleApplication.exe"),
                mvid.Handle,
                default(GuidHandle),
                default(GuidHandle));

            metadata.AddAssembly(
                metadata.GetOrAddString("ConsoleApplication"),
                version: new Version(0, 0, 0, 0),
                culture: default(StringHandle),
                publicKey: default(BlobHandle),
                flags: default(AssemblyFlags),
                hashAlgorithm: AssemblyHashAlgorithm.Sha1);

            var mscorlibAssemblyRef = metadata.AddAssemblyReference(
                name: metadata.GetOrAddString("mscorlib"),
                version: new Version(4, 0, 0, 0),
                culture: default(StringHandle),
                publicKeyOrToken: metadata.GetOrAddBlob(ImmutableArray.Create <byte>(0xB7, 0x7A, 0x5C, 0x56, 0x19, 0x34, 0xE0, 0x89)),
                flags: default(AssemblyFlags),
                hashValue: default(BlobHandle));

            // TypeRefs:

            var systemObjectTypeRef              = metadata.AddTypeReference(mscorlibAssemblyRef, metadata.GetOrAddString("System"), metadata.GetOrAddString("Object"));
            var dictionaryTypeRef                = metadata.AddTypeReference(mscorlibAssemblyRef, metadata.GetOrAddString("System.Collections.Generic"), metadata.GetOrAddString("Dictionary`2"));
            var strignBuilderTypeRef             = metadata.AddTypeReference(mscorlibAssemblyRef, metadata.GetOrAddString("System.Text"), metadata.GetOrAddString("StringBuilder"));
            var typeTypeRef                      = metadata.AddTypeReference(mscorlibAssemblyRef, metadata.GetOrAddString("System"), metadata.GetOrAddString("Type"));
            var int32TypeRef                     = metadata.AddTypeReference(mscorlibAssemblyRef, metadata.GetOrAddString("System"), metadata.GetOrAddString("Int32"));
            var runtimeTypeHandleRef             = metadata.AddTypeReference(mscorlibAssemblyRef, metadata.GetOrAddString("System"), metadata.GetOrAddString("RuntimeTypeHandle"));
            var invalidOperationExceptionTypeRef = metadata.AddTypeReference(mscorlibAssemblyRef, metadata.GetOrAddString("System"), metadata.GetOrAddString("InvalidOperationException"));

            // TypeDefs:

            metadata.AddTypeDefinition(
                default(TypeAttributes),
                default(StringHandle),
                metadata.GetOrAddString("<Module>"),
                baseType: default(EntityHandle),
                fieldList: MetadataTokens.FieldDefinitionHandle(1),
                methodList: MetadataTokens.MethodDefinitionHandle(1));

            var baseClassTypeDef = metadata.AddTypeDefinition(
                TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.AutoLayout | TypeAttributes.BeforeFieldInit | TypeAttributes.Abstract,
                metadata.GetOrAddString("Lib"),
                metadata.GetOrAddString("BaseClass"),
                systemObjectTypeRef,
                fieldList: MetadataTokens.FieldDefinitionHandle(1),
                methodList: MetadataTokens.MethodDefinitionHandle(1));

            var derivedClassTypeDef = metadata.AddTypeDefinition(
                TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.AutoLayout | TypeAttributes.BeforeFieldInit,
                metadata.GetOrAddString("Lib"),
                metadata.GetOrAddString("DerivedClass"),
                baseClassTypeDef,
                fieldList: MetadataTokens.FieldDefinitionHandle(4),
                methodList: MetadataTokens.MethodDefinitionHandle(1));

            // FieldDefs:

            // Field1
            var baseClassNumberFieldDef = metadata.AddFieldDefinition(
                FieldAttributes.Private,
                metadata.GetOrAddString("_number"),
                metadata.GetOrAddBlob(BuildSignature(e => e.FieldSignature().Int32())));

            // Field2
            var baseClassNegativeFieldDef = metadata.AddFieldDefinition(
                FieldAttributes.Assembly,
                metadata.GetOrAddString("negative"),
                metadata.GetOrAddBlob(BuildSignature(e => e.FieldSignature().Boolean())));

            // Field3
            var derivedClassSumCacheFieldDef = metadata.AddFieldDefinition(
                FieldAttributes.Assembly,
                metadata.GetOrAddString("_sumCache"),
                metadata.GetOrAddBlob(BuildSignature(e =>
            {
                var inst = e.FieldSignature().GenericInstantiation(genericType: dictionaryTypeRef, genericArgumentCount: 2, isValueType: false);
                inst.AddArgument().Int32();
                inst.AddArgument().Object();
            })));

            // Field4
            var derivedClassCountFieldDef = metadata.AddFieldDefinition(
                FieldAttributes.Assembly,
                metadata.GetOrAddString("_count"),
                metadata.GetOrAddBlob(BuildSignature(e => e.FieldSignature().SZArray().Int32())));

            // Field5
            var derivedClassBCFieldDef = metadata.AddFieldDefinition(
                FieldAttributes.Assembly,
                metadata.GetOrAddString("_bc"),
                metadata.GetOrAddBlob(BuildSignature(e => e.FieldSignature().Type(type: baseClassTypeDef, isValueType: false))));

            var methodBodyStream = new MethodBodyStreamEncoder(ilBuilder);

            var buffer = new BlobBuilder();
            var il     = new InstructionEncoder(buffer);

            //
            // Foo
            //
            il.LoadString(metadata.GetOrAddUserString("asdsad"));
            il.OpCode(ILOpCode.Newobj);
            il.Token(invalidOperationExceptionTypeRef);
            il.OpCode(ILOpCode.Throw);

            int fooBodyOffset = methodBodyStream.AddMethodBody(il);

            // Method1
            var derivedClassFooMethodDef = metadata.AddMethodDefinition(
                MethodAttributes.PrivateScope | MethodAttributes.Private | MethodAttributes.HideBySig,
                MethodImplAttributes.IL,
                metadata.GetOrAddString("Foo"),
                metadata.GetOrAddBlob(BuildSignature(e =>
                                                     e.MethodSignature(isInstanceMethod: true).Parameters(0, returnType => returnType.Void(), parameters => { }))),
                fooBodyOffset,
                default(ParameterHandle));

            return(default(MethodDefinitionHandle));
        }
示例#14
0
        private static MethodDefinitionHandle BasicValidationEmit(MetadataBuilder metadata, BlobBuilder ilBuilder)
        {
            metadata.AddModule(
                0,
                metadata.GetOrAddString("ConsoleApplication.exe"),
                metadata.GetOrAddGuid(s_guid),
                default(GuidHandle),
                default(GuidHandle));

            metadata.AddAssembly(
                metadata.GetOrAddString("ConsoleApplication"),
                version: new Version(1, 0, 0, 0),
                culture: default(StringHandle),
                publicKey: metadata.GetOrAddBlob(ImmutableArray.Create(Misc.KeyPair_PublicKey)),
                flags: AssemblyFlags.PublicKey,
                hashAlgorithm: AssemblyHashAlgorithm.Sha1);

            var mscorlibAssemblyRef = metadata.AddAssemblyReference(
                name: metadata.GetOrAddString("mscorlib"),
                version: new Version(4, 0, 0, 0),
                culture: default(StringHandle),
                publicKeyOrToken: metadata.GetOrAddBlob(ImmutableArray.Create <byte>(0xB7, 0x7A, 0x5C, 0x56, 0x19, 0x34, 0xE0, 0x89)),
                flags: default(AssemblyFlags),
                hashValue: default(BlobHandle));

            var systemObjectTypeRef = metadata.AddTypeReference(
                mscorlibAssemblyRef,
                metadata.GetOrAddString("System"),
                metadata.GetOrAddString("Object"));

            var systemConsoleTypeRefHandle = metadata.AddTypeReference(
                mscorlibAssemblyRef,
                metadata.GetOrAddString("System"),
                metadata.GetOrAddString("Console"));

            var consoleWriteLineSignature = new BlobBuilder();

            new BlobEncoder(consoleWriteLineSignature).
            MethodSignature().
            Parameters(1,
                       returnType => returnType.Void(),
                       parameters => parameters.AddParameter().Type().String());

            var consoleWriteLineMemberRef = metadata.AddMemberReference(
                systemConsoleTypeRefHandle,
                metadata.GetOrAddString("WriteLine"),
                metadata.GetOrAddBlob(consoleWriteLineSignature));

            var parameterlessCtorSignature = new BlobBuilder();

            new BlobEncoder(parameterlessCtorSignature).
            MethodSignature(isInstanceMethod: true).
            Parameters(0, returnType => returnType.Void(), parameters => { });

            var parameterlessCtorBlobIndex = metadata.GetOrAddBlob(parameterlessCtorSignature);

            var objectCtorMemberRef = metadata.AddMemberReference(
                systemObjectTypeRef,
                metadata.GetOrAddString(".ctor"),
                parameterlessCtorBlobIndex);

            var mainSignature = new BlobBuilder();

            new BlobEncoder(mainSignature).
            MethodSignature().
            Parameters(0, returnType => returnType.Void(), parameters => { });

            var methodBodyStream = new MethodBodyStreamEncoder(ilBuilder);

            var codeBuilder = new BlobBuilder();
            InstructionEncoder il;

            //
            // Program::.ctor
            //
            il = new InstructionEncoder(codeBuilder);

            // ldarg.0
            il.LoadArgument(0);

            // call instance void [mscorlib]System.Object::.ctor()
            il.Call(objectCtorMemberRef);

            // ret
            il.OpCode(ILOpCode.Ret);

            int ctorBodyOffset = methodBodyStream.AddMethodBody(il);

            codeBuilder.Clear();

            //
            // Program::Main
            //
            var flowBuilder = new ControlFlowBuilder();

            il = new InstructionEncoder(codeBuilder, flowBuilder);

            var tryStart     = il.DefineLabel();
            var tryEnd       = il.DefineLabel();
            var finallyStart = il.DefineLabel();
            var finallyEnd   = il.DefineLabel();

            flowBuilder.AddFinallyRegion(tryStart, tryEnd, finallyStart, finallyEnd);

            // .try
            il.MarkLabel(tryStart);

            //   ldstr "hello"
            il.LoadString(metadata.GetOrAddUserString("hello"));

            //   call void [mscorlib]System.Console::WriteLine(string)
            il.Call(consoleWriteLineMemberRef);

            //   leave.s END
            il.Branch(ILOpCode.Leave_s, finallyEnd);
            il.MarkLabel(tryEnd);

            // .finally
            il.MarkLabel(finallyStart);

            //   ldstr "world"
            il.LoadString(metadata.GetOrAddUserString("world"));

            //   call void [mscorlib]System.Console::WriteLine(string)
            il.Call(consoleWriteLineMemberRef);

            // .endfinally
            il.OpCode(ILOpCode.Endfinally);
            il.MarkLabel(finallyEnd);

            // ret
            il.OpCode(ILOpCode.Ret);

            int mainBodyOffset = methodBodyStream.AddMethodBody(il);

            codeBuilder.Clear();
            flowBuilder.Clear();

            var mainMethodDef = metadata.AddMethodDefinition(
                MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.HideBySig,
                MethodImplAttributes.IL | MethodImplAttributes.Managed,
                metadata.GetOrAddString("Main"),
                metadata.GetOrAddBlob(mainSignature),
                mainBodyOffset,
                parameterList: default(ParameterHandle));

            var ctorDef = metadata.AddMethodDefinition(
                MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName,
                MethodImplAttributes.IL | MethodImplAttributes.Managed,
                metadata.GetOrAddString(".ctor"),
                parameterlessCtorBlobIndex,
                ctorBodyOffset,
                parameterList: default(ParameterHandle));

            metadata.AddTypeDefinition(
                default(TypeAttributes),
                default(StringHandle),
                metadata.GetOrAddString("<Module>"),
                baseType: default(EntityHandle),
                fieldList: MetadataTokens.FieldDefinitionHandle(1),
                methodList: mainMethodDef);

            metadata.AddTypeDefinition(
                TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.AutoLayout | TypeAttributes.BeforeFieldInit,
                metadata.GetOrAddString("ConsoleApplication"),
                metadata.GetOrAddString("Program"),
                systemObjectTypeRef,
                fieldList: MetadataTokens.FieldDefinitionHandle(1),
                methodList: mainMethodDef);

            return(mainMethodDef);
        }
        public unsafe void FatBody()
        {
            var streamBuilder = new BlobBuilder();
            var codeBuilder   = new BlobBuilder();
            var flowBuilder   = new ControlFlowBuilder();
            var il            = new InstructionEncoder(codeBuilder, flowBuilder);

            codeBuilder.WriteBytes(1, 62);
            var l1 = il.DefineLabel();

            il.MarkLabel(l1);

            Assert.Equal(62, flowBuilder.Labels.Single());

            il.Branch(ILOpCode.Br_s, l1);

            var brInfo = flowBuilder.Branches.Single();

            Assert.Equal(62, brInfo.ILOffset);
            Assert.Equal(l1, brInfo.Label);
            Assert.Equal(ILOpCode.Br_s, brInfo.OpCode);

            AssertEx.Equal(new byte[] { 1, 1, (byte)ILOpCode.Br_s, unchecked ((byte)-1) }, codeBuilder.ToArray(60, 4));

            var streamEncoder = new MethodBodyStreamEncoder(streamBuilder);
            int bodyOffset    = streamEncoder.AddMethodBody(
                il,
                maxStack: 2,
                localVariablesSignature: default(StandaloneSignatureHandle),
                attributes: MethodBodyAttributes.None);

            var bodyBytes = streamBuilder.ToArray();

            AssertEx.Equal(new byte[]
            {
                0x03, 0x30, 0x02, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // fat header
                0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x2B, 0xFE
            }, bodyBytes);

            fixed(byte *bodyPtr = &bodyBytes[0])
            {
                var body = MethodBodyBlock.Create(new BlobReader(bodyPtr, bodyBytes.Length));

                Assert.Equal(0, body.ExceptionRegions.Length);
                Assert.Equal(default(StandaloneSignatureHandle), body.LocalSignature);
                Assert.Equal(2, body.MaxStack);
                Assert.Equal(bodyBytes.Length, body.Size);

                var ilBytes = body.GetILBytes();

                AssertEx.Equal(new byte[]
                {
                    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x2B, 0xFE
                }, ilBytes);
            }
        }
示例#16
0
        private static MethodDefinitionHandle BasicValidationEmit(MetadataBuilder metadata, BlobBuilder ilBuilder)
        {
            metadata.AddModule(
                0,
                metadata.GetOrAddString("ConsoleApplication.exe"),
                metadata.GetOrAddGuid(Guid.NewGuid()),
                default(GuidHandle),
                default(GuidHandle));

            metadata.AddAssembly(
                metadata.GetOrAddString("ConsoleApplication"),
                version: new Version(0, 0, 0, 0),
                culture: default(StringHandle),
                publicKey: default(BlobHandle),
                flags: default(AssemblyFlags),
                hashAlgorithm: AssemblyHashAlgorithm.Sha1);

            var mscorlibAssemblyRef = metadata.AddAssemblyReference(
                name: metadata.GetOrAddString("mscorlib"),
                version: new Version(4, 0, 0, 0),
                culture: default(StringHandle),
                publicKeyOrToken: metadata.GetOrAddBlob(ImmutableArray.Create<byte>(0xB7, 0x7A, 0x5C, 0x56, 0x19, 0x34, 0xE0, 0x89)),
                flags: default(AssemblyFlags),
                hashValue: default(BlobHandle));

            var systemObjectTypeRef = metadata.AddTypeReference(
                mscorlibAssemblyRef,
                metadata.GetOrAddString("System"),
                metadata.GetOrAddString("Object"));

            var systemConsoleTypeRefHandle = metadata.AddTypeReference(
                mscorlibAssemblyRef,
                metadata.GetOrAddString("System"),
                metadata.GetOrAddString("Console"));

            var consoleWriteLineSignature = new BlobBuilder();

            new BlobEncoder(consoleWriteLineSignature).
                MethodSignature().
                Parameters(1,
                    returnType => returnType.Void(),
                    parameters =>
                    {
                        parameters.AddParameter().Type().String();
                        parameters.EndParameters();
                    });

            var consoleWriteLineMemberRef = metadata.AddMemberReference(
                systemConsoleTypeRefHandle,
                metadata.GetOrAddString("WriteLine"),
                metadata.GetOrAddBlob(consoleWriteLineSignature));

            var parameterlessCtorSignature = new BlobBuilder();

            new BlobEncoder(parameterlessCtorSignature).
                MethodSignature(isInstanceMethod: true).
                Parameters(0, returnType => returnType.Void(), parameters => parameters.EndParameters());

            var parameterlessCtorBlobIndex = metadata.GetOrAddBlob(parameterlessCtorSignature);

            var objectCtorMemberRef = metadata.AddMemberReference(
                systemObjectTypeRef,
                metadata.GetOrAddString(".ctor"),
                parameterlessCtorBlobIndex);

            var mainSignature = new BlobBuilder();

            new BlobEncoder(mainSignature).
                MethodSignature().
                Parameters(0, returnType => returnType.Void(), parameters => parameters.EndParameters());

            var methodBodies = new MethodBodiesEncoder(ilBuilder);

            var codeBuilder = new BlobBuilder();
            var branchBuilder = new BranchBuilder();
            InstructionEncoder il;

            //
            // Program::.ctor
            //
            int ctorBodyOffset;
            il = new InstructionEncoder(codeBuilder);

            // ldarg.0
            il.LoadArgument(0);

            // call instance void [mscorlib]System.Object::.ctor()
            il.Call(objectCtorMemberRef);

            // ret
            il.OpCode(ILOpCode.Ret);

            methodBodies.AddMethodBody().WriteInstructions(codeBuilder, out ctorBodyOffset);
            codeBuilder.Clear();

            //
            // Program::Main
            //
            int mainBodyOffset;
            il = new InstructionEncoder(codeBuilder, branchBuilder);
            var endLabel = il.DefineLabel();

            // .try
            int tryOffset = il.Offset;

            //   ldstr "hello"
            il.LoadString(metadata.GetOrAddUserString("hello"));

            //   call void [mscorlib]System.Console::WriteLine(string)
            il.Call(consoleWriteLineMemberRef);

            //   leave.s END
            il.Branch(ILOpCode.Leave, endLabel);

            // .finally
            int handlerOffset = il.Offset;

            //   ldstr "world"
            il.LoadString(metadata.GetOrAddUserString("world"));

            //   call void [mscorlib]System.Console::WriteLine(string)
            il.Call(consoleWriteLineMemberRef);

            // .endfinally
            il.OpCode(ILOpCode.Endfinally);
            int handlerEnd = il.Offset;

            // END:
            il.MarkLabel(endLabel);

            // ret
            il.OpCode(ILOpCode.Ret);

            var body = methodBodies.AddMethodBody(exceptionRegionCount: 1);
            var eh = body.WriteInstructions(codeBuilder, branchBuilder, out mainBodyOffset);
            eh.StartRegions();
            eh.AddFinally(tryOffset, handlerOffset - tryOffset, handlerOffset, handlerEnd - handlerOffset);
            eh.EndRegions();

            codeBuilder.Clear();
            branchBuilder.Clear();

            var mainMethodDef = metadata.AddMethodDefinition(
                MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.HideBySig,
                MethodImplAttributes.IL | MethodImplAttributes.Managed,
                metadata.GetOrAddString("Main"),
                metadata.GetOrAddBlob(mainSignature),
                mainBodyOffset,
                paramList: default(ParameterHandle));

            var ctorDef = metadata.AddMethodDefinition(
                MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName,
                MethodImplAttributes.IL | MethodImplAttributes.Managed,
                metadata.GetOrAddString(".ctor"),
                parameterlessCtorBlobIndex,
                ctorBodyOffset,
                paramList: default(ParameterHandle));

            metadata.AddTypeDefinition(
                default(TypeAttributes),
                default(StringHandle),
                metadata.GetOrAddString("<Module>"),
                baseType: default(EntityHandle),
                fieldList: MetadataTokens.FieldDefinitionHandle(1),
                methodList: mainMethodDef);

            metadata.AddTypeDefinition(
                TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.AutoLayout | TypeAttributes.BeforeFieldInit,
                metadata.GetOrAddString("ConsoleApplication"),
                metadata.GetOrAddString("Program"),
                systemObjectTypeRef,
                fieldList: MetadataTokens.FieldDefinitionHandle(1),
                methodList: mainMethodDef);

            return mainMethodDef;
        }
示例#17
0
        public void LoadArgumentAddress()
        {
            var builder = new BlobBuilder();
            var il = new InstructionEncoder(builder);

            il.LoadArgumentAddress(0);
            il.LoadArgumentAddress(1);
            il.LoadArgumentAddress(2);
            il.LoadArgumentAddress(3);
            il.LoadArgumentAddress(4);
            il.LoadArgumentAddress(byte.MaxValue);
            il.LoadArgumentAddress(byte.MaxValue + 1);
            il.LoadArgumentAddress(int.MaxValue);

            AssertEx.Equal(new byte[]
            {
                (byte)ILOpCode.Ldarga_s, 0x00,
                (byte)ILOpCode.Ldarga_s, 0x01,
                (byte)ILOpCode.Ldarga_s, 0x02,
                (byte)ILOpCode.Ldarga_s, 0x03,
                (byte)ILOpCode.Ldarga_s, 0x04,
                (byte)ILOpCode.Ldarga_s, 0xFF,
                0xFE, 0x0A, 0x00, 0x01, 0x00, 0x00,
                0xFE, 0x0A, 0xFF, 0xFF, 0xFF, 0x7F
            }, builder.ToArray());

            Assert.Throws<ArgumentOutOfRangeException>(() => il.LoadArgumentAddress(-1));
            Assert.Throws<ArgumentOutOfRangeException>(() => il.LoadArgumentAddress(int.MinValue));
        }
示例#18
0
        public void StoreArgument()
        {
            var builder = new BlobBuilder();
            var il = new InstructionEncoder(builder);

            il.StoreArgument(0);
            il.StoreArgument(1);
            il.StoreArgument(2);
            il.StoreArgument(3);
            il.StoreArgument(4);
            il.StoreArgument(byte.MaxValue);
            il.StoreArgument(byte.MaxValue + 1);
            il.StoreArgument(int.MaxValue);

            AssertEx.Equal(new byte[]
            {
                (byte)ILOpCode.Starg_s, 0x00,
                (byte)ILOpCode.Starg_s, 0x01,
                (byte)ILOpCode.Starg_s, 0x02,
                (byte)ILOpCode.Starg_s, 0x03,
                (byte)ILOpCode.Starg_s, 0x04,
                (byte)ILOpCode.Starg_s, 0xFF,
                0xFE, 0x0B, 0x00, 0x01, 0x00, 0x00,
                0xFE, 0x0B, 0xFF, 0xFF, 0xFF, 0x7F
            }, builder.ToArray());

            Assert.Throws<ArgumentOutOfRangeException>(() => il.StoreArgument(-1));
            Assert.Throws<ArgumentOutOfRangeException>(() => il.StoreArgument(int.MinValue));
        }
示例#19
0
        public void LoadConstantI4()
        {
            var builder = new BlobBuilder();
            var il = new InstructionEncoder(builder);

            for (int i = -1; i < 9; i++)
            {
                il.LoadConstantI4(i);
            }

            il.LoadConstantI4(sbyte.MinValue);
            il.LoadConstantI4(sbyte.MaxValue);
            il.LoadConstantI4(-2);
            il.LoadConstantI4(10);
            il.LoadConstantI4(int.MinValue);
            il.LoadConstantI4(int.MaxValue);

            AssertEx.Equal(new byte[]
            {
                (byte)ILOpCode.Ldc_i4_m1,
                (byte)ILOpCode.Ldc_i4_0,
                (byte)ILOpCode.Ldc_i4_1,
                (byte)ILOpCode.Ldc_i4_2,
                (byte)ILOpCode.Ldc_i4_3,
                (byte)ILOpCode.Ldc_i4_4,
                (byte)ILOpCode.Ldc_i4_5,
                (byte)ILOpCode.Ldc_i4_6,
                (byte)ILOpCode.Ldc_i4_7,
                (byte)ILOpCode.Ldc_i4_8,
                (byte)ILOpCode.Ldc_i4_s, 0x80,
                (byte)ILOpCode.Ldc_i4_s, 0x7F,
                (byte)ILOpCode.Ldc_i4_s, 0xFE,
                (byte)ILOpCode.Ldc_i4_s, 0x0A,
                (byte)ILOpCode.Ldc_i4, 0x00, 0x00, 0x00, 0x80,
                (byte)ILOpCode.Ldc_i4, 0xFF, 0xFF, 0xFF, 0x7F
            }, builder.ToArray());
        }
示例#20
0
        public void BranchAndLabel_Errors()
        {
            var builder = new BlobBuilder();
            var il = new InstructionEncoder(builder);
            var ilcf1 = new InstructionEncoder(builder, new ControlFlowBuilder());
            var ilcf2 = new InstructionEncoder(builder, new ControlFlowBuilder());

            var l1 = ilcf1.DefineLabel();
            ilcf2.DefineLabel();
            var l2 = ilcf2.DefineLabel();

            Assert.Throws<InvalidOperationException>(() => il.DefineLabel());
            Assert.Throws<InvalidOperationException>(() => il.Branch(ILOpCode.Br, default(LabelHandle)));
            Assert.Throws<InvalidOperationException>(() => il.MarkLabel(default(LabelHandle)));

            Assert.Throws<ArgumentNullException>(() => ilcf1.Branch(ILOpCode.Br, default(LabelHandle)));
            Assert.Throws<ArgumentNullException>(() => ilcf1.MarkLabel(default(LabelHandle)));
            Assert.Throws<ArgumentException>(() => ilcf1.Branch(ILOpCode.Br, l2));
            Assert.Throws<ArgumentException>(() => ilcf1.MarkLabel(l2));

            Assert.Throws<ArgumentException>(() => ilcf1.Branch(ILOpCode.Box, l1));
        }
示例#21
0
        public void AddFinallyFaultFilterRegions()
        {
            var code = new BlobBuilder();
            var flow = new ControlFlowBuilder();
            var il = new InstructionEncoder(code, flow);

            var l1 = il.DefineLabel();
            var l2 = il.DefineLabel();
            var l3 = il.DefineLabel();
            var l4 = il.DefineLabel();
            var l5 = il.DefineLabel();

            il.MarkLabel(l1);
            Assert.Equal(0, il.Offset);
            il.OpCode(ILOpCode.Nop);
            il.MarkLabel(l2);
            Assert.Equal(1, il.Offset);
            il.OpCode(ILOpCode.Nop);
            il.OpCode(ILOpCode.Nop);
            il.MarkLabel(l3);
            Assert.Equal(3, il.Offset);
            il.OpCode(ILOpCode.Nop);
            il.OpCode(ILOpCode.Nop);
            il.OpCode(ILOpCode.Nop);
            il.MarkLabel(l4);
            Assert.Equal(6, il.Offset);
            il.OpCode(ILOpCode.Nop);
            il.OpCode(ILOpCode.Nop);
            il.OpCode(ILOpCode.Nop);
            il.OpCode(ILOpCode.Nop);
            il.MarkLabel(l5);
            Assert.Equal(10, il.Offset);

            flow.AddFaultRegion(l1, l2, l3, l4);
            flow.AddFinallyRegion(l1, l2, l3, l4);
            flow.AddFilterRegion(l1, l2, l3, l4, l5);
            
            var builder = new BlobBuilder();
            builder.WriteByte(0xff);
            flow.SerializeExceptionTable(builder);

            AssertEx.Equal(new byte[] 
            {
                0xFF, 0x00, 0x00, 0x00,    // padding
                0x01,                      // flag
                (byte)(builder.Count - 4), // size
                0x00, 0x00,                // reserved

                0x04, 0x00,                // kind
                0x00, 0x00,                // try offset
                0x01,                      // try length
                0x03, 0x00,                // handler offset
                0x03,                      // handler length
                                           
                0x00, 0x00, 0x00, 0x00,    // catch type or filter offset
                                           
                0x02, 0x00,                // kind
                0x00, 0x00,                // try offset
                0x01,                      // try length
                0x03, 0x00,                // handler offset
                0x03,                      // handler length
                                           
                0x00, 0x00, 0x00, 0x00,    // catch type or filter offset

                0x01, 0x00,                // kind
                0x00, 0x00,                // try offset
                0x01,                      // try length
                0x03, 0x00,                // handler offset
                0x03,                      // handler length
                                           
                0x0A, 0x00, 0x00, 0x00     // catch type or filter offset
            }, builder.ToArray());
        }
示例#22
0
        public void AddRegion_Errors3()
        {
            var code = new BlobBuilder();
            var flow = new ControlFlowBuilder();
            var il = new InstructionEncoder(code, flow);

            var l1 = il.DefineLabel();
            var l2 = il.DefineLabel();
            var l3 = il.DefineLabel();
            var l4 = il.DefineLabel();
            var l5 = il.DefineLabel();

            il.MarkLabel(l1);
            il.OpCode(ILOpCode.Nop);
            il.MarkLabel(l2);
            il.OpCode(ILOpCode.Nop);
            il.MarkLabel(l3);
            il.OpCode(ILOpCode.Nop);
            il.MarkLabel(l4);

            var streamBuilder = new BlobBuilder();
            var encoder = new MethodBodyStreamEncoder(streamBuilder);

            flow.AddFaultRegion(l1, l2, l4, l3);
            Assert.Throws<InvalidOperationException>(() => encoder.AddMethodBody(il));
        }
        public void AddCatchRegions()
        {
            var code = new BlobBuilder();
            var flow = new ControlFlowBuilder();
            var il   = new InstructionEncoder(code, flow);

            var l1 = il.DefineLabel();
            var l2 = il.DefineLabel();
            var l3 = il.DefineLabel();
            var l4 = il.DefineLabel();
            var l5 = il.DefineLabel();

            il.MarkLabel(l1);
            Assert.Equal(0, il.Offset);
            il.OpCode(ILOpCode.Nop);
            il.MarkLabel(l2);
            Assert.Equal(1, il.Offset);
            il.OpCode(ILOpCode.Nop);
            il.OpCode(ILOpCode.Nop);
            il.MarkLabel(l3);
            Assert.Equal(3, il.Offset);
            il.OpCode(ILOpCode.Nop);
            il.OpCode(ILOpCode.Nop);
            il.OpCode(ILOpCode.Nop);
            il.MarkLabel(l4);
            Assert.Equal(6, il.Offset);
            il.OpCode(ILOpCode.Nop);
            il.OpCode(ILOpCode.Nop);
            il.OpCode(ILOpCode.Nop);
            il.OpCode(ILOpCode.Nop);
            il.MarkLabel(l5);
            Assert.Equal(10, il.Offset);

            flow.AddCatchRegion(l1, l2, l3, l4, MetadataTokens.TypeDefinitionHandle(1));
            flow.AddCatchRegion(l1, l2, l3, l4, MetadataTokens.TypeSpecificationHandle(2));
            flow.AddCatchRegion(l1, l2, l3, l4, MetadataTokens.TypeReferenceHandle(3));

            var builder = new BlobBuilder();

            flow.SerializeExceptionTable(builder);

            AssertEx.Equal(new byte[]
            {
                0x01,                      // flag
                (byte)builder.Count,       // size
                0x00, 0x00,                // reserved

                0x00, 0x00,                // kind
                0x00, 0x00,                // try offset
                0x01,                      // try length
                0x03, 0x00,                // handler offset
                0x03,                      // handler length

                0x01, 0x00, 0x00, 0x02,    // catch type or filter offset

                0x00, 0x00,                // kind
                0x00, 0x00,                // try offset
                0x01,                      // try length
                0x03, 0x00,                // handler offset
                0x03,                      // handler length

                0x02, 0x00, 0x00, 0x1B,    // catch type or filter offset

                0x00, 0x00,                // kind
                0x00, 0x00,                // try offset
                0x01,                      // try length
                0x03, 0x00,                // handler offset
                0x03,                      // handler length

                0x03, 0x00, 0x00, 0x01,    // catch type or filter offset
            }, builder.ToArray());
        }
示例#24
0
        public void AddRegion_Errors1()
        {
            var code = new BlobBuilder();
            var flow = new ControlFlowBuilder();
            var il = new InstructionEncoder(code, flow);
            var ilx = new InstructionEncoder(code, new ControlFlowBuilder());

            var l1 = il.DefineLabel();
            var l2 = il.DefineLabel();
            var l3 = il.DefineLabel();
            var l4 = il.DefineLabel();
            var l5 = il.DefineLabel();

            ilx.DefineLabel();
            ilx.DefineLabel();
            ilx.DefineLabel();
            ilx.DefineLabel();
            ilx.DefineLabel();
            ilx.DefineLabel();
            var lx = ilx.DefineLabel();

            il.MarkLabel(l1);
            il.OpCode(ILOpCode.Nop);
            il.MarkLabel(l2);
            il.OpCode(ILOpCode.Nop);
            il.MarkLabel(l3);
            il.OpCode(ILOpCode.Nop);
            il.MarkLabel(l4);
            il.OpCode(ILOpCode.Nop);
            il.MarkLabel(l5);

            Assert.Throws<ArgumentException>(() => flow.AddCatchRegion(l1, l2, l3, l4, default(TypeDefinitionHandle)));
            Assert.Throws<ArgumentException>(() => flow.AddCatchRegion(l1, l2, l3, l4, MetadataTokens.MethodDefinitionHandle(1)));
            
            Assert.Throws<ArgumentNullException>(() => flow.AddCatchRegion(default(LabelHandle), l2, l3, l4, MetadataTokens.TypeReferenceHandle(1)));
            Assert.Throws<ArgumentNullException>(() => flow.AddCatchRegion(l1, default(LabelHandle), l3, l4, MetadataTokens.TypeReferenceHandle(1)));
            Assert.Throws<ArgumentNullException>(() => flow.AddCatchRegion(l1, l2, default(LabelHandle), l4, MetadataTokens.TypeReferenceHandle(1)));
            Assert.Throws<ArgumentNullException>(() => flow.AddCatchRegion(l1, l2, l3, default(LabelHandle), MetadataTokens.TypeReferenceHandle(1)));

            Assert.Throws<ArgumentException>(() => flow.AddCatchRegion(lx, l2, l3, l4, MetadataTokens.TypeReferenceHandle(1)));
            Assert.Throws<ArgumentException>(() => flow.AddCatchRegion(l1, lx, l3, l4, MetadataTokens.TypeReferenceHandle(1)));
            Assert.Throws<ArgumentException>(() => flow.AddCatchRegion(l1, l2, lx, l4, MetadataTokens.TypeReferenceHandle(1)));
            Assert.Throws<ArgumentException>(() => flow.AddCatchRegion(l1, l2, l3, lx, MetadataTokens.TypeReferenceHandle(1)));
        }
示例#25
0
        public void LoadConstantI8()
        {
            var builder = new BlobBuilder();
            var il = new InstructionEncoder(builder);

            il.LoadConstantI8(0);
            il.LoadConstantI8(long.MinValue);
            il.LoadConstantI8(long.MaxValue);

            AssertEx.Equal(new byte[]
            {
                (byte)ILOpCode.Ldc_i8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                (byte)ILOpCode.Ldc_i8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
                (byte)ILOpCode.Ldc_i8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F
            }, builder.ToArray());
        }
示例#26
0
        public void AddCatchRegions()
        {
            var code = new BlobBuilder();
            var flow = new ControlFlowBuilder();
            var il = new InstructionEncoder(code, flow);

            var l1 = il.DefineLabel();
            var l2 = il.DefineLabel();
            var l3 = il.DefineLabel();
            var l4 = il.DefineLabel();
            var l5 = il.DefineLabel();

            il.MarkLabel(l1);
            Assert.Equal(0, il.Offset);
            il.OpCode(ILOpCode.Nop);
            il.MarkLabel(l2);
            Assert.Equal(1, il.Offset);
            il.OpCode(ILOpCode.Nop);
            il.OpCode(ILOpCode.Nop);
            il.MarkLabel(l3);
            Assert.Equal(3, il.Offset);
            il.OpCode(ILOpCode.Nop);
            il.OpCode(ILOpCode.Nop);
            il.OpCode(ILOpCode.Nop);
            il.MarkLabel(l4);
            Assert.Equal(6, il.Offset);
            il.OpCode(ILOpCode.Nop);
            il.OpCode(ILOpCode.Nop);
            il.OpCode(ILOpCode.Nop);
            il.OpCode(ILOpCode.Nop);
            il.MarkLabel(l5);
            Assert.Equal(10, il.Offset);

            flow.AddCatchRegion(l1, l2, l3, l4, MetadataTokens.TypeDefinitionHandle(1));
            flow.AddCatchRegion(l1, l2, l3, l4, MetadataTokens.TypeSpecificationHandle(2));
            flow.AddCatchRegion(l1, l2, l3, l4, MetadataTokens.TypeReferenceHandle(3));

            var builder = new BlobBuilder();
            flow.SerializeExceptionTable(builder);

            AssertEx.Equal(new byte[]
            {
                0x01,                      // flag
                (byte)builder.Count,       // size
                0x00, 0x00,                // reserved

                0x00, 0x00,                // kind
                0x00, 0x00,                // try offset
                0x01,                      // try length
                0x03, 0x00,                // handler offset
                0x03,                      // handler length
                                           
                0x01, 0x00, 0x00, 0x02,    // catch type or filter offset
                                           
                0x00, 0x00,                // kind
                0x00, 0x00,                // try offset
                0x01,                      // try length
                0x03, 0x00,                // handler offset
                0x03,                      // handler length
                                           
                0x02, 0x00, 0x00, 0x1B,    // catch type or filter offset

                0x00, 0x00,                // kind
                0x00, 0x00,                // try offset
                0x01,                      // try length
                0x03, 0x00,                // handler offset
                0x03,                      // handler length
                                           
                0x03, 0x00, 0x00, 0x01,    // catch type or filter offset
            }, builder.ToArray());
        }
示例#27
0
        public void LoadConstantR4()
        {
            var builder = new BlobBuilder();
            var il = new InstructionEncoder(builder);

            il.LoadConstantR4(0.0f);
            il.LoadConstantR4(float.MaxValue);
            il.LoadConstantR4(float.MinValue);
            il.LoadConstantR4(float.NaN);
            il.LoadConstantR4(float.NegativeInfinity);
            il.LoadConstantR4(float.PositiveInfinity);
            il.LoadConstantR4(float.Epsilon);

            AssertEx.Equal(new byte[]
            {
                (byte)ILOpCode.Ldc_r4, 0x00, 0x00, 0x00, 0x00,
                (byte)ILOpCode.Ldc_r4, 0xFF, 0xFF, 0x7F, 0x7F,
                (byte)ILOpCode.Ldc_r4, 0xFF, 0xFF, 0x7F, 0xFF,
                (byte)ILOpCode.Ldc_r4, 0x00, 0x00, 0xC0, 0xFF,
                (byte)ILOpCode.Ldc_r4, 0x00, 0x00, 0x80, 0xFF,
                (byte)ILOpCode.Ldc_r4, 0x00, 0x00, 0x80, 0x7F,
                (byte)ILOpCode.Ldc_r4, 0x01, 0x00, 0x00, 0x00
            }, builder.ToArray());
        }
        public unsafe void FatBody()
        {
            var streamBuilder = new BlobBuilder();
            var codeBuilder = new BlobBuilder();
            var flowBuilder = new ControlFlowBuilder();
            var il = new InstructionEncoder(codeBuilder, flowBuilder);

            codeBuilder.WriteBytes(1, 62);
            var l1 = il.DefineLabel();
            il.MarkLabel(l1);

            Assert.Equal(62, flowBuilder.Labels.Single());

            il.Branch(ILOpCode.Br_s, l1);

            var brInfo = flowBuilder.Branches.Single();
            Assert.Equal(62, brInfo.ILOffset);
            Assert.Equal(l1, brInfo.Label);
            Assert.Equal(ILOpCode.Br_s, brInfo.OpCode);

            AssertEx.Equal(new byte[] { 1, 1, (byte)ILOpCode.Br_s, unchecked((byte)-1) }, codeBuilder.ToArray(60, 4));

            var streamEncoder = new MethodBodyStreamEncoder(streamBuilder);
            int bodyOffset = streamEncoder.AddMethodBody(
                il,
                maxStack: 2,
                localVariablesSignature: default(StandaloneSignatureHandle),
                attributes: MethodBodyAttributes.None);

            var bodyBytes = streamBuilder.ToArray();

            AssertEx.Equal(new byte[]
            {
                0x03, 0x30, 0x02, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // fat header
                0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x2B, 0xFE
            }, bodyBytes);

            fixed (byte* bodyPtr = &bodyBytes[0])
            {
                var body = MethodBodyBlock.Create(new BlobReader(bodyPtr, bodyBytes.Length));

                Assert.Equal(0, body.ExceptionRegions.Length);
                Assert.Equal(default(StandaloneSignatureHandle), body.LocalSignature);
                Assert.Equal(2, body.MaxStack);
                Assert.Equal(bodyBytes.Length, body.Size);

                var ilBytes = body.GetILBytes();
                AssertEx.Equal(new byte[]
                {
                    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x2B, 0xFE
                }, ilBytes);
            }
        }
示例#29
0
        public void LoadConstantR8()
        {
            var builder = new BlobBuilder();
            var il = new InstructionEncoder(builder);

            il.LoadConstantR8(0.0);
            il.LoadConstantR8(double.MaxValue);
            il.LoadConstantR8(double.MinValue);
            il.LoadConstantR8(double.NaN);
            il.LoadConstantR8(double.NegativeInfinity);
            il.LoadConstantR8(double.PositiveInfinity);
            il.LoadConstantR8(double.Epsilon);

            AssertEx.Equal(new byte[]
            {
                (byte)ILOpCode.Ldc_r8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                (byte)ILOpCode.Ldc_r8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0x7F,
                (byte)ILOpCode.Ldc_r8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF,
                (byte)ILOpCode.Ldc_r8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF,
                (byte)ILOpCode.Ldc_r8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF,
                (byte)ILOpCode.Ldc_r8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x7F,
                (byte)ILOpCode.Ldc_r8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
            }, builder.ToArray());
        }
        public void BranchErrors_UnmarkedLabel()
        {
            var streamBuilder = new BlobBuilder();
            var codeBuilder = new BlobBuilder();
            var flowBuilder = new ControlFlowBuilder();

            var il = new InstructionEncoder(codeBuilder, flowBuilder);
            var l = il.DefineLabel();
            il.Branch(ILOpCode.Br_s, l);
            il.OpCode(ILOpCode.Ret);

            Assert.Throws<InvalidOperationException>(() => new MethodBodyStreamEncoder(streamBuilder).AddMethodBody(il));
        }
示例#31
0
        public void LoadLocal()
        {
            var builder = new BlobBuilder();
            var il = new InstructionEncoder(builder);

            il.LoadLocal(0);
            il.LoadLocal(1);
            il.LoadLocal(2);
            il.LoadLocal(3);
            il.LoadLocal(4);
            il.LoadLocal(byte.MaxValue);
            il.LoadLocal(byte.MaxValue + 1);
            il.LoadLocal(int.MaxValue);

            AssertEx.Equal(new byte[]
            {
                (byte)ILOpCode.Ldloc_0,
                (byte)ILOpCode.Ldloc_1,
                (byte)ILOpCode.Ldloc_2,
                (byte)ILOpCode.Ldloc_3,
                (byte)ILOpCode.Ldloc_s, 0x04,
                (byte)ILOpCode.Ldloc_s, 0xFF,
                0xFE, 0x0C, 0x00, 0x01, 0x00, 0x00,
                0xFE, 0x0C, 0xFF, 0xFF, 0xFF, 0x7F
            }, builder.ToArray());

            Assert.Throws<ArgumentOutOfRangeException>(() => il.LoadLocal(-1));
            Assert.Throws<ArgumentOutOfRangeException>(() => il.LoadLocal(int.MinValue));
        }
        public unsafe void TinyBody()
        {
            var bodyBuilder = new BlobBuilder();
            var codeBuilder = new BlobBuilder();
            var branchBuilder = new BranchBuilder();
            var il = new InstructionEncoder(codeBuilder, branchBuilder);

            var bodyEncoder = new MethodBodyEncoder(
                bodyBuilder, 
                maxStack: 2, 
                exceptionRegionCount: 0, 
                localVariablesSignature: default(StandaloneSignatureHandle), 
                attributes: MethodBodyAttributes.None);

            Assert.True(bodyEncoder.IsTiny(10));
            Assert.True(bodyEncoder.IsTiny(63));
            Assert.False(bodyEncoder.IsTiny(64));

            codeBuilder.WriteBytes(1, 61);
            var l1 = il.DefineLabel();
            il.MarkLabel(l1);

            Assert.Equal(61, branchBuilder.Labels.Single());

            il.Branch(ILOpCode.Br, l1);

            var brInfo = branchBuilder.Branches.Single();
            Assert.Equal(61, brInfo.ILOffset);
            Assert.Equal(l1, brInfo.Label);
            Assert.Equal((byte)ILOpCode.Br_s, brInfo.ShortOpCode);

            AssertEx.Equal(new byte[] { 1, (byte)ILOpCode.Br_s, unchecked((byte)-1) }, codeBuilder.ToArray(60, 3));

            int bodyOffset;
            bodyEncoder.WriteInstructions(codeBuilder, branchBuilder, out bodyOffset);

            var bodyBytes = bodyBuilder.ToArray();

            AssertEx.Equal(new byte[] 
            {
                0xFE, // tiny header
                0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                0x01, 0x01, 0x01, 0x01, 0x01, 0x2B, 0xFE
            }, bodyBytes);

            fixed (byte* bodyPtr = &bodyBytes[0])
            {
                var body = MethodBodyBlock.Create(new BlobReader(bodyPtr, bodyBytes.Length));

                Assert.Equal(0, body.ExceptionRegions.Length);
                Assert.Equal(default(StandaloneSignatureHandle), body.LocalSignature);
                Assert.Equal(8, body.MaxStack);
                Assert.Equal(bodyBytes.Length, body.Size);

                var ilBytes = body.GetILBytes();
                AssertEx.Equal(new byte[]
                {
                    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                    0x01, 0x01, 0x01, 0x01, 0x01, 0x2B, 0xFE
                }, ilBytes);
            }
        }
        public void AddFinallyFaultFilterRegions()
        {
            var code = new BlobBuilder();
            var flow = new ControlFlowBuilder();
            var il   = new InstructionEncoder(code, flow);

            var l1 = il.DefineLabel();
            var l2 = il.DefineLabel();
            var l3 = il.DefineLabel();
            var l4 = il.DefineLabel();
            var l5 = il.DefineLabel();

            il.MarkLabel(l1);
            Assert.Equal(0, il.Offset);
            il.OpCode(ILOpCode.Nop);
            il.MarkLabel(l2);
            Assert.Equal(1, il.Offset);
            il.OpCode(ILOpCode.Nop);
            il.OpCode(ILOpCode.Nop);
            il.MarkLabel(l3);
            Assert.Equal(3, il.Offset);
            il.OpCode(ILOpCode.Nop);
            il.OpCode(ILOpCode.Nop);
            il.OpCode(ILOpCode.Nop);
            il.MarkLabel(l4);
            Assert.Equal(6, il.Offset);
            il.OpCode(ILOpCode.Nop);
            il.OpCode(ILOpCode.Nop);
            il.OpCode(ILOpCode.Nop);
            il.OpCode(ILOpCode.Nop);
            il.MarkLabel(l5);
            Assert.Equal(10, il.Offset);

            flow.AddFaultRegion(l1, l2, l3, l4);
            flow.AddFinallyRegion(l1, l2, l3, l4);
            flow.AddFilterRegion(l1, l2, l3, l4, l5);

            var builder = new BlobBuilder();

            builder.WriteByte(0xff);
            flow.SerializeExceptionTable(builder);

            AssertEx.Equal(new byte[]
            {
                0xFF, 0x00, 0x00, 0x00,    // padding
                0x01,                      // flag
                (byte)(builder.Count - 4), // size
                0x00, 0x00,                // reserved

                0x04, 0x00,                // kind
                0x00, 0x00,                // try offset
                0x01,                      // try length
                0x03, 0x00,                // handler offset
                0x03,                      // handler length

                0x00, 0x00, 0x00, 0x00,    // catch type or filter offset

                0x02, 0x00,                // kind
                0x00, 0x00,                // try offset
                0x01,                      // try length
                0x03, 0x00,                // handler offset
                0x03,                      // handler length

                0x00, 0x00, 0x00, 0x00,    // catch type or filter offset

                0x01, 0x00,                // kind
                0x00, 0x00,                // try offset
                0x01,                      // try length
                0x03, 0x00,                // handler offset
                0x03,                      // handler length

                0x0A, 0x00, 0x00, 0x00     // catch type or filter offset
            }, builder.ToArray());
        }