Beispiel #1
0
        public override void Run(IRContext context)
        {
            var unresolved = new List <IRBasicBlock>();

            foreach (var block in context.Function.BasicBlocks.AsEnumerable().Reverse())
            {
                if (block.SwitchFollow != null)
                {
                    foreach (var uBlock in unresolved)
                    {
                        if (block.SwitchFollow.ReversePostOrderIndex > uBlock.ReversePostOrderIndex)
                        {
                            uBlock.IfFollow = block.SwitchFollow;
                        }
                    }
                    unresolved.RemoveAll(a => a.IfFollow != null);
                    continue;
                }

                //and not some loop thingie
                if (block.Successors.Count != 2 || block.BlockJump.IsLoopJump || block.SwitchFollow != null)
                {
                    continue;
                }
                IRBasicBlock follow        = null;
                int          followInEdges = 0;
                for (int i = block.ReversePostOrderIndex + 1; i < context.Function.BasicBlocks.Count; i++)
                {
                    var dominatedBlock = context.Function.BasicBlocks[i];
                    if (dominatedBlock.ImmediateDominator != block)
                    {
                        continue;
                    }
                    int followInEdgesNew = dominatedBlock.Predecessors.Count - dominatedBlock.BackEdgeCount;
                    //if (followInEdgesNew >= followInEdges)
                    {
                        follow        = dominatedBlock;
                        followInEdges = followInEdgesNew;
                    }
                }

                if (follow != null && followInEdges > 1)
                {
                    block.IfFollow = follow;
                    foreach (var uBlock in unresolved)
                    {
                        if (follow.ReversePostOrderIndex > uBlock.ReversePostOrderIndex)
                        {
                            uBlock.IfFollow = follow;
                        }
                    }
                    unresolved.RemoveAll(a => a.IfFollow != null);
                }
                else
                {
                    unresolved.Add(block);
                }
            }
        }
Beispiel #2
0
 public IRReturn(IRBasicBlock parentBlock, IRExpression returnValue)
     : base(parentBlock)
 {
     ReturnValue = returnValue;
     if (!(ReturnValue is null))
     {
         Uses.UnionWith(ReturnValue.GetAllVariables());
     }
 }
Beispiel #3
0
        private bool IsBackEdge(IRBasicBlock p, IRBasicBlock s)
        {
            if (p.PreOrderIndex < s.PreOrderIndex)
            {
                return(false);
            }

            s.BackEdgeCount++;
            return(true);
        }
Beispiel #4
0
 public IRAssignment(IRBasicBlock parentBlock, IRExpression destination, IRExpression source)
     : base(parentBlock)
 {
     Destination = destination;
     Source      = source;
     if (Destination is IRVariable v)
     {
         Defs.Add(v);
     }
     Uses.UnionWith(Source.GetAllVariables());
 }
Beispiel #5
0
 public IRStore(IRBasicBlock parentBlock, IRType type, IRExpression address, IRExpression operand)
     : base(parentBlock)
 {
     if (type == IRPrimitive.Void || type == IRPrimitive.Bool)
     {
         throw new IRTypeException();
     }
     Type    = type;
     Address = address;
     Operand = operand;
     Uses.UnionWith(Address.GetAllVariables());
     Uses.UnionWith(Operand.GetAllVariables());
 }
Beispiel #6
0
        public override void Run(IRContext context)
        {
            var intervals =
                IRBasicBlock.GetIntervalSequence(context.Function.BasicBlocks, context.Function.BasicBlocks[0]);

            foreach (var gi in intervals)
            {
                var ni = gi.SelectMany(g => g.GetNodes()).ToArray();
                foreach (var intervalNode in gi)
                {
                    var headBBlock = intervalNode.GetHeadBasicBlock();
                    var nodes      = intervalNode.GetAllBasicBlocks().ToArray();

                    IRBasicBlock latchNode = null;
                    foreach (var predecessor in headBBlock.Predecessors)
                    {
                        if (!nodes.Contains(predecessor) || !IsBackEdge(predecessor, headBBlock))
                        {
                            continue;
                        }
                        if (latchNode == null || predecessor.ReversePostOrderIndex > latchNode.ReversePostOrderIndex)
                        {
                            latchNode = predecessor;
                        }
                    }

                    if (latchNode != null)
                    {
                        //todo: case level check
                        headBBlock.LatchNode = latchNode;
                        FindLoopNodes(context.Function, headBBlock, latchNode, nodes);
                        latchNode.IsLatchNode = true;
                    }
                }
            }
        }
Beispiel #7
0
 public override IEnumerable <IRInstruction> GetIRInstructions(IRContext context, IRBasicBlock parentBlock)
 {
     yield return(new IRReturn(parentBlock,
                               VariableUses.Count == 0 ? null : context.VariableMapping[VariableUses.First()]));
 }
        public override IEnumerable <IRInstruction> GetIRInstructions(IRContext context, IRBasicBlock parentBlock)
        {
            switch (Instruction.Id)
            {
            case ArmInstructionId.ARM_INS_ADD:
                if (Instruction.Details.Operands[0].Register.Id == ArmRegisterId.ARM_REG_PC)
                {
                    yield break;
                }
                if (Instruction.DisassembleMode == ArmDisassembleMode.Thumb &&
                    Instruction.Details.Operands.Length == 2)
                {
                    yield return(new IRAssignment(parentBlock, GetIROperand(context, 0),
                                                  GetIROperand(context, 0) + GetIRSecondOperand(context, 1)));
                }
                else if (Instruction.DisassembleMode == ArmDisassembleMode.Thumb &&
                         Instruction.Details.Operands.Length == 3 &&
                         Instruction.Details.Operands[2].Type == ArmOperandType.Immediate &&
                         Instruction.Details.Operands[2].Immediate == 0)
                {
                    yield return(new IRAssignment(parentBlock, GetIROperand(context, 0),
                                                  GetIROperand(context, 1)));
                }
                else
                {
                    yield return(new IRAssignment(parentBlock, GetIROperand(context, 0),
                                                  GetIROperand(context, 1) + GetIRSecondOperand(context, 2)));
                }
                break;

            case ArmInstructionId.ARM_INS_SUB:
                if (Instruction.DisassembleMode == ArmDisassembleMode.Thumb &&
                    Instruction.Details.Operands.Length == 2)
                {
                    yield return(new IRAssignment(parentBlock, GetIROperand(context, 0),
                                                  GetIROperand(context, 0) - GetIRSecondOperand(context, 1)));
                }
                else
                {
                    yield return(new IRAssignment(parentBlock, GetIROperand(context, 0),
                                                  GetIROperand(context, 1) - GetIRSecondOperand(context, 2)));
                }
                break;

            case ArmInstructionId.ARM_INS_RSB:
                yield return(new IRAssignment(parentBlock, GetIROperand(context, 0),
                                              GetIRSecondOperand(context, 2) - GetIROperand(context, 1)));

                break;

            case ArmInstructionId.ARM_INS_AND:
                yield return(new IRAssignment(parentBlock, GetIROperand(context, 0),
                                              GetIROperand(context, 1) & GetIRSecondOperand(context, 2)));

                break;

            case ArmInstructionId.ARM_INS_ORR:
                yield return(new IRAssignment(parentBlock, GetIROperand(context, 0),
                                              GetIROperand(context, 1) | GetIRSecondOperand(context, 2)));

                break;

            case ArmInstructionId.ARM_INS_EOR:
                yield return(new IRAssignment(parentBlock, GetIROperand(context, 0),
                                              GetIROperand(context, 1) ^ GetIRSecondOperand(context, 2)));

                break;

            case ArmInstructionId.ARM_INS_BIC:
                yield return(new IRAssignment(parentBlock, GetIROperand(context, 0),
                                              GetIROperand(context, 1) & ~GetIRSecondOperand(context, 2)));

                break;

            case ArmInstructionId.ARM_INS_LSL:
                if (Instruction.DisassembleMode == ArmDisassembleMode.Arm)
                {
                    goto case ArmInstructionId.ARM_INS_MOV;
                }
                yield return(new IRAssignment(parentBlock, GetIROperand(context, 0),
                                              GetIROperand(context, 1).ShiftLeft(GetIRSecondOperand(context, 2))));

                break;

            case ArmInstructionId.ARM_INS_LSR:
                if (Instruction.DisassembleMode == ArmDisassembleMode.Arm)
                {
                    goto case ArmInstructionId.ARM_INS_MOV;
                }
                yield return(new IRAssignment(parentBlock, GetIROperand(context, 0),
                                              GetIROperand(context, 1).ShiftRightLogical(GetIRSecondOperand(context, 2))));

                break;

            case ArmInstructionId.ARM_INS_ASR:
                if (Instruction.DisassembleMode == ArmDisassembleMode.Arm)
                {
                    goto case ArmInstructionId.ARM_INS_MOV;
                }
                yield return(new IRAssignment(parentBlock, GetIROperand(context, 0),
                                              GetIROperand(context, 1).ShiftRightArithmetic(GetIRSecondOperand(context, 2))));

                break;

            case ArmInstructionId.ARM_INS_ROR:
                if (Instruction.DisassembleMode == ArmDisassembleMode.Arm)
                {
                    goto case ArmInstructionId.ARM_INS_MOV;
                }
                throw new NotImplementedException();
                break;

            case ArmInstructionId.ARM_INS_RRX:
                if (Instruction.DisassembleMode == ArmDisassembleMode.Arm)
                {
                    goto case ArmInstructionId.ARM_INS_MOV;
                }
                throw new NotImplementedException();
                break;

            case ArmInstructionId.ARM_INS_MOV:
                yield return(new IRAssignment(parentBlock, GetIROperand(context, 0),
                                              GetIRSecondOperand(context, 1)));

                break;

            case ArmInstructionId.ARM_INS_MVN:
                yield return(new IRAssignment(parentBlock, GetIROperand(context, 0),
                                              ~GetIRSecondOperand(context, 1)));

                break;

            case ArmInstructionId.ARM_INS_MUL:
                yield return(new IRAssignment(parentBlock, GetIROperand(context, 0),
                                              GetIROperand(context, 1) * GetIROperand(context, 2)));

                break;

            case ArmInstructionId.ARM_INS_MLA:
                yield return(new IRAssignment(parentBlock, GetIROperand(context, 0),
                                              GetIROperand(context, 1) * GetIROperand(context, 2) + GetIROperand(context, 3)));

                break;

            case ArmInstructionId.ARM_INS_SMULL:
                yield return(new IRAssignment(parentBlock,
                                              GetIROperand(context, 0),
                                              (GetIROperand(context, 2).Cast(IRPrimitive.S32).Cast(IRPrimitive.S64) *
                                               GetIROperand(context, 3).Cast(IRPrimitive.S32).Cast(IRPrimitive.S64)).Cast(IRPrimitive.U32)));

                yield return(new IRAssignment(parentBlock,
                                              GetIROperand(context, 1),
                                              (GetIROperand(context, 2).Cast(IRPrimitive.S32).Cast(IRPrimitive.S64) *
                                               GetIROperand(context, 3).Cast(IRPrimitive.S32).Cast(IRPrimitive.S64)).ShiftRightLogical(32)
                                              .Cast(IRPrimitive.U32)));

                break;

            case ArmInstructionId.ARM_INS_LDR:
            case ArmInstructionId.ARM_INS_LDRH:
            case ArmInstructionId.ARM_INS_LDRSH:
            case ArmInstructionId.ARM_INS_LDRB:
            case ArmInstructionId.ARM_INS_LDRSB:
            {
                IRType type = IRPrimitive.Void;
                switch (Instruction.Id)
                {
                case ArmInstructionId.ARM_INS_LDR:
                    type = IRPrimitive.U32;
                    break;

                case ArmInstructionId.ARM_INS_LDRH:
                    type = IRPrimitive.U16;
                    break;

                case ArmInstructionId.ARM_INS_LDRSH:
                    type = IRPrimitive.S16;
                    break;

                case ArmInstructionId.ARM_INS_LDRB:
                    type = IRPrimitive.U8;
                    break;

                case ArmInstructionId.ARM_INS_LDRSB:
                    type = IRPrimitive.S8;
                    break;
                }

                if (Instruction.Details.WriteBack)
                {
                    throw new NotImplementedException("Unimplemented instruction!");
                }


                if (Instruction.Details.Operands[1].Memory.Base.Id == ArmRegisterId.ARM_REG_SP)
                {
                    yield return(new IRAssignment(parentBlock, GetIROperand(context, 0),
                                                  context.VariableMapping[VariableUses.First(v => v.Location == VariableLocation.Stack)]));

                    break;
                }

                if (Instruction.Details.Operands[1].Memory.Index == null &&
                    Instruction.Details.Operands[1].Memory.Displacement == 0)
                {
                    yield return(new IRAssignment(parentBlock, GetIROperand(context, 0),
                                                  new IRDerefExpression(type, GetIROperand(context, 1)).Cast(IRPrimitive.U32)));

                    break;
                }
                else if (Instruction.Details.Operands[1].Memory.Index == null)
                {
                    var deref = new IRDerefExpression(type,
                                                      GetIROperand(context, 1) + (uint)Instruction.Details.Operands[1].Memory.Displacement);
                    yield return(new IRAssignment(parentBlock, GetIROperand(context, 0),
                                                  deref.Cast(IRPrimitive.U32)));

                    break;
                }
                else
                {
                    if (Instruction.Details.Operands[1].ShiftOperation == ArmShiftOperation.Invalid ||
                        (Instruction.Details.Operands[1].ShiftOperation == ArmShiftOperation.ARM_SFT_LSL &&
                         Instruction.Details.Operands[1].ShiftValue == 0))
                    {
                        var deref = new IRDerefExpression(type,
                                                          GetIROperand(context, 1) + GetIROperand(context, 2));
                        yield return(new IRAssignment(parentBlock, GetIROperand(context, 0),
                                                      deref.Cast(IRPrimitive.U32)));

                        break;
                    }
                    else
                    {
                        throw new NotImplementedException("Unimplemented instruction!");
                    }
                }
            }

            case ArmInstructionId.ARM_INS_STR:
            case ArmInstructionId.ARM_INS_STRH:
            case ArmInstructionId.ARM_INS_STRB:
            {
                var type = IRPrimitive.Void;
                switch (Instruction.Id)
                {
                case ArmInstructionId.ARM_INS_STR:
                    type = IRPrimitive.U32;
                    break;

                case ArmInstructionId.ARM_INS_STRH:
                    type = IRPrimitive.U16;
                    break;

                case ArmInstructionId.ARM_INS_STRB:
                    type = IRPrimitive.U8;
                    break;
                }

                if (Instruction.Details.WriteBack)
                {
                    throw new NotImplementedException("Unimplemented instruction!");
                }


                if (Instruction.Details.Operands[1].Memory.Base.Id == ArmRegisterId.ARM_REG_SP)
                {
                    yield return(new IRAssignment(parentBlock,
                                                  context.VariableMapping[VariableDefs.First(v => v.Location == VariableLocation.Stack)],
                                                  GetIROperand(context, 0)));

                    break;
                }

                if (Instruction.Details.Operands[1].Memory.Index == null &&
                    Instruction.Details.Operands[1].Memory.Displacement == 0)
                {
                    yield return(new IRStore(parentBlock, type, GetIROperand(context, 1),
                                             GetIROperand(context, 0)));

                    break;
                }
                else if (Instruction.Details.Operands[1].Memory.Index == null)
                {
                    yield return(new IRStore(parentBlock, type,
                                             GetIROperand(context, 1) + (uint)Instruction.Details.Operands[1].Memory.Displacement,
                                             GetIROperand(context, 0)));

                    break;
                }
                else
                {
                    if (Instruction.Details.Operands[1].ShiftOperation == ArmShiftOperation.Invalid ||
                        (Instruction.Details.Operands[1].ShiftOperation == ArmShiftOperation.ARM_SFT_LSL &&
                         Instruction.Details.Operands[1].ShiftValue == 0))
                    {
                        yield return(new IRStore(parentBlock, type,
                                                 GetIROperand(context, 1) + GetIROperand(context, 2),
                                                 GetIROperand(context, 0)));

                        break;
                    }
                    else
                    {
                        throw new NotImplementedException("Unimplemented instruction!");
                    }
                }
            }

            case ArmInstructionId.ARM_INS_BL:
                yield return(new IRAssignment(parentBlock,
                                              context.VariableMapping[VariableDefs
                                                                      .First(v => v.Location == VariableLocation.Register && v.Address == 0)],
                                              new IRCallExpression(IRPrimitive.U32, $"sub_{Instruction.Details.Operands[0].Immediate:X08}",
                                                                   context.VariableMapping[VariableUses
                                                                                           .First(v => v.Location == VariableLocation.Register && v.Address == 0)],
                                                                   context.VariableMapping[VariableUses
                                                                                           .First(v => v.Location == VariableLocation.Register && v.Address == 1)],
                                                                   context.VariableMapping[VariableUses
                                                                                           .First(v => v.Location == VariableLocation.Register && v.Address == 2)],
                                                                   context.VariableMapping[VariableUses
                                                                                           .First(v => v.Location == VariableLocation.Register && v.Address == 3)]
                                                                   )));

                break;

            case ArmInstructionId.ARM_INS_BLX:
                if (Instruction.Details.Operands[0].Type == ArmOperandType.Immediate)
                {
                    goto case ArmInstructionId.ARM_INS_BL;
                }
                yield return(new IRAssignment(parentBlock,
                                              context.VariableMapping[VariableDefs
                                                                      .First(v => v.Location == VariableLocation.Register && v.Address == 0)],
                                              new IRCallExpression(IRPrimitive.U32, ((Variable)Operands[0].op).Name,
                                                                   context.VariableMapping[VariableUses
                                                                                           .First(v => v.Location == VariableLocation.Register && v.Address == 0)],
                                                                   context.VariableMapping[VariableUses
                                                                                           .First(v => v.Location == VariableLocation.Register && v.Address == 1)],
                                                                   context.VariableMapping[VariableUses
                                                                                           .First(v => v.Location == VariableLocation.Register && v.Address == 2)],
                                                                   context.VariableMapping[VariableUses
                                                                                           .First(v => v.Location == VariableLocation.Register && v.Address == 3)]
                                                                   )));

                break;

            case ArmInstructionId.ARM_INS_LDM:
                if (Instruction.Details.Operands[0].Register.Id == ArmRegisterId.ARM_REG_SP &&
                    Instruction.Details.WriteBack)
                {
                    break;
                }
                goto default;

            case ArmInstructionId.ARM_INS_STMDB:
                if (Instruction.Details.Operands[0].Register.Id == ArmRegisterId.ARM_REG_SP &&
                    Instruction.Details.WriteBack)
                {
                    break;
                }
                goto default;

            case ArmInstructionId.ARM_INS_PUSH:
            case ArmInstructionId.ARM_INS_POP:
            case ArmInstructionId.ARM_INS_CMP:
            case ArmInstructionId.ARM_INS_B:
            case ArmInstructionId.ARM_INS_BX:
                break;

            default:
                throw new NotImplementedException("Unimplemented instruction!");
            }
        }
Beispiel #9
0
 protected IRInstruction(IRBasicBlock parentBlock)
 {
     ParentBlock = parentBlock;
 }
 public override IEnumerable <IRInstruction> GetIRInstructions(IRContext context, IRBasicBlock parentBlock)
 {
     yield return(new IRAssignment(parentBlock, context.VariableMapping[(Variable)Operands[0].op], Constant));
 }
Beispiel #11
0
        public override void Run(IRContext context)
        {
            for (int i = context.Function.BasicBlocks.Count - 1; i >= 0; i--)
            {
                var block = context.Function.BasicBlocks[i];
                if (block.LoopHead != block || block.LoopType != LoopType.DoWhile)
                {
                    continue;
                }

                //find all loop invariant things
                var defs = new HashSet <IRVariable>();
                var uses = new HashSet <IRVariable>();
                for (int j = block.ReversePostOrderIndex; j <= block.LatchNode.ReversePostOrderIndex; j++)
                {
                    var loopBlock = context.Function.BasicBlocks[j];
                    if (loopBlock.LoopHead != block)
                    {
                        continue;
                    }
                    foreach (var instruction in loopBlock.Instructions)
                    {
                        defs.UnionWith(instruction.Defs);
                        uses.UnionWith(instruction.Uses);
                    }
                }

                var candidates = new HashSet <IRVariable>(defs);
                candidates.IntersectWith(uses);

                var condVars = new HashSet <IRVariable>(candidates);
                condVars.IntersectWith(block.LatchNode.BlockJump.Uses);

                if (condVars.Count != 1)
                {
                    continue;
                }

                var condVar = condVars.First();

                var condVarDefs  = block.FindDefs(block.Instructions.First(), condVar);
                int inLoopCount  = condVarDefs.Count(v => v.ParentBlock.LoopHead == block);
                int outLoopCount = condVarDefs.Length - inLoopCount;
                if (outLoopCount != 1 || inLoopCount != 1)
                {
                    continue;
                }
                var initialDef = condVarDefs.First(v => v.ParentBlock.LoopHead != block);
                if (!(initialDef is IRAssignment initialAssgn))
                {
                    continue;
                }
                var ifExpr = block.LatchNode.BlockJump.Condition.CloneComplete();
                ifExpr.Substitute(condVar, initialAssgn.Source);
                ifExpr = ifExpr.ReverseConditionSides();

                if (!(ifExpr is IRComparisonExpression cmp && cmp.OperandA is IRConstant && cmp.OperandB is IRConstant))
                {
                    var          invIfExpr = ifExpr.CloneComplete().InverseCondition();
                    IRBasicBlock ifBlock   = null;
                    for (int j = i - 1; j >= 0; j--)
                    {
                        var b = context.Function.BasicBlocks[j];
                        if (b.BlockJump != null &&
                            ((b.BlockJump.Destination != block.LoopFollow && b.BlockJump.Condition.Equals(ifExpr)) ||
                             (b.BlockJump.Destination == block.LoopFollow && b.BlockJump.Condition.Equals(invIfExpr))))
                        {
                            ifBlock = b;
                            break;
                        }
                    }

                    if (ifBlock == null)
                    {
                        continue;
                    }

                    block.ForLoopInitialIf = ifBlock;
                    ifBlock.ForLoopHead    = block;

                    //if we found the if block, we need to check for hoisted variables which are declared just before the loop
                    var hoistBlock = ifBlock.Successors.First(s => s != block.LoopFollow);
                    if (hoistBlock != block)
                    {
                        if (hoistBlock.Successors.Count != 1 || hoistBlock.Successors[0] != block)
                        {
                            throw new Exception();
                        }
                        var hoistVars  = new HashSet <IRVariable>();
                        var hoistInsts = new Dictionary <IRVariable, IRAssignment>();
                        foreach (var instruction in hoistBlock.Instructions)
                        {
                            if (!(instruction is IRAssignment assg) || !(assg.Destination is IRVariable hoistVar))
                            {
                                continue;
                            }
                            hoistInsts.Add(hoistVar, assg);
                            hoistVars.Add(hoistVar);
                        }

                        var invariantVars = new HashSet <IRVariable>(hoistVars);
                        invariantVars.ExceptWith(defs);
                        //invariantVars should be the vars that were invariant-hoisted out of the loop
                        //we can now simply substitute them back
                        foreach (var invariantVar in invariantVars)
                        {
                            var hoistInst = hoistInsts[invariantVar];
                            var hoistUses = hoistBlock.FindUses(hoistInst, invariantVar);
                            foreach (var use in hoistUses)
                            {
                                use.SubstituteUse(invariantVar, hoistInst.Source);
                            }
                            hoistBlock.Instructions.Remove(hoistInst);
                        }

                        hoistVars.ExceptWith(invariantVars);

                        var strengthVars = new HashSet <IRVariable>(hoistVars);
                        strengthVars.IntersectWith(candidates);
                        foreach (var strengthVar in strengthVars)
                        {
                            var hoistInst = hoistInsts[strengthVar];
                            var hoistDefs = block.FindDefs(0, strengthVar);
                            if (hoistDefs.Length != 2)
                            {
                                continue;
                            }
                            if (!(hoistDefs.FirstOrDefault(d => d != hoistInst) is IRAssignment assg))
                            {
                                continue;
                            }
                            if (!(assg.Source is IRBinaryExpression bin) || bin.Operator != IRBinaryOperator.Add)
                            {
                                continue;
                            }

                            var mulFactor = bin.OperandA.Equals(strengthVar) ? bin.OperandB : bin.OperandA;
                            var mulExpr   = condVar * mulFactor;

                            var hoistUses = hoistBlock.FindUses(hoistInst, strengthVar);
                            foreach (var use in hoistUses)
                            {
                                use.SubstituteUse(strengthVar, mulExpr);
                            }
                            hoistBlock.Instructions.Remove(hoistInst);
                            assg.ParentBlock.Instructions.Remove(assg);
                        }

                        if (hoistBlock.Instructions.Count != 0)
                        {
                            continue;
                        }
                        ifBlock.Successors[ifBlock.Successors.IndexOf(hoistBlock)] = block;
                        block.Predecessors[block.Predecessors.IndexOf(hoistBlock)] = ifBlock;
                        hoistBlock.Predecessors.Clear();
                        hoistBlock.Successors.Clear();
                    }
                }

                block.LoopType = LoopType.For;

                //move update of loop var to end of latch block
                if (condVarDefs.Length != 2)
                {
                    throw new Exception();
                }
                var loopVarDef = condVarDefs.First(v => v is IRAssignment && v.ParentBlock.LoopHead == block);//v.ParentBlock == block.LatchNode);
                loopVarDef.ParentBlock.Instructions.Remove(loopVarDef);
                block.LatchNode.Instructions.Insert(block.LatchNode.Instructions.Count - 1, loopVarDef);
            }
        }
 public IntervalNode(IRBasicBlock block)
 {
     Block = block;
 }
Beispiel #13
0
 public override IEnumerable <IRInstruction> GetIRInstructions(IRContext context, IRBasicBlock parentBlock)
 {
     yield return(new IRJump(parentBlock, context.BasicBlockMapping[Destination],
                             FlagsUseOperand == null || Condition == ArmConditionCode.ARM_CC_AL
             ? null
             : VariableUseLocs[(Variable)FlagsUseOperand].First().GetIRPredicateCode(context, Condition)));
 }
Beispiel #14
0
        public override IEnumerable <IRInstruction> GetIRInstructions(IRContext context, IRBasicBlock parentBlock)
        {
            var a = context.VariableMapping[(Variable)Operands[2].op].Cast(IRPrimitive.U64) |
                    context.VariableMapping[(Variable)Operands[3].op].Cast(IRPrimitive.U64).ShiftLeft(32);
            IRExpression b;

            if (Operands[4].op is Constant && Operands[5].op is Constant)
            {
                b = ((Constant)Operands[4].op).Value | ((ulong)((Constant)Operands[5].op).Value << 32);
            }
            else if (Operands[4].op is Constant && Operands[5].op is Variable)
            {
                uint constant = ((Constant)Operands[4].op).Value;
                if (constant == 0)
                {
                    b = context.VariableMapping[(Variable)Operands[5].op].Cast(IRPrimitive.U64).ShiftLeft(32);
                }
                else
                {
                    b = (ulong)((Constant)Operands[4].op).Value |
                        context.VariableMapping[(Variable)Operands[5].op].Cast(IRPrimitive.U64).ShiftLeft(32);
                }
            }
            else if (Operands[4].op is Variable && Operands[5].op is Constant)
            {
                uint constant = ((Constant)Operands[5].op).Value;
                if (constant == 0)
                {
                    b = context.VariableMapping[(Variable)Operands[4].op].Cast(IRPrimitive.U64);
                }
                else
                {
                    b = context.VariableMapping[(Variable)Operands[4].op].Cast(IRPrimitive.U64) |
                        ((ulong)((Constant)Operands[5].op).Value << 32);
                }
            }
            else
            {
                b = context.VariableMapping[(Variable)Operands[4].op].Cast(IRPrimitive.U64) |
                    context.VariableMapping[(Variable)Operands[5].op].Cast(IRPrimitive.U64).ShiftLeft(32);
            }

            yield return(new IRAssignment(parentBlock,
                                          context.VariableMapping[(Variable)Operands[0].op],
                                          (a + b).Cast(IRPrimitive.U32)));

            yield return(new IRAssignment(parentBlock,
                                          context.VariableMapping[(Variable)Operands[1].op],
                                          (a + b).ShiftRightLogical(32).Cast(IRPrimitive.U32)));
        }
Beispiel #15
0
        private void FindLoopNodes(IRFunction func, IRBasicBlock headNode, IRBasicBlock latchNode,
                                   IRBasicBlock[] intervalNodes)
        {
            headNode.LoopHead = headNode;
            var loopNodes = new List <IRBasicBlock>();

            loopNodes.Add(headNode);
            for (int i = headNode.ReversePostOrderIndex + 1; i < latchNode.ReversePostOrderIndex; i++)
            {
                var block = func.BasicBlocks[i];
                if (loopNodes.Contains(block.ImmediateDominator) && intervalNodes.Contains(block))
                {
                    loopNodes.Add(block);
                    if (block.LoopHead == null)
                    {
                        block.LoopHead = headNode;
                    }
                }
            }

            latchNode.LoopHead = headNode;
            if (latchNode != headNode)
            {
                loopNodes.Add(latchNode);
            }

            if (latchNode.Successors.Count == 2)
            {
                var latchElseBlock = latchNode.BlockJump.Destination;
                var latchIfBlock   = latchNode.Successors.First(s => s != latchElseBlock);
                // if (headNode.Successors.Count == 2 || latchNode == headNode)
                // {
                //     var headElseBlock = headNode.BlockBranch.Destination;
                //     var headIfBlock   = headNode.Successors.First(s => s != headElseBlock);
                //     // if (latchNode == headNode || (loopNodes.Contains(headElseBlock) && loopNodes.Contains(headIfBlock)))
                //     // {
                //         headNode.LoopType = LoopType.Repeat;
                //         if (latchIfBlock == headIfBlock)
                //             headNode.LoopFollow = latchElseBlock;
                //         else
                //             headNode.LoopFollow = latchIfBlock;
                //     // }
                //     // else
                //     // {
                //     //     headNode.LoopType = LoopType.While;
                //     //     if (loopNodes.Contains(headIfBlock))
                //     //         headNode.LoopFollow = headElseBlock;
                //     //     else
                //     //         headNode.LoopFollow = headIfBlock;
                //     // }
                // }
                // else
                // {
                headNode.LoopType = LoopType.DoWhile;
                if (latchIfBlock == headNode)
                {
                    headNode.LoopFollow = latchElseBlock;
                }
                else
                {
                    headNode.LoopFollow = latchIfBlock;
                }
                latchNode.BlockJump.IsLoopJump = true;
                // }
            }
            else
            {
                //todo
            }
        }