Mercurial > lcfOS
diff python/c3/codegenerator.py @ 171:3eb9b9e2958d
Improved IR code
author | Windel Bouwman |
---|---|
date | Wed, 03 Apr 2013 22:20:20 +0200 |
parents | 4348da5ca307 |
children | 5a7d37d615ee |
line wrap: on
line diff
--- a/python/c3/codegenerator.py Fri Mar 29 17:33:17 2013 +0100 +++ b/python/c3/codegenerator.py Wed Apr 03 22:20:20 2013 +0200 @@ -1,32 +1,17 @@ import ir from . import astnodes - -def NumGen(): - a = 0 - while True: - yield a - a = a + 1 - -class NameGenerator: - def __init__(self, prefix): - self.prefix = prefix - self.nums = NumGen() - def gen(self): - return '{0}{1}'.format(self.prefix, self.nums.__next__()) - +from .scope import boolType + class CodeGenerator: """ Generates intermediate code from a package """ def gencode(self, pkg): assert type(pkg) is astnodes.Package - self.m = ir.Module(pkg.name) - self.newTmp = NameGenerator('t').gen - self.newLab = NameGenerator('lab').gen + self.builder = ir.Builder() + m = ir.Module(pkg.name) + self.builder.setModule(m) self.genModule(pkg) - return self.m + return m - # Helpers: - def addIns(self, i): - self.m.Instructions.append(i) # inner helpers: def genModule(self, pkg): for s in pkg.scope: @@ -36,9 +21,10 @@ elif type(s) is astnodes.Function: # TODO: handle arguments # TODO handle return? - self.addIns(ir.LabelInstruction(s.name)) + bb = self.builder.newBB() + self.builder.setBB(bb) self.genCode(s.body) - self.addIns(ir.RetInstruction()) + self.builder.addIns(ir.Return()) else: print(s) @@ -48,17 +34,19 @@ self.genCode(s) elif type(code) is astnodes.Assignment: re = self.genExprCode(code.rval) - self.addIns(ir.StoreInstruction(code.lval, re)) + self.builder.addIns(ir.Store(code.lval, re)) elif type(code) is astnodes.IfStatement: - cr = self.genExprCode(code.condition) - t1, t2, te = self.newLab(), self.newLab(), self.newLab() - self.addIns(ir.IfInstruction(cr, t1, t2)) - self.addIns(ir.LabelInstruction(t1)) + 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.addIns(ir.BranchInstruction(te)) - self.addIns(ir.LabelInstruction(t2)) + self.builder.addIns(ir.Branch(te)) + self.builder.setBB(bbfalse) self.genCode(code.falsestatement) - self.addIns(ir.LabelInstruction(te)) + self.builder.addIns(ir.Branch(te)) + self.builder.setBB(te) elif type(code) is astnodes.FunctionCall: pass elif type(code) is astnodes.EmptyStatement: @@ -67,28 +55,63 @@ 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 - tmp = self.newTmp() ins = ir.BinaryOperator(tmp, op, ra, rb) - self.addIns(ins) + self.builder.addIns(ins) return tmp else: - print('Unknown binop {0}'.format(expr)) + print('Unknown {0}'.format(expr)) + # TODO + return tmp elif type(expr) is astnodes.Constant: - tmp = unique() + tmp = self.builder.newTmp() + # TODO + return tmp elif type(expr) is astnodes.VariableUse: - tmp = self.newTmp() + tmp = self.builder.newTmp() + i = ir.Load(expr, tmp) + self.builder.addIns(i) + return tmp elif type(expr) is astnodes.Literal: - tmp = self.newTmp() - ins = ir.MoveInstruction(tmp, expr.val) - self.addIns(ins) + tmp = self.builder.newTmp() + ins = ir.ImmLoad(tmp, expr.val) + self.builder.addIns(ins) return tmp else: print('Unknown expr:', code)