Mercurial > lcfOS
view python/ppci/ir.py @ 373:fc1b89b09896
Added run test.py
author | Windel Bouwman |
---|---|
date | Fri, 21 Mar 2014 14:32:54 +0100 |
parents | c49459768aaa |
children | 9667d78ba79e |
line wrap: on
line source
""" Intermediate representation (IR) code classes. """ def label_name(dut): """ Function that returns the assembly code label name """ if isinstance(dut, Block): f = dut.function return label_name(f) + '_' + dut.name elif isinstance(dut, Function) or isinstance(dut, GlobalVariable): return label_name(dut.module) + '_' + dut.name elif isinstance(dut, Module): return dut.name else: raise NotImplementedError(str(dut)) class Module: """ Container unit for variables and functions. """ def __init__(self, name): self.name = name self.functions = [] self.variables = [] def __repr__(self): return 'module {0}'.format(self.name) def add_function(self, f): """ Add a function to this module """ self.functions.append(f) f.module = self def add_variable(self, v): assert type(v) is GlobalVariable self.variables.append(v) v.module = self def get_variables(self): return self.variables Variables = property(get_variables) def getFunctions(self): return self.functions Functions = property(getFunctions) def findFunction(self, name): for f in self.funcs: if f.name == name: return f raise KeyError(name) getFunction = findFunction class Function: """ Represents a function. """ def __init__(self, name, module=None): self.name = name self.entry = Block('entry') self.entry.function = self self.epiloog = Block('epilog') self.epiloog.function = self self.epiloog.addInstruction(Terminator()) self.return_value = Temp('{}_retval'.format(name)) self.arguments = [] self.localvars = [] if module: module.add_function(self) def __repr__(self): args = ','.join(str(a) for a in self.arguments) return 'function i32 {}({})'.format(self.name, args) def add_block(self, bb): #self.bbs.append(bb) bb.function = self def removeBlock(self, bb): #self.bbs.remove(bb) bb.function = None def getBlocks(self): bbs = [self.entry] worklist = [self.entry] while worklist: b = worklist.pop() for sb in b.Successors: if sb not in bbs: bbs.append(sb) worklist.append(sb) bbs.remove(self.entry) if self.epiloog in bbs: bbs.remove(self.epiloog) bbs.insert(0, self.entry) bbs.append(self.epiloog) return bbs def findBasicBlock(self, name): for bb in self.bbs: if bb.name == name: return bb raise KeyError(name) Blocks = property(getBlocks) @property def Entry(self): return self.entry def check(self): for b in self.Blocks: b.check() def addParameter(self, p): assert type(p) is Parameter p.num = len(self.arguments) self.arguments.append(p) def addLocal(self, l): assert type(l) is LocalVariable self.localvars.append(l) class Block: """ Uninterrupted sequence of instructions with a label at the start. """ def __init__(self, name, function=None): self.name = name self.function = function self.instructions = [] parent = property(lambda s: s.function) def __repr__(self): return '{0}:'.format(self.name) def addInstruction(self, i): i.parent = self assert not isinstance(self.LastInstruction, LastStatement) self.instructions.append(i) def replaceInstruction(self, i1, i2): idx = self.instructions.index(i1) i1.parent = None i1.delete() i2.parent = self self.instructions[idx] = i2 def removeInstruction(self, i): i.parent = None #i.delete() self.instructions.remove(i) @property def Instructions(self): return self.instructions @property def LastInstruction(self): if not self.Empty: return self.instructions[-1] @property def Empty(self): return len(self.instructions) == 0 @property def FirstInstruction(self): return self.instructions[0] def getSuccessors(self): if not self.Empty: return self.LastInstruction.Targets return [] Successors = property(getSuccessors) def getPredecessors(self): preds = [] for bb in self.parent.Blocks: if self in bb.Successors: preds.append(bb) return preds Predecessors = property(getPredecessors) def precedes(self, other): raise NotImplementedError() # Instructions: class Expression: """ Base class for an expression """ pass class Const(Expression): """ Represents a constant value """ def __init__(self, value): self.value = value def __repr__(self): return 'Const {}'.format(self.value) class Call(Expression): """ Call a function with some arguments """ def __init__(self, f, arguments): assert type(f) is str self.f = f self.arguments = arguments def __repr__(self): args = ', '.join(str(arg) for arg in self.arguments) return '{}({})'.format(self.f, args) # Data operations class Binop(Expression): """ Generic binary operation """ ops = ['+', '-', '*', '/', '|', '&', '<<', '>>'] def __init__(self, value1, operation, value2): assert operation in Binop.ops self.a = value1 self.b = value2 self.operation = operation def __repr__(self): a, b = self.a, self.b return '({} {} {})'.format(a, self.operation, b) def Add(a, b): """ Add a and b """ return Binop(a, '+', b) def Sub(a, b): """ Substract b from a """ return Binop(a, '-', b) def Mul(a, b): """ Multiply a by b """ return Binop(a, '*', b) def Div(a, b): """ Divide a in b pieces """ return Binop(a, '/', b) class Eseq(Expression): """ Sequence of instructions where the last is an expression """ def __init__(self, stmt, e): self.stmt = stmt self.e = e def __repr__(self): return '({}, {})'.format(self.stmt, self.e) class Alloc(Expression): """ Allocates space on the stack """ def __init__(self): super().__init__() def __repr__(self): return 'Alloc' class Variable(Expression): def __init__(self, name): self.name = name def __repr__(self): return 'Var {}'.format(self.name) class LocalVariable(Variable): def __repr__(self): return 'Local {}'.format(self.name) class GlobalVariable(Variable): def __repr__(self): return 'Global {}'.format(self.name) class Parameter(Variable): def __repr__(self): return 'Param {}'.format(self.name) class Temp(Expression): """ Temporary storage, same as register """ def __init__(self, name): self.name = name def __repr__(self): return 'TMP_{}'.format(self.name) class Mem(Expression): """ Memory access """ def __init__(self, e): self.e = e def __repr__(self): return '[{}]'.format(self.e) class Addr(Expression): """ Address of label """ def __init__(self, e): self.e = e def __repr__(self): return '&{}'.format(self.e) class Statement: """ Base class for all instructions. """ @property def IsTerminator(self): return isinstance(self, LastStatement) class Move(Statement): """ Move source to destination """ def __init__(self, dst, src): self.dst = dst self.src = src def __repr__(self): return '{} = {}'.format(self.dst, self.src) class Exp(Statement): def __init__(self, e): self.e = e def __repr__(self): return '{}'.format(self.e) # Branching: class LastStatement(Statement): def changeTarget(self, old, new): idx = self.Targets.index(old) self.Targets[idx] = new class Terminator(LastStatement): """ Instruction that terminates the terminal block """ def __init__(self): self.Targets = [] def __repr__(self): return 'Terminator' class Jump(LastStatement): """ Jump statement to some target location """ def __init__(self, target): self.Targets = [target] def setTarget(self, t): self.Targets[0] = t target = property(lambda s: s.Targets[0], setTarget) def __repr__(self): return 'JUMP {}'.format(self.target.name) class CJump(LastStatement): """ Conditional jump to true or false labels. """ conditions = ['==', '<', '>', '>=', '<=', '!='] def __init__(self, a, cond, b, lab_yes, lab_no): assert cond in CJump.conditions self.a = a self.cond = cond self.b = b self.Targets = [lab_yes, lab_no] lab_yes = property(lambda s: s.Targets[0]) lab_no = property(lambda s: s.Targets[1]) def __repr__(self): return 'IF {} {} {} THEN {} ELSE {}'\ .format(self.a, self.cond, self.b, self.lab_yes, self.lab_no)