Mercurial > lcfOS
changeset 173:c1d2b6b9f9a7
Rework into passes
author | Windel Bouwman |
---|---|
date | Fri, 19 Apr 2013 12:42:21 +0200 |
parents | 5a7d37d615ee |
children | 3eb06f5fb987 |
files | python/ir/basicblock.py python/ir/function.py python/ir/instruction.py python/ir/module.py python/registerallocator.py python/st-util.py python/testir.py python/transform.py python/x86.py |
diffstat | 9 files changed, 153 insertions(+), 89 deletions(-) [+] |
line wrap: on
line diff
--- a/python/ir/basicblock.py Thu Apr 04 17:58:37 2013 +0200 +++ b/python/ir/basicblock.py Fri Apr 19 12:42:21 2013 +0200 @@ -5,9 +5,19 @@ self.name = name self.instructions = [] def __repr__(self): - return 'BB {0}'.format(self.name) - def addIns(self, i): + return 'BasicBlock {0}'.format(self.name) + def addInstruction(self, i): + i.parent = self self.instructions.append(i) + addIns = addInstruction + def replaceInstruction(self, i1, i2): + idx = self.instructions.index(i1) + i1.parent = None + i2.parent = self + self.instructions[idx] = i2 + def removeInstruction(self, i): + i.parent = None + self.instructions.remove(i) def getInstructions(self): return self.instructions Instructions = property(getInstructions) @@ -18,6 +28,13 @@ def Empty(self): return len(self.instructions) == 0 @property - def FirstIns(self): + def FirstInstruction(self): return self.instructions[0] + FirstIns = FirstInstruction + def getSuccessors(self): + if not self.Empty: + i = self.LastIns + return i.Targets + return [] + Successors = property(getSuccessors)
--- a/python/ir/function.py Thu Apr 04 17:58:37 2013 +0200 +++ b/python/ir/function.py Fri Apr 19 12:42:21 2013 +0200 @@ -6,7 +6,7 @@ self.bbs = [] self.entry = None def __repr__(self): - return 'FUNC {0}, entry:{1}'.format(self.name, self.entry) + return 'Function {0}'.format(self.name) def addBB(self, bb): self.bbs.append(bb) def getBBs(self):
--- a/python/ir/instruction.py Thu Apr 04 17:58:37 2013 +0200 +++ b/python/ir/instruction.py Fri Apr 19 12:42:21 2013 +0200 @@ -17,16 +17,18 @@ class Instruction: """ Base class for all instructions. """ def __init__(self): - # successors: - self.succ = set() - # predecessors: - self.pred = set() # live variables at this node: self.live_in = set() self.live_out = set() # What variables this instruction uses and defines: self.defs = set() self.uses = set() + def getParent(self): + return self.parent + Parent = property(getParent) + @property + def Targets(self): + return self.getTargets() # Function calling: class Call(Instruction): @@ -40,6 +42,8 @@ class Return(Instruction): def __repr__(self): return 'RET' + def getTargets(self): + return [] class ImmLoad(Instruction): def __init__(self, target, value): @@ -93,6 +97,8 @@ self.target = target def __repr__(self): return 'BRANCH {0}'.format(self.target) + def getTargets(self): + return [self.target] class ConditionalBranch(Instruction): def __init__(self, a, cond, b, lab1, lab2): @@ -110,6 +116,8 @@ self.lab2 = lab2 def __repr__(self): return 'IF {0} {1} {2} THEN {3} ELSE {4}'.format(self.a, self.cond, self.b, self.lab1, self.lab2) + def getTargets(self): + return [self.lab1, self.lab2] class PhiNode(Instruction): def __init__(self):
--- a/python/ir/module.py Thu Apr 04 17:58:37 2013 +0200 +++ b/python/ir/module.py Fri Apr 19 12:42:21 2013 +0200 @@ -37,10 +37,15 @@ print('END') def dumpgv(self, outf): outf.write('digraph G \n{\n') - for i in self.Instructions: - outf.write('{0} [label="{1}"];\n'.format(id(i), i)) - for succ in i.succ: - outf.write('"{0}" -> "{1}" [label="{2}"];\n'.format(id(i), id(succ), succ.live_in)) + for f in self.Functions: + outf.write('{0} [label="{1}"]\n'.format(id(f), f)) + for bb in f.BasicBlocks: + contents = str(bb) + '\n' + contents += '\n'.join([str(i) for i in bb.Instructions]) + outf.write('{0} [label="{1}"];\n'.format(id(bb), contents)) + for successor in bb.Successors: + outf.write('"{0}" -> "{1}"\n'.format(id(bb), id(successor))) + outf.write('"{0}" -> "{1}" [label="entry"]\n'.format(id(f), id(f.entry))) outf.write('}\n') # Analysis functions: @@ -51,73 +56,4 @@ assert type(t) is Value, "def must be Value, not {0}".format(type(t)) for t in i.uses: assert type(t) is Value, "use must be Value, not {0}".format(type(t)) - def analyze(self): - # Determine pred and succ: - def link(a, b): - a.succ.add(b) - b.pred.add(a) - for bb in self.BasicBlocks: - if not bb.Empty: - if len(bb.Instructions) > 1: - for i1, i2 in zip(bb.Instructions[:-1], bb.Instructions[1:]): - link(i1, i2) - else: - print('Only 1 long!', bb, bb.Instructions) - if type(bb.LastIns) is ConditionalBranch: - link(bb.LastIns, bb.LastIns.lab1.FirstIns) - link(bb.LastIns, bb.LastIns.lab2.FirstIns) - if type(bb.LastIns) is Branch: - link(bb.LastIns, bb.LastIns.target.FirstIns) - else: - print('Empty!', bb) - # We now have cfg - # Determine liveness: - for i in self.Instructions: - i.live_in = set() - i.live_out = set() - for z in range(50): - # TODO iterate until converge - for i in self.Instructions: - lo_mk = i.live_out.difference(i.defs) - i.live_in = i.uses.union(lo_mk) - lo = set() - for s in i.succ: - lo = lo.union(s.live_in) - i.live_out = lo - def constantProp(self): - """ Constant propagation. Pre-calculate constant values """ - for i in self.Instructions: - if type(i) is ImmLoad: - i.target.constval = i.value - elif type(i) is BinaryOperator: - a = i.value1 - b = i.value2 - if i.value1.constval and i.value2.constval: - op = i.operation - if op == '+': - i.result.constval = a + b - else: - raise NotImplementedError(op) - else: - i.result.constval = None - - def registerAllocate(self, regs): - print(regs) - allVals = [] - # construct interference: - for i in self.Instructions: - for v in i.live_in: - allVals.append(v) - for v2 in i.live_in: - if v != v2: - v.interferes.add(v2) - # assign random registers: - print(allVals) - regs = set(regs) - for v in allVals: - takenregs = set([iv.reg for iv in v.interferes]) - r2 = list(regs.difference(takenregs)) - # Pick next available: - v.reg = r2[0] -
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/python/registerallocator.py Fri Apr 19 12:42:21 2013 +0200 @@ -0,0 +1,35 @@ + +class RegisterAllocator: + def live_analyze(self): + # Determine liveness: + for i in self.Instructions: + i.live_in = set() + i.live_out = set() + for z in range(50): + # TODO iterate until converge + for i in self.Instructions: + lo_mk = i.live_out.difference(i.defs) + i.live_in = i.uses.union(lo_mk) + lo = set() + for s in i.succ: + lo = lo.union(s.live_in) + i.live_out = lo + def registerAllocate(self, ir, regs): + print(regs) + allVals = [] + # construct interference: + for i in ir.Instructions: + for v in i.live_in: + allVals.append(v) + for v2 in i.live_in: + if v != v2: + v.interferes.add(v2) + # assign random registers: + print(allVals) + regs = set(regs) + for v in allVals: + takenregs = set([iv.reg for iv in v.interferes]) + r2 = list(regs.difference(takenregs)) + # Pick next available: + v.reg = r2[0] +
--- a/python/st-util.py Thu Apr 04 17:58:37 2013 +0200 +++ b/python/st-util.py Fri Apr 19 12:42:21 2013 +0200 @@ -3,7 +3,7 @@ import sys from PyQt4.QtCore import * from PyQt4.QtGui import * -import stlink, devices, stm32 +import stlink, devices, stm32, usb from devices import Interface, Device from hexedit import HexEdit @@ -255,9 +255,13 @@ ip = idx.internalPointer() if isinstance(ip, Interface): if not ip.IsOpen: - ip.open() - # Try to get a device: - self.mdl.addDevice(ip.createDevice()) + try: + ip.open() + except usb.UsbError as e: + QMessageBox.critical(self, "Error", 'Error opening interface: "{0}"'.format(e)) + else: + # Try to get a device: + self.mdl.addDevice(ip.createDevice()) if isinstance(ip, Device): self.deviceSelected.emit(ip) def openMenu(self, pt):
--- a/python/testir.py Thu Apr 04 17:58:37 2013 +0200 +++ b/python/testir.py Fri Apr 19 12:42:21 2013 +0200 @@ -1,4 +1,4 @@ -import c3, ppci, ir, x86 +import c3, ppci, ir, x86, transform import os testsrc = """ @@ -39,9 +39,13 @@ cgenx86 = x86.X86CodeGen(diag) ir = builder.build(testsrc) diag.printErrors(testsrc) + #ir.dump() + cf = transform.ConstantFolder() + dcd = transform.DeadCodeDeleter() ir.check() - ir.analyze() - #ir.constantProp() + cf.run(ir) + cf.run(ir) + #dcd.run(ir) ir.dump() asm = cgenx86.genBin(ir) for a in asm:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/python/transform.py Fri Apr 19 12:42:21 2013 +0200 @@ -0,0 +1,58 @@ +from ir import * +# Standard passes: + +class FunctionPass: + def run(self, ir): + """ Main entry point for the pass """ + for f in ir.Functions: + self.onFunction(f) + def onFunction(self, f): + """ Override this virtual method """ + raise NotImplementedError() + +class BasicBlockPass(FunctionPass): + def onFunction(self, f): + for bb in f.BasicBlocks: + self.onBasicBlock(bb) + def onBasicBlock(self, bb): + """ Override this virtual method """ + raise NotImplementedError() + +class InstructionPass(BasicBlockPass): + def onBasicBlock(self, bb): + for ins in bb.Instructions: + self.onInstruction(ins) + def onInstruction(self, ins): + """ Override this virtual method """ + raise NotImplementedError() + +# Usefull transforms: +class ConstantFolder(InstructionPass): + def onInstruction(self, i): + if type(i) is ImmLoad: + i.target.constval = i.value + print(type(i.value), i.value) + elif type(i) is BinaryOperator: + a = i.value1 + b = i.value2 + if hasattr(a, 'constval') and hasattr(b,'constval'): + op = i.operation + if op == '+': + i2 = ImmLoad(i.result, a.constval + b.constval) + print(i2) + i.Parent.replaceInstruction(i, i2) + elif op == '*': + i2 = ImmLoad(i.result, a.constval * b.constval) + print(i2) + i.Parent.replaceInstruction(i, i2) + elif op == '-': + i2 = ImmLoad(i.result, a.constval - b.constval) + print(i2) + i.Parent.replaceInstruction(i, i2) + +class DeadCodeDeleter(InstructionPass): + def onInstruction(self, ins): + print(ins, ins.Users) + if not ins.defs in ins.live_out: + ins.Parent.removeInstruction(ins) +
--- a/python/x86.py Thu Apr 04 17:58:37 2013 +0200 +++ b/python/x86.py Fri Apr 19 12:42:21 2013 +0200 @@ -1,5 +1,6 @@ import ppci import ir +import registerallocator class AsmLabel: def __init__(self, lab): @@ -33,7 +34,8 @@ def genBin(self, ir): self.asm = [] # Allocate registers: - ir.registerAllocate(self.regs) + ra = registerallocator.RegisterAllocator() + ra.registerAllocate(ir, self.regs) self.genModule(ir) return self.asm