Commit 0134e5d2a1
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();
@@ -1742,6 +1737,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/Coff lowerAnonDecl");
+}
+
+pub fn getAnonDeclVAddr(self: *Coff, decl_val: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 {
_ = self;
_ = decl_val;
_ = reloc_info;
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(
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();
@@ -2855,6 +2850,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/MachO lowerAnonDecl");
+}
+
+pub fn getAnonDeclVAddr(self: *MachO, decl_val: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 {
_ = self;
_ = decl_val;
_ = reloc_info;
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();
@@ -1433,6 +1428,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/Plan9 lowerAnonDecl");
+}
+
+pub fn getAnonDeclVAddr(self: *Plan9, decl_val: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 {
_ = self;
_ = decl_val;
_ = reloc_info;
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;
src/codegen.zig
@@ -739,7 +739,6 @@ fn lowerAnonDeclRef(
debug_output: DebugInfoOutput,
reloc_info: RelocInfo,
) CodeGenError!Result {
- _ = src_loc;
_ = debug_output;
const target = bin_file.options.target;
const mod = bin_file.options.module.?;
@@ -752,6 +751,12 @@ fn lowerAnonDeclRef(
return Result.ok;
}
+ const res = try bin_file.lowerAnonDecl(decl_val, src_loc);
+ switch (res) {
+ .ok => {},
+ .fail => |em| return .{ .fail = em },
+ }
+
const vaddr = try bin_file.getAnonDeclVAddr(decl_val, .{
.parent_atom_index = reloc_info.parent_atom_index,
.offset = code.items.len,
src/link.zig
@@ -937,6 +937,22 @@ pub const File = struct {
}
}
+ pub const LowerResult = @import("codegen.zig").Result;
+
+ pub fn lowerAnonDecl(base: *File, decl_val: InternPool.Index, src_loc: Module.SrcLoc) !LowerResult {
+ if (build_options.only_c) unreachable;
+ switch (base.tag) {
+ .coff => return @fieldParentPtr(Coff, "base", base).lowerAnonDecl(decl_val, src_loc),
+ .elf => return @fieldParentPtr(Elf, "base", base).lowerAnonDecl(decl_val, src_loc),
+ .macho => return @fieldParentPtr(MachO, "base", base).lowerAnonDecl(decl_val, src_loc),
+ .plan9 => return @fieldParentPtr(Plan9, "base", base).lowerAnonDecl(decl_val, src_loc),
+ .c => unreachable,
+ .wasm => return @fieldParentPtr(Wasm, "base", base).lowerAnonDecl(decl_val, src_loc),
+ .spirv => unreachable,
+ .nvptx => unreachable,
+ }
+ }
+
pub fn getAnonDeclVAddr(base: *File, decl_val: InternPool.Index, reloc_info: RelocInfo) !u64 {
if (build_options.only_c) unreachable;
switch (base.tag) {