Exemple #1
0
            // A basic block can end with a non-branch instruction or a conditional branch instruction.
            // In those cases there is an implict flow, it is not encoded in any instruction.
            // That forces us to translate the nodes in a very specific order or translate each instruction linearly.
            // The implicit flow expects a particular instruction after another one.
            // In order to avoid that situation we make the control flow explicit.
            // If a basic block terminates with a non branch instruction,
            // we generate a unconditional branch to the original fall through target.
            // If a basic block terminates with a conditional branch, we create an unconditional branch to the implicit target.
            private void TranslateImplicitFlow(IInstructionContainer container)
            {
                CFGNode n = container as CFGNode;

                var last = n.Instructions.Last();

                if (Model.Extensions.CanFallThroughNextInstruction(last))
                {
                    UnconditionalBranchInstruction explicitBr;
                    if (last is ConditionalBranchInstruction conditionalBranch)
                    {
                        var successor = n.Successors.Where(s => s.Instructions.First().Label != conditionalBranch.Target).Single();
                        explicitBr = new UnconditionalBranchInstruction(0, successor.Instructions.First().Label);
                    }
                    else
                    {
                        var successor = n.Successors.Single();
                        explicitBr = new UnconditionalBranchInstruction(0, successor.Instructions.First().Label);
                    }

                    explicitBr.Accept(this);
                }
            }
Exemple #2
0
 public virtual void Visit(UnconditionalBranchInstruction instruction)
 {
 }
Exemple #3
0
        public static void Inline(this MethodBody callerBody, MethodCallInstruction methodCall, MethodBody calleeBody)
        {
            // TODO: Fix local variables (and parameters) name clashing

            var index = callerBody.Instructions.IndexOf(methodCall);

            callerBody.Instructions.RemoveAt(index);

            Instruction nextInstruction = null;

            if (callerBody.Instructions.Count > index)
            {
                // The caller method has more instructions after the method call
                nextInstruction = callerBody.Instructions[index];
            }

            for (var i = 0; i < calleeBody.Parameters.Count; ++i)
            {
                var parameter = calleeBody.Parameters[i];
                var argument  = methodCall.Arguments[i];
                var copy      = new LoadInstruction(methodCall.Offset, parameter, argument);

                copy.Label = string.Format("{0}_{1}", methodCall.Label, copy.Label);
                callerBody.Instructions.Insert(index, copy);
                index++;
            }

            var lastCalleeInstructionIndex = calleeBody.Instructions.Count - 1;

            for (var i = 0; i < calleeBody.Instructions.Count; ++i)
            {
                var instruction = calleeBody.Instructions[i];

                if (instruction is ReturnInstruction)
                {
                    var ret = instruction as ReturnInstruction;

                    if (ret.HasOperand && methodCall.HasResult)
                    {
                        // Copy the return value of the callee to the result variable of the method call
                        var copy = new LoadInstruction(ret.Offset, methodCall.Result, ret.Operand);

                        copy.Label = string.Format("{0}_{1}", methodCall.Label, copy.Label);
                        callerBody.Instructions.Insert(index, copy);
                        index++;
                    }

                    if (nextInstruction != null && i < lastCalleeInstructionIndex)
                    {
                        // Jump to the instruction after the method call
                        var branch = new UnconditionalBranchInstruction(ret.Offset, nextInstruction.Offset);

                        branch.Label = string.Format("{0}_{1}", methodCall.Label, branch.Label);
                        callerBody.Instructions.Insert(index, branch);
                        index++;
                    }
                }
                else
                {
                    // TODO: Fix! We should clone the instruction
                    // so the original is not modified
                    // and calleeBody remain intacted

                    if (instruction is BranchInstruction)
                    {
                        var branch = instruction as BranchInstruction;
                        branch.Target = string.Format("{0}_{1}", methodCall.Label, branch.Target);
                    }
                    else if (instruction is SwitchInstruction)
                    {
                        var branch = instruction as SwitchInstruction;

                        for (var j = 0; j < branch.Targets.Count; ++j)
                        {
                            var target = branch.Targets[j];
                            branch.Targets[j] = string.Format("{0}_{1}", methodCall.Label, target);
                        }
                    }

                    instruction.Label = string.Format("{0}_{1}", methodCall.Label, instruction.Label);
                    callerBody.Instructions.Insert(index, instruction);
                    index++;
                }
            }
        }