Mercurial > lcfOS
view python/c3/codegenerator.py @ 172:5a7d37d615ee
Added function to IR
author | Windel Bouwman |
---|---|
date | Thu, 04 Apr 2013 17:58:37 +0200 |
parents | 3eb9b9e2958d |
children | 3eb06f5fb987 |
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.builder = ir.Builder() m = ir.Module(pkg.name) self.builder.setModule(m) self.genModule(pkg) return m # inner helpers: def genModule(self, pkg): for s in pkg.scope: if type(s) is astnodes.Variable: # TODO pass elif type(s) is astnodes.Function: # TODO: handle arguments f = self.builder.newFunc(s.name) self.builder.setFunc(f) bb = self.builder.newBB() f.entry = bb self.builder.setBB(bb) self.genCode(s.body) # TODO handle return? self.builder.addIns(ir.Return()) self.builder.setFunc(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) self.builder.addIns(ir.Store(code.lval, 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: pass elif type(code) is astnodes.EmptyStatement: pass elif type(code) is astnodes.ReturnStatement: pass 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() print('Unknown cond', expr) elif type(expr) is astnodes.Literal: if expr.val: self.builder.addIns(ir.BranchInstruction(bbtrue)) else: self.builder.addIns(ir.BranchInstruction(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) tmp = self.builder.newTmp() ops = ['+', '-', '*', '/', 'and', 'or'] if expr.op in ops: op = expr.op ins = ir.BinaryOperator(tmp, op, ra, rb) self.builder.addIns(ins) return tmp else: print('Unknown {0}'.format(expr)) # 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() i = ir.Load(expr, 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 else: print('Unknown expr:', code)