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