authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-01-18 18:58:29+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-01-24 12:34:41+01:00
log96cc9fafbf0a382c0ed0b6142986cd8373cffaa3
treeec6cf83208e30a54f263807cf4e72f07b90457cd
parent76dc305d4e71a9a4c9de92e6dde40a53eac1e328

codegen: re-implement enough of codegen to error out instead panic


8 files changed, 197 insertions(+), 202 deletions(-)

src/arch/x86_64/CodeGen.zig+27-63
...@@ -139,10 +139,7 @@ const Owner = union(enum) {...@@ -139,10 +139,7 @@ const Owner = union(enum) {
139 if (ctx.bin_file.cast(link.File.Elf)) |elf_file| {139 if (ctx.bin_file.cast(link.File.Elf)) |elf_file| {
140 return elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, decl_index);140 return elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, decl_index);
141 } else if (ctx.bin_file.cast(link.File.MachO)) |macho_file| {141 } else if (ctx.bin_file.cast(link.File.MachO)) |macho_file| {
142 _ = macho_file;142 return macho_file.getZigObject().?.getOrCreateMetadataForDecl(macho_file, decl_index);
143 // const atom = try macho_file.getOrCreateAtomForDecl(decl_index);
144 // return macho_file.getAtom(atom).getSymbolIndex().?;
145 @panic("TODO getSymbolIndex");
146 } else if (ctx.bin_file.cast(link.File.Coff)) |coff_file| {143 } else if (ctx.bin_file.cast(link.File.Coff)) |coff_file| {
147 const atom = try coff_file.getOrCreateAtomForDecl(decl_index);144 const atom = try coff_file.getOrCreateAtomForDecl(decl_index);
148 return coff_file.getAtom(atom).getSymbolIndex().?;145 return coff_file.getAtom(atom).getSymbolIndex().?;
...@@ -155,11 +152,8 @@ const Owner = union(enum) {...@@ -155,11 +152,8 @@ const Owner = union(enum) {
155 return elf_file.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(elf_file, lazy_sym) catch |err|152 return elf_file.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(elf_file, lazy_sym) catch |err|
156 ctx.fail("{s} creating lazy symbol", .{@errorName(err)});153 ctx.fail("{s} creating lazy symbol", .{@errorName(err)});
157 } else if (ctx.bin_file.cast(link.File.MachO)) |macho_file| {154 } else if (ctx.bin_file.cast(link.File.MachO)) |macho_file| {
158 _ = macho_file;155 return macho_file.getZigObject().?.getOrCreateMetadataForLazySymbol(macho_file, lazy_sym) catch |err|
159 // const atom = macho_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err|156 ctx.fail("{s} creating lazy symbol", .{@errorName(err)});
160 // return ctx.fail("{s} creating lazy symbol", .{@errorName(err)});
161 // return macho_file.getAtom(atom).getSymbolIndex().?;
162 @panic("TODO getSymbolIndex");
163 } else if (ctx.bin_file.cast(link.File.Coff)) |coff_file| {157 } else if (ctx.bin_file.cast(link.File.Coff)) |coff_file| {
164 const atom = coff_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err|158 const atom = coff_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err|
165 return ctx.fail("{s} creating lazy symbol", .{@errorName(err)});159 return ctx.fail("{s} creating lazy symbol", .{@errorName(err)});
...@@ -10955,12 +10949,10 @@ fn genCall(self: *Self, info: union(enum) {...@@ -10955,12 +10949,10 @@ fn genCall(self: *Self, info: union(enum) {
10955 try self.genSetReg(.rax, Type.usize, .{ .lea_got = sym_index });10949 try self.genSetReg(.rax, Type.usize, .{ .lea_got = sym_index });
10956 try self.asmRegister(.{ ._, .call }, .rax);10950 try self.asmRegister(.{ ._, .call }, .rax);
10957 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {10951 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
10958 _ = macho_file;10952 const sym_index = try macho_file.getZigObject().?.getOrCreateMetadataForDecl(macho_file, func.owner_decl);
10959 @panic("TODO genCall");10953 const sym = macho_file.getSymbol(sym_index);
10960 // const atom = try macho_file.getOrCreateAtomForDecl(func.owner_decl);10954 try self.genSetReg(.rax, Type.usize, .{ .load_symbol = .{ .sym = sym.nlist_idx } });
10961 // const sym_index = macho_file.getAtom(atom).getSymbolIndex().?;10955 try self.asmRegister(.{ ._, .call }, .rax);
10962 // try self.genSetReg(.rax, Type.usize, .{ .lea_got = sym_index });
10963 // try self.asmRegister(.{ ._, .call }, .rax);
10964 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {10956 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
10965 const atom_index = try p9.seeDecl(func.owner_decl);10957 const atom_index = try p9.seeDecl(func.owner_decl);
10966 const atom = p9.getAtom(atom_index);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,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| {13551 .lea_tlv => unreachable, // TODO: remove this
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 },
13583 .air_ref => |src_ref| try self.genSetReg(dst_reg, ty, try self.resolveInst(src_ref)),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,19 +13785,14 @@ fn genExternSymbolRef(
13816 else => unreachable,13785 else => unreachable,
13817 }13786 }
13818 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {13787 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
13819 const global_index = try macho_file.getGlobalSymbol(callee, lib);
13820 _ = try self.addInst(.{13788 _ = try self.addInst(.{
13821 .tag = .call,13789 .tag = .call,
13822 .ops = .extern_fn_reloc,13790 .ops = .extern_fn_reloc,
13823 .data = .{13791 .data = .{ .reloc = .{
13824 .reloc = .{13792 .atom_index = atom_index,
13825 .atom_index = atom_index,13793 .sym_index = try macho_file.getGlobalSymbol(callee, lib),
13826 // .sym_index = link.File.MachO.global_symbol_bit | global_index,13794 } },
13827 .sym_index = global_index,
13828 },
13829 },
13830 });13795 });
13831 @panic("TODO genExternSymbolRef");
13832 } else return self.fail("TODO implement calling extern functions", .{});13796 } else return self.fail("TODO implement calling extern functions", .{});
13833}13797}
1383413798
...@@ -13916,21 +13880,19 @@ fn genLazySymbolRef(...@@ -13916,21 +13880,19 @@ fn genLazySymbolRef(
13916 else => unreachable,13880 else => unreachable,
13917 }13881 }
13918 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {13882 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
13919 _ = macho_file;13883 const sym_index = macho_file.getZigObject().?.getOrCreateMetadataForLazySymbol(macho_file, lazy_sym) catch |err|
13920 @panic("TODO genLazySymbolRef");13884 return self.fail("{s} creating lazy symbol", .{@errorName(err)});
13921 // const atom_index = macho_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err|13885 const sym = macho_file.getSymbol(sym_index);
13922 // return self.fail("{s} creating lazy symbol", .{@errorName(err)});13886 switch (tag) {
13923 // const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;13887 .lea, .call => try self.genSetReg(reg, Type.usize, .{ .load_symbol = .{ .sym = sym.nlist_idx } }),
13924 // switch (tag) {13888 .mov => try self.genSetReg(reg, Type.usize, .{ .load_symbol = .{ .sym = sym.nlist_idx } }),
13925 // .lea, .call => try self.genSetReg(reg, Type.usize, .{ .lea_got = sym_index }),13889 else => unreachable,
13926 // .mov => try self.genSetReg(reg, Type.usize, .{ .load_got = sym_index }),13890 }
13927 // else => unreachable,13891 switch (tag) {
13928 // }13892 .lea, .mov => {},
13929 // switch (tag) {13893 .call => try self.asmRegister(.{ ._, .call }, reg),
13930 // .lea, .mov => {},13894 else => unreachable,
13931 // .call => try self.asmRegister(.{ ._, .call }, reg),13895 }
13932 // else => unreachable,
13933 // }
13934 } else {13896 } else {
13935 return self.fail("TODO implement genLazySymbol for x86_64 {s}", .{@tagName(self.bin_file.tag)});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,6 +16065,8 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue {
16103 .{ .lea_symbol = .{ .sym = tlv_sym } },16065 .{ .lea_symbol = .{ .sym = tlv_sym } },
16104 );16066 );
16105 break :init .{ .load_frame = .{ .index = frame_index } };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 } else break :init const_mcv,16070 } else break :init const_mcv,
16107 else => break :init const_mcv,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,23 +49,21 @@ pub fn emitMir(emit: *Emit) Error!void {
49 .r_addend = -4,49 .r_addend = -4,
50 });50 });
51 } else if (emit.lower.bin_file.cast(link.File.MachO)) |macho_file| {51 } else if (emit.lower.bin_file.cast(link.File.MachO)) |macho_file| {
52 _ = macho_file;52 // Add relocation to the decl.
53 @panic("TODO emitMir");53 const atom = macho_file.getSymbol(symbol.atom_index).getAtom(macho_file).?;
54 // // Add relocation to the decl.54 try atom.addReloc(macho_file, .{
55 // const atom_index =55 .tag = .@"extern",
56 // macho_file.getAtomIndexForSymbol(.{ .sym_index = symbol.atom_index }).?;56 .offset = end_offset - 4,
57 // const target = if (link.File.MachO.global_symbol_bit & symbol.sym_index != 0)57 .target = symbol.sym_index,
58 // macho_file.getGlobalByIndex(link.File.MachO.global_symbol_mask & symbol.sym_index)58 .addend = 0,
59 // else59 .type = .branch,
60 // link.File.MachO.SymbolWithLoc{ .sym_index = symbol.sym_index };60 .meta = .{
61 // try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{61 .pcrel = true,
62 // .type = .branch,62 .has_subtractor = false,
63 // .target = target,63 .length = 2,
64 // .offset = end_offset - 4,64 .symbolnum = 0,
65 // .addend = 0,65 },
66 // .pcrel = true,66 });
67 // .length = 2,
68 // });
69 } else if (emit.lower.bin_file.cast(link.File.Coff)) |coff_file| {67 } else if (emit.lower.bin_file.cast(link.File.Coff)) |coff_file| {
70 // Add relocation to the decl.68 // Add relocation to the decl.
71 const atom_index = coff_file.getAtomIndexForSymbol(69 const atom_index = coff_file.getAtomIndexForSymbol(
...@@ -151,6 +149,36 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -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 } else unreachable,182 } else unreachable,
155 .linker_got,183 .linker_got,
156 .linker_direct,184 .linker_direct,
...@@ -158,28 +186,8 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -158,28 +186,8 @@ pub fn emitMir(emit: *Emit) Error!void {
158 .linker_tlv,186 .linker_tlv,
159 => |symbol| if (emit.lower.bin_file.cast(link.File.Elf)) |_| {187 => |symbol| if (emit.lower.bin_file.cast(link.File.Elf)) |_| {
160 unreachable;188 unreachable;
161 } else if (emit.lower.bin_file.cast(link.File.MachO)) |macho_file| {189 } else if (emit.lower.bin_file.cast(link.File.MachO)) |_| {
162 _ = macho_file;190 unreachable;
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 // });
183 } else if (emit.lower.bin_file.cast(link.File.Coff)) |coff_file| {191 } else if (emit.lower.bin_file.cast(link.File.Coff)) |coff_file| {
184 const atom_index = coff_file.getAtomIndexForSymbol(.{192 const atom_index = coff_file.getAtomIndexForSymbol(.{
185 .sym_index = symbol.atom_index,193 .sym_index = symbol.atom_index,
src/arch/x86_64/Lower.zig+89-80
...@@ -14,7 +14,7 @@ result_relocs_len: u8 = undefined,...@@ -14,7 +14,7 @@ result_relocs_len: u8 = undefined,
14result_insts: [14result_insts: [
15 std.mem.max(usize, &.{15 std.mem.max(usize, &.{
16 1, // non-pseudo instructions16 1, // non-pseudo instructions
17 3, // TLS local dynamic (LD) sequence in PIC mode17 3, // (ELF only) TLS local dynamic (LD) sequence in PIC mode
18 2, // cmovcc: cmovcc \ cmovcc18 2, // cmovcc: cmovcc \ cmovcc
19 3, // setcc: setcc \ setcc \ logicop19 3, // setcc: setcc \ setcc \ logicop
20 2, // jcc: jcc \ jcc20 2, // jcc: jcc \ jcc
...@@ -32,7 +32,7 @@ result_relocs: [...@@ -32,7 +32,7 @@ result_relocs: [
32 2, // jcc: jcc \ jcc32 2, // jcc: jcc \ jcc
33 2, // test \ jcc \ probe \ sub \ jmp33 2, // test \ jcc \ probe \ sub \ jmp
34 1, // probe \ sub \ jcc34 1, // probe \ sub \ jcc
35 3, // TLS local dynamic (LD) sequence in PIC mode35 3, // (ELF only) TLS local dynamic (LD) sequence in PIC mode
36 })36 })
37]Reloc = undefined,37]Reloc = undefined,
3838
...@@ -326,18 +326,6 @@ fn reloc(lower: *Lower, target: Reloc.Target) Immediate {...@@ -326,18 +326,6 @@ fn reloc(lower: *Lower, target: Reloc.Target) Immediate {
326 return Immediate.s(0);326 return Immediate.s(0);
327}327}
328328
329fn 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
335fn 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
341fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) Error!void {329fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) Error!void {
342 const is_obj_or_static_lib = switch (lower.output_mode) {330 const is_obj_or_static_lib = switch (lower.output_mode) {
343 .Exe => false,331 .Exe => false,
...@@ -359,80 +347,101 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)...@@ -359,80 +347,101 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
359 assert(mem_op.sib.disp == 0);347 assert(mem_op.sib.disp == 0);
360 assert(mem_op.sib.scale_index.scale == 0);348 assert(mem_op.sib.scale_index.scale == 0);
361349
362 if (isTls(sym, lower.bin_file)) {350 if (lower.bin_file.cast(link.File.Elf)) |elf_file| {
363 // TODO handle extern TLS vars, i.e., emit GD model351 const sym_index = elf_file.zigObjectPtr().?.symbol(sym.sym_index);
364 if (lower.pic) {352 const elf_sym = elf_file.symbol(sym_index);
365 // Here, we currently assume local dynamic TLS vars, and so353
366 // we emit LD model.354 if (elf_sym.flags.is_tls) {
367 _ = lower.reloc(.{ .linker_tlsld = sym });355 // TODO handle extern TLS vars, i.e., emit GD model
368 lower.result_insts[lower.result_insts_len] =356 if (lower.pic) {
369 try Instruction.new(.none, .lea, &[_]Operand{357 // Here, we currently assume local dynamic TLS vars, and so
370 .{ .reg = .rdi },358 // we emit LD model.
371 .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) },359 _ = lower.reloc(.{ .linker_tlsld = sym });
372 });360 lower.result_insts[lower.result_insts_len] =
373 lower.result_insts_len += 1;361 try Instruction.new(.none, .lea, &[_]Operand{
374 if (lower.bin_file.cast(link.File.Elf)) |elf_file| {362 .{ .reg = .rdi },
363 .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) },
364 });
365 lower.result_insts_len += 1;
375 _ = lower.reloc(.{ .linker_extern_fn = .{366 _ = lower.reloc(.{ .linker_extern_fn = .{
376 .atom_index = sym.atom_index,367 .atom_index = sym.atom_index,
377 .sym_index = try elf_file.getGlobalSymbol("__tls_get_addr", null),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 }
407397
408 _ = lower.reloc(.{ .linker_reloc = sym });398 _ = lower.reloc(.{ .linker_reloc = sym });
409 break :op if (lower.pic) switch (mnemonic) {399 break :op if (lower.pic) switch (mnemonic) {
410 .lea => {400 .lea => {
411 break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) };401 break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) };
412 },402 },
413 .mov => {403 .mov => {
414 if (is_obj_or_static_lib and needsZigGot(sym, lower.bin_file)) emit_mnemonic = .lea;404 if (is_obj_or_static_lib and elf_sym.flags.needs_zig_got) emit_mnemonic = .lea;
415 break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) };405 break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) };
416 },406 },
417 else => unreachable,407 else => unreachable,
418 } else switch (mnemonic) {408 } else switch (mnemonic) {
419 .call => break :op if (is_obj_or_static_lib and needsZigGot(sym, lower.bin_file)) .{409 .call => break :op if (is_obj_or_static_lib and elf_sym.flags.needs_zig_got) .{
420 .imm = Immediate.s(0),410 .imm = Immediate.s(0),
421 } else .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{411 } 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, .{
431 .base = .{ .reg = .ds },412 .base = .{ .reg = .ds },
432 }) };413 }) },
433 },414 .lea => {
434 else => unreachable,415 emit_mnemonic = .mov;
435 };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,7 +1045,12 @@ fn genUnnamedConst(
1045 const local = elf_file.symbol(local_sym_index);1045 const local = elf_file.symbol(local_sym_index);
1046 return GenResult.mcv(.{ .load_symbol = local.esym_index });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 return GenResult.mcv(.{ .load_direct = local_sym_index });1054 return GenResult.mcv(.{ .load_direct = local_sym_index });
1050 },1055 },
1051 .plan9 => {1056 .plan9 => {
src/link/MachO.zig+1-1
...@@ -4280,7 +4280,7 @@ const Md5 = std.crypto.hash.Md5;...@@ -4280,7 +4280,7 @@ const Md5 = std.crypto.hash.Md5;
4280const Module = @import("../Module.zig");4280const Module = @import("../Module.zig");
4281const InternPool = @import("../InternPool.zig");4281const InternPool = @import("../InternPool.zig");
4282const RebaseSection = synthetic.RebaseSection;4282const RebaseSection = synthetic.RebaseSection;
4283const Relocation = @import("MachO/Relocation.zig");4283pub const Relocation = @import("MachO/Relocation.zig");
4284const StringTable = @import("StringTable.zig");4284const StringTable = @import("StringTable.zig");
4285const StubsSection = synthetic.StubsSection;4285const StubsSection = synthetic.StubsSection;
4286const StubsHelperSection = synthetic.StubsHelperSection;4286const StubsHelperSection = synthetic.StubsHelperSection;
src/link/MachO/Atom.zig+6
...@@ -686,6 +686,10 @@ fn resolveRelocInner(...@@ -686,6 +686,10 @@ fn resolveRelocInner(
686 }686 }
687 },687 },
688688
689 .zig_got_load => {
690 @panic("TODO resolve __got_zig indirection reloc");
691 },
692
689 .tlv => {693 .tlv => {
690 assert(rel.tag == .@"extern");694 assert(rel.tag == .@"extern");
691 assert(rel.meta.length == 2);695 assert(rel.meta.length == 2);
...@@ -987,6 +991,7 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: *std.Arra...@@ -987,6 +991,7 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: *std.Arra
987 .subtractor => .ARM64_RELOC_SUBTRACTOR,991 .subtractor => .ARM64_RELOC_SUBTRACTOR,
988 .unsigned => .ARM64_RELOC_UNSIGNED,992 .unsigned => .ARM64_RELOC_UNSIGNED,
989993
994 .zig_got_load,
990 .signed,995 .signed,
991 .signed1,996 .signed1,
992 .signed2,997 .signed2,
...@@ -1030,6 +1035,7 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: *std.Arra...@@ -1030,6 +1035,7 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: *std.Arra
1030 .subtractor => .X86_64_RELOC_SUBTRACTOR,1035 .subtractor => .X86_64_RELOC_SUBTRACTOR,
1031 .unsigned => .X86_64_RELOC_UNSIGNED,1036 .unsigned => .X86_64_RELOC_UNSIGNED,
10321037
1038 .zig_got_load,
1033 .page,1039 .page,
1034 .pageoff,1040 .pageoff,
1035 .got_load_page,1041 .got_load_page,
src/link/MachO/Relocation.zig+2
...@@ -99,6 +99,8 @@ pub const Type = enum {...@@ -99,6 +99,8 @@ pub const Type = enum {
99 got_load,99 got_load,
100 /// RIP-relative TLV load (X86_64_RELOC_TLV)100 /// RIP-relative TLV load (X86_64_RELOC_TLV)
101 tlv,101 tlv,
102 /// Zig-specific __got_zig indirection
103 zig_got_load,
102104
103 // arm64105 // arm64
104 /// PC-relative load (distance to page, ARM64_RELOC_PAGE21)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,7 +248,7 @@ pub fn getDeclVAddr(
248 .pcrel = false,248 .pcrel = false,
249 .has_subtractor = false,249 .has_subtractor = false,
250 .length = 3,250 .length = 3,
251 .symbolnum = @intCast(sym.nlist_idx),251 .symbolnum = 0,
252 },252 },
253 });253 });
254 return vaddr;254 return vaddr;
...@@ -274,7 +274,7 @@ pub fn getAnonDeclVAddr(...@@ -274,7 +274,7 @@ pub fn getAnonDeclVAddr(
274 .pcrel = false,274 .pcrel = false,
275 .has_subtractor = false,275 .has_subtractor = false,
276 .length = 3,276 .length = 3,
277 .symbolnum = @intCast(sym.nlist_idx),277 .symbolnum = 0,
278 },278 },
279 });279 });
280 return vaddr;280 return vaddr;
...@@ -604,25 +604,26 @@ fn getDeclOutputSection(...@@ -604,25 +604,26 @@ fn getDeclOutputSection(
604 _ = self;604 _ = self;
605 const mod = macho_file.base.comp.module.?;605 const mod = macho_file.base.comp.module.?;
606 const any_non_single_threaded = macho_file.base.comp.config.any_non_single_threaded;606 const any_non_single_threaded = macho_file.base.comp.config.any_non_single_threaded;
607 _ = any_non_single_threaded;
607 const sect_id: u8 = switch (decl.ty.zigTypeTag(mod)) {608 const sect_id: u8 = switch (decl.ty.zigTypeTag(mod)) {
608 .Fn => macho_file.zig_text_section_index.?,609 .Fn => macho_file.zig_text_section_index.?,
609 else => blk: {610 else => blk: {
610 if (decl.getOwnedVariable(mod)) |variable| {611 if (decl.getOwnedVariable(mod)) |variable| {
611 if (variable.is_threadlocal and any_non_single_threaded) {612 // if (variable.is_threadlocal and any_non_single_threaded) {
612 const is_all_zeroes = for (code) |byte| {613 // const is_all_zeroes = for (code) |byte| {
613 if (byte != 0) break false;614 // if (byte != 0) break false;
614 } else true;615 // } else true;
615 if (is_all_zeroes) break :blk macho_file.getSectionByName("__DATA", "__thread_bss") orelse try macho_file.addSection(616 // if (is_all_zeroes) break :blk macho_file.getSectionByName("__DATA", "__thread_bss") orelse try macho_file.addSection(
616 "__DATA",617 // "__DATA",
617 "__thread_bss",618 // "__thread_bss",
618 .{ .flags = macho.S_THREAD_LOCAL_ZEROFILL },619 // .{ .flags = macho.S_THREAD_LOCAL_ZEROFILL },
619 );620 // );
620 break :blk macho_file.getSectionByName("__DATA", "__thread_data") orelse try macho_file.addSection(621 // break :blk macho_file.getSectionByName("__DATA", "__thread_data") orelse try macho_file.addSection(
621 "__DATA",622 // "__DATA",
622 "__thread_data",623 // "__thread_data",
623 .{ .flags = macho.S_THREAD_LOCAL_REGULAR },624 // .{ .flags = macho.S_THREAD_LOCAL_REGULAR },
624 );625 // );
625 }626 // }
626627
627 if (variable.is_const) break :blk macho_file.zig_const_section_index.?;628 if (variable.is_const) break :blk macho_file.zig_const_section_index.?;
628 if (Value.fromInterned(variable.init).isUndefDeep(mod)) {629 if (Value.fromInterned(variable.init).isUndefDeep(mod)) {
...@@ -917,7 +918,7 @@ fn updateLazySymbol(...@@ -917,7 +918,7 @@ fn updateLazySymbol(
917918
918 sym.value = 0;919 sym.value = 0;
919 sym.flags.needs_zig_got = true;920 sym.flags.needs_zig_got = true;
920 nlist.st_value = 0;921 nlist.n_value = 0;
921922
922 if (!macho_file.base.isRelocatable()) {923 if (!macho_file.base.isRelocatable()) {
923 const gop = try sym.getOrCreateZigGotEntry(symbol_index, macho_file);924 const gop = try sym.getOrCreateZigGotEntry(symbol_index, macho_file);