authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-11-11 17:03:35+01:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-11-12 18:12:41-05:00
log1afc6917f5e6acc7f7f700b54023a82e4ad923a6
tree1f87cb8855dd6a4dfb9aa0f0a8fb037887dfe2a0
parentb48baeeebbec2f5d06f8ffc5305d2994d8389a72

x86_64: get something going for the local exec model


4 files changed, 59 insertions(+), 11 deletions(-)

src/arch/x86_64/Emit.zig+2
...@@ -120,6 +120,8 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -120,6 +120,8 @@ pub fn emitMir(emit: *Emit) Error!void {
120 link.File.Elf.R_X86_64_ZIG_GOT32120 link.File.Elf.R_X86_64_ZIG_GOT32
121 else if (sym.flags.needs_got)121 else if (sym.flags.needs_got)
122 std.elf.R_X86_64_GOT32122 std.elf.R_X86_64_GOT32
123 else if (sym.isTls(elf_file))
124 std.elf.R_X86_64_TPOFF32
123 else125 else
124 std.elf.R_X86_64_32;126 std.elf.R_X86_64_32;
125 try atom.addReloc(elf_file, .{127 try atom.addReloc(elf_file, .{
src/arch/x86_64/Lower.zig+36-8
...@@ -319,20 +319,25 @@ fn reloc(lower: *Lower, target: Reloc.Target) Immediate {...@@ -319,20 +319,25 @@ fn reloc(lower: *Lower, target: Reloc.Target) Immediate {
319 return Immediate.s(0);319 return Immediate.s(0);
320}320}
321321
322fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) Error!void {322fn needsZigGot(sym: bits.Symbol, ctx: *link.File) bool {
323 const needsZigGot = struct {323 const elf_file = ctx.cast(link.File.Elf).?;
324 fn needsZigGot(sym: bits.Symbol, ctx: *link.File) bool {324 const sym_index = elf_file.zigObjectPtr().?.symbol(sym.sym_index);
325 const elf_file = ctx.cast(link.File.Elf).?;325 return elf_file.symbol(sym_index).flags.needs_zig_got;
326 const sym_index = elf_file.zigObjectPtr().?.symbol(sym.sym_index);326}
327 return elf_file.symbol(sym_index).flags.needs_zig_got;327
328 }328fn isTls(sym: bits.Symbol, ctx: *link.File) bool {
329 }.needsZigGot;329 const elf_file = ctx.cast(link.File.Elf).?;
330 const sym_index = elf_file.zigObjectPtr().?.symbol(sym.sym_index);
331 return elf_file.symbol(sym_index).isTls(elf_file);
332}
330333
334fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) Error!void {
331 const is_obj_or_static_lib = switch (lower.bin_file.options.output_mode) {335 const is_obj_or_static_lib = switch (lower.bin_file.options.output_mode) {
332 .Exe => false,336 .Exe => false,
333 .Obj => true,337 .Obj => true,
334 .Lib => lower.bin_file.options.link_mode == .Static,338 .Lib => lower.bin_file.options.link_mode == .Static,
335 };339 };
340
336 var emit_prefix = prefix;341 var emit_prefix = prefix;
337 var emit_mnemonic = mnemonic;342 var emit_mnemonic = mnemonic;
338 var emit_ops_storage: [4]Operand = undefined;343 var emit_ops_storage: [4]Operand = undefined;
...@@ -346,6 +351,29 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)...@@ -346,6 +351,29 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
346 assert(prefix == .none);351 assert(prefix == .none);
347 assert(mem_op.sib.disp == 0);352 assert(mem_op.sib.disp == 0);
348 assert(mem_op.sib.scale_index.scale == 0);353 assert(mem_op.sib.scale_index.scale == 0);
354
355 if (isTls(sym, lower.bin_file)) {
356 lower.result_insts[lower.result_insts_len] =
357 try Instruction.new(.none, .mov, &[_]Operand{
358 .{ .reg = ops[0].reg.to64() },
359 .{ .mem = Memory.sib(.qword, .{ .base = .{ .reg = .fs } }) },
360 });
361 lower.result_insts_len += 1;
362 _ = lower.reloc(.{ .linker_reloc = sym });
363 if (lower.bin_file.cast(link.File.Elf)) |elf_file| {
364 const sym_index = elf_file.zigObjectPtr().?.symbol(sym.sym_index);
365 elf_file.symbol(sym_index).flags.needs_zig_got = false;
366 }
367 emit_mnemonic = .lea;
368 switch (mnemonic) {
369 .lea, .mov => break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{
370 .base = .{ .reg = ops[0].reg.to64() },
371 .disp = undefined,
372 }) },
373 else => unreachable,
374 }
375 }
376
349 _ = lower.reloc(.{ .linker_reloc = sym });377 _ = lower.reloc(.{ .linker_reloc = sym });
350 break :op if (lower.bin_file.options.pic) switch (mnemonic) {378 break :op if (lower.bin_file.options.pic) switch (mnemonic) {
351 .lea => {379 .lea => {
src/link/Elf/Symbol.zig+7
...@@ -51,6 +51,13 @@ pub fn isIFunc(symbol: Symbol, elf_file: *Elf) bool {...@@ -51,6 +51,13 @@ pub fn isIFunc(symbol: Symbol, elf_file: *Elf) bool {
51 return symbol.type(elf_file) == elf.STT_GNU_IFUNC;51 return symbol.type(elf_file) == elf.STT_GNU_IFUNC;
52}52}
5353
54// TODO this check is enough for ZigObject emitted TLS vars but what about those emitted
55// by different backends/compilers?
56pub fn isTls(symbol: Symbol, elf_file: *Elf) bool {
57 if (symbol.file(elf_file) == null) return false;
58 return symbol.type(elf_file) == elf.STT_TLS;
59}
60
54pub fn @"type"(symbol: Symbol, elf_file: *Elf) u4 {61pub fn @"type"(symbol: Symbol, elf_file: *Elf) u4 {
55 const esym = symbol.elfSym(elf_file);62 const esym = symbol.elfSym(elf_file);
56 const file_ptr = symbol.file(elf_file).?;63 const file_ptr = symbol.file(elf_file).?;
src/link/Elf/ZigObject.zig+14-3
...@@ -723,7 +723,18 @@ pub fn getOrCreateMetadataForDecl(...@@ -723,7 +723,18 @@ pub fn getOrCreateMetadataForDecl(
723) !Symbol.Index {723) !Symbol.Index {
724 const gop = try self.decls.getOrPut(elf_file.base.allocator, decl_index);724 const gop = try self.decls.getOrPut(elf_file.base.allocator, decl_index);
725 if (!gop.found_existing) {725 if (!gop.found_existing) {
726 gop.value_ptr.* = .{ .symbol_index = try self.addAtom(elf_file) };726 const symbol_index = try self.addAtom(elf_file);
727 const mod = elf_file.base.options.module.?;
728 const decl = mod.declPtr(decl_index);
729 const single_threaded = elf_file.base.options.single_threaded;
730 if (decl.getOwnedVariable(mod)) |variable| {
731 if (variable.is_threadlocal and !single_threaded) {
732 const sym = elf_file.symbol(symbol_index);
733 self.elfSym(sym.esym_index).st_info = elf.STT_TLS;
734 }
735 }
736
737 gop.value_ptr.* = .{ .symbol_index = symbol_index };
727 }738 }
728 return gop.value_ptr.symbol_index;739 return gop.value_ptr.symbol_index;
729}740}
...@@ -891,7 +902,7 @@ fn updateTlv(...@@ -891,7 +902,7 @@ fn updateTlv(
891 const decl = mod.declPtr(decl_index);902 const decl = mod.declPtr(decl_index);
892 const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));903 const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
893904
894 log.debug("updateTlv {s}{*}", .{ decl_name, decl });905 log.debug("updateTlv {s} ({*})", .{ decl_name, decl });
895906
896 const required_alignment = decl.getAlignment(mod);907 const required_alignment = decl.getAlignment(mod);
897908
...@@ -906,7 +917,7 @@ fn updateTlv(...@@ -906,7 +917,7 @@ fn updateTlv(
906 atom_ptr.flags.alive = true;917 atom_ptr.flags.alive = true;
907 atom_ptr.name_offset = sym.name_offset;918 atom_ptr.name_offset = sym.name_offset;
908 esym.st_name = sym.name_offset;919 esym.st_name = sym.name_offset;
909 esym.st_info |= elf.STT_TLS;920 esym.st_info = elf.STT_TLS;
910 esym.st_size = code.len;921 esym.st_size = code.len;
911922
912 atom_ptr.alignment = required_alignment;923 atom_ptr.alignment = required_alignment;