From dd0addab1fe11b019e83c0050eedfa0ec67eb408 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Tue, 9 Jan 2024 19:51:01 +0100 Subject: macho: get the ball rolling! --- src/codegen.zig | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'src/codegen.zig') diff --git a/src/codegen.zig b/src/codegen.zig index 1ac8626a79..f9263c2a69 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -984,20 +984,22 @@ fn genDeclRef( } return GenResult.mcv(.{ .load_symbol = sym.esym_index }); } else if (lf.cast(link.File.MachO)) |macho_file| { + _ = macho_file; if (is_extern) { // TODO make this part of getGlobalSymbol - const name = zcu.intern_pool.stringToSlice(decl.name); - const sym_name = try std.fmt.allocPrint(gpa, "_{s}", .{name}); - defer gpa.free(sym_name); - const global_index = try macho_file.addUndefined(sym_name, .{ .add_got = true }); - return GenResult.mcv(.{ .load_got = link.File.MachO.global_symbol_bit | global_index }); - } - const atom_index = try macho_file.getOrCreateAtomForDecl(decl_index); - const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?; - if (is_threadlocal) { - return GenResult.mcv(.{ .load_tlv = sym_index }); + // const name = zcu.intern_pool.stringToSlice(decl.name); + // const sym_name = try std.fmt.allocPrint(gpa, "_{s}", .{name}); + // defer gpa.free(sym_name); + // const global_index = try macho_file.addUndefined(sym_name, .{ .add_got = true }); + // return GenResult.mcv(.{ .load_got = link.File.MachO.global_symbol_bit | global_index }); } - return GenResult.mcv(.{ .load_got = sym_index }); + // const atom_index = try macho_file.getOrCreateAtomForDecl(decl_index); + // const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?; + // if (is_threadlocal) { + // return GenResult.mcv(.{ .load_tlv = sym_index }); + // } + // return GenResult.mcv(.{ .load_got = sym_index }); + @panic("TODO genDeclRef"); } else if (lf.cast(link.File.Coff)) |coff_file| { if (is_extern) { const name = zcu.intern_pool.stringToSlice(decl.name); -- cgit v1.2.3 From 76dc305d4e71a9a4c9de92e6dde40a53eac1e328 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Thu, 18 Jan 2024 17:55:49 +0100 Subject: codegen: re-enable MachO support in genDeclRef --- src/codegen.zig | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'src/codegen.zig') diff --git a/src/codegen.zig b/src/codegen.zig index f9263c2a69..83d0215cfa 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -984,22 +984,24 @@ fn genDeclRef( } return GenResult.mcv(.{ .load_symbol = sym.esym_index }); } else if (lf.cast(link.File.MachO)) |macho_file| { - _ = macho_file; if (is_extern) { - // TODO make this part of getGlobalSymbol - // const name = zcu.intern_pool.stringToSlice(decl.name); - // const sym_name = try std.fmt.allocPrint(gpa, "_{s}", .{name}); - // defer gpa.free(sym_name); - // const global_index = try macho_file.addUndefined(sym_name, .{ .add_got = true }); - // return GenResult.mcv(.{ .load_got = link.File.MachO.global_symbol_bit | global_index }); + const name = zcu.intern_pool.stringToSlice(decl.name); + const sym_name = try std.fmt.allocPrint(gpa, "_{s}", .{name}); + defer gpa.free(sym_name); + const lib_name = if (decl.getOwnedVariable(zcu)) |ov| + zcu.intern_pool.stringToSliceUnwrap(ov.lib_name) + else + null; + const sym_index = try macho_file.getGlobalSymbol(sym_name, lib_name); + macho_file.getSymbol(sym_index).flags.needs_got = true; + return GenResult.mcv(.{ .load_symbol = sym_index }); + } + const sym_index = try macho_file.getZigObject().?.getOrCreateMetadataForDecl(macho_file, decl_index); + const sym = macho_file.getSymbol(sym_index); + if (is_threadlocal) { + return GenResult.mcv(.{ .load_tlv = sym.nlist_idx }); } - // const atom_index = try macho_file.getOrCreateAtomForDecl(decl_index); - // const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?; - // if (is_threadlocal) { - // return GenResult.mcv(.{ .load_tlv = sym_index }); - // } - // return GenResult.mcv(.{ .load_got = sym_index }); - @panic("TODO genDeclRef"); + return GenResult.mcv(.{ .load_symbol = sym.nlist_idx }); } else if (lf.cast(link.File.Coff)) |coff_file| { if (is_extern) { const name = zcu.intern_pool.stringToSlice(decl.name); -- cgit v1.2.3 From 96cc9fafbf0a382c0ed0b6142986cd8373cffaa3 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Thu, 18 Jan 2024 18:58:29 +0100 Subject: codegen: re-implement enough of codegen to error out instead panic --- src/arch/x86_64/CodeGen.zig | 90 +++++++--------------- src/arch/x86_64/Emit.zig | 86 +++++++++++---------- src/arch/x86_64/Lower.zig | 169 ++++++++++++++++++++++-------------------- src/codegen.zig | 7 +- src/link/MachO.zig | 2 +- src/link/MachO/Atom.zig | 6 ++ src/link/MachO/Relocation.zig | 2 + src/link/MachO/ZigObject.zig | 37 ++++----- 8 files changed, 197 insertions(+), 202 deletions(-) (limited to 'src/codegen.zig') diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 870b6a2472..2b4932c5c2 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/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, } diff --git a/src/arch/x86_64/Emit.zig b/src/arch/x86_64/Emit.zig index 97c6cdfc1b..9cadef1ef6 100644 --- a/src/arch/x86_64/Emit.zig +++ b/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, diff --git a/src/arch/x86_64/Lower.zig b/src/arch/x86_64/Lower.zig index cc5ae7712b..eb3ed88b37 100644 --- a/src/arch/x86_64/Lower.zig +++ b/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, + }; + } }, }, }; diff --git a/src/codegen.zig b/src/codegen.zig index 83d0215cfa..8172e15c3e 100644 --- a/src/codegen.zig +++ b/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 => { diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 165dbbe17a..34f2d0b49e 100644 --- a/src/link/MachO.zig +++ b/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; diff --git a/src/link/MachO/Atom.zig b/src/link/MachO/Atom.zig index 25cbe6ca64..5389303337 100644 --- a/src/link/MachO/Atom.zig +++ b/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, diff --git a/src/link/MachO/Relocation.zig b/src/link/MachO/Relocation.zig index f77e0c8792..20891f07e3 100644 --- a/src/link/MachO/Relocation.zig +++ b/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) diff --git a/src/link/MachO/ZigObject.zig b/src/link/MachO/ZigObject.zig index 0199c0707c..96ef3c1996 100644 --- a/src/link/MachO/ZigObject.zig +++ b/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); -- cgit v1.2.3 From a79a038e61541d6faffaab70c82a18a812c2e9df Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Thu, 18 Jan 2024 19:11:48 +0100 Subject: codegen: implement more missing bits --- src/arch/x86_64/CodeGen.zig | 41 ++++++++++++++++++++++------------------- src/codegen.zig | 7 ++++--- 2 files changed, 26 insertions(+), 22 deletions(-) (limited to 'src/codegen.zig') diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 2b4932c5c2..2cc5fe267e 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -13507,24 +13507,27 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr }, .lea_symbol => |sym_index| { const atom_index = try self.owner.getSymbolIndex(self); - if (self.bin_file.cast(link.File.Elf)) |_| { - try self.asmRegisterMemory( - .{ ._, .lea }, - dst_reg.to64(), - .{ - .base = .{ .reloc = .{ - .atom_index = atom_index, - .sym_index = sym_index.sym, - } }, - .mod = .{ .rm = .{ - .size = .qword, - .disp = sym_index.off, - } }, - }, - ); - } else return self.fail("TODO emit symbol sequence on {s}", .{ - @tagName(self.bin_file.tag), - }); + switch (self.bin_file.tag) { + .elf, .macho => { + try self.asmRegisterMemory( + .{ ._, .lea }, + dst_reg.to64(), + .{ + .base = .{ .reloc = .{ + .atom_index = atom_index, + .sym_index = sym_index.sym, + } }, + .mod = .{ .rm = .{ + .size = .qword, + .disp = sym_index.off, + } }, + }, + ); + }, + else => return self.fail("TODO emit symbol sequence on {s}", .{ + @tagName(self.bin_file.tag), + }), + } }, .lea_direct, .lea_got => |sym_index| { const atom_index = try self.owner.getSymbolIndex(self); @@ -16066,7 +16069,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue { ); 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", .{}); + return self.fail("TODO implement saving TLV variable to stack", .{}); } else break :init const_mcv, else => break :init const_mcv, } diff --git a/src/codegen.zig b/src/codegen.zig index 8172e15c3e..c39c541235 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -998,9 +998,10 @@ fn genDeclRef( } const sym_index = try macho_file.getZigObject().?.getOrCreateMetadataForDecl(macho_file, decl_index); const sym = macho_file.getSymbol(sym_index); - if (is_threadlocal) { - return GenResult.mcv(.{ .load_tlv = sym.nlist_idx }); - } + // TODO: tlv + // if (is_threadlocal) { + // return GenResult.mcv(.{ .load_tlv = sym.nlist_idx }); + // } return GenResult.mcv(.{ .load_symbol = sym.nlist_idx }); } else if (lf.cast(link.File.Coff)) |coff_file| { if (is_extern) { -- cgit v1.2.3 From a8629fb8501275d826912085ccd120eb48a53199 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Thu, 18 Jan 2024 21:55:31 +0100 Subject: macho: fix symbol index dereference in codegen wrt ZigObject This is incredibly confusing and I really need to simplify it. Elf also possesses this shortcoming so once I get Coff up to speed it should hopefully become clear on how to refactor this. --- src/arch/x86_64/Emit.zig | 5 +++-- src/codegen.zig | 2 +- src/link/MachO.zig | 27 ++++++++++++++++++++------- src/link/MachO/Atom.zig | 31 +++++++++++++++++++++++-------- src/link/MachO/Object.zig | 4 +--- src/link/MachO/ZigObject.zig | 33 ++++++++++++++++++++++++++++----- 6 files changed, 76 insertions(+), 26 deletions(-) (limited to 'src/codegen.zig') diff --git a/src/arch/x86_64/Emit.zig b/src/arch/x86_64/Emit.zig index 9cadef1ef6..08209f5198 100644 --- a/src/arch/x86_64/Emit.zig +++ b/src/arch/x86_64/Emit.zig @@ -156,9 +156,10 @@ pub fn emitMir(emit: *Emit) Error!void { .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); + const sym_index = macho_file.getZigObject().?.symbols.items[data.sym_index]; + const sym = macho_file.getSymbol(sym_index); if (sym.flags.needs_zig_got and !is_obj_or_static_lib) { - _ = try sym.getOrCreateZigGotEntry(data.sym_index, macho_file); + _ = try sym.getOrCreateZigGotEntry(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 diff --git a/src/codegen.zig b/src/codegen.zig index c39c541235..7365c3b6b0 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -993,7 +993,7 @@ fn genDeclRef( else null; const sym_index = try macho_file.getGlobalSymbol(sym_name, lib_name); - macho_file.getSymbol(sym_index).flags.needs_got = true; + macho_file.getSymbol(macho_file.getZigObject().?.symbols.items[sym_index]).flags.needs_got = true; return GenResult.mcv(.{ .load_symbol = sym_index }); } const sym_index = try macho_file.getZigObject().?.getOrCreateMetadataForDecl(macho_file, decl_index); diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 6763d21fdf..5eb45981a6 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -542,8 +542,6 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node self.internal_object = index; } - state_log.debug("{}", .{self.dumpState()}); - try self.addUndefinedGlobals(); try self.resolveSymbols(); try self.resolveSyntheticSymbols(); @@ -2389,14 +2387,23 @@ fn initDyldInfoSections(self: *MachO) !void { if (self.la_symbol_ptr_sect_index != null) try self.la_symbol_ptr.addDyldRelocs(self); try self.initExportTrie(); + var objects = try std.ArrayList(File.Index).initCapacity(gpa, self.objects.items.len + 1); + defer objects.deinit(); + if (self.getZigObject()) |zo| objects.appendAssumeCapacity(zo.index); + objects.appendSliceAssumeCapacity(self.objects.items); + var nrebases: usize = 0; var nbinds: usize = 0; var nweak_binds: usize = 0; - for (self.objects.items) |index| { - const object = self.getFile(index).?.object; - nrebases += object.num_rebase_relocs; - nbinds += object.num_bind_relocs; - nweak_binds += object.num_weak_bind_relocs; + for (objects.items) |index| { + const ctx = switch (self.getFile(index).?) { + .zig_object => |x| x.dynamic_relocs, + .object => |x| x.dynamic_relocs, + else => unreachable, + }; + nrebases += ctx.rebase_relocs; + nbinds += ctx.bind_relocs; + nweak_binds += ctx.weak_bind_relocs; } try self.rebase.entries.ensureUnusedCapacity(gpa, nrebases); try self.bind.entries.ensureUnusedCapacity(gpa, nbinds); @@ -3947,6 +3954,12 @@ const HotUpdateState = struct { mach_task: ?std.os.darwin.MachTask = null, }; +pub const DynamicRelocs = struct { + rebase_relocs: u32 = 0, + bind_relocs: u32 = 0, + weak_bind_relocs: u32 = 0, +}; + pub const SymtabCtx = struct { ilocal: u32 = 0, istab: u32 = 0, diff --git a/src/link/MachO/Atom.zig b/src/link/MachO/Atom.zig index 5389303337..b30344854f 100644 --- a/src/link/MachO/Atom.zig +++ b/src/link/MachO/Atom.zig @@ -402,7 +402,11 @@ pub fn scanRelocs(self: Atom, macho_file: *MachO) !void { defer tracy.end(); assert(self.flags.alive); - const object = self.getFile(macho_file).object; + const dynrel_ctx = switch (self.getFile(macho_file)) { + .zig_object => |x| &x.dynamic_relocs, + .object => |x| &x.dynamic_relocs, + else => unreachable, + }; const relocs = self.getRelocs(macho_file); for (relocs) |rel| { @@ -437,6 +441,10 @@ pub fn scanRelocs(self: Atom, macho_file: *MachO) !void { } }, + .zig_got_load => { + assert(rel.getTargetSymbol(macho_file).flags.has_zig_got); + }, + .got => { rel.getTargetSymbol(macho_file).flags.needs_got = true; }, @@ -448,7 +456,7 @@ pub fn scanRelocs(self: Atom, macho_file: *MachO) !void { const symbol = rel.getTargetSymbol(macho_file); if (!symbol.flags.tlv) { try macho_file.reportParseError2( - object.index, + self.getFile(macho_file).getIndex(), "{s}: illegal thread-local variable reference to regular symbol {s}", .{ self.getName(macho_file), symbol.getName(macho_file) }, ); @@ -470,27 +478,34 @@ pub fn scanRelocs(self: Atom, macho_file: *MachO) !void { continue; } if (symbol.flags.import) { - object.num_bind_relocs += 1; + dynrel_ctx.bind_relocs += 1; if (symbol.flags.weak) { - object.num_weak_bind_relocs += 1; + dynrel_ctx.weak_bind_relocs += 1; macho_file.binds_to_weak = true; } continue; } if (symbol.flags.@"export") { if (symbol.flags.weak) { - object.num_weak_bind_relocs += 1; + dynrel_ctx.weak_bind_relocs += 1; macho_file.binds_to_weak = true; } else if (symbol.flags.interposable) { - object.num_bind_relocs += 1; + dynrel_ctx.bind_relocs += 1; } } } - object.num_rebase_relocs += 1; + dynrel_ctx.rebase_relocs += 1; } }, - else => {}, + .signed, + .signed1, + .signed2, + .signed4, + .page, + .pageoff, + .subtractor, + => {}, } } } diff --git a/src/link/MachO/Object.zig b/src/link/MachO/Object.zig index 3fe4142ebc..11846a66d3 100644 --- a/src/link/MachO/Object.zig +++ b/src/link/MachO/Object.zig @@ -25,10 +25,8 @@ unwind_records: std.ArrayListUnmanaged(UnwindInfo.Record.Index) = .{}, alive: bool = true, hidden: bool = false, -num_rebase_relocs: u32 = 0, -num_bind_relocs: u32 = 0, -num_weak_bind_relocs: u32 = 0, +dynamic_relocs: MachO.DynamicRelocs = .{}, output_symtab_ctx: MachO.SymtabCtx = .{}, pub fn isObject(path: []const u8) !bool { diff --git a/src/link/MachO/ZigObject.zig b/src/link/MachO/ZigObject.zig index b6a8f5448b..af805600c5 100644 --- a/src/link/MachO/ZigObject.zig +++ b/src/link/MachO/ZigObject.zig @@ -41,6 +41,7 @@ anon_decls: AnonDeclTable = .{}, /// A table of relocations. relocs: RelocationTable = .{}, +dynamic_relocs: MachO.DynamicRelocs = .{}, output_symtab_ctx: MachO.SymtabCtx = .{}, pub fn init(self: *ZigObject, macho_file: *MachO) !void { @@ -222,10 +223,31 @@ pub fn markLive(self: *ZigObject, macho_file: *MachO) void { } pub fn checkDuplicates(self: *ZigObject, dupes: anytype, macho_file: *MachO) !void { - _ = self; - _ = dupes; - _ = macho_file; - @panic("TODO checkDuplicates"); + for (self.symbols.items, 0..) |index, nlist_idx| { + const sym = macho_file.getSymbol(index); + if (sym.visibility != .global) continue; + const file = sym.getFile(macho_file) orelse continue; + if (file.getIndex() == self.index) continue; + + const nlist = self.symtab.items(.nlist)[nlist_idx]; + if (!nlist.undf() and !nlist.tentative() and !(nlist.weakDef() or nlist.pext())) { + const gop = try dupes.getOrPut(index); + if (!gop.found_existing) { + gop.value_ptr.* = .{}; + } + try gop.value_ptr.append(macho_file.base.comp.gpa, self.index); + } + } +} + +pub fn scanRelocs(self: *ZigObject, macho_file: *MachO) !void { + for (self.atoms.items) |atom_index| { + const atom = macho_file.getAtom(atom_index) orelse continue; + if (!atom.flags.alive) continue; + const sect = atom.getInputSection(macho_file); + if (sect.isZerofill()) continue; + try atom.scanRelocs(macho_file); + } } pub fn calcSymtabSize(self: *ZigObject, macho_file: *MachO) !void { @@ -537,7 +559,8 @@ pub fn updateDecl( const name = mod.intern_pool.stringToSlice(decl.name); const lib_name = mod.intern_pool.stringToSliceUnwrap(variable.lib_name); const index = try self.getGlobalSymbol(macho_file, name, lib_name); - macho_file.getSymbol(index).flags.needs_got = true; + const actual_index = self.symbols.items[index]; + macho_file.getSymbol(actual_index).flags.needs_got = true; return; } -- cgit v1.2.3 From 0143dd8fdcf39f308a1a68098bb54f78068ac1e6 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Fri, 19 Jan 2024 14:09:06 +0100 Subject: macho: fix '_' prefixing rules for exports --- src/codegen.zig | 4 +--- src/link/MachO.zig | 4 +--- src/link/MachO/ZigObject.zig | 16 ++++++---------- 3 files changed, 8 insertions(+), 16 deletions(-) (limited to 'src/codegen.zig') diff --git a/src/codegen.zig b/src/codegen.zig index 7365c3b6b0..49f7feda8f 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -986,13 +986,11 @@ fn genDeclRef( } else if (lf.cast(link.File.MachO)) |macho_file| { if (is_extern) { const name = zcu.intern_pool.stringToSlice(decl.name); - const sym_name = try std.fmt.allocPrint(gpa, "_{s}", .{name}); - defer gpa.free(sym_name); const lib_name = if (decl.getOwnedVariable(zcu)) |ov| zcu.intern_pool.stringToSliceUnwrap(ov.lib_name) else null; - const sym_index = try macho_file.getGlobalSymbol(sym_name, lib_name); + const sym_index = try macho_file.getGlobalSymbol(name, lib_name); macho_file.getSymbol(macho_file.getZigObject().?.symbols.items[sym_index]).flags.needs_got = true; return GenResult.mcv(.{ .load_symbol = sym_index }); } diff --git a/src/link/MachO.zig b/src/link/MachO.zig index df96318e7b..cb2debf6f2 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -3243,9 +3243,7 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void { const appendSect = struct { fn appendSect(macho_file: *MachO, sect_id: u8, seg_id: u8) void { const sect = &macho_file.sections.items(.header)[sect_id]; - const seg = &macho_file.segments.items[seg_id]; - seg.cmdsize += @sizeOf(macho.section_64); - seg.nsects += 1; + const seg = macho_file.segments.items[seg_id]; sect.addr = seg.vmaddr; sect.offset = @intCast(seg.fileoff); sect.size = seg.vmsize; diff --git a/src/link/MachO/ZigObject.zig b/src/link/MachO/ZigObject.zig index 4b677d3d61..f2e80f69cd 100644 --- a/src/link/MachO/ZigObject.zig +++ b/src/link/MachO/ZigObject.zig @@ -916,10 +916,7 @@ pub fn updateExports( continue; } - const exp_name = try std.fmt.allocPrint(gpa, "_{}", .{exp.opts.name.fmt(&mod.intern_pool)}); - defer gpa.free(exp_name); - - const name_off = try macho_file.strings.insert(gpa, exp_name); + const exp_name = mod.intern_pool.stringToSlice(exp.opts.name); const global_nlist_index = if (metadata.@"export"(self, macho_file, exp_name)) |exp_index| exp_index.* else blk: { @@ -928,7 +925,6 @@ pub fn updateExports( break :blk global_nlist_index; }; const global_nlist = &self.symtab.items(.nlist)[global_nlist_index]; - global_nlist.n_strx = name_off; global_nlist.n_value = nlist.n_value; global_nlist.n_sect = nlist.n_sect; global_nlist.n_type = macho.N_EXT | macho.N_SECT; @@ -1053,13 +1049,11 @@ pub fn deleteDeclExport( macho_file: *MachO, decl_index: InternPool.DeclIndex, name: InternPool.NullTerminatedString, -) Allocator.Error!void { +) void { const metadata = self.decls.getPtr(decl_index) orelse return; - const gpa = macho_file.base.comp.gpa; const mod = macho_file.base.comp.module.?; - const exp_name = try std.fmt.allocPrint(gpa, "_{s}", .{mod.intern_pool.stringToSlice(name)}); - defer gpa.free(exp_name); + const exp_name = mod.intern_pool.stringToSlice(name); const nlist_index = metadata.@"export"(self, macho_file, exp_name) orelse return; log.debug("deleting export '{s}'", .{exp_name}); @@ -1079,7 +1073,9 @@ pub fn deleteDeclExport( pub fn getGlobalSymbol(self: *ZigObject, macho_file: *MachO, name: []const u8, lib_name: ?[]const u8) !u32 { _ = lib_name; const gpa = macho_file.base.comp.gpa; - const off = try macho_file.strings.insert(gpa, name); + const sym_name = try std.fmt.allocPrint(gpa, "_{s}", .{name}); + defer gpa.free(sym_name); + const off = try macho_file.strings.insert(gpa, sym_name); const lookup_gop = try self.globals_lookup.getOrPut(gpa, off); if (!lookup_gop.found_existing) { const nlist_index = try self.addNlist(gpa); -- cgit v1.2.3 From 55f57ceb2e8f900ba281c5cf5524718cf7eb332f Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Sat, 20 Jan 2024 18:08:11 +0100 Subject: macho: prep for lowering TLS variables --- src/codegen.zig | 7 +++---- src/link/MachO/ZigObject.zig | 43 ++++++++++++++++++++----------------------- 2 files changed, 23 insertions(+), 27 deletions(-) (limited to 'src/codegen.zig') diff --git a/src/codegen.zig b/src/codegen.zig index 49f7feda8f..e9509c4efd 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -996,10 +996,9 @@ fn genDeclRef( } const sym_index = try macho_file.getZigObject().?.getOrCreateMetadataForDecl(macho_file, decl_index); const sym = macho_file.getSymbol(sym_index); - // TODO: tlv - // if (is_threadlocal) { - // return GenResult.mcv(.{ .load_tlv = sym.nlist_idx }); - // } + if (is_threadlocal) { + return GenResult.mcv(.{ .load_tlv = sym.nlist_idx }); + } return GenResult.mcv(.{ .load_symbol = sym.nlist_idx }); } else if (lf.cast(link.File.Coff)) |coff_file| { if (is_extern) { diff --git a/src/link/MachO/ZigObject.zig b/src/link/MachO/ZigObject.zig index 23673f2438..930d500e29 100644 --- a/src/link/MachO/ZigObject.zig +++ b/src/link/MachO/ZigObject.zig @@ -724,26 +724,25 @@ 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_sect_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_sect_index.?; if (Value.fromInterned(variable.init).isUndefDeep(mod)) { @@ -1112,17 +1111,15 @@ pub fn getOrCreateMetadataForDecl( const gop = try self.decls.getOrPut(gpa, decl_index); if (!gop.found_existing) { const any_non_single_threaded = macho_file.base.comp.config.any_non_single_threaded; - _ = any_non_single_threaded; const sym_index = try self.addAtom(macho_file); const mod = macho_file.base.comp.module.?; const decl = mod.declPtr(decl_index); - _ = decl; const sym = macho_file.getSymbol(sym_index); - // if (decl.getOwnedVariable(mod)) |variable| { - // if (variable.is_threadlocal and any_non_single_threaded) { - // sym.flags.tlv = true; - // } - // } + if (decl.getOwnedVariable(mod)) |variable| { + if (variable.is_threadlocal and any_non_single_threaded) { + sym.flags.tlv = true; + } + } if (!sym.flags.tlv) { sym.flags.needs_zig_got = true; } -- cgit v1.2.3