changeset 261:444b9df2ed99

try to split up code generation
author Windel Bouwman
date Fri, 09 Aug 2013 09:05:13 +0200
parents b2f94b4951f1
children ed14e077124c
files python/c3/codegenerator.py python/codegenarm.py python/cortexm3.py python/cortexm3desc.py python/grind.py python/ir/instruction.py python/irmach.py python/mem2reg.py python/transform.py
diffstat 9 files changed, 131 insertions(+), 66 deletions(-) [+]
line wrap: on
line diff
--- a/python/c3/codegenerator.py	Tue Aug 06 18:29:53 2013 +0200
+++ b/python/c3/codegenerator.py	Fri Aug 09 09:05:13 2013 +0200
@@ -9,9 +9,10 @@
     '&':'and', '>>':'shl', '<<':'shr'}
 
 class CodeGenerator:
+    """ Generates intermediate code from a package """
     def __init__(self):
-        self.logger = logging.getLogger('c3')
-    """ Generates intermediate code from a package """
+        self.logger = logging.getLogger('c3cgen')
+
     def gencode(self, pkg):
         assert type(pkg) is astnodes.Package
         self.logger.info('Generating ir-code for {}'.format(pkg.name))
@@ -101,6 +102,7 @@
             self.builder.setBB(te)
         else:
             print('Unknown stmt:', code)
+            raise NotImplementedError()
 
     def genCondCode(self, expr, bbtrue, bbfalse):
         # Implement sequential logical operators
@@ -130,6 +132,7 @@
                 self.builder.addIns(ir.Branch(bbfalse))
         else:
              print('Unknown cond', expr)
+             raise NotImplementedError()
 
     def cast_to_rvalue(self, expr, loc):
         """ Cast lvalue to rvalue if required """
--- a/python/codegenarm.py	Tue Aug 06 18:29:53 2013 +0200
+++ b/python/codegenarm.py	Fri Aug 09 09:05:13 2013 +0200
@@ -3,6 +3,7 @@
 from target import Label, Comment, Alignment, LabelRef, Imm32, DebugInfo
 import cortexm3 as arm
 from ppci import CompilerError
+import irmach
 
 class ArmCodeGenerator:
     """
@@ -19,7 +20,7 @@
     def generate(self, ircode):
         assert isinstance(ircode, ir.Module)
         self.logger.info('Generating arm code for {}'.format(ircode.name))
-        self.available_regs = {arm.r2, arm.r3, arm.r4, arm.r5, arm.r6, arm.r7}
+        self.available_regs = {arm.r3, arm.r4, arm.r5, arm.r6, arm.r7}
         self.regmap = {}
         # TODO: get these from linker descriptor?
         self.outs.getSection('code').address = 0x08000000
@@ -51,7 +52,7 @@
             self.stack_frame = []
             self.emit(Label(f.name))
             # Save some registers:
-            self.emit(arm.push_ins(arm.RegisterSet({arm.r4, arm.r5, arm.r6,arm.r7,arm.lr})))
+            self.emit(arm.push_ins(arm.RegisterSet({arm.r3, arm.r4, arm.r5, arm.r6,arm.r7,arm.lr})))
             for bb in f.BasicBlocks:
                 self.emit(Label(bb.name))
                 for ins in bb.Instructions:
@@ -167,7 +168,7 @@
             # TODO: prep parameters:
             self.emit(arm.bl_ins(LabelRef(ins.callee.name)))
         elif type(ins) is ir.Return:
-            self.emit(arm.pop_ins(arm.RegisterSet({arm.r4, arm.r5, arm.r6, arm.r7, arm.pc})))
+            self.emit(arm.pop_ins(arm.RegisterSet({arm.r3, arm.r4, arm.r5, arm.r6, arm.r7, arm.pc})))
         elif type(ins) is ir.ConditionalBranch:
             r0 = self.getreg(ins.a)
             r1 = self.getreg(ins.b)
--- a/python/cortexm3.py	Tue Aug 06 18:29:53 2013 +0200
+++ b/python/cortexm3.py	Fri Aug 09 09:05:13 2013 +0200
@@ -1,4 +1,5 @@
-import struct, types
+import struct
+import types
 from target import Register, Instruction, Target, Imm8, Label, Imm3, LabelRef, Imm32
 from asmnodes import ASymbol, ANumber, AUnop, ABinop
 from ppci import CompilerError
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/cortexm3desc.py	Fri Aug 09 09:05:13 2013 +0200
@@ -0,0 +1,17 @@
+
+# Patterns
+
+import cortexm3
+import ir
+
+
+{
+"""
+v3 = const1
+v1 = v2 + v3
+[v1] = v3
+""": cortexm3.
+}
+
+
+
--- a/python/grind.py	Tue Aug 06 18:29:53 2013 +0200
+++ b/python/grind.py	Fri Aug 09 09:05:13 2013 +0200
@@ -7,5 +7,6 @@
     suite = unittest.TestLoader().discover('.')
     def runtests():
         unittest.TextTestRunner().run(suite)
-    s = cProfile.run('runtests()',sort='cumtime')
+    #s = cProfile.run('runtests()',sort='cumtime')
+    s = cProfile.run('runtests()',sort='tottime')
 
--- a/python/ir/instruction.py	Tue Aug 06 18:29:53 2013 +0200
+++ b/python/ir/instruction.py	Fri Aug 09 09:05:13 2013 +0200
@@ -32,6 +32,11 @@
         assert ins in self.used_by
         return all(not ins.precedes(ub) for ub in self.used_by)
 
+    def replaceby(self, v2):
+        for use_ins in self.used_by:
+            use_ins.replaceValue(self, v2.value)
+        assert not self.Used
+
 class Variable(Value):
     pass
 
@@ -133,13 +138,6 @@
 
 
 
-class Terminator(Instruction):
-    @property
-    def Targets(self):
-        return self.getTargets()
-
-    def changeTarget(self, tfrom, tto):
-        pass
 
 
 # Function calling:
@@ -156,6 +154,7 @@
       if result:
          assert type(result) is Value
          self.addDef(result)
+
    def __repr__(self):
       if self.result:
          pfx = '{0} = '.format(self.result)
@@ -164,55 +163,43 @@
       args = ','.join([str(arg) for arg in self.arguments])
       return pfx + '{0}({1})'.format(self.callee.name, args)
 
-class Return(Terminator):
-   def __init__(self, value=None):
-      super().__init__()
-      self.value = value
-      if value:
-         self.addUse(value)
-   def __repr__(self):
-      if self.value:
-         return 'ret {0}'.format(self.value)
-      else:
-         return 'ret'
-   def getTargets(self):
-      return []
 
 class Alloc(Instruction):
-   """ Allocates space on the stack """
-   def __init__(self, value):
-      super().__init__()
-      assert isinstance(value, Value)
-      self.value = value
-      self.addDef(value)
-   def __repr__(self):
-      return '{0} = alloc'.format(self.value)
+    """ Allocates space on the stack """
+    def __init__(self, value):
+        super().__init__()
+        assert isinstance(value, Value)
+        self.value = value
+        self.addDef(value)
+
+    def __repr__(self):
+        return '{0} = alloc'.format(self.value)
+
 
 class ImmLoad(Instruction):
-   def __init__(self, target, value):
-      super().__init__()
-      assert type(target) is Value
-      self.target = target
-      self.value = value
-      self.addDef(target)
-   def __repr__(self):
-      return '{} = {}'.format(self.target, self.value)
+    def __init__(self, target, value):
+        super().__init__()
+        assert type(target) is Value
+        self.target = target
+        self.value = value
+        self.addDef(target)
+
+    def __repr__(self):
+        return '{} = {}'.format(self.target, self.value)
 
 # Data operations
 class BinaryOperator(Instruction):
     def __init__(self, result, operation, value1, value2):
-      super().__init__()
-      #print('operation is in binops:', operation in BinOps)
-      # Check types of the two operands:
-      assert type(value1) is Value, str(value1) + str(type(value1))
-      assert type(value2) is Value, value2
-      self.result = result
-      self.addDef(result)
-      self.value1 = value1
-      self.value2 = value2
-      self.addUse(value1)
-      self.addUse(value2)
-      self.operation = operation
+        super().__init__()
+        assert type(value1) is Value, str(value1) + str(type(value1))
+        assert type(value2) is Value, value2
+        self.result = result
+        self.addDef(result)
+        self.value1 = value1
+        self.value2 = value2
+        self.addUse(value1)
+        self.addUse(value2)
+        self.operation = operation
 
     def __repr__(self):
         a, b = self.value1, self.value2
@@ -230,6 +217,7 @@
         self.removeUse(old)
         self.addUse(new)
 
+
 # Memory functions:
 class Load(Instruction):
     def __init__(self, location, value):
@@ -244,6 +232,7 @@
     def __repr__(self):
         return '{} = [{}]'.format(self.value, self.location)
 
+
 class Store(Instruction):
     def __init__(self, location, value):
         super().__init__()
@@ -267,20 +256,34 @@
         self.removeUse(old)
         self.addUse(new)
 
+
 # Branching:
+class Terminator(Instruction):
+    @property
+    def Targets(self):
+        return self.getTargets()
+
+    def changeTarget(self, tfrom, tto):
+        pass
+
+
 class Branch(Terminator):
     def __init__(self, target):
-      super().__init__()
-      assert type(target) is BasicBlock
-      self.target = target
+        super().__init__()
+        assert type(target) is BasicBlock
+        self.target = target
+
     def __repr__(self):
         return 'BRANCH {0}'.format(self.target)
+
     def getTargets(self):
         return [self.target]
+
     def changeTarget(self, tfrom, tto):
         assert tfrom is self.target
         self.target = tto
 
+
 class ConditionalBranch(Terminator):
    def __init__(self, a, cond, b, lab1, lab2):
       super().__init__()
@@ -296,10 +299,12 @@
       self.lab1 = lab1
       assert type(lab2) is BasicBlock
       self.lab2 = lab2
+
    def __repr__(self):
       return 'IF {0} {1} {2} THEN {3} ELSE {4}'.format(self.a, self.cond, self.b, self.lab1, self.lab2)
    def getTargets(self):
       return [self.lab1, self.lab2]
+
    def changeTarget(self, tfrom, tto):
       assert tfrom is self.lab1 or tfrom is self.lab2
       if tfrom is self.lab1:
@@ -307,6 +312,24 @@
       elif tfrom is self.lab2:
          self.lab2 = tto
 
+
+class Return(Terminator):
+    def __init__(self, value=None):
+        super().__init__()
+        self.value = value
+        if value:
+            self.addUse(value)
+
+    def __repr__(self):
+        if self.value:
+            return 'ret {0}'.format(self.value)
+        else:
+            return 'ret'
+
+    def getTargets(self):
+        return []
+
+
 class PhiNode(Instruction):
     def __init__(self):
         super().__init__()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/irmach.py	Fri Aug 09 09:05:13 2013 +0200
@@ -0,0 +1,23 @@
+
+
+class MachProgram:
+    pass
+
+
+class MachFunction:
+    def __init__(self, name):
+        self.name = name
+        self.entry = None
+
+
+class MachBlock:
+    def __init__(self):
+        self.instructions = []
+
+
+class MachIns:
+    """ Absract machine instruction """
+    def __init__(self, mi):
+        self.mi = mi
+        
+
--- a/python/mem2reg.py	Tue Aug 06 18:29:53 2013 +0200
+++ b/python/mem2reg.py	Fri Aug 09 09:05:13 2013 +0200
@@ -5,7 +5,7 @@
 def isAllocPromotable(allocinst):
     # Check if alloc value is only used by load and store operations.
     assert type(allocinst) is Alloc
-    return all(type(use) in [Load,Store] for use in allocinst.value.used_by)
+    return all(type(use) in [Load, Store] for use in allocinst.value.used_by)
 
 class Mem2RegPromotor(FunctionPass):
     def promoteSingleBlock(self, ai):
@@ -24,9 +24,7 @@
             for store in stores:
                 if store.Position < load.Position:
                     break
-            for use_ins in load.value.used_by:
-                use_ins.replaceValue(load.value, store.value)
-            assert not load.value.Used
+            load.value.replaceby(store.value)
             logging.debug('replaced {} with {}'.format(load, store.value))
             bb.removeInstruction(load)
 
--- a/python/transform.py	Tue Aug 06 18:29:53 2013 +0200
+++ b/python/transform.py	Fri Aug 09 09:05:13 2013 +0200
@@ -107,8 +107,7 @@
                     t_new = constMap[i.value]
                     t_old = i.target
                     logging.debug('Replacing {} with {}'.format(t_old, t_new))
-                    for ui in t_old.used_by:
-                        ui.replaceValue(t_old, t_new)
+                    t_old.replaceby(t_new)
                     to_remove.append(i)
                 else:
                     constMap[i.value] = i.target
@@ -118,8 +117,7 @@
                     t_old = i.result
                     t_new = constMap[k]
                     logging.debug('Replacing {} with {}'.format(t_old, t_new))
-                    for ui in t_old.used_by:
-                        ui.replaceValue(t_old, t_new)
+                    t_old.replaceby(t_new)
                     to_remove.append(i)
                 else:
                     constMap[k] = i.result