changeset 305:0615b5308710

Updated docs
author Windel Bouwman
date Fri, 06 Dec 2013 13:50:38 +0100
parents fa99f36fabb5
children b145f8e6050b
files doc/compiler.rst doc/ir.rst kernel/make.py kernel/syscall.c3 python/ppci/c3/__init__.py python/ppci/c3/analyse.py python/ppci/c3/builder.py python/ppci/c3/codegenerator.py python/ppci/c3/lexer.py python/ppci/codegen/registerallocator.py python/ppci/errors.py python/ppci/ir.py python/target/arminstructions.py python/target/arminstructionselector.py python/zcc.py
diffstat 15 files changed, 103 insertions(+), 75 deletions(-) [+]
line wrap: on
line diff
--- a/doc/compiler.rst	Fri Dec 06 12:45:02 2013 +0100
+++ b/doc/compiler.rst	Fri Dec 06 13:50:38 2013 +0100
@@ -62,6 +62,8 @@
    40 -> 99
    }
 
+.. autoclass:: ppci.c3.Lexer
+
 .. autoclass:: ppci.c3.Builder
 
 .. autoclass:: ppci.c3.Parser
--- a/doc/ir.rst	Fri Dec 06 12:45:02 2013 +0100
+++ b/doc/ir.rst	Fri Dec 06 13:50:38 2013 +0100
@@ -17,6 +17,10 @@
 
 .. autoclass:: ppci.ir.Statement
 
+.. autoclass:: ppci.ir.Move
+
+Jump instructions:
+
 .. autoclass:: ppci.ir.Jump
 
 .. autoclass:: ppci.ir.CJump
@@ -29,4 +33,7 @@
 
 .. autoclass:: ppci.ir.Binop
 
+.. autoclass:: ppci.ir.Call
 
+.. autoclass:: ppci.ir.Eseq
+
--- a/kernel/make.py	Fri Dec 06 12:45:02 2013 +0100
+++ b/kernel/make.py	Fri Dec 06 13:50:38 2013 +0100
@@ -7,7 +7,7 @@
 
 arglist = ['memory.c3', 'kernel.c3', 'syscall.c3', 'process.c3', 'schedule.c3', 'arch_arm.c3']
 arglist += ['--target', 'arm']
-arglist += ['--dumpasm']
+arglist += ['--dumpasm', '--dumpir']
 arglist += ['--log', 'debug']
 
 args = zcc.parser.parse_args(arglist)
--- a/kernel/syscall.c3	Fri Dec 06 12:45:02 2013 +0100
+++ b/kernel/syscall.c3	Fri Dec 06 13:50:38 2013 +0100
@@ -15,7 +15,7 @@
 
 
 // System call handlers. System calls are made from user space.
-function void handle_system_call(int callId, int a, int b, int c, int d)
+function void handle_system_call(int callId, int a, int b)
 {
     // Main entry, check what to do here
     if (callId == 1)
--- a/python/ppci/c3/__init__.py	Fri Dec 06 12:45:02 2013 +0100
+++ b/python/ppci/c3/__init__.py	Fri Dec 06 13:50:38 2013 +0100
@@ -1,9 +1,10 @@
 """ This is the C3 language front end. """
 
-
 from .parser import Parser
 from .lexer import Lexer
-from .analyse import Analyzer, TypeChecker
+from .analyse import Analyzer
+from .analyse import TypeChecker
 from .codegenerator import CodeGenerator
-from .visitor import Visitor, AstPrinter
+from .visitor import Visitor
+from .visitor import AstPrinter
 from .builder import Builder
--- a/python/ppci/c3/analyse.py	Fri Dec 06 12:45:02 2013 +0100
+++ b/python/ppci/c3/analyse.py	Fri Dec 06 13:50:38 2013 +0100
@@ -136,7 +136,6 @@
             sym.target = self.resolveDesignator(sym.target, sym.scope)
         elif type(sym) is FunctionCall:
             varuse = sym.proc
-            print(varuse)
             if type(varuse) is VariableUse:
                 sym.proc = self.resolveDesignator(varuse.target, sym.scope)
         elif type(sym) is Function:
@@ -178,8 +177,8 @@
             return all(equalTypes(am.typ, bm.typ) for am, bm in
                        zip(a.mems, b.mems))
         else:
-            raise NotImplementedError(
-                    'Type compare for {} not implemented'.format(type(a)))
+            raise NotImplementedError('Type compare for {} not implemented'
+                                      .format(type(a)))
     return False
 
 
@@ -228,12 +227,14 @@
             ptypes = sym.proc.typ.parametertypes
             nreq = len(ptypes)
             if ngiv != nreq:
-                self.error('Function {2}: {0} arguments required, {1} given'.format(nreq, ngiv, sym.proc.name), sym.loc)
+                self.error('Function {2}: {0} arguments required, {1} given'
+                           .format(nreq, ngiv, sym.proc.name), sym.loc)
             else:
                 for a, at in zip(sym.args, ptypes):
                     expectRval(a)
                     if not equalTypes(a.typ, at):
-                        self.error('Got {0}, expected {1}'.format(a.typ, at), a.loc)
+                        self.error('Got {0}, expected {1}'
+                                   .format(a.typ, at), a.loc)
             # determine return type:
             sym.typ = sym.proc.typ.returntype
         elif type(sym) is VariableUse:
@@ -264,7 +265,8 @@
             if type(ptype) is PointerType:
                 sym.typ = ptype.ptype
             else:
-                self.error('Cannot dereference non-pointer type {}'.format(ptype), sym.loc)
+                self.error('Cannot dereference non-pointer type {}'
+                           .format(ptype), sym.loc)
                 sym.typ = intType
         elif type(sym) is FieldRef:
             basetype = sym.base.typ
@@ -274,10 +276,12 @@
                 if basetype.hasField(sym.field):
                     sym.typ = basetype.fieldType(sym.field)
                 else:
-                    self.error('{} does not contain field {}'.format(basetype, sym.field), sym.loc)
+                    self.error('{} does not contain field {}'
+                               .format(basetype, sym.field), sym.loc)
                     sym.typ = intType
             else:
-                self.error('Cannot select field {} of non-structure type {}'.format(sym.field, basetype), sym.loc)
+                self.error('Cannot select field {} of non-structure type {}'
+                           .format(sym.field, basetype), sym.loc)
                 sym.typ = intType
         elif type(sym) is Binop:
             sym.lvalue = False
@@ -293,13 +297,15 @@
                 else:
                     # assume void here? TODO: throw exception!
                     sym.typ = intType
-                    self.error('Types unequal {} != {}'.format(sym.a.typ, sym.b.typ), sym.loc)
+                    self.error('Types unequal {} != {}'
+                               .format(sym.a.typ, sym.b.typ), sym.loc)
             elif sym.op in ['>', '<', '==', '<=', '>=', '!=']:
                 expectRval(sym.a)
                 expectRval(sym.b)
                 sym.typ = boolType
                 if not equalTypes(sym.a.typ, sym.b.typ):
-                    self.error('Types unequal {} != {}'.format(sym.a.typ, sym.b.typ), sym.loc)
+                    self.error('Types unequal {} != {}'
+                               .format(sym.a.typ, sym.b.typ), sym.loc)
             elif sym.op in ['or', 'and']:
                 sym.typ = boolType
                 if not equalTypes(sym.a.typ, boolType):
@@ -316,12 +322,15 @@
             if canCast(sym.a.typ, sym.to_type):
                 sym.typ = sym.to_type
             else:
-                self.error('Cannot cast {} to {}'.format(sym.a.typ, sym.to_type), sym.loc)
+                self.error('Cannot cast {} to {}'
+                           .format(sym.a.typ, sym.to_type), sym.loc)
                 sym.typ = intType
         elif type(sym) is Constant:
             if not equalTypes(sym.typ, sym.value.typ):
-                self.error('Cannot assign {0} to {1}'.format(sym.value.typ, sym.typ), sym.loc)
-        elif type(sym) in [CompoundStatement, Package, Function, FunctionType, ExpressionStatement, DefinedType]:
+                self.error('Cannot assign {0} to {1}'
+                           .format(sym.value.typ, sym.typ), sym.loc)
+        elif type(sym) in [CompoundStatement, Package, Function, FunctionType,
+                           ExpressionStatement, DefinedType]:
             pass
         else:
             raise NotImplementedError('Unknown type check {0}'.format(sym))
--- a/python/ppci/c3/builder.py	Fri Dec 06 12:45:02 2013 +0100
+++ b/python/ppci/c3/builder.py	Fri Dec 06 13:50:38 2013 +0100
@@ -57,7 +57,7 @@
 
     def build(self, srcs, imps=[]):
         """ Create IR-code from sources """
-        self.logger.info('Starting build with {} source files'.format(len(srcs)))
+        self.logger.info('Building {} source files'.format(len(srcs)))
         self.ok = True
         for pkg in self.checkSource(srcs, imps):
             # Only return ircode when everything is OK
--- a/python/ppci/c3/codegenerator.py	Fri Dec 06 12:45:02 2013 +0100
+++ b/python/ppci/c3/codegenerator.py	Fri Dec 06 13:50:38 2013 +0100
@@ -131,7 +131,7 @@
                 self.genCondCode(expr.a, l2, bbfalse)
                 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)
                 self.emit(ir.CJump(ta, expr.op, tb, bbtrue, bbfalse))
@@ -190,7 +190,8 @@
                 raise NotImplementedError("not implemented")
         elif type(expr) is astnodes.FunctionCall:
             args = [self.genExprCode(e) for e in expr.args]
-            fn = self.funcMap[expr.proc]
+            #fn = self.funcMap[expr.proc]
+            fn = expr.proc.name
             return ir.Call(fn, args)
         else:
             raise NotImplementedError('Unknown expr {}'.format(expr))
--- a/python/ppci/c3/lexer.py	Fri Dec 06 12:45:02 2013 +0100
+++ b/python/ppci/c3/lexer.py	Fri Dec 06 13:50:38 2013 +0100
@@ -8,13 +8,14 @@
 """
 
 keywords = ['and', 'or', 'not', 'true', 'false',
-        'else', 'if', 'while', 'return',
-        'function', 'var', 'type', 'const',
-        'struct', 'cast',
-        'import', 'module']
+            'else', 'if', 'while', 'return',
+            'function', 'var', 'type', 'const',
+            'struct', 'cast',
+            'import', 'module']
 
 
 class Lexer:
+    """ Generates a sequence of token from an input stream """
     def __init__(self, diag):
         self.diag = diag
 
@@ -65,7 +66,7 @@
             elif typ == 'SKIP':
                 pass
             elif incomment:
-                pass # Wait until we are not in a comment section
+                pass    # Wait until we are not in a comment section
             else:
                 if typ == 'ID':
                     if val in keywords:
@@ -82,7 +83,7 @@
                 elif typ == 'STRING':
                     val = val[1:-1]
                 loc = SourceLocation(filename, line, mo.start() - line_start,
-                        mo.end() - mo.start())
+                                     mo.end() - mo.start())
                 yield Token(typ, val, loc)
             pos = mo.end()
             mo = gettok(s, pos)
--- a/python/ppci/codegen/registerallocator.py	Fri Dec 06 12:45:02 2013 +0100
+++ b/python/ppci/codegen/registerallocator.py	Fri Dec 06 13:50:38 2013 +0100
@@ -35,12 +35,6 @@
         self.activeMoves = set()
         self.worklistMoves = set()
 
-    def printLive(self):
-        print('Liveness:')
-        for i in self.f.instructions:
-            cfgn = self.f.cfg._map[i]
-            print(i, cfgn.live_in)
-
     def Build(self):
         """ 1. Construct interference graph from instruction list """
         self.f.cfg = FlowGraph(self.f.instructions)
--- a/python/ppci/errors.py	Fri Dec 06 12:45:02 2013 +0100
+++ b/python/ppci/errors.py	Fri Dec 06 13:50:38 2013 +0100
@@ -1,5 +1,5 @@
-""" 
-   Error handling routines 
+"""
+   Error handling routines
    Diagnostic utils
 """
 
@@ -13,7 +13,7 @@
         self.loc = loc
         if loc:
             assert type(loc) is SourceLocation, \
-                    '{0} must be SourceLocation'.format(type(loc))
+                   '{0} must be SourceLocation'.format(type(loc))
             self.row = loc.row
             self.col = loc.col
         else:
--- a/python/ppci/ir.py	Fri Dec 06 12:45:02 2013 +0100
+++ b/python/ppci/ir.py	Fri Dec 06 13:50:38 2013 +0100
@@ -7,20 +7,22 @@
     print('digraph G ', file=outf)
     print('{', file=outf)
     for f in m.Functions:
-     print('{} [label="{}" shape=box3d]'.format(id(f), f),file=outf)
-     for bb in f.Blocks:
-        contents = str(bb) + '\n'
-        contents += '\n'.join([str(i) for i in bb.Instructions])
-        outf.write('{0} [shape=note label="{1}"];\n'.format(id(bb), contents))
-        for successor in bb.Successors:
-           print('"{}" -> "{}"\n'.format(id(bb), id(successor)), file=outf)
+        print('{} [label="{}" shape=box3d]'.format(id(f), f), file=outf)
+        for bb in f.Blocks:
+            contents = str(bb) + '\n'
+            contents += '\n'.join([str(i) for i in bb.Instructions])
+            print('{0} [shape=note label="{1}"];'
+                  .format(id(bb), contents), file=outf)
+            for successor in bb.Successors:
+                print('"{}" -> "{}"'.format(id(bb), id(successor)), file=outf)
 
-     outf.write('"{}" -> "{}" [label="entry"]\n'.format(id(f), id(f.entry)))
+        print('"{}" -> "{}" [label="entry"]'
+              .format(id(f), id(f.entry)), file=outf)
     print('}', file=outf)
 
 
 class Module:
-    """ Main container of variables and functions. """
+    """ Container unit for variables and functions. """
     def __init__(self, name):
         self.name = name
         self.funcs = []
@@ -70,9 +72,7 @@
 
 
 class Function:
-    """
-      Function definition. Contains an entry block.
-    """
+    """ Represents a function. """
     def __init__(self, name):
         self.name = name
         self.entry = Block('{}_entry'.format(name))
@@ -140,13 +140,13 @@
     def dump(self, indent=''):
         print(indent+str(self))
         for bb in self.Blocks:
-            print(indent+'   '+str(bb))
+            print(indent+'   ' + str(bb))
             for ins in bb.Instructions:
-                print(indent +'   '*2 + str(ins))
+                print(indent + '   ' * 2 + str(ins))
 
 
 class Block:
-    """ 
+    """
         Uninterrupted sequence of instructions with a label at the start.
     """
     def __init__(self, name):
@@ -221,16 +221,19 @@
     def __init__(self, x):
         self.x = x
 
+
 def match_tree(tree, pattern):
     if type(pattern) is Term:
         return True, {pattern: tree}
-    elif type(pattern) is Binop and type(tree) is Binop and tree.operation == pattern.operation:
+    elif type(pattern) is Binop and type(tree) is Binop and \
+            tree.operation == pattern.operation:
         res_a, mp_a = match_tree(tree.a, pattern.a)
         res_b, mp_b = match_tree(tree.b, pattern.b)
         assert not (mp_a.keys() & mp_b.keys())
         mp_a.update(mp_b)
         return res_a and res_b, mp_a
-    elif type(pattern) is Const and type(tree) is Const and pattern.value == tree.value:
+    elif type(pattern) is Const and type(tree) is Const and \
+            pattern.value == tree.value:
         return True, {}
     else:
         return False, {}
@@ -250,22 +253,22 @@
         return 'Const {}'.format(self.value)
 
 
-# Function calling:
 class Call(Expression):
+    """ Call a function with some arguments """
     def __init__(self, f, arguments):
         self.f = f
-        assert type(f) is Function
         self.arguments = arguments
 
     def __repr__(self):
         args = ', '.join([str(arg) for arg in self.arguments])
-        return '{}({})'.format(self.f.name, args)
+        return '{}({})'.format(self.f, args)
 
 
 # Data operations
 class Binop(Expression):
     """ Generic binary operation """
     ops = ['+', '-', '*', '/', '|', '&', '<<', '>>']
+
     def __init__(self, value1, operation, value2):
         assert operation in Binop.ops
         self.a = value1
@@ -278,11 +281,12 @@
 
 
 def Add(a, b):
-    """ Convenience call """
+    """ Add a and b """
     return Binop(a, '+', b)
 
 
 def Sub(a, b):
+    """ Substract b from a """
     return Binop(a, '-', b)
 
 
@@ -341,6 +345,7 @@
 
 
 class Mem(Expression):
+    """ Memory access """
     def __init__(self, e):
         self.e = e
 
@@ -354,6 +359,7 @@
 
 
 class Move(Statement):
+    """ Move source to destination """
     def __init__(self, dst, src):
         self.dst = dst
         self.src = src
@@ -400,9 +406,11 @@
 
 
 class CJump(LastStatement):
+    """ Conditional jump to true or false labels. """
     conditions = ['==', '<', '>', '>=', '<=', '!=']
+
     def __init__(self, a, cond, b, lab_yes, lab_no):
-        assert cond in CJump.conditions 
+        assert cond in CJump.conditions
         self.a = a
         self.cond = cond
         self.b = b
@@ -412,26 +420,28 @@
     lab_no = property(lambda s: s.Targets[1])
 
     def __repr__(self):
-        return 'IF {} {} {} THEN {} ELSE {}'.format(self.a, self.cond, self.b, self.lab_yes, self.lab_no)
+        return 'IF {} {} {} THEN {} ELSE {}'\
+               .format(self.a, self.cond, self.b, self.lab_yes, self.lab_no)
 
 
 # Constructing IR:
 
 class NamedClassGenerator:
-   def __init__(self, prefix, cls):
-      self.prefix = prefix
-      self.cls = cls
-      def NumGen():
-         a = 0
-         while True:
-            yield a
-            a = a + 1
-      self.nums = NumGen()
+    def __init__(self, prefix, cls):
+        self.prefix = prefix
+        self.cls = cls
 
-   def gen(self, prefix=None):
-      if not prefix:
-         prefix = self.prefix
-      return self.cls('{0}{1}'.format(prefix, self.nums.__next__()))
+        def NumGen():
+            a = 0
+            while True:
+                yield a
+                a = a + 1
+        self.nums = NumGen()
+
+    def gen(self, prefix=None):
+        if not prefix:
+            prefix = self.prefix
+        return self.cls('{0}{1}'.format(prefix, self.nums.__next__()))
 
 
 class Builder:
--- a/python/target/arminstructions.py	Fri Dec 06 12:45:02 2013 +0100
+++ b/python/target/arminstructions.py	Fri Dec 06 13:50:38 2013 +0100
@@ -746,6 +746,7 @@
     def __repr__(self):
         return '{} sp, sp, {}'.format(self.mnemonic, self.imm7 << 2)
 
+
 @instruction
 class AddSp(addspsp_base):
     mnemonic = 'add'
--- a/python/target/arminstructionselector.py	Fri Dec 06 12:45:02 2013 +0100
+++ b/python/target/arminstructionselector.py	Fri Dec 06 13:50:38 2013 +0100
@@ -2,7 +2,8 @@
 from ppci.irmach import AbstractInstruction as makeIns
 from .basetarget import Label, Comment, Alignment, LabelRef, DebugInfo, Nop
 from .instructionselector import InstructionSelector
-from .arminstructions import Orr, Lsl, Str2, Ldr2, Ldr3, B, Bl, Bgt, Blt, Beq
+from .arminstructions import Orr, Lsl, Str2, Ldr2, Ldr3
+from .arminstructions import B, Bl, Bgt, Blt, Beq, Bne
 from .arminstructions import Mov2, Mov3
 from .arminstructions import Add, Sub, Cmp, Sub2, Add2, Mul
 from .basetarget import Imm8, Imm7, Imm3
@@ -94,7 +95,7 @@
                 self.munchStm(m)
                 if isinstance(loc, ir.Temp):
                     reguses.append(loc)
-            self.emit(Bl(LabelRef(e.f.name)), src=reguses, dst=[self.frame.rv])
+            self.emit(Bl(LabelRef(e.f)), src=reguses, dst=[self.frame.rv])
             d = self.newTmp()
             self.move(d, self.frame.rv)
             return d
@@ -133,7 +134,7 @@
             ntgt = self.targets[s.lab_no]
             ytgt = self.targets[s.lab_yes]
             jmp_ins = makeIns(B(LabelRef(s.lab_no.name)), jumps=[ntgt])
-            opnames = {'<': Blt, '>':Bgt, '==':Beq}
+            opnames = {'<': Blt, '>':Bgt, '==':Beq, '!=':Bne}
             op = opnames[s.cond](LabelRef(s.lab_yes.name))
             self.emit(op, jumps=[ytgt, jmp_ins])  # Explicitely add fallthrough
             self.emit2(jmp_ins)
--- a/python/zcc.py	Fri Dec 06 12:45:02 2013 +0100
+++ b/python/zcc.py	Fri Dec 06 13:50:38 2013 +0100
@@ -71,6 +71,7 @@
             ircode.dump()
 
         # Code generation:
+        logging.info('Starting code generation for {}'.format(ircode))
         cg.generate(ircode, outs)
     # TODO: fixup references, do this in another way?
     outs.backpatch()