Commit 0483b4a512

Andrew Kelley <andrew@ziglang.org>
2023-10-01 06:41:36
link: stub out getAnonDeclVAddr
1 parent c4b0b7a
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]`.