# HG changeset patch # User Windel Bouwman # Date 1381564583 -7200 # Node ID 2ccd57b1d78cd6053d82807542b27e1ad07587a9 # Parent 9fca39eebe507c339fad8f8df24456af0ff113c2 Fix register allocator to do burn2 OK diff -r 9fca39eebe50 -r 2ccd57b1d78c python/c3/codegenerator.py --- a/python/c3/codegenerator.py Sun Sep 29 14:08:15 2013 +0200 +++ b/python/c3/codegenerator.py Sat Oct 12 09:56:23 2013 +0200 @@ -155,20 +155,22 @@ return ir.Binop(ra, expr.op, rb) elif type(expr) is astnodes.Unop and expr.op == '&': ra = self.genExprCode(expr.a) - # TODO: Make this work? - return ra + assert type(ra) is ir.Mem + return ra.e elif type(expr) is astnodes.VariableUse: - return self.varMap[expr.target] + # This returns the dereferenced variable. + return ir.Mem(self.varMap[expr.target]) elif type(expr) is astnodes.Deref: # dereference pointer type: addr = self.genExprCode(expr.ptr) return ir.Mem(addr) elif type(expr) is astnodes.FieldRef: - b = self.genExprCode(expr.base) - #b = b.e + base = self.genExprCode(expr.base) + assert type(base) is ir.Mem, type(base) + base = base.e bt = theType(expr.base.typ) offset = ir.Const(bt.fieldOffset(expr.field)) - return ir.Mem(ir.Binop(b, '+', offset)) + return ir.Mem(ir.Add(base, offset)) elif type(expr) is astnodes.Literal: return ir.Const(expr.val) elif type(expr) is astnodes.TypeCast: diff -r 9fca39eebe50 -r 2ccd57b1d78c python/c3/examples/burn2.c3 --- a/python/c3/examples/burn2.c3 Sun Sep 29 14:08:15 2013 +0200 +++ b/python/c3/examples/burn2.c3 Sat Oct 12 09:56:23 2013 +0200 @@ -24,7 +24,7 @@ var int pin; pin = 15; // PD13 == output (01) - GPIOD->MODER = (1 << (pin * 2)); + GPIOD->MODER = (1 << (pin << 1)); GPIOD->ODR = (1 << pin); } diff -r 9fca39eebe50 -r 2ccd57b1d78c python/canon.py --- a/python/canon.py Sun Sep 29 14:08:15 2013 +0200 +++ b/python/canon.py Sat Oct 12 09:56:23 2013 +0200 @@ -58,7 +58,7 @@ return frame.parMap[exp] elif isinstance(exp, ir.LocalVariable): offset = frame.allocVar(exp) - return ir.Mem(ir.Binop(frame.fp, '+', ir.Const(offset))) + return ir.Add(frame.fp, ir.Const(offset)) elif isinstance(exp, ir.Mem): exp.e = rewriteExp(exp.e, frame) return exp diff -r 9fca39eebe50 -r 2ccd57b1d78c python/codeedit.py --- a/python/codeedit.py Sun Sep 29 14:08:15 2013 +0200 +++ b/python/codeedit.py Sat Oct 12 09:56:23 2013 +0200 @@ -1,6 +1,7 @@ #!/usr/bin/python import sys +import os from PyQt4.QtCore import * from PyQt4.QtGui import * import inspect @@ -262,7 +263,9 @@ def setFileName(self, fn): self.filename = fn - if not fn: + if fn: + fn = os.path.basename(fn) + else: fn = 'Untitled' self.setWindowTitle(fn) diff -r 9fca39eebe50 -r 2ccd57b1d78c python/codegenarm.py --- a/python/codegenarm.py Sun Sep 29 14:08:15 2013 +0200 +++ b/python/codegenarm.py Sat Oct 12 09:56:23 2013 +0200 @@ -70,11 +70,15 @@ """ self.instructions.insert(0, makeIns('{}:'.format(self.name))) self.instructions.insert(1, makeIns('push {lr, r7}')) - self.instructions.insert(2, makeIns('mov r7, sp')) - self.instructions.insert(3, makeIns('add sp, sp, {}'.format(self.stacksize))) - self.instructions.append(makeIns('sub sp, sp, {}'.format(self.stacksize))) + # Reserve stack space for locals: + self.instructions.insert(2, makeIns('sub sp, sp, {}'.format(self.stacksize))) + # Setup frame pointer: + self.instructions.insert(3, makeIns('mov r7, sp')) + # Stack grows downwards + self.instructions.append(makeIns('add sp, sp, {}'.format(self.stacksize))) self.instructions.append(makeIns('pop {pc,r7}')) # Add constant literals: + self.instructions.append(makeIns('align 4')) # Align at 4 bytes for ln, v in self.constants: self.instructions.append(makeIns('{}:'.format(ln))) self.instructions.append(makeIns('dcd {}'.format(v))) @@ -86,7 +90,8 @@ def munchExpr(self, e): if isinstance(e, ir.Alloc): return 0 - elif isinstance(e, ir.Binop) and e.operation == '+' and isinstance(e.b, ir.Const) and e.b.value < 8: + elif isinstance(e, ir.Binop) and e.operation == '+' and \ + isinstance(e.b, ir.Const) and e.b.value < 8: a = self.munchExpr(e.a) d = self.newTmp() self.emit('add %d0, %s0, {}'.format(e.b.value), dst=[d], src=[a]) @@ -97,7 +102,8 @@ d = self.newTmp() self.emit('add %d0, %s0, %s1', dst=[d], src=[a, b]) return d - elif isinstance(e, ir.Binop) and e.operation == '-' and isinstance(e.b, ir.Const) and e.b.value < 8: + elif isinstance(e, ir.Binop) and e.operation == '-' and \ + isinstance(e.b, ir.Const) and e.b.value < 8: a = self.munchExpr(e.a) d = self.newTmp() self.emit('sub %d0, %s0, {}'.format(e.b.value), dst=[d], src=[a]) @@ -112,22 +118,23 @@ a = self.munchExpr(e.a) b = self.munchExpr(e.b) d = self.newTmp() - self.emit('mov %d0, %s0', src=[a], dst=[d]) - self.emit('orr %d0, %s0', dst=[d], src=[b, d]) + self.move(d, a) + self.emit('orr %s1, %s0', dst=[], src=[b, d]) return d elif isinstance(e, ir.Binop) and e.operation == '<<': a = self.munchExpr(e.a) b = self.munchExpr(e.b) d = self.newTmp() - self.emit('mov %d0, %s0', src=[a], dst=[d]) - self.emit('lsl %d0, %s0', dst=[d], src=[b, d]) # TODO: is d a source variable? + self.move(d, a) + self.emit('lsl %s1, %s0', dst=[], src=[b, d]) # TODO: is d a source variable? return d elif isinstance(e, ir.Binop) and e.operation == '*': a = self.munchExpr(e.a) b = self.munchExpr(e.b) d = self.newTmp() - self.emit('mov %d0, %s0', src=[a], dst=[d]) - self.emit('mul %d0, %s0', dst=[d], src=[b, d]) + self.move(d, a) + # this mul instruction has operands swapped: + self.emit('mul %s0, %d0', dst=[d], src=[b, d]) return d elif isinstance(e, ir.Const) and e.value < 256: d = self.newTmp() @@ -142,7 +149,8 @@ e.e.operation == '+' and isinstance(e.e.b, ir.Const): base = self.munchExpr(e.e.a) d = self.newTmp() - self.emit('ldr %d0, [%s0 + {}]'.format(e.e.b.value), src=[base], dst=[d]) + c = e.e.b.value + self.emit('ldr %d0, [%s0 + {}]'.format(c), src=[base], dst=[d]) return d elif isinstance(e, ir.Mem): # Load from memory @@ -171,9 +179,13 @@ def munchStm(self, s): if isinstance(s, ir.Terminator): pass - elif isinstance(s, ir.Move) and isinstance(s.dst, ir.Mem) and isinstance(s.dst.e, ir.Binop) and s.dst.e.operation == '+' and isinstance(s.dst.e.a, ir.Temp) and isinstance(s.dst.e.b, ir.Const): + elif isinstance(s, ir.Move) and isinstance(s.dst, ir.Mem) and \ + isinstance(s.dst.e, ir.Binop) and s.dst.e.operation == '+' and \ + isinstance(s.dst.e.b, ir.Const): + a = self.munchExpr(s.dst.e.a) val = self.munchExpr(s.src) - self.emit('str %s1, [%s0 + {}]'.format(s.dst.e.b.value), src=[s.dst.e.a, val]) + c = s.dst.e.b.value + self.emit('str %s1, [%s0 + {}]'.format(c), src=[a, val]) elif isinstance(s, ir.Move) and isinstance(s.dst, ir.Mem): memloc = self.munchExpr(s.dst.e) val = self.munchExpr(s.src) @@ -185,7 +197,7 @@ elif isinstance(s, ir.Exp): # Generate expression code and discard the result. x = self.munchExpr(s.e) - self.emit('mov r0, r0', src=[x]) + self.emit('nop', src=[x]) elif isinstance(s, ir.Jump): tgt = self.targets[s.target] self.emit('b {}'.format(s.target.name), jumps=[tgt]) @@ -248,6 +260,10 @@ # another interface? assembler = asm.Assembler(target=arm.armtarget, stream=self.outs) self.outs.selectSection('code') + # assembly glue to make it work: + self.outs.emit(arm.dcd_ins(Imm32(0x20000678))) # initial SP + self.outs.emit(arm.dcd_ins(Imm32(0x08000009))) # reset vector + self.outs.emit(arm.b_ins(LabelRef('main'))) for frame in self.frames: for i in frame.instructions: assembler.assemble_line(str(i)) diff -r 9fca39eebe50 -r 2ccd57b1d78c python/cortexm3.py --- a/python/cortexm3.py Sun Sep 29 14:08:15 2013 +0200 +++ b/python/cortexm3.py Sat Oct 12 09:56:23 2013 +0200 @@ -218,6 +218,16 @@ def __repr__(self): return 'DCD 0x{0:X}'.format(self.expr) +@armtarget.instruction +class nop_ins(ArmInstruction): + mnemonic = 'nop' + operands = tuple() + + def encode(self): + return bytes() + + def __repr__(self): + return 'NOP' # Memory related @@ -299,6 +309,7 @@ def encode(self): rt = self.rt.num assert rt < 8 + assert self.offset % 4 == 0 imm8 = self.offset >> 2 assert imm8 < 256 assert imm8 >= 0 @@ -434,7 +445,7 @@ class mulregreg_ins(ArmInstruction): """ mul Rn, Rdm """ operands = (Reg8Op, Reg8Op) - mnemonic = 'mul' + mnemonic = 'MUL' def __init__(self, rn, rdm): self.rn = rn self.rdm = rdm diff -r 9fca39eebe50 -r 2ccd57b1d78c python/hexedit.py --- a/python/hexedit.py Sun Sep 29 14:08:15 2013 +0200 +++ b/python/hexedit.py Sat Oct 12 09:56:23 2013 +0200 @@ -5,7 +5,7 @@ from PyQt4.QtGui import * from PyQt4 import uic -BYTES_PER_LINE, GAP = 16, 12 +BYTES_PER_LINE, GAP = 8, 12 def clamp(minimum, x, maximum): return max(minimum, min(x, maximum)) diff -r 9fca39eebe50 -r 2ccd57b1d78c python/ide.py --- a/python/ide.py Sun Sep 29 14:08:15 2013 +0200 +++ b/python/ide.py Sat Oct 12 09:56:23 2013 +0200 @@ -282,15 +282,18 @@ self.builderrors.setErrorList(self.diag.diags) ce.setErrors(self.diag.diags) self.astViewer.setAst(pkg) + c3.AstPrinter().printAst(pkg) self.logger.info('Done!') def buildFile(self): ce = self.activeMdiChild() if not ce: return + fn = ce.FileName + wd = os.path.dirname(fn) self.diag.clear() outs = outstream.TextOutputStream() - if not zcc.zcc(ce.Source, outs, self.diag): + if not zcc.zcc(ce.Source, outs, self.diag, pack_dir=wd): # Set errors: self.builderrors.setErrorList(self.diag.diags) ce.setErrors(self.diag.diags) @@ -300,14 +303,17 @@ ce = self.activeMdiChild() if not ce: return + fn = ce.FileName + wd = os.path.dirname(fn) self.diag.clear() outs = outstream.TextOutputStream() - if not zcc.zcc(ce.Source, outs, self.diag, do_optimize=True): + if not zcc.zcc(ce.Source, outs, self.diag, do_optimize=True, pack_dir=wd): # Set errors: self.builderrors.setErrorList(self.diag.diags) ce.setErrors(self.diag.diags) return + outs.dump() code_s = outs.getSection('code') self.debugInfo = code_s.debugInfos() if self.ctrlToolbar.device: diff -r 9fca39eebe50 -r 2ccd57b1d78c python/instructionselector.py --- a/python/instructionselector.py Sun Sep 29 14:08:15 2013 +0200 +++ b/python/instructionselector.py Sat Oct 12 09:56:23 2013 +0200 @@ -1,4 +1,3 @@ - import ir import irmach from irmach import makeIns @@ -36,7 +35,6 @@ for i in bb.Instructions: self.munchStm(i) self.munchStm(ir.Move(self.frame.rv, f.return_value)) - self.emit('mov %s0, %s0', src=[self.frame.rv]) def move(self, dst, src): self.emit('mov %d0, %s0', src=[src], dst=[dst]) diff -r 9fca39eebe50 -r 2ccd57b1d78c python/interferencegraph.py --- a/python/interferencegraph.py Sun Sep 29 14:08:15 2013 +0200 +++ b/python/interferencegraph.py Sat Oct 12 09:56:23 2013 +0200 @@ -6,9 +6,10 @@ super().__init__(g) self.temps = [varname] self.moves = set() + self.color = None def __repr__(self): - return 'IGN<{}>'.format(self.temps) + return '{}({})'.format(self.temps, self.color) class InterferenceGraph(graph.Graph): @@ -52,12 +53,24 @@ n2 = self.getNode(tmp2) self.addEdge(n1, n2) + def to_dot(self, f): + """ Generate graphviz dot representation """ + for node in self.nodes: + print('{} [label="{}" shape=box3d];'.format(id(node), node), file=f) + for n, m in self.edges: + print('{} -> {};'.format(id(n), id(m)), file=f) + + def to_txt(self): + for node in self.nodes: + print('{} interferes: {}'.format(node, node.Adjecent)) + def getNode(self, tmp): # Linear search # TODO: can be improved for speed! for n in self.nodes: if tmp in n.temps: return n + print('new one!') n = InterferenceGraphNode(self, tmp) self.addNode(n) return n @@ -66,7 +79,15 @@ """ Combine n and m into n """ n.temps.extend(m.temps) n.moves.update(m.moves) - for t in m.Adjecent: - self.addEdge(n, t) + # Reroute all edges: + e1 = [e for e in self.edges if e[0] is m] + e2 = [e for e in self.edges if e[1] is m] + for e in e1: + self.edges.remove(e) + self.addEdge(n, e[1]) + for e in e2: + self.edges.remove(e) + self.addEdge(n, e[0]) + # Remove node m: self.delNode(m) diff -r 9fca39eebe50 -r 2ccd57b1d78c python/ir.py --- a/python/ir.py Sun Sep 29 14:08:15 2013 +0200 +++ b/python/ir.py Sat Oct 12 09:56:23 2013 +0200 @@ -274,6 +274,14 @@ """ Convenience call """ return Binop(a, '+', b) +def Sub(a, b): + return Binop(a, '-', b) + +def Mul(a, b): + return Binop(a, '*', b) + +def Div(a, b): + return Binop(a, '/', b) class Eseq(Expression): """ Sequence of instructions where the last is an expression """ @@ -397,6 +405,8 @@ return 'IF {} {} {} THEN {} ELSE {}'.format(self.a, self.cond, self.b, self.lab_yes, self.lab_no) +# Constructing IR: + class NamedClassGenerator: def __init__(self, prefix, cls): self.prefix = prefix diff -r 9fca39eebe50 -r 2ccd57b1d78c python/optimize.py --- a/python/optimize.py Sun Sep 29 14:08:15 2013 +0200 +++ b/python/optimize.py Sat Oct 12 09:56:23 2013 +0200 @@ -3,13 +3,14 @@ from transform import DeadCodeDeleter, ConstantFolder def optimize(ir): + return + cf = ConstantFolder() + cf.run(ir) return - cf = ConstantFolder() dcd = DeadCodeDeleter() m2r = Mem2RegPromotor() clr = CleanPass() cse = CommonSubexpressionElimination() - cf.run(ir) dcd.run(ir) clr.run(ir) m2r.run(ir) diff -r 9fca39eebe50 -r 2ccd57b1d78c python/registerallocator.py --- a/python/registerallocator.py Sun Sep 29 14:08:15 2013 +0200 +++ b/python/registerallocator.py Sat Oct 12 09:56:23 2013 +0200 @@ -34,10 +34,18 @@ self.activeMoves = set() self.worklistMoves = set() + def printLive(self): + print('Liveness:') + for i in self.f.instructions: + cfgn = self.f.cfg._map[i] + print(i, cfgn.live_in) + def Build(self): """ 1. Construct interference graph from instruction list """ self.f.cfg = FlowGraph(self.f.instructions) self.f.ig = InterferenceGraph(self.f.cfg) + self.printLive() + self.Node = self.f.ig.getNode # Divide nodes into pre-colored and initial: @@ -56,6 +64,7 @@ dict(self.f.tempMap) # start with pre-colored self.moves = [i for i in self.f.instructions if i.ismove] + print(self.moves) for mv in self.moves: self.Node(mv.src[0]).moves.add(mv) self.Node(mv.dst[0]).moves.add(mv) @@ -159,6 +168,7 @@ okColors = self.regs - takenregs if okColors: self.color[n] = first(okColors) + n.color = self.color[n] else: raise NotImplementedError('Spill required here!') @@ -166,6 +176,7 @@ # Remove coalesced moves: for mv in self.coalescedMoves: self.f.instructions.remove(mv) + # Use allocated registers: lookup = lambda t: self.color[self.Node(t)] for i in self.f.instructions: @@ -173,7 +184,7 @@ i.dst = tuple(map(lookup, i.dst)) def allocFrame(self, f): - """ Do register allocation for a single stack frame. """ + """ Do iterated register allocation for a single stack frame. """ self.InitData(f) self.Build() self.makeWorkList() diff -r 9fca39eebe50 -r 2ccd57b1d78c python/st-util.py --- a/python/st-util.py Sun Sep 29 14:08:15 2013 +0200 +++ b/python/st-util.py Sat Oct 12 09:56:23 2013 +0200 @@ -19,34 +19,46 @@ fl.addRow('Status:', QLabel(parent.stl.StatusString)) class RegisterModel(QAbstractTableModel): - def __init__(self): + def __init__(self): super().__init__() self.regCount = 15 self.device = None - def rowCount(self, parent): + + def rowCount(self, parent): if parent.isValid(): return 0 if self.device: return 21 # TODO make variable else: return 0 - def setDevice(self, dev): + + def setDevice(self, dev): self.device = dev self.modelReset.emit() - def columnCount(self, parent): + + def columnCount(self, parent): if parent.isValid(): return 0 return 2 - def data(self, index, role): + + def data(self, index, role): if index.isValid(): row, col = index.row(), index.column() if role == Qt.DisplayRole: if col == 0: - return 'R{0}'.format(row) + if row == 15: + return 'PC' + elif row == 14: + return 'LR' + elif row == 13: + return 'SP' + else: + return 'R{0}'.format(row) elif col == 1: v = self.device.iface.read_reg(row) return '0x{0:X}'.format(v) - def setData(self, index, value, role): + + def setData(self, index, value, role): if index.isValid(): row = index.row() col = index.column() @@ -55,14 +67,16 @@ self.device.iface.write_reg(row, value) return True return False - def flags(self, index): + + def flags(self, index): if index.isValid(): row = index.row() col = index.column() if col == 1: return super().flags(index) | Qt.ItemIsEditable return super().flags(index) - def refresh(self): + + def refresh(self): if self.device: fromIndex = self.index(0, 1) toIndex = self.index(21, 1) @@ -70,15 +84,17 @@ class RegisterView(QTableView): - def __init__(self): + def __init__(self): super().__init__() self.mdl = RegisterModel() self.setModel(self.mdl) - def refresh(self): + + def refresh(self): if self.mdl.device: self.setEnabled(not self.mdl.device.Running) self.mdl.refresh() + class MemoryView(QWidget): BlockSize = 0x100 def __init__(self): diff -r 9fca39eebe50 -r 2ccd57b1d78c python/tcodegen.py --- a/python/tcodegen.py Sun Sep 29 14:08:15 2013 +0200 +++ b/python/tcodegen.py Sat Oct 12 09:56:23 2013 +0200 @@ -82,6 +82,10 @@ function int ab(int a, int b) { var int c; + var int *a2; + a2 = cast(2); + *a2 = 2; + *a2 = *a2 + 2; c = 0; c = c + a + b; return c; @@ -127,16 +131,11 @@ cga = codegenarm.ArmCodeGenerator(outs) ir2 = cga.generate(irc) - #with open('cfg.gv', 'w') as cfg_file: - # dump_cfg(cga, cfg_file) + with open('cfg.gv', 'w') as cfg_file: + dump_cfg(cga, cfg_file) - #with open('ig.gv', 'w') as ig_file: - # dump_ig(cga, ig_file) + with open('ig.gv', 'w') as ig_file: + dump_ig(cga, ig_file) - #for f in ir2: - # print(f) - # for i in f.instructions: - # print(' {}'.format(i)) - outs.dump() diff -r 9fca39eebe50 -r 2ccd57b1d78c python/testgraph.py --- a/python/testgraph.py Sun Sep 29 14:08:15 2013 +0200 +++ b/python/testgraph.py Sat Oct 12 09:56:23 2013 +0200 @@ -2,8 +2,14 @@ import unittest import graph +import interferencegraph +import flowgraph +import ir +import irmach + class GraphTestCase(unittest.TestCase): + def testEdge(self): g = graph.Graph() n1 = graph.Node(g) @@ -31,10 +37,48 @@ g.delNode(n2) self.assertEqual(1, n1.Degree) + class DigraphTestCase(unittest.TestCase): pass +class InterferenceGraphTestCase(unittest.TestCase): + def testNormalUse(self): + t1 = ir.Temp('t1') + t2 = ir.Temp('t2') + t3 = ir.Temp('t3') + t4 = ir.Temp('t4') + t5 = ir.Temp('t5') + t6 = ir.Temp('t6') + instrs = [] + instrs.append(irmach.makeIns('ld %d', dst=[t1])) + instrs.append(irmach.makeIns('ld %d', dst=[t2])) + instrs.append(irmach.makeIns('ld %d', dst=[t3])) + cfg = flowgraph.FlowGraph(instrs) + ig = interferencegraph.InterferenceGraph(cfg) + + def testCombine(self): + t1 = ir.Temp('t1') + t2 = ir.Temp('t2') + t3 = ir.Temp('t3') + t4 = ir.Temp('t4') + instrs = [] + instrs.append(irmach.makeIns('ld %d0', dst=[t1])) + instrs.append(irmach.makeIns('ld %d0', dst=[t2])) + instrs.append(irmach.makeIns('ld %d0', dst=[t3])) + instrs.append(irmach.makeIns('mov %d0, %s0', dst=[t4], src=[t3])) + instrs.append(irmach.makeIns('st %s0', src=[t4])) + instrs.append(irmach.makeIns('st %s0', src=[t1])) + instrs.append(irmach.makeIns('st %s0', src=[t2])) + cfg = flowgraph.FlowGraph(instrs) + ig = interferencegraph.InterferenceGraph(cfg) + ig.to_txt() + ig.Combine(ig.getNode(t4), ig.getNode(t3)) + self.assertIs(ig.getNode(t4), ig.getNode(t3)) + print('after') + ig.to_txt() + + if __name__ == '__main__': unittest.main() diff -r 9fca39eebe50 -r 2ccd57b1d78c python/testir.py --- a/python/testir.py Sun Sep 29 14:08:15 2013 +0200 +++ b/python/testir.py Sat Oct 12 09:56:23 2013 +0200 @@ -66,7 +66,7 @@ v2 = ir.Const(7) v3 = ir.Add(v1, v2) self.b.emit(ir.Jump(f.epiloog)) - #self.cf.run(self.m) + self.cf.run(self.m) def testAdd0(self): f = self.b.newFunction('test') diff -r 9fca39eebe50 -r 2ccd57b1d78c python/testregalloc.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/python/testregalloc.py Sat Oct 12 09:56:23 2013 +0200 @@ -0,0 +1,63 @@ +import unittest +import os +import sys +import irmach +import registerallocator +import ir + + +class RegAllocTestCase(unittest.TestCase): + def setUp(self): + self.ra = registerallocator.RegisterAllocator() + + def testRegAlloc(self): + f = irmach.Frame('tst') + f.regs = [1,2,3,4,5,6] # for test use numbers! + f.tempMap = {} + t1 = ir.Temp('t1') + t2 = ir.Temp('t2') + t3 = ir.Temp('t3') + t4 = ir.Temp('t4') + t5 = ir.Temp('t5') + f.instructions.append(irmach.makeIns('ld %d0', dst=[t1])) + f.instructions.append(irmach.makeIns('ld %d0', dst=[t2])) + f.instructions.append(irmach.makeIns('ld %d0', dst=[t3])) + f.instructions.append(irmach.makeIns('add %d0, %s0, %s1', dst=[t4], src=[t1, t2])) + f.instructions.append(irmach.makeIns('add %d0, %s0, %s1', dst=[t5], src=[t4, t3])) + f.instructions.append(irmach.makeIns('st %s0', src=[t5])) + self.ra.allocFrame(f) + self.conflict(t1, t2) + self.conflict(t2, t3) + + def conflict(self, ta, tb): + self.assertNotEqual(self.ra.Node(ta).color, self.ra.Node(tb).color) + + def testRegCoalesc(self): + f = irmach.Frame('tst') + f.regs = [1,2,3,4,5,6] # for test use numbers! + f.tempMap = {} + t1 = ir.Temp('t1') + t2 = ir.Temp('t2') + t3 = ir.Temp('t3') + t4 = ir.Temp('t4') + t5 = ir.Temp('t5') + t6 = ir.Temp('t6') + f.instructions.append(irmach.makeIns('ld %d0', dst=[t1])) + f.instructions.append(irmach.makeIns('ld %d0', dst=[t2])) + f.instructions.append(irmach.makeIns('ld %d0', dst=[t3])) + f.instructions.append(irmach.makeIns('lsl %s0, %s1', dst=[t4], src=[t2, t1])) + f.instructions.append(irmach.makeIns('mov %d0, %s0', dst=[t5], src=[t3])) + f.instructions.append(irmach.makeIns('orr %s0, %s1', dst=[t5], src=[t4, t5])) + f.instructions.append(irmach.makeIns('mov %d0, %s0', dst=[t6], src=[t5])) + f.instructions.append(irmach.makeIns('st %s0', src=[t6])) + self.ra.allocFrame(f) + f.ig.to_txt() + for i in f.instructions: + print(i) + self.conflict(t1, t2) + self.conflict(t2, t3) + self.conflict(t1, t3) + +if __name__ == '__main__': + unittest.main() + diff -r 9fca39eebe50 -r 2ccd57b1d78c python/transform.py --- a/python/transform.py Sun Sep 29 14:08:15 2013 +0200 +++ b/python/transform.py Sat Oct 12 09:56:23 2013 +0200 @@ -3,7 +3,7 @@ """ import logging -from ir import * +import ir # Standard passes: class FunctionPass: @@ -46,34 +46,29 @@ """ Override this virtual method """ raise NotImplementedError() -# Usefull transforms: -class ConstantFolder(BasicBlockPass): +class BasePass(BasicBlockPass): def onBasicBlock(self, bb): - constMap = {} - ins = [i for i in bb.Instructions if type(i) in [ImmLoad, BinaryOperator]] - for i in ins: - if type(i) is ImmLoad: - constMap[i.target] = i.value - elif type(i) is BinaryOperator: - if i.value1 in constMap and i.value2 in constMap and i.operation in ['+', '-', '*', '<<']: - op = i.operation - va = constMap[i.value1] - vb = constMap[i.value2] - if op == '+': - vr = va + vb - elif op == '*': - vr = va * vb - elif op == '-': - vr = va - vb - elif op == '<<': - vr = va << vb - else: - raise NotImplementedError() - constMap[i.result] = vr - i.removeDef(i.result) - i2 = ImmLoad(i.result, vr) - logging.debug('Replacing {} with {}'.format(i, i2)) - i.Parent.replaceInstruction(i, i2) + pass + +# Usefull transforms: +class ConstantFolder(BasePass): + def __init__(self): + super().__init__() + self.ops = {} + self.ops['+'] = lambda x, y: x + y + self.ops['-'] = lambda x, y: x - y + self.ops['*'] = lambda x, y: x * y + self.ops['<<'] = lambda x, y: x << y + + def postExpr(self, expr): + if type(i) is BinaryOperator and i.operation in self.ops.keys() and type(i.a) is Const and type(i.b) is Const: + op = i.operation + va = i.a.value + vb = i.b.value + vr = self.ops[i.operation](va, vb) + return Const(vr) + else: + return expr class DeadCodeDeleter(BasicBlockPass): diff -r 9fca39eebe50 -r 2ccd57b1d78c python/trunner2.sh --- a/python/trunner2.sh Sun Sep 29 14:08:15 2013 +0200 +++ b/python/trunner2.sh Sat Oct 12 09:56:23 2013 +0200 @@ -5,9 +5,9 @@ python tcodegen.py # Create svg from dot file: - # dot -Tpdf -o ir.pdf ir.gv - #dot -Tpdf -o cfg.pdf cfg.gv - #dot -Tpdf -o ig.pdf ig.gv + #dot -Tpdf -o ir.pdf ir.gv + dot -Tpdf -o cfg.pdf cfg.gv + dot -Tpdf -o ig.pdf ig.gv echo "Awaiting changes in $DIR" inotifywait -r -e modify $DIR done