Mercurial > lcfOS
diff python/c3/codegenerator.py @ 268:5ec7580976d9
Op naar tree-IR
author | Windel Bouwman |
---|---|
date | Wed, 14 Aug 2013 20:12:40 +0200 |
parents | 444b9df2ed99 |
children | 5f8c04a8d26b |
line wrap: on
line diff
--- a/python/c3/codegenerator.py Mon Aug 12 20:14:47 2013 +0200 +++ b/python/c3/codegenerator.py Wed Aug 14 20:12:40 2013 +0200 @@ -5,203 +5,154 @@ from ppci import CompilerError from .typecheck import theType -tmpnames = {'+':'add', '-':'sub', '*': 'mul', '/':'div', '|':'or', \ - '&':'and', '>>':'shl', '<<':'shr'} -class CodeGenerator: +class CodeGenerator(ir.Builder): """ Generates intermediate code from a package """ def __init__(self): self.logger = logging.getLogger('c3cgen') def gencode(self, pkg): + self.prepare() assert type(pkg) is astnodes.Package self.logger.info('Generating ir-code for {}'.format(pkg.name)) self.varMap = {} # Maps variables to storage locations. self.funcMap = {} - self.builder = ir.Builder() - m = ir.Module(pkg.name) - self.builder.setModule(m) + self.m = ir.Module(pkg.name) self.genModule(pkg) - return m + return self.m # inner helpers: def genModule(self, pkg): - # Take care of forward declarations: - for s in pkg.innerScope.Functions: - f = self.builder.newFunction(s.name) + # Take care of forward declarations: + for s in pkg.innerScope.Functions: + f = self.newFunction(s.name) self.funcMap[s] = f - for s in pkg.innerScope: - if type(s) is astnodes.Variable: - v = self.builder.newTmp(s.name) - #self.builder.addIns(ir.Alloc(v)) - self.varMap[s] = v - elif type(s) is astnodes.Function: - # TODO: handle arguments - f = self.funcMap[s] - self.builder.setFunction(f) - bb = self.builder.newBB() - f.entry = bb - self.builder.setBB(bb) - # generate room for locals: + for s in pkg.innerScope: + if type(s) is astnodes.Variable: + #v = self.builder.newTmp(s.name) + self.varMap[s] = self.newTemp() + pass + elif type(s) is astnodes.Function: + self.genFunction(s) + else: + raise NotImplementedError(str(s)) - for sym in s.innerScope: - #print(sym, sym.isParameter) - # TODO: handle parameters different - v = self.builder.newTmp(sym.name) - self.builder.addIns(ir.Alloc(v)) - self.varMap[sym] = v + def genFunction(self, fn): + # TODO: handle arguments + f = self.funcMap[fn] + self.setFunction(f) + # generate room for locals: - self.genCode(s.body) - # TODO handle return? - self.builder.addIns(ir.Return()) - self.builder.setFunction(None) - else: - print(s) + for sym in fn.innerScope: + # TODO: handle parameters different + v = self.newTemp() + # TODO: make this ssa here?? + self.varMap[sym] = v + + self.genCode(fn.body) + # TODO handle return? + self.emit(ir.Return(ir.Const(0))) + self.setFunction(None) def genCode(self, code): assert isinstance(code, astnodes.Statement) - self.builder.setLoc(code.loc) + self.setLoc(code.loc) if type(code) is astnodes.CompoundStatement: for s in code.statements: self.genCode(s) elif type(code) is astnodes.Assignment: - re = self.genExprCode(code.rval) - loc = self.genExprCode(code.lval) - self.builder.addIns(ir.Store(loc, re)) + rval = self.genExprCode(code.rval) + lval = self.genExprCode(code.lval) + self.emit(ir.Move(lval, rval)) elif type(code) is astnodes.ExpressionStatement: self.genExprCode(code.ex) elif type(code) is astnodes.IfStatement: - bbtrue = self.builder.newBB() - bbfalse = self.builder.newBB() - te = self.builder.newBB() - self.genCondCode(code.condition, bbtrue, bbfalse) - self.builder.setBB(bbtrue) - self.genCode(code.truestatement) - self.builder.addIns(ir.Branch(te)) - self.builder.setBB(bbfalse) - if code.falsestatement: - self.genCode(code.falsestatement) - self.builder.addIns(ir.Branch(te)) - self.builder.setBB(te) + bbtrue = self.newBlock() + bbfalse = self.newBlock() + te = self.newBlock() + self.genCondCode(code.condition, bbtrue, bbfalse) + self.setBlock(bbtrue) + self.genCode(code.truestatement) + self.emit(ir.Jump(te)) + self.setBlock(bbfalse) + if code.falsestatement: + self.genCode(code.falsestatement) + self.emit(ir.Jump(te)) + self.setBlock(te) elif type(code) is astnodes.ReturnStatement: if code.expr: re = self.genExprCode(code.expr) - self.builder.addIns(ir.Return(re)) + self.emit(ir.Return(re)) else: self.builder.addIns(ir.Return()) elif type(code) is astnodes.WhileStatement: - bbdo = self.builder.newBB() - bbtest = self.builder.newBB() - te = self.builder.newBB() - self.builder.addIns(ir.Branch(bbtest)) - self.builder.setBB(bbtest) + bbdo = self.newBlock() + bbtest = self.newBlock() + te = self.newBlock() + self.emit(ir.Jump(bbtest)) + self.setBlock(bbtest) self.genCondCode(code.condition, bbdo, te) - self.builder.setBB(bbdo) + self.setBlock(bbdo) self.genCode(code.statement) - self.builder.addIns(ir.Branch(bbtest)) - self.builder.setBB(te) + self.emit(ir.Jump(bbtest)) + self.setBlock(te) else: - print('Unknown stmt:', code) - raise NotImplementedError() + raise NotImplementedError('Unknown stmt {}'.format(code)) def genCondCode(self, expr, bbtrue, bbfalse): # Implement sequential logical operators assert expr.typ == boolType if type(expr) is astnodes.Binop: - if expr.op == 'or': - l2 = self.builder.newBB() + if expr.op == 'or': + l2 = self.newBlock() self.genCondCode(expr.a, bbtrue, l2) - self.builder.setBB(l2) + self.setBlock(l2) self.genCondCode(expr.b, bbtrue, bbfalse) - elif expr.op == 'and': - l2 = self.builder.newBB() + elif expr.op == 'and': + l2 = self.newBlock() self.genCondCode(expr.a, l2, bbfalse) - self.builder.setBB(l2) + self.setBlock(l2) self.genCondCode(expr.b, bbtrue, bbfalse) - elif expr.op in ['==', '>', '<']: + elif expr.op in ['==', '>', '<']: ta = self.genExprCode(expr.a) tb = self.genExprCode(expr.b) - i = ir.ConditionalBranch(ta, expr.op, tb, bbtrue, bbfalse) - self.builder.addIns(i) - else: - raise NotImlementedError('Unknown condition {0}'.format(expr)) + self.emit(ir.CJump(ta, expr.op, tb, bbtrue, bbfalse)) + else: + raise NotImplementedError('Unknown condition {}'.format(expr)) elif type(expr) is astnodes.Literal: if expr.val: - self.builder.addIns(ir.Branch(bbtrue)) + self.emit(ir.Jump(bbtrue)) else: - self.builder.addIns(ir.Branch(bbfalse)) + self.emit(ir.Jump(bbfalse)) else: - print('Unknown cond', expr) - raise NotImplementedError() - - def cast_to_rvalue(self, expr, loc): - """ Cast lvalue to rvalue if required """ - if hasattr(expr, 'expect_rvalue'): - # Load value from memory location: - tmp = self.builder.newTmp() - i = ir.Load(loc, tmp) - self.builder.addIns(i) - return tmp - if expr.lvalue: - return loc + raise NotImplementedError('Unknown cond {}'.format(expr)) def genExprCode(self, expr): assert isinstance(expr, astnodes.Expression) - if type(expr) is astnodes.Binop: - ra = self.genExprCode(expr.a) - rb = self.genExprCode(expr.b) - ops = ['+', '-', '*', '/', '|', '&', '<<', '>>'] - if expr.op in ops: - tmp = self.builder.newTmp(tmpnames[expr.op]) - op = expr.op - ins = ir.BinaryOperator(tmp, op, ra, rb) - self.builder.addIns(ins) - return tmp - else: - raise NotImplementedError('Unknown {0}'.format(expr)) - tmp = self.builder.newTmp() - # TODO - return tmp - elif type(expr) is astnodes.Unop: + if type(expr) is astnodes.Binop and expr.op in ir.Binop.ops: ra = self.genExprCode(expr.a) - if expr.op == '&': - # Address of operator - tmp = self.builder.newTmp('addr') - return tmp - #self.builder.addIns(ins) - else: - raise NotImplementedError('Unknown {0}'.format(expr)) - elif type(expr) is astnodes.Constant: - tmp = self.builder.newTmp() - # TODO - return tmp + rb = self.genExprCode(expr.b) + return ir.Binop(ra, expr.op, rb) + elif type(expr) is astnodes.Unop and expr.op == '&': + ra = self.genExprCode(expr.a) + # TODO: Make this work? + return ra elif type(expr) is astnodes.VariableUse: - loc = self.varMap[expr.target] - return self.cast_to_rvalue(expr, loc) + return self.varMap[expr.target] elif type(expr) is astnodes.Deref: # dereference pointer type: addr = self.genExprCode(expr.ptr) - tmp = self.builder.newTmp('deref') - ins = ir.Load(addr, tmp) - self.builder.addIns(ins) - return tmp + return ir.Mem(addr) elif type(expr) is astnodes.FieldRef: b = self.genExprCode(expr.base) - offset = self.builder.newTmp('off_' + expr.field) + #b = b.e bt = theType(expr.base.typ) - ofs = bt.fieldOffset(expr.field) - ins = ir.ImmLoad(offset, ofs) - self.builder.addIns(ins) - tmp2 = self.builder.newTmp('adr_' + expr.field) - ins = ir.BinaryOperator(tmp2, '+', b, offset) - self.builder.addIns(ins) - return self.cast_to_rvalue(expr, tmp2) + offset = ir.Const(bt.fieldOffset(expr.field)) + return ir.Mem(ir.Binop(b, '+', offset)) elif type(expr) is astnodes.Literal: - tmp = self.builder.newTmp('const') - ins = ir.ImmLoad(tmp, expr.val) - self.builder.addIns(ins) - return tmp + return ir.Const(expr.val) elif type(expr) is astnodes.TypeCast: + # TODO: improve this mess: ar = self.genExprCode(expr.a) tt = theType(expr.to_type) if isinstance(tt, astnodes.PointerType): @@ -214,15 +165,9 @@ else: raise NotImplementedError("not implemented") elif type(expr) is astnodes.FunctionCall: - tmp = self.builder.newTmp("res") - args = [] - for arg in expr.args: - ar = self.genExprCode(arg) - args.append(ar) + args = [self.genExprCode(e) for e in expr.args] fn = self.funcMap[expr.proc] - ins = ir.Call(fn, args, tmp) - self.builder.addIns(ins) - return tmp + return ir.Call(fn, args) else: raise NotImplementedError('Unknown expr {}'.format(expr))