Mercurial > lcfOS
view python/ir/module.py @ 274:ea93e0a7a31e
Move docs
author | Windel Bouwman |
---|---|
date | Wed, 04 Sep 2013 17:35:06 +0200 |
parents | e64bae57cda8 |
children | 6f2423df0675 |
line wrap: on
line source
# IR-Structures: def dumpgv(m, outf): print('digraph G ', file=outf) print('{', file=outf) for f in m.Functions: print('{} [label="{}" shape=box3d]'.format(id(f), f),file=outf) for bb in f.Blocks: contents = str(bb) + '\n' contents += '\n'.join([str(i) for i in bb.Instructions]) outf.write('{0} [shape=note label="{1}"];\n'.format(id(bb), contents)) for successor in bb.Successors: print('"{}" -> "{}"\n'.format(id(bb), id(successor)), file=outf) outf.write('"{}" -> "{}" [label="entry"]\n'.format(id(f), id(f.entry))) print('}', file=outf) class Module: """ Main container of variables and functions. """ def __init__(self, name): self.name = name self.funcs = [] self.variables = [] def __repr__(self): return 'IR-module [{0}]'.format(self.name) def addFunc(self, f): self.funcs.append(f) addFunction = addFunc def addVariable(self, v): self.variables.append(v) def getVariables(self): return self.variables Variables = property(getVariables) def getFunctions(self): return self.funcs Functions = property(getFunctions) def findFunction(self, name): for f in self.funcs: if f.name == name: return f raise KeyError(name) getFunction = findFunction def dump(self): print(self) indent = ' ' for v in self.Variables: print(indent, v) for fn in self.Functions: print(fn) for bb in fn.Blocks: print(indent+str(bb)) for ins in bb.Instructions: print(indent * 2 + str(ins)) # Analysis functions: def check(self): """ Perform sanity check on module """ for f in self.Functions: f.check() class Function: """ Function definition. Contains an entry block. """ def __init__(self, name): self.name = name self.entry = Block('{}_entry'.format(name)) self.epiloog = Block('{}_epilog'.format(name)) self.epiloog.addInstruction(Terminator()) self.arguments = [] def __repr__(self): args = ','.join(str(a) for a in self.arguments) return 'Function {}({})'.format(self.name, args) def addBB(self, bb): self.bbs.append(bb) bb.parent = self addBlock = addBB def removeBasicBlock(self, bb): self.bbs.remove(bb) bb.parent = None def getBBs(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(getBBs) @property def Entry(self): return self.entry def check(self): for b in self.Blocks: b.check() def addParameter(self, pname): self.arguments.append(pname) def call(self, *args): varmap = {} bb = self.Entry ip = 0 while True: i = bb.Instructions[ip] ip += 1 return class Block: """ Uninterrupted sequence of instructions with a label at the start. """ def __init__(self, name): self.name = name self.instructions = [] def __repr__(self): return 'Block {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) def getInstructions(self): return self.instructions Instructions = property(getInstructions) def getLastIns(self): if not self.Empty: return self.instructions[-1] LastInstruction = property(getLastIns) @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.BasicBlocks: if self in bb.Successors: preds.append(bb) return preds Predecessors = property(getPredecessors) def precedes(self, other): raise NotImplementedError() def check(self): assert isinstance(self.LastInstruction, LastStatement) for i in self.instructions[:-1]: assert not isinstance(i, LastStatement) # Instructions: class Expression: pass class Const(Expression): def __init__(self, value): self.value = value def __repr__(self): return 'Constant {}'.format(self.value) # Function calling: class Call(Expression): def __init__(self, f, arguments): self.f = f assert type(f) is Function self.arguments = arguments def __repr__(self): args = ','.join([str(arg) for arg in self.arguments]) return '{}({})'.format(self.f.name, args) # Data operations class Binop(Expression): ops = ['+', '-', '*', '/', '|', '&', '<<', '>>'] def __init__(self, value1, operation, value2): assert operation in Binop.ops self.value1 = value1 self.value2 = value2 self.operation = operation def __repr__(self): a, b = self.value1, self.value2 return '({} {} {})'.format(a, self.operation, b) def Add(a, b): """ Convenience call """ return Binop(a, '+', b) 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): pass class GlobalVariable(Variable): pass 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 'T_{}_'.format(self.name) class Mem(Expression): def __init__(self, e): self.e = e def __repr__(self): return '[{}]'.format(self.e) class Statement: """ Base class for all instructions. """ pass class Move(Statement): 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 class Label(Statement): def __init__(self, name): self.name = name self.statements = [] def __repr__(self): return 'LABEL {}:'.format(self.name) # Branching: class LastStatement(Statement): pass class Terminator(LastStatement): """ Instruction that terminates the terminal block """ Targets = [] def __repr__(self): return 'Terminator' class Jump(LastStatement): def __init__(self, target): self.target = target self.Targets = [target] def __repr__(self): return 'BRANCH {}'.format(self.target.name) class CJump(LastStatement): def __init__(self, a, cond, b, lab_yes, lab_no): assert cond in ['==', '<', '>', '>=', '<=', '!='] self.a = a self.cond = cond self.b = b self.lab_yes = lab_yes self.lab_no = lab_no self.Targets = [lab_yes, lab_no] def __repr__(self): return 'IF {} {} {} THEN {} ELSE {}'.format(self.a, self.cond, self.b, self.lab_yes, self.lab_no)