Пример #1
0
        public static void FindLoops(LBlock[] blocks)
        {
            // Mark backedges and headers.
            for (int i = 1; i < blocks.Length; i++)
            {
                LBlock block = blocks[i];
                for (int j = 0; j < block.numSuccessors; j++)
                {
                    LBlock successor = block.getSuccessor(j);
                    if (successor.id < block.id)
                    {
                        successor.setLoopHeader(block);
                        block.setInLoop(successor);
                        break;
                    }
                }
            }

            for (int i = 0; i < blocks.Length; i++)
            {
                LBlock block = blocks[i];
                if (block.backedge != null)
                {
                    MarkLoop(block.backedge);
                }
            }
        }
Пример #2
0
        // Split critical edges in the graph. A critical edge is an edge which
        // is neither its successor's only predecessor, nor its predecessor's
        // only successor. Critical edges must be split to prevent copy-insertion
        // and code motion from affecting other edges. It is probably not strictly
        // needed here.
        public static void SplitCriticalEdges(LBlock[] blocks)
        {
            for (var i = 0; i < blocks.Length; i++)
            {
                var block = blocks[i];
                if (block.numSuccessors < 2)
                {
                    continue;
                }

                for (var j = 0; j < block.numSuccessors; j++)
                {
                    var target = block.getSuccessor(j);
                    if (target.numPredecessors < 2)
                    {
                        continue;
                    }

                    // Create a new block inheriting from the predecessor.
                    var            split        = new LBlock(block.pc);
                    var            ins          = new LGoto(target);
                    LInstruction[] instructions = { ins };
                    split.setInstructions(instructions);
                    block.replaceSuccessor(j, split);
                    target.replacePredecessor(block, split);
                    split.addPredecessor(block);
                }
            }
        }
Пример #3
0
        public static void ComputeDominators(LBlock[] blocks)
        {
            BitArray[] doms = new BitArray[blocks.Length];
            for (int i = 0; i < doms.Length; i++)
            {
                doms[i] = new BitArray(doms.Length);
            }

            doms[0].Set(0, true);

            for (int i = 1; i < blocks.Length; i++)
            {
                for (int j = 0; j < blocks.Length; j++)
                {
                    doms[i].SetAll(true);
                }
            }

            // Compute dominators.
            bool changed;

            do
            {
                changed = false;
                for (int i = 1; i < blocks.Length; i++)
                {
                    LBlock block = blocks[i];
                    for (int j = 0; j < block.numPredecessors; j++)
                    {
                        LBlock   pred = block.getPredecessor(j);
                        BitArray u    = new BitArray(doms[i]);
                        doms[block.id].And(doms[pred.id]);
                        doms[block.id].Set(block.id, true);
                        if (!CompareBitArrays(doms[block.id], u))
                        {
                            changed = true;
                        }
                    }
                }
            }while (changed);

            // Turn the bit vectors into lists.
            for (int i = 0; i < blocks.Length; i++)
            {
                LBlock        block = blocks[i];
                List <LBlock> list  = new List <LBlock>();
                for (int j = 0; j < blocks.Length; j++)
                {
                    if (doms[block.id][j])
                    {
                        list.Add(blocks[j]);
                    }
                }
                block.setDominators(list.ToArray());
            }
        }
Пример #4
0
 public override void replaceSuccessor(int i, LBlock block)
 {
     if (i == 0)
     {
         defaultCase_ = block;
     }
     if (cases_.Count >= i && i > 0)
     {
         cases_[i - 1].target = block;
     }
 }
Пример #5
0
 private void transitionBlocks(LBlock next)
 {
     //Debug.Assert(pending_.Count == 0 || block_ != null);
     if (block_ != null)
     {
         //Debug.Assert(pending_[pending_.Count - 1].isControl());
         //Debug.Assert(block_.pc >= lir_.entry_pc && block_.pc < lir_.exit_pc);
         block_.setInstructions(pending_.ToArray());
         pending_.Clear();
     }
     block_ = next;
 }
Пример #6
0
        private static void MarkLoop(LBlock backedge)
        {
            var worklist = new LoopBodyWorklist(backedge);

            worklist.scan(backedge);
            while (!worklist.empty)
            {
                var block = worklist.pop();
                worklist.scan(block);
                block.setInLoop(backedge.loop);
            }
        }
Пример #7
0
 public void replacePredecessor(LBlock from, LBlock split)
 {
     //Debug.Assert(predecessors_.Contains(from));
     for (int i = 0; i < numPredecessors; i++)
     {
         if (getPredecessor(i) == from)
         {
             predecessors_[i] = split;
             break;
         }
     }
     //Debug.Assert(!predecessors_.Contains(from));
 }
Пример #8
0
 public static void DumpGraph(LBlock[] blocks, TextWriter tw)
 {
     for (int i = 0; i < blocks.Length; i++)
     {
         tw.WriteLine("Block " + i + ": (" + blocks[i].pc + ")");
         for (int j = 0; j < blocks[i].instructions.Length; j++)
         {
             tw.Write("  ");
             blocks[i].instructions[j].print(tw);
             tw.Write("\n");
         }
         tw.WriteLine("\n");
     }
 }
Пример #9
0
        // Return a reverse post-order listing of reachable blocks.
        public static LBlock[] Order(LBlock entry)
        {
            // Postorder traversal without recursion.
            var pending    = new Stack <LBlock>();
            var successors = new Stack <int>();
            var done       = new Stack <LBlock>();

            var current       = entry;
            var nextSuccessor = 0;

            for (; ;)
            {
                if (!current.marked)
                {
                    current.mark();
                    if (nextSuccessor < current.numSuccessors)
                    {
                        pending.Push(current);
                        successors.Push(nextSuccessor);
                        current       = current.getSuccessor(nextSuccessor);
                        nextSuccessor = 0;
                        continue;
                    }

                    done.Push(current);
                }

                if (pending.Count == 0)
                {
                    break;
                }

                current = pending.Pop();
                current.unmark();
                nextSuccessor = successors.Pop() + 1;
            }

            var blocks = new List <LBlock>();

            while (done.Count > 0)
            {
                current = done.Pop();
                current.unmark();
                current.setId(blocks.Count);
                blocks.Add(current);
            }

            return(blocks.ToArray());
        }
Пример #10
0
 private static LBlock SkipContainedLoop(LBlock block, LBlock header)
 {
     while (block.loop != null && block.loop == block)
     {
         if (block.loop != null)
         {
             block = block.loop;
         }
         if (block == header)
         {
             break;
         }
         block = block.getLoopPredecessor();
     }
     return(block);
 }
Пример #11
0
        // Return a reverse post-order listing of reachable blocks.
        public static LBlock[] Order(LBlock entry)
        {
            // Postorder traversal without recursion.
            Stack<LBlock> pending = new Stack<LBlock>();
            Stack<int> successors = new Stack<int>();
            Stack<LBlock> done = new Stack<LBlock>();

            LBlock current = entry;
            int nextSuccessor = 0;

            for (; ; )
            {
                if (!current.marked)
                {
                    current.mark();
                    if (nextSuccessor < current.numSuccessors)
                    {
                        pending.Push(current);
                        successors.Push(nextSuccessor);
                        current = current.getSuccessor(nextSuccessor);
                        nextSuccessor = 0;
                        continue;
                    }

                    done.Push(current);
                }

                if (pending.Count == 0)
                    break;

                current = pending.Pop();
                current.unmark();
                nextSuccessor = successors.Pop() + 1;
            }

            List<LBlock> blocks = new List<LBlock>();

            while (done.Count > 0)
            {
                current = done.Pop();
                current.unmark();
                current.setId(blocks.Count);
                blocks.Add(current);
            }

            return blocks.ToArray();
        }
Пример #12
0
        private static bool StrictlyDominatesADominator(LBlock from, LBlock dom)
        {
            for (var i = 0; i < from.dominators.Length; i++)
            {
                var other = from.dominators[i];
                if (other == from || other == dom)
                {
                    continue;
                }

                if (other.dominators.Contains(dom))
                {
                    return(true);
                }
            }
            return(false);
        }
Пример #13
0
        // The immediate dominator or idom of a node n is the unique node that
        // strictly dominates n but does not strictly dominate any other node
        // that strictly dominates n.
        private static void ComputeImmediateDominator(LBlock block)
        {
            for (var i = 0; i < block.dominators.Length; i++)
            {
                var dom = block.dominators[i];
                if (dom == block)
                {
                    continue;
                }

                if (!StrictlyDominatesADominator(block, dom))
                {
                    block.setImmediateDominator(dom);
                    return;
                }
            }
            //Debug.Assert(false, "not reached");
        }
Пример #14
0
        public static void ComputeDominatorTree(LBlock[] blocks)
        {
            List <LBlock>[] idominated = new List <LBlock> [blocks.Length];
            for (int i = 0; i < blocks.Length; i++)
            {
                idominated[i] = new List <LBlock>();
            }

            for (int i = 1; i < blocks.Length; i++)
            {
                LBlock block = blocks[i];
                idominated[block.idom.id].Add(block);
            }

            for (int i = 0; i < blocks.Length; i++)
            {
                blocks[i].setImmediateDominated(idominated[i].ToArray());
            }
        }
Пример #15
0
        private LGraph buildBlocks()
        {
            lir_.entry = new LBlock(lir_.entry_pc);
            BlockBuilder builder = new BlockBuilder(lir_);
            LBlock       entry   = builder.parse();

            // Get an RPO ordering of the blocks, since we don't have predecessors yet.
            LBlock[] blocks = BlockAnalysis.Order(entry);

            if (!BlockAnalysis.IsReducible(blocks))
            {
                throw new Exception("control flow graph is not reducible");
            }

            // Split critical edges in the graph (is this even needed?)
            BlockAnalysis.SplitCriticalEdges(blocks);

            // Reorder the blocks since we could have introduced new nodes.
            blocks = BlockAnalysis.Order(entry);
            //Debug.Assert(BlockAnalysis.IsReducible(blocks));

            BlockAnalysis.ComputeDominators(blocks);
            BlockAnalysis.ComputeImmediateDominators(blocks);
            BlockAnalysis.ComputeDominatorTree(blocks);
            BlockAnalysis.FindLoops(blocks);

            LGraph graph = new LGraph();

            graph.blocks = blocks;
            graph.entry  = blocks[0];
            if (lir_.argDepth > 0)
            {
                graph.nargs = ((lir_.argDepth - 12) / 4) + 1;
            }
            else
            {
                graph.nargs = 0;
            }

            return(graph);
        }
Пример #16
0
        // Split critical edges in the graph. A critical edge is an edge which
        // is neither its successor's only predecessor, nor its predecessor's
        // only successor. Critical edges must be split to prevent copy-insertion
        // and code motion from affecting other edges. It is probably not strictly
        // needed here.
        public static void SplitCriticalEdges(LBlock[] blocks)
        {
            for (int i = 0; i < blocks.Length; i++)
            {
                LBlock block = blocks[i];
                if (block.numSuccessors < 2)
                    continue;
                for (int j = 0; j < block.numSuccessors; j++)
                {
                    LBlock target = block.getSuccessor(j);
                    if (target.numPredecessors < 2)
                        continue;

                    // Create a new block inheriting from the predecessor.
                    LBlock split = new LBlock(block.pc);
                    LGoto ins = new LGoto(target);
                    LInstruction[] instructions = { ins };
                    split.setInstructions(instructions);
                    block.replaceSuccessor(j, split);
                    target.replacePredecessor(block, split);
                    split.addPredecessor(block);
                }
            }
        }
Пример #17
0
            public void scan(LBlock block)
            {
                for (var i = 0; i < block.numPredecessors; i++)
                {
                    var pred = block.getPredecessor(i);

                    // Has this block already been scanned?
                    if (pred.loop == backedge_.loop)
                    {
                        continue;
                    }

                    pred = SkipContainedLoop(pred, backedge_.loop);

                    // If this assert hits, there is probably a |break| keyword.
                    //Debug.Assert(pred.loop == null || pred.loop == backedge_.loop);
                    if (pred.loop != null)
                    {
                        continue;
                    }

                    stack_.Push(pred);
                }
            }
Пример #18
0
 public void setDominators(LBlock[] dominators)
 {
     dominators_ = dominators;
 }
Пример #19
0
 public virtual void replaceSuccessor(int i, LBlock block)
 {
     successors_[i] = block;
 }
Пример #20
0
 public SwitchCase(int value, LBlock target)
 {
     value_ = value;
     this.target = target;
 }
Пример #21
0
 public void setInLoop(LBlock loop)
 {
     loop_ = loop;
 }
Пример #22
0
 private void transitionBlocks(LBlock next)
 {
     //Debug.Assert(pending_.Count == 0 || block_ != null);
     if (block_ != null)
     {
         //Debug.Assert(pending_[pending_.Count - 1].isControl());
         //Debug.Assert(block_.pc >= lir_.entry_pc && block_.pc < lir_.exit_pc);
         block_.setInstructions(pending_.ToArray());
         pending_.Clear();
     }
     block_ = next;
 }
Пример #23
0
        public void traverse(NodeBlock block)
        {
            for (int i = 0; i < block.lir.numPredecessors; i++)
            {
                NodeBlock pred = blocks_[block.lir.getPredecessor(i).id];

                // Don't bother with backedges yet.
                if (pred.lir.id >= block.lir.id)
                {
                    continue;
                }

                block.inherit(graph_, pred);
            }

            foreach (LInstruction uins in block.lir.instructions)
            {
                // Attempt to find static declarations. This is really
                // expensive - we could cheapen it by creating per-method
                // lists of statics.
                {
                    int i = -1;
                    do
                    {
                        Variable var = file_.lookupDeclarations(uins.pc, ref i, Scope.Static);
                        if (var == null)
                        {
                            break;
                        }
                        block.add(new DDeclareStatic(var));
                    } while (true);
                }

                switch (uins.op)
                {
                case Opcode.DebugBreak:
                    break;

                case Opcode.Stack:
                {
                    LStack ins = (LStack)uins;
                    if (ins.amount < 0)
                    {
                        for (int i = 0; i < -ins.amount / 4; i++)
                        {
                            DDeclareLocal local = new DDeclareLocal(ins.pc, null);
                            block.stack.push(local);
                            block.add(local);
                        }
                    }
                    else
                    {
                        for (int i = 0; i < ins.amount / 4; i++)
                        {
                            block.stack.pop();
                        }
                    }
                    break;
                }

                case Opcode.Fill:
                {
                    LFill         ins   = (LFill)uins;
                    DNode         node  = block.stack.alt;
                    DDeclareLocal local = (DDeclareLocal)node;
                    //Debug.Assert(block.stack.pri.type == NodeType.Constant);
                    for (int i = 0; i < ins.amount; i += 4)
                    {
                        block.stack.set(local.offset + i, block.stack.pri);
                    }
                    break;
                }

                case Opcode.Constant:
                {
                    LConstant ins = (LConstant)uins;
                    DConstant v   = new DConstant(ins.val, ins.pc);
                    block.stack.set(ins.reg, v);
                    block.add(v);
                    break;
                }

                case Opcode.PushConstant:
                {
                    LPushConstant ins   = (LPushConstant)uins;
                    DConstant     v     = new DConstant(ins.val);
                    DDeclareLocal local = new DDeclareLocal(ins.pc, v);
                    block.stack.push(local);
                    block.add(v);
                    block.add(local);
                    break;
                }

                case Opcode.PushReg:
                {
                    LPushReg      ins   = (LPushReg)uins;
                    DDeclareLocal local = new DDeclareLocal(ins.pc, block.stack.reg(ins.reg));
                    block.stack.push(local);
                    block.add(local);
                    break;
                }

                case Opcode.Pop:
                {
                    LPop  ins  = (LPop)uins;
                    DNode node = block.stack.popAsTemp();
                    block.stack.set(ins.reg, node);
                    break;
                }

                case Opcode.StackAddress:
                {
                    LStackAddress ins   = (LStackAddress)uins;
                    DDeclareLocal local = block.stack.getName(ins.offset);
                    block.stack.set(ins.reg, local);
                    break;
                }

                case Opcode.PushStackAddress:
                {
                    LPushStackAddress ins   = (LPushStackAddress)uins;
                    DLocalRef         lref  = new DLocalRef(block.stack.getName(ins.offset));
                    DDeclareLocal     local = new DDeclareLocal(ins.pc, lref);
                    block.stack.push(local);
                    block.add(lref);
                    block.add(local);
                    break;
                }

                case Opcode.Goto:
                {
                    LGoto ins  = (LGoto)uins;
                    DJump node = new DJump(blocks_[ins.target.id]);
                    block.add(node);
                    break;
                }

                case Opcode.Jump:
                {
                    LJump ins  = (LJump)uins;
                    DJump node = new DJump(blocks_[ins.target.id]);
                    block.add(node);
                    break;
                }

                case Opcode.JumpCondition:
                {
                    LJumpCondition ins      = (LJumpCondition)uins;
                    NodeBlock      lhtarget = blocks_[ins.trueTarget.id];
                    NodeBlock      rhtarget = blocks_[ins.falseTarget.id];
                    DNode          cmp      = block.stack.pri;
                    SPOpcode       jmp      = ins.spop;
                    if (jmp != SPOpcode.jzer && jmp != SPOpcode.jnz)
                    {
                        SPOpcode newop;
                        switch (ins.spop)
                        {
                        case SPOpcode.jeq:
                            newop = SPOpcode.neq;
                            jmp   = SPOpcode.jzer;
                            break;

                        case SPOpcode.jneq:
                            newop = SPOpcode.eq;
                            jmp   = SPOpcode.jzer;
                            break;

                        case SPOpcode.jsgeq:
                            newop = SPOpcode.sless;
                            jmp   = SPOpcode.jzer;
                            break;

                        case SPOpcode.jsgrtr:
                            newop = SPOpcode.sleq;
                            jmp   = SPOpcode.jzer;
                            break;

                        case SPOpcode.jsleq:
                            newop = SPOpcode.sgrtr;
                            jmp   = SPOpcode.jzer;
                            break;

                        case SPOpcode.jsless:
                            newop = SPOpcode.sgeq;
                            jmp   = SPOpcode.jzer;
                            break;

                        default:
                            //Debug.Assert(false);
                            return;
                        }
                        cmp = new DBinary(newop, block.stack.pri, block.stack.alt);
                        block.add(cmp);
                    }
                    DJumpCondition jcc = new DJumpCondition(jmp, cmp, lhtarget, rhtarget);
                    block.add(jcc);
                    break;
                }

                case Opcode.LoadLocal:
                {
                    LLoadLocal ins  = (LLoadLocal)uins;
                    DLoad      load = new DLoad(block.stack.getName(ins.offset));
                    block.stack.set(ins.reg, load);
                    block.add(load);
                    break;
                }

                case Opcode.LoadLocalRef:
                {
                    LLoadLocalRef ins  = (LLoadLocalRef)uins;
                    DLoad         load = new DLoad(block.stack.getName(ins.offset));
                    load = new DLoad(load);
                    block.stack.set(ins.reg, load);
                    block.add(load);
                    break;
                }

                case Opcode.StoreLocal:
                {
                    LStoreLocal ins   = (LStoreLocal)uins;
                    DStore      store = new DStore(block.stack.getName(ins.offset), block.stack.reg(ins.reg));
                    block.add(store);
                    break;
                }

                case Opcode.StoreLocalRef:
                {
                    LStoreLocalRef ins   = (LStoreLocalRef)uins;
                    DLoad          load  = new DLoad(block.stack.getName(ins.offset));
                    DStore         store = new DStore(load, block.stack.reg(ins.reg));
                    block.add(store);
                    break;
                }

                case Opcode.SysReq:
                {
                    LSysReq      sysreq    = (LSysReq)uins;
                    DConstant    ins       = (DConstant)block.stack.popValue();
                    List <DNode> arguments = new List <DNode>();
                    for (int i = 0; i < ins.value; i++)
                    {
                        arguments.Add(block.stack.popName());
                    }
                    DSysReq call = new DSysReq(sysreq.native, arguments.ToArray());
                    block.stack.set(Register.Pri, call);
                    block.add(call);
                    break;
                }

                case Opcode.AddConstant:
                {
                    LAddConstant ins  = (LAddConstant)uins;
                    DConstant    val  = new DConstant(ins.amount);
                    DBinary      node = new DBinary(SPOpcode.add, block.stack.pri, val);
                    block.stack.set(Register.Pri, node);
                    block.add(val);
                    block.add(node);
                    break;
                }

                case Opcode.MulConstant:
                {
                    LMulConstant ins  = (LMulConstant)uins;
                    DConstant    val  = new DConstant(ins.amount);
                    DBinary      node = new DBinary(SPOpcode.smul, block.stack.pri, val);
                    block.stack.set(Register.Pri, node);
                    block.add(val);
                    block.add(node);
                    break;
                }

                case Opcode.Bounds:
                {
                    LBounds      ins  = (LBounds)uins;
                    DBoundsCheck node = new DBoundsCheck(block.stack.pri);
                    block.add(node);
                    break;
                }

                case Opcode.IndexAddress:
                {
                    LIndexAddress ins  = (LIndexAddress)uins;
                    DArrayRef     node = new DArrayRef(block.stack.alt, block.stack.pri, ins.shift);
                    block.stack.set(Register.Pri, node);
                    block.add(node);
                    break;
                }

                case Opcode.Move:
                {
                    LMove ins = (LMove)uins;
                    if (ins.reg == Register.Pri)
                    {
                        block.stack.set(Register.Pri, block.stack.alt);
                    }
                    else
                    {
                        block.stack.set(Register.Alt, block.stack.pri);
                    }
                    break;
                }

                case Opcode.Store:
                {
                    LStore ins   = (LStore)uins;
                    DStore store = new DStore(block.stack.alt, block.stack.pri);
                    block.add(store);
                    break;
                }

                case Opcode.Load:
                {
                    LLoad ins  = (LLoad)uins;
                    DLoad load = new DLoad(block.stack.pri);
                    block.stack.set(Register.Pri, load);
                    block.add(load);
                    break;
                }

                case Opcode.Swap:
                {
                    LSwap         ins   = (LSwap)uins;
                    DNode         lhs   = block.stack.popAsTemp();
                    DNode         rhs   = block.stack.reg(ins.reg);
                    DDeclareLocal local = new DDeclareLocal(ins.pc, rhs);
                    block.stack.set(ins.reg, lhs);
                    block.stack.push(local);
                    block.add(local);
                    break;
                }

                case Opcode.IncI:
                {
                    DIncDec inc = new DIncDec(block.stack.pri, 1);
                    block.add(inc);
                    break;
                }

                case Opcode.DecI:
                {
                    DIncDec dec = new DIncDec(block.stack.pri, -1);
                    block.add(dec);
                    break;
                }

                case Opcode.IncLocal:
                {
                    LIncLocal     ins   = (LIncLocal)uins;
                    DDeclareLocal local = block.stack.getName(ins.offset);
                    DIncDec       inc   = new DIncDec(local, 1);
                    block.add(inc);
                    break;
                }

                case Opcode.IncReg:
                {
                    LIncReg ins = (LIncReg)uins;
                    DIncDec dec = new DIncDec(block.stack.reg(ins.reg), 1);
                    block.add(dec);
                    break;
                }

                case Opcode.DecLocal:
                {
                    LDecLocal     ins   = (LDecLocal)uins;
                    DDeclareLocal local = block.stack.getName(ins.offset);
                    DIncDec       dec   = new DIncDec(local, -1);
                    block.add(dec);
                    break;
                }

                case Opcode.DecReg:
                {
                    LDecReg ins = (LDecReg)uins;
                    DIncDec dec = new DIncDec(block.stack.reg(ins.reg), -1);
                    block.add(dec);
                    break;
                }

                case Opcode.Return:
                {
                    DReturn node = new DReturn(block.stack.pri);
                    block.add(node);
                    break;
                }

                case Opcode.PushLocal:
                {
                    LPushLocal    ins   = (LPushLocal)uins;
                    DLoad         load  = new DLoad(block.stack.getName(ins.offset));
                    DDeclareLocal local = new DDeclareLocal(ins.pc, load);
                    block.stack.push(local);
                    block.add(load);
                    block.add(local);
                    break;
                }

                case Opcode.Exchange:
                {
                    DNode node = block.stack.alt;
                    block.stack.set(Register.Alt, block.stack.pri);
                    block.stack.set(Register.Pri, node);
                    break;
                }

                case Opcode.Unary:
                {
                    LUnary ins   = (LUnary)uins;
                    DUnary unary = new DUnary(ins.spop, block.stack.reg(ins.reg));
                    block.stack.set(Register.Pri, unary);
                    block.add(unary);
                    break;
                }

                case Opcode.Binary:
                {
                    LBinary ins    = (LBinary)uins;
                    DBinary binary = new DBinary(ins.spop, block.stack.reg(ins.lhs), block.stack.reg(ins.rhs));
                    block.stack.set(Register.Pri, binary);
                    block.add(binary);
                    break;
                }

                case Opcode.PushGlobal:
                {
                    LPushGlobal ins    = (LPushGlobal)uins;
                    Variable    global = file_.lookupGlobal(ins.address);
                    if (global == null)
                    {
                        global = file_.lookupVariable(ins.pc, ins.address, Scope.Static);
                    }
                    DGlobal       dglobal = new DGlobal(global);
                    DNode         node    = new DLoad(dglobal);
                    DDeclareLocal local   = new DDeclareLocal(ins.pc, node);
                    block.stack.push(local);
                    block.add(dglobal);
                    block.add(node);
                    block.add(local);
                    break;
                }

                case Opcode.LoadGlobal:
                {
                    LLoadGlobal ins    = (LLoadGlobal)uins;
                    Variable    global = file_.lookupGlobal(ins.address);
                    if (global == null)
                    {
                        global = file_.lookupVariable(ins.pc, ins.address, Scope.Static);
                    }
                    DNode dglobal = new DGlobal(global);
                    DNode node    = new DLoad(dglobal);
                    block.stack.set(ins.reg, node);
                    block.add(dglobal);
                    block.add(node);
                    break;
                }

                case Opcode.StoreGlobal:
                {
                    LStoreGlobal ins    = (LStoreGlobal)uins;
                    Variable     global = file_.lookupGlobal(ins.address);
                    if (global == null)
                    {
                        global = file_.lookupVariable(ins.pc, ins.address, Scope.Static);
                    }
                    DGlobal node  = new DGlobal(global);
                    DStore  store = new DStore(node, block.stack.reg(ins.reg));
                    block.add(node);
                    block.add(store);
                    break;
                }

                case Opcode.Call:
                {
                    LCall        ins       = (LCall)uins;
                    Function     f         = file_.lookupFunction((uint)ins.address);
                    DConstant    args      = (DConstant)block.stack.popValue();
                    List <DNode> arguments = new List <DNode>();
                    for (int i = 0; i < args.value; i++)
                    {
                        arguments.Add(block.stack.popName());
                    }
                    DCall call = new DCall(f, arguments.ToArray());
                    block.stack.set(Register.Pri, call);
                    block.add(call);
                    break;
                }

                case Opcode.EqualConstant:
                {
                    LEqualConstant ins  = (LEqualConstant)uins;
                    DConstant      c    = new DConstant(ins.value);
                    DBinary        node = new DBinary(SPOpcode.eq, block.stack.reg(ins.reg), c);
                    block.stack.set(Register.Pri, node);
                    block.add(c);
                    block.add(node);
                    break;
                }

                case Opcode.LoadIndex:
                {
                    LLoadIndex ins  = (LLoadIndex)uins;
                    DArrayRef  aref = new DArrayRef(block.stack.alt, block.stack.pri, ins.shift);
                    DLoad      load = new DLoad(aref);
                    block.stack.set(Register.Pri, load);
                    block.add(aref);
                    block.add(load);
                    break;
                }

                case Opcode.ZeroGlobal:
                {
                    LZeroGlobal ins     = (LZeroGlobal)uins;
                    Variable    global  = file_.lookupGlobal(ins.address);
                    DNode       dglobal = new DGlobal(global);
                    DConstant   rhs     = new DConstant(0);
                    DStore      lhs     = new DStore(dglobal, rhs);
                    block.add(dglobal);
                    block.add(rhs);
                    block.add(lhs);
                    break;
                }

                case Opcode.IncGlobal:
                {
                    LIncGlobal ins     = (LIncGlobal)uins;
                    Variable   global  = file_.lookupGlobal(ins.address);
                    DNode      dglobal = new DGlobal(global);

                    DLoad     load  = new DLoad(dglobal);
                    DConstant val   = new DConstant(1);
                    DBinary   add   = new DBinary(SPOpcode.add, load, val);
                    DStore    store = new DStore(dglobal, add);
                    block.add(load);
                    block.add(val);
                    block.add(add);
                    block.add(store);
                    break;
                }

                case Opcode.StoreGlobalConstant:
                {
                    LStoreGlobalConstant lstore = (LStoreGlobalConstant)uins;
                    Variable             var    = file_.lookupGlobal(lstore.address);
                    DConstant            val    = new DConstant(lstore.value);
                    DGlobal global = new DGlobal(var);
                    DStore  store  = new DStore(global, val);
                    block.add(val);
                    block.add(global);
                    block.add(store);
                    break;
                }

                case Opcode.StoreLocalConstant:
                {
                    LStoreLocalConstant lstore = (LStoreLocalConstant)uins;
                    DDeclareLocal       var    = block.stack.getName(lstore.address);
                    DConstant           val    = new DConstant(lstore.value);
                    DStore store = new DStore(var, val);
                    block.add(val);
                    block.add(store);
                    break;
                }

                case Opcode.ZeroLocal:
                {
                    LZeroLocal    lstore = (LZeroLocal)uins;
                    DDeclareLocal var    = block.stack.getName(lstore.address);
                    DConstant     val    = new DConstant(0);
                    DStore        store  = new DStore(var, val);
                    block.add(val);
                    block.add(store);
                    break;
                }

                case Opcode.Heap:
                {
                    LHeap ins  = (LHeap)uins;
                    DHeap heap = new DHeap(ins.amount);
                    block.add(heap);
                    block.stack.set(Register.Alt, heap);
                    break;
                }

                case Opcode.MemCopy:
                {
                    LMemCopy ins  = (LMemCopy)uins;
                    DMemCopy copy = new DMemCopy(block.stack.alt, block.stack.pri, ins.bytes);
                    block.add(copy);
                    break;
                }

                case Opcode.Switch:
                {
                    LSwitch ins     = (LSwitch)uins;
                    DSwitch switch_ = new DSwitch(block.stack.pri, ins);
                    block.add(switch_);
                    break;
                }

                default:
                    throw new Exception("unhandled opcode");
                }
            }

            for (int i = 0; i < block.lir.idominated.Length; i++)
            {
                LBlock lir = block.lir.idominated[i];
                traverse(blocks_[lir.id]);
            }
        }
Пример #24
0
            public void scan(LBlock block)
            {
                for (int i = 0; i < block.numPredecessors; i++)
                {
                    LBlock pred = block.getPredecessor(i);

                    // Has this block already been scanned?
                    if (pred.loop == backedge_.loop)
                        continue;

                    pred = SkipContainedLoop(pred, backedge_.loop);

                    // If this assert hits, there is probably a |break| keyword.
                    //Debug.Assert(pred.loop == null || pred.loop == backedge_.loop);
                    if (pred.loop != null)
                        continue;

                    stack_.Push(pred);
                }
            }
Пример #25
0
        public static void FindLoops(LBlock[] blocks)
        {
            // Mark backedges and headers.
            for (int i = 1; i < blocks.Length; i++)
            {
                LBlock block = blocks[i];
                for (int j = 0; j < block.numSuccessors; j++)
                {
                    LBlock successor = block.getSuccessor(j);
                    if (successor.id < block.id)
                    {
                        successor.setLoopHeader(block);
                        block.setInLoop(successor);
                        break;
                    }
                }
            }

            for (int i = 0; i < blocks.Length; i++)
            {
                LBlock block = blocks[i];
                if (block.backedge != null)
                    MarkLoop(block.backedge);
            }
        }
Пример #26
0
 public LJump(LBlock target, uint target_offs)
     : base(target_offs, target)
 {
 }
Пример #27
0
 public LJumpCondition(SPOpcode op, LBlock true_target, LBlock false_target, uint target_offs)
     : base(target_offs, true_target, false_target)
 {
     op_ = op;
 }
Пример #28
0
 public LGoto(LBlock target)
     : base(target)
 {
 }
Пример #29
0
 public override void replaceSuccessor(int i, LBlock block)
 {
     if (i == 0)
         defaultCase_ = block;
     if (cases_.Count >= i && i > 0)
     {
         cases_[i - 1].target = block;
     }
 }
Пример #30
0
 public LSwitch(LBlock defaultCase, List<SwitchCase> cases)
 {
     defaultCase_ = defaultCase;
     cases_ = cases;
 }
Пример #31
0
 public LSwitch(LBlock defaultCase, List <SwitchCase> cases)
 {
     defaultCase_ = defaultCase;
     cases_       = cases;
 }
Пример #32
0
 public LoopBodyWorklist(LBlock backedge)
 {
     backedge_ = backedge;
 }
Пример #33
0
 public LGoto(LBlock target)
     : base(target)
 {
 }
Пример #34
0
 private static LBlock SkipContainedLoop(LBlock block, LBlock header)
 {
     while (block.loop != null && block.loop == block)
     {
         if (block.loop != null)
             block = block.loop;
         if (block == header)
             break;
         block = block.getLoopPredecessor();
     }
     return block;
 }
Пример #35
0
 public void setImmediateDominator(LBlock idom)
 {
     idom_ = idom;
 }
Пример #36
0
 public void replaceSuccessor(int pos, LBlock split)
 {
     last.replaceSuccessor(pos, split);
 }
Пример #37
0
 public BlockBuilder(LIR lir)
 {
     lir_ = lir;
     block_ = lir_.entry;
 }
Пример #38
0
 public void addPredecessor(LBlock pred)
 {
     //Debug.Assert(!predecessors_.Contains(pred));
     predecessors_.Add(pred);
 }
Пример #39
0
        private ControlType findLoopJoinAndBody(NodeBlock header, NodeBlock effectiveHeader,
                                                out NodeBlock join, out NodeBlock body, out NodeBlock cond)
        {
            //Debug.Assert(effectiveHeader.lir.numSuccessors == 2);

            LBlock succ1 = effectiveHeader.lir.getSuccessor(0);
            LBlock succ2 = effectiveHeader.lir.getSuccessor(1);

            if (succ1.loop != header.lir || succ2.loop != header.lir)
            {
                //Debug.Assert(succ1.loop == header.lir || succ2.loop == header.lir);
                if (succ1.loop != header.lir)
                {
                    join = graph_[succ1.id];
                    body = graph_[succ2.id];
                }
                else
                {
                    join = graph_[succ2.id];
                    body = graph_[succ1.id];
                }
                cond = header;

                // If this is a self-loop, it is more correct to decompose it
                // to a do-while loop. This may not be source accurate in the
                // case of something like |while (x);| but it catches many more
                // source-accurate cases.
                if (header == effectiveHeader &&
                    BlockAnalysis.GetEmptyTarget(body) == header)
                {
                    body = null;
                    return(ControlType.DoWhileLoop);
                }

                return(ControlType.WhileLoop);
            }
            else
            {
                // Neither successor of the header exits the loop, so this is
                // probably a do-while loop. For now, assume it's simple.
                //Debug.Assert(header == effectiveHeader);
                LBlock backedge = header.lir.backedge;
                if (BlockAnalysis.GetEmptyTarget(graph_[backedge.id]) == header)
                {
                    // Skip an empty block sitting in between the backedge and
                    // the condition.
                    //Debug.Assert(backedge.numPredecessors == 1);
                    backedge = backedge.getPredecessor(0);
                }

                //Debug.Assert(backedge.numSuccessors == 2);
                succ1 = backedge.getSuccessor(0);
                succ2 = backedge.getSuccessor(1);

                body = header;
                cond = graph_[backedge.id];
                if (succ1.loop != header.lir)
                {
                    join = graph_[succ1.id];
                }
                else
                {
                    //Debug.Assert(succ2.loop != header.lir);
                    join = graph_[succ2.id];
                }
                return(ControlType.DoWhileLoop);
            }
        }
Пример #40
0
 public virtual void replaceSuccessor(int i, LBlock block)
 {
     successors_[i] = block;
 }
Пример #41
0
 public void replacePredecessor(LBlock from, LBlock split)
 {
     //Debug.Assert(predecessors_.Contains(from));
     for (int i = 0; i < numPredecessors; i++)
     {
         if (getPredecessor(i) == from)
         {
             predecessors_[i] = split;
             break;
         }
     }
     //Debug.Assert(!predecessors_.Contains(from));
 }
Пример #42
0
        private static bool StrictlyDominatesADominator(LBlock from, LBlock dom)
        {
            for (int i = 0; i < from.dominators.Length; i++)
            {
                LBlock other = from.dominators[i];
                if (other == from || other == dom)
                    continue;

                if (other.dominators.Contains(dom))
                    return true;
            }
            return false;
        }
Пример #43
0
 public void setLoopHeader(LBlock backedge)
 {
     backedge_ = backedge;
     loop_ = this;
 }
Пример #44
0
        public static void ComputeDominators(LBlock[] blocks)
        {
            BitArray[] doms = new BitArray[blocks.Length];
            for (int i = 0; i < doms.Length; i++)
                doms[i] = new BitArray(doms.Length);

            doms[0].Set(0, true);

            for (int i = 1; i < blocks.Length; i++)
            {
                for (int j = 0; j < blocks.Length; j++)
                    doms[i].SetAll(true);
            }

            // Compute dominators.
            bool changed;
            do
            {
                changed = false;
                for (int i = 1; i < blocks.Length; i++)
                {
                    LBlock block = blocks[i];
                    for (int j = 0; j < block.numPredecessors; j++)
                    {
                        LBlock pred = block.getPredecessor(j);
                        BitArray u = new BitArray(doms[i]);
                        doms[block.id].And(doms[pred.id]);
                        doms[block.id].Set(block.id, true);
                        if (!CompareBitArrays(doms[block.id], u))
                            changed = true;
                    }
                }
            }
            while (changed);

            // Turn the bit vectors into lists.
            for (int i = 0; i < blocks.Length; i++)
            {
                LBlock block = blocks[i];
                List<LBlock> list = new List<LBlock>();
                for (int j = 0; j < blocks.Length; j++)
                {
                    if (doms[block.id][j])
                        list.Add(blocks[j]);
                }
                block.setDominators(list.ToArray());
            }
        }
Пример #45
0
 public void setImmediateDominator(LBlock idom)
 {
     idom_ = idom;
 }
Пример #46
0
 public LJumpCondition(SPOpcode op, LBlock true_target, LBlock false_target, uint target_offs)
     : base(target_offs, true_target, false_target)
 {
     op_ = op;
 }
Пример #47
0
 public void setImmediateDominated(LBlock[] idominated)
 {
     idominated_ = idominated;
 }
Пример #48
0
 public BlockBuilder(LIR lir)
 {
     lir_   = lir;
     block_ = lir_.entry;
 }
Пример #49
0
 public SwitchCase(int value, LBlock target)
 {
     value_      = value;
     this.target = target;
 }
Пример #50
0
        public static void ComputeImmediateDominators(LBlock[] blocks)
        {
            blocks[0].setImmediateDominator(blocks[0]);

            for (int i = 1; i < blocks.Length; i++)
                ComputeImmediateDominator(blocks[i]);
        }
Пример #51
0
        public static void ComputeDominatorTree(LBlock[] blocks)
        {
            List<LBlock>[] idominated = new List<LBlock>[blocks.Length];
            for (int i = 0; i < blocks.Length; i++)
                idominated[i] = new List<LBlock>();

            for (int i = 1; i < blocks.Length; i++)
            {
                LBlock block = blocks[i];
                idominated[block.idom.id].Add(block);
            }

            for (int i = 0; i < blocks.Length; i++)
                blocks[i].setImmediateDominated(idominated[i].ToArray());
        }
Пример #52
0
 public void setInLoop(LBlock loop)
 {
     loop_ = loop;
 }
Пример #53
0
 public LJump(LBlock target, uint target_offs)
     : base(target_offs, target)
 {
 }
Пример #54
0
        private static void MarkLoop(LBlock backedge)
        {
            var worklist = new LoopBodyWorklist(backedge);

            worklist.scan(backedge);
            while (!worklist.empty)
            {
                LBlock block = worklist.pop();
                worklist.scan(block);
                block.setInLoop(backedge.loop);
            }
        }
Пример #55
0
 public void addPredecessor(LBlock pred)
 {
     //Debug.Assert(!predecessors_.Contains(pred));
     predecessors_.Add(pred);
 }
Пример #56
0
 public void setLoopHeader(LBlock backedge)
 {
     backedge_ = backedge;
     loop_     = this;
 }
Пример #57
0
            public LBlock parse()
            {
                for (int i = 0; i < lir_.instructions.Count; i++)
                {
                    LInstruction ins = lir_.instructions[i];

                    if (lir_.isTarget(ins.pc))
                    {
                        // This instruction is the target of a basic block, so
                        // finish the old one.
                        LBlock next = lir_.blockOfTarget(ins.pc);

                        // Multiple instructions could be at the same pc,
                        // because of decomposition, so make sure we're not
                        // transitioning to the same block.
                        if (block_ != next)
                        {
                            // Add implicit control flow to make further algorithms easier.
                            if (block_ != null)
                            {
                                //Debug.Assert(!pending_[pending_.Count - 1].isControl());
                                pending_.Add(new LGoto(next));
                                next.addPredecessor(block_);
                            }

                            // Fallthrough to the next block.
                            transitionBlocks(next);
                        }
                    }

                    // If there is no block present, we assume this is dead code.
                    if (block_ == null)
                    {
                        continue;
                    }

                    pending_.Add(ins);

                    switch (ins.op)
                    {
                    case Opcode.Return:
                    {
                        // A return terminates the current block.
                        transitionBlocks(null);
                        break;
                    }

                    case Opcode.Jump:
                    {
                        LJump jump = (LJump)ins;
                        jump.target.addPredecessor(block_);
                        transitionBlocks(null);
                        break;
                    }

                    case Opcode.JumpCondition:
                    {
                        LJumpCondition jcc = (LJumpCondition)ins;
                        jcc.trueTarget.addPredecessor(block_);
                        jcc.falseTarget.addPredecessor(block_);

                        // The next iteration will pick the false target up.
                        //Debug.Assert(lir_.instructions[i + 1].pc == jcc.falseTarget.pc);
                        transitionBlocks(null);
                        break;
                    }

                    case Opcode.Switch:
                    {
                        LSwitch switch_ = (LSwitch)ins;
                        for (int j = 0; j < switch_.numSuccessors; j++)
                        {
                            switch_.getSuccessor(j).addPredecessor(block_);
                        }
                        transitionBlocks(null);
                        break;
                    }
                    }
                }
                return(lir_.entry);
            }
Пример #58
0
        // The immediate dominator or idom of a node n is the unique node that
        // strictly dominates n but does not strictly dominate any other node
        // that strictly dominates n.
        private static void ComputeImmediateDominator(LBlock block)
        {
            for (int i = 0; i < block.dominators.Length; i++)
            {
                LBlock dom = block.dominators[i];
                if (dom == block)
                    continue;

                if (!StrictlyDominatesADominator(block, dom))
                {
                    block.setImmediateDominator(dom);
                    return;
                }
            }
            //Debug.Assert(false, "not reached");
        }
Пример #59
0
        private LInstruction readInstruction(SPOpcode op)
        {
            switch (op)
            {
            case SPOpcode.load_pri:
            case SPOpcode.load_alt:
            {
                Register reg = (op == SPOpcode.load_pri) ? Register.Pri : Register.Alt;
                return(new LLoadGlobal(readInt32(), reg));
            }

            case SPOpcode.load_s_pri:
            case SPOpcode.load_s_alt:
            {
                Register reg = (op == SPOpcode.load_s_pri) ? Register.Pri : Register.Alt;
                return(new LLoadLocal(trackStack(readInt32()), reg));
            }

            case SPOpcode.lref_s_pri:
            case SPOpcode.lref_s_alt:
            {
                Register reg = (op == SPOpcode.lref_s_pri) ? Register.Pri : Register.Alt;
                return(new LLoadLocalRef(trackStack(readInt32()), reg));
            }

            case SPOpcode.stor_s_pri:
            case SPOpcode.stor_s_alt:
            {
                Register reg = (op == SPOpcode.stor_s_pri) ? Register.Pri : Register.Alt;
                return(new LStoreLocal(reg, trackStack(readInt32())));
            }

            case SPOpcode.sref_s_pri:
            case SPOpcode.sref_s_alt:
            {
                Register reg = (op == SPOpcode.sref_s_pri) ? Register.Pri : Register.Alt;
                return(new LStoreLocalRef(reg, trackStack(readInt32())));
            }

            case SPOpcode.load_i:
                return(new LLoad(4));

            case SPOpcode.lodb_i:
                return(new LLoad(readInt32()));

            case SPOpcode.const_pri:
            case SPOpcode.const_alt:
            {
                Register reg = (op == SPOpcode.const_pri) ? Register.Pri : Register.Alt;
                return(new LConstant(readInt32(), reg));
            }

            case SPOpcode.addr_pri:
            case SPOpcode.addr_alt:
            {
                Register reg = (op == SPOpcode.addr_pri) ? Register.Pri : Register.Alt;
                return(new LStackAddress(trackStack(readInt32()), reg));
            }

            case SPOpcode.stor_pri:
            case SPOpcode.stor_alt:
            {
                Register reg = (op == SPOpcode.stor_pri) ? Register.Pri : Register.Alt;
                return(new LStoreGlobal(readInt32(), reg));
            }

            case SPOpcode.stor_i:
                return(new LStore(4));

            case SPOpcode.strb_i:
                return(new LStore(readInt32()));

            case SPOpcode.lidx:
                return(new LLoadIndex(4));

            case SPOpcode.lidx_b:
                return(new LLoadIndex(readInt32()));

            case SPOpcode.idxaddr:
                return(new LIndexAddress(2));

            case SPOpcode.idxaddr_b:
                return(new LIndexAddress(readInt32()));

            case SPOpcode.move_pri:
            case SPOpcode.move_alt:
            {
                Register reg = (op == SPOpcode.move_pri) ? Register.Pri : Register.Alt;
                return(new LMove(reg));
            }

            case SPOpcode.xchg:
                return(new LExchange());

            case SPOpcode.push_pri:
            case SPOpcode.push_alt:
            {
                Register reg = (op == SPOpcode.push_pri) ? Register.Pri : Register.Alt;
                return(new LPushReg(reg));
            }

            case SPOpcode.push_c:
                return(new LPushConstant(readInt32()));

            case SPOpcode.push:
                return(new LPushGlobal(readInt32()));

            case SPOpcode.push_s:
                return(new LPushLocal(trackStack(readInt32())));

            case SPOpcode.pop_pri:
            case SPOpcode.pop_alt:
            {
                Register reg = (op == SPOpcode.pop_pri) ? Register.Pri : Register.Alt;
                return(new LPop(reg));
            }

            case SPOpcode.stack:
                return(new LStack(readInt32()));

            case SPOpcode.retn:
                return(new LReturn());

            case SPOpcode.call:
                return(new LCall(readInt32()));

            case SPOpcode.jump:
            {
                uint offset = readUInt32();
                return(new LJump(prepareJumpTarget(offset), offset));
            }

            case SPOpcode.jeq:
            case SPOpcode.jneq:
            case SPOpcode.jnz:
            case SPOpcode.jzer:
            case SPOpcode.jsgeq:
            case SPOpcode.jsless:
            case SPOpcode.jsgrtr:
            case SPOpcode.jsleq:
            {
                uint offset = readUInt32();
                if (offset == pc_)
                {
                    return(new LJump(prepareJumpTarget(offset), offset));
                }
                return(new LJumpCondition(op, prepareJumpTarget(offset), prepareJumpTarget(pc_), offset));
            }

            case SPOpcode.sdiv_alt:
            case SPOpcode.sub_alt:
                return(new LBinary(op, Register.Alt, Register.Pri));

            case SPOpcode.add:
            case SPOpcode.and:
            case SPOpcode.or:
            case SPOpcode.smul:
            case SPOpcode.shr:
            case SPOpcode.shl:
            case SPOpcode.sub:
            case SPOpcode.sshr:
            case SPOpcode.xor:
                return(new LBinary(op, Register.Pri, Register.Alt));

            case SPOpcode.not:
            case SPOpcode.invert:
                return(new LUnary(op, Register.Pri));

            case SPOpcode.add_c:
                return(new LAddConstant(readInt32()));

            case SPOpcode.smul_c:
                return(new LMulConstant(readInt32()));

            case SPOpcode.zero_pri:
            case SPOpcode.zero_alt:
            {
                Register reg = (op == SPOpcode.zero_pri) ? Register.Pri : Register.Alt;
                return(new LConstant(0, reg));
            }

            case SPOpcode.zero_s:
                return(new LZeroLocal(trackStack(readInt32())));

            case SPOpcode.zero:
                return(new LZeroGlobal(readInt32()));

            case SPOpcode.eq:
            case SPOpcode.neq:
            case SPOpcode.sleq:
            case SPOpcode.sgeq:
            case SPOpcode.sgrtr:
            case SPOpcode.sless:
                return(new LBinary(op, Register.Pri, Register.Alt));

            case SPOpcode.eq_c_pri:
            case SPOpcode.eq_c_alt:
            {
                Register reg = (op == SPOpcode.eq_c_pri) ? Register.Pri : Register.Alt;
                return(new LEqualConstant(reg, readInt32()));
            }

            case SPOpcode.inc:
                return(new LIncGlobal(readInt32()));

            case SPOpcode.inc_s:
                return(new LIncLocal(trackStack(readInt32())));

            case SPOpcode.dec_s:
                return(new LDecLocal(trackStack(readInt32())));

            case SPOpcode.inc_i:
                return(new LIncI());

            case SPOpcode.inc_pri:
            case SPOpcode.inc_alt:
            {
                Register reg = (op == SPOpcode.inc_pri) ? Register.Pri : Register.Alt;
                return(new LIncReg(reg));
            }

            case SPOpcode.dec_pri:
            case SPOpcode.dec_alt:
            {
                Register reg = (op == SPOpcode.dec_pri) ? Register.Pri : Register.Alt;
                return(new LDecReg(reg));
            }

            case SPOpcode.dec_i:
                return(new LDecI());

            case SPOpcode.fill:
                return(new LFill(readInt32()));

            case SPOpcode.bounds:
                return(new LBounds(readInt32()));

            case SPOpcode.swap_pri:
            case SPOpcode.swap_alt:
            {
                Register reg = (op == SPOpcode.swap_pri) ? Register.Pri : Register.Alt;
                return(new LSwap(reg));
            }

            case SPOpcode.push_adr:
                return(new LPushStackAddress(trackStack(readInt32())));

            case SPOpcode.sysreq_n:
            {
                int index = readInt32();
                add(new LPushConstant(readInt32()));
                return(new LSysReq(file_.natives[index]));
            }

            case SPOpcode.dbreak:
                return(new LDebugBreak());

            case SPOpcode.endproc:
                return(null);

            case SPOpcode.push2_s:
            {
                add(new LPushLocal(trackStack(readInt32())));
                return(new LPushLocal(trackStack(readInt32())));
            }

            case SPOpcode.push2_adr:
            {
                add(new LPushStackAddress(trackStack(readInt32())));
                return(new LPushStackAddress(trackStack(readInt32())));
            }

            case SPOpcode.push2_c:
            {
                add(new LPushConstant(readInt32()));
                return(new LPushConstant(readInt32()));
            }

            case SPOpcode.push2:
            {
                add(new LPushGlobal(readInt32()));
                return(new LPushGlobal(readInt32()));
            }

            case SPOpcode.push3_s:
            {
                add(new LPushLocal(trackStack(readInt32())));
                add(new LPushLocal(trackStack(readInt32())));
                return(new LPushLocal(trackStack(readInt32())));
            }

            case SPOpcode.push3_adr:
            {
                add(new LPushStackAddress(trackStack(readInt32())));
                add(new LPushStackAddress(trackStack(readInt32())));
                return(new LPushStackAddress(trackStack(readInt32())));
            }

            case SPOpcode.push3_c:
            {
                add(new LPushConstant(readInt32()));
                add(new LPushConstant(readInt32()));
                return(new LPushConstant(readInt32()));
            }

            case SPOpcode.push3:
            {
                add(new LPushGlobal(readInt32()));
                add(new LPushGlobal(readInt32()));
                return(new LPushGlobal(readInt32()));
            }

            case SPOpcode.push4_s:
            {
                add(new LPushLocal(trackStack(readInt32())));
                add(new LPushLocal(trackStack(readInt32())));
                add(new LPushLocal(trackStack(readInt32())));
                return(new LPushLocal(trackStack(readInt32())));
            }

            case SPOpcode.push4_adr:
            {
                add(new LPushStackAddress(trackStack(readInt32())));
                add(new LPushStackAddress(trackStack(readInt32())));
                add(new LPushStackAddress(trackStack(readInt32())));
                return(new LPushStackAddress(trackStack(readInt32())));
            }

            case SPOpcode.push4_c:
            {
                add(new LPushConstant(readInt32()));
                add(new LPushConstant(readInt32()));
                add(new LPushConstant(readInt32()));
                return(new LPushConstant(readInt32()));
            }

            case SPOpcode.push4:
            {
                add(new LPushGlobal(readInt32()));
                add(new LPushGlobal(readInt32()));
                add(new LPushGlobal(readInt32()));
                return(new LPushGlobal(readInt32()));
            }

            case SPOpcode.push5_s:
            {
                add(new LPushLocal(trackStack(readInt32())));
                add(new LPushLocal(trackStack(readInt32())));
                add(new LPushLocal(trackStack(readInt32())));
                add(new LPushLocal(trackStack(readInt32())));
                return(new LPushLocal(trackStack(readInt32())));
            }

            case SPOpcode.push5_c:
            {
                add(new LPushConstant(readInt32()));
                add(new LPushConstant(readInt32()));
                add(new LPushConstant(readInt32()));
                add(new LPushConstant(readInt32()));
                return(new LPushConstant(readInt32()));
            }

            case SPOpcode.push5_adr:
            {
                add(new LPushStackAddress(trackStack(readInt32())));
                add(new LPushStackAddress(trackStack(readInt32())));
                add(new LPushStackAddress(trackStack(readInt32())));
                add(new LPushStackAddress(trackStack(readInt32())));
                return(new LPushStackAddress(trackStack(readInt32())));
            }

            case SPOpcode.push5:
            {
                add(new LPushGlobal(readInt32()));
                add(new LPushGlobal(readInt32()));
                add(new LPushGlobal(readInt32()));
                add(new LPushGlobal(readInt32()));
                return(new LPushGlobal(readInt32()));
            }

            case SPOpcode.load_both:
            {
                add(new LLoadLocal(readInt32(), Register.Pri));
                return(new LLoadLocal(readInt32(), Register.Alt));
            }

            case SPOpcode.load_s_both:
            {
                add(new LLoadLocal(trackStack(readInt32()), Register.Pri));
                return(new LLoadLocal(trackStack(readInt32()), Register.Alt));
            }

            case SPOpcode.const_:
            {
                return(new LStoreGlobalConstant(readInt32(), readInt32()));
            }

            case SPOpcode.const_s:
            {
                return(new LStoreLocalConstant(trackStack(readInt32()), readInt32()));
            }

            case SPOpcode.heap:
            {
                return(new LHeap(readInt32()));
            }

            case SPOpcode.movs:
            {
                return(new LMemCopy(readInt32()));
            }

            case SPOpcode.switch_:
            {
                uint table  = readUInt32();
                uint savePc = pc_;
                pc_ = table;

                SPOpcode casetbl = (SPOpcode)readUInt32();
                //Debug.Assert(casetbl == SPOpcode.casetbl);

                int  ncases      = readInt32();
                uint defaultCase = readUInt32();
                var  cases       = new List <SwitchCase>();
                for (int i = 0; i < ncases; i++)
                {
                    int    value  = readInt32();
                    uint   pc     = readUInt32();
                    LBlock target = prepareJumpTarget(pc);
                    cases.Add(new SwitchCase(value, target));
                }
                pc_ = savePc;
                return(new LSwitch(prepareJumpTarget(defaultCase), cases));
            }

            case SPOpcode.casetbl:
            {
                int ncases = readInt32();
                pc_ += (uint)ncases * 8 + 4;
                return(new LDebugBreak());
            }

            default:
            {
                throw new OpCodeNotKnownException("Unrecognized opcode " + op);
            }
            }
        }
Пример #60
0
 public void replaceSuccessor(int pos, LBlock split)
 {
     last.replaceSuccessor(pos, split);
 }