public static SPOpcode ConditionToJump(SPOpcode spop, bool onTrue) { switch (spop) { case SPOpcode.sleq: return(onTrue ? SPOpcode.jsleq : SPOpcode.jsgrtr); case SPOpcode.sless: return(onTrue ? SPOpcode.jsless : SPOpcode.jsgeq); case SPOpcode.sgrtr: return(onTrue ? SPOpcode.jsgrtr : SPOpcode.jsleq); case SPOpcode.sgeq: return(onTrue ? SPOpcode.jsgeq : SPOpcode.jsless); case SPOpcode.eq: return(onTrue ? SPOpcode.jeq : SPOpcode.jneq); case SPOpcode.neq: return(onTrue ? SPOpcode.jneq : SPOpcode.jeq); case SPOpcode.not: return(onTrue ? SPOpcode.jzer : SPOpcode.jnz); default: //Debug.Assert(false); break; } return(spop); }
public DJumpCondition(SPOpcode spop, DNode node, NodeBlock lht, NodeBlock rht) : base(node) { // //Debug.Assert(getOperand(0) != null); spop_ = spop; trueTarget_ = lht; falseTarget_ = rht; }
static public string spop(SPOpcode op) { switch (op) { case SPOpcode.add: return "+"; case SPOpcode.sub: case SPOpcode.sub_alt: return "-"; case SPOpcode.less: case SPOpcode.sless: case SPOpcode.jsless: return "<"; case SPOpcode.grtr: case SPOpcode.sgrtr: case SPOpcode.jsgrtr: return ">"; case SPOpcode.leq: case SPOpcode.sleq: case SPOpcode.jsleq: return "<="; case SPOpcode.geq: case SPOpcode.sgeq: case SPOpcode.jsgeq: return ">="; case SPOpcode.eq: case SPOpcode.jeq: case SPOpcode.jzer: return "=="; case SPOpcode.jnz: case SPOpcode.jneq: case SPOpcode.neq: return "!="; case SPOpcode.and: return "&"; case SPOpcode.not: return "!"; case SPOpcode.or: return "|"; case SPOpcode.sdiv_alt: return "/"; case SPOpcode.smul: return "*"; case SPOpcode.shr: return ">>"; case SPOpcode.shl: return "<<"; case SPOpcode.invert: return "~"; case SPOpcode.xor: return "^"; case SPOpcode.sshr: return ">>>"; default: throw new Exception("NYI"); } }
public static SPOpcode Invert(SPOpcode spop) { switch (spop) { case SPOpcode.jsleq: return(SPOpcode.jsgrtr); case SPOpcode.jsless: return(SPOpcode.jsgeq); case SPOpcode.jsgrtr: return(SPOpcode.jsleq); case SPOpcode.jsgeq: return(SPOpcode.jsless); case SPOpcode.jeq: return(SPOpcode.jneq); case SPOpcode.jneq: return(SPOpcode.jeq); case SPOpcode.jnz: return(SPOpcode.jzer); case SPOpcode.jzer: return(SPOpcode.jnz); case SPOpcode.sleq: return(SPOpcode.sgrtr); case SPOpcode.sless: return(SPOpcode.sgeq); case SPOpcode.sgrtr: return(SPOpcode.sleq); case SPOpcode.sgeq: return(SPOpcode.sless); case SPOpcode.eq: return(SPOpcode.neq); case SPOpcode.neq: return(SPOpcode.eq); default: //Debug.Assert(false); break; } return(spop); }
private void readAll() { lir_.entry_pc = pc_; if (readOp() != SPOpcode.proc) { throw new Exception("invalid method, first op must be PROC"); } while (pc_ < (uint)file_.code.bytes.Length) { current_pc_ = pc_; SPOpcode op = readOp(); if (op == SPOpcode.proc) { break; } add(readInstruction(op)); } lir_.exit_pc = pc_; }
public LBinary(SPOpcode op, Register lhs, Register rhs) { spop_ = op; lhs_ = lhs; rhs_ = rhs; }
public LJumpCondition(SPOpcode op, LBlock true_target, LBlock false_target, uint target_offs) : base(target_offs, true_target, false_target) { op_ = op; }
public static SPOpcode Invert(SPOpcode spop) { switch (spop) { case SPOpcode.jsleq: return SPOpcode.jsgrtr; case SPOpcode.jsless: return SPOpcode.jsgeq; case SPOpcode.jsgrtr: return SPOpcode.jsleq; case SPOpcode.jsgeq: return SPOpcode.jsless; case SPOpcode.jeq: return SPOpcode.jneq; case SPOpcode.jneq: return SPOpcode.jeq; case SPOpcode.jnz: return SPOpcode.jzer; case SPOpcode.jzer: return SPOpcode.jnz; case SPOpcode.sleq: return SPOpcode.sgrtr; case SPOpcode.sless: return SPOpcode.sgeq; case SPOpcode.sgrtr: return SPOpcode.sleq; case SPOpcode.sgeq: return SPOpcode.sless; case SPOpcode.eq: return SPOpcode.neq; case SPOpcode.neq: return SPOpcode.eq; default: //Debug.Assert(false); break; } return spop; }
public LUnary(SPOpcode op, Register reg) { spop_ = op; reg_ = reg; }
public void makeStoreOp(SPOpcode op) { spop_ = op; }
public DBinary(SPOpcode op, DNode lhs, DNode rhs) : base(lhs, rhs) { spop_ = op; }
public void setConditional(SPOpcode op) { spop_ = op; }
public DUnary(SPOpcode op, DNode node) : base(node) { spop_ = op; }
public void rewrite(SPOpcode spop, DNode node) { spop_ = spop; replaceOperand(0, node); }
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); } } }
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]); } }
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); } } }
public DStore(DNode addr, DNode value) : base(addr, value) { //Debug.Assert(value != null); spop_ = SPOpcode.nop; }
public static SPOpcode ConditionToJump(SPOpcode spop, bool onTrue) { switch (spop) { case SPOpcode.sleq: return onTrue ? SPOpcode.jsleq : SPOpcode.jsgrtr; case SPOpcode.sless: return onTrue ? SPOpcode.jsless : SPOpcode.jsgeq; case SPOpcode.sgrtr: return onTrue ? SPOpcode.jsgrtr : SPOpcode.jsleq; case SPOpcode.sgeq: return onTrue ? SPOpcode.jsgeq : SPOpcode.jsless; case SPOpcode.eq: return onTrue ? SPOpcode.jeq : SPOpcode.jneq; case SPOpcode.neq: return onTrue ? SPOpcode.jneq : SPOpcode.jeq; case SPOpcode.not: return onTrue ? SPOpcode.jzer : SPOpcode.jnz; default: //Debug.Assert(false); break; } return spop; }
static public string spop(SPOpcode op) { switch (op) { case SPOpcode.add: return("+"); case SPOpcode.sub: case SPOpcode.sub_alt: return("-"); case SPOpcode.less: case SPOpcode.sless: case SPOpcode.jsless: return("<"); case SPOpcode.grtr: case SPOpcode.sgrtr: case SPOpcode.jsgrtr: return(">"); case SPOpcode.leq: case SPOpcode.sleq: case SPOpcode.jsleq: return("<="); case SPOpcode.geq: case SPOpcode.sgeq: case SPOpcode.jsgeq: return(">="); case SPOpcode.eq: case SPOpcode.jeq: case SPOpcode.jzer: return("=="); case SPOpcode.jnz: case SPOpcode.jneq: case SPOpcode.neq: return("!="); case SPOpcode.and: return("&"); case SPOpcode.not: return("!"); case SPOpcode.or: return("|"); case SPOpcode.sdiv_alt: return("/"); case SPOpcode.smul: return("*"); case SPOpcode.shr: return(">>"); case SPOpcode.shl: return("<<"); case SPOpcode.invert: return("~"); case SPOpcode.xor: return("^"); case SPOpcode.sshr: return(">>>"); default: throw new Exception("NYI"); } }