| author | |
| committer | |
| log | 96cc9fafbf0a382c0ed0b6142986cd8373cffaa3 |
| tree | ec6cf83208e30a54f263807cf4e72f07b90457cd |
| parent | 76dc305d4e71a9a4c9de92e6dde40a53eac1e328 |
8 files changed, 197 insertions(+), 202 deletions(-)
src/arch/x86_64/CodeGen.zig+27-63| ... | ... | @@ -139,10 +139,7 @@ const Owner = union(enum) { |
| 139 | 139 | if (ctx.bin_file.cast(link.File.Elf)) |elf_file| { |
| 140 | 140 | return elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, decl_index); |
| 141 | 141 | } else if (ctx.bin_file.cast(link.File.MachO)) |macho_file| { |
| 142 | _ = macho_file; | |
| 143 | // const atom = try macho_file.getOrCreateAtomForDecl(decl_index); | |
| 144 | // return macho_file.getAtom(atom).getSymbolIndex().?; | |
| 145 | @panic("TODO getSymbolIndex"); | |
| 142 | return macho_file.getZigObject().?.getOrCreateMetadataForDecl(macho_file, decl_index); | |
| 146 | 143 | } else if (ctx.bin_file.cast(link.File.Coff)) |coff_file| { |
| 147 | 144 | const atom = try coff_file.getOrCreateAtomForDecl(decl_index); |
| 148 | 145 | return coff_file.getAtom(atom).getSymbolIndex().?; |
| ... | ... | @@ -155,11 +152,8 @@ const Owner = union(enum) { |
| 155 | 152 | return elf_file.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(elf_file, lazy_sym) catch |err| |
| 156 | 153 | ctx.fail("{s} creating lazy symbol", .{@errorName(err)}); |
| 157 | 154 | } else if (ctx.bin_file.cast(link.File.MachO)) |macho_file| { |
| 158 | _ = macho_file; | |
| 159 | // const atom = macho_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err| | |
| 160 | // return ctx.fail("{s} creating lazy symbol", .{@errorName(err)}); | |
| 161 | // return macho_file.getAtom(atom).getSymbolIndex().?; | |
| 162 | @panic("TODO getSymbolIndex"); | |
| 155 | return macho_file.getZigObject().?.getOrCreateMetadataForLazySymbol(macho_file, lazy_sym) catch |err| | |
| 156 | ctx.fail("{s} creating lazy symbol", .{@errorName(err)}); | |
| 163 | 157 | } else if (ctx.bin_file.cast(link.File.Coff)) |coff_file| { |
| 164 | 158 | const atom = coff_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err| |
| 165 | 159 | return ctx.fail("{s} creating lazy symbol", .{@errorName(err)}); |
| ... | ... | @@ -10955,12 +10949,10 @@ fn genCall(self: *Self, info: union(enum) { |
| 10955 | 10949 | try self.genSetReg(.rax, Type.usize, .{ .lea_got = sym_index }); |
| 10956 | 10950 | try self.asmRegister(.{ ._, .call }, .rax); |
| 10957 | 10951 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { |
| 10958 | _ = macho_file; | |
| 10959 | @panic("TODO genCall"); | |
| 10960 | // const atom = try macho_file.getOrCreateAtomForDecl(func.owner_decl); | |
| 10961 | // const sym_index = macho_file.getAtom(atom).getSymbolIndex().?; | |
| 10962 | // try self.genSetReg(.rax, Type.usize, .{ .lea_got = sym_index }); | |
| 10963 | // try self.asmRegister(.{ ._, .call }, .rax); | |
| 10952 | const sym_index = try macho_file.getZigObject().?.getOrCreateMetadataForDecl(macho_file, func.owner_decl); | |
| 10953 | const sym = macho_file.getSymbol(sym_index); | |
| 10954 | try self.genSetReg(.rax, Type.usize, .{ .load_symbol = .{ .sym = sym.nlist_idx } }); | |
| 10955 | try self.asmRegister(.{ ._, .call }, .rax); | |
| 10964 | 10956 | } else if (self.bin_file.cast(link.File.Plan9)) |p9| { |
| 10965 | 10957 | const atom_index = try p9.seeDecl(func.owner_decl); |
| 10966 | 10958 | const atom = p9.getAtom(atom_index); |
| ... | ... | @@ -13556,30 +13548,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr |
| 13556 | 13548 | } }, |
| 13557 | 13549 | }); |
| 13558 | 13550 | }, |
| 13559 | .lea_tlv => |sym_index| { | |
| 13560 | const atom_index = try self.owner.getSymbolIndex(self); | |
| 13561 | if (self.bin_file.cast(link.File.MachO)) |_| { | |
| 13562 | _ = try self.addInst(.{ | |
| 13563 | .tag = .lea, | |
| 13564 | .ops = .tlv_reloc, | |
| 13565 | .data = .{ .rx = .{ | |
| 13566 | .r1 = .rdi, | |
| 13567 | .payload = try self.addExtra(bits.Symbol{ | |
| 13568 | .atom_index = atom_index, | |
| 13569 | .sym_index = sym_index, | |
| 13570 | }), | |
| 13571 | } }, | |
| 13572 | }); | |
| 13573 | // TODO: spill registers before calling | |
| 13574 | try self.asmMemory(.{ ._, .call }, .{ | |
| 13575 | .base = .{ .reg = .rdi }, | |
| 13576 | .mod = .{ .rm = .{ .size = .qword } }, | |
| 13577 | }); | |
| 13578 | try self.genSetReg(dst_reg.to64(), Type.usize, .{ .register = .rax }); | |
| 13579 | } else return self.fail("TODO emit ptr to TLV sequence on {s}", .{ | |
| 13580 | @tagName(self.bin_file.tag), | |
| 13581 | }); | |
| 13582 | }, | |
| 13551 | .lea_tlv => unreachable, // TODO: remove this | |
| 13583 | 13552 | .air_ref => |src_ref| try self.genSetReg(dst_reg, ty, try self.resolveInst(src_ref)), |
| 13584 | 13553 | } |
| 13585 | 13554 | } |
| ... | ... | @@ -13816,19 +13785,14 @@ fn genExternSymbolRef( |
| 13816 | 13785 | else => unreachable, |
| 13817 | 13786 | } |
| 13818 | 13787 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { |
| 13819 | const global_index = try macho_file.getGlobalSymbol(callee, lib); | |
| 13820 | 13788 | _ = try self.addInst(.{ |
| 13821 | 13789 | .tag = .call, |
| 13822 | 13790 | .ops = .extern_fn_reloc, |
| 13823 | .data = .{ | |
| 13824 | .reloc = .{ | |
| 13825 | .atom_index = atom_index, | |
| 13826 | // .sym_index = link.File.MachO.global_symbol_bit | global_index, | |
| 13827 | .sym_index = global_index, | |
| 13828 | }, | |
| 13829 | }, | |
| 13791 | .data = .{ .reloc = .{ | |
| 13792 | .atom_index = atom_index, | |
| 13793 | .sym_index = try macho_file.getGlobalSymbol(callee, lib), | |
| 13794 | } }, | |
| 13830 | 13795 | }); |
| 13831 | @panic("TODO genExternSymbolRef"); | |
| 13832 | 13796 | } else return self.fail("TODO implement calling extern functions", .{}); |
| 13833 | 13797 | } |
| 13834 | 13798 | |
| ... | ... | @@ -13916,21 +13880,19 @@ fn genLazySymbolRef( |
| 13916 | 13880 | else => unreachable, |
| 13917 | 13881 | } |
| 13918 | 13882 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { |
| 13919 | _ = macho_file; | |
| 13920 | @panic("TODO genLazySymbolRef"); | |
| 13921 | // const atom_index = macho_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err| | |
| 13922 | // return self.fail("{s} creating lazy symbol", .{@errorName(err)}); | |
| 13923 | // const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?; | |
| 13924 | // switch (tag) { | |
| 13925 | // .lea, .call => try self.genSetReg(reg, Type.usize, .{ .lea_got = sym_index }), | |
| 13926 | // .mov => try self.genSetReg(reg, Type.usize, .{ .load_got = sym_index }), | |
| 13927 | // else => unreachable, | |
| 13928 | // } | |
| 13929 | // switch (tag) { | |
| 13930 | // .lea, .mov => {}, | |
| 13931 | // .call => try self.asmRegister(.{ ._, .call }, reg), | |
| 13932 | // else => unreachable, | |
| 13933 | // } | |
| 13883 | const sym_index = macho_file.getZigObject().?.getOrCreateMetadataForLazySymbol(macho_file, lazy_sym) catch |err| | |
| 13884 | return self.fail("{s} creating lazy symbol", .{@errorName(err)}); | |
| 13885 | const sym = macho_file.getSymbol(sym_index); | |
| 13886 | switch (tag) { | |
| 13887 | .lea, .call => try self.genSetReg(reg, Type.usize, .{ .load_symbol = .{ .sym = sym.nlist_idx } }), | |
| 13888 | .mov => try self.genSetReg(reg, Type.usize, .{ .load_symbol = .{ .sym = sym.nlist_idx } }), | |
| 13889 | else => unreachable, | |
| 13890 | } | |
| 13891 | switch (tag) { | |
| 13892 | .lea, .mov => {}, | |
| 13893 | .call => try self.asmRegister(.{ ._, .call }, reg), | |
| 13894 | else => unreachable, | |
| 13895 | } | |
| 13934 | 13896 | } else { |
| 13935 | 13897 | return self.fail("TODO implement genLazySymbol for x86_64 {s}", .{@tagName(self.bin_file.tag)}); |
| 13936 | 13898 | } |
| ... | ... | @@ -16103,6 +16065,8 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue { |
| 16103 | 16065 | .{ .lea_symbol = .{ .sym = tlv_sym } }, |
| 16104 | 16066 | ); |
| 16105 | 16067 | break :init .{ .load_frame = .{ .index = frame_index } }; |
| 16068 | } else if (self.bin_file.cast(link.File.MachO)) |_| { | |
| 16069 | return self.fail("TODO implement lowering TLV variable to stack", .{}); | |
| 16106 | 16070 | } else break :init const_mcv, |
| 16107 | 16071 | else => break :init const_mcv, |
| 16108 | 16072 | } |
src/arch/x86_64/Emit.zig+47-39| ... | ... | @@ -49,23 +49,21 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 49 | 49 | .r_addend = -4, |
| 50 | 50 | }); |
| 51 | 51 | } else if (emit.lower.bin_file.cast(link.File.MachO)) |macho_file| { |
| 52 | _ = macho_file; | |
| 53 | @panic("TODO emitMir"); | |
| 54 | // // Add relocation to the decl. | |
| 55 | // const atom_index = | |
| 56 | // macho_file.getAtomIndexForSymbol(.{ .sym_index = symbol.atom_index }).?; | |
| 57 | // const target = if (link.File.MachO.global_symbol_bit & symbol.sym_index != 0) | |
| 58 | // macho_file.getGlobalByIndex(link.File.MachO.global_symbol_mask & symbol.sym_index) | |
| 59 | // else | |
| 60 | // link.File.MachO.SymbolWithLoc{ .sym_index = symbol.sym_index }; | |
| 61 | // try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{ | |
| 62 | // .type = .branch, | |
| 63 | // .target = target, | |
| 64 | // .offset = end_offset - 4, | |
| 65 | // .addend = 0, | |
| 66 | // .pcrel = true, | |
| 67 | // .length = 2, | |
| 68 | // }); | |
| 52 | // Add relocation to the decl. | |
| 53 | const atom = macho_file.getSymbol(symbol.atom_index).getAtom(macho_file).?; | |
| 54 | try atom.addReloc(macho_file, .{ | |
| 55 | .tag = .@"extern", | |
| 56 | .offset = end_offset - 4, | |
| 57 | .target = symbol.sym_index, | |
| 58 | .addend = 0, | |
| 59 | .type = .branch, | |
| 60 | .meta = .{ | |
| 61 | .pcrel = true, | |
| 62 | .has_subtractor = false, | |
| 63 | .length = 2, | |
| 64 | .symbolnum = 0, | |
| 65 | }, | |
| 66 | }); | |
| 69 | 67 | } else if (emit.lower.bin_file.cast(link.File.Coff)) |coff_file| { |
| 70 | 68 | // Add relocation to the decl. |
| 71 | 69 | const atom_index = coff_file.getAtomIndexForSymbol( |
| ... | ... | @@ -151,6 +149,36 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 151 | 149 | }); |
| 152 | 150 | } |
| 153 | 151 | } |
| 152 | } else if (emit.lower.bin_file.cast(link.File.MachO)) |macho_file| { | |
| 153 | const is_obj_or_static_lib = switch (emit.lower.output_mode) { | |
| 154 | .Exe => false, | |
| 155 | .Obj => true, | |
| 156 | .Lib => emit.lower.link_mode == .Static, | |
| 157 | }; | |
| 158 | const atom = macho_file.getSymbol(data.atom_index).getAtom(macho_file).?; | |
| 159 | const sym = macho_file.getSymbol(data.sym_index); | |
| 160 | if (sym.flags.needs_zig_got and !is_obj_or_static_lib) { | |
| 161 | _ = try sym.getOrCreateZigGotEntry(data.sym_index, macho_file); | |
| 162 | } | |
| 163 | const @"type": link.File.MachO.Relocation.Type = if (sym.flags.needs_zig_got and !is_obj_or_static_lib) | |
| 164 | .zig_got_load | |
| 165 | else if (sym.flags.needs_got) | |
| 166 | .got_load | |
| 167 | else | |
| 168 | .signed; | |
| 169 | try atom.addReloc(macho_file, .{ | |
| 170 | .tag = .@"extern", | |
| 171 | .offset = @intCast(end_offset - 4), | |
| 172 | .target = data.sym_index, | |
| 173 | .addend = 0, | |
| 174 | .type = @"type", | |
| 175 | .meta = .{ | |
| 176 | .pcrel = true, | |
| 177 | .has_subtractor = false, | |
| 178 | .length = 2, | |
| 179 | .symbolnum = 0, | |
| 180 | }, | |
| 181 | }); | |
| 154 | 182 | } else unreachable, |
| 155 | 183 | .linker_got, |
| 156 | 184 | .linker_direct, |
| ... | ... | @@ -158,28 +186,8 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 158 | 186 | .linker_tlv, |
| 159 | 187 | => |symbol| if (emit.lower.bin_file.cast(link.File.Elf)) |_| { |
| 160 | 188 | unreachable; |
| 161 | } else if (emit.lower.bin_file.cast(link.File.MachO)) |macho_file| { | |
| 162 | _ = macho_file; | |
| 163 | @panic("TODO emitMir"); | |
| 164 | // const atom_index = | |
| 165 | // macho_file.getAtomIndexForSymbol(.{ .sym_index = symbol.atom_index }).?; | |
| 166 | // const target = if (link.File.MachO.global_symbol_bit & symbol.sym_index != 0) | |
| 167 | // macho_file.getGlobalByIndex(link.File.MachO.global_symbol_mask & symbol.sym_index) | |
| 168 | // else | |
| 169 | // link.File.MachO.SymbolWithLoc{ .sym_index = symbol.sym_index }; | |
| 170 | // try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{ | |
| 171 | // .type = switch (lowered_relocs[0].target) { | |
| 172 | // .linker_got => .got, | |
| 173 | // .linker_direct => .signed, | |
| 174 | // .linker_tlv => .tlv, | |
| 175 | // else => unreachable, | |
| 176 | // }, | |
| 177 | // .target = target, | |
| 178 | // .offset = @intCast(end_offset - 4), | |
| 179 | // .addend = 0, | |
| 180 | // .pcrel = true, | |
| 181 | // .length = 2, | |
| 182 | // }); | |
| 189 | } else if (emit.lower.bin_file.cast(link.File.MachO)) |_| { | |
| 190 | unreachable; | |
| 183 | 191 | } else if (emit.lower.bin_file.cast(link.File.Coff)) |coff_file| { |
| 184 | 192 | const atom_index = coff_file.getAtomIndexForSymbol(.{ |
| 185 | 193 | .sym_index = symbol.atom_index, |
src/arch/x86_64/Lower.zig+89-80| ... | ... | @@ -14,7 +14,7 @@ result_relocs_len: u8 = undefined, |
| 14 | 14 | result_insts: [ |
| 15 | 15 | std.mem.max(usize, &.{ |
| 16 | 16 | 1, // non-pseudo instructions |
| 17 | 3, // TLS local dynamic (LD) sequence in PIC mode | |
| 17 | 3, // (ELF only) TLS local dynamic (LD) sequence in PIC mode | |
| 18 | 18 | 2, // cmovcc: cmovcc \ cmovcc |
| 19 | 19 | 3, // setcc: setcc \ setcc \ logicop |
| 20 | 20 | 2, // jcc: jcc \ jcc |
| ... | ... | @@ -32,7 +32,7 @@ result_relocs: [ |
| 32 | 32 | 2, // jcc: jcc \ jcc |
| 33 | 33 | 2, // test \ jcc \ probe \ sub \ jmp |
| 34 | 34 | 1, // probe \ sub \ jcc |
| 35 | 3, // TLS local dynamic (LD) sequence in PIC mode | |
| 35 | 3, // (ELF only) TLS local dynamic (LD) sequence in PIC mode | |
| 36 | 36 | }) |
| 37 | 37 | ]Reloc = undefined, |
| 38 | 38 | |
| ... | ... | @@ -326,18 +326,6 @@ fn reloc(lower: *Lower, target: Reloc.Target) Immediate { |
| 326 | 326 | return Immediate.s(0); |
| 327 | 327 | } |
| 328 | 328 | |
| 329 | fn needsZigGot(sym: bits.Symbol, ctx: *link.File) bool { | |
| 330 | const elf_file = ctx.cast(link.File.Elf).?; | |
| 331 | const sym_index = elf_file.zigObjectPtr().?.symbol(sym.sym_index); | |
| 332 | return elf_file.symbol(sym_index).flags.needs_zig_got; | |
| 333 | } | |
| 334 | ||
| 335 | fn isTls(sym: bits.Symbol, ctx: *link.File) bool { | |
| 336 | const elf_file = ctx.cast(link.File.Elf).?; | |
| 337 | const sym_index = elf_file.zigObjectPtr().?.symbol(sym.sym_index); | |
| 338 | return elf_file.symbol(sym_index).flags.is_tls; | |
| 339 | } | |
| 340 | ||
| 341 | 329 | fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) Error!void { |
| 342 | 330 | const is_obj_or_static_lib = switch (lower.output_mode) { |
| 343 | 331 | .Exe => false, |
| ... | ... | @@ -359,80 +347,101 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) |
| 359 | 347 | assert(mem_op.sib.disp == 0); |
| 360 | 348 | assert(mem_op.sib.scale_index.scale == 0); |
| 361 | 349 | |
| 362 | if (isTls(sym, lower.bin_file)) { | |
| 363 | // TODO handle extern TLS vars, i.e., emit GD model | |
| 364 | if (lower.pic) { | |
| 365 | // Here, we currently assume local dynamic TLS vars, and so | |
| 366 | // we emit LD model. | |
| 367 | _ = lower.reloc(.{ .linker_tlsld = sym }); | |
| 368 | lower.result_insts[lower.result_insts_len] = | |
| 369 | try Instruction.new(.none, .lea, &[_]Operand{ | |
| 370 | .{ .reg = .rdi }, | |
| 371 | .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) }, | |
| 372 | }); | |
| 373 | lower.result_insts_len += 1; | |
| 374 | if (lower.bin_file.cast(link.File.Elf)) |elf_file| { | |
| 350 | if (lower.bin_file.cast(link.File.Elf)) |elf_file| { | |
| 351 | const sym_index = elf_file.zigObjectPtr().?.symbol(sym.sym_index); | |
| 352 | const elf_sym = elf_file.symbol(sym_index); | |
| 353 | ||
| 354 | if (elf_sym.flags.is_tls) { | |
| 355 | // TODO handle extern TLS vars, i.e., emit GD model | |
| 356 | if (lower.pic) { | |
| 357 | // Here, we currently assume local dynamic TLS vars, and so | |
| 358 | // we emit LD model. | |
| 359 | _ = lower.reloc(.{ .linker_tlsld = sym }); | |
| 360 | lower.result_insts[lower.result_insts_len] = | |
| 361 | try Instruction.new(.none, .lea, &[_]Operand{ | |
| 362 | .{ .reg = .rdi }, | |
| 363 | .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) }, | |
| 364 | }); | |
| 365 | lower.result_insts_len += 1; | |
| 375 | 366 | _ = lower.reloc(.{ .linker_extern_fn = .{ |
| 376 | 367 | .atom_index = sym.atom_index, |
| 377 | 368 | .sym_index = try elf_file.getGlobalSymbol("__tls_get_addr", null), |
| 378 | 369 | } }); |
| 370 | lower.result_insts[lower.result_insts_len] = | |
| 371 | try Instruction.new(.none, .call, &[_]Operand{ | |
| 372 | .{ .imm = Immediate.s(0) }, | |
| 373 | }); | |
| 374 | lower.result_insts_len += 1; | |
| 375 | _ = lower.reloc(.{ .linker_dtpoff = sym }); | |
| 376 | emit_mnemonic = .lea; | |
| 377 | break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{ | |
| 378 | .base = .{ .reg = .rax }, | |
| 379 | .disp = std.math.minInt(i32), | |
| 380 | }) }; | |
| 381 | } else { | |
| 382 | // Since we are linking statically, we emit LE model directly. | |
| 383 | lower.result_insts[lower.result_insts_len] = | |
| 384 | try Instruction.new(.none, .mov, &[_]Operand{ | |
| 385 | .{ .reg = .rax }, | |
| 386 | .{ .mem = Memory.sib(.qword, .{ .base = .{ .reg = .fs } }) }, | |
| 387 | }); | |
| 388 | lower.result_insts_len += 1; | |
| 389 | _ = lower.reloc(.{ .linker_reloc = sym }); | |
| 390 | emit_mnemonic = .lea; | |
| 391 | break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{ | |
| 392 | .base = .{ .reg = .rax }, | |
| 393 | .disp = std.math.minInt(i32), | |
| 394 | }) }; | |
| 379 | 395 | } |
| 380 | lower.result_insts[lower.result_insts_len] = | |
| 381 | try Instruction.new(.none, .call, &[_]Operand{ | |
| 382 | .{ .imm = Immediate.s(0) }, | |
| 383 | }); | |
| 384 | lower.result_insts_len += 1; | |
| 385 | _ = lower.reloc(.{ .linker_dtpoff = sym }); | |
| 386 | emit_mnemonic = .lea; | |
| 387 | break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{ | |
| 388 | .base = .{ .reg = .rax }, | |
| 389 | .disp = std.math.minInt(i32), | |
| 390 | }) }; | |
| 391 | } else { | |
| 392 | // Since we are linking statically, we emit LE model directly. | |
| 393 | lower.result_insts[lower.result_insts_len] = | |
| 394 | try Instruction.new(.none, .mov, &[_]Operand{ | |
| 395 | .{ .reg = .rax }, | |
| 396 | .{ .mem = Memory.sib(.qword, .{ .base = .{ .reg = .fs } }) }, | |
| 397 | }); | |
| 398 | lower.result_insts_len += 1; | |
| 399 | _ = lower.reloc(.{ .linker_reloc = sym }); | |
| 400 | emit_mnemonic = .lea; | |
| 401 | break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{ | |
| 402 | .base = .{ .reg = .rax }, | |
| 403 | .disp = std.math.minInt(i32), | |
| 404 | }) }; | |
| 405 | 396 | } |
| 406 | } | |
| 407 | 397 | |
| 408 | _ = lower.reloc(.{ .linker_reloc = sym }); | |
| 409 | break :op if (lower.pic) switch (mnemonic) { | |
| 410 | .lea => { | |
| 411 | break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) }; | |
| 412 | }, | |
| 413 | .mov => { | |
| 414 | if (is_obj_or_static_lib and needsZigGot(sym, lower.bin_file)) emit_mnemonic = .lea; | |
| 415 | break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) }; | |
| 416 | }, | |
| 417 | else => unreachable, | |
| 418 | } else switch (mnemonic) { | |
| 419 | .call => break :op if (is_obj_or_static_lib and needsZigGot(sym, lower.bin_file)) .{ | |
| 420 | .imm = Immediate.s(0), | |
| 421 | } else .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{ | |
| 422 | .base = .{ .reg = .ds }, | |
| 423 | }) }, | |
| 424 | .lea => { | |
| 425 | emit_mnemonic = .mov; | |
| 426 | break :op .{ .imm = Immediate.s(0) }; | |
| 427 | }, | |
| 428 | .mov => { | |
| 429 | if (is_obj_or_static_lib and needsZigGot(sym, lower.bin_file)) emit_mnemonic = .lea; | |
| 430 | break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{ | |
| 398 | _ = lower.reloc(.{ .linker_reloc = sym }); | |
| 399 | break :op if (lower.pic) switch (mnemonic) { | |
| 400 | .lea => { | |
| 401 | break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) }; | |
| 402 | }, | |
| 403 | .mov => { | |
| 404 | if (is_obj_or_static_lib and elf_sym.flags.needs_zig_got) emit_mnemonic = .lea; | |
| 405 | break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) }; | |
| 406 | }, | |
| 407 | else => unreachable, | |
| 408 | } else switch (mnemonic) { | |
| 409 | .call => break :op if (is_obj_or_static_lib and elf_sym.flags.needs_zig_got) .{ | |
| 410 | .imm = Immediate.s(0), | |
| 411 | } else .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{ | |
| 431 | 412 | .base = .{ .reg = .ds }, |
| 432 | }) }; | |
| 433 | }, | |
| 434 | else => unreachable, | |
| 435 | }; | |
| 413 | }) }, | |
| 414 | .lea => { | |
| 415 | emit_mnemonic = .mov; | |
| 416 | break :op .{ .imm = Immediate.s(0) }; | |
| 417 | }, | |
| 418 | .mov => { | |
| 419 | if (is_obj_or_static_lib and elf_sym.flags.needs_zig_got) emit_mnemonic = .lea; | |
| 420 | break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{ | |
| 421 | .base = .{ .reg = .ds }, | |
| 422 | }) }; | |
| 423 | }, | |
| 424 | else => unreachable, | |
| 425 | }; | |
| 426 | } else if (lower.bin_file.cast(link.File.MachO)) |macho_file| { | |
| 427 | const macho_sym = macho_file.getSymbol(sym.sym_index); | |
| 428 | ||
| 429 | if (macho_sym.flags.tlv) { | |
| 430 | @panic("TODO lower TLS access on macOS"); | |
| 431 | } | |
| 432 | ||
| 433 | _ = lower.reloc(.{ .linker_reloc = sym }); | |
| 434 | break :op switch (mnemonic) { | |
| 435 | .lea => { | |
| 436 | break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) }; | |
| 437 | }, | |
| 438 | .mov => { | |
| 439 | if (is_obj_or_static_lib and macho_sym.flags.needs_zig_got) emit_mnemonic = .lea; | |
| 440 | break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) }; | |
| 441 | }, | |
| 442 | else => unreachable, | |
| 443 | }; | |
| 444 | } | |
| 436 | 445 | }, |
| 437 | 446 | }, |
| 438 | 447 | }; |
src/codegen.zig+6-1| ... | ... | @@ -1045,7 +1045,12 @@ fn genUnnamedConst( |
| 1045 | 1045 | const local = elf_file.symbol(local_sym_index); |
| 1046 | 1046 | return GenResult.mcv(.{ .load_symbol = local.esym_index }); |
| 1047 | 1047 | }, |
| 1048 | .macho, .coff => { | |
| 1048 | .macho => { | |
| 1049 | const macho_file = lf.cast(link.File.MachO).?; | |
| 1050 | const local = macho_file.getSymbol(local_sym_index); | |
| 1051 | return GenResult.mcv(.{ .load_symbol = local.nlist_idx }); | |
| 1052 | }, | |
| 1053 | .coff => { | |
| 1049 | 1054 | return GenResult.mcv(.{ .load_direct = local_sym_index }); |
| 1050 | 1055 | }, |
| 1051 | 1056 | .plan9 => { |
src/link/MachO.zig+1-1| ... | ... | @@ -4280,7 +4280,7 @@ const Md5 = std.crypto.hash.Md5; |
| 4280 | 4280 | const Module = @import("../Module.zig"); |
| 4281 | 4281 | const InternPool = @import("../InternPool.zig"); |
| 4282 | 4282 | const RebaseSection = synthetic.RebaseSection; |
| 4283 | const Relocation = @import("MachO/Relocation.zig"); | |
| 4283 | pub const Relocation = @import("MachO/Relocation.zig"); | |
| 4284 | 4284 | const StringTable = @import("StringTable.zig"); |
| 4285 | 4285 | const StubsSection = synthetic.StubsSection; |
| 4286 | 4286 | const StubsHelperSection = synthetic.StubsHelperSection; |
src/link/MachO/Atom.zig+6| ... | ... | @@ -686,6 +686,10 @@ fn resolveRelocInner( |
| 686 | 686 | } |
| 687 | 687 | }, |
| 688 | 688 | |
| 689 | .zig_got_load => { | |
| 690 | @panic("TODO resolve __got_zig indirection reloc"); | |
| 691 | }, | |
| 692 | ||
| 689 | 693 | .tlv => { |
| 690 | 694 | assert(rel.tag == .@"extern"); |
| 691 | 695 | assert(rel.meta.length == 2); |
| ... | ... | @@ -987,6 +991,7 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: *std.Arra |
| 987 | 991 | .subtractor => .ARM64_RELOC_SUBTRACTOR, |
| 988 | 992 | .unsigned => .ARM64_RELOC_UNSIGNED, |
| 989 | 993 | |
| 994 | .zig_got_load, | |
| 990 | 995 | .signed, |
| 991 | 996 | .signed1, |
| 992 | 997 | .signed2, |
| ... | ... | @@ -1030,6 +1035,7 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: *std.Arra |
| 1030 | 1035 | .subtractor => .X86_64_RELOC_SUBTRACTOR, |
| 1031 | 1036 | .unsigned => .X86_64_RELOC_UNSIGNED, |
| 1032 | 1037 | |
| 1038 | .zig_got_load, | |
| 1033 | 1039 | .page, |
| 1034 | 1040 | .pageoff, |
| 1035 | 1041 | .got_load_page, |
src/link/MachO/Relocation.zig+2| ... | ... | @@ -99,6 +99,8 @@ pub const Type = enum { |
| 99 | 99 | got_load, |
| 100 | 100 | /// RIP-relative TLV load (X86_64_RELOC_TLV) |
| 101 | 101 | tlv, |
| 102 | /// Zig-specific __got_zig indirection | |
| 103 | zig_got_load, | |
| 102 | 104 | |
| 103 | 105 | // arm64 |
| 104 | 106 | /// PC-relative load (distance to page, ARM64_RELOC_PAGE21) |
src/link/MachO/ZigObject.zig+19-18| ... | ... | @@ -248,7 +248,7 @@ pub fn getDeclVAddr( |
| 248 | 248 | .pcrel = false, |
| 249 | 249 | .has_subtractor = false, |
| 250 | 250 | .length = 3, |
| 251 | .symbolnum = @intCast(sym.nlist_idx), | |
| 251 | .symbolnum = 0, | |
| 252 | 252 | }, |
| 253 | 253 | }); |
| 254 | 254 | return vaddr; |
| ... | ... | @@ -274,7 +274,7 @@ pub fn getAnonDeclVAddr( |
| 274 | 274 | .pcrel = false, |
| 275 | 275 | .has_subtractor = false, |
| 276 | 276 | .length = 3, |
| 277 | .symbolnum = @intCast(sym.nlist_idx), | |
| 277 | .symbolnum = 0, | |
| 278 | 278 | }, |
| 279 | 279 | }); |
| 280 | 280 | return vaddr; |
| ... | ... | @@ -604,25 +604,26 @@ fn getDeclOutputSection( |
| 604 | 604 | _ = self; |
| 605 | 605 | const mod = macho_file.base.comp.module.?; |
| 606 | 606 | const any_non_single_threaded = macho_file.base.comp.config.any_non_single_threaded; |
| 607 | _ = any_non_single_threaded; | |
| 607 | 608 | const sect_id: u8 = switch (decl.ty.zigTypeTag(mod)) { |
| 608 | 609 | .Fn => macho_file.zig_text_section_index.?, |
| 609 | 610 | else => blk: { |
| 610 | 611 | if (decl.getOwnedVariable(mod)) |variable| { |
| 611 | if (variable.is_threadlocal and any_non_single_threaded) { | |
| 612 | const is_all_zeroes = for (code) |byte| { | |
| 613 | if (byte != 0) break false; | |
| 614 | } else true; | |
| 615 | if (is_all_zeroes) break :blk macho_file.getSectionByName("__DATA", "__thread_bss") orelse try macho_file.addSection( | |
| 616 | "__DATA", | |
| 617 | "__thread_bss", | |
| 618 | .{ .flags = macho.S_THREAD_LOCAL_ZEROFILL }, | |
| 619 | ); | |
| 620 | break :blk macho_file.getSectionByName("__DATA", "__thread_data") orelse try macho_file.addSection( | |
| 621 | "__DATA", | |
| 622 | "__thread_data", | |
| 623 | .{ .flags = macho.S_THREAD_LOCAL_REGULAR }, | |
| 624 | ); | |
| 625 | } | |
| 612 | // if (variable.is_threadlocal and any_non_single_threaded) { | |
| 613 | // const is_all_zeroes = for (code) |byte| { | |
| 614 | // if (byte != 0) break false; | |
| 615 | // } else true; | |
| 616 | // if (is_all_zeroes) break :blk macho_file.getSectionByName("__DATA", "__thread_bss") orelse try macho_file.addSection( | |
| 617 | // "__DATA", | |
| 618 | // "__thread_bss", | |
| 619 | // .{ .flags = macho.S_THREAD_LOCAL_ZEROFILL }, | |
| 620 | // ); | |
| 621 | // break :blk macho_file.getSectionByName("__DATA", "__thread_data") orelse try macho_file.addSection( | |
| 622 | // "__DATA", | |
| 623 | // "__thread_data", | |
| 624 | // .{ .flags = macho.S_THREAD_LOCAL_REGULAR }, | |
| 625 | // ); | |
| 626 | // } | |
| 626 | 627 | |
| 627 | 628 | if (variable.is_const) break :blk macho_file.zig_const_section_index.?; |
| 628 | 629 | if (Value.fromInterned(variable.init).isUndefDeep(mod)) { |
| ... | ... | @@ -917,7 +918,7 @@ fn updateLazySymbol( |
| 917 | 918 | |
| 918 | 919 | sym.value = 0; |
| 919 | 920 | sym.flags.needs_zig_got = true; |
| 920 | nlist.st_value = 0; | |
| 921 | nlist.n_value = 0; | |
| 921 | 922 | |
| 922 | 923 | if (!macho_file.base.isRelocatable()) { |
| 923 | 924 | const gop = try sym.getOrCreateZigGotEntry(symbol_index, macho_file); |