diff --git a/src/arch/x86_64/Emit.zig b/src/arch/x86_64/Emit.zig index 97899f224d..35d6935d77 100644 --- a/src/arch/x86_64/Emit.zig +++ b/src/arch/x86_64/Emit.zig @@ -166,6 +166,8 @@ pub fn emitMir(emit: *Emit) Error!void { .zig_got_load else if (sym.flags.needs_got) .got_load + else if (sym.flags.tlv) + .tlv else .signed; try atom.addReloc(macho_file, .{ @@ -185,7 +187,6 @@ pub fn emitMir(emit: *Emit) Error!void { .linker_got, .linker_direct, .linker_import, - .linker_tlv, => |symbol| if (emit.lower.bin_file.cast(link.File.Elf)) |_| { unreachable; } else if (emit.lower.bin_file.cast(link.File.MachO)) |_| { diff --git a/src/arch/x86_64/Lower.zig b/src/arch/x86_64/Lower.zig index 0b48afe0c6..5271b3e93c 100644 --- a/src/arch/x86_64/Lower.zig +++ b/src/arch/x86_64/Lower.zig @@ -62,7 +62,6 @@ pub const Reloc = struct { linker_got: bits.Symbol, linker_direct: bits.Symbol, linker_import: bits.Symbol, - linker_tlv: bits.Symbol, }; }; @@ -428,7 +427,23 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) const macho_sym = macho_file.getSymbol(sym_index); if (macho_sym.flags.tlv) { - @panic("TODO lower TLS access on macOS"); + _ = lower.reloc(.{ .linker_reloc = sym }); + lower.result_insts[lower.result_insts_len] = + try Instruction.new(.none, .mov, &[_]Operand{ + .{ .reg = .rdi }, + .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) }, + }); + lower.result_insts_len += 1; + lower.result_insts[lower.result_insts_len] = + try Instruction.new(.none, .call, &[_]Operand{ + .{ .mem = Memory.sib(.qword, .{ .base = .{ .reg = .rdi } }) }, + }); + lower.result_insts_len += 1; + 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 }); @@ -594,14 +609,13 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void { .extern_fn_reloc => &.{ .{ .imm = lower.reloc(.{ .linker_extern_fn = inst.data.reloc }) }, }, - .got_reloc, .direct_reloc, .import_reloc, .tlv_reloc => ops: { + .got_reloc, .direct_reloc, .import_reloc => ops: { const reg = inst.data.rx.r1; const extra = lower.mir.extraData(bits.Symbol, inst.data.rx.payload).data; _ = lower.reloc(switch (inst.ops) { .got_reloc => .{ .linker_got = extra }, .direct_reloc => .{ .linker_direct = extra }, .import_reloc => .{ .linker_import = extra }, - .tlv_reloc => .{ .linker_tlv = extra }, else => unreachable, }); break :ops &.{ diff --git a/src/link/MachO/ZigObject.zig b/src/link/MachO/ZigObject.zig index 976a3236ae..fc9ce86762 100644 --- a/src/link/MachO/ZigObject.zig +++ b/src/link/MachO/ZigObject.zig @@ -141,13 +141,23 @@ pub fn getAtomDataAlloc(self: ZigObject, macho_file: *MachO, atom: Atom) ![]u8 { const gpa = macho_file.base.comp.gpa; assert(atom.file == self.index); const sect = macho_file.sections.items(.header)[atom.out_n_sect]; - const file_offset = sect.offset + atom.value - sect.addr; - const size = std.math.cast(usize, atom.size) orelse return error.Overflow; - const code = try gpa.alloc(u8, size); - errdefer gpa.free(code); - const amt = try macho_file.base.file.?.preadAll(code, file_offset); - if (amt != code.len) return error.InputOutput; - return code; + + switch (sect.type()) { + macho.S_THREAD_LOCAL_REGULAR => { + const tlv = self.tls_variables.get(atom.atom_index).?; + const code = try gpa.dupe(u8, tlv.code); + return code; + }, + else => { + const file_offset = sect.offset + atom.value - sect.addr; + const size = std.math.cast(usize, atom.size) orelse return error.Overflow; + const code = try gpa.alloc(u8, size); + errdefer gpa.free(code); + const amt = try macho_file.base.file.?.preadAll(code, file_offset); + if (amt != code.len) return error.InputOutput; + return code; + }, + } } pub fn getAtomRelocs(self: *ZigObject, atom: Atom) []const Relocation {