# HG changeset patch # User Windel Bouwman # Date 1386334238 -3600 # Node ID 0615b53087100c853fd0819423d060a35aaa009d # Parent fa99f36fabb52a1ba4643b25f28e2ef182a45142 Updated docs diff -r fa99f36fabb5 -r 0615b5308710 doc/compiler.rst --- 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 diff -r fa99f36fabb5 -r 0615b5308710 doc/ir.rst --- 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 + diff -r fa99f36fabb5 -r 0615b5308710 kernel/make.py --- 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) diff -r fa99f36fabb5 -r 0615b5308710 kernel/syscall.c3 --- 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) diff -r fa99f36fabb5 -r 0615b5308710 python/ppci/c3/__init__.py --- 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 diff -r fa99f36fabb5 -r 0615b5308710 python/ppci/c3/analyse.py --- 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)) diff -r fa99f36fabb5 -r 0615b5308710 python/ppci/c3/builder.py --- 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 diff -r fa99f36fabb5 -r 0615b5308710 python/ppci/c3/codegenerator.py --- 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)) diff -r fa99f36fabb5 -r 0615b5308710 python/ppci/c3/lexer.py --- 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) diff -r fa99f36fabb5 -r 0615b5308710 python/ppci/codegen/registerallocator.py --- 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) diff -r fa99f36fabb5 -r 0615b5308710 python/ppci/errors.py --- 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: diff -r fa99f36fabb5 -r 0615b5308710 python/ppci/ir.py --- 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: diff -r fa99f36fabb5 -r 0615b5308710 python/target/arminstructions.py --- 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' diff -r fa99f36fabb5 -r 0615b5308710 python/target/arminstructionselector.py --- 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) diff -r fa99f36fabb5 -r 0615b5308710 python/zcc.py --- 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()