| ... | ... | @@ -109,6 +109,7 @@ atom_by_index_table: std.AutoHashMapUnmanaged(u32, Atom.Index) = .{}, |
| 109 | 109 | /// value assigned to label `foo` is an unnamed constant belonging/associated |
| 110 | 110 | /// with `Decl` `main`, and lives as long as that `Decl`. |
| 111 | 111 | unnamed_const_atoms: UnnamedConstTable = .{}, |
| 112 | anon_decls: AnonDeclTable = .{}, |
| 112 | 113 | |
| 113 | 114 | /// A table of relocations indexed by the owning them `Atom`. |
| 114 | 115 | /// Note that once we refactor `Atom`'s lifetime and ownership rules, |
| ... | ... | @@ -1899,6 +1900,7 @@ pub fn deinit(self: *MachO) void { |
| 1899 | 1900 | atoms.deinit(gpa); |
| 1900 | 1901 | } |
| 1901 | 1902 | self.unnamed_const_atoms.deinit(gpa); |
| 1903 | self.anon_decls.deinit(gpa); |
| 1902 | 1904 | |
| 1903 | 1905 | self.atom_by_index_table.deinit(gpa); |
| 1904 | 1906 | |
| ... | ... | @@ -2172,27 +2174,49 @@ pub fn updateFunc(self: *MachO, mod: *Module, func_index: InternPool.Index, air: |
| 2172 | 2174 | |
| 2173 | 2175 | pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Module.Decl.Index) !u32 { |
| 2174 | 2176 | const gpa = self.base.allocator; |
| 2175 | | |
| 2176 | | var code_buffer = std.ArrayList(u8).init(gpa); |
| 2177 | | defer code_buffer.deinit(); |
| 2178 | | |
| 2179 | 2177 | const mod = self.base.options.module.?; |
| 2180 | 2178 | const gop = try self.unnamed_const_atoms.getOrPut(gpa, decl_index); |
| 2181 | 2179 | if (!gop.found_existing) { |
| 2182 | 2180 | gop.value_ptr.* = .{}; |
| 2183 | 2181 | } |
| 2184 | 2182 | const unnamed_consts = gop.value_ptr; |
| 2185 | | |
| 2186 | 2183 | const decl = mod.declPtr(decl_index); |
| 2187 | 2184 | const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod)); |
| 2188 | | |
| 2189 | | const name_str_index = blk: { |
| 2190 | | const index = unnamed_consts.items.len; |
| 2191 | | const name = try std.fmt.allocPrint(gpa, "___unnamed_{s}_{d}", .{ decl_name, index }); |
| 2192 | | defer gpa.free(name); |
| 2193 | | break :blk try self.strtab.insert(gpa, name); |
| 2185 | const index = unnamed_consts.items.len; |
| 2186 | const name = try std.fmt.allocPrint(gpa, "___unnamed_{s}_{d}", .{ decl_name, index }); |
| 2187 | defer gpa.free(name); |
| 2188 | const atom_index = switch (try self.lowerConst(name, typed_value, self.data_const_section_index.?, decl.srcLoc(mod))) { |
| 2189 | .ok => |atom_index| atom_index, |
| 2190 | .fail => |em| { |
| 2191 | decl.analysis = .codegen_failure; |
| 2192 | try mod.failed_decls.put(mod.gpa, decl_index, em); |
| 2193 | log.debug("{s}", .{em.msg}); |
| 2194 | return error.CodegenFail; |
| 2195 | }, |
| 2194 | 2196 | }; |
| 2195 | | const name = self.strtab.get(name_str_index).?; |
| 2197 | try unnamed_consts.append(gpa, atom_index); |
| 2198 | const atom = self.getAtomPtr(atom_index); |
| 2199 | return atom.getSymbolIndex().?; |
| 2200 | } |
| 2201 | |
| 2202 | const LowerConstResult = union(enum) { |
| 2203 | ok: Atom.Index, |
| 2204 | fail: *Module.ErrorMsg, |
| 2205 | }; |
| 2206 | |
| 2207 | fn lowerConst( |
| 2208 | self: *MachO, |
| 2209 | name: []const u8, |
| 2210 | tv: TypedValue, |
| 2211 | sect_id: u8, |
| 2212 | src_loc: Module.SrcLoc, |
| 2213 | ) !LowerConstResult { |
| 2214 | const gpa = self.base.allocator; |
| 2215 | |
| 2216 | var code_buffer = std.ArrayList(u8).init(gpa); |
| 2217 | defer code_buffer.deinit(); |
| 2218 | |
| 2219 | const mod = self.base.options.module.?; |
| 2196 | 2220 | |
| 2197 | 2221 | log.debug("allocating symbol indexes for {s}", .{name}); |
| 2198 | 2222 | |
| ... | ... | @@ -2200,40 +2224,33 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Modu |
| 2200 | 2224 | const atom_index = try self.createAtom(sym_index, .{}); |
| 2201 | 2225 | try self.atom_by_index_table.putNoClobber(gpa, sym_index, atom_index); |
| 2202 | 2226 | |
| 2203 | | const res = try codegen.generateSymbol(&self.base, decl.srcLoc(mod), typed_value, &code_buffer, .none, .{ |
| 2227 | const res = try codegen.generateSymbol(&self.base, src_loc, tv, &code_buffer, .none, .{ |
| 2204 | 2228 | .parent_atom_index = self.getAtom(atom_index).getSymbolIndex().?, |
| 2205 | 2229 | }); |
| 2206 | 2230 | var code = switch (res) { |
| 2207 | 2231 | .ok => code_buffer.items, |
| 2208 | | .fail => |em| { |
| 2209 | | decl.analysis = .codegen_failure; |
| 2210 | | try mod.failed_decls.put(mod.gpa, decl_index, em); |
| 2211 | | log.debug("{s}", .{em.msg}); |
| 2212 | | return error.CodegenFail; |
| 2213 | | }, |
| 2232 | .fail => |em| return .{ .fail = em }, |
| 2214 | 2233 | }; |
| 2215 | 2234 | |
| 2216 | | const required_alignment = typed_value.ty.abiAlignment(mod); |
| 2235 | const required_alignment = tv.ty.abiAlignment(mod); |
| 2217 | 2236 | const atom = self.getAtomPtr(atom_index); |
| 2218 | 2237 | atom.size = code.len; |
| 2219 | 2238 | // TODO: work out logic for disambiguating functions from function pointers |
| 2220 | 2239 | // const sect_id = self.getDeclOutputSection(decl_index); |
| 2221 | | const sect_id = self.data_const_section_index.?; |
| 2222 | 2240 | const symbol = atom.getSymbolPtr(self); |
| 2241 | const name_str_index = try self.strtab.insert(gpa, name); |
| 2223 | 2242 | symbol.n_strx = name_str_index; |
| 2224 | 2243 | symbol.n_type = macho.N_SECT; |
| 2225 | 2244 | symbol.n_sect = sect_id + 1; |
| 2226 | 2245 | symbol.n_value = try self.allocateAtom(atom_index, code.len, required_alignment); |
| 2227 | 2246 | errdefer self.freeAtom(atom_index); |
| 2228 | 2247 | |
| 2229 | | try unnamed_consts.append(gpa, atom_index); |
| 2230 | | |
| 2231 | 2248 | log.debug("allocated atom for {s} at 0x{x}", .{ name, symbol.n_value }); |
| 2232 | 2249 | log.debug(" (required alignment 0x{x})", .{required_alignment}); |
| 2233 | 2250 | |
| 2234 | 2251 | try self.writeAtom(atom_index, code); |
| 2235 | 2252 | |
| 2236 | | return atom.getSymbolIndex().?; |
| 2253 | return .{ .ok = atom_index }; |
| 2237 | 2254 | } |
| 2238 | 2255 | |
| 2239 | 2256 | pub fn updateDecl(self: *MachO, mod: *Module, decl_index: Module.Decl.Index) !void { |
| ... | ... | @@ -2850,17 +2867,50 @@ pub fn lowerAnonDecl(self: *MachO, decl_val: InternPool.Index, src_loc: Module.S |
| 2850 | 2867 | // be used by more than one function, however, its address is being used so we need |
| 2851 | 2868 | // to put it in some location. |
| 2852 | 2869 | // ... |
| 2853 | | _ = self; |
| 2854 | | _ = decl_val; |
| 2855 | | _ = src_loc; |
| 2856 | | _ = @panic("TODO: link/MachO lowerAnonDecl"); |
| 2870 | const gpa = self.base.allocator; |
| 2871 | const gop = try self.anon_decls.getOrPut(gpa, decl_val); |
| 2872 | if (!gop.found_existing) { |
| 2873 | const mod = self.base.options.module.?; |
| 2874 | const ty = mod.intern_pool.typeOf(decl_val).toType(); |
| 2875 | const val = decl_val.toValue(); |
| 2876 | const tv = TypedValue{ .ty = ty, .val = val }; |
| 2877 | const name = try std.fmt.allocPrint(gpa, "__anon_{d}", .{@intFromEnum(decl_val)}); |
| 2878 | defer gpa.free(name); |
| 2879 | const res = self.lowerConst(name, tv, self.data_const_section_index.?, src_loc) catch |err| switch (err) { |
| 2880 | else => { |
| 2881 | // TODO improve error message |
| 2882 | const em = try Module.ErrorMsg.create(gpa, src_loc, "lowerAnonDecl failed with error: {s}", .{ |
| 2883 | @errorName(err), |
| 2884 | }); |
| 2885 | return .{ .fail = em }; |
| 2886 | }, |
| 2887 | }; |
| 2888 | const atom_index = switch (res) { |
| 2889 | .ok => |atom_index| atom_index, |
| 2890 | .fail => |em| return .{ .fail = em }, |
| 2891 | }; |
| 2892 | gop.value_ptr.* = atom_index; |
| 2893 | } |
| 2894 | return .ok; |
| 2857 | 2895 | } |
| 2858 | 2896 | |
| 2859 | 2897 | pub fn getAnonDeclVAddr(self: *MachO, decl_val: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 { |
| 2860 | | _ = self; |
| 2861 | | _ = decl_val; |
| 2862 | | _ = reloc_info; |
| 2863 | | _ = @panic("TODO: link/MachO getAnonDeclVAddr"); |
| 2898 | assert(self.llvm_object == null); |
| 2899 | |
| 2900 | const this_atom_index = self.anon_decls.get(decl_val).?; |
| 2901 | const sym_index = self.getAtom(this_atom_index).getSymbolIndex().?; |
| 2902 | const atom_index = self.getAtomIndexForSymbol(.{ .sym_index = reloc_info.parent_atom_index }).?; |
| 2903 | try Atom.addRelocation(self, atom_index, .{ |
| 2904 | .type = .unsigned, |
| 2905 | .target = .{ .sym_index = sym_index }, |
| 2906 | .offset = @as(u32, @intCast(reloc_info.offset)), |
| 2907 | .addend = reloc_info.addend, |
| 2908 | .pcrel = false, |
| 2909 | .length = 3, |
| 2910 | }); |
| 2911 | try Atom.addRebase(self, atom_index, @as(u32, @intCast(reloc_info.offset))); |
| 2912 | |
| 2913 | return 0; |
| 2864 | 2914 | } |
| 2865 | 2915 | |
| 2866 | 2916 | fn populateMissingMetadata(self: *MachO) !void { |
| ... | ... | @@ -5412,6 +5462,7 @@ const DeclMetadata = struct { |
| 5412 | 5462 | } |
| 5413 | 5463 | }; |
| 5414 | 5464 | |
| 5465 | const AnonDeclTable = std.AutoHashMapUnmanaged(InternPool.Index, Atom.Index); |
| 5415 | 5466 | const BindingTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(Atom.Binding)); |
| 5416 | 5467 | const UnnamedConstTable = std.AutoArrayHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(Atom.Index)); |
| 5417 | 5468 | const RebaseTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(u32)); |