コード例 #1
0
        internal void TestPrint()
        {
            MemoryStore store = new MemoryStore();

            IdentOperand idA    = new IdentOperand("A");
            TypeOperand  typeOp = new TypeOperand(TYPE.INT);

            NumOperand numA = new NumOperand(10);


            // We must define the variable prior to using it
            DefOpCode defOp = new DefOpCode(new Operand[] { idA, typeOp }, store);

            defOp.Execute();


            // Store A
            Operand[] operands = new Operand[] { idA, numA };
            SetOpCode op       = new SetOpCode(operands, store);

            op.Execute();

            PrintOpCode printOp = new PrintOpCode(new Operand[] { idA }, store);

            printOp.Execute();
        }
コード例 #2
0
        internal void TestSet()
        {
            MemoryStore store = new MemoryStore();

            IdentOperand id     = new IdentOperand("A");
            TypeOperand  typeOp = new TypeOperand(TYPE.INT);
            NumOperand   num    = new NumOperand(10);

            // We must define the variable prior to using it
            DefOpCode defOp = new DefOpCode(new Operand[] { id, typeOp }, store);

            defOp.Execute();

            Operand[] operands = new Operand[] { id, num };

            SetOpCode setOp = new SetOpCode(operands, store);

            setOp.Execute();

            var storedValue = Convert.ToInt32(store.Get(id));

            if (storedValue != 10)
            {
                throw new Exception("Stored value != 10");
            }
        }
コード例 #3
0
        internal void TestAdd()
        {
            MemoryStore store = new MemoryStore();

            IdentOperand idA = new IdentOperand("A");
            IdentOperand idB = new IdentOperand("B");
            IdentOperand idC = new IdentOperand("C");

            TypeOperand typeOp = new TypeOperand(TYPE.INT);

            NumOperand numA = new NumOperand(10);
            NumOperand numB = new NumOperand(20);


            // We must define the variable prior to using it
            DefOpCode defOp = new DefOpCode(new Operand[] { idA, typeOp }, store);

            defOp.Execute();

            defOp = new DefOpCode(new Operand[] { idB, typeOp }, store);
            defOp.Execute();

            defOp = new DefOpCode(new Operand[] { idC, typeOp }, store);
            defOp.Execute();

            // Store A
            Operand[] operands = new Operand[] { idA, numA };
            SetOpCode op       = new SetOpCode(operands, store);

            op.Execute();

            // Store B
            operands = new Operand[] { idB, numB };
            op       = new SetOpCode(operands, store);
            op.Execute();

            // Add: C = A + B
            AddOpCode addOp = new AddOpCode(new Operand[] { idC, idA, idB }, store);

            addOp.Execute();

            var storedValue = Convert.ToInt32(store.Get(idC));

            if (storedValue != 30)
            {
                throw new Exception("Stored value != 30");
            }
        }
コード例 #4
0
        internal void TestDef()
        {
            IdentOperand id     = new IdentOperand("A");
            TypeOperand  typeOp = new TypeOperand(TYPE.INT);

            Operand[]   operands = new Operand[] { id, typeOp };
            MemoryStore store    = new MemoryStore();

            DefOpCode op = new DefOpCode(operands, store);

            op.Execute();

            var storedValue = store.Get(id);

            if (storedValue != null)
            {
                throw new Exception("Stored value should have been null");
            }

            id       = new IdentOperand("@A");
            operands = new Operand[] { id, typeOp };

            bool noAtSignsPassed = false;

            try
            {
                op = new DefOpCode(operands, store);
                op.Execute();
            }
            catch (Exception ex)
            {
                noAtSignsPassed = true;
            }

            if (noAtSignsPassed == false)
            {
                throw new Exception("Expected Def.Execute to fail with @ in IDENT name.");
            }
        }
コード例 #5
0
        private static Instruction Parse(MethodInfo methodInfo)
        {
            Instruction head = null;
            Instruction tail = null;

            var data = methodInfo.GetMethodBody().GetILAsByteArray();

            var offset = 0u;

            while (offset < data.Length)
            {
                IOperand operand = null;

                short opcodeValue = data[offset++];
                if (opcodeValue == 0xFE)
                {
                    opcodeValue |= (short)data[offset++];
                }

                OpCode opcode = _opcodes[opcodeValue];

                switch (opcode.OperandType)
                {
                case OperandType.InlineBrTarget:
                {
                    var branchTarget = Read <uint>(data, ref offset) + offset;
                    operand = new BranchTargetOperand(branchTarget);
                    break;
                }

                case OperandType.InlineField:
                {
                    var metadataToken = Read <int>(data, ref offset);
                    try {
                        var fieldInfo = methodInfo.Module.ResolveField(metadataToken);
                        operand = new FieldOperand(fieldInfo);
                    } catch (Exception) {
                        operand = new FieldOperand(null);
                    }
                    break;
                }

                case OperandType.InlineI:
                    operand = new ImmediateOperand <uint>(opcode.OperandType, Read <uint>(data, ref offset));
                    break;

                case OperandType.InlineI8:
                    operand = new ImmediateOperand <ulong>(opcode.OperandType, Read <ulong>(data, ref offset));
                    break;

                case OperandType.InlineMethod:
                {
                    var metadataToken = Read <int>(data, ref offset);
                    try {
                        var inlineMethodInfo = methodInfo.Module.ResolveMethod(metadataToken);
                        operand = new MethodOperand(inlineMethodInfo);
                    } catch (Exception) {
                        operand = new MethodOperand(null);
                    }
                    break;
                }

                case OperandType.InlineNone:
                    break;

                case OperandType.InlineR:
                    operand = new ImmediateOperand <double>(opcode.OperandType, Read <double>(data, ref offset));
                    break;

                case OperandType.InlineSig:
                {
                    var metadataToken = Read <int>(data, ref offset);
                    try {
                        var blobData = methodInfo.Module.ResolveSignature(metadataToken);
                        operand = new DataBlobOperand(blobData);
                    } catch (Exception) {
                        operand = new DataBlobOperand(null);
                    }
                    break;
                }

                case OperandType.InlineString:
                {
                    var metadataToken = Read <int>(data, ref offset);
                    try {
                        var stringInfo = methodInfo.Module.ResolveString(metadataToken);
                        operand = new StringOperand(stringInfo);
                    } catch (Exception) {
                        operand = new StringOperand(null);
                    }
                    break;
                }

                case OperandType.InlineSwitch:
                {
                    var count         = Read <uint>(data, ref offset);
                    var tableOffset   = offset;
                    var switchTargets = new uint[count];
                    for (var i = 0; i < count; ++i)
                    {
                        switchTargets[i] = Read <uint>(data, ref offset) + tableOffset * count * 4;
                    }
                    throw new NotImplementedException();
                }

                case OperandType.InlineTok:
                {
                    var metadataToken = Read <int>(data, ref offset);
                    try {
                        var tokenRef = methodInfo.Module.ResolveType(metadataToken);
                        operand = new TypeOperand(opcode.OperandType, tokenRef);
                    } catch (Exception) {
                        operand = new TypeOperand(opcode.OperandType, null);
                    }
                    break;
                }

                case OperandType.InlineType:
                {
                    var metadataToken = Read <int>(data, ref offset);
                    try {
                        var tokenRef = methodInfo.Module.ResolveType(metadataToken, methodInfo.DeclaringType.GetGenericArguments(), methodInfo.GetGenericArguments());
                        operand = new TypeOperand(opcode.OperandType, tokenRef);
                    } catch (Exception) {
                        operand = new TypeOperand(opcode.OperandType, null);
                    }
                    break;
                }

                case OperandType.InlineVar:
                {
                    var variableOrdinal = Read <ushort>(data, ref offset);
                    operand = new VariableOperand(methodInfo.GetMethodBody().LocalVariables[variableOrdinal]);
                    break;
                }
                }

                var instruction = new Instruction(opcode, operand);

                if (head == null)
                {
                    head = tail = instruction;
                }
                else
                {
                    tail = tail.Next = instruction;
                }
            }

            // Fix branch instruction targets
            tail = head;
            while (tail != null)
            {
                if (tail.Operand is BranchTargetOperand branchTargetOperand)
                {
                    var next = tail.Next;
                    while (next != null && next.Offset != branchTargetOperand.BranchTarget)
                    {
                        next = next.Next;
                    }
                    branchTargetOperand.Target = next ?? throw new InvalidProgramException("Unable to resolve branch target");
                }
                tail = tail.Next;
            }

            return(head);
        }