| author | |
| committer | |
| log | d312dfc1f21a9194dd06c1d45f653bdaf823d2f6 |
| tree | 8fb63f9b4c650c44ad3dadf41139cb585995c3c5 |
| parent | 56119699bf5fbb44d844d4ad181d51629f754be8 |
| signature |
5 files changed, 23 insertions(+), 66 deletions(-)
src/arch/x86_64/CodeGen.zig+2-1| ... | ... | @@ -163354,7 +163354,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 163354 | 163354 | }, |
| 163355 | 163355 | .runtime_nav_ptr => { |
| 163356 | 163356 | const ty_nav = air_datas[@intFromEnum(inst)].ty_nav; |
| 163357 | const is_threadlocal = ip.getNav(ty_nav.nav).isThreadlocal(ip); | |
| 163357 | const nav = ip.getNav(ty_nav.nav); | |
| 163358 | const is_threadlocal = zcu.comp.config.any_non_single_threaded and nav.isThreadlocal(ip); | |
| 163358 | 163359 | if (is_threadlocal) if (cg.mod.pic) { |
| 163359 | 163360 | try cg.spillRegisters(&.{ .rdi, .rax }); |
| 163360 | 163361 | } else { |
src/arch/x86_64/Emit.zig+8-20| ... | ... | @@ -21,7 +21,8 @@ pub const Error = Lower.Error || error{ |
| 21 | 21 | } || link.File.UpdateDebugInfoError; |
| 22 | 22 | |
| 23 | 23 | pub fn emitMir(emit: *Emit) Error!void { |
| 24 | const gpa = emit.bin_file.comp.gpa; | |
| 24 | const comp = emit.bin_file.comp; | |
| 25 | const gpa = comp.gpa; | |
| 25 | 26 | try emit.code_offset_mapping.resize(gpa, emit.lower.mir.instructions.len); |
| 26 | 27 | emit.relocs.clearRetainingCapacity(); |
| 27 | 28 | emit.table_relocs.clearRetainingCapacity(); |
| ... | ... | @@ -99,12 +100,10 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 99 | 100 | .inst => |inst| .{ .index = inst, .is_extern = false, .type = .inst }, |
| 100 | 101 | .table => .{ .index = undefined, .is_extern = false, .type = .table }, |
| 101 | 102 | .nav => |nav| { |
| 102 | const ip = &emit.pt.zcu.intern_pool; | |
| 103 | 103 | const sym_index = switch (try codegen.genNavRef( |
| 104 | 104 | emit.bin_file, |
| 105 | 105 | emit.pt, |
| 106 | 106 | emit.lower.src_loc, |
| 107 | .fromInterned(ip.getNav(nav).typeOf(ip)), | |
| 108 | 107 | nav, |
| 109 | 108 | emit.lower.target.*, |
| 110 | 109 | )) { |
| ... | ... | @@ -118,12 +117,13 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 118 | 117 | return error.EmitFail; |
| 119 | 118 | }, |
| 120 | 119 | }; |
| 120 | const ip = &emit.pt.zcu.intern_pool; | |
| 121 | 121 | break :target switch (ip.getNav(nav).status) { |
| 122 | 122 | .unresolved => unreachable, |
| 123 | 123 | .type_resolved => |type_resolved| .{ |
| 124 | 124 | .index = sym_index, |
| 125 | 125 | .is_extern = false, |
| 126 | .type = if (type_resolved.is_threadlocal) .tlv else .symbol, | |
| 126 | .type = if (type_resolved.is_threadlocal and comp.config.any_non_single_threaded) .tlv else .symbol, | |
| 127 | 127 | }, |
| 128 | 128 | .fully_resolved => |fully_resolved| switch (ip.indexToKey(fully_resolved.val)) { |
| 129 | 129 | .@"extern" => |@"extern"| .{ |
| ... | ... | @@ -132,7 +132,7 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 132 | 132 | .default => true, |
| 133 | 133 | .hidden, .protected => false, |
| 134 | 134 | }, |
| 135 | .type = if (@"extern".is_threadlocal) .tlv else .symbol, | |
| 135 | .type = if (@"extern".is_threadlocal and comp.config.any_non_single_threaded) .tlv else .symbol, | |
| 136 | 136 | .force_pcrel_direct = switch (@"extern".relocation) { |
| 137 | 137 | .any => false, |
| 138 | 138 | .pcrel => true, |
| ... | ... | @@ -141,7 +141,7 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 141 | 141 | .variable => |variable| .{ |
| 142 | 142 | .index = sym_index, |
| 143 | 143 | .is_extern = false, |
| 144 | .type = if (variable.is_threadlocal) .tlv else .symbol, | |
| 144 | .type = if (variable.is_threadlocal and comp.config.any_non_single_threaded) .tlv else .symbol, | |
| 145 | 145 | }, |
| 146 | 146 | else => .{ .index = sym_index, .is_extern = false, .type = .symbol }, |
| 147 | 147 | }, |
| ... | ... | @@ -292,12 +292,8 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 292 | 292 | .branch, .tls => unreachable, |
| 293 | 293 | .tlv => { |
| 294 | 294 | if (emit.bin_file.cast(.elf)) |elf_file| { |
| 295 | if (reloc.target.is_extern) { | |
| 296 | // TODO handle extern TLS vars, i.e., emit GD model | |
| 297 | return emit.fail("TODO implement extern {s} reloc for {s}", .{ | |
| 298 | @tagName(reloc.target.type), @tagName(emit.bin_file.tag), | |
| 299 | }); | |
| 300 | } else if (emit.pic) switch (lowered_inst.encoding.mnemonic) { | |
| 295 | // TODO handle extern TLS vars, i.e., emit GD model | |
| 296 | if (emit.pic) switch (lowered_inst.encoding.mnemonic) { | |
| 301 | 297 | .lea, .mov => { |
| 302 | 298 | // Here, we currently assume local dynamic TLS vars, and so |
| 303 | 299 | // we emit LD model. |
| ... | ... | @@ -507,7 +503,6 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 507 | 503 | } }; |
| 508 | 504 | }, |
| 509 | 505 | .pseudo_dbg_arg_m, .pseudo_dbg_var_m => { |
| 510 | const ip = &emit.pt.zcu.intern_pool; | |
| 511 | 506 | const mem = emit.lower.mir.resolveMemoryExtra(mir_inst.data.x.payload).decode(); |
| 512 | 507 | break :loc .{ .plus = .{ |
| 513 | 508 | base: { |
| ... | ... | @@ -519,7 +514,6 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 519 | 514 | emit.bin_file, |
| 520 | 515 | emit.pt, |
| 521 | 516 | emit.lower.src_loc, |
| 522 | .fromInterned(ip.getNav(nav).typeOf(ip)), | |
| 523 | 517 | nav, |
| 524 | 518 | emit.lower.target.*, |
| 525 | 519 | ) catch |err| switch (err) { |
| ... | ... | @@ -803,9 +797,6 @@ fn encodeInst(emit: *Emit, lowered_inst: Instruction, reloc_info: []const RelocI |
| 803 | 797 | @tagName(reloc.target.type), @tagName(emit.bin_file.tag), |
| 804 | 798 | }), |
| 805 | 799 | .tls => if (emit.bin_file.cast(.elf)) |elf_file| { |
| 806 | if (reloc.target.is_extern) return emit.fail("TODO implement extern {s} reloc for {s}", .{ | |
| 807 | @tagName(reloc.target.type), @tagName(emit.bin_file.tag), | |
| 808 | }); | |
| 809 | 800 | const zo = elf_file.zigObjectPtr().?; |
| 810 | 801 | const atom = zo.symbol(emit.atom_index).atom(elf_file).?; |
| 811 | 802 | const r_type: std.elf.R_X86_64 = if (emit.pic) .TLSLD else unreachable; |
| ... | ... | @@ -818,9 +809,6 @@ fn encodeInst(emit: *Emit, lowered_inst: Instruction, reloc_info: []const RelocI |
| 818 | 809 | @tagName(reloc.target.type), @tagName(emit.bin_file.tag), |
| 819 | 810 | }), |
| 820 | 811 | .tlv => if (emit.bin_file.cast(.elf)) |elf_file| { |
| 821 | if (reloc.target.is_extern) return emit.fail("TODO implement extern {s} reloc for {s}", .{ | |
| 822 | @tagName(reloc.target.type), @tagName(emit.bin_file.tag), | |
| 823 | }); | |
| 824 | 812 | const zo = elf_file.zigObjectPtr().?; |
| 825 | 813 | const atom = zo.symbol(emit.atom_index).atom(elf_file).?; |
| 826 | 814 | const r_type: std.elf.R_X86_64 = if (emit.pic) .DTPOFF32 else .TPOFF32; |
src/codegen.zig+9-39| ... | ... | @@ -955,47 +955,18 @@ pub fn genNavRef( |
| 955 | 955 | lf: *link.File, |
| 956 | 956 | pt: Zcu.PerThread, |
| 957 | 957 | src_loc: Zcu.LazySrcLoc, |
| 958 | ty: Type, | |
| 959 | 958 | nav_index: InternPool.Nav.Index, |
| 960 | 959 | target: std.Target, |
| 961 | 960 | ) CodeGenError!GenResult { |
| 962 | 961 | const zcu = pt.zcu; |
| 963 | 962 | const ip = &zcu.intern_pool; |
| 964 | log.debug("genNavRef: ty = {}", .{ty.fmt(pt)}); | |
| 965 | ||
| 966 | if (!ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) { | |
| 967 | const imm: u64 = switch (@divExact(target.ptrBitWidth(), 8)) { | |
| 968 | 1 => 0xaa, | |
| 969 | 2 => 0xaaaa, | |
| 970 | 4 => 0xaaaaaaaa, | |
| 971 | 8 => 0xaaaaaaaaaaaaaaaa, | |
| 972 | else => unreachable, | |
| 973 | }; | |
| 974 | return .{ .mcv = .{ .immediate = imm } }; | |
| 975 | } | |
| 976 | ||
| 977 | const comp = lf.comp; | |
| 978 | const gpa = comp.gpa; | |
| 979 | ||
| 980 | // TODO this feels clunky. Perhaps we should check for it in `genTypedValue`? | |
| 981 | if (ty.castPtrToFn(zcu)) |fn_ty| { | |
| 982 | if (zcu.typeToFunc(fn_ty).?.is_generic) { | |
| 983 | return .{ .mcv = .{ .immediate = fn_ty.abiAlignment(zcu).toByteUnits().? } }; | |
| 984 | } | |
| 985 | } else if (ty.zigTypeTag(zcu) == .pointer) { | |
| 986 | const elem_ty = ty.elemType2(zcu); | |
| 987 | if (!elem_ty.hasRuntimeBits(zcu)) { | |
| 988 | return .{ .mcv = .{ .immediate = elem_ty.abiAlignment(zcu).toByteUnits().? } }; | |
| 989 | } | |
| 990 | } | |
| 991 | ||
| 992 | 963 | const nav = ip.getNav(nav_index); |
| 964 | log.debug("genNavRef({})", .{nav.fqn.fmt(ip)}); | |
| 965 | ||
| 993 | 966 | const lib_name, const linkage, const is_threadlocal = if (nav.getExtern(ip)) |e| |
| 994 | .{ e.lib_name, e.linkage, e.is_threadlocal and !zcu.navFileScope(nav_index).mod.?.single_threaded } | |
| 967 | .{ e.lib_name, e.linkage, e.is_threadlocal and zcu.comp.config.any_non_single_threaded } | |
| 995 | 968 | else |
| 996 | 969 | .{ .none, .internal, false }; |
| 997 | ||
| 998 | const name = nav.name; | |
| 999 | 970 | if (lf.cast(.elf)) |elf_file| { |
| 1000 | 971 | const zo = elf_file.zigObjectPtr().?; |
| 1001 | 972 | switch (linkage) { |
| ... | ... | @@ -1005,7 +976,7 @@ pub fn genNavRef( |
| 1005 | 976 | return .{ .mcv = .{ .lea_symbol = sym_index } }; |
| 1006 | 977 | }, |
| 1007 | 978 | .strong, .weak => { |
| 1008 | const sym_index = try elf_file.getGlobalSymbol(name.toSlice(ip), lib_name.toSlice(ip)); | |
| 979 | const sym_index = try elf_file.getGlobalSymbol(nav.name.toSlice(ip), lib_name.toSlice(ip)); | |
| 1009 | 980 | switch (linkage) { |
| 1010 | 981 | .internal => unreachable, |
| 1011 | 982 | .strong => {}, |
| ... | ... | @@ -1026,7 +997,7 @@ pub fn genNavRef( |
| 1026 | 997 | return .{ .mcv = .{ .lea_symbol = sym_index } }; |
| 1027 | 998 | }, |
| 1028 | 999 | .strong, .weak => { |
| 1029 | const sym_index = try macho_file.getGlobalSymbol(name.toSlice(ip), lib_name.toSlice(ip)); | |
| 1000 | const sym_index = try macho_file.getGlobalSymbol(nav.name.toSlice(ip), lib_name.toSlice(ip)); | |
| 1030 | 1001 | switch (linkage) { |
| 1031 | 1002 | .internal => unreachable, |
| 1032 | 1003 | .strong => {}, |
| ... | ... | @@ -1047,8 +1018,8 @@ pub fn genNavRef( |
| 1047 | 1018 | return .{ .mcv = .{ .load_got = sym_index } }; |
| 1048 | 1019 | }, |
| 1049 | 1020 | .strong, .weak => { |
| 1050 | const global_index = try coff_file.getGlobalSymbol(name.toSlice(ip), lib_name.toSlice(ip)); | |
| 1051 | try coff_file.need_got_table.put(gpa, global_index, {}); // needs GOT | |
| 1021 | const global_index = try coff_file.getGlobalSymbol(nav.name.toSlice(ip), lib_name.toSlice(ip)); | |
| 1022 | try coff_file.need_got_table.put(zcu.gpa, global_index, {}); // needs GOT | |
| 1052 | 1023 | return .{ .mcv = .{ .load_got = link.File.Coff.global_symbol_bit | global_index } }; |
| 1053 | 1024 | }, |
| 1054 | 1025 | .link_once => unreachable, |
| ... | ... | @@ -1058,7 +1029,7 @@ pub fn genNavRef( |
| 1058 | 1029 | const atom = p9.getAtom(atom_index); |
| 1059 | 1030 | return .{ .mcv = .{ .memory = atom.getOffsetTableAddress(p9) } }; |
| 1060 | 1031 | } else { |
| 1061 | const msg = try ErrorMsg.create(gpa, src_loc, "TODO genNavRef for target {}", .{target}); | |
| 1032 | const msg = try ErrorMsg.create(zcu.gpa, src_loc, "TODO genNavRef for target {}", .{target}); | |
| 1062 | 1033 | return .{ .fail = msg }; |
| 1063 | 1034 | } |
| 1064 | 1035 | } |
| ... | ... | @@ -1071,12 +1042,11 @@ pub fn genTypedValue( |
| 1071 | 1042 | val: Value, |
| 1072 | 1043 | target: std.Target, |
| 1073 | 1044 | ) CodeGenError!GenResult { |
| 1074 | const ip = &pt.zcu.intern_pool; | |
| 1075 | 1045 | return switch (try lowerValue(pt, val, &target)) { |
| 1076 | 1046 | .none => .{ .mcv = .none }, |
| 1077 | 1047 | .undef => .{ .mcv = .undef }, |
| 1078 | 1048 | .immediate => |imm| .{ .mcv = .{ .immediate = imm } }, |
| 1079 | .lea_nav => |nav| genNavRef(lf, pt, src_loc, .fromInterned(ip.getNav(nav).typeOf(ip)), nav, target), | |
| 1049 | .lea_nav => |nav| genNavRef(lf, pt, src_loc, nav, target), | |
| 1080 | 1050 | .lea_uav => |uav| switch (try lf.lowerUav( |
| 1081 | 1051 | pt, |
| 1082 | 1052 | uav.val, |
src/link/Elf/ZigObject.zig+2-3| ... | ... | @@ -1142,7 +1142,6 @@ fn getNavShdrIndex( |
| 1142 | 1142 | const gpa = elf_file.base.comp.gpa; |
| 1143 | 1143 | const ptr_size = elf_file.ptrWidthBytes(); |
| 1144 | 1144 | const ip = &zcu.intern_pool; |
| 1145 | const any_non_single_threaded = elf_file.base.comp.config.any_non_single_threaded; | |
| 1146 | 1145 | const nav_val = zcu.navValue(nav_index); |
| 1147 | 1146 | if (ip.isFunctionType(nav_val.typeOf(zcu).toIntern())) { |
| 1148 | 1147 | if (self.text_index) |symbol_index| |
| ... | ... | @@ -1162,7 +1161,7 @@ fn getNavShdrIndex( |
| 1162 | 1161 | else => .{ true, false, nav_val.toIntern() }, |
| 1163 | 1162 | }; |
| 1164 | 1163 | const has_relocs = self.symbol(sym_index).atom(elf_file).?.relocs(elf_file).len > 0; |
| 1165 | if (any_non_single_threaded and is_threadlocal) { | |
| 1164 | if (is_threadlocal and elf_file.base.comp.config.any_non_single_threaded) { | |
| 1166 | 1165 | const is_bss = !has_relocs and for (code) |byte| { |
| 1167 | 1166 | if (byte != 0) break false; |
| 1168 | 1167 | } else true; |
| ... | ... | @@ -1542,7 +1541,7 @@ pub fn updateNav( |
| 1542 | 1541 | nav.name.toSlice(ip), |
| 1543 | 1542 | @"extern".lib_name.toSlice(ip), |
| 1544 | 1543 | ); |
| 1545 | if (@"extern".is_threadlocal) self.symbol(sym_index).flags.is_tls = true; | |
| 1544 | if (@"extern".is_threadlocal and elf_file.base.comp.config.any_non_single_threaded) self.symbol(sym_index).flags.is_tls = true; | |
| 1546 | 1545 | if (self.dwarf) |*dwarf| dwarf: { |
| 1547 | 1546 | var debug_wip_nav = try dwarf.initWipNav(pt, nav_index, sym_index) orelse break :dwarf; |
| 1548 | 1547 | defer debug_wip_nav.deinit(); |
src/link/MachO/ZigObject.zig+2-3| ... | ... | @@ -881,7 +881,7 @@ pub fn updateNav( |
| 881 | 881 | const name = @"extern".name.toSlice(ip); |
| 882 | 882 | const lib_name = @"extern".lib_name.toSlice(ip); |
| 883 | 883 | const sym_index = try self.getGlobalSymbol(macho_file, name, lib_name); |
| 884 | if (@"extern".is_threadlocal) self.symbols.items[sym_index].flags.tlv = true; | |
| 884 | if (@"extern".is_threadlocal and macho_file.base.comp.config.any_non_single_threaded) self.symbols.items[sym_index].flags.tlv = true; | |
| 885 | 885 | if (self.dwarf) |*dwarf| dwarf: { |
| 886 | 886 | var debug_wip_nav = try dwarf.initWipNav(pt, nav_index, sym_index) orelse break :dwarf; |
| 887 | 887 | defer debug_wip_nav.deinit(); |
| ... | ... | @@ -1154,7 +1154,6 @@ fn getNavOutputSection( |
| 1154 | 1154 | ) error{OutOfMemory}!u8 { |
| 1155 | 1155 | _ = self; |
| 1156 | 1156 | const ip = &zcu.intern_pool; |
| 1157 | const any_non_single_threaded = macho_file.base.comp.config.any_non_single_threaded; | |
| 1158 | 1157 | const nav_val = zcu.navValue(nav_index); |
| 1159 | 1158 | if (ip.isFunctionType(nav_val.typeOf(zcu).toIntern())) return macho_file.zig_text_sect_index.?; |
| 1160 | 1159 | const is_const, const is_threadlocal, const nav_init = switch (ip.indexToKey(nav_val.toIntern())) { |
| ... | ... | @@ -1162,7 +1161,7 @@ fn getNavOutputSection( |
| 1162 | 1161 | .@"extern" => |@"extern"| .{ @"extern".is_const, @"extern".is_threadlocal, .none }, |
| 1163 | 1162 | else => .{ true, false, nav_val.toIntern() }, |
| 1164 | 1163 | }; |
| 1165 | if (any_non_single_threaded and is_threadlocal) { | |
| 1164 | if (is_threadlocal and macho_file.base.comp.config.any_non_single_threaded) { | |
| 1166 | 1165 | for (code) |byte| { |
| 1167 | 1166 | if (byte != 0) break; |
| 1168 | 1167 | } else return macho_file.getSectionByName("__DATA", "__thread_bss") orelse try macho_file.addSection( |