Mercurial > lcfOS
comparison python/ppci/c3/codegenerator.py @ 394:988f3fb861e4
c3 code generator rewrite
author | Windel Bouwman |
---|---|
date | Thu, 22 May 2014 08:14:12 +0200 |
parents | 6ae782a085e0 |
children |
comparison
equal
deleted
inserted
replaced
393:6ae782a085e0 | 394:988f3fb861e4 |
---|---|
11 super().__init__() | 11 super().__init__() |
12 self.msg = msg | 12 self.msg = msg |
13 self.loc = loc | 13 self.loc = loc |
14 | 14 |
15 | 15 |
16 class CodeGenerator(irutils.Builder): | 16 class CodeGenerator: |
17 """ | 17 """ |
18 Generates intermediate (IR) code from a package. The entry function is | 18 Generates intermediate (IR) code from a package. The entry function is |
19 'genModule'. The main task of this part is to rewrite complex control | 19 'genModule'. The main task of this part is to rewrite complex control |
20 structures, such as while and for loops into simple conditional | 20 structures, such as while and for loops into simple conditional |
21 jump statements. Also complex conditional statements are simplified. | 21 jump statements. Also complex conditional statements are simplified. |
24 | 24 |
25 Type checking is done in one run with code generation. | 25 Type checking is done in one run with code generation. |
26 """ | 26 """ |
27 def __init__(self, diag): | 27 def __init__(self, diag): |
28 self.logger = logging.getLogger('c3cgen') | 28 self.logger = logging.getLogger('c3cgen') |
29 self.builder = irutils.Builder() | |
29 self.diag = diag | 30 self.diag = diag |
30 | 31 |
31 def gencode(self, pkg): | 32 def gencode(self, pkg): |
32 """ Generate code for a single module """ | 33 """ Generate code for a single module """ |
33 self.prepare() | 34 self.builder.prepare() |
34 assert type(pkg) is ast.Package | 35 assert type(pkg) is ast.Package |
35 self.pkg = pkg | 36 self.pkg = pkg |
36 self.intType = pkg.scope['int'] | 37 self.intType = pkg.scope['int'] |
37 self.boolType = pkg.scope['bool'] | 38 self.boolType = pkg.scope['bool'] |
38 self.pointerSize = 4 | 39 self.pointerSize = 4 |
39 self.logger.debug('Generating ir-code for {}'.format(pkg.name), | 40 self.logger.debug('Generating ir-code for {}'.format(pkg.name), |
40 extra={'c3_ast': pkg}) | 41 extra={'c3_ast': pkg}) |
41 self.varMap = {} # Maps variables to storage locations. | 42 self.varMap = {} # Maps variables to storage locations. |
42 self.m = ir.Module(pkg.name) | 43 self.builder.m = ir.Module(pkg.name) |
43 try: | 44 try: |
44 for typ in pkg.Types: | 45 for typ in pkg.Types: |
45 self.check_type(typ) | 46 self.check_type(typ) |
46 # Only generate function if function contains a body: | 47 # Only generate function if function contains a body: |
47 real_functions = list(filter( | 48 real_functions = list(filter( |
48 lambda f: f.body, pkg.innerScope.Functions)) | 49 lambda f: f.body, pkg.Functions)) |
49 for v in pkg.innerScope.Variables: | 50 for v in pkg.innerScope.Variables: |
50 v2 = ir.GlobalVariable(v.name) | 51 v2 = ir.GlobalVariable(v.name, ir.i32) |
51 self.varMap[v] = v2 | 52 self.varMap[v] = v2 |
52 if not v.isLocal: | 53 if not v.isLocal: |
53 self.m.add_variable(v2) | 54 self.builder.m.add_variable(v2) |
54 for s in real_functions: | 55 for s in real_functions: |
55 self.gen_function(s) | 56 self.gen_function(s) |
56 except SemanticError as e: | 57 except SemanticError as e: |
57 self.error(e.msg, e.loc) | 58 self.error(e.msg, e.loc) |
58 if self.pkg.ok: | 59 if self.pkg.ok: |
59 return self.m | 60 return self.builder.m |
60 | 61 |
61 def error(self, msg, loc=None): | 62 def error(self, msg, loc=None): |
62 self.pkg.ok = False | 63 self.pkg.ok = False |
63 self.diag.error(msg, loc) | 64 self.diag.error(msg, loc) |
64 | 65 |
65 def gen_function(self, fn): | 66 def gen_function(self, fn): |
66 # TODO: handle arguments | 67 # TODO: handle arguments |
67 f = self.newFunction(fn.name) | 68 f = self.builder.new_function(fn.name) |
68 f.return_value = self.newTemp() | 69 f.return_value = self.builder.newTemp() |
69 self.setFunction(f) | 70 self.builder.setFunction(f) |
70 l2 = self.newBlock() | 71 l2 = self.builder.newBlock() |
71 self.emit(ir.Jump(l2)) | 72 self.builder.emit(ir.Jump(l2)) |
72 self.setBlock(l2) | 73 self.builder.setBlock(l2) |
73 # generate room for locals: | 74 # generate room for locals: |
74 | 75 |
75 for sym in fn.innerScope: | 76 for sym in fn.innerScope: |
76 self.check_type(sym.typ) | 77 self.check_type(sym.typ) |
77 if sym.isParameter: | 78 if sym.isParameter: |
78 p = ir.Parameter(sym.name) | 79 p = ir.Parameter(sym.name, ir.i32) |
79 variable = ir.LocalVariable(sym.name + '_copy') | 80 variable = ir.LocalVariable(sym.name + '_copy', ir.i32) |
80 f.addParameter(p) | 81 f.addParameter(p) |
81 f.addLocal(variable) | 82 f.addLocal(variable) |
82 # Move parameter into local copy: | 83 # Move parameter into local copy: |
83 self.emit(ir.Move(ir.Mem(variable), p)) | 84 self.builder.emit(ir.Move(ir.Mem(variable), p)) |
84 elif sym.isLocal: | 85 elif sym.isLocal: |
85 variable = ir.LocalVariable(sym.name) | 86 variable = ir.LocalVariable(sym.name, ir.i32) |
86 f.addLocal(variable) | 87 f.addLocal(variable) |
87 elif isinstance(sym, ast.Variable): | 88 elif isinstance(sym, ast.Variable): |
88 variable = ir.LocalVariable(sym.name) | 89 variable = ir.LocalVariable(sym.name, ir.i32) |
89 f.addLocal(variable) | 90 f.addLocal(variable) |
90 else: | 91 else: |
91 raise NotImplementedError('{}'.format(sym)) | 92 raise NotImplementedError('{}'.format(sym)) |
92 self.varMap[sym] = variable | 93 self.varMap[sym] = variable |
93 | 94 |
94 self.genCode(fn.body) | 95 self.gen_stmt(fn.body) |
95 self.emit(ir.Move(f.return_value, ir.Const(0))) | 96 self.builder.emit(ir.Move(f.return_value, ir.Const(0))) |
96 self.emit(ir.Jump(f.epiloog)) | 97 self.builder.emit(ir.Jump(f.epiloog)) |
97 self.setFunction(None) | 98 self.builder.setFunction(None) |
98 | 99 |
99 def genCode(self, code): | 100 def gen_stmt(self, code): |
100 """ Wrapper around gen_stmt to catch errors """ | 101 """ Generate code for a statement """ |
101 try: | 102 try: |
102 self.gen_stmt(code) | 103 assert isinstance(code, ast.Statement) |
104 self.builder.setLoc(code.loc) | |
105 if type(code) is ast.Compound: | |
106 for s in code.statements: | |
107 self.gen_stmt(s) | |
108 elif type(code) is ast.Empty: | |
109 pass | |
110 elif type(code) is ast.Assignment: | |
111 self.gen_assignment_stmt(code) | |
112 elif type(code) is ast.ExpressionStatement: | |
113 self.builder.emit(ir.Exp(self.gen_expr_code(code.ex))) | |
114 elif type(code) is ast.If: | |
115 self.gen_if_stmt(code) | |
116 elif type(code) is ast.Return: | |
117 re = self.gen_expr_code(code.expr) | |
118 self.builder.emit(ir.Move(self.builder.fn.return_value, re)) | |
119 self.builder.emit(ir.Jump(self.builder.fn.epiloog)) | |
120 b = self.builder.newBlock() | |
121 self.builder.setBlock(b) | |
122 elif type(code) is ast.While: | |
123 self.gen_while(code) | |
124 elif type(code) is ast.For: | |
125 self.gen_for_stmt(code) | |
126 elif type(code) is ast.Switch: | |
127 raise NotImplementedError('Unknown stmt {}'.format(code)) | |
128 else: | |
129 raise NotImplementedError('Unknown stmt {}'.format(code)) | |
103 except SemanticError as e: | 130 except SemanticError as e: |
104 self.error(e.msg, e.loc) | 131 self.error(e.msg, e.loc) |
105 | 132 |
106 def gen_stmt(self, code): | 133 def gen_assignment_stmt(self, code): |
107 """ Generate code for a statement """ | 134 """ Generate code for assignment statement """ |
108 assert isinstance(code, ast.Statement) | 135 lval = self.gen_expr_code(code.lval) |
109 self.setLoc(code.loc) | 136 rval = self.gen_expr_code(code.rval) |
110 if type(code) is ast.Compound: | 137 if not self.equal_types(code.lval.typ, code.rval.typ): |
111 for s in code.statements: | 138 raise SemanticError('Cannot assign {} to {}' |
112 self.genCode(s) | 139 .format(code.rval.typ, code.lval.typ), |
113 elif type(code) is ast.Empty: | 140 code.loc) |
114 pass | 141 if not code.lval.lvalue: |
115 elif type(code) is ast.Assignment: | 142 raise SemanticError('No valid lvalue {}'.format(code.lval), |
116 lval = self.gen_expr_code(code.lval) | 143 code.lval.loc) |
117 rval = self.gen_expr_code(code.rval) | 144 self.builder.emit(ir.Move(lval, rval)) |
118 if not self.equal_types(code.lval.typ, code.rval.typ): | 145 |
119 raise SemanticError('Cannot assign {} to {}' | 146 def gen_if_stmt(self, code): |
120 .format(code.rval.typ, code.lval.typ), | 147 """ Generate code for if statement """ |
121 code.loc) | 148 true_block = self.builder.newBlock() |
122 if not code.lval.lvalue: | 149 bbfalse = self.builder.newBlock() |
123 raise SemanticError('No valid lvalue {}'.format(code.lval), | 150 te = self.builder.newBlock() |
124 code.lval.loc) | 151 self.gen_cond_code(code.condition, true_block, bbfalse) |
125 self.emit(ir.Move(lval, rval)) | 152 self.builder.setBlock(true_block) |
126 elif type(code) is ast.ExpressionStatement: | 153 self.gen_stmt(code.truestatement) |
127 self.emit(ir.Exp(self.gen_expr_code(code.ex))) | 154 self.builder.emit(ir.Jump(te)) |
128 elif type(code) is ast.If: | 155 self.builder.setBlock(bbfalse) |
129 bbtrue = self.newBlock() | 156 self.gen_stmt(code.falsestatement) |
130 bbfalse = self.newBlock() | 157 self.builder.emit(ir.Jump(te)) |
131 te = self.newBlock() | 158 self.builder.setBlock(te) |
132 self.gen_cond_code(code.condition, bbtrue, bbfalse) | 159 |
133 self.setBlock(bbtrue) | 160 def gen_while(self, code): |
134 self.genCode(code.truestatement) | 161 """ Generate code for while statement """ |
135 self.emit(ir.Jump(te)) | 162 bbdo = self.builder.newBlock() |
136 self.setBlock(bbfalse) | 163 test_block = self.builder.newBlock() |
137 self.genCode(code.falsestatement) | 164 final_block = self.builder.newBlock() |
138 self.emit(ir.Jump(te)) | 165 self.builder.emit(ir.Jump(test_block)) |
139 self.setBlock(te) | 166 self.builder.setBlock(test_block) |
140 elif type(code) is ast.Return: | 167 self.gen_cond_code(code.condition, bbdo, final_block) |
141 re = self.gen_expr_code(code.expr) | 168 self.builder.setBlock(bbdo) |
142 self.emit(ir.Move(self.fn.return_value, re)) | 169 self.gen_stmt(code.statement) |
143 self.emit(ir.Jump(self.fn.epiloog)) | 170 self.builder.emit(ir.Jump(test_block)) |
144 b = self.newBlock() | 171 self.builder.setBlock(final_block) |
145 self.setBlock(b) | 172 |
146 elif type(code) is ast.While: | 173 def gen_for_stmt(self, code): |
147 bbdo = self.newBlock() | 174 """ Generate for statement code """ |
148 bbtest = self.newBlock() | 175 bbdo = self.builder.newBlock() |
149 te = self.newBlock() | 176 test_block = self.builder.newBlock() |
150 self.emit(ir.Jump(bbtest)) | 177 final_block = self.builder.newBlock() |
151 self.setBlock(bbtest) | 178 self.gen_stmt(code.init) |
152 self.gen_cond_code(code.condition, bbdo, te) | 179 self.builder.emit(ir.Jump(test_block)) |
153 self.setBlock(bbdo) | 180 self.builder.setBlock(test_block) |
154 self.genCode(code.statement) | 181 self.gen_cond_code(code.condition, bbdo, final_block) |
155 self.emit(ir.Jump(bbtest)) | 182 self.builder.setBlock(bbdo) |
156 self.setBlock(te) | 183 self.gen_stmt(code.statement) |
157 elif type(code) is ast.For: | 184 self.gen_stmt(code.final) |
158 bbdo = self.newBlock() | 185 self.builder.emit(ir.Jump(test_block)) |
159 bbtest = self.newBlock() | 186 self.builder.setBlock(final_block) |
160 te = self.newBlock() | |
161 self.genCode(code.init) | |
162 self.emit(ir.Jump(bbtest)) | |
163 self.setBlock(bbtest) | |
164 self.gen_cond_code(code.condition, bbdo, te) | |
165 self.setBlock(bbdo) | |
166 self.genCode(code.statement) | |
167 self.genCode(code.final) | |
168 self.emit(ir.Jump(bbtest)) | |
169 self.setBlock(te) | |
170 elif type(code) is ast.Switch: | |
171 raise NotImplementedError('Unknown stmt {}'.format(code)) | |
172 else: | |
173 raise NotImplementedError('Unknown stmt {}'.format(code)) | |
174 | 187 |
175 def gen_cond_code(self, expr, bbtrue, bbfalse): | 188 def gen_cond_code(self, expr, bbtrue, bbfalse): |
176 """ Generate conditional logic. | 189 """ Generate conditional logic. |
177 Implement sequential logical operators. """ | 190 Implement sequential logical operators. """ |
178 if type(expr) is ast.Binop: | 191 if type(expr) is ast.Binop: |
179 if expr.op == 'or': | 192 if expr.op == 'or': |
180 l2 = self.newBlock() | 193 l2 = self.builder.newBlock() |
181 self.gen_cond_code(expr.a, bbtrue, l2) | 194 self.gen_cond_code(expr.a, bbtrue, l2) |
182 if not self.equal_types(expr.a.typ, self.boolType): | 195 if not self.equal_types(expr.a.typ, self.boolType): |
183 raise SemanticError('Must be boolean', expr.a.loc) | 196 raise SemanticError('Must be boolean', expr.a.loc) |
184 self.setBlock(l2) | 197 self.builder.setBlock(l2) |
185 self.gen_cond_code(expr.b, bbtrue, bbfalse) | 198 self.gen_cond_code(expr.b, bbtrue, bbfalse) |
186 if not self.equal_types(expr.b.typ, self.boolType): | 199 if not self.equal_types(expr.b.typ, self.boolType): |
187 raise SemanticError('Must be boolean', expr.b.loc) | 200 raise SemanticError('Must be boolean', expr.b.loc) |
188 elif expr.op == 'and': | 201 elif expr.op == 'and': |
189 l2 = self.newBlock() | 202 l2 = self.builder.newBlock() |
190 self.gen_cond_code(expr.a, l2, bbfalse) | 203 self.gen_cond_code(expr.a, l2, bbfalse) |
191 if not self.equal_types(expr.a.typ, self.boolType): | 204 if not self.equal_types(expr.a.typ, self.boolType): |
192 self.error('Must be boolean', expr.a.loc) | 205 self.error('Must be boolean', expr.a.loc) |
193 self.setBlock(l2) | 206 self.builder.setBlock(l2) |
194 self.gen_cond_code(expr.b, bbtrue, bbfalse) | 207 self.gen_cond_code(expr.b, bbtrue, bbfalse) |
195 if not self.equal_types(expr.b.typ, self.boolType): | 208 if not self.equal_types(expr.b.typ, self.boolType): |
196 raise SemanticError('Must be boolean', expr.b.loc) | 209 raise SemanticError('Must be boolean', expr.b.loc) |
197 elif expr.op in ['==', '>', '<', '!=', '<=', '>=']: | 210 elif expr.op in ['==', '>', '<', '!=', '<=', '>=']: |
198 ta = self.gen_expr_code(expr.a) | 211 ta = self.gen_expr_code(expr.a) |
199 tb = self.gen_expr_code(expr.b) | 212 tb = self.gen_expr_code(expr.b) |
200 if not self.equal_types(expr.a.typ, expr.b.typ): | 213 if not self.equal_types(expr.a.typ, expr.b.typ): |
201 raise SemanticError('Types unequal {} != {}' | 214 raise SemanticError('Types unequal {} != {}' |
202 .format(expr.a.typ, expr.b.typ), | 215 .format(expr.a.typ, expr.b.typ), |
203 expr.loc) | 216 expr.loc) |
204 self.emit(ir.CJump(ta, expr.op, tb, bbtrue, bbfalse)) | 217 self.builder.emit(ir.CJump(ta, expr.op, tb, bbtrue, bbfalse)) |
205 else: | 218 else: |
206 raise SemanticError('non-bool: {}'.format(expr.op), expr.loc) | 219 raise SemanticError('non-bool: {}'.format(expr.op), expr.loc) |
207 expr.typ = self.boolType | 220 expr.typ = self.boolType |
208 elif type(expr) is ast.Literal: | 221 elif type(expr) is ast.Literal: |
209 self.gen_expr_code(expr) | 222 self.gen_expr_code(expr) |
210 if expr.val: | 223 if expr.val: |
211 self.emit(ir.Jump(bbtrue)) | 224 self.builder.emit(ir.Jump(bbtrue)) |
212 else: | 225 else: |
213 self.emit(ir.Jump(bbfalse)) | 226 self.builder.emit(ir.Jump(bbfalse)) |
214 else: | 227 else: |
215 raise NotImplementedError('Unknown cond {}'.format(expr)) | 228 raise NotImplementedError('Unknown cond {}'.format(expr)) |
216 | 229 |
217 # Check that the condition is a boolean value: | 230 # Check that the condition is a boolean value: |
218 if not self.equal_types(expr.typ, self.boolType): | 231 if not self.equal_types(expr.typ, self.boolType): |
235 expr.typ = expr.a.typ | 248 expr.typ = expr.a.typ |
236 else: | 249 else: |
237 raise SemanticError('Can only add integers', expr.loc) | 250 raise SemanticError('Can only add integers', expr.loc) |
238 else: | 251 else: |
239 raise NotImplementedError("Cannot use equality as expressions") | 252 raise NotImplementedError("Cannot use equality as expressions") |
240 return ir.Binop(ra, expr.op, rb) | 253 return ir.Binop(ra, expr.op, rb, "op", ir.i32) |
241 elif type(expr) is ast.Unop: | 254 elif type(expr) is ast.Unop: |
242 if expr.op == '&': | 255 if expr.op == '&': |
243 ra = self.gen_expr_code(expr.a) | 256 ra = self.gen_expr_code(expr.a) |
244 expr.typ = ast.PointerType(expr.a.typ) | 257 expr.typ = ast.PointerType(expr.a.typ) |
245 if not expr.a.lvalue: | 258 if not expr.a.lvalue: |
272 expr.typ = ptr_typ.ptype | 285 expr.typ = ptr_typ.ptype |
273 return ir.Mem(addr) | 286 return ir.Mem(addr) |
274 else: | 287 else: |
275 raise SemanticError('Cannot deref non-pointer', expr.loc) | 288 raise SemanticError('Cannot deref non-pointer', expr.loc) |
276 elif type(expr) is ast.Member: | 289 elif type(expr) is ast.Member: |
277 base = self.gen_expr_code(expr.base) | 290 return self.gen_member_expr(expr) |
278 expr.lvalue = expr.base.lvalue | |
279 basetype = self.the_type(expr.base.typ) | |
280 if type(basetype) is ast.StructureType: | |
281 if basetype.hasField(expr.field): | |
282 expr.typ = basetype.fieldType(expr.field) | |
283 else: | |
284 raise SemanticError('{} does not contain field {}' | |
285 .format(basetype, expr.field), | |
286 expr.loc) | |
287 else: | |
288 raise SemanticError('Cannot select {} of non-structure type {}' | |
289 .format(expr.field, basetype), expr.loc) | |
290 | |
291 assert type(base) is ir.Mem, type(base) | |
292 bt = self.the_type(expr.base.typ) | |
293 offset = ir.Const(bt.fieldOffset(expr.field)) | |
294 return ir.Mem(ir.Add(base.e, offset)) | |
295 elif type(expr) is ast.Index: | 291 elif type(expr) is ast.Index: |
296 """ Array indexing """ | 292 return self.gen_index_expr(expr) |
297 base = self.gen_expr_code(expr.base) | |
298 idx = self.gen_expr_code(expr.i) | |
299 base_typ = self.the_type(expr.base.typ) | |
300 if not isinstance(base_typ, ast.ArrayType): | |
301 raise SemanticError('Cannot index non-array type {}' | |
302 .format(base_typ), | |
303 expr.base.loc) | |
304 idx_type = self.the_type(expr.i.typ) | |
305 if not self.equal_types(idx_type, self.intType): | |
306 raise SemanticError('Index must be int not {}' | |
307 .format(idx_type), expr.i.loc) | |
308 assert type(base) is ir.Mem | |
309 element_type = self.the_type(base_typ.element_type) | |
310 element_size = self.size_of(element_type) | |
311 expr.typ = base_typ.element_type | |
312 expr.lvalue = True | |
313 | |
314 return ir.Mem(ir.Add(base.e, ir.Mul(idx, ir.Const(element_size)))) | |
315 elif type(expr) is ast.Literal: | 293 elif type(expr) is ast.Literal: |
316 expr.lvalue = False | 294 return self.gen_literal_expr(expr) |
317 typemap = {int: 'int', | |
318 float: 'double', | |
319 bool: 'bool', | |
320 str: 'string'} | |
321 if type(expr.val) in typemap: | |
322 expr.typ = self.pkg.scope[typemap[type(expr.val)]] | |
323 else: | |
324 raise SemanticError('Unknown literal type {}' | |
325 .format(expr.val), expr.loc) | |
326 # Construct correct const value: | |
327 if type(expr.val) is str: | |
328 cval = self.pack_string(expr.val) | |
329 return ir.Addr(ir.Const(cval)) | |
330 else: | |
331 return ir.Const(expr.val) | |
332 elif type(expr) is ast.TypeCast: | 295 elif type(expr) is ast.TypeCast: |
333 return self.gen_type_cast(expr) | 296 return self.gen_type_cast(expr) |
334 elif type(expr) is ast.Sizeof: | 297 elif type(expr) is ast.Sizeof: |
335 # The type of this expression is int: | 298 # The type of this expression is int: |
336 expr.typ = self.intType | 299 expr.typ = self.intType |
339 return ir.Const(type_size) | 302 return ir.Const(type_size) |
340 elif type(expr) is ast.FunctionCall: | 303 elif type(expr) is ast.FunctionCall: |
341 return self.gen_function_call(expr) | 304 return self.gen_function_call(expr) |
342 else: | 305 else: |
343 raise NotImplementedError('Unknown expr {}'.format(expr)) | 306 raise NotImplementedError('Unknown expr {}'.format(expr)) |
307 | |
308 def gen_member_expr(self, expr): | |
309 base = self.gen_expr_code(expr.base) | |
310 expr.lvalue = expr.base.lvalue | |
311 basetype = self.the_type(expr.base.typ) | |
312 if type(basetype) is ast.StructureType: | |
313 if basetype.hasField(expr.field): | |
314 expr.typ = basetype.fieldType(expr.field) | |
315 else: | |
316 raise SemanticError('{} does not contain field {}' | |
317 .format(basetype, expr.field), | |
318 expr.loc) | |
319 else: | |
320 raise SemanticError('Cannot select {} of non-structure type {}' | |
321 .format(expr.field, basetype), expr.loc) | |
322 | |
323 assert type(base) is ir.Mem, type(base) | |
324 bt = self.the_type(expr.base.typ) | |
325 offset = ir.Const(bt.fieldOffset(expr.field)) | |
326 addr = ir.Add(base.e, offset, "mem_addr", ir.i32) | |
327 return ir.Mem(addr) | |
328 | |
329 def gen_index_expr(self, expr): | |
330 """ Array indexing """ | |
331 base = self.gen_expr_code(expr.base) | |
332 idx = self.gen_expr_code(expr.i) | |
333 base_typ = self.the_type(expr.base.typ) | |
334 if not isinstance(base_typ, ast.ArrayType): | |
335 raise SemanticError('Cannot index non-array type {}' | |
336 .format(base_typ), | |
337 expr.base.loc) | |
338 idx_type = self.the_type(expr.i.typ) | |
339 if not self.equal_types(idx_type, self.intType): | |
340 raise SemanticError('Index must be int not {}' | |
341 .format(idx_type), expr.i.loc) | |
342 assert type(base) is ir.Mem | |
343 element_type = self.the_type(base_typ.element_type) | |
344 element_size = self.size_of(element_type) | |
345 expr.typ = base_typ.element_type | |
346 expr.lvalue = True | |
347 | |
348 offset = ir.Mul(idx, ir.Const(element_size), "element_offset", ir.i32) | |
349 addr = ir.Add(base.e, offset, "element_address", ir.i32) | |
350 return ir.Mem(addr) | |
351 | |
352 def gen_literal_expr(self, expr): | |
353 """ Generate code for literal """ | |
354 expr.lvalue = False | |
355 typemap = {int: 'int', | |
356 float: 'double', | |
357 bool: 'bool', | |
358 str: 'string'} | |
359 if type(expr.val) in typemap: | |
360 expr.typ = self.pkg.scope[typemap[type(expr.val)]] | |
361 else: | |
362 raise SemanticError('Unknown literal type {}' | |
363 .format(expr.val), expr.loc) | |
364 # Construct correct const value: | |
365 if type(expr.val) is str: | |
366 cval = self.pack_string(expr.val) | |
367 return ir.Addr(ir.Const(cval)) | |
368 else: | |
369 return ir.Const(expr.val) | |
344 | 370 |
345 def pack_string(self, txt): | 371 def pack_string(self, txt): |
346 """ Pack a string using 4 bytes length followed by text data """ | 372 """ Pack a string using 4 bytes length followed by text data """ |
347 length = struct.pack('<I', len(txt)) | 373 length = struct.pack('<I', len(txt)) |
348 data = txt.encode('ascii') | 374 data = txt.encode('ascii') |