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)))