changeset 316:56e6ff84f646

Fixed burn led demo
author Windel Bouwman
date Sat, 21 Dec 2013 13:13:26 +0100
parents 084cccaa5deb
children e30a77ae359b
files python/outstream.py python/ppci/c3/astnodes.py python/ppci/c3/codegenerator.py python/ppci/codegen/codegen.py python/ppci/transform.py python/target/arminstructionselector.py python/zcc.py
diffstat 7 files changed, 95 insertions(+), 60 deletions(-) [+]
line wrap: on
line diff
--- a/python/outstream.py	Sat Dec 21 10:03:01 2013 +0100
+++ b/python/outstream.py	Sat Dec 21 13:13:26 2013 +0100
@@ -33,6 +33,7 @@
         di = [i for i in self.instructions if isinstance(i, DebugInfo)]
         return di
 
+
 class OutputStream:
     def __init__(self):
         self.sections = {}
@@ -69,15 +70,19 @@
                 bts = i.encode()
                 address += len(bts)
 
-    def dump(self):
-        self.backpatch()
-        self.backpatch()
-        for s in sorted(self.sections.keys()):
-            self.dumpSection(s)
+class OutputStreamWriter:
+    def __init__(self, extra_indent=''):
+        self.extra_indent = extra_indent
 
-    def dumpSection(self, s):
-        print('.section '+ s)
-        for i in self.sections[s].instructions:
+    def dump(self, stream, f):
+        stream.backpatch()
+        stream.backpatch()
+        for s in sorted(stream.sections.keys()):
+            # print('.section '+ s)
+            self.dumpSection(stream.sections[s], f)
+
+    def dumpSection(self, s, f):
+        for i in s.instructions:
             if type(i) is DebugInfo:
                 continue
             addr = i.address
@@ -86,9 +91,9 @@
             insword = binascii.hexlify(bytes(reversed(insword))).decode('ascii')
             asm = str(i)
             if len(insword) == 0:
-                print('        {}'.format(asm))
+                print('        {}'.format(asm), file=f)
             else:
-                print('    0x{0:08x} 0x{1} {2}'.format(addr, insword, asm))
+                print('    0x{0:08x} 0x{1} {2}'.format(addr, insword, asm), file=f)
 
 
 class TextOutputStream(OutputStream):
--- a/python/ppci/c3/astnodes.py	Sat Dec 21 10:03:01 2013 +0100
+++ b/python/ppci/c3/astnodes.py	Sat Dec 21 13:13:26 2013 +0100
@@ -85,11 +85,11 @@
 
 
 class StructField:
+    """ Field of a struct type """
     def __init__(self, name, typ):
         assert type(name) is str
         self.name = name
         self.typ = typ
-        self.offset = 0
 
 
 class StructureType(Type):
@@ -133,6 +133,7 @@
 
 
 class Constant(Symbol):
+    """ Constant definition """
     def __init__(self, name, typ, value):
         super().__init__(name)
         self.typ = typ
@@ -147,7 +148,6 @@
         super().__init__(name)
         self.typ = typ
         self.isLocal = False
-        self.isReadOnly = False
         self.isParameter = False
 
     def __repr__(self):
--- a/python/ppci/c3/codegenerator.py	Sat Dec 21 10:03:01 2013 +0100
+++ b/python/ppci/c3/codegenerator.py	Sat Dec 21 13:13:26 2013 +0100
@@ -55,10 +55,6 @@
         self.pkg.ok = False
         self.diag.error(msg, loc)
 
-    def checkType(self, t):
-        """ Verify the type is correct """
-        t = self.theType(t)
-
     def gen_function(self, fn):
         # TODO: handle arguments
         f = self.funcMap[fn]
@@ -70,11 +66,14 @@
         # generate room for locals:
 
         for sym in fn.innerScope:
-            # TODO: handle parameters different
-            self.checkType(sym.typ)
+            self.the_type(sym.typ)
             if sym.isParameter:
-                variable = ir.Parameter(sym.name)
-                f.addParameter(variable)
+                p = ir.Parameter(sym.name)
+                variable = ir.LocalVariable(sym.name + '_copy')
+                f.addParameter(p)
+                f.addLocal(variable)
+                # Move parameter into local copy:
+                self.emit(ir.Move(ir.Mem(variable), p))
             elif sym.isLocal:
                 variable = ir.LocalVariable(sym.name)
                 f.addLocal(variable)
@@ -248,7 +247,7 @@
         elif type(expr) is ast.Deref:
             # dereference pointer type:
             addr = self.genExprCode(expr.ptr)
-            ptr_typ = self.theType(expr.ptr.typ)
+            ptr_typ = self.the_type(expr.ptr.typ)
             expr.lvalue = True
             if type(ptr_typ) is ast.PointerType:
                 expr.typ = ptr_typ.ptype
@@ -258,7 +257,7 @@
         elif type(expr) is ast.Member:
             base = self.genExprCode(expr.base)
             expr.lvalue = expr.base.lvalue
-            basetype = self.theType(expr.base.typ)
+            basetype = self.the_type(expr.base.typ)
             if type(basetype) is ast.StructureType:
                 if basetype.hasField(expr.field):
                     expr.typ = basetype.fieldType(expr.field)
@@ -270,7 +269,7 @@
                                     .format(expr.field, basetype), expr.loc)
 
             assert type(base) is ir.Mem, type(base)
-            bt = self.theType(expr.base.typ)
+            bt = self.the_type(expr.base.typ)
             offset = ir.Const(bt.fieldOffset(expr.field))
             return ir.Mem(ir.Add(base.e, offset))
         elif type(expr) is ast.Literal:
@@ -291,8 +290,8 @@
     def gen_type_cast(self, expr):
         """ Generate code for type casting """
         ar = self.genExprCode(expr.a)
-        from_type = self.theType(expr.a.typ)
-        to_type = self.theType(expr.to_type)
+        from_type = self.the_type(expr.a.typ)
+        to_type = self.the_type(expr.to_type)
         if isinstance(from_type, ast.PointerType) and isinstance(to_type, ast.PointerType):
             expr.typ = expr.to_type
             return ar
@@ -351,12 +350,28 @@
         assert isinstance(s, ast.Symbol)
         return s
 
-    def theType(self, t):
+    def size_of(self, t):
+        """ Determine the byte size of a type """
+        t = self.the_type(t)
+        if type(t) is ast.BaseType:
+            return t.bytesize
+        elif type(t) is ast.StructureType:
+            return sum(self.size_of(mem.typ) for mem in t.mems)
+        else:
+            raise NotImplementedError(str(t))
+
+    def the_type(self, t):
         """ Recurse until a 'real' type is found """
         if type(t) is ast.DefinedType:
-            t = self.theType(t.typ)
+            t = self.the_type(t.typ)
         elif type(t) in [ast.Identifier, ast.Member]:
-            t = self.theType(self.resolveSymbol(t))
+            t = self.the_type(self.resolveSymbol(t))
+        elif type(t) is ast.StructureType:
+            # Setup offsets of fields. Is this the right place?:
+            offset = 0
+            for mem in t.mems:
+                mem.offset = offset
+                offset = offset + self.size_of(mem.typ)
         elif isinstance(t, ast.Type):
             pass
         else:
@@ -367,10 +382,8 @@
     def equalTypes(self, a, b):
         """ Compare types a and b for structural equavalence. """
         # Recurse into named types:
-        a = self.theType(a)
-        b = self.theType(b)
-        assert isinstance(a, ast.Type)
-        assert isinstance(b, ast.Type)
+        a = self.the_type(a)
+        b = self.the_type(b)
 
         if type(a) is type(b):
             if type(a) is ast.BaseType:
--- a/python/ppci/codegen/codegen.py	Sat Dec 21 10:03:01 2013 +0100
+++ b/python/ppci/codegen/codegen.py	Sat Dec 21 13:13:26 2013 +0100
@@ -27,10 +27,10 @@
 
         # Canonicalize the intermediate language:
         canonicalize(irfunc, frame)
-        self.logger.info('after canonicalize', extra={'irfunc':irfunc})
+        self.logger.info('after canonicalize', extra={'irfunc': irfunc})
         self.verifier.verify_function(irfunc)
         self.ins_sel.munchFunction(irfunc, frame)
-        self.logger.info('Selected instructions', extra={'ppci_frame':frame})
+        self.logger.info('Selected instructions', extra={'ppci_frame': frame})
 
         # Do register allocation:
         self.ra.allocFrame(frame)
--- a/python/ppci/transform.py	Sat Dec 21 10:03:01 2013 +0100
+++ b/python/ppci/transform.py	Sat Dec 21 13:13:26 2013 +0100
@@ -8,7 +8,7 @@
 
 class FunctionPass:
     def __init__(self):
-        self.logger = logging.getLogger('optimize')
+        self.logger = logging.getLogger(str(self.__class__.__name__))
 
     def run(self, ir):
         """ Main entry point for the pass """
@@ -116,27 +116,26 @@
                 else:
                     constMap[k] = i.result
         for i in to_remove:
-            logging.debug('removing {}'.format(i))
+            self.logger.debug('removing {}'.format(i))
             bb.removeInstruction(i)
 
 
 class CleanPass(FunctionPass):
     def onFunction(self, f):
-        removeEmptyBasicBlocks(f)
-
+        self.remove_empty_blocks(f)
 
-def removeEmptyBlocks(f):
-    """ Remove empty basic blocks from function. """
-    # If a block only contains a branch, it can be removed:
-    empty = lambda b: type(b.FirstInstruction) is ir.Jump
-    empty_blocks = list(filter(empty, f.Blocks))
-    for b in empty_blocks:
-        # Update predecessors
-        preds = b.Predecessors
-        if b not in preds + [f.entry]:
-            # Do not remove if preceeded by itself
-            tgt = b.LastInstruction.target
-            for pred in preds:
-                  pred.LastInstruction.changeTarget(b, tgt)
-            logging.debug('Removing empty block: {}'.format(b))
-            f.removeBlock(b)
+    def remove_empty_blocks(self, f):
+        """ Remove empty basic blocks from function. """
+        # If a block only contains a branch, it can be removed:
+        empty = lambda b: type(b.FirstInstruction) is ir.Jump
+        empty_blocks = list(filter(empty, f.Blocks))
+        for b in empty_blocks:
+            # Update predecessors
+            preds = b.Predecessors
+            if b not in preds + [f.entry]:
+                # Do not remove if preceeded by itself
+                tgt = b.LastInstruction.target
+                for pred in preds:
+                      pred.LastInstruction.changeTarget(b, tgt)
+                self.logger.debug('Removing empty block: {}'.format(b))
+                f.removeBlock(b)
--- a/python/target/arminstructionselector.py	Sat Dec 21 10:03:01 2013 +0100
+++ b/python/target/arminstructionselector.py	Sat Dec 21 13:13:26 2013 +0100
@@ -45,14 +45,14 @@
             b = self.munchExpr(e.b)
             d = self.newTmp()
             self.move(d, a)
-            self.emit(Orr, dst=[], src=[b, d])
+            self.emit(Orr, dst=[], src=[d, b])
             return d
         elif isinstance(e, ir.Binop) and e.operation == '<<':
             a = self.munchExpr(e.a)
             b = self.munchExpr(e.b)
             d = self.newTmp()
             self.move(d, a)
-            self.emit(Lsl, dst=[], src=[b, d]) # TODO: is d a source variable?
+            self.emit(Lsl, dst=[], src=[d, b]) # TODO: is d a source variable?
             return d
         elif isinstance(e, ir.Binop) and e.operation == '*':
             a = self.munchExpr(e.a)
--- a/python/zcc.py	Sat Dec 21 10:03:01 2013 +0100
+++ b/python/zcc.py	Sat Dec 21 13:13:26 2013 +0100
@@ -13,6 +13,7 @@
 import target
 from ppci import irutils
 import io
+from ppci.transform import CleanPass
 
 
 logformat='%(asctime)s|%(levelname)s|%(name)s|%(message)s'
@@ -79,6 +80,7 @@
             print('.. graphviz::', file=f)
             print('', file=f)
             print('  digraph G {', file=f)
+            print('    size="8,80";', file=f)
             cfg = record.ra_cfg
             cfg.to_dot(f)
             print('  }', file=f)
@@ -91,11 +93,22 @@
             print('.. graphviz::', file=f)
             print('', file=f)
             print('  digraph G {', file=f)
+            print('    ratio="compress";', file=f)
+            print('    size="8,80";', file=f)
             ig = record.ra_ig
             ig.to_dot(f)
             print('  }', file=f)
             print('', file=f)
             s += '\n' + f.getvalue()
+        if hasattr(record, 'zcc_outs'):
+            f = io.StringIO()
+            print('', file=f)
+            print('', file=f)
+            print('.. code::', file=f)
+            print('', file=f)
+            outstream.OutputStreamWriter('  ').dump(record.zcc_outs, f)
+            print('', file=f)
+            s += '\n' + f.getvalue()
         return s
 
 
@@ -119,7 +132,8 @@
     type=argparse.FileType('w'))
 parser.add_argument('--log', help='Log level (INFO,DEBUG,[WARN])', 
                     type=logLevel, default='WARN')
-parser.add_argument('--report', help='Specify a file to write the compile report to', 
+parser.add_argument('--report', 
+            help='Specify a file to write the compile report to', 
             type=argparse.FileType('w'))
 
 
@@ -129,7 +143,8 @@
         Compile sources into output stream.
         Sources is an iterable of open files.
     """
-    logging.info('Zcc started {}'.format(srcs))
+    logger = logging.getLogger('zcc')
+    logger.info('Zcc started {}'.format(srcs))
     # Front end:
     c3b = Builder(diag, tg)
     cg = CodeGenerator(tg)
@@ -145,13 +160,16 @@
             return
 
         d = {'ircode':ircode}
-        logging.info('Verifying code {}'.format(ircode), extra=d)
-        # Optimization passes, TODO
+        logger.info('Verifying code {}'.format(ircode), extra=d)
+        Verifier().verify(ircode)
+
+        # Optimization passes:
+        CleanPass().run(ircode)
         Verifier().verify(ircode)
 
         # Code generation:
         d = {'ircode':ircode}
-        logging.info('Starting code generation for {}'.format(ircode), extra=d)
+        logger.info('Starting code generation for {}'.format(ircode), extra=d)
         cg.generate(ircode, outs)
     # TODO: fixup references, do this in another way?
     outs.backpatch()