diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2023-10-03 14:55:18 +0200 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2023-10-03 12:49:12 -0700 |
| commit | 0134e5d2a1a5042b1485b7bb121870d2eaeb00b6 (patch) | |
| tree | 1c5e41cffa699a0e396a08771152d6e024a61af5 /src/link | |
| parent | 0483b4a5126c0d07b1e9ad298729e8d34b5d2272 (diff) | |
| download | zig-0134e5d2a1a5042b1485b7bb121870d2eaeb00b6.tar.gz zig-0134e5d2a1a5042b1485b7bb121870d2eaeb00b6.zip | |
codegen: separate getAnonDeclVAddr into lowerAnonDecl and the former
Implement the stub for Elf.
I believe that separating the concerns, namely, having an interface
function that is responsible for signalling the linker to lower
the anon decl only, and a separate function to obtain the decl's
vaddr is preferable since it allows us to handle codegen errors
in a simpler way.
Diffstat (limited to 'src/link')
| -rw-r--r-- | src/link/Coff.zig | 16 | ||||
| -rw-r--r-- | src/link/Elf.zig | 125 | ||||
| -rw-r--r-- | src/link/MachO.zig | 16 | ||||
| -rw-r--r-- | src/link/Plan9.zig | 16 | ||||
| -rw-r--r-- | src/link/Wasm.zig | 16 |
5 files changed, 123 insertions, 66 deletions
diff --git a/src/link/Coff.zig b/src/link/Coff.zig index 8aebd0de6a..bfd7c9da46 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -1727,13 +1727,8 @@ pub fn getDeclVAddr(self: *Coff, decl_index: Module.Decl.Index, reloc_info: link return 0; } -pub fn getAnonDeclVAddr( - self: *Coff, - decl_val: InternPool.Index, - reloc_info: link.File.RelocInfo, -) !u64 { - // This is basically the same as lowerUnnamedConst except it needs - // to return the same thing as `getDeclVAddr` +pub fn lowerAnonDecl(self: *Coff, decl_val: InternPool.Index, src_loc: Module.SrcLoc) !codegen.Result { + // This is basically the same as lowerUnnamedConst. // example: // const ty = mod.intern_pool.typeOf(decl_val).toType(); // const val = decl_val.toValue(); @@ -1744,6 +1739,13 @@ pub fn getAnonDeclVAddr( // ... _ = self; _ = decl_val; + _ = src_loc; + _ = @panic("TODO: link/Coff lowerAnonDecl"); +} + +pub fn getAnonDeclVAddr(self: *Coff, decl_val: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 { + _ = self; + _ = decl_val; _ = reloc_info; _ = @panic("TODO: link/Coff getAnonDeclVAddr"); } diff --git a/src/link/Elf.zig b/src/link/Elf.zig index eff720eac4..a9a4757883 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -155,12 +155,14 @@ last_atom_and_free_list_table: std.AutoArrayHashMapUnmanaged(u16, LastAtomAndFre /// value assigned to label `foo` is an unnamed constant belonging/associated /// with `Decl` `main`, and lives as long as that `Decl`. unnamed_consts: UnnamedConstTable = .{}, +anon_decls: AnonDeclTable = .{}, comdat_groups: std.ArrayListUnmanaged(ComdatGroup) = .{}, comdat_groups_owners: std.ArrayListUnmanaged(ComdatGroupOwner) = .{}, comdat_groups_table: std.AutoHashMapUnmanaged(u32, ComdatGroupOwner.Index) = .{}, const UnnamedConstTable = std.AutoHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(Symbol.Index)); +const AnonDeclTable = std.AutoHashMapUnmanaged(InternPool.Index, Symbol.Index); const LazySymbolTable = std.AutoArrayHashMapUnmanaged(Module.Decl.OptionalIndex, LazySymbolMetadata); /// When allocating, the ideal_capacity is calculated by @@ -321,6 +323,7 @@ pub fn deinit(self: *Elf) void { } self.unnamed_consts.deinit(gpa); } + self.anon_decls.deinit(gpa); if (self.dwarf) |*dw| { dw.deinit(); @@ -348,13 +351,8 @@ pub fn getDeclVAddr(self: *Elf, decl_index: Module.Decl.Index, reloc_info: link. return vaddr; } -pub fn getAnonDeclVAddr( - self: *Elf, - decl_val: InternPool.Index, - reloc_info: link.File.RelocInfo, -) !u64 { - // This is basically the same as lowerUnnamedConst except it needs - // to return the same thing as `getDeclVAddr` +pub fn lowerAnonDecl(self: *Elf, decl_val: InternPool.Index, src_loc: Module.SrcLoc) !codegen.Result { + // This is basically the same as lowerUnnamedConst. // example: // const ty = mod.intern_pool.typeOf(decl_val).toType(); // const val = decl_val.toValue(); @@ -363,10 +361,44 @@ pub fn getAnonDeclVAddr( // be used by more than one function, however, its address is being used so we need // to put it in some location. // ... - _ = self; - _ = decl_val; - _ = reloc_info; - _ = @panic("TODO: link/Elf getAnonDeclVAddr"); + const gpa = self.base.allocator; + const gop = try self.anon_decls.getOrPut(gpa, decl_val); + if (!gop.found_existing) { + const mod = self.base.options.module.?; + const ty = mod.intern_pool.typeOf(decl_val).toType(); + const val = decl_val.toValue(); + const tv = TypedValue{ .ty = ty, .val = val }; + const name = try std.fmt.allocPrint(gpa, "__anon_{d}", .{@intFromEnum(decl_val)}); + defer gpa.free(name); + const res = self.lowerConst(name, tv, self.rodata_section_index.?, src_loc) catch |err| switch (err) { + else => { + // TODO improve error message + const em = try Module.ErrorMsg.create(gpa, src_loc, "lowerAnonDecl failed with error: {s}", .{ + @errorName(err), + }); + return .{ .fail = em }; + }, + }; + const sym_index = switch (res) { + .ok => |sym_index| sym_index, + .fail => |em| return .{ .fail = em }, + }; + gop.value_ptr.* = sym_index; + } + return .ok; +} + +pub fn getAnonDeclVAddr(self: *Elf, decl_val: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 { + const sym_index = self.anon_decls.get(decl_val).?; + const sym = self.symbol(sym_index); + const vaddr = sym.value; + const parent_atom = self.symbol(reloc_info.parent_atom_index).atom(self).?; + try parent_atom.addReloc(self, .{ + .r_offset = reloc_info.offset, + .r_info = (@as(u64, @intCast(sym.esym_index)) << 32) | elf.R_X86_64_64, + .r_addend = reloc_info.addend, + }); + return vaddr; } /// Returns end pos of collision, if any. @@ -3126,50 +3158,68 @@ fn updateLazySymbol(self: *Elf, sym: link.File.LazySymbol, symbol_index: Symbol. pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module.Decl.Index) !u32 { const gpa = self.base.allocator; - - var code_buffer = std.ArrayList(u8).init(gpa); - defer code_buffer.deinit(); - const mod = self.base.options.module.?; const gop = try self.unnamed_consts.getOrPut(gpa, decl_index); if (!gop.found_existing) { gop.value_ptr.* = .{}; } const unnamed_consts = gop.value_ptr; - const decl = mod.declPtr(decl_index); - const name_str_index = blk: { - const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod)); - const index = unnamed_consts.items.len; - const name = try std.fmt.allocPrint(gpa, "__unnamed_{s}_{d}", .{ decl_name, index }); - defer gpa.free(name); - break :blk try self.strtab.insert(gpa, name); + const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod)); + const index = unnamed_consts.items.len; + const name = try std.fmt.allocPrint(gpa, "__unnamed_{s}_{d}", .{ decl_name, index }); + defer gpa.free(name); + const sym_index = switch (try self.lowerConst(name, typed_value, self.rodata_section_index.?, decl.srcLoc(mod))) { + .ok => |sym_index| sym_index, + .fail => |em| { + decl.analysis = .codegen_failure; + try mod.failed_decls.put(mod.gpa, decl_index, em); + log.err("{s}", .{em.msg}); + return error.CodegenFail; + }, }; + const sym = self.symbol(sym_index); + try unnamed_consts.append(gpa, sym.atom_index); + return sym_index; +} + +const LowerConstResult = union(enum) { + ok: Symbol.Index, + fail: *Module.ErrorMsg, +}; + +fn lowerConst( + self: *Elf, + name: []const u8, + tv: TypedValue, + output_section_index: u16, + src_loc: Module.SrcLoc, +) !LowerConstResult { + const gpa = self.base.allocator; + + var code_buffer = std.ArrayList(u8).init(gpa); + defer code_buffer.deinit(); + const mod = self.base.options.module.?; const zig_module = self.file(self.zig_module_index.?).?.zig_module; const sym_index = try zig_module.addAtom(self); - const res = try codegen.generateSymbol(&self.base, decl.srcLoc(mod), typed_value, &code_buffer, .{ + const res = try codegen.generateSymbol(&self.base, src_loc, tv, &code_buffer, .{ .none = {}, }, .{ .parent_atom_index = sym_index, }); const code = switch (res) { .ok => code_buffer.items, - .fail => |em| { - decl.analysis = .codegen_failure; - try mod.failed_decls.put(mod.gpa, decl_index, em); - log.err("{s}", .{em.msg}); - return error.CodegenFail; - }, + .fail => |em| return .{ .fail = em }, }; - const required_alignment = typed_value.ty.abiAlignment(mod); - const shdr_index = self.rodata_section_index.?; - const phdr_index = self.phdr_to_shdr_table.get(shdr_index).?; + const required_alignment = tv.ty.abiAlignment(mod); + const phdr_index = self.phdr_to_shdr_table.get(output_section_index).?; const local_sym = self.symbol(sym_index); + const name_str_index = try self.strtab.insert(gpa, name); local_sym.name_offset = name_str_index; - local_sym.output_section_index = self.rodata_section_index.?; + local_sym.output_section_index = output_section_index; const local_esym = &zig_module.local_esyms.items[local_sym.esym_index]; local_esym.st_name = name_str_index; local_esym.st_info |= elf.STT_OBJECT; @@ -3179,21 +3229,20 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module atom_ptr.name_offset = name_str_index; atom_ptr.alignment = required_alignment; atom_ptr.size = code.len; - atom_ptr.output_section_index = self.rodata_section_index.?; + atom_ptr.output_section_index = output_section_index; try atom_ptr.allocate(self); + // TODO rename and re-audit this method errdefer self.freeDeclMetadata(sym_index); local_sym.value = atom_ptr.value; local_esym.st_value = atom_ptr.value; - try unnamed_consts.append(gpa, atom_ptr.atom_index); - const section_offset = atom_ptr.value - self.phdrs.items[phdr_index].p_vaddr; - const file_offset = self.shdrs.items[shdr_index].sh_offset + section_offset; + const file_offset = self.shdrs.items[output_section_index].sh_offset + section_offset; try self.base.file.?.pwriteAll(code, file_offset); - return sym_index; + return .{ .ok = sym_index }; } pub fn updateDeclExports( diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 3786eccba9..10e6c614de 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -2840,13 +2840,8 @@ pub fn getDeclVAddr(self: *MachO, decl_index: Module.Decl.Index, reloc_info: Fil return 0; } -pub fn getAnonDeclVAddr( - self: *MachO, - decl_val: InternPool.Index, - reloc_info: link.File.RelocInfo, -) !u64 { - // This is basically the same as lowerUnnamedConst except it needs - // to return the same thing as `getDeclVAddr` +pub fn lowerAnonDecl(self: *MachO, decl_val: InternPool.Index, src_loc: Module.SrcLoc) !codegen.Result { + // This is basically the same as lowerUnnamedConst. // example: // const ty = mod.intern_pool.typeOf(decl_val).toType(); // const val = decl_val.toValue(); @@ -2857,6 +2852,13 @@ pub fn getAnonDeclVAddr( // ... _ = self; _ = decl_val; + _ = src_loc; + _ = @panic("TODO: link/MachO lowerAnonDecl"); +} + +pub fn getAnonDeclVAddr(self: *MachO, decl_val: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 { + _ = self; + _ = decl_val; _ = reloc_info; _ = @panic("TODO: link/MachO getAnonDeclVAddr"); } diff --git a/src/link/Plan9.zig b/src/link/Plan9.zig index ba333c666c..5355e19e1b 100644 --- a/src/link/Plan9.zig +++ b/src/link/Plan9.zig @@ -1418,13 +1418,8 @@ pub fn getDeclVAddr( return undefined; } -pub fn getAnonDeclVAddr( - self: *Plan9, - decl_val: InternPool.Index, - reloc_info: link.File.RelocInfo, -) !u64 { - // This is basically the same as lowerUnnamedConst except it needs - // to return the same thing as `getDeclVAddr` +pub fn lowerAnonDecl(self: *Plan9, decl_val: InternPool.Index, src_loc: Module.SrcLoc) !codegen.Result { + // This is basically the same as lowerUnnamedConst. // example: // const ty = mod.intern_pool.typeOf(decl_val).toType(); // const val = decl_val.toValue(); @@ -1435,6 +1430,13 @@ pub fn getAnonDeclVAddr( // ... _ = self; _ = decl_val; + _ = src_loc; + _ = @panic("TODO: link/Plan9 lowerAnonDecl"); +} + +pub fn getAnonDeclVAddr(self: *Plan9, decl_val: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 { + _ = self; + _ = decl_val; _ = reloc_info; _ = @panic("TODO: link/Plan9 getAnonDeclVAddr"); } diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 9ae580bb9e..34244d2247 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -1679,13 +1679,8 @@ pub fn getDeclVAddr( return target_symbol_index; } -pub fn getAnonDeclVAddr( - wasm: *Wasm, - decl_val: InternPool.Index, - reloc_info: link.File.RelocInfo, -) !u64 { - // This is basically the same as lowerUnnamedConst except it needs - // to return the same thing as `getDeclVAddr` +pub fn lowerAnonDecl(self: *Wasm, decl_val: InternPool.Index, src_loc: Module.SrcLoc) !codegen.Result { + // This is basically the same as lowerUnnamedConst. // example: // const ty = mod.intern_pool.typeOf(decl_val).toType(); // const val = decl_val.toValue(); @@ -1694,6 +1689,13 @@ pub fn getAnonDeclVAddr( // be used by more than one function, however, its address is being used so we need // to put it in some location. // ... + _ = self; + _ = decl_val; + _ = src_loc; + _ = @panic("TODO: link/Wasm lowerAnonDecl"); +} + +pub fn getAnonDeclVAddr(wasm: *Wasm, decl_val: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 { _ = wasm; _ = decl_val; _ = reloc_info; |
