| ... | @@ -109,6 +109,7 @@ atom_by_index_table: std.AutoHashMapUnmanaged(u32, Atom.Index) = .{}, | ... | @@ -109,6 +109,7 @@ atom_by_index_table: std.AutoHashMapUnmanaged(u32, Atom.Index) = .{}, |
| 109 | /// value assigned to label `foo` is an unnamed constant belonging/associated | 109 | /// value assigned to label `foo` is an unnamed constant belonging/associated |
| 110 | /// with `Decl` `main`, and lives as long as that `Decl`. | 110 | /// with `Decl` `main`, and lives as long as that `Decl`. |
| 111 | unnamed_const_atoms: UnnamedConstTable = .{}, | 111 | unnamed_const_atoms: UnnamedConstTable = .{}, |
| | 112 | anon_decls: AnonDeclTable = .{}, |
| 112 | | 113 | |
| 113 | /// A table of relocations indexed by the owning them `Atom`. | 114 | /// A table of relocations indexed by the owning them `Atom`. |
| 114 | /// Note that once we refactor `Atom`'s lifetime and ownership rules, | 115 | /// Note that once we refactor `Atom`'s lifetime and ownership rules, |
| ... | @@ -1899,6 +1900,7 @@ pub fn deinit(self: *MachO) void { | ... | @@ -1899,6 +1900,7 @@ pub fn deinit(self: *MachO) void { |
| 1899 | atoms.deinit(gpa); | 1900 | atoms.deinit(gpa); |
| 1900 | } | 1901 | } |
| 1901 | self.unnamed_const_atoms.deinit(gpa); | 1902 | self.unnamed_const_atoms.deinit(gpa); |
| | 1903 | self.anon_decls.deinit(gpa); |
| 1902 | | 1904 | |
| 1903 | self.atom_by_index_table.deinit(gpa); | 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,27 +2174,49 @@ pub fn updateFunc(self: *MachO, mod: *Module, func_index: InternPool.Index, air: |
| 2172 | | 2174 | |
| 2173 | pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Module.Decl.Index) !u32 { | 2175 | pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Module.Decl.Index) !u32 { |
| 2174 | const gpa = self.base.allocator; | 2176 | const gpa = self.base.allocator; |
| 2175 | | | |
| 2176 | var code_buffer = std.ArrayList(u8).init(gpa); | | |
| 2177 | defer code_buffer.deinit(); | | |
| 2178 | | | |
| 2179 | const mod = self.base.options.module.?; | 2177 | const mod = self.base.options.module.?; |
| 2180 | const gop = try self.unnamed_const_atoms.getOrPut(gpa, decl_index); | 2178 | const gop = try self.unnamed_const_atoms.getOrPut(gpa, decl_index); |
| 2181 | if (!gop.found_existing) { | 2179 | if (!gop.found_existing) { |
| 2182 | gop.value_ptr.* = .{}; | 2180 | gop.value_ptr.* = .{}; |
| 2183 | } | 2181 | } |
| 2184 | const unnamed_consts = gop.value_ptr; | 2182 | const unnamed_consts = gop.value_ptr; |
| 2185 | | | |
| 2186 | const decl = mod.declPtr(decl_index); | 2183 | const decl = mod.declPtr(decl_index); |
| 2187 | const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod)); | 2184 | const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod)); |
| 2188 | | 2185 | const index = unnamed_consts.items.len; |
| 2189 | const name_str_index = blk: { | 2186 | const name = try std.fmt.allocPrint(gpa, "___unnamed_{s}_{d}", .{ decl_name, index }); |
| 2190 | const index = unnamed_consts.items.len; | 2187 | defer gpa.free(name); |
| 2191 | const name = try std.fmt.allocPrint(gpa, "___unnamed_{s}_{d}", .{ decl_name, index }); | 2188 | const atom_index = switch (try self.lowerConst(name, typed_value, self.data_const_section_index.?, decl.srcLoc(mod))) { |
| 2192 | defer gpa.free(name); | 2189 | .ok => |atom_index| atom_index, |
| 2193 | break :blk try self.strtab.insert(gpa, name); | 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 | log.debug("allocating symbol indexes for {s}", .{name}); | 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,40 +2224,33 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Modu |
| 2200 | const atom_index = try self.createAtom(sym_index, .{}); | 2224 | const atom_index = try self.createAtom(sym_index, .{}); |
| 2201 | try self.atom_by_index_table.putNoClobber(gpa, sym_index, atom_index); | 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 | .parent_atom_index = self.getAtom(atom_index).getSymbolIndex().?, | 2228 | .parent_atom_index = self.getAtom(atom_index).getSymbolIndex().?, |
| 2205 | }); | 2229 | }); |
| 2206 | var code = switch (res) { | 2230 | var code = switch (res) { |
| 2207 | .ok => code_buffer.items, | 2231 | .ok => code_buffer.items, |
| 2208 | .fail => |em| { | 2232 | .fail => |em| return .{ .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 | }, | | |
| 2214 | }; | 2233 | }; |
| 2215 | | 2234 | |
| 2216 | const required_alignment = typed_value.ty.abiAlignment(mod); | 2235 | const required_alignment = tv.ty.abiAlignment(mod); |
| 2217 | const atom = self.getAtomPtr(atom_index); | 2236 | const atom = self.getAtomPtr(atom_index); |
| 2218 | atom.size = code.len; | 2237 | atom.size = code.len; |
| 2219 | // TODO: work out logic for disambiguating functions from function pointers | 2238 | // TODO: work out logic for disambiguating functions from function pointers |
| 2220 | // const sect_id = self.getDeclOutputSection(decl_index); | 2239 | // const sect_id = self.getDeclOutputSection(decl_index); |
| 2221 | const sect_id = self.data_const_section_index.?; | | |
| 2222 | const symbol = atom.getSymbolPtr(self); | 2240 | const symbol = atom.getSymbolPtr(self); |
| | 2241 | const name_str_index = try self.strtab.insert(gpa, name); |
| 2223 | symbol.n_strx = name_str_index; | 2242 | symbol.n_strx = name_str_index; |
| 2224 | symbol.n_type = macho.N_SECT; | 2243 | symbol.n_type = macho.N_SECT; |
| 2225 | symbol.n_sect = sect_id + 1; | 2244 | symbol.n_sect = sect_id + 1; |
| 2226 | symbol.n_value = try self.allocateAtom(atom_index, code.len, required_alignment); | 2245 | symbol.n_value = try self.allocateAtom(atom_index, code.len, required_alignment); |
| 2227 | errdefer self.freeAtom(atom_index); | 2246 | errdefer self.freeAtom(atom_index); |
| 2228 | | 2247 | |
| 2229 | try unnamed_consts.append(gpa, atom_index); | | |
| 2230 | | | |
| 2231 | log.debug("allocated atom for {s} at 0x{x}", .{ name, symbol.n_value }); | 2248 | log.debug("allocated atom for {s} at 0x{x}", .{ name, symbol.n_value }); |
| 2232 | log.debug(" (required alignment 0x{x})", .{required_alignment}); | 2249 | log.debug(" (required alignment 0x{x})", .{required_alignment}); |
| 2233 | | 2250 | |
| 2234 | try self.writeAtom(atom_index, code); | 2251 | try self.writeAtom(atom_index, code); |
| 2235 | | 2252 | |
| 2236 | return atom.getSymbolIndex().?; | 2253 | return .{ .ok = atom_index }; |
| 2237 | } | 2254 | } |
| 2238 | | 2255 | |
| 2239 | pub fn updateDecl(self: *MachO, mod: *Module, decl_index: Module.Decl.Index) !void { | 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,17 +2867,50 @@ pub fn lowerAnonDecl(self: *MachO, decl_val: InternPool.Index, src_loc: Module.S |
| 2850 | // be used by more than one function, however, its address is being used so we need | 2867 | // be used by more than one function, however, its address is being used so we need |
| 2851 | // to put it in some location. | 2868 | // to put it in some location. |
| 2852 | // ... | 2869 | // ... |
| 2853 | _ = self; | 2870 | const gpa = self.base.allocator; |
| 2854 | _ = decl_val; | 2871 | const gop = try self.anon_decls.getOrPut(gpa, decl_val); |
| 2855 | _ = src_loc; | 2872 | if (!gop.found_existing) { |
| 2856 | _ = @panic("TODO: link/MachO lowerAnonDecl"); | 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 | pub fn getAnonDeclVAddr(self: *MachO, decl_val: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 { | 2897 | pub fn getAnonDeclVAddr(self: *MachO, decl_val: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 { |
| 2860 | _ = self; | 2898 | assert(self.llvm_object == null); |
| 2861 | _ = decl_val; | 2899 | |
| 2862 | _ = reloc_info; | 2900 | const this_atom_index = self.anon_decls.get(decl_val).?; |
| 2863 | _ = @panic("TODO: link/MachO getAnonDeclVAddr"); | 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 | fn populateMissingMetadata(self: *MachO) !void { | 2916 | fn populateMissingMetadata(self: *MachO) !void { |
| ... | @@ -5412,6 +5462,7 @@ const DeclMetadata = struct { | ... | @@ -5412,6 +5462,7 @@ const DeclMetadata = struct { |
| 5412 | } | 5462 | } |
| 5413 | }; | 5463 | }; |
| 5414 | | 5464 | |
| | 5465 | const AnonDeclTable = std.AutoHashMapUnmanaged(InternPool.Index, Atom.Index); |
| 5415 | const BindingTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(Atom.Binding)); | 5466 | const BindingTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(Atom.Binding)); |
| 5416 | const UnnamedConstTable = std.AutoArrayHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(Atom.Index)); | 5467 | const UnnamedConstTable = std.AutoArrayHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(Atom.Index)); |
| 5417 | const RebaseTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(u32)); | 5468 | const RebaseTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(u32)); |