# HG changeset patch # User Windel Bouwman # Date 1372004598 -7200 # Node ID d77cb5962cc563e52bd99b554a671dc11fa494d3 # Parent de3a68f677a5914e1939ba8b2c22bf3ae88deaf1 Added some handcoded arm code generation diff -r de3a68f677a5 -r d77cb5962cc5 python/arm_cm3.py --- a/python/arm_cm3.py Fri Jun 21 15:01:08 2013 +0200 +++ b/python/arm_cm3.py Sun Jun 23 18:23:18 2013 +0200 @@ -1,11 +1,15 @@ +import struct, types from target import Register, Instruction, Target from asmnodes import ASymbol, ANumber from ppci import CompilerError -import struct, types +import ir def u16(h): return struct.pack('=|<=|<>|>|<|{|}'), + ('LEESTEKEN', r'==|[\.,=:;\-+*\[\]/\(\)]|>=|<=|<>|>|<|{|}|&|\^|\|'), ('STRING', r"'.*?'") ] tok_re = '|'.join('(?P<%s>%s)' % pair for pair in tok_spec) @@ -43,7 +43,7 @@ if typ == 'NEWLINE': line_start = pos line += 1 - elif typ == 'COMMENT': + elif typ == 'COMMENTS': pass elif typ == 'LONGCOMMENTBEGIN': incomment = True @@ -73,9 +73,9 @@ pos = mo.end() mo = gettok(s, pos) if pos != len(s): - col = pos - line_start - pos = line - raise CompilerError('Unexpected character {0}'.format(s[pos]), pos) + col = pos - line_start + loc = SourceLocation(line, col, 1) + raise CompilerError('Unexpected character "{0}"'.format(s[pos]), loc) loc = SourceLocation(line, 0, 0) yield Token('END', '', loc) diff -r de3a68f677a5 -r d77cb5962cc5 python/ir/basicblock.py --- a/python/ir/basicblock.py Fri Jun 21 15:01:08 2013 +0200 +++ b/python/ir/basicblock.py Sun Jun 23 18:23:18 2013 +0200 @@ -10,17 +10,21 @@ i.parent = self self.instructions.append(i) addIns = addInstruction + def replaceInstruction(self, i1, i2): idx = self.instructions.index(i1) i1.parent = None i1.delete() i2.parent = self self.instructions[idx] = i2 + def removeInstruction(self, i): i.parent = None self.instructions.remove(i) + def getInstructions(self): - return self.instructions + return self.instructions + def setInstructions(self, ins): for i in self.instructions: i.parent = None @@ -28,6 +32,7 @@ for i in self.instructions: i.parent = self Instructions = property(getInstructions, setInstructions) + def getLastIns(self): return self.instructions[-1] LastInstruction = property(getLastIns) diff -r de3a68f677a5 -r d77cb5962cc5 python/ir/builder.py --- a/python/ir/builder.py Fri Jun 21 15:01:08 2013 +0200 +++ b/python/ir/builder.py Sun Jun 23 18:23:18 2013 +0200 @@ -1,4 +1,4 @@ -from . import Value, BasicBlock, Function +from . import Value, BasicBlock, Function, Variable class NameGenerator: def __init__(self, prefix): @@ -41,16 +41,26 @@ bb = self.newBBint() self.fn.addBB(bb) return bb + def setModule(self, m): self.m = m + def newFunction(self, name): f = Function(name) self.m.addFunc(f) return f + + def newVariable(self, name): + v = Variable(name) + self.m.addVariable(v) + return v + def setFunction(self, f): self.fn = f + def setBB(self, bb): self.bb = bb + def addIns(self, i): if not self.bb: raise Exception('No basic block') diff -r de3a68f677a5 -r d77cb5962cc5 python/ir/function.py --- a/python/ir/function.py Fri Jun 21 15:01:08 2013 +0200 +++ b/python/ir/function.py Sun Jun 23 18:23:18 2013 +0200 @@ -5,14 +5,19 @@ self.name = name self.bbs = [] self.entry = None + def __repr__(self): return 'Function {0}'.format(self.name) + def addBB(self, bb): self.bbs.append(bb) bb.parent = self + addBasicBlock = addBB + def removeBasicBlock(self, bb): self.bbs.remove(bb) bb.parent = None + def getBBs(self): return self.bbs BasicBlocks = property(getBBs) diff -r de3a68f677a5 -r d77cb5962cc5 python/ir/instruction.py --- a/python/ir/instruction.py Fri Jun 21 15:01:08 2013 +0200 +++ b/python/ir/instruction.py Sun Jun 23 18:23:18 2013 +0200 @@ -1,6 +1,7 @@ from .basicblock import BasicBlock from .function import Function + class Value: """ Temporary SSA value (value that is assigned only once! """ def __init__(self, name): @@ -13,10 +14,13 @@ def IsUsed(self): return len(self.used_by) > 0 +class Variable(Value): + pass + class Use: def __init__(self, user, val): self.user = user - assert type(val) is Value + assert isinstance(val, Value) self.val = val self.val.used_by.append(self.user) def delete(self): @@ -130,7 +134,7 @@ def __init__(self, location, value): super().__init__() assert type(value) is Value - assert type(location) is Value, "Location must be a value" + assert isinstance(location, Value), "Location must be a value" self.value = value self.addDef(value) self.location = location @@ -142,7 +146,7 @@ def __init__(self, location, value): super().__init__() assert type(value) is Value - assert type(location) is Value, "Location must be a value" + assert isinstance(location, Value), "Location must be a value" self.location = location self.value = value self.addUse(value) diff -r de3a68f677a5 -r d77cb5962cc5 python/ir/module.py --- a/python/ir/module.py Fri Jun 21 15:01:08 2013 +0200 +++ b/python/ir/module.py Sun Jun 23 18:23:18 2013 +0200 @@ -7,34 +7,51 @@ def __init__(self, name): self.name = name self.funcs = [] + self.variables = [] + def __repr__(self): return 'IR-module [{0}]'.format(self.name) + def getInstructions(self): ins = [] for bb in self.BasicBlocks: ins += bb.Instructions return ins Instructions = property(getInstructions) + def getBBs(self): bbs = [] for f in self.Functions: bbs += f.BasicBlocks return bbs + BasicBlocks = property(getBBs) def addFunc(self, f): self.funcs.append(f) - def getFuncs(self): + addFunction = addFunc + + def addVariable(self, v): + self.variables.append(v) + + def getVariables(self): + return self.variables + Variables = property(getVariables) + + def getFunctions(self): return self.funcs - Functions = property(getFuncs) + Functions = property(getFunctions) + def dump(self): print(self) + for v in self.Variables: + print(' ', v) for fn in self.Functions: print(fn) for bb in fn.BasicBlocks: print(' ', bb) for ins in bb.Instructions: print(' ', ins) - print('END') + def dumpgv(self, outf): outf.write('digraph G \n{\n') for f in self.Functions: diff -r de3a68f677a5 -r d77cb5962cc5 python/stm32f4/blink.c3 --- a/python/stm32f4/blink.c3 Fri Jun 21 15:01:08 2013 +0200 +++ b/python/stm32f4/blink.c3 Sun Jun 23 18:23:18 2013 +0200 @@ -39,7 +39,7 @@ TIM2->CR1 |= TIM_CR1_ARPE | TIM_CR1_CEN; TIM2->EGR = 1; - while(1); */ + while(true) {} } diff -r de3a68f677a5 -r d77cb5962cc5 python/target.py --- a/python/target.py Fri Jun 21 15:01:08 2013 +0200 +++ b/python/target.py Sun Jun 23 18:23:18 2013 +0200 @@ -16,7 +16,7 @@ class Instruction: def encode(self): - raise NotImplementedError('TODO') + raise NotImplementedError('Instruction {0} has no encode yet, TODO'.format(type(self))) class Target: def __init__(self, name, desc=''): diff -r de3a68f677a5 -r d77cb5962cc5 python/testc3.py --- a/python/testc3.py Fri Jun 21 15:01:08 2013 +0200 +++ b/python/testc3.py Sun Jun 23 18:23:18 2013 +0200 @@ -56,28 +56,6 @@ """ -testsrc2 = """ -package test2; - -function void tst() -{ - var int a, b; - a = 2 * 33 - 12; - b = a * 2 + 13; - a = b + a; - if (a > b and b == 3) - { - var int x = a; - x = b * 2 - a; - a = x*x; - } - else - { - a = b + a; - } -} - -""" def c3compile(src, diag): # Structures: @@ -101,6 +79,11 @@ c3compile(testsrc, diag) class testLexer(unittest.TestCase): + def testUnexpectedCharacter(self): + snippet = """ var s \u6c34 """ + with self.assertRaises(ppci.CompilerError): + list(c3.lexer.tokenize(snippet)) + def testBlockComment(self): snippet = """ /* Demo */ @@ -108,6 +91,7 @@ """ toks = ['var', 'ID', 'ID', '=', 'NUMBER', ';', 'END'] self.assertSequenceEqual([tok.typ for tok in c3.lexer.tokenize(snippet)], toks) + def testBlockCommentMultiLine(self): snippet = """ /* Demo @@ -138,8 +122,8 @@ self.diag.clear() ir = self.builder.build(snippet) assert len(self.diag.diags) == 2 - assert self.diag.diags[0].loc.row == 5 - assert self.diag.diags[1].loc.row == 6 + self.assertEqual(5, self.diag.diags[0].loc.row) + self.assertEqual(6, self.diag.diags[1].loc.row) def testExpressions(self): snippet = """ @@ -161,17 +145,20 @@ self.assertEqual(self.diag.diags[1].loc.row, 9) self.assertEqual(self.diag.diags[2].loc.row, 10) self.assertFalse(ircode) + def testEmpty(self): snippet = """ package A """ ircode = self.builder.build(snippet) self.assertFalse(ircode) + def testEmpty2(self): snippet = "" self.diag.clear() ircode = self.builder.build(snippet) self.assertFalse(ircode) + def testRedefine(self): snippet = """ package test; @@ -184,6 +171,7 @@ self.assertFalse(ircode) self.assertEqual(len(self.diag.diags), 1) self.assertEqual(self.diag.diags[0].loc.row, 5) + def testWhile(self): snippet = """ package tstwhile; @@ -196,6 +184,14 @@ i = i + 3; a = a + i; } + + while(true) + { + } + + while(false) + { + } } """ ircode = self.builder.build(snippet) @@ -228,11 +224,34 @@ if not ircode: self.diag.printErrors(snippet) self.assertTrue(ircode) + def test2(self): - # testsrc2 is valid code: - self.diag.clear() - ir = self.builder.build(testsrc2) - self.assertTrue(ir) + # testsrc2 is valid code: + testsrc2 = """ + package test2; + + function void tst() + { + var int a, b; + a = 2 * 33 - 12; + b = a * 2 + 13; + a = b + a; + if (a > b and b == 3) + { + var int x = a; + x = b * 2 - a; + a = x*x; + } + else + { + a = b + a; + } + } + + """ + self.diag.clear() + ir = self.builder.build(testsrc2) + self.assertTrue(ir) if __name__ == '__main__': do() diff -r de3a68f677a5 -r d77cb5962cc5 python/zcc.py --- a/python/zcc.py Fri Jun 21 15:01:08 2013 +0200 +++ b/python/zcc.py Sun Jun 23 18:23:18 2013 +0200 @@ -1,13 +1,19 @@ #!/usr/bin/python import sys, os, argparse -import c3, ppci +import c3, ppci, codegen +import arm_cm3 +import codegenarm +import outstream +# Parse arguments: parser = argparse.ArgumentParser(description='lcfos Compiler') parser.add_argument('source', type=argparse.FileType('r'), help='the source file to build') +parser.add_argument('-d', '--dumpir', action='store_true', help="Dump IR-code") +parser.add_argument('-o', '--output', help='Output file', metavar='filename') args = parser.parse_args() -# Building: +# Front end: src = args.source.read() diag = ppci.DiagnosticsManager() c3b = c3.Builder(diag) @@ -17,15 +23,23 @@ diag.printErrors(src) sys.exit(1) -# optionally run passes here: -# TODO +if args.dumpir: + ircode.dump() + +# Code generation: + +#cg = codegen.CodeGenerator(arm_cm3.armtarget) +outs = outstream.TextOutputStream() +cg = codegenarm.ArmCodeGenerator(outs) +obj = cg.generate(ircode) -print('stage 3: Code generation') -asmWriter = core.AsmWriter() -asmWriter.printModule(module) +if args.dumpir: + outs.dump() -# Generate code: -bitcodeWriter = core.BitcodeWriter() -with open(args.source + '.bc', 'wb') as f: - bitcodeWriter.WriteModuleToFile(module, f) +if args.output: + output_filename = args.output +else: + output_filename = 'lc.output' +# TODO: store data +