authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-10-03 15:11:56+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-10-03 12:49:17-07:00
log57eefe0533d6de517f42be4fa9ddfc9ff7ab5c53
tree9462288d5e4499fd15f084a26c6d42fc5a14df2d
parent0134e5d2a1a5042b1485b7bb121870d2eaeb00b6

macho: implement lowering anon decls


1 files changed, 83 insertions(+), 32 deletions(-)

src/link/MachO.zig+83-32
...@@ -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/associated109/// 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`.
111unnamed_const_atoms: UnnamedConstTable = .{},111unnamed_const_atoms: UnnamedConstTable = .{},
112anon_decls: AnonDeclTable = .{},
112113
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);
19021904
1903 self.atom_by_index_table.deinit(gpa);1905 self.atom_by_index_table.deinit(gpa);
19041906
...@@ -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:
21722174
2173pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Module.Decl.Index) !u32 {2175pub 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));
21882185 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
2202const LowerConstResult = union(enum) {
2203 ok: Atom.Index,
2204 fail: *Module.ErrorMsg,
2205};
2206
2207fn 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.?;
21962220
2197 log.debug("allocating symbol indexes for {s}", .{name});2221 log.debug("allocating symbol indexes for {s}", .{name});
21982222
...@@ -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);
22022226
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 };
22152234
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 pointers2238 // 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);
22282247
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});
22332250
2234 try self.writeAtom(atom_index, code);2251 try self.writeAtom(atom_index, code);
22352252
2236 return atom.getSymbolIndex().?;2253 return .{ .ok = atom_index };
2237}2254}
22382255
2239pub fn updateDecl(self: *MachO, mod: *Module, decl_index: Module.Decl.Index) !void {2256pub 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 need2867 // 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}
28582896
2859pub fn getAnonDeclVAddr(self: *MachO, decl_val: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 {2897pub 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}
28652915
2866fn populateMissingMetadata(self: *MachO) !void {2916fn populateMissingMetadata(self: *MachO) !void {
...@@ -5412,6 +5462,7 @@ const DeclMetadata = struct {...@@ -5412,6 +5462,7 @@ const DeclMetadata = struct {
5412 }5462 }
5413};5463};
54145464
5465const AnonDeclTable = std.AutoHashMapUnmanaged(InternPool.Index, Atom.Index);
5415const BindingTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(Atom.Binding));5466const BindingTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(Atom.Binding));
5416const UnnamedConstTable = std.AutoArrayHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(Atom.Index));5467const UnnamedConstTable = std.AutoArrayHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(Atom.Index));
5417const RebaseTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(u32));5468const RebaseTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(u32));