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))