Mercurial > lcfOS
comparison python/ppci/c3/codegenerator.py @ 389:2ec730e45ea1
Added check for recursive struct
author | Windel Bouwman |
---|---|
date | Fri, 16 May 2014 12:29:31 +0200 |
parents | c49459768aaa |
children | 6ae782a085e0 |
comparison
equal
deleted
inserted
replaced
388:e07c2a9abac1 | 389:2ec730e45ea1 |
---|---|
33 self.prepare() | 33 self.prepare() |
34 assert type(pkg) is ast.Package | 34 assert type(pkg) is ast.Package |
35 self.pkg = pkg | 35 self.pkg = pkg |
36 self.intType = pkg.scope['int'] | 36 self.intType = pkg.scope['int'] |
37 self.boolType = pkg.scope['bool'] | 37 self.boolType = pkg.scope['bool'] |
38 self.logger.debug('Generating ir-code for {}'.format(pkg.name), extra={'c3_ast':pkg}) | 38 self.pointerSize = 4 |
39 self.logger.debug('Generating ir-code for {}'.format(pkg.name), | |
40 extra={'c3_ast': pkg}) | |
39 self.varMap = {} # Maps variables to storage locations. | 41 self.varMap = {} # Maps variables to storage locations. |
40 self.m = ir.Module(pkg.name) | 42 self.m = ir.Module(pkg.name) |
41 try: | 43 try: |
44 for typ in pkg.Types: | |
45 self.check_type(typ) | |
42 # Only generate function if function contains a body: | 46 # Only generate function if function contains a body: |
43 real_functions = list(filter(lambda f: f.body, pkg.innerScope.Functions)) | 47 real_functions = list(filter( |
48 lambda f: f.body, pkg.innerScope.Functions)) | |
44 for v in pkg.innerScope.Variables: | 49 for v in pkg.innerScope.Variables: |
45 v2 = ir.GlobalVariable(v.name) | 50 v2 = ir.GlobalVariable(v.name) |
46 self.varMap[v] = v2 | 51 self.varMap[v] = v2 |
47 if not v.isLocal: | 52 if not v.isLocal: |
48 self.m.add_variable(v2) | 53 self.m.add_variable(v2) |
66 self.emit(ir.Jump(l2)) | 71 self.emit(ir.Jump(l2)) |
67 self.setBlock(l2) | 72 self.setBlock(l2) |
68 # generate room for locals: | 73 # generate room for locals: |
69 | 74 |
70 for sym in fn.innerScope: | 75 for sym in fn.innerScope: |
71 self.the_type(sym.typ) | 76 self.check_type(sym.typ) |
72 if sym.isParameter: | 77 if sym.isParameter: |
73 p = ir.Parameter(sym.name) | 78 p = ir.Parameter(sym.name) |
74 variable = ir.LocalVariable(sym.name + '_copy') | 79 variable = ir.LocalVariable(sym.name + '_copy') |
75 f.addParameter(p) | 80 f.addParameter(p) |
76 f.addLocal(variable) | 81 f.addLocal(variable) |
108 elif type(code) is ast.Empty: | 113 elif type(code) is ast.Empty: |
109 pass | 114 pass |
110 elif type(code) is ast.Assignment: | 115 elif type(code) is ast.Assignment: |
111 lval = self.genExprCode(code.lval) | 116 lval = self.genExprCode(code.lval) |
112 rval = self.genExprCode(code.rval) | 117 rval = self.genExprCode(code.rval) |
113 if not self.equalTypes(code.lval.typ, code.rval.typ): | 118 if not self.equal_types(code.lval.typ, code.rval.typ): |
114 msg = 'Cannot assign {} to {}'.format(code.rval.typ, code.lval.typ) | 119 raise SemanticError('Cannot assign {} to {}' |
115 raise SemanticError(msg, code.loc) | 120 .format(code.rval.typ, code.lval.typ), |
121 code.loc) | |
116 if not code.lval.lvalue: | 122 if not code.lval.lvalue: |
117 raise SemanticError('No valid lvalue {}'.format(code.lval), code.lval.loc) | 123 raise SemanticError('No valid lvalue {}'.format(code.lval), |
124 code.lval.loc) | |
118 self.emit(ir.Move(lval, rval)) | 125 self.emit(ir.Move(lval, rval)) |
119 elif type(code) is ast.ExpressionStatement: | 126 elif type(code) is ast.ExpressionStatement: |
120 self.emit(ir.Exp(self.genExprCode(code.ex))) | 127 self.emit(ir.Exp(self.genExprCode(code.ex))) |
121 elif type(code) is ast.If: | 128 elif type(code) is ast.If: |
122 bbtrue = self.newBlock() | 129 bbtrue = self.newBlock() |
168 Implement sequential logical operators. """ | 175 Implement sequential logical operators. """ |
169 if type(expr) is ast.Binop: | 176 if type(expr) is ast.Binop: |
170 if expr.op == 'or': | 177 if expr.op == 'or': |
171 l2 = self.newBlock() | 178 l2 = self.newBlock() |
172 self.gen_cond_code(expr.a, bbtrue, l2) | 179 self.gen_cond_code(expr.a, bbtrue, l2) |
173 if not self.equalTypes(expr.a.typ, self.boolType): | 180 if not self.equal_types(expr.a.typ, self.boolType): |
174 raise SemanticError('Must be boolean', expr.a.loc) | 181 raise SemanticError('Must be boolean', expr.a.loc) |
175 self.setBlock(l2) | 182 self.setBlock(l2) |
176 self.gen_cond_code(expr.b, bbtrue, bbfalse) | 183 self.gen_cond_code(expr.b, bbtrue, bbfalse) |
177 if not self.equalTypes(expr.b.typ, self.boolType): | 184 if not self.equal_types(expr.b.typ, self.boolType): |
178 raise SemanticError('Must be boolean', expr.b.loc) | 185 raise SemanticError('Must be boolean', expr.b.loc) |
179 elif expr.op == 'and': | 186 elif expr.op == 'and': |
180 l2 = self.newBlock() | 187 l2 = self.newBlock() |
181 self.gen_cond_code(expr.a, l2, bbfalse) | 188 self.gen_cond_code(expr.a, l2, bbfalse) |
182 if not self.equalTypes(expr.a.typ, self.boolType): | 189 if not self.equal_types(expr.a.typ, self.boolType): |
183 self.error('Must be boolean', expr.a.loc) | 190 self.error('Must be boolean', expr.a.loc) |
184 self.setBlock(l2) | 191 self.setBlock(l2) |
185 self.gen_cond_code(expr.b, bbtrue, bbfalse) | 192 self.gen_cond_code(expr.b, bbtrue, bbfalse) |
186 if not self.equalTypes(expr.b.typ, self.boolType): | 193 if not self.equal_types(expr.b.typ, self.boolType): |
187 raise SemanticError('Must be boolean', expr.b.loc) | 194 raise SemanticError('Must be boolean', expr.b.loc) |
188 elif expr.op in ['==', '>', '<', '!=', '<=', '>=']: | 195 elif expr.op in ['==', '>', '<', '!=', '<=', '>=']: |
189 ta = self.genExprCode(expr.a) | 196 ta = self.genExprCode(expr.a) |
190 tb = self.genExprCode(expr.b) | 197 tb = self.genExprCode(expr.b) |
191 if not self.equalTypes(expr.a.typ, expr.b.typ): | 198 if not self.equal_types(expr.a.typ, expr.b.typ): |
192 raise SemanticError('Types unequal {} != {}' | 199 raise SemanticError('Types unequal {} != {}' |
193 .format(expr.a.typ, expr.b.typ), expr.loc) | 200 .format(expr.a.typ, expr.b.typ), |
201 expr.loc) | |
194 self.emit(ir.CJump(ta, expr.op, tb, bbtrue, bbfalse)) | 202 self.emit(ir.CJump(ta, expr.op, tb, bbtrue, bbfalse)) |
195 else: | 203 else: |
196 raise SemanticError('non-bool: {}'.format(expr.op), expr.loc) | 204 raise SemanticError('non-bool: {}'.format(expr.op), expr.loc) |
197 expr.typ = self.boolType | 205 expr.typ = self.boolType |
198 elif type(expr) is ast.Literal: | 206 elif type(expr) is ast.Literal: |
203 self.emit(ir.Jump(bbfalse)) | 211 self.emit(ir.Jump(bbfalse)) |
204 else: | 212 else: |
205 raise NotImplementedError('Unknown cond {}'.format(expr)) | 213 raise NotImplementedError('Unknown cond {}'.format(expr)) |
206 | 214 |
207 # Check that the condition is a boolean value: | 215 # Check that the condition is a boolean value: |
208 if not self.equalTypes(expr.typ, self.boolType): | 216 if not self.equal_types(expr.typ, self.boolType): |
209 self.error('Condition must be boolean', expr.loc) | 217 self.error('Condition must be boolean', expr.loc) |
210 | 218 |
211 def genExprCode(self, expr): | 219 def genExprCode(self, expr): |
212 """ Generate code for an expression. Return the generated ir-value """ | 220 """ Generate code for an expression. Return the generated ir-value """ |
213 assert isinstance(expr, ast.Expression) | 221 assert isinstance(expr, ast.Expression) |
214 if type(expr) is ast.Binop: | 222 if type(expr) is ast.Binop: |
215 expr.lvalue = False | 223 expr.lvalue = False |
216 if expr.op in ['+', '-', '*', '/', '<<', '>>', '|', '&']: | 224 if expr.op in ['+', '-', '*', '/', '<<', '>>', '|', '&']: |
217 ra = self.genExprCode(expr.a) | 225 ra = self.genExprCode(expr.a) |
218 rb = self.genExprCode(expr.b) | 226 rb = self.genExprCode(expr.b) |
219 if self.equalTypes(expr.a.typ, self.intType) and \ | 227 if self.equal_types(expr.a.typ, self.intType) and \ |
220 self.equalTypes(expr.b.typ, self.intType): | 228 self.equal_types(expr.b.typ, self.intType): |
221 expr.typ = expr.a.typ | 229 expr.typ = expr.a.typ |
222 else: | 230 else: |
223 raise SemanticError('Can only add integers', expr.loc) | 231 raise SemanticError('Can only add integers', expr.loc) |
224 else: | 232 else: |
225 raise NotImplementedError("Cannot use equality as expressions") | 233 raise NotImplementedError("Cannot use equality as expressions") |
266 if type(basetype) is ast.StructureType: | 274 if type(basetype) is ast.StructureType: |
267 if basetype.hasField(expr.field): | 275 if basetype.hasField(expr.field): |
268 expr.typ = basetype.fieldType(expr.field) | 276 expr.typ = basetype.fieldType(expr.field) |
269 else: | 277 else: |
270 raise SemanticError('{} does not contain field {}' | 278 raise SemanticError('{} does not contain field {}' |
271 .format(basetype, expr.field), expr.loc) | 279 .format(basetype, expr.field), |
280 expr.loc) | |
272 else: | 281 else: |
273 raise SemanticError('Cannot select {} of non-structure type {}' | 282 raise SemanticError('Cannot select {} of non-structure type {}' |
274 .format(expr.field, basetype), expr.loc) | 283 .format(expr.field, basetype), expr.loc) |
275 | 284 |
276 assert type(base) is ir.Mem, type(base) | 285 assert type(base) is ir.Mem, type(base) |
281 """ Array indexing """ | 290 """ Array indexing """ |
282 base = self.genExprCode(expr.base) | 291 base = self.genExprCode(expr.base) |
283 idx = self.genExprCode(expr.i) | 292 idx = self.genExprCode(expr.i) |
284 base_typ = self.the_type(expr.base.typ) | 293 base_typ = self.the_type(expr.base.typ) |
285 if not isinstance(base_typ, ast.ArrayType): | 294 if not isinstance(base_typ, ast.ArrayType): |
286 raise SemanticError('Cannot index non-array type {}'.format(base_typ), expr.base.loc) | 295 raise SemanticError('Cannot index non-array type {}' |
296 .format(base_typ), | |
297 expr.base.loc) | |
287 idx_type = self.the_type(expr.i.typ) | 298 idx_type = self.the_type(expr.i.typ) |
288 if not self.equalTypes(idx_type, self.intType): | 299 if not self.equal_types(idx_type, self.intType): |
289 raise SemanticError('Index must be int not {}'.format(idx_type), expr.i.loc) | 300 raise SemanticError('Index must be int not {}' |
301 .format(idx_type), expr.i.loc) | |
290 assert type(base) is ir.Mem | 302 assert type(base) is ir.Mem |
291 element_type = self.the_type(base_typ.element_type) | 303 element_type = self.the_type(base_typ.element_type) |
292 element_size = self.size_of(element_type) | 304 element_size = self.size_of(element_type) |
293 expr.typ = base_typ.element_type | 305 expr.typ = base_typ.element_type |
294 expr.lvalue = True | 306 expr.lvalue = True |
295 | 307 |
296 return ir.Mem(ir.Add(base.e, ir.Mul(idx, ir.Const(element_size)))) | 308 return ir.Mem(ir.Add(base.e, ir.Mul(idx, ir.Const(element_size)))) |
297 elif type(expr) is ast.Literal: | 309 elif type(expr) is ast.Literal: |
298 expr.lvalue = False | 310 expr.lvalue = False |
299 typemap = {int: 'int', float: 'double', bool: 'bool', str:'string'} | 311 typemap = {int: 'int', |
312 float: 'double', | |
313 bool: 'bool', | |
314 str: 'string'} | |
300 if type(expr.val) in typemap: | 315 if type(expr.val) in typemap: |
301 expr.typ = self.pkg.scope[typemap[type(expr.val)]] | 316 expr.typ = self.pkg.scope[typemap[type(expr.val)]] |
302 else: | 317 else: |
303 raise SemanticError('Unknown literal type {}'.format(expr.val), expr.loc) | 318 raise SemanticError('Unknown literal type {}' |
319 .format(expr.val), expr.loc) | |
304 # Construct correct const value: | 320 # Construct correct const value: |
305 if type(expr.val) is str: | 321 if type(expr.val) is str: |
306 cval = struct.pack('<I', len(expr.val)) + expr.val.encode('ascii') | 322 cval = self.pack_string(expr.val) |
307 return ir.Addr(ir.Const(cval)) | 323 return ir.Addr(ir.Const(cval)) |
308 else: | 324 else: |
309 return ir.Const(expr.val) | 325 return ir.Const(expr.val) |
310 elif type(expr) is ast.TypeCast: | 326 elif type(expr) is ast.TypeCast: |
311 return self.gen_type_cast(expr) | 327 return self.gen_type_cast(expr) |
312 elif type(expr) is ast.FunctionCall: | 328 elif type(expr) is ast.FunctionCall: |
313 return self.gen_function_call(expr) | 329 return self.gen_function_call(expr) |
314 else: | 330 else: |
315 raise NotImplementedError('Unknown expr {}'.format(expr)) | 331 raise NotImplementedError('Unknown expr {}'.format(expr)) |
316 | 332 |
333 def pack_string(self, txt): | |
334 """ Pack a string using 4 bytes length followed by text data """ | |
335 length = struct.pack('<I', len(txt)) | |
336 data = txt.encode('ascii') | |
337 return length + data | |
338 | |
317 def gen_type_cast(self, expr): | 339 def gen_type_cast(self, expr): |
318 """ Generate code for type casting """ | 340 """ Generate code for type casting """ |
319 ar = self.genExprCode(expr.a) | 341 ar = self.genExprCode(expr.a) |
320 from_type = self.the_type(expr.a.typ) | 342 from_type = self.the_type(expr.a.typ) |
321 to_type = self.the_type(expr.to_type) | 343 to_type = self.the_type(expr.to_type) |
322 if isinstance(from_type, ast.PointerType) and isinstance(to_type, ast.PointerType): | 344 if isinstance(from_type, ast.PointerType) and \ |
323 expr.typ = expr.to_type | |
324 return ar | |
325 elif self.equalTypes(self.intType, from_type) and \ | |
326 isinstance(to_type, ast.PointerType): | 345 isinstance(to_type, ast.PointerType): |
327 expr.typ = expr.to_type | 346 expr.typ = expr.to_type |
328 return ar | 347 return ar |
329 elif self.equalTypes(self.intType, to_type) \ | 348 elif self.equal_types(self.intType, from_type) and \ |
349 isinstance(to_type, ast.PointerType): | |
350 expr.typ = expr.to_type | |
351 return ar | |
352 elif self.equal_types(self.intType, to_type) \ | |
330 and isinstance(from_type, ast.PointerType): | 353 and isinstance(from_type, ast.PointerType): |
331 expr.typ = expr.to_type | 354 expr.typ = expr.to_type |
332 return ar | 355 return ar |
333 elif type(from_type) is ast.BaseType and from_type.name == 'byte' and \ | 356 elif type(from_type) is ast.BaseType and from_type.name == 'byte' and \ |
334 type(to_type) is ast.BaseType and to_type.name == 'int': | 357 type(to_type) is ast.BaseType and to_type.name == 'int': |
349 ftyp = tg.typ | 372 ftyp = tg.typ |
350 fname = tg.package.name + '_' + tg.name | 373 fname = tg.package.name + '_' + tg.name |
351 ptypes = ftyp.parametertypes | 374 ptypes = ftyp.parametertypes |
352 if len(expr.args) != len(ptypes): | 375 if len(expr.args) != len(ptypes): |
353 raise SemanticError('{} requires {} arguments, {} given' | 376 raise SemanticError('{} requires {} arguments, {} given' |
354 .format(fname, len(ptypes), len(expr.args)), expr.loc) | 377 .format(fname, len(ptypes), len(expr.args)), |
378 expr.loc) | |
355 for arg, at in zip(expr.args, ptypes): | 379 for arg, at in zip(expr.args, ptypes): |
356 if not self.equalTypes(arg.typ, at): | 380 if not self.equal_types(arg.typ, at): |
357 raise SemanticError('Got {}, expected {}' | 381 raise SemanticError('Got {}, expected {}' |
358 .format(arg.typ, at), arg.loc) | 382 .format(arg.typ, at), arg.loc) |
359 # determine return type: | 383 # determine return type: |
360 expr.typ = ftyp.returntype | 384 expr.typ = ftyp.returntype |
361 return ir.Call(fname, args) | 385 return ir.Call(fname, args) |
362 | 386 |
363 def evalConst(self, c): | 387 def evalConst(self, c): |
392 return t.bytesize | 416 return t.bytesize |
393 elif type(t) is ast.StructureType: | 417 elif type(t) is ast.StructureType: |
394 return sum(self.size_of(mem.typ) for mem in t.mems) | 418 return sum(self.size_of(mem.typ) for mem in t.mems) |
395 elif type(t) is ast.ArrayType: | 419 elif type(t) is ast.ArrayType: |
396 return t.size * self.size_of(t.element_type) | 420 return t.size * self.size_of(t.element_type) |
421 elif type(t) is ast.PointerType: | |
422 return self.pointerSize | |
397 else: | 423 else: |
398 raise NotImplementedError(str(t)) | 424 raise NotImplementedError(str(t)) |
399 | 425 |
400 def the_type(self, t): | 426 def the_type(self, t, reveil_defined=True): |
401 """ Recurse until a 'real' type is found """ | 427 """ Recurse until a 'real' type is found |
428 When reveil_defined is True, defined types are resolved to | |
429 their backing types. | |
430 """ | |
402 if type(t) is ast.DefinedType: | 431 if type(t) is ast.DefinedType: |
403 t = self.the_type(t.typ) | 432 if reveil_defined: |
433 t = self.the_type(t.typ) | |
404 elif type(t) in [ast.Identifier, ast.Member]: | 434 elif type(t) in [ast.Identifier, ast.Member]: |
405 t = self.the_type(self.resolveSymbol(t)) | 435 t = self.the_type(self.resolveSymbol(t), reveil_defined) |
406 elif type(t) is ast.StructureType: | |
407 # Setup offsets of fields. Is this the right place?: | |
408 offset = 0 | |
409 for mem in t.mems: | |
410 mem.offset = offset | |
411 offset = offset + self.size_of(mem.typ) | |
412 elif isinstance(t, ast.Type): | 436 elif isinstance(t, ast.Type): |
413 pass | 437 pass |
414 else: | 438 else: |
415 raise NotImplementedError(str(t)) | 439 raise NotImplementedError(str(t)) |
416 assert isinstance(t, ast.Type) | 440 assert isinstance(t, ast.Type) |
417 return t | 441 return t |
418 | 442 |
419 def equalTypes(self, a, b): | 443 def equal_types(self, a, b, byname=False): |
420 """ Compare types a and b for structural equavalence. """ | 444 """ Compare types a and b for structural equavalence. |
445 if byname is True stop on defined types. | |
446 """ | |
421 # Recurse into named types: | 447 # Recurse into named types: |
422 a = self.the_type(a) | 448 a = self.the_type(a, not byname) |
423 b = self.the_type(b) | 449 b = self.the_type(b, not byname) |
424 | 450 |
451 # Check types for sanity: | |
452 self.check_type(a) | |
453 self.check_type(b) | |
454 | |
455 # Do structural equivalence check: | |
425 if type(a) is type(b): | 456 if type(a) is type(b): |
426 if type(a) is ast.BaseType: | 457 if type(a) is ast.BaseType: |
427 return a.name == b.name | 458 return a.name == b.name |
428 elif type(a) is ast.PointerType: | 459 elif type(a) is ast.PointerType: |
429 return self.equalTypes(a.ptype, b.ptype) | 460 # If a pointed type is detected, stop structural |
461 # equivalence: | |
462 return self.equal_types(a.ptype, b.ptype, byname=True) | |
430 elif type(a) is ast.StructureType: | 463 elif type(a) is ast.StructureType: |
431 if len(a.mems) != len(b.mems): | 464 if len(a.mems) != len(b.mems): |
432 return False | 465 return False |
433 return all(self.equalTypes(am.typ, bm.typ) for am, bm in | 466 return all(self.equal_types(am.typ, bm.typ) for am, bm in |
434 zip(a.mems, b.mems)) | 467 zip(a.mems, b.mems)) |
435 elif type(a) is ast.ArrayType: | 468 elif type(a) is ast.ArrayType: |
436 return self.equalTypes(a.element_type, b.element_type) | 469 return self.equal_types(a.element_type, b.element_type) |
470 elif type(a) is ast.DefinedType: | |
471 # Try by name in case of defined types: | |
472 return a.name == b.name | |
437 else: | 473 else: |
438 raise NotImplementedError('{} not implemented'.format(type(a))) | 474 raise NotImplementedError('{} not implemented'.format(type(a))) |
439 return False | 475 return False |
476 | |
477 def check_type(self, t, first=True, byname=False): | |
478 """ Determine struct offsets and check for recursiveness by using | |
479 mark and sweep algorithm. | |
480 The calling function could call this function with first set | |
481 to clear the marks. | |
482 """ | |
483 | |
484 # Reset the mark and sweep: | |
485 if first: | |
486 self.got_types = set() | |
487 | |
488 # Resolve the type: | |
489 t = self.the_type(t, not byname) | |
490 | |
491 # Check for recursion: | |
492 if t in self.got_types: | |
493 raise SemanticError('Recursive data type {}'.format(t), None) | |
494 | |
495 if type(t) is ast.BaseType: | |
496 pass | |
497 elif type(t) is ast.PointerType: | |
498 # If a pointed type is detected, stop structural | |
499 # equivalence: | |
500 self.check_type(t.ptype, first=False, byname=True) | |
501 elif type(t) is ast.StructureType: | |
502 self.got_types.add(t) | |
503 # Setup offsets of fields. Is this the right place?: | |
504 offset = 0 | |
505 for struct_member in t.mems: | |
506 self.check_type(struct_member.typ, first=False) | |
507 struct_member.offset = offset | |
508 offset = offset + self.size_of(struct_member.typ) | |
509 elif type(t) is ast.ArrayType: | |
510 self.check_type(t.element_type, first=False) | |
511 elif type(t) is ast.DefinedType: | |
512 pass | |
513 else: | |
514 raise NotImplementedError('{} not implemented'.format(type(t))) |