Mercurial > lcfOS
view python/ir/instruction.py @ 192:6cd6260789a1
Added more tests for parser generator
author | Windel Bouwman |
---|---|
date | Sun, 26 May 2013 23:19:27 +0200 |
parents | 460db5669efa |
children | de3a68f677a5 |
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 = [] def __repr__(self): return '{0}'.format(self.name) # + str(self.IsUsed) @property def IsUsed(self): return len(self.used_by) > 0 class Use: def __init__(self, user, val): self.user = user 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): for use in self.uses: use.delete() self.uses.clear() def addUse(self, val): self.uses.append(Use(self, val)) def addDef(self, v): self.defs.append(v) def getParent(self): return self.parent def setParent(self, p): self.parent = p Parent = property(getParent, setParent) 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 'Return {0}'.format(self.value) else: return 'Return' def getTargets(self): return [] class Alloc(Instruction): """ Allocates space on the stack """ def __init__(self, value): super().__init__() 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__() self.target = target self.value = value self.addDef(target) def __repr__(self): return '{0} = {1}'.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: self.result = result self.addDef(result) self.value1 = value1 self.value2 = value2 self.addUse(value1) self.addUse(value2) self.operation = operation def __repr__(self): return '{0} = {2} {1} {3}'.format(self.result, self.operation, self.value1, self.value2) # Memory functions: class Load(Instruction): def __init__(self, location, value): super().__init__() assert type(value) is Value assert type(location) is Value, "Location must be a value" self.value = value self.addDef(value) self.location = location self.addUse(self.location) def __repr__(self): return '{1} = [{0}]'.format(self.location, self.value) class Store(Instruction): def __init__(self, location, value): super().__init__() assert type(value) is Value assert type(location) is Value, "Location must be a value" self.location = location self.value = value self.addUse(value) self.addUse(location) def __repr__(self): return '[{0}] = {1}'.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): if 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 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): if tfrom is self.lab1: self.lab1 = tto if 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)