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) = .{},
109109/// value assigned to label `foo` is an unnamed constant belonging/associated
110110/// with `Decl` `main`, and lives as long as that `Decl`.
111111unnamed_const_atoms: UnnamedConstTable = .{},
112anon_decls: AnonDeclTable = .{},
112113
113114/// A table of relocations indexed by the owning them `Atom`.
114115/// Note that once we refactor `Atom`'s lifetime and ownership rules,
......@@ -1899,6 +1900,7 @@ pub fn deinit(self: *MachO) void {
18991900 atoms.deinit(gpa);
19001901 }
19011902 self.unnamed_const_atoms.deinit(gpa);
1903 self.anon_decls.deinit(gpa);
19021904
19031905 self.atom_by_index_table.deinit(gpa);
19041906
......@@ -2172,27 +2174,49 @@ pub fn updateFunc(self: *MachO, mod: *Module, func_index: InternPool.Index, air:
21722174
21732175pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Module.Decl.Index) !u32 {
21742176 const gpa = self.base.allocator;
2175
2176 var code_buffer = std.ArrayList(u8).init(gpa);
2177 defer code_buffer.deinit();
2178
21792177 const mod = self.base.options.module.?;
21802178 const gop = try self.unnamed_const_atoms.getOrPut(gpa, decl_index);
21812179 if (!gop.found_existing) {
21822180 gop.value_ptr.* = .{};
21832181 }
21842182 const unnamed_consts = gop.value_ptr;
2185
21862183 const decl = mod.declPtr(decl_index);
21872184 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 },
21942196 };
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
21972221 log.debug("allocating symbol indexes for {s}", .{name});
21982222
......@@ -2200,40 +2224,33 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Modu
22002224 const atom_index = try self.createAtom(sym_index, .{});
22012225 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, .{
22042228 .parent_atom_index = self.getAtom(atom_index).getSymbolIndex().?,
22052229 });
22062230 var code = switch (res) {
22072231 .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 },
22142233 };
22152234
2216 const required_alignment = typed_value.ty.abiAlignment(mod);
2235 const required_alignment = tv.ty.abiAlignment(mod);
22172236 const atom = self.getAtomPtr(atom_index);
22182237 atom.size = code.len;
22192238 // TODO: work out logic for disambiguating functions from function pointers
22202239 // const sect_id = self.getDeclOutputSection(decl_index);
2221 const sect_id = self.data_const_section_index.?;
22222240 const symbol = atom.getSymbolPtr(self);
2241 const name_str_index = try self.strtab.insert(gpa, name);
22232242 symbol.n_strx = name_str_index;
22242243 symbol.n_type = macho.N_SECT;
22252244 symbol.n_sect = sect_id + 1;
22262245 symbol.n_value = try self.allocateAtom(atom_index, code.len, required_alignment);
22272246 errdefer self.freeAtom(atom_index);
22282247
2229 try unnamed_consts.append(gpa, atom_index);
2230
22312248 log.debug("allocated atom for {s} at 0x{x}", .{ name, symbol.n_value });
22322249 log.debug(" (required alignment 0x{x})", .{required_alignment});
22332250
22342251 try self.writeAtom(atom_index, code);
22352252
2236 return atom.getSymbolIndex().?;
2253 return .{ .ok = atom_index };
22372254}
22382255
22392256pub 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
28502867 // be used by more than one function, however, its address is being used so we need
28512868 // to put it in some location.
28522869 // ...
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;
28572895}
28582896
28592897pub 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;
28642914}
28652915
28662916fn populateMissingMetadata(self: *MachO) !void {
......@@ -5412,6 +5462,7 @@ const DeclMetadata = struct {
54125462 }
54135463};
54145464
5465const AnonDeclTable = std.AutoHashMapUnmanaged(InternPool.Index, Atom.Index);
54155466const BindingTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(Atom.Binding));
54165467const UnnamedConstTable = std.AutoArrayHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(Atom.Index));
54175468const RebaseTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(u32));