Mercurial > lcfOS
view python/c3/codegenerator.py @ 219:1fa3e0050b49
Expanded ad hoc code generator
author | Windel Bouwman |
---|---|
date | Sat, 06 Jul 2013 12:38:09 +0200 |
parents | 8b2e5f3cd579 |
children | 3f6c30a5d234 |
line wrap: on
line source
import ir from . import astnodes from .scope import boolType class CodeGenerator: """ Generates intermediate code from a package """ def gencode(self, pkg): assert type(pkg) is astnodes.Package self.varMap = {} # Maps variables to storage locations. self.funcMap = {} self.builder = ir.Builder() m = ir.Module(pkg.name) self.builder.setModule(m) self.genModule(pkg) return m # inner helpers: def genModule(self, pkg): # Take care of forward declarations: for s in pkg.innerScope.Functions: f = self.builder.newFunction(s.name) self.funcMap[s] = f for s in pkg.innerScope: if type(s) is astnodes.Variable: v = self.builder.newVariable(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 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 self.genCode(s.body) # TODO handle return? self.builder.addIns(ir.Return()) self.builder.setFunction(None) else: print(s) def genCode(self, code): 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.varMap[code.lval.target] self.builder.addIns(ir.Store(loc, re)) 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) self.genCode(code.falsestatement) self.builder.addIns(ir.Branch(te)) self.builder.setBB(te) elif type(code) is astnodes.FunctionCall: print('TODO') pass elif type(code) is astnodes.EmptyStatement: pass elif type(code) is astnodes.ReturnStatement: if code.expr: re = self.genExprCode(code.expr) self.builder.addIns(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) self.genCondCode(code.condition, bbdo, te) self.builder.setBB(bbdo) self.genCode(code.statement) self.builder.addIns(ir.Branch(bbtest)) self.builder.setBB(te) else: print('Unknown stmt:', 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() self.genCondCode(expr.a, bbtrue, l2) self.builder.setBB(l2) self.genCondCode(expr.b, bbtrue, bbfalse) elif expr.op == 'and': l2 = self.builder.newBB() self.genCondCode(expr.a, l2, bbfalse) self.builder.setBB(l2) self.genCondCode(expr.b, bbtrue, bbfalse) 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)) elif type(expr) is astnodes.Literal: if expr.val: self.builder.addIns(ir.Branch(bbtrue)) else: self.builder.addIns(ir.Branch(bbfalse)) else: print('Unknown cond', expr) def genExprCode(self, expr): if type(expr) is astnodes.Binop: ra = self.genExprCode(expr.a) rb = self.genExprCode(expr.b) ops = ['+', '-', '*', '/'] if expr.op in ops: tmpnames = {'+':'addtmp', '-':'subtmp', '*': 'multmp', '/':'divtmp'} tmp = self.builder.newTmp(tmpnames[expr.op]) op = expr.op ins = ir.BinaryOperator(tmp, op, ra, rb) self.builder.addIns(ins) return tmp else: print('Unknown {0}'.format(expr)) tmp = self.builder.newTmp() # TODO return tmp elif type(expr) is astnodes.Constant: tmp = self.builder.newTmp() # TODO return tmp elif type(expr) is astnodes.VariableUse: tmp = self.builder.newTmp() loc = self.varMap[expr.target] i = ir.Load(loc, tmp) self.builder.addIns(i) return tmp elif type(expr) is astnodes.Literal: tmp = self.builder.newTmp() ins = ir.ImmLoad(tmp, expr.val) self.builder.addIns(ins) return tmp elif type(expr) is astnodes.FunctionCall: tmp = self.builder.newTmp("res") args = [] for arg in expr.args: ar = self.genExprCode(arg) args.append(ar) fn = self.funcMap[expr.proc] ins = ir.Call(fn, args, tmp) self.builder.addIns(ins) return tmp else: print('Unknown expr:', code)