Commit 0483b4a512
src/link/Coff.zig
@@ -1727,6 +1727,27 @@ 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`
+ // example:
+ // const ty = mod.intern_pool.typeOf(decl_val).toType();
+ // const val = decl_val.toValue();
+ // The symbol name can be something like `__anon_{d}` with `@intFromEnum(decl_val)`.
+ // It doesn't have an owner decl because it's just an unnamed constant that might
+ // 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/Coff getAnonDeclVAddr");
+}
+
pub fn getGlobalSymbol(self: *Coff, name: []const u8, lib_name_name: ?[]const u8) !u32 {
const gop = try self.getOrPutGlobalPtr(name);
const global_index = self.getGlobalIndex(name).?;
src/link/Elf.zig
@@ -348,6 +348,27 @@ 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`
+ // example:
+ // const ty = mod.intern_pool.typeOf(decl_val).toType();
+ // const val = decl_val.toValue();
+ // The symbol name can be something like `__anon_{d}` with `@intFromEnum(decl_val)`.
+ // It doesn't have an owner decl because it's just an unnamed constant that might
+ // 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");
+}
+
/// Returns end pos of collision, if any.
fn detectAllocCollision(self: *Elf, start: u64, size: u64) ?u64 {
const small_ptr = self.ptr_width == .p32;
src/link/MachO.zig
@@ -2840,6 +2840,27 @@ 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`
+ // example:
+ // const ty = mod.intern_pool.typeOf(decl_val).toType();
+ // const val = decl_val.toValue();
+ // The symbol name can be something like `__anon_{d}` with `@intFromEnum(decl_val)`.
+ // It doesn't have an owner decl because it's just an unnamed constant that might
+ // 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/MachO getAnonDeclVAddr");
+}
+
fn populateMissingMetadata(self: *MachO) !void {
assert(self.mode == .incremental);
src/link/Plan9.zig
@@ -1418,6 +1418,27 @@ 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`
+ // example:
+ // const ty = mod.intern_pool.typeOf(decl_val).toType();
+ // const val = decl_val.toValue();
+ // The symbol name can be something like `__anon_{d}` with `@intFromEnum(decl_val)`.
+ // It doesn't have an owner decl because it's just an unnamed constant that might
+ // 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/Plan9 getAnonDeclVAddr");
+}
+
pub fn addReloc(self: *Plan9, parent_index: Atom.Index, reloc: Reloc) !void {
const gop = try self.relocs.getOrPut(self.base.allocator, parent_index);
if (!gop.found_existing) {
src/link/Wasm.zig
@@ -1679,6 +1679,27 @@ 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`
+ // example:
+ // const ty = mod.intern_pool.typeOf(decl_val).toType();
+ // const val = decl_val.toValue();
+ // The symbol name can be something like `__anon_{d}` with `@intFromEnum(decl_val)`.
+ // It doesn't have an owner decl because it's just an unnamed constant that might
+ // be used by more than one function, however, its address is being used so we need
+ // to put it in some location.
+ // ...
+ _ = wasm;
+ _ = decl_val;
+ _ = reloc_info;
+ _ = @panic("TODO: link/Wasm getAnonDeclVAddr");
+}
+
pub fn deleteDeclExport(wasm: *Wasm, decl_index: Module.Decl.Index) void {
if (wasm.llvm_object) |_| return;
const atom_index = wasm.decls.get(decl_index) orelse return;
src/codegen.zig
@@ -643,19 +643,9 @@ fn lowerParentPtr(
const ptr = mod.intern_pool.indexToKey(parent_ptr).ptr;
assert(ptr.len == .none);
return switch (ptr.addr) {
- .decl, .mut_decl => try lowerDeclRef(
- bin_file,
- src_loc,
- switch (ptr.addr) {
- .decl => |decl| decl,
- .mut_decl => |mut_decl| mut_decl.decl,
- else => unreachable,
- },
- code,
- debug_output,
- reloc_info,
- ),
- .anon_decl => @panic("TODO"),
+ .decl => |decl| try lowerDeclRef(bin_file, src_loc, decl, code, debug_output, reloc_info),
+ .mut_decl => |md| try lowerDeclRef(bin_file, src_loc, md.decl, code, debug_output, reloc_info),
+ .anon_decl => |ad| try lowerAnonDeclRef(bin_file, src_loc, ad, code, debug_output, reloc_info),
.int => |int| try generateSymbol(bin_file, src_loc, .{
.ty = Type.usize,
.val = int.toValue(),
@@ -741,6 +731,43 @@ const RelocInfo = struct {
}
};
+fn lowerAnonDeclRef(
+ bin_file: *link.File,
+ src_loc: Module.SrcLoc,
+ decl_val: InternPool.Index,
+ code: *std.ArrayList(u8),
+ debug_output: DebugInfoOutput,
+ reloc_info: RelocInfo,
+) CodeGenError!Result {
+ _ = src_loc;
+ _ = debug_output;
+ const target = bin_file.options.target;
+ const mod = bin_file.options.module.?;
+
+ const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8);
+ const decl_ty = mod.intern_pool.typeOf(decl_val).toType();
+ const is_fn_body = decl_ty.zigTypeTag(mod) == .Fn;
+ if (!is_fn_body and !decl_ty.hasRuntimeBits(mod)) {
+ try code.appendNTimes(0xaa, ptr_width_bytes);
+ return Result.ok;
+ }
+
+ const vaddr = try bin_file.getAnonDeclVAddr(decl_val, .{
+ .parent_atom_index = reloc_info.parent_atom_index,
+ .offset = code.items.len,
+ .addend = reloc_info.addend orelse 0,
+ });
+ const endian = target.cpu.arch.endian();
+ switch (ptr_width_bytes) {
+ 2 => mem.writeInt(u16, try code.addManyAsArray(2), @intCast(vaddr), endian),
+ 4 => mem.writeInt(u32, try code.addManyAsArray(4), @intCast(vaddr), endian),
+ 8 => mem.writeInt(u64, try code.addManyAsArray(8), vaddr, endian),
+ else => unreachable,
+ }
+
+ return Result.ok;
+}
+
fn lowerDeclRef(
bin_file: *link.File,
src_loc: Module.SrcLoc,
src/link.zig
@@ -937,6 +937,20 @@ pub const File = struct {
}
}
+ pub fn getAnonDeclVAddr(base: *File, decl_val: InternPool.Index, reloc_info: RelocInfo) !u64 {
+ if (build_options.only_c) unreachable;
+ switch (base.tag) {
+ .coff => return @fieldParentPtr(Coff, "base", base).getAnonDeclVAddr(decl_val, reloc_info),
+ .elf => return @fieldParentPtr(Elf, "base", base).getAnonDeclVAddr(decl_val, reloc_info),
+ .macho => return @fieldParentPtr(MachO, "base", base).getAnonDeclVAddr(decl_val, reloc_info),
+ .plan9 => return @fieldParentPtr(Plan9, "base", base).getAnonDeclVAddr(decl_val, reloc_info),
+ .c => unreachable,
+ .wasm => return @fieldParentPtr(Wasm, "base", base).getAnonDeclVAddr(decl_val, reloc_info),
+ .spirv => unreachable,
+ .nvptx => unreachable,
+ }
+ }
+
/// This function is called by the frontend before flush(). It communicates that
/// `options.bin_file.emit` directory needs to be renamed from
/// `[zig-cache]/tmp/[random]` to `[zig-cache]/o/[digest]`.