From 0483b4a5126c0d07b1e9ad298729e8d34b5d2272 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 30 Sep 2023 21:41:36 -0700 Subject: [PATCH] link: stub out getAnonDeclVAddr --- src/codegen.zig | 53 ++++++++++++++++++++++++++++++++++------------ src/link.zig | 14 ++++++++++++ src/link/Coff.zig | 21 ++++++++++++++++++ src/link/Elf.zig | 21 ++++++++++++++++++ src/link/MachO.zig | 21 ++++++++++++++++++ src/link/Plan9.zig | 21 ++++++++++++++++++ src/link/Wasm.zig | 21 ++++++++++++++++++ 7 files changed, 159 insertions(+), 13 deletions(-) diff --git a/src/codegen.zig b/src/codegen.zig index ecbc05b1cc1439d44178709c8fe13793b5187b59..f2eff7806a5471449602ceb6521f48b1059e3ba9 100644 --- a/src/codegen.zig +++ b/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, diff --git a/src/link.zig b/src/link.zig index dd94ed9a5664e7812b040ad8f3930e1dcd7cd3bc..3c4a6d18f4a9ce476ec2a3f62b6f749b4a64fe16 100644 --- a/src/link.zig +++ b/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]`. diff --git a/src/link/Coff.zig b/src/link/Coff.zig index 40e33db2bd8dc44b658b058357175198ed9c2447..8aebd0de6a6f2c8118f9c046801e36e27eaa4b4a 100644 --- a/src/link/Coff.zig +++ b/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).?; diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 8e214da1bc78c8c67fb5f24ecc670f20dc77ea55..eff720eac439233a53a72e83c83f176ba2c05082 100644 --- a/src/link/Elf.zig +++ b/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; diff --git a/src/link/MachO.zig b/src/link/MachO.zig index b779aff41f9cdb06ab63dba74c5d7ae57b72da74..3786eccba92b1bd53c7127bdd1976eaf6d89bd0f 100644 --- a/src/link/MachO.zig +++ b/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); diff --git a/src/link/Plan9.zig b/src/link/Plan9.zig index 98f5b37a82f03567a7b7220c1c01cc18a0bcaaf8..ba333c666cc2f681c21ad1552e28570b2003b008 100644 --- a/src/link/Plan9.zig +++ b/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) { diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index a59527359c12ea7223283f891b78a315381e342f..9ae580bb9e9dd6339902a3800b05d205c9454bf2 100644 --- a/src/link/Wasm.zig +++ b/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; -- 2.54.0