Exemple #1
0
 public InstructionAttribute(char character, string engrish, string description, NodeType type, InstructionGroup group)
 {
     Character = character;
     Engrish = engrish;
     Description = description;
     Type = type;
     Group = group;
 }
Exemple #2
0
 public InstructionAttribute(char character, string engrish, string description, NodeType type, InstructionGroup group)
 {
     Character   = character;
     Engrish     = engrish;
     Description = description;
     Type        = type;
     Group       = group;
 }
Exemple #3
0
        /// <summary>
        /// Populated the initialization variables and instructions. Also populates the boundary instruction index.
        /// </summary>
        private void PopulateInitializationItemsAndFindBoundary()
        {
            // we want the collection of instructions before the boundary instruction (base constructor or chained constructor call)
            InstructionGroup instructionGroup = null;
            var isConstructorCallFound        = false;

            while (!isConstructorCallFound && InstructionGroup.TryGetNext(
                       this.Constructor.Body.Instructions,
                       instructionGroup?.LastIndex + 1 ?? 0,
                       out instructionGroup))
            {
                var instructionOperandAsMethodReference = instructionGroup.LastInstruction.Operand as MethodReference;
                if (instructionGroup.IsCall &&
                    instructionOperandAsMethodReference != null &&
                    instructionOperandAsMethodReference.Name == ".ctor" &&
                    (instructionOperandAsMethodReference.DeclaringType.FullName == this.Constructor.DeclaringType.FullName ||
                     instructionOperandAsMethodReference.DeclaringType.FullName == this.Constructor.DeclaringType.BaseType.FullName))
                {
                    this.InnerBoundaryFirstInstructionIndex = instructionGroup.FirstIndex;
                    this.InnerBoundaryLastInstructionIndex  = instructionGroup.LastIndex;
                    this.IsInitializingConstructor          =
                        instructionOperandAsMethodReference.DeclaringType.FullName == this.Constructor.DeclaringType.BaseType.FullName;
                    isConstructorCallFound = true;
                }
                else
                {
                    // add the instruction to initialization instructions
                    this.InnerInitializationInstructions.AddRange(instructionGroup.Instructions);
                }

                // any variables referenced by instructions should be removed from construction variables
                // and if we have not yet found the constructor call, then the variable should be put into initialization
                foreach (var instruction in instructionGroup.Instructions)
                {
                    VariableDefinition variable;
                    if (!this.TryGetReferencedVariable(instruction, out variable) ||
                        !this.InnerConstructionVariables.Contains(variable))
                    {
                        continue;
                    }

                    this.InnerConstructionVariables.Remove(variable);
                    if (!isConstructorCallFound)
                    {
                        // if an instance arises where a variable is only used in a constructor call
                        // then it would be dropped
                        this.InnerInitializationVariables.Add(variable);
                    }
                }
            }

            if (!isConstructorCallFound)
            {
                throw new InvalidOperationException(
                          $"Cannot find base or chained constructor call while multiplexing a constructor: {this.Constructor.FullName}");
            }
        }
Exemple #4
0
            /// <summary>
            /// Grabs the next group of instructions that could potentially be a base or chained construtor call.
            /// </summary>
            /// <param name="sourceInstructions">Source instructions to look at.</param>
            /// <param name="firstIndex">Index of the first instruction to look at.</param>
            /// <param name="instructionGroup">Output parameter to contain the results.</param>
            /// <returns><c>true</c> if a group was successfully created, else <c>false</c>.</returns>
            public static bool TryGetNext(IList <Instruction> sourceInstructions, int firstIndex, out InstructionGroup instructionGroup)
            {
                Contract.Requires(sourceInstructions != null);

                if (firstIndex < 0 || firstIndex >= sourceInstructions.Count)
                {
                    instructionGroup = null;
                    return(false);
                }

                var instructions = new List <Instruction>();
                var instruction  = sourceInstructions[firstIndex];

                instructions.Add(instruction);


                int lastIndex;

                if (instruction.OpCode.Code != Code.Ldarg_0)
                {
                    lastIndex = firstIndex;
                }
                else
                {
                    int i;
                    // calls into base and chained constructors start like this
                    // so we'll look for the next call instruction or any instruction where the next instruction is another ldarg.0
                    // meaning that the stack was cleared at some point
                    // there is no assumption that this grouping is generally useful, but the hope is that it will catch constructor calls in this specific case
                    var isLastInstructionFound = false;
                    for (i = firstIndex + 1; !isLastInstructionFound && i < sourceInstructions.Count; i++)
                    {
                        instruction = sourceInstructions[i];
                        instructions.Add(instruction);
                        if (instruction.OpCode.Code == Code.Call ||
                            instruction.OpCode.Code == Code.Callvirt ||
                            instruction.OpCode.Code == Code.Calli ||
                            (instruction.Next != null && instruction.Next.OpCode.Code == Code.Ldarg_0))
                        {
                            isLastInstructionFound = true;
                        }
                    }

                    lastIndex = i - 1;
                }

                instructionGroup = new InstructionGroup(firstIndex, lastIndex, instructions);
                return(true);
            }
Exemple #5
0
        protected static CreateMethod GetMethod(InstructionGroup group, bool unsigned, bool useReg)
        {
            var(regCount, immCount, memCount) = GetOpKindCount(group, useReg);
            int    regId = 1, immId = 1, memId = 1;
            string doc = group.Operands.Length switch {
                0 => "Creates an instruction with no operands",
                1 => "Creates an instruction with 1 operand",
                _ => $"Creates an instruction with {group.Operands.Length} operands",
            };
            var method = new CreateMethod(doc);

            AddCodeArg(method);
            int opNum = -1;

            foreach (var op in group.Operands)
            {
                opNum++;
                switch (op.Split(useReg))
                {
                case InstructionOperand.RegisterMemory:
                    throw new InvalidOperationException();

                case InstructionOperand.Register:
                    method.Args.Add(new MethodArg($"op{opNum}: Register", MethodArgType.Register, GetArgName("register", regCount, regId++)));
                    break;

                case InstructionOperand.Memory:
                    method.Args.Add(new MethodArg($"op{opNum}: Memory operand", MethodArgType.Memory, GetArgName("memory", memCount, memId++)));
                    break;

                case InstructionOperand.Imm32:
                    method.Args.Add(new MethodArg($"op{opNum}: Immediate value", unsigned ? MethodArgType.UInt32 : MethodArgType.Int32, GetArgName("immediate", immCount, immId++)));
                    break;

                case InstructionOperand.Imm64:
                    method.Args.Add(new MethodArg($"op{opNum}: Immediate value", unsigned ? MethodArgType.UInt64 : MethodArgType.Int64, GetArgName("immediate", immCount, immId++)));
                    break;

                default:
                    throw new InvalidOperationException();
                }
            }
            return(method);
Exemple #6
0
        private static void DoInstruction(Instruction ins)
        {
            InstructionGroup grp = ins.GetGroup();

            Debug.Write(ins.ToString() + " ");
            if (ins.HasArgument())
            {
                Debug.WriteLine(ReadInt32(cursor, code));
            }
            else
            {
                Debug.WriteLine("");
            }

            switch (grp)
            {
            case InstructionGroup.Base:
                BaseInstruction(ins);
                break;

            case InstructionGroup.Stack:
                StackInstruction(ins, ins.HasArgument() ? ReadInt32() : 0);
                break;

            case InstructionGroup.Aritmetics:
                ArithmeticInstruction(ins);
                break;

            case InstructionGroup.Bitwise:
                BitwiseCommand(ins);
                break;

            case InstructionGroup.ConditionsAndJumps:
                CondAndJumpInstruction(ins, ins.HasArgument() ? ReadInt32() : 0);
                break;
            }

                        #if DEBUG
            //Dump();
                        #endif
        }
Exemple #7
0
        public static void processMethod1(MethodDef method)
        {
            method.Body.SimplifyBranches();
            InstructionGroups instructionGroups = new InstructionGroups();
            InstructionGroup  instructionGroup  = new InstructionGroup();
            int  num  = 0;
            int  num2 = 0;
            bool flag = false;

            foreach (Instruction instruction in method.Body.Instructions)
            {
                int num3 = 0;
                int num4;
                instruction.CalculateStackUsage(out num4, out num3);
                instructionGroup.Add(instruction);
                num2 += num4 - num3;
                if (num4 == 0 && instruction.OpCode != OpCodes.Nop && (num2 == 0 || instruction.OpCode == OpCodes.Ret))
                {
                    if (!flag)
                    {
                        InstructionGroup instructionGroup2 = new InstructionGroup();
                        instructionGroup2.ID        = num++;
                        instructionGroup2.nextGroup = instructionGroup2.ID + 1;
                        instructionGroups.Add(instructionGroup2);
                        instructionGroup2           = new InstructionGroup();
                        instructionGroup2.ID        = num++;
                        instructionGroup2.nextGroup = instructionGroup2.ID + 1;
                        instructionGroups.Add(instructionGroup2);
                        flag = true;
                    }
                    instructionGroup.ID        = num++;
                    instructionGroup.nextGroup = instructionGroup.ID + 1;
                    instructionGroups.Add(instructionGroup);
                    instructionGroup = new InstructionGroup();
                }
            }
            if (instructionGroups.Count == 1)
            {
                return;
            }
            InstructionGroup last = instructionGroups.getLast();

            instructionGroups.Scramble(out instructionGroups);
            method.Body.Instructions.Clear();
            Local local = new Local(controlflow.asm.CorLibTypes.Int32);

            method.Body.Variables.Add(local);
            Instruction instruction2 = Instruction.Create(OpCodes.Nop);
            Instruction instruction3 = Instruction.Create(OpCodes.Br, instruction2);

            method.Body.Instructions.Add(Instruction.Create(OpCodes.Ldc_I4_0));
            method.Body.Instructions.Add(Instruction.Create(OpCodes.Stloc, local));
            method.Body.Instructions.Add(Instruction.Create(OpCodes.Br, instruction3));
            method.Body.Instructions.Add(instruction2);
            foreach (InstructionGroup instructionGroup3 in instructionGroups)
            {
                if (instructionGroup3 != last)
                {
                    method.Body.Instructions.Add(Instruction.Create(OpCodes.Ldloc, local));
                    method.Body.Instructions.Add(Instruction.Create(OpCodes.Ldc_I4, instructionGroup3.ID));
                    method.Body.Instructions.Add(Instruction.Create(OpCodes.Ceq));
                    Instruction instruction4 = Instruction.Create(OpCodes.Nop);
                    method.Body.Instructions.Add(Instruction.Create(OpCodes.Brfalse, instruction4));
                    foreach (Instruction item in instructionGroup3)
                    {
                        method.Body.Instructions.Add(item);
                    }
                    method.Body.Instructions.Add(Instruction.Create(OpCodes.Ldc_I4, instructionGroup3.nextGroup));
                    method.Body.Instructions.Add(Instruction.Create(OpCodes.Stloc, local));
                    method.Body.Instructions.Add(instruction4);
                }
            }
            method.Body.Instructions.Add(Instruction.Create(OpCodes.Ldloc, local));
            method.Body.Instructions.Add(Instruction.Create(OpCodes.Ldc_I4, instructionGroups.Count - 1));
            method.Body.Instructions.Add(Instruction.Create(OpCodes.Ceq));
            method.Body.Instructions.Add(Instruction.Create(OpCodes.Brfalse, instruction3));
            method.Body.Instructions.Add(Instruction.Create(OpCodes.Br, last[0]));
            method.Body.Instructions.Add(instruction3);
            foreach (Instruction item2 in last)
            {
                method.Body.Instructions.Add(item2);
            }
            method.Body.OptimizeBranches();
            method.Body.OptimizeMacros();
        }
Exemple #8
0
 protected abstract void GenCreate(FileWriter writer, CreateMethod method, InstructionGroup group, int id);
            /// <summary>
            /// Grabs the next group of instructions that could potentially be a base or chained construtor call.
            /// </summary>
            /// <param name="sourceInstructions">Source instructions to look at.</param>
            /// <param name="firstIndex">Index of the first instruction to look at.</param>
            /// <param name="instructionGroup">Output parameter to contain the results.</param>
            /// <returns><c>true</c> if a group was successfully created, else <c>false</c>.</returns>
            public static bool TryGetNext(IList<Instruction> sourceInstructions, int firstIndex, out InstructionGroup instructionGroup)
            {
                Contract.Requires(sourceInstructions != null);

                if (firstIndex < 0 || firstIndex >= sourceInstructions.Count)
                {
                    instructionGroup = null;
                    return false;
                }

                var instructions = new List<Instruction>();
                var instruction = sourceInstructions[firstIndex];
                instructions.Add(instruction);

                int lastIndex;
                if (instruction.OpCode.Code != Code.Ldarg_0) { lastIndex = firstIndex; }
                else
                {
                    int i;
                    // calls into base and chained constructors start like this
                    // so we'll look for the next call instruction or any instruction where the next instruction is another ldarg.0
                    // meaning that the stack was cleared at some point
                    // there is no assumption that this grouping is generally useful, but the hope is that it will catch constructor calls in this specific case
                    var isLastInstructionFound = false;
                    for (i = firstIndex + 1; !isLastInstructionFound && i < sourceInstructions.Count; i++)
                    {
                        instruction = sourceInstructions[i];
                        instructions.Add(instruction);
                        if (instruction.OpCode.Code == Code.Call ||
                            instruction.OpCode.Code == Code.Callvirt ||
                            instruction.OpCode.Code == Code.Calli ||
                            (instruction.Next != null && instruction.Next.OpCode.Code == Code.Ldarg_0))
                        {
                            isLastInstructionFound = true;
                        }
                    }

                    lastIndex = i - 1;
                }

                instructionGroup = new InstructionGroup(firstIndex, lastIndex, instructions);
                return true;
            }
 private static InstructionDescription MAKE_INST(InstructionCode code, string name, InstructionGroup group, InstructionFlags flags, OperandFlags oflags0, OperandFlags oflags1, int opReg, uint opcode0, uint opcode1)
 {
     return new InstructionDescription(code, name, group, flags, new OperandFlags[] { oflags0, oflags1 }, opReg, (int)opcode0, (int)opcode1);
 }
        private InstructionDescription(InstructionCode code, string name, InstructionGroup group, InstructionFlags flags, OperandFlags[] operandFlags, int opReg, int opcode0, int opcode1)
        {
            Contract.Requires(operandFlags != null);

            _code = code;
            _name = name;
            _group = (byte)group;
            _flags = (byte)flags;
            _operandFlags = new ReadOnlyCollection<OperandFlags>((OperandFlags[])operandFlags.Clone());
            _opcodeR = (short)opReg;
            _opcode0 = opcode0;
            _opcode1 = opcode1;
        }