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)