Mercurial > lcfOS
view python/ppci/frontends/ks/irgenerator.py @ 104:ed230e947dc6
Added hexviewer
author | windel |
---|---|
date | Sun, 30 Dec 2012 22:31:55 +0100 |
parents | 28a35161ef23 |
children | f2d980eef509 |
line wrap: on
line source
""" Generates ir code from ast tree. """ from .nodes import * from ...core.errors import Error from ... import core from .builtin import real, integer, boolean, char class KsIrGenerator: def __init__(self): pass # Code generation functions: def genexprcode(self, node): """ Generate code for expressions! Recursively evaluates, and ensures a register contains the answer. register is an integer register or a floating point reg """ if isinstance(node, Binop): """ Handle a binary operation (two arguments) of some kind """ self.genexprcode(node.a) self.genexprcode(node.b) if node.op == 'mod': assert(node.typ.isType(integer)) elif node.op == 'div': assert(node.typ.isType(integer)) elif node.op == '*': if node.typ.isType(integer): pass elif node.op == '+': if node.typ.isType(integer): pass elif node.op == '-': if node.typ.isType(integer): pass else: Error('Unknown Binop {0}'.format(node.op)) elif type(node) is Unop: if node.op == 'INTTOREAL': self.genexprcode(node.a) node.reg = node.a.reg # TODO use 'FILD' instruction freg = 12 code.append('Unop inttoreal TODO') elif node.op == 'ABS': if isType(node.typ, real): code = [0xD9, 0xE1] # st(0) = fabs st(0) Error('ABS error integer') elif isType(node.typ, integer): code = [] Error('ABS error integer') else: Error('ABS error') else: Error('Unknown Unop {0}'.format(node.op)) elif isinstance(node, Designator): # dereference, array index. Make sure that the result comes into a register if len(node.selectors) > 0: self.gencode(node) # Load the pointer into some register # Now we can access the object at location '[node.reg]': if node.typ.isType(integer): self.addCode( mov(node.reg, [node.reg, 0x0]) ) else: Error('Only integer types implemented') else: # No selectors, load variable directly if node.obj.typ.isType(integer): if type(node.obj) is Constant: self.genexprcode(node.obj) node.reg = node.obj.reg else: pass # Get a register to store the integer value else: Error('Cannot load variable type {0}'.format(node.typ)) elif isinstance(node, Relop): # Create a boolean from operands # TODO create an alternative for expressions used as conditions. self.genexprcode(node.a) self.genexprcode(node.b) if node.a.typ.isType(integer): self.freereg(node.b) else: Error('Relop not implemented for {0}'.format(node.a.typ)) elif type(node) is Constant: print('TODO: constant') elif type(node) is ProcedureCall: Error('TODO: proc call') else: Error('Cannot generate expression code for: {0}'.format(node)) def gencode(self, node): """ Code generation function for AST nodes """ if isinstance(node, Module): # TODO: recurse! self.mod = core.Module() # Create a function called init for this module: ftype = core.FunctionType(self.context.VoidType, []) func = core.Function(ftype, "init", self.mod) bb = self.gencode(node.initcode) self.mod.dump() return self.mod elif type(node) is Procedure: # calculate offsets for local variables and parameters # Variable location relative to 'rbp' register variables = node.symtable.getAllLocal(Variable) elif isinstance(node, StatementSequence): for s in node.statements: self.gencode(s) elif type(node) is ProcedureCall: # Prepare parameters on the stack: assert(len(node.args) == len(node.proc.typ.parameters)) for arg, param in zip(node.args, node.proc.typ.parameters): if param.kind == 'value': self.genexprcode(arg) self.addCode( push(arg.reg) ) self.freereg( arg ) stacksize += 8 else: Error('Parameter kind other than value') elif type(node) is Assignment: if node.lval.typ.isType(integer): # TODO if node.rval is Constant of some datatype, move it to mem directly self.genexprcode(node.rval) # Calculate the value that has to be stored. print("TODO") else: Error('Assignments of other types not implemented') # TODO if left and right are designators, do some sort of memcpy. elif type(node) is IfStatement: self.genexprcode(node.condition) print("TODO IF") if node.falsestatement: # If with else clause pass else: # If without else clause pass elif isinstance(node, WhileStatement): self.genexprcode(node.condition) self.gencode(node.dostatements) elif type(node) is ForStatement: # Initial load of iterator variable: self.genexprcode(node.begin) self.genexprcode(node.end) self.gencode(node.statements) Error('No implementation of FOR statement') elif type(node) is AsmCode: def processOperand(op): if type(op) is list: if type(op[0]) is Variable: var = op[0] if var.isLocal: return ['rbp', var.offset] else: Error('Can only use local variables in inline assembler') return op for asmline in node.asmcode: opcode, operands = asmline operands = [processOperand(opx) for opx in operands] print('assembling', opcode, *operands) func,nargs = opcodes[opcode] code = func(*operands) self.addCode(code) elif isinstance(node, EmptyStatement): pass elif type(node) is StringConstant: self.strings.append(node) self.data.append(node.value) # Add string to the data section elif type(node) is Designator: if len(node.selectors) > 0: self.getreg(node) # Load starting address if node.obj.isLocal: self.addCode( leareg64(node.reg, ['rbp', node.obj.offset]) ) else: # Global variables need to be relocated... self.addCode(leareg64(node.reg, ['RIP', 0])) self.fixCode(self.rip - 4, imm32(node.obj.offset - self.rip)) # Loop over all designators.. for selector in node.selectors: if type(selector) is Index: # Deref an array index self.genexprcode(selector.index) self.freereg(selector) elif type(selector) is Field: print('Field') Error('Field not implemented') else: Error('Unknown selector') else: Error('Can only gencode for designator with selectors') else: print('not generating code for {0}'.format(node)) def generateIr(self, context, ast): """ ir generation front end """ # Create a new context for this code. self.context = context return self.gencode(ast)