public void Append(Instruction instruction)
        {
            if (instruction == null)
                throw new ArgumentNullException("instruction");

            instructions.Add(instruction);
        }
        public void Replace(Instruction target, Instruction instruction)
        {
            if (target == null)
                throw new ArgumentNullException("target");
            if (instruction == null)
                throw new ArgumentNullException("instruction");

            InsertAfter(target, instruction);
            Remove(target);
        }
        public void Remove(Instruction instruction)
        {
            if (instruction == null)
                throw new ArgumentNullException("instruction");

            if (!instructions.Remove(instruction))
                throw new ArgumentOutOfRangeException("instruction");
        }
        public static Instruction Create(OpCode opcode, Instruction[] targets)
        {
            if (targets == null)
                throw new ArgumentNullException("targets");
            if (opcode.OperandType != OperandType.InlineSwitch)
                throw new ArgumentException("opcode");

            return new Instruction(opcode, targets);
        }
Esempio n. 5
0
        int GetTargetOffset(Instruction instruction)
        {
            if (instruction == null)
            {
                var last = body.instructions[body.instructions.size - 1];
                return last.offset + last.GetSize();
            }

            return instruction.offset;
        }
Esempio n. 6
0
        static void CopyBranchStackSize(ref Dictionary<Instruction, int> stack_sizes, Instruction target, int stack_size)
        {
            if (stack_sizes == null)
                stack_sizes = new Dictionary<Instruction, int>();

            int branch_stack_size = stack_size;

            int computed_size;
            if (stack_sizes.TryGetValue(target, out computed_size))
                branch_stack_size = System.Math.Max(branch_stack_size, computed_size);

            stack_sizes[target] = branch_stack_size;
        }
Esempio n. 7
0
 static void ComputeStackSize(Instruction instruction, ref int stack_size)
 {
     switch (instruction.opcode.FlowControl)
     {
         case FlowControl.Branch:
         case FlowControl.Break:
         case FlowControl.Throw:
         case FlowControl.Return:
             stack_size = 0;
             break;
     }
 }
Esempio n. 8
0
 static void ComputeStackDelta(Instruction instruction, ref int stack_size)
 {
     switch (instruction.opcode.FlowControl)
     {
         case FlowControl.Call:
             {
                 var method = (IMethodSignature)instruction.operand;
                 // pop 'this' argument
                 if (method.HasImplicitThis() && instruction.opcode.Code != Code.Newobj)
                     stack_size--;
                 // pop normal arguments
                 if (method.HasParameters)
                     stack_size -= method.Parameters.Count;
                 // pop function pointer
                 if (instruction.opcode.Code == Code.Calli)
                     stack_size--;
                 // push return value
                 if (method.ReturnType.etype != ElementType.Void || instruction.opcode.Code == Code.Newobj)
                     stack_size++;
                 break;
             }
         default:
             ComputePopDelta(instruction.opcode.StackBehaviourPop, ref stack_size);
             ComputePushDelta(instruction.opcode.StackBehaviourPush, ref stack_size);
             break;
     }
 }
 static void ExpandMacro(Instruction instruction, OpCode opcode, object operand)
 {
     instruction.OpCode = opcode;
     instruction.Operand = operand;
 }
Esempio n. 10
0
        private static MethodBody CloneMethodBody(MethodBody body, MethodDefinition source, MethodDefinition target)
        {
            var context = target.DeclaringType.Module;
            var nb = new MethodBody(target)
            {
                MaxStackSize = body.MaxStackSize,
                InitLocals = body.InitLocals,
                CodeSize = body.CodeSize
            };

            var worker = nb.GetILProcessor();

            foreach (var var in body.Variables)
                nb.Variables.Add(new VariableDefinition(
                    var.Name, FixTypeImport(context, source, target, var.VariableType)));

            foreach (var instr in body.Instructions)
            {
                var ni = new Instruction(instr.OpCode, OpCodes.Nop);

                switch (instr.OpCode.OperandType)
                {
                    case OperandType.InlineArg:
                    case OperandType.ShortInlineArg:
                        if (instr.Operand == body.ThisParameter)
                            ni.Operand = nb.ThisParameter;
                        else
                        {
                            var param = body.Method.Parameters.IndexOf((ParameterDefinition)instr.Operand);
                            ni.Operand = target.Parameters[param];
                        }
                        break;
                    case OperandType.InlineVar:
                    case OperandType.ShortInlineVar:
                        var var = body.Variables.IndexOf((VariableDefinition)instr.Operand);
                        ni.Operand = nb.Variables[var];
                        break;
                    case OperandType.InlineField:
                        ni.Operand = FixFieldImport(context, source, target, (FieldReference)instr.Operand);
                        break;
                    case OperandType.InlineMethod:
                        ni.Operand = FixMethodImport(context, source, target, (MethodReference)instr.Operand);
                        break;
                    case OperandType.InlineType:
                        ni.Operand = FixTypeImport(context, source, target, (TypeReference)instr.Operand);
                        break;
                    case OperandType.InlineTok:
                        if ((instr.Operand) is TypeReference)
                            ni.Operand = FixTypeImport(context, source, target, (TypeReference)instr.Operand);
                        else if ((instr.Operand) is FieldReference)
                            ni.Operand = FixFieldImport(context, source, target, (FieldReference)instr.Operand);
                        else if ((instr.Operand) is MethodReference)
                            ni.Operand = FixMethodImport(context, source, target, (MethodReference)instr.Operand);
                        break;
                    case OperandType.ShortInlineBrTarget:
                    case OperandType.InlineBrTarget:
                    case OperandType.InlineSwitch:
                        break;
                    default:
                        ni.Operand = instr.Operand;
                        break;
                }

                worker.Append(ni);
            }

            for (var i = 0; i < body.Instructions.Count; i++)
            {
                var instr = nb.Instructions[i];
                var oldi = body.Instructions[i];

                switch (instr.OpCode.OperandType)
                {
                    case OperandType.InlineSwitch:
                        {
                            var olds = (Instruction[])oldi.Operand;
                            var targets = new Instruction[olds.Length];

                            for (var j = 0; j < targets.Length; j++)
                                targets[j] = GetInstruction(body, nb, olds[j]);

                            instr.Operand = targets;
                        }
                        break;
                    case OperandType.InlineBrTarget:
                    case OperandType.ShortInlineBrTarget:
                        instr.Operand = GetInstruction(body, nb, (Instruction)oldi.Operand);
                        break;
                }
            }

            foreach (var eh in body.ExceptionHandlers)
            {
                var neh = new ExceptionHandler(eh.HandlerType)
                {
                    TryStart = GetInstruction(body, nb, eh.TryStart),
                    TryEnd = GetInstruction(body, nb, eh.TryEnd),
                    HandlerStart = GetInstruction(body, nb, eh.HandlerStart),
                    HandlerEnd = GetInstruction(body, nb, eh.HandlerEnd)
                };

                switch (eh.HandlerType)
                {
                    case ExceptionHandlerType.Catch:
                        neh.CatchType = FixTypeImport(context, source, target, eh.CatchType);
                        break;
                    case ExceptionHandlerType.Filter:
                        neh.FilterStart = GetInstruction(body, nb, eh.FilterStart);
                        break;
                }

                nb.ExceptionHandlers.Add(neh);
            }

            return nb;
        }
Esempio n. 11
0
        internal static Instruction GetInstruction(MethodBody oldBody, MethodBody newBody, Instruction i)
        {
            int pos = oldBody.Instructions.IndexOf(i);
            if (pos > -1 && pos < newBody.Instructions.Count)
                return newBody.Instructions[pos];

            return new Instruction(int.MaxValue, OpCodes.Nop);
        }
Esempio n. 12
0
        void ResolveBranches(Collection<Instruction> instructions)
        {
            var items = instructions.items;
            var size = instructions.size;

            for (int i = 0; i < size; i++)
            {
                var instruction = items[i];
                switch (instruction.opcode.OperandType)
                {
                    case OperandType.ShortInlineBrTarget:
                    case OperandType.InlineBrTarget:
                        instruction.operand = GetInstruction((int)instruction.operand);
                        break;
                    case OperandType.InlineSwitch:
                        var offsets = (int[])instruction.operand;
                        var branches = new Instruction[offsets.Length];
                        for (int j = 0; j < offsets.Length; j++)
                            branches[j] = GetInstruction(offsets[j]);

                        instruction.operand = branches;
                        break;
                }
            }
        }
Esempio n. 13
0
        object ReadOperand(Instruction instruction)
        {
            switch (instruction.opcode.OperandType)
            {
                case OperandType.InlineSwitch:
                    var length = ReadInt32();
                    var base_offset = Offset + (4 * length);
                    var branches = new int[length];
                    for (int i = 0; i < length; i++)
                        branches[i] = base_offset + ReadInt32();
                    return branches;
                case OperandType.ShortInlineBrTarget:
                    return ReadSByte() + Offset;
                case OperandType.InlineBrTarget:
                    return ReadInt32() + Offset;
                case OperandType.ShortInlineI:
                    if (instruction.opcode == OpCodes.Ldc_I4_S)
                        return ReadSByte();

                    return ReadByte();
                case OperandType.InlineI:
                    return ReadInt32();
                case OperandType.ShortInlineR:
                    return ReadSingle();
                case OperandType.InlineR:
                    return ReadDouble();
                case OperandType.InlineI8:
                    return ReadInt64();
                case OperandType.ShortInlineVar:
                    return GetVariable(ReadByte());
                case OperandType.InlineVar:
                    return GetVariable(ReadUInt16());
                case OperandType.ShortInlineArg:
                    return GetParameter(ReadByte());
                case OperandType.InlineArg:
                    return GetParameter(ReadUInt16());
                case OperandType.InlineSig:
                    return GetCallSite(ReadToken());
                case OperandType.InlineString:
                    return GetString(ReadToken());
                case OperandType.InlineTok:
                case OperandType.InlineType:
                case OperandType.InlineMethod:
                case OperandType.InlineField:
                    return reader.LookupToken(ReadToken());
                default:
                    throw new NotSupportedException();
            }
        }
Esempio n. 14
0
        void ReadCode()
        {
            start = position;
            var code_size = body.code_size;

            if (code_size < 0 || buffer.Length <= (uint)(code_size + position))
                code_size = 0;

            var end = start + code_size;
            var instructions = body.instructions = new InstructionCollection((code_size + 1) / 2);

            while (position < end)
            {
                var offset = base.position - start;
                var opcode = ReadOpCode();
                var current = new Instruction(offset, opcode);

                if (opcode.OperandType != OperandType.InlineNone)
                    current.operand = ReadOperand(current);

                instructions.Add(current);
            }

            ResolveBranches(instructions);
        }
Esempio n. 15
0
 static void AppendLabel(StringBuilder builder, Instruction instruction)
 {
     builder.Append("IL_");
     builder.Append(instruction.offset.ToString("x4"));
 }
 static void MakeMacro(Instruction instruction, OpCode opcode)
 {
     instruction.OpCode = opcode;
     instruction.Operand = null;
 }
Esempio n. 17
0
        static void AddExceptionStackSize(Instruction handler_start, ref Dictionary<Instruction, int> stack_sizes)
        {
            if (handler_start == null)
                return;

            if (stack_sizes == null)
                stack_sizes = new Dictionary<Instruction, int>();

            stack_sizes[handler_start] = 1;
        }
        static bool OptimizeBranch(Instruction instruction)
        {
            var offset = ((Instruction)instruction.Operand).Offset - (instruction.Offset + instruction.OpCode.Size + 4);
            if (!(offset >= -128 && offset <= 127))
                return false;

            switch (instruction.OpCode.Code)
            {
                case Code.Br:
                    instruction.OpCode = OpCodes.Br_S;
                    break;
                case Code.Brfalse:
                    instruction.OpCode = OpCodes.Brfalse_S;
                    break;
                case Code.Brtrue:
                    instruction.OpCode = OpCodes.Brtrue_S;
                    break;
                case Code.Beq:
                    instruction.OpCode = OpCodes.Beq_S;
                    break;
                case Code.Bge:
                    instruction.OpCode = OpCodes.Bge_S;
                    break;
                case Code.Bgt:
                    instruction.OpCode = OpCodes.Bgt_S;
                    break;
                case Code.Ble:
                    instruction.OpCode = OpCodes.Ble_S;
                    break;
                case Code.Blt:
                    instruction.OpCode = OpCodes.Blt_S;
                    break;
                case Code.Bne_Un:
                    instruction.OpCode = OpCodes.Bne_Un_S;
                    break;
                case Code.Bge_Un:
                    instruction.OpCode = OpCodes.Bge_Un_S;
                    break;
                case Code.Bgt_Un:
                    instruction.OpCode = OpCodes.Bgt_Un_S;
                    break;
                case Code.Ble_Un:
                    instruction.OpCode = OpCodes.Ble_Un_S;
                    break;
                case Code.Blt_Un:
                    instruction.OpCode = OpCodes.Blt_Un_S;
                    break;
                case Code.Leave:
                    instruction.OpCode = OpCodes.Leave_S;
                    break;
            }

            return true;
        }
Esempio n. 19
0
        static void ComputeStackSize(Instruction instruction, ref Dictionary<Instruction, int> stack_sizes, ref int stack_size, ref int max_stack)
        {
            int computed_size;
            if (stack_sizes != null && stack_sizes.TryGetValue(instruction, out computed_size))
                stack_size = computed_size;

            max_stack = System.Math.Max(max_stack, stack_size);
            ComputeStackDelta(instruction, ref stack_size);
            max_stack = System.Math.Max(max_stack, stack_size);

            CopyBranchStackSize(instruction, ref stack_sizes, stack_size);
            ComputeStackSize(instruction, ref stack_size);
        }
Esempio n. 20
0
 public Instruction Create(OpCode opcode, Instruction[] targets)
 {
     return Instruction.Create(opcode, targets);
 }
Esempio n. 21
0
        static void CopyBranchStackSize(Instruction instruction, ref Dictionary<Instruction, int> stack_sizes, int stack_size)
        {
            if (stack_size == 0)
                return;

            switch (instruction.opcode.OperandType)
            {
                case OperandType.ShortInlineBrTarget:
                case OperandType.InlineBrTarget:
                    CopyBranchStackSize(ref stack_sizes, (Instruction)instruction.operand, stack_size);
                    break;
                case OperandType.InlineSwitch:
                    var targets = (Instruction[])instruction.operand;
                    for (int i = 0; i < targets.Length; i++)
                        CopyBranchStackSize(ref stack_sizes, targets[i], stack_size);
                    break;
            }
        }
Esempio n. 22
0
 public void Emit(OpCode opcode, Instruction[] targets)
 {
     Append(Create(opcode, targets));
 }
Esempio n. 23
0
        static bool IsFatRange(Instruction start, Instruction end)
        {
            if (start == null)
                throw new ArgumentException();

            if (end == null)
                return true;

            return end.Offset - start.Offset > 255 || start.Offset > 65535;
        }
Esempio n. 24
0
        public void InsertBefore(Instruction target, Instruction instruction)
        {
            if (target == null)
                throw new ArgumentNullException("target");
            if (instruction == null)
                throw new ArgumentNullException("instruction");

            var index = instructions.IndexOf(target);
            if (index == -1)
                throw new ArgumentOutOfRangeException("target");

            instructions.Insert(index, instruction);
        }
Esempio n. 25
0
        void WriteOperand(Instruction instruction)
        {
            var opcode = instruction.opcode;
            var operand_type = opcode.OperandType;
            if (operand_type == OperandType.InlineNone)
                return;

            var operand = instruction.operand;
            if (operand == null)
                throw new ArgumentException();

            switch (operand_type)
            {
                case OperandType.InlineSwitch:
                    {
                        var targets = (Instruction[])operand;
                        WriteInt32(targets.Length);
                        var diff = instruction.Offset + opcode.Size + (4 * (targets.Length + 1));
                        for (int i = 0; i < targets.Length; i++)
                            WriteInt32(GetTargetOffset(targets[i]) - diff);
                        break;
                    }
                case OperandType.ShortInlineBrTarget:
                    {
                        var target = (Instruction)operand;
                        WriteSByte((sbyte)(GetTargetOffset(target) - (instruction.Offset + opcode.Size + 1)));
                        break;
                    }
                case OperandType.InlineBrTarget:
                    {
                        var target = (Instruction)operand;
                        WriteInt32(GetTargetOffset(target) - (instruction.Offset + opcode.Size + 4));
                        break;
                    }
                case OperandType.ShortInlineVar:
                    WriteByte((byte)GetVariableIndex((VariableDefinition)operand));
                    break;
                case OperandType.ShortInlineArg:
                    WriteByte((byte)GetParameterIndex((ParameterDefinition)operand));
                    break;
                case OperandType.InlineVar:
                    WriteInt16((short)GetVariableIndex((VariableDefinition)operand));
                    break;
                case OperandType.InlineArg:
                    WriteInt16((short)GetParameterIndex((ParameterDefinition)operand));
                    break;
                case OperandType.InlineSig:
                    WriteMetadataToken(GetStandAloneSignature((CallSite)operand));
                    break;
                case OperandType.ShortInlineI:
                    if (opcode == OpCodes.Ldc_I4_S)
                        WriteSByte((sbyte)operand);
                    else
                        WriteByte((byte)operand);
                    break;
                case OperandType.InlineI:
                    WriteInt32((int)operand);
                    break;
                case OperandType.InlineI8:
                    WriteInt64((long)operand);
                    break;
                case OperandType.ShortInlineR:
                    WriteSingle((float)operand);
                    break;
                case OperandType.InlineR:
                    WriteDouble((double)operand);
                    break;
                case OperandType.InlineString:
                    WriteMetadataToken(
                        new MetadataToken(
                            TokenType.String,
                            GetUserStringIndex((string)operand)));
                    break;
                case OperandType.InlineType:
                case OperandType.InlineField:
                case OperandType.InlineMethod:
                case OperandType.InlineTok:
                    WriteMetadataToken(metadata.LookupToken((IMetadataTokenProvider)operand));
                    break;
                default:
                    throw new ArgumentException();
            }
        }
Esempio n. 26
0
        public static Instruction Create(OpCode opcode, Instruction target)
        {
            if (target == null)
                throw new ArgumentNullException("target");
            if (opcode.OperandType != OperandType.InlineBrTarget &&
                opcode.OperandType != OperandType.ShortInlineBrTarget)
                throw new ArgumentException("opcode");

            return new Instruction(opcode, target);
        }