def addr(self, il_code): self.fix_block_count(il_code) out = ILValue(PointerCType(self.ctype())) il_code.add( value_cmds.AddrRel(out, self.base, self.fixed_block, self.fixed_count)) return out
def generate_func_ctype(self, decl, prev_ctype): """ Generate a function ctype from a given a decl_node """ # Prohibit storage class specifiers in parameters. for param in decl.args: decl_info = self.get_decl_infos(param)[0] if decl_info.storage: err = "storage class specified for function parameter" raise CompilerError(err, decl_info.span) # Create a new scope because if we create a new struct type inside the function parameters, it should be local # to those parameters. self.symbol_table.new_scope() args = [self.get_decl_infos(decl)[0].ctype for decl in decl.args] self.symbol_table.end_scope() # adjust array and function parameters has_void = False for i in range(len(args)): ctype = args[i] if ctype.is_array(): args[i] = PointerCType(ctype.elem) elif ctype.is_function(): args[i] = PointerCType(ctype) elif ctype.is_void(): has_void = True if has_void and len(args) > 1: decl_info = self.get_decl_infos(decl.args[0])[0] err = "'void' must be the only parameter" raise CompilerError(err, decl_info.span) if prev_ctype.is_function(): err = "function cannot return function type" raise CompilerError(err, self.r) if prev_ctype.is_array(): err = "function cannot return array type" raise CompilerError(err, self.r) if not args and not self.body: new_ctype = FunctionCType([], prev_ctype, True) elif has_void: new_ctype = FunctionCType([], prev_ctype, False) else: new_ctype = FunctionCType(args, prev_ctype, False) return new_ctype
def _lvalue(self, il_code, symbol_table, c): struct_addr = self.head.make_il(il_code, symbol_table, c) if not struct_addr.ctype.is_pointer(): err = "first argument of '->' must have pointer type" raise CompilerError(err, self.r) offset, ctype = self.get_offset_info(struct_addr.ctype.arg) shift = ILValue(ctypes.longint) il_code.register_literal_var(shift, str(offset)) out = ILValue(PointerCType(ctype)) il_code.add(math_cmds.Add(out, struct_addr, shift)) return IndirectLValue(out)
def make_ctype(self, decl, prev_ctype): """Generate a ctype from the given declaration. Return a `ctype, identifier token` tuple. decl - Node of decl_nodes to parse. See decl_tree.py for explanation about decl_nodes. prev_ctype - The ctype formed from all parts of the tree above the current one. """ if isinstance(decl, decl_nodes.Pointer): new_ctype = PointerCType(prev_ctype, decl.const) elif isinstance(decl, decl_nodes.Array): new_ctype = self.generate_array_ctype(decl, prev_ctype) elif isinstance(decl, decl_nodes.Function): new_ctype = self.generate_func_ctype(decl, prev_ctype) elif isinstance(decl, decl_nodes.Identifier): return prev_ctype, decl.identifier return self.make_ctype(decl.child, new_ctype)
def make_il(self, il_code, symbol_table, c): lvalue = self.lvalue(il_code, symbol_table, c) # Decay array if lvalue.ctype().is_array(): addr = lvalue.addr(il_code) return set_type(addr, PointerCType(lvalue.ctype().elem), il_code) # Decay function elif lvalue.ctype().is_function(): return lvalue.addr(il_code) # Nothing to decay else: return lvalue.val(il_code)
def _lvalue(self, il_code, symbol_table, c): head_lv = self.head.lvalue(il_code, symbol_table, c) struct_ctype = head_lv.ctype() if head_lv else None offset, ctype = self.get_offset_info(struct_ctype) if isinstance(head_lv, DirectLValue): head_val = self.head.make_il(il_code, symbol_table, c) return RelativeLValue(ctype, head_val, offset) else: struct_addr = head_lv.addr(il_code) shift = ILValue(ctypes.longint) il_code.register_literal_var(shift, str(offset)) out = ILValue(PointerCType(ctype)) il_code.add(math_cmds.Add(out, struct_addr, shift)) return IndirectLValue(out)
def addr(self, il_code): out = ILValue(PointerCType(self.il_value.ctype)) il_code.add(value_cmds.AddrOf(out, self.il_value)) return out