| ... | ... | @@ -38,6 +38,9 @@ unnamed_consts: UnnamedConstTable = .{}, |
| 38 | 38 | /// Table of tracked AnonDecls. |
| 39 | 39 | anon_decls: AnonDeclTable = .{}, |
| 40 | 40 | |
| 41 | /// TLS variables indexed by Atom.Index. |
| 42 | tls_variables: TlsTable = .{}, |
| 43 | |
| 41 | 44 | /// A table of relocations. |
| 42 | 45 | relocs: RelocationTable = .{}, |
| 43 | 46 | |
| ... | ... | @@ -87,6 +90,11 @@ pub fn deinit(self: *ZigObject, allocator: Allocator) void { |
| 87 | 90 | list.deinit(allocator); |
| 88 | 91 | } |
| 89 | 92 | self.relocs.deinit(allocator); |
| 93 | |
| 94 | for (self.tls_variables.values()) |*tlv| { |
| 95 | tlv.deinit(allocator); |
| 96 | } |
| 97 | self.tls_variables.deinit(allocator); |
| 90 | 98 | } |
| 91 | 99 | |
| 92 | 100 | fn addNlist(self: *ZigObject, allocator: Allocator) !Symbol.Index { |
| ... | ... | @@ -612,8 +620,7 @@ pub fn updateDecl( |
| 612 | 620 | else => false, |
| 613 | 621 | }; |
| 614 | 622 | if (is_threadlocal) { |
| 615 | | // TODO: emit TLV |
| 616 | | @panic("TODO updateDecl for TLS"); |
| 623 | try self.updateTlv(macho_file, decl_index, sym_index, sect_index, code); |
| 617 | 624 | } else { |
| 618 | 625 | try self.updateDeclCode(macho_file, decl_index, sym_index, sect_index, code); |
| 619 | 626 | } |
| ... | ... | @@ -715,6 +722,58 @@ fn updateDeclCode( |
| 715 | 722 | } |
| 716 | 723 | } |
| 717 | 724 | |
| 725 | fn updateTlv( |
| 726 | self: *ZigObject, |
| 727 | macho_file: *MachO, |
| 728 | decl_index: InternPool.DeclIndex, |
| 729 | sym_index: Symbol.Index, |
| 730 | sect_index: u8, |
| 731 | code: []const u8, |
| 732 | ) !void { |
| 733 | const comp = macho_file.base.comp; |
| 734 | const gpa = comp.gpa; |
| 735 | const mod = comp.module.?; |
| 736 | const decl = mod.declPtr(decl_index); |
| 737 | const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod)); |
| 738 | |
| 739 | log.debug("updateTlv {s} ({*})", .{ decl_name, decl }); |
| 740 | |
| 741 | const required_alignment = decl.getAlignment(mod); |
| 742 | |
| 743 | const sym = macho_file.getSymbol(sym_index); |
| 744 | const nlist = &self.symtab.items(.nlist)[sym.nlist_idx]; |
| 745 | const atom = sym.getAtom(macho_file).?; |
| 746 | |
| 747 | sym.out_n_sect = sect_index; |
| 748 | atom.out_n_sect = sect_index; |
| 749 | |
| 750 | sym.name = try macho_file.strings.insert(gpa, decl_name); |
| 751 | atom.flags.alive = true; |
| 752 | atom.name = sym.name; |
| 753 | nlist.n_strx = sym.name; |
| 754 | nlist.n_sect = sect_index + 1; |
| 755 | nlist.n_type = macho.N_EXT; |
| 756 | self.symtab.items(.size)[sym.nlist_idx] = code.len; |
| 757 | |
| 758 | atom.alignment = required_alignment; |
| 759 | atom.size = code.len; |
| 760 | |
| 761 | const slice = macho_file.sections.slice(); |
| 762 | const header = slice.items(.header)[sect_index]; |
| 763 | const atoms = &slice.items(.atoms)[sect_index]; |
| 764 | |
| 765 | const gop = try self.tls_variables.getOrPut(gpa, atom.atom_index); |
| 766 | assert(!gop.found_existing); // TODO incremental updates |
| 767 | gop.value_ptr.* = .{ .symbol_index = sym_index }; |
| 768 | |
| 769 | // We only store the data for the TLV if it's non-zerofill. |
| 770 | if (!header.isZerofill()) { |
| 771 | gop.value_ptr.code = try gpa.dupe(u8, code); |
| 772 | } |
| 773 | |
| 774 | try atoms.append(gpa, atom.atom_index); |
| 775 | } |
| 776 | |
| 718 | 777 | fn getDeclOutputSection( |
| 719 | 778 | self: *ZigObject, |
| 720 | 779 | macho_file: *MachO, |
| ... | ... | @@ -1244,11 +1303,21 @@ const LazySymbolMetadata = struct { |
| 1244 | 1303 | const_state: State = .unused, |
| 1245 | 1304 | }; |
| 1246 | 1305 | |
| 1306 | const TlsVariable = struct { |
| 1307 | symbol_index: Symbol.Index, |
| 1308 | code: []const u8 = &[0]u8{}, |
| 1309 | |
| 1310 | fn deinit(tlv: *TlsVariable, allocator: Allocator) void { |
| 1311 | allocator.free(tlv.code); |
| 1312 | } |
| 1313 | }; |
| 1314 | |
| 1247 | 1315 | const DeclTable = std.AutoHashMapUnmanaged(InternPool.DeclIndex, DeclMetadata); |
| 1248 | 1316 | const UnnamedConstTable = std.AutoHashMapUnmanaged(InternPool.DeclIndex, std.ArrayListUnmanaged(Symbol.Index)); |
| 1249 | 1317 | const AnonDeclTable = std.AutoHashMapUnmanaged(InternPool.Index, DeclMetadata); |
| 1250 | 1318 | const LazySymbolTable = std.AutoArrayHashMapUnmanaged(InternPool.OptionalDeclIndex, LazySymbolMetadata); |
| 1251 | 1319 | const RelocationTable = std.ArrayListUnmanaged(std.ArrayListUnmanaged(Relocation)); |
| 1320 | const TlsTable = std.AutoArrayHashMapUnmanaged(Atom.Index, TlsVariable); |
| 1252 | 1321 | |
| 1253 | 1322 | const assert = std.debug.assert; |
| 1254 | 1323 | const builtin = @import("builtin"); |