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