Mercurial > lcfOS
comparison python/c3/codegenerator.py @ 268:5ec7580976d9
Op naar tree-IR
author | Windel Bouwman |
---|---|
date | Wed, 14 Aug 2013 20:12:40 +0200 |
parents | 444b9df2ed99 |
children | 5f8c04a8d26b |
comparison
equal
deleted
inserted
replaced
267:e7c8f7eb3f59 | 268:5ec7580976d9 |
---|---|
3 from . import astnodes | 3 from . import astnodes |
4 from .scope import boolType, intType | 4 from .scope import boolType, intType |
5 from ppci import CompilerError | 5 from ppci import CompilerError |
6 from .typecheck import theType | 6 from .typecheck import theType |
7 | 7 |
8 tmpnames = {'+':'add', '-':'sub', '*': 'mul', '/':'div', '|':'or', \ | |
9 '&':'and', '>>':'shl', '<<':'shr'} | |
10 | 8 |
11 class CodeGenerator: | 9 class CodeGenerator(ir.Builder): |
12 """ Generates intermediate code from a package """ | 10 """ Generates intermediate code from a package """ |
13 def __init__(self): | 11 def __init__(self): |
14 self.logger = logging.getLogger('c3cgen') | 12 self.logger = logging.getLogger('c3cgen') |
15 | 13 |
16 def gencode(self, pkg): | 14 def gencode(self, pkg): |
15 self.prepare() | |
17 assert type(pkg) is astnodes.Package | 16 assert type(pkg) is astnodes.Package |
18 self.logger.info('Generating ir-code for {}'.format(pkg.name)) | 17 self.logger.info('Generating ir-code for {}'.format(pkg.name)) |
19 self.varMap = {} # Maps variables to storage locations. | 18 self.varMap = {} # Maps variables to storage locations. |
20 self.funcMap = {} | 19 self.funcMap = {} |
21 self.builder = ir.Builder() | 20 self.m = ir.Module(pkg.name) |
22 m = ir.Module(pkg.name) | |
23 self.builder.setModule(m) | |
24 self.genModule(pkg) | 21 self.genModule(pkg) |
25 return m | 22 return self.m |
26 | 23 |
27 # inner helpers: | 24 # inner helpers: |
28 def genModule(self, pkg): | 25 def genModule(self, pkg): |
29 # Take care of forward declarations: | 26 # Take care of forward declarations: |
30 for s in pkg.innerScope.Functions: | 27 for s in pkg.innerScope.Functions: |
31 f = self.builder.newFunction(s.name) | 28 f = self.newFunction(s.name) |
32 self.funcMap[s] = f | 29 self.funcMap[s] = f |
33 for s in pkg.innerScope: | 30 for s in pkg.innerScope: |
34 if type(s) is astnodes.Variable: | 31 if type(s) is astnodes.Variable: |
35 v = self.builder.newTmp(s.name) | 32 #v = self.builder.newTmp(s.name) |
36 #self.builder.addIns(ir.Alloc(v)) | 33 self.varMap[s] = self.newTemp() |
37 self.varMap[s] = v | 34 pass |
38 elif type(s) is astnodes.Function: | 35 elif type(s) is astnodes.Function: |
39 # TODO: handle arguments | 36 self.genFunction(s) |
40 f = self.funcMap[s] | 37 else: |
41 self.builder.setFunction(f) | 38 raise NotImplementedError(str(s)) |
42 bb = self.builder.newBB() | |
43 f.entry = bb | |
44 self.builder.setBB(bb) | |
45 # generate room for locals: | |
46 | 39 |
47 for sym in s.innerScope: | 40 def genFunction(self, fn): |
48 #print(sym, sym.isParameter) | 41 # TODO: handle arguments |
49 # TODO: handle parameters different | 42 f = self.funcMap[fn] |
50 v = self.builder.newTmp(sym.name) | 43 self.setFunction(f) |
51 self.builder.addIns(ir.Alloc(v)) | 44 # generate room for locals: |
52 self.varMap[sym] = v | |
53 | 45 |
54 self.genCode(s.body) | 46 for sym in fn.innerScope: |
55 # TODO handle return? | 47 # TODO: handle parameters different |
56 self.builder.addIns(ir.Return()) | 48 v = self.newTemp() |
57 self.builder.setFunction(None) | 49 # TODO: make this ssa here?? |
58 else: | 50 self.varMap[sym] = v |
59 print(s) | 51 |
52 self.genCode(fn.body) | |
53 # TODO handle return? | |
54 self.emit(ir.Return(ir.Const(0))) | |
55 self.setFunction(None) | |
60 | 56 |
61 def genCode(self, code): | 57 def genCode(self, code): |
62 assert isinstance(code, astnodes.Statement) | 58 assert isinstance(code, astnodes.Statement) |
63 self.builder.setLoc(code.loc) | 59 self.setLoc(code.loc) |
64 if type(code) is astnodes.CompoundStatement: | 60 if type(code) is astnodes.CompoundStatement: |
65 for s in code.statements: | 61 for s in code.statements: |
66 self.genCode(s) | 62 self.genCode(s) |
67 elif type(code) is astnodes.Assignment: | 63 elif type(code) is astnodes.Assignment: |
68 re = self.genExprCode(code.rval) | 64 rval = self.genExprCode(code.rval) |
69 loc = self.genExprCode(code.lval) | 65 lval = self.genExprCode(code.lval) |
70 self.builder.addIns(ir.Store(loc, re)) | 66 self.emit(ir.Move(lval, rval)) |
71 elif type(code) is astnodes.ExpressionStatement: | 67 elif type(code) is astnodes.ExpressionStatement: |
72 self.genExprCode(code.ex) | 68 self.genExprCode(code.ex) |
73 elif type(code) is astnodes.IfStatement: | 69 elif type(code) is astnodes.IfStatement: |
74 bbtrue = self.builder.newBB() | 70 bbtrue = self.newBlock() |
75 bbfalse = self.builder.newBB() | 71 bbfalse = self.newBlock() |
76 te = self.builder.newBB() | 72 te = self.newBlock() |
77 self.genCondCode(code.condition, bbtrue, bbfalse) | 73 self.genCondCode(code.condition, bbtrue, bbfalse) |
78 self.builder.setBB(bbtrue) | 74 self.setBlock(bbtrue) |
79 self.genCode(code.truestatement) | 75 self.genCode(code.truestatement) |
80 self.builder.addIns(ir.Branch(te)) | 76 self.emit(ir.Jump(te)) |
81 self.builder.setBB(bbfalse) | 77 self.setBlock(bbfalse) |
82 if code.falsestatement: | 78 if code.falsestatement: |
83 self.genCode(code.falsestatement) | 79 self.genCode(code.falsestatement) |
84 self.builder.addIns(ir.Branch(te)) | 80 self.emit(ir.Jump(te)) |
85 self.builder.setBB(te) | 81 self.setBlock(te) |
86 elif type(code) is astnodes.ReturnStatement: | 82 elif type(code) is astnodes.ReturnStatement: |
87 if code.expr: | 83 if code.expr: |
88 re = self.genExprCode(code.expr) | 84 re = self.genExprCode(code.expr) |
89 self.builder.addIns(ir.Return(re)) | 85 self.emit(ir.Return(re)) |
90 else: | 86 else: |
91 self.builder.addIns(ir.Return()) | 87 self.builder.addIns(ir.Return()) |
92 elif type(code) is astnodes.WhileStatement: | 88 elif type(code) is astnodes.WhileStatement: |
93 bbdo = self.builder.newBB() | 89 bbdo = self.newBlock() |
94 bbtest = self.builder.newBB() | 90 bbtest = self.newBlock() |
95 te = self.builder.newBB() | 91 te = self.newBlock() |
96 self.builder.addIns(ir.Branch(bbtest)) | 92 self.emit(ir.Jump(bbtest)) |
97 self.builder.setBB(bbtest) | 93 self.setBlock(bbtest) |
98 self.genCondCode(code.condition, bbdo, te) | 94 self.genCondCode(code.condition, bbdo, te) |
99 self.builder.setBB(bbdo) | 95 self.setBlock(bbdo) |
100 self.genCode(code.statement) | 96 self.genCode(code.statement) |
101 self.builder.addIns(ir.Branch(bbtest)) | 97 self.emit(ir.Jump(bbtest)) |
102 self.builder.setBB(te) | 98 self.setBlock(te) |
103 else: | 99 else: |
104 print('Unknown stmt:', code) | 100 raise NotImplementedError('Unknown stmt {}'.format(code)) |
105 raise NotImplementedError() | |
106 | 101 |
107 def genCondCode(self, expr, bbtrue, bbfalse): | 102 def genCondCode(self, expr, bbtrue, bbfalse): |
108 # Implement sequential logical operators | 103 # Implement sequential logical operators |
109 assert expr.typ == boolType | 104 assert expr.typ == boolType |
110 if type(expr) is astnodes.Binop: | 105 if type(expr) is astnodes.Binop: |
111 if expr.op == 'or': | 106 if expr.op == 'or': |
112 l2 = self.builder.newBB() | 107 l2 = self.newBlock() |
113 self.genCondCode(expr.a, bbtrue, l2) | 108 self.genCondCode(expr.a, bbtrue, l2) |
114 self.builder.setBB(l2) | 109 self.setBlock(l2) |
115 self.genCondCode(expr.b, bbtrue, bbfalse) | 110 self.genCondCode(expr.b, bbtrue, bbfalse) |
116 elif expr.op == 'and': | 111 elif expr.op == 'and': |
117 l2 = self.builder.newBB() | 112 l2 = self.newBlock() |
118 self.genCondCode(expr.a, l2, bbfalse) | 113 self.genCondCode(expr.a, l2, bbfalse) |
119 self.builder.setBB(l2) | 114 self.setBlock(l2) |
120 self.genCondCode(expr.b, bbtrue, bbfalse) | 115 self.genCondCode(expr.b, bbtrue, bbfalse) |
121 elif expr.op in ['==', '>', '<']: | 116 elif expr.op in ['==', '>', '<']: |
122 ta = self.genExprCode(expr.a) | 117 ta = self.genExprCode(expr.a) |
123 tb = self.genExprCode(expr.b) | 118 tb = self.genExprCode(expr.b) |
124 i = ir.ConditionalBranch(ta, expr.op, tb, bbtrue, bbfalse) | 119 self.emit(ir.CJump(ta, expr.op, tb, bbtrue, bbfalse)) |
125 self.builder.addIns(i) | 120 else: |
126 else: | 121 raise NotImplementedError('Unknown condition {}'.format(expr)) |
127 raise NotImlementedError('Unknown condition {0}'.format(expr)) | |
128 elif type(expr) is astnodes.Literal: | 122 elif type(expr) is astnodes.Literal: |
129 if expr.val: | 123 if expr.val: |
130 self.builder.addIns(ir.Branch(bbtrue)) | 124 self.emit(ir.Jump(bbtrue)) |
131 else: | 125 else: |
132 self.builder.addIns(ir.Branch(bbfalse)) | 126 self.emit(ir.Jump(bbfalse)) |
133 else: | 127 else: |
134 print('Unknown cond', expr) | 128 raise NotImplementedError('Unknown cond {}'.format(expr)) |
135 raise NotImplementedError() | |
136 | |
137 def cast_to_rvalue(self, expr, loc): | |
138 """ Cast lvalue to rvalue if required """ | |
139 if hasattr(expr, 'expect_rvalue'): | |
140 # Load value from memory location: | |
141 tmp = self.builder.newTmp() | |
142 i = ir.Load(loc, tmp) | |
143 self.builder.addIns(i) | |
144 return tmp | |
145 if expr.lvalue: | |
146 return loc | |
147 | 129 |
148 def genExprCode(self, expr): | 130 def genExprCode(self, expr): |
149 assert isinstance(expr, astnodes.Expression) | 131 assert isinstance(expr, astnodes.Expression) |
150 if type(expr) is astnodes.Binop: | 132 if type(expr) is astnodes.Binop and expr.op in ir.Binop.ops: |
151 ra = self.genExprCode(expr.a) | |
152 rb = self.genExprCode(expr.b) | |
153 ops = ['+', '-', '*', '/', '|', '&', '<<', '>>'] | |
154 if expr.op in ops: | |
155 tmp = self.builder.newTmp(tmpnames[expr.op]) | |
156 op = expr.op | |
157 ins = ir.BinaryOperator(tmp, op, ra, rb) | |
158 self.builder.addIns(ins) | |
159 return tmp | |
160 else: | |
161 raise NotImplementedError('Unknown {0}'.format(expr)) | |
162 tmp = self.builder.newTmp() | |
163 # TODO | |
164 return tmp | |
165 elif type(expr) is astnodes.Unop: | |
166 ra = self.genExprCode(expr.a) | 133 ra = self.genExprCode(expr.a) |
167 if expr.op == '&': | 134 rb = self.genExprCode(expr.b) |
168 # Address of operator | 135 return ir.Binop(ra, expr.op, rb) |
169 tmp = self.builder.newTmp('addr') | 136 elif type(expr) is astnodes.Unop and expr.op == '&': |
170 return tmp | 137 ra = self.genExprCode(expr.a) |
171 #self.builder.addIns(ins) | 138 # TODO: Make this work? |
172 else: | 139 return ra |
173 raise NotImplementedError('Unknown {0}'.format(expr)) | |
174 elif type(expr) is astnodes.Constant: | |
175 tmp = self.builder.newTmp() | |
176 # TODO | |
177 return tmp | |
178 elif type(expr) is astnodes.VariableUse: | 140 elif type(expr) is astnodes.VariableUse: |
179 loc = self.varMap[expr.target] | 141 return self.varMap[expr.target] |
180 return self.cast_to_rvalue(expr, loc) | |
181 elif type(expr) is astnodes.Deref: | 142 elif type(expr) is astnodes.Deref: |
182 # dereference pointer type: | 143 # dereference pointer type: |
183 addr = self.genExprCode(expr.ptr) | 144 addr = self.genExprCode(expr.ptr) |
184 tmp = self.builder.newTmp('deref') | 145 return ir.Mem(addr) |
185 ins = ir.Load(addr, tmp) | |
186 self.builder.addIns(ins) | |
187 return tmp | |
188 elif type(expr) is astnodes.FieldRef: | 146 elif type(expr) is astnodes.FieldRef: |
189 b = self.genExprCode(expr.base) | 147 b = self.genExprCode(expr.base) |
190 offset = self.builder.newTmp('off_' + expr.field) | 148 #b = b.e |
191 bt = theType(expr.base.typ) | 149 bt = theType(expr.base.typ) |
192 ofs = bt.fieldOffset(expr.field) | 150 offset = ir.Const(bt.fieldOffset(expr.field)) |
193 ins = ir.ImmLoad(offset, ofs) | 151 return ir.Mem(ir.Binop(b, '+', offset)) |
194 self.builder.addIns(ins) | |
195 tmp2 = self.builder.newTmp('adr_' + expr.field) | |
196 ins = ir.BinaryOperator(tmp2, '+', b, offset) | |
197 self.builder.addIns(ins) | |
198 return self.cast_to_rvalue(expr, tmp2) | |
199 elif type(expr) is astnodes.Literal: | 152 elif type(expr) is astnodes.Literal: |
200 tmp = self.builder.newTmp('const') | 153 return ir.Const(expr.val) |
201 ins = ir.ImmLoad(tmp, expr.val) | |
202 self.builder.addIns(ins) | |
203 return tmp | |
204 elif type(expr) is astnodes.TypeCast: | 154 elif type(expr) is astnodes.TypeCast: |
155 # TODO: improve this mess: | |
205 ar = self.genExprCode(expr.a) | 156 ar = self.genExprCode(expr.a) |
206 tt = theType(expr.to_type) | 157 tt = theType(expr.to_type) |
207 if isinstance(tt, astnodes.PointerType): | 158 if isinstance(tt, astnodes.PointerType): |
208 if expr.a.typ is intType: | 159 if expr.a.typ is intType: |
209 return ar | 160 return ar |
212 else: | 163 else: |
213 raise Exception() | 164 raise Exception() |
214 else: | 165 else: |
215 raise NotImplementedError("not implemented") | 166 raise NotImplementedError("not implemented") |
216 elif type(expr) is astnodes.FunctionCall: | 167 elif type(expr) is astnodes.FunctionCall: |
217 tmp = self.builder.newTmp("res") | 168 args = [self.genExprCode(e) for e in expr.args] |
218 args = [] | |
219 for arg in expr.args: | |
220 ar = self.genExprCode(arg) | |
221 args.append(ar) | |
222 fn = self.funcMap[expr.proc] | 169 fn = self.funcMap[expr.proc] |
223 ins = ir.Call(fn, args, tmp) | 170 return ir.Call(fn, args) |
224 self.builder.addIns(ins) | |
225 return tmp | |
226 else: | 171 else: |
227 raise NotImplementedError('Unknown expr {}'.format(expr)) | 172 raise NotImplementedError('Unknown expr {}'.format(expr)) |
228 | 173 |