Commit 96cc9fafbf

Jakub Konka <kubkon@jakubkonka.com>
2024-01-18 18:58:29
codegen: re-implement enough of codegen to error out instead panic
1 parent 76dc305
src/arch/x86_64/CodeGen.zig
@@ -139,10 +139,7 @@ const Owner = union(enum) {
                 if (ctx.bin_file.cast(link.File.Elf)) |elf_file| {
                     return elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, decl_index);
                 } else if (ctx.bin_file.cast(link.File.MachO)) |macho_file| {
-                    _ = macho_file;
-                    // const atom = try macho_file.getOrCreateAtomForDecl(decl_index);
-                    // return macho_file.getAtom(atom).getSymbolIndex().?;
-                    @panic("TODO getSymbolIndex");
+                    return macho_file.getZigObject().?.getOrCreateMetadataForDecl(macho_file, decl_index);
                 } else if (ctx.bin_file.cast(link.File.Coff)) |coff_file| {
                     const atom = try coff_file.getOrCreateAtomForDecl(decl_index);
                     return coff_file.getAtom(atom).getSymbolIndex().?;
@@ -155,11 +152,8 @@ const Owner = union(enum) {
                     return elf_file.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(elf_file, lazy_sym) catch |err|
                         ctx.fail("{s} creating lazy symbol", .{@errorName(err)});
                 } else if (ctx.bin_file.cast(link.File.MachO)) |macho_file| {
-                    _ = macho_file;
-                    // const atom = macho_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err|
-                    //     return ctx.fail("{s} creating lazy symbol", .{@errorName(err)});
-                    // return macho_file.getAtom(atom).getSymbolIndex().?;
-                    @panic("TODO getSymbolIndex");
+                    return macho_file.getZigObject().?.getOrCreateMetadataForLazySymbol(macho_file, lazy_sym) catch |err|
+                        ctx.fail("{s} creating lazy symbol", .{@errorName(err)});
                 } else if (ctx.bin_file.cast(link.File.Coff)) |coff_file| {
                     const atom = coff_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err|
                         return ctx.fail("{s} creating lazy symbol", .{@errorName(err)});
@@ -10955,12 +10949,10 @@ fn genCall(self: *Self, info: union(enum) {
                         try self.genSetReg(.rax, Type.usize, .{ .lea_got = sym_index });
                         try self.asmRegister(.{ ._, .call }, .rax);
                     } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
-                        _ = macho_file;
-                        @panic("TODO genCall");
-                        // const atom = try macho_file.getOrCreateAtomForDecl(func.owner_decl);
-                        // const sym_index = macho_file.getAtom(atom).getSymbolIndex().?;
-                        // try self.genSetReg(.rax, Type.usize, .{ .lea_got = sym_index });
-                        // try self.asmRegister(.{ ._, .call }, .rax);
+                        const sym_index = try macho_file.getZigObject().?.getOrCreateMetadataForDecl(macho_file, func.owner_decl);
+                        const sym = macho_file.getSymbol(sym_index);
+                        try self.genSetReg(.rax, Type.usize, .{ .load_symbol = .{ .sym = sym.nlist_idx } });
+                        try self.asmRegister(.{ ._, .call }, .rax);
                     } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
                         const atom_index = try p9.seeDecl(func.owner_decl);
                         const atom = p9.getAtom(atom_index);
@@ -13556,30 +13548,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
                 } },
             });
         },
-        .lea_tlv => |sym_index| {
-            const atom_index = try self.owner.getSymbolIndex(self);
-            if (self.bin_file.cast(link.File.MachO)) |_| {
-                _ = try self.addInst(.{
-                    .tag = .lea,
-                    .ops = .tlv_reloc,
-                    .data = .{ .rx = .{
-                        .r1 = .rdi,
-                        .payload = try self.addExtra(bits.Symbol{
-                            .atom_index = atom_index,
-                            .sym_index = sym_index,
-                        }),
-                    } },
-                });
-                // TODO: spill registers before calling
-                try self.asmMemory(.{ ._, .call }, .{
-                    .base = .{ .reg = .rdi },
-                    .mod = .{ .rm = .{ .size = .qword } },
-                });
-                try self.genSetReg(dst_reg.to64(), Type.usize, .{ .register = .rax });
-            } else return self.fail("TODO emit ptr to TLV sequence on {s}", .{
-                @tagName(self.bin_file.tag),
-            });
-        },
+        .lea_tlv => unreachable, // TODO: remove this
         .air_ref => |src_ref| try self.genSetReg(dst_reg, ty, try self.resolveInst(src_ref)),
     }
 }
@@ -13816,19 +13785,14 @@ fn genExternSymbolRef(
             else => unreachable,
         }
     } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
-        const global_index = try macho_file.getGlobalSymbol(callee, lib);
         _ = try self.addInst(.{
             .tag = .call,
             .ops = .extern_fn_reloc,
-            .data = .{
-                .reloc = .{
-                    .atom_index = atom_index,
-                    // .sym_index = link.File.MachO.global_symbol_bit | global_index,
-                    .sym_index = global_index,
-                },
-            },
+            .data = .{ .reloc = .{
+                .atom_index = atom_index,
+                .sym_index = try macho_file.getGlobalSymbol(callee, lib),
+            } },
         });
-        @panic("TODO genExternSymbolRef");
     } else return self.fail("TODO implement calling extern functions", .{});
 }
 
@@ -13916,21 +13880,19 @@ fn genLazySymbolRef(
             else => unreachable,
         }
     } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
-        _ = macho_file;
-        @panic("TODO genLazySymbolRef");
-        // const atom_index = macho_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err|
-        //     return self.fail("{s} creating lazy symbol", .{@errorName(err)});
-        // const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;
-        // switch (tag) {
-        //     .lea, .call => try self.genSetReg(reg, Type.usize, .{ .lea_got = sym_index }),
-        //     .mov => try self.genSetReg(reg, Type.usize, .{ .load_got = sym_index }),
-        //     else => unreachable,
-        // }
-        // switch (tag) {
-        //     .lea, .mov => {},
-        //     .call => try self.asmRegister(.{ ._, .call }, reg),
-        //     else => unreachable,
-        // }
+        const sym_index = macho_file.getZigObject().?.getOrCreateMetadataForLazySymbol(macho_file, lazy_sym) catch |err|
+            return self.fail("{s} creating lazy symbol", .{@errorName(err)});
+        const sym = macho_file.getSymbol(sym_index);
+        switch (tag) {
+            .lea, .call => try self.genSetReg(reg, Type.usize, .{ .load_symbol = .{ .sym = sym.nlist_idx } }),
+            .mov => try self.genSetReg(reg, Type.usize, .{ .load_symbol = .{ .sym = sym.nlist_idx } }),
+            else => unreachable,
+        }
+        switch (tag) {
+            .lea, .mov => {},
+            .call => try self.asmRegister(.{ ._, .call }, reg),
+            else => unreachable,
+        }
     } else {
         return self.fail("TODO implement genLazySymbol for x86_64 {s}", .{@tagName(self.bin_file.tag)});
     }
@@ -16103,6 +16065,8 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue {
                         .{ .lea_symbol = .{ .sym = tlv_sym } },
                     );
                     break :init .{ .load_frame = .{ .index = frame_index } };
+                } else if (self.bin_file.cast(link.File.MachO)) |_| {
+                    return self.fail("TODO implement lowering TLV variable to stack", .{});
                 } else break :init const_mcv,
                 else => break :init const_mcv,
             }
src/arch/x86_64/Emit.zig
@@ -49,23 +49,21 @@ pub fn emitMir(emit: *Emit) Error!void {
                         .r_addend = -4,
                     });
                 } else if (emit.lower.bin_file.cast(link.File.MachO)) |macho_file| {
-                    _ = macho_file;
-                    @panic("TODO emitMir");
-                    // // Add relocation to the decl.
-                    // const atom_index =
-                    //     macho_file.getAtomIndexForSymbol(.{ .sym_index = symbol.atom_index }).?;
-                    // const target = if (link.File.MachO.global_symbol_bit & symbol.sym_index != 0)
-                    //     macho_file.getGlobalByIndex(link.File.MachO.global_symbol_mask & symbol.sym_index)
-                    // else
-                    //     link.File.MachO.SymbolWithLoc{ .sym_index = symbol.sym_index };
-                    // try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
-                    //     .type = .branch,
-                    //     .target = target,
-                    //     .offset = end_offset - 4,
-                    //     .addend = 0,
-                    //     .pcrel = true,
-                    //     .length = 2,
-                    // });
+                    // Add relocation to the decl.
+                    const atom = macho_file.getSymbol(symbol.atom_index).getAtom(macho_file).?;
+                    try atom.addReloc(macho_file, .{
+                        .tag = .@"extern",
+                        .offset = end_offset - 4,
+                        .target = symbol.sym_index,
+                        .addend = 0,
+                        .type = .branch,
+                        .meta = .{
+                            .pcrel = true,
+                            .has_subtractor = false,
+                            .length = 2,
+                            .symbolnum = 0,
+                        },
+                    });
                 } else if (emit.lower.bin_file.cast(link.File.Coff)) |coff_file| {
                     // Add relocation to the decl.
                     const atom_index = coff_file.getAtomIndexForSymbol(
@@ -151,6 +149,36 @@ pub fn emitMir(emit: *Emit) Error!void {
                             });
                         }
                     }
+                } else if (emit.lower.bin_file.cast(link.File.MachO)) |macho_file| {
+                    const is_obj_or_static_lib = switch (emit.lower.output_mode) {
+                        .Exe => false,
+                        .Obj => true,
+                        .Lib => emit.lower.link_mode == .Static,
+                    };
+                    const atom = macho_file.getSymbol(data.atom_index).getAtom(macho_file).?;
+                    const sym = macho_file.getSymbol(data.sym_index);
+                    if (sym.flags.needs_zig_got and !is_obj_or_static_lib) {
+                        _ = try sym.getOrCreateZigGotEntry(data.sym_index, macho_file);
+                    }
+                    const @"type": link.File.MachO.Relocation.Type = if (sym.flags.needs_zig_got and !is_obj_or_static_lib)
+                        .zig_got_load
+                    else if (sym.flags.needs_got)
+                        .got_load
+                    else
+                        .signed;
+                    try atom.addReloc(macho_file, .{
+                        .tag = .@"extern",
+                        .offset = @intCast(end_offset - 4),
+                        .target = data.sym_index,
+                        .addend = 0,
+                        .type = @"type",
+                        .meta = .{
+                            .pcrel = true,
+                            .has_subtractor = false,
+                            .length = 2,
+                            .symbolnum = 0,
+                        },
+                    });
                 } else unreachable,
                 .linker_got,
                 .linker_direct,
@@ -158,28 +186,8 @@ pub fn emitMir(emit: *Emit) Error!void {
                 .linker_tlv,
                 => |symbol| if (emit.lower.bin_file.cast(link.File.Elf)) |_| {
                     unreachable;
-                } else if (emit.lower.bin_file.cast(link.File.MachO)) |macho_file| {
-                    _ = macho_file;
-                    @panic("TODO emitMir");
-                    // const atom_index =
-                    //     macho_file.getAtomIndexForSymbol(.{ .sym_index = symbol.atom_index }).?;
-                    // const target = if (link.File.MachO.global_symbol_bit & symbol.sym_index != 0)
-                    //     macho_file.getGlobalByIndex(link.File.MachO.global_symbol_mask & symbol.sym_index)
-                    // else
-                    //     link.File.MachO.SymbolWithLoc{ .sym_index = symbol.sym_index };
-                    // try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
-                    //     .type = switch (lowered_relocs[0].target) {
-                    //         .linker_got => .got,
-                    //         .linker_direct => .signed,
-                    //         .linker_tlv => .tlv,
-                    //         else => unreachable,
-                    //     },
-                    //     .target = target,
-                    //     .offset = @intCast(end_offset - 4),
-                    //     .addend = 0,
-                    //     .pcrel = true,
-                    //     .length = 2,
-                    // });
+                } else if (emit.lower.bin_file.cast(link.File.MachO)) |_| {
+                    unreachable;
                 } else if (emit.lower.bin_file.cast(link.File.Coff)) |coff_file| {
                     const atom_index = coff_file.getAtomIndexForSymbol(.{
                         .sym_index = symbol.atom_index,
src/arch/x86_64/Lower.zig
@@ -14,7 +14,7 @@ result_relocs_len: u8 = undefined,
 result_insts: [
     std.mem.max(usize, &.{
         1, // non-pseudo instructions
-        3, // TLS local dynamic (LD) sequence in PIC mode
+        3, // (ELF only) TLS local dynamic (LD) sequence in PIC mode
         2, // cmovcc: cmovcc \ cmovcc
         3, // setcc: setcc \ setcc \ logicop
         2, // jcc: jcc \ jcc
@@ -32,7 +32,7 @@ result_relocs: [
         2, // jcc: jcc \ jcc
         2, // test \ jcc \ probe \ sub \ jmp
         1, // probe \ sub \ jcc
-        3, // TLS local dynamic (LD) sequence in PIC mode
+        3, // (ELF only) TLS local dynamic (LD) sequence in PIC mode
     })
 ]Reloc = undefined,
 
@@ -326,18 +326,6 @@ fn reloc(lower: *Lower, target: Reloc.Target) Immediate {
     return Immediate.s(0);
 }
 
-fn needsZigGot(sym: bits.Symbol, ctx: *link.File) bool {
-    const elf_file = ctx.cast(link.File.Elf).?;
-    const sym_index = elf_file.zigObjectPtr().?.symbol(sym.sym_index);
-    return elf_file.symbol(sym_index).flags.needs_zig_got;
-}
-
-fn isTls(sym: bits.Symbol, ctx: *link.File) bool {
-    const elf_file = ctx.cast(link.File.Elf).?;
-    const sym_index = elf_file.zigObjectPtr().?.symbol(sym.sym_index);
-    return elf_file.symbol(sym_index).flags.is_tls;
-}
-
 fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) Error!void {
     const is_obj_or_static_lib = switch (lower.output_mode) {
         .Exe => false,
@@ -359,80 +347,101 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
                     assert(mem_op.sib.disp == 0);
                     assert(mem_op.sib.scale_index.scale == 0);
 
-                    if (isTls(sym, lower.bin_file)) {
-                        // TODO handle extern TLS vars, i.e., emit GD model
-                        if (lower.pic) {
-                            // Here, we currently assume local dynamic TLS vars, and so
-                            // we emit LD model.
-                            _ = lower.reloc(.{ .linker_tlsld = sym });
-                            lower.result_insts[lower.result_insts_len] =
-                                try Instruction.new(.none, .lea, &[_]Operand{
-                                .{ .reg = .rdi },
-                                .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) },
-                            });
-                            lower.result_insts_len += 1;
-                            if (lower.bin_file.cast(link.File.Elf)) |elf_file| {
+                    if (lower.bin_file.cast(link.File.Elf)) |elf_file| {
+                        const sym_index = elf_file.zigObjectPtr().?.symbol(sym.sym_index);
+                        const elf_sym = elf_file.symbol(sym_index);
+
+                        if (elf_sym.flags.is_tls) {
+                            // TODO handle extern TLS vars, i.e., emit GD model
+                            if (lower.pic) {
+                                // Here, we currently assume local dynamic TLS vars, and so
+                                // we emit LD model.
+                                _ = lower.reloc(.{ .linker_tlsld = sym });
+                                lower.result_insts[lower.result_insts_len] =
+                                    try Instruction.new(.none, .lea, &[_]Operand{
+                                    .{ .reg = .rdi },
+                                    .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) },
+                                });
+                                lower.result_insts_len += 1;
                                 _ = lower.reloc(.{ .linker_extern_fn = .{
                                     .atom_index = sym.atom_index,
                                     .sym_index = try elf_file.getGlobalSymbol("__tls_get_addr", null),
                                 } });
+                                lower.result_insts[lower.result_insts_len] =
+                                    try Instruction.new(.none, .call, &[_]Operand{
+                                    .{ .imm = Immediate.s(0) },
+                                });
+                                lower.result_insts_len += 1;
+                                _ = lower.reloc(.{ .linker_dtpoff = sym });
+                                emit_mnemonic = .lea;
+                                break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{
+                                    .base = .{ .reg = .rax },
+                                    .disp = std.math.minInt(i32),
+                                }) };
+                            } else {
+                                // Since we are linking statically, we emit LE model directly.
+                                lower.result_insts[lower.result_insts_len] =
+                                    try Instruction.new(.none, .mov, &[_]Operand{
+                                    .{ .reg = .rax },
+                                    .{ .mem = Memory.sib(.qword, .{ .base = .{ .reg = .fs } }) },
+                                });
+                                lower.result_insts_len += 1;
+                                _ = lower.reloc(.{ .linker_reloc = sym });
+                                emit_mnemonic = .lea;
+                                break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{
+                                    .base = .{ .reg = .rax },
+                                    .disp = std.math.minInt(i32),
+                                }) };
                             }
-                            lower.result_insts[lower.result_insts_len] =
-                                try Instruction.new(.none, .call, &[_]Operand{
-                                .{ .imm = Immediate.s(0) },
-                            });
-                            lower.result_insts_len += 1;
-                            _ = lower.reloc(.{ .linker_dtpoff = sym });
-                            emit_mnemonic = .lea;
-                            break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{
-                                .base = .{ .reg = .rax },
-                                .disp = std.math.minInt(i32),
-                            }) };
-                        } else {
-                            // Since we are linking statically, we emit LE model directly.
-                            lower.result_insts[lower.result_insts_len] =
-                                try Instruction.new(.none, .mov, &[_]Operand{
-                                .{ .reg = .rax },
-                                .{ .mem = Memory.sib(.qword, .{ .base = .{ .reg = .fs } }) },
-                            });
-                            lower.result_insts_len += 1;
-                            _ = lower.reloc(.{ .linker_reloc = sym });
-                            emit_mnemonic = .lea;
-                            break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{
-                                .base = .{ .reg = .rax },
-                                .disp = std.math.minInt(i32),
-                            }) };
                         }
-                    }
 
-                    _ = lower.reloc(.{ .linker_reloc = sym });
-                    break :op if (lower.pic) switch (mnemonic) {
-                        .lea => {
-                            break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) };
-                        },
-                        .mov => {
-                            if (is_obj_or_static_lib and needsZigGot(sym, lower.bin_file)) emit_mnemonic = .lea;
-                            break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) };
-                        },
-                        else => unreachable,
-                    } else switch (mnemonic) {
-                        .call => break :op if (is_obj_or_static_lib and needsZigGot(sym, lower.bin_file)) .{
-                            .imm = Immediate.s(0),
-                        } else .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{
-                            .base = .{ .reg = .ds },
-                        }) },
-                        .lea => {
-                            emit_mnemonic = .mov;
-                            break :op .{ .imm = Immediate.s(0) };
-                        },
-                        .mov => {
-                            if (is_obj_or_static_lib and needsZigGot(sym, lower.bin_file)) emit_mnemonic = .lea;
-                            break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{
+                        _ = lower.reloc(.{ .linker_reloc = sym });
+                        break :op if (lower.pic) switch (mnemonic) {
+                            .lea => {
+                                break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) };
+                            },
+                            .mov => {
+                                if (is_obj_or_static_lib and elf_sym.flags.needs_zig_got) emit_mnemonic = .lea;
+                                break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) };
+                            },
+                            else => unreachable,
+                        } else switch (mnemonic) {
+                            .call => break :op if (is_obj_or_static_lib and elf_sym.flags.needs_zig_got) .{
+                                .imm = Immediate.s(0),
+                            } else .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{
                                 .base = .{ .reg = .ds },
-                            }) };
-                        },
-                        else => unreachable,
-                    };
+                            }) },
+                            .lea => {
+                                emit_mnemonic = .mov;
+                                break :op .{ .imm = Immediate.s(0) };
+                            },
+                            .mov => {
+                                if (is_obj_or_static_lib and elf_sym.flags.needs_zig_got) emit_mnemonic = .lea;
+                                break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{
+                                    .base = .{ .reg = .ds },
+                                }) };
+                            },
+                            else => unreachable,
+                        };
+                    } else if (lower.bin_file.cast(link.File.MachO)) |macho_file| {
+                        const macho_sym = macho_file.getSymbol(sym.sym_index);
+
+                        if (macho_sym.flags.tlv) {
+                            @panic("TODO lower TLS access on macOS");
+                        }
+
+                        _ = lower.reloc(.{ .linker_reloc = sym });
+                        break :op switch (mnemonic) {
+                            .lea => {
+                                break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) };
+                            },
+                            .mov => {
+                                if (is_obj_or_static_lib and macho_sym.flags.needs_zig_got) emit_mnemonic = .lea;
+                                break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) };
+                            },
+                            else => unreachable,
+                        };
+                    }
                 },
             },
         };
src/link/MachO/Atom.zig
@@ -686,6 +686,10 @@ fn resolveRelocInner(
             }
         },
 
+        .zig_got_load => {
+            @panic("TODO resolve __got_zig indirection reloc");
+        },
+
         .tlv => {
             assert(rel.tag == .@"extern");
             assert(rel.meta.length == 2);
@@ -987,6 +991,7 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: *std.Arra
                     .subtractor => .ARM64_RELOC_SUBTRACTOR,
                     .unsigned => .ARM64_RELOC_UNSIGNED,
 
+                    .zig_got_load,
                     .signed,
                     .signed1,
                     .signed2,
@@ -1030,6 +1035,7 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: *std.Arra
                     .subtractor => .X86_64_RELOC_SUBTRACTOR,
                     .unsigned => .X86_64_RELOC_UNSIGNED,
 
+                    .zig_got_load,
                     .page,
                     .pageoff,
                     .got_load_page,
src/link/MachO/Relocation.zig
@@ -99,6 +99,8 @@ pub const Type = enum {
     got_load,
     /// RIP-relative TLV load (X86_64_RELOC_TLV)
     tlv,
+    /// Zig-specific __got_zig indirection
+    zig_got_load,
 
     // arm64
     /// PC-relative load (distance to page, ARM64_RELOC_PAGE21)
src/link/MachO/ZigObject.zig
@@ -248,7 +248,7 @@ pub fn getDeclVAddr(
             .pcrel = false,
             .has_subtractor = false,
             .length = 3,
-            .symbolnum = @intCast(sym.nlist_idx),
+            .symbolnum = 0,
         },
     });
     return vaddr;
@@ -274,7 +274,7 @@ pub fn getAnonDeclVAddr(
             .pcrel = false,
             .has_subtractor = false,
             .length = 3,
-            .symbolnum = @intCast(sym.nlist_idx),
+            .symbolnum = 0,
         },
     });
     return vaddr;
@@ -604,25 +604,26 @@ fn getDeclOutputSection(
     _ = self;
     const mod = macho_file.base.comp.module.?;
     const any_non_single_threaded = macho_file.base.comp.config.any_non_single_threaded;
+    _ = any_non_single_threaded;
     const sect_id: u8 = switch (decl.ty.zigTypeTag(mod)) {
         .Fn => macho_file.zig_text_section_index.?,
         else => blk: {
             if (decl.getOwnedVariable(mod)) |variable| {
-                if (variable.is_threadlocal and any_non_single_threaded) {
-                    const is_all_zeroes = for (code) |byte| {
-                        if (byte != 0) break false;
-                    } else true;
-                    if (is_all_zeroes) break :blk macho_file.getSectionByName("__DATA", "__thread_bss") orelse try macho_file.addSection(
-                        "__DATA",
-                        "__thread_bss",
-                        .{ .flags = macho.S_THREAD_LOCAL_ZEROFILL },
-                    );
-                    break :blk macho_file.getSectionByName("__DATA", "__thread_data") orelse try macho_file.addSection(
-                        "__DATA",
-                        "__thread_data",
-                        .{ .flags = macho.S_THREAD_LOCAL_REGULAR },
-                    );
-                }
+                // if (variable.is_threadlocal and any_non_single_threaded) {
+                //     const is_all_zeroes = for (code) |byte| {
+                //         if (byte != 0) break false;
+                //     } else true;
+                //     if (is_all_zeroes) break :blk macho_file.getSectionByName("__DATA", "__thread_bss") orelse try macho_file.addSection(
+                //         "__DATA",
+                //         "__thread_bss",
+                //         .{ .flags = macho.S_THREAD_LOCAL_ZEROFILL },
+                //     );
+                //     break :blk macho_file.getSectionByName("__DATA", "__thread_data") orelse try macho_file.addSection(
+                //         "__DATA",
+                //         "__thread_data",
+                //         .{ .flags = macho.S_THREAD_LOCAL_REGULAR },
+                //     );
+                // }
 
                 if (variable.is_const) break :blk macho_file.zig_const_section_index.?;
                 if (Value.fromInterned(variable.init).isUndefDeep(mod)) {
@@ -917,7 +918,7 @@ fn updateLazySymbol(
 
     sym.value = 0;
     sym.flags.needs_zig_got = true;
-    nlist.st_value = 0;
+    nlist.n_value = 0;
 
     if (!macho_file.base.isRelocatable()) {
         const gop = try sym.getOrCreateZigGotEntry(symbol_index, macho_file);
src/link/MachO.zig
@@ -4280,7 +4280,7 @@ const Md5 = std.crypto.hash.Md5;
 const Module = @import("../Module.zig");
 const InternPool = @import("../InternPool.zig");
 const RebaseSection = synthetic.RebaseSection;
-const Relocation = @import("MachO/Relocation.zig");
+pub const Relocation = @import("MachO/Relocation.zig");
 const StringTable = @import("StringTable.zig");
 const StubsSection = synthetic.StubsSection;
 const StubsHelperSection = synthetic.StubsHelperSection;
src/codegen.zig
@@ -1045,7 +1045,12 @@ fn genUnnamedConst(
             const local = elf_file.symbol(local_sym_index);
             return GenResult.mcv(.{ .load_symbol = local.esym_index });
         },
-        .macho, .coff => {
+        .macho => {
+            const macho_file = lf.cast(link.File.MachO).?;
+            const local = macho_file.getSymbol(local_sym_index);
+            return GenResult.mcv(.{ .load_symbol = local.nlist_idx });
+        },
+        .coff => {
             return GenResult.mcv(.{ .load_direct = local_sym_index });
         },
         .plan9 => {