Mercurial > lcfOS
view python/ir/instruction.py @ 239:63bb40758066
added check
author | Windel Bouwman |
---|---|
date | Mon, 22 Jul 2013 17:57:25 +0200 |
parents | 88a1e0baef65 |
children | c4370696ccc7 |
line wrap: on
line source
from .basicblock import BasicBlock from .function import Function class Value: """ Temporary SSA value (value that is assigned only once! """ def __init__(self, name): # TODO: add typing? for now only handle integers self.name = name self.used_by = [] self.Setter = None def __repr__(self): return '{0}'.format(self.name) # + str(self.IsUsed) @property def IsUsed(self): return len(self.used_by) > 0 def onlyUsedInBlock(self, bb): for use in self.used_by: ins = use if ins.parent != bb: return False return True class Variable(Value): pass class Use: def __init__(self, user, val): self.user = user assert isinstance(val, Value) self.val = val self.val.used_by.append(self.user) def delete(self): self.val.used_by.remove(self.user) class Instruction: """ Base class for all instructions. """ def __init__(self): # live variables at this node: self.live_in = set() self.live_out = set() # What variables this instruction uses and defines: self.defs = [] self.uses = [] def delete(self): while self.uses: use = self.uses.pop() use.delete() while self.defs: d = self.defs.pop() d.Setter = None def addUse(self, val): self.uses.append(Use(self, val)) def removeUse(self, val): for u in self.uses: if u.val is val: theUse = u theUse.delete() self.uses.remove(theUse) def addDef(self, v): self.defs.append(v) assert v.Setter == None v.Setter = self def removeDef(self, v): assert v.Setter is self v.Setter = None self.defs.remove(v) def getParent(self): return self.parent def setParent(self, p): self.parent = p Parent = property(getParent, setParent) def replaceValue(self, old, new): raise NotImplementedError() @property def Position(self): return self.parent.Instructions.index(self) def check(self): # Check that the variables defined by this instruction # are only used in the same block for v in self.defs: assert v.Setter is self for ub in v.used_by: assert ub.parent == self.parent # Check that variables used are defined earlier: for u in self.uses: v = u.val assert self.Position > v.Setter.Position class Terminator(Instruction): @property def Targets(self): return self.getTargets() def changeTarget(self, tfrom, tto): pass # Function calling: class Call(Instruction): def __init__(self, callee, arguments, result=None): super().__init__() self.callee = callee assert type(callee) is Function self.arguments = arguments for arg in arguments: assert type(arg) is Value self.addUse(arg) self.result = result if result: assert type(result) is Value self.addDef(result) def __repr__(self): if self.result: pfx = '{0} = '.format(self.result) else: pfx = '' args = ','.join([str(arg) for arg in self.arguments]) return pfx + '{0}({1})'.format(self.callee.name, args) class Return(Terminator): def __init__(self, value=None): super().__init__() self.value = value if value: self.addUse(value) def __repr__(self): if self.value: return 'ret {0}'.format(self.value) else: return 'ret' def getTargets(self): return [] class Alloc(Instruction): """ Allocates space on the stack """ def __init__(self, value): super().__init__() assert isinstance(value, Value) self.value = value self.addDef(value) def __repr__(self): return '{0} = alloc'.format(self.value) class ImmLoad(Instruction): def __init__(self, target, value): super().__init__() assert type(target) is Value self.target = target self.value = value self.addDef(target) def __repr__(self): return '{} = {}'.format(self.target, self.value) # Data operations class BinaryOperator(Instruction): def __init__(self, result, operation, value1, value2): super().__init__() #print('operation is in binops:', operation in BinOps) # Check types of the two operands: assert type(value1) is Value, str(value1) + str(type(value1)) assert type(value2) is Value, value2 self.result = result self.addDef(result) self.value1 = value1 self.value2 = value2 self.addUse(value1) self.addUse(value2) self.operation = operation def __repr__(self): a, b = self.value1, self.value2 return '{} = {} {} {}'.format(self.result, a, self.operation, b) def replaceValue(self, old, new): if old is self.value1: self.value1 = new elif old is self.value2: self.value2 = new elif old is self.result: self.result = new else: raise Exception() self.removeUse(old) self.addUse(new) # Memory functions: class Load(Instruction): def __init__(self, location, value): super().__init__() assert type(value) is Value assert isinstance(location, Value), "Location must be a value" self.value = value self.addDef(value) self.location = location self.addUse(self.location) def __repr__(self): return '{} = [{}]'.format(self.value, self.location) class Store(Instruction): def __init__(self, location, value): super().__init__() assert type(value) is Value, value assert isinstance(location, Value), "Location must be a value" self.location = location self.value = value self.addUse(value) self.addUse(location) def __repr__(self): return '[{}] = {}'.format(self.location, self.value) # Branching: class Branch(Terminator): def __init__(self, target): super().__init__() assert type(target) is BasicBlock self.target = target def __repr__(self): return 'BRANCH {0}'.format(self.target) def getTargets(self): return [self.target] def changeTarget(self, tfrom, tto): assert tfrom is self.target self.target = tto class ConditionalBranch(Terminator): def __init__(self, a, cond, b, lab1, lab2): super().__init__() self.a = a assert type(a) is Value self.cond = cond assert cond in ['==', '<', '>'] self.b = b self.addUse(a) self.addUse(b) assert type(b) is Value assert type(lab1) is BasicBlock self.lab1 = lab1 assert type(lab2) is BasicBlock 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] def changeTarget(self, tfrom, tto): assert tfrom is self.lab1 or tfrom is self.lab2 if tfrom is self.lab1: self.lab1 = tto elif tfrom is self.lab2: self.lab2 = tto class PhiNode(Instruction): def __init__(self): super().__init__() self.incBB = [] def addIncoming(self, bb): self.incBB.append(bb)