def make_il(self, il_code, symbol_table, c): # noqa D102 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().el), 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 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_nodes.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 addr(self, il_code): # noqa D102 out = ILValue(PointerCType(self.il_value.ctype)) il_code.add(value_cmds.AddrOf(out, self.il_value)) return out
def addr(self, il_code): self._fix_chunk_count(il_code) out = ILValue(PointerCType(self.ctype())) il_code.add(value_cmds.AddrRel( out, self.base, self.fixed_chunk, self.fixed_count)) return out
def make_ctype(self, decl, prev_ctype, symbol_table): """Generate a ctype from the given declaration. Return a `ctype, identifier token, storage class` triple. decl - Node of decl_nodes to parse. See decl_nodes.py for explanation about decl_nodess. prev_ctype - The ctype formed from all parts of the tree above the current one. storage - The storage class of this declaration. """ if isinstance(decl, decl_nodes.Pointer): new_ctype = PointerCType(prev_ctype, decl.const) elif isinstance(decl, decl_nodes.Array): new_ctype = ArrayCType(prev_ctype, decl.n) elif isinstance(decl, decl_nodes.Function): # Prohibit storage class specifiers in parameters. for param in decl.args: decl_info = self.get_decl_infos(param, symbol_table)[0] if decl_info.storage: err = "storage class specified for function parameter" raise CompilerError(err, decl_info.range) # Create a new scope because if we create a new struct type inside # the function parameters, it should be local to those parameters. symbol_table.new_scope() args = [ self.get_decl_infos(decl, symbol_table)[0].ctype for decl in decl.args ] 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.el) 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], symbol_table)[0] err = "'void' must be the only parameter" raise CompilerError(err, decl_info.range) # Function declarators cannot have a function or array return type. # TODO: Relevant only when typedef is implemented. if has_void: new_ctype = FunctionCType([], prev_ctype, False) elif not args: new_ctype = FunctionCType([], prev_ctype, True) else: new_ctype = FunctionCType(args, prev_ctype) elif isinstance(decl, decl_nodes.Identifier): return prev_ctype, decl.identifier return self.make_ctype(decl.child, new_ctype, symbol_table)