Mercurial > lcfOS
changeset 158:9683a4cd848f
Added some functions for code generation
author | Windel Bouwman |
---|---|
date | Fri, 08 Mar 2013 16:52:44 +0100 |
parents | 8f3924b6076e |
children | 5e1dd04cb61c |
files | python/c3/astnodes.py python/c3/codegenerator.py python/c3/parser.py python/ir/__init__.py python/ir/instruction.py python/ir/module.py python/ir/value.py python/testc3.py python/x86.py |
diffstat | 9 files changed, 161 insertions(+), 50 deletions(-) [+] |
line wrap: on
line diff
--- a/python/c3/astnodes.py Sun Mar 03 18:14:35 2013 +0100 +++ b/python/c3/astnodes.py Fri Mar 08 16:52:44 2013 +0100 @@ -145,7 +145,8 @@ return 'COMPOUND STATEMENT' class EmptyStatement(Node): - pass + def __repr__(self): + return 'NOP' class ReturnStatement(Node): def __init__(self, expr): @@ -168,7 +169,7 @@ return 'CALL {0} '.format(self.proc) class IfStatement(Node): - def __init__(self, condition, truestatement, falsestatement=None): + def __init__(self, condition, truestatement, falsestatement): self.condition = condition self.truestatement = truestatement self.falsestatement = falsestatement
--- a/python/c3/codegenerator.py Sun Mar 03 18:14:35 2013 +0100 +++ b/python/c3/codegenerator.py Fri Mar 08 16:52:44 2013 +0100 @@ -20,36 +20,73 @@ def genFunction(m, fnc): ft = genType(fnc.typ) f = ir.Function(fnc.name, ft) - m.Globals.append(f) + m.Functions.append(f) bb = ir.BasicBlock() f.BasicBlocks.append(bb) genCode(bb, fnc.body) + bb.Instructions.append(ir.RetInstruction()) def genCode(bb, code): if type(code) is astnodes.CompoundStatement: for s in code.statements: genCode(bb, s) elif type(code) is astnodes.Assignment: - genCode(bb, code.rval) - print('assign') + genExprCode(bb, code.rval) + # TODO: store elif type(code) is astnodes.IfStatement: - genCode(bb, code.condition) + genExprCode(bb, code.condition) + # TODO: implement IF. + t1, t2 = 1,2 + b = ir.BranchInstruction(t1, t2) + bb.Instructions.append(b) genCode(bb, code.truestatement) - print('If!') - elif type(code) is astnodes.Binop: - genCode(bb, code.a) - genCode(bb, code.b) - a = 1 - b = 2 - if code.op == '+': - bb.Instructions.append(ir.AddInstruction(a, b)) + genCode(bb, code.falsestatement) + elif type(code) is astnodes.ProcedureCall: + ins = ir.CallInstruction('f', []) + bb.Instructions.append(ins) + elif type(code) is astnodes.EmptyStatement: + pass + elif type(code) is astnodes.ReturnStatement: + bb.Instructions.append(ir.RetInstruction()) + else: + print('Unknown stmt:', code) + +def NumGen(): + a = 0 + while True: + yield a + a = a + 1 + +nums = NumGen() +def unique(): + return 'tmp{0}'.format(nums.__next__()) + +def genExprCode(bb, code): + if type(code) is astnodes.Binop: + a = genExprCode(bb, code.a) + b = genExprCode(bb, code.b) + ops = {'+': 'fadd', '-': 'fsub', '*':'fmul', '/':'fdiv'} + if code.op in ops: + op = ops[code.op] + tmp = unique() + ins = ir.BinaryOperator(tmp, op, a, b) + bb.Instructions.append(ins) + return tmp else: - bb.Instructions.append(ir.BinaryOperator(code.op, a, b)) + print('Unknown binop') + bb.Instructions.append(ir.BinaryOperator('unk2', code.op, a, b)) + return 'unk2' elif type(code) is astnodes.Constant: - print('CST') - bb.Instructions.append(ir.ImmLoadInstruction(code.value)) + tmp = unique() + bb.Instructions.append(ir.LoadInstruction(tmp, code.value)) + return tmp + elif type(code) is astnodes.VariableUse: + tmp = unique() + ins = ir.LoadInstruction(tmp, code.target.name) + return tmp else: - print('Unknown:', code) + print('Unknown expr:', code) + return 'unk' def genType(t): return ir.Type()
--- a/python/c3/parser.py Sun Mar 03 18:14:35 2013 +0100 +++ b/python/c3/parser.py Fri Mar 08 16:52:44 2013 +0100 @@ -111,7 +111,7 @@ # Statements: def parseAssignment(self, lval): - lval = astnodes.VariableUse(lval) + lval = self.sema.actOnVariableUse(lval) self.Consume('=') rval = self.parseExpression() self.Consume(';') @@ -136,7 +136,7 @@ if self.hasConsumed('else'): no = self.parseCompoundStatement() return astnodes.IfStatement(condition, yes, no) - return astnodes.IfStatement(condition, yes) + return astnodes.IfStatement(condition, yes, astnodes.EmptyStatement()) def parseWhileStatement(self): self.Consume('while') @@ -167,11 +167,11 @@ return self.parseWhileStatement() elif self.Peak == '{': return self.parseCompoundStatement() - elif self.Peak == ';': - self.Consume(';') + elif self.hasConsumed(';'): return astnodes.EmptyStatement() elif self.Peak == 'var': - return self.parseVarDef() + self.parseVarDef() + return astnodes.EmptyStatement() elif self.Peak == 'return': return self.parseReturnStatement() elif self.Peak == 'ID':
--- a/python/ir/__init__.py Sun Mar 03 18:14:35 2013 +0100 +++ b/python/ir/__init__.py Fri Mar 08 16:52:44 2013 +0100 @@ -2,6 +2,7 @@ from .value import Value from .module import Type, FunctionType from .module import i8, i16, i32, void -from .instruction import AddInstruction, BinaryOperator, ImmLoadInstruction +from .module import printIr +from .instruction import *
--- a/python/ir/instruction.py Sun Mar 03 18:14:35 2013 +0100 +++ b/python/ir/instruction.py Fri Mar 08 16:52:44 2013 +0100 @@ -1,34 +1,44 @@ - -def Enum(**enums): - return type('Enum', (), enums) class Instruction: """ Base class for all instructions. """ pass +# Function calling: class CallInstruction(Instruction): def __init__(self, callee, arguments): super().__init__() self.callee = callee self.arguments = arguments + def __repr__(self): + return 'CALL {0}'.format(self.callee) -BinOps = Enum(Add=1, Sub=2, Mul=3) +class RetInstruction(Instruction): + def __repr__(self): + return 'RET' class BinaryOperator(Instruction): - def __init__(self, operation, value1, value2): + def __init__(self, name, operation, value1, value2): assert value1 assert value2 #print('operation is in binops:', operation in BinOps) # Check types of the two operands: + self.name = name self.value1 = value1 self.value2 = value2 self.operation = operation - -class AddInstruction(BinaryOperator): - def __init__(self, a, b): - super().__init__('add', a, b) + def __repr__(self): + return '{0} = {1} {2}, {3}'.format(self.name, self.operation, self.value1, self.value2) -class ImmLoadInstruction(Instruction): - def __init__(self, value): +class LoadInstruction(Instruction): + def __init__(self, name, value): self.value = value + self.name = name + def __repr__(self): + return 'load {0} = {1}'.format(self.name, self.value) +class BranchInstruction(Instruction): + def __init__(self, t1, t2): + self.t1 = t1 + self.t2 = t2 + def __repr__(self): + return 'BRANCH {0}'.format(self.t1)
--- a/python/ir/module.py Sun Mar 03 18:14:35 2013 +0100 +++ b/python/ir/module.py Fri Mar 08 16:52:44 2013 +0100 @@ -33,11 +33,12 @@ def __init__(self, name): self.name = name self.functions = [] # Do functions come out of symbol table? - self.globals_ = [] # TODO: are globals in symbol table? + self.globs = [] # TODO: are globals in symbol table? self.symtable = SymbolTable() - Globals = property(lambda self: self.globals_) + Globals = property(lambda self: self.globs) Functions = property(lambda self: self.functions) - Identifier = property(lambda self: self.identifier) + def __repr__(self): + return 'IR-mod {0}'.format(self.name) class Argument: def __init__(self, argtype, name, function): @@ -57,6 +58,8 @@ Arguments = property(lambda self: self.arguments) ReturnType = property(lambda self: self.functiontype.returnType) FunctionType = property(lambda self: self.functiontype) + def __repr__(self): + return 'FUNC {0}'.format(self.name) class BasicBlock: """ @@ -66,8 +69,20 @@ def __init__(self): super().__init__() self.instructions = [] - self.name = None + self.label = None def getInstructions(self): return self.instructions Instructions = property(getInstructions) +def printIr(md): + print(md) + for g in md.Globals: + print(g) + for f in md.Functions: + print(f) + for bb in f.BasicBlocks: + print('{0}:'.format(bb)) + for ins in bb.Instructions: + print(' {0}'.format(ins)) + print() +
--- a/python/ir/value.py Sun Mar 03 18:14:35 2013 +0100 +++ b/python/ir/value.py Fri Mar 08 16:52:44 2013 +0100 @@ -14,6 +14,8 @@ return self.name = name Name = property(getName, setName) + def __repr__(self): + return 'VALUE {0}'.format(self.name) class Constant(Value): def __init__(self, value, vty):
--- a/python/testc3.py Sun Mar 03 18:14:35 2013 +0100 +++ b/python/testc3.py Fri Mar 08 16:52:44 2013 +0100 @@ -1,4 +1,5 @@ -import c3, time, ppci, x86 +import c3 +import time, ppci, x86, ir testsrc = """ package test; @@ -62,14 +63,8 @@ al = c3.Analyzer(diag) cg = c3.CodeGenerator() x86gen = x86.X86CodeGen(diag) - t1 = time.time() p.parseSource(src) - t2 = time.time() - print('parsetime: {0} [s]'.format(t2 - t1)) - t2 = time.time() tc.checkPackage(sema.mod) - t3 = time.time() - print('checktime: {0} [s]'.format(t3 - t2)) print('{0} errors'.format(len(diag.diags))) for d in diag.diags: @@ -80,12 +75,18 @@ ok = len(diag.diags) == 0 if ok: - print('Generating code') + print('Generating ir-code') i = cg.gencode(sema.mod) + #ir.printIr(i) + + print('generating x86 code') - print(i) - print(i.Globals) x86gen.genBin(i) + + with open('dummydummy.asm', 'w') as f: + f.write('bits 64\n') + for a in x86gen.asm: + f.write(str(a) + '\n') else: print('Not generating code')
--- a/python/x86.py Sun Mar 03 18:14:35 2013 +0100 +++ b/python/x86.py Fri Mar 08 16:52:44 2013 +0100 @@ -1,9 +1,53 @@ import ppci +import ir + +class AsmLabel: + def __init__(self, lab): + self.lab = lab + def __repr__(self): + return '{0}:'.format(self.lab) + +class Op: + def __init__(self, op, a, b): + self.op = op + self.a = a + self.b = b + def __repr__(self): + return '{0} {1}, {2}'.format(self.op, self.a, self.b) class X86CodeGen: def __init__(self, diag): self.diag = diag + def emit(self, i): + self.asm.append(i) + def genBin(self, i): - print(i) + self.asm = [] + self.genModule(i) + def genModule(self, m): + for g in m.Globals: + self.emit(AsmLabel(g.name)) + # Ignore types for now .. + self.emit('dw 0') + for f in m.Functions: + self.genFunction(f) + def genFunction(self, f): + self.emit('global {0}'.format(f.name)) + self.emit(AsmLabel(f.name)) + for bb in f.BasicBlocks: + self.genBB(bb) + def genBB(self, bb): + for i in bb.Instructions: + self.genIns(i) + def genIns(self, i): + if type(i) is ir.BinaryOperator: + if i.operation == 'fadd': + r = 'rax' + self.emit(Op('add', r, '11')) + elif type(i) is ir.RetInstruction: + self.emit('ret') + else: + print('Unknown ins', i) +