Mercurial > lcfOS
diff python/ppci/frontends/ks/irgenerator.py @ 110:9e552d34bd60
Work on compiler
author | Windel Bouwman |
---|---|
date | Fri, 04 Jan 2013 15:25:58 +0100 |
parents | 1544e7a4aa98 |
children |
line wrap: on
line diff
--- a/python/ppci/frontends/ks/irgenerator.py Tue Jan 01 17:17:44 2013 +0100 +++ b/python/ppci/frontends/ks/irgenerator.py Fri Jan 04 15:25:58 2013 +0100 @@ -5,106 +5,87 @@ from .nodes import * from ...core.errors import Error from ... import core -from .builtin import real, integer, boolean, char +from .builtin import real, integer, boolean, char, void + +def coreType(typ): + """ Return the correct core type given a type """ + if type(typ) is BaseType: + if typ is integer: + return core.i32 + if typ is void: + return core.void + elif type(typ) is ProcedureType: + rType = coreType(typ.returntype) + fpTypes = [coreType(p.typ) for p in typ.parameters] + return core.FunctionType(rType, fpTypes) + print(typ) + raise NotImplementedError() class KsIrGenerator: def __init__(self): - pass - + self.builder = core.IRBuilder() # 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 - """ + """ Generate code for expressions! """ if isinstance(node, Binop): """ Handle a binary operation (two arguments) of some kind """ - self.genexprcode(node.a) - self.genexprcode(node.b) + lhs = self.genexprcode(node.a) + rhs = 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.op == '*': if node.typ.isType(integer): - pass + return self.builder.createMul(lhs, rhs) elif node.op == '+': if node.typ.isType(integer): - pass + return self.builder.createAdd(lhs, rhs) 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) - code.append('Unop inttoreal TODO') - elif node.op == 'ABS': - if isType(node.typ, real): - 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)) + return self.builder.createSub(lhs, rhs) + Error('Unknown binop or type {0}'.format(node)) 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') + 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)) + print(node) + #Error('Cannot load variable type {0}'.format(node.typ)) elif type(node) is Constant: - print('TODO: constant') + return core.Constant(node.value, coreType(node.typ)) 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! + # Create module: + self.mod = core.Module(node.name) + globs = node.symtable.getAllLocal(Variable) + for g in globs: + print('global:', g) + # Loop over all functions: print(node.symtable) node.symtable.printTable() funcs = node.symtable.getAllLocal(Procedure) for f in funcs: - print('function', f) - ftype = f.typ.coreType() - ftype = core.FunctionType(retType) - - self.mod = core.Module(node.name) + self.gencode(f) # 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) + ftype = coreType(node.typ) + print('function', node, ftype) + func = core.Function(ftype, node.name, self.mod) + bb = core.BasicBlock() + func.basicblocks.append(bb) + self.builder.setInsertPoint(bb) + self.gencode(node.block) + self.builder.setInsertPoint(None) + variables = node.symtable.getAllLocal(Variable) + print(variables) elif isinstance(node, StatementSequence): for s in node.statements: @@ -112,25 +93,17 @@ 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') + print("TODO") 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") + print('assign') + rhs = self.genexprcode(node.rval) # Calculate the value that has to be stored. + #self.gencode(node.lval) + print("TODO: assigment") + 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) @@ -152,54 +125,14 @@ 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 + pass # That was easy :) 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') + Error('Can only gencode for designator with selectors') else: print('not generating code for {0}'.format(node))