| ... | @@ -38,6 +38,9 @@ unnamed_consts: UnnamedConstTable = .{}, | ... | @@ -38,6 +38,9 @@ unnamed_consts: UnnamedConstTable = .{}, |
| 38 | /// Table of tracked AnonDecls. | 38 | /// Table of tracked AnonDecls. |
| 39 | anon_decls: AnonDeclTable = .{}, | 39 | anon_decls: AnonDeclTable = .{}, |
| 40 | | 40 | |
| | 41 | /// TLS variables indexed by Atom.Index. |
| | 42 | tls_variables: TlsTable = .{}, |
| | 43 | |
| 41 | /// A table of relocations. | 44 | /// A table of relocations. |
| 42 | relocs: RelocationTable = .{}, | 45 | relocs: RelocationTable = .{}, |
| 43 | | 46 | |
| ... | @@ -87,6 +90,11 @@ pub fn deinit(self: *ZigObject, allocator: Allocator) void { | ... | @@ -87,6 +90,11 @@ pub fn deinit(self: *ZigObject, allocator: Allocator) void { |
| 87 | list.deinit(allocator); | 90 | list.deinit(allocator); |
| 88 | } | 91 | } |
| 89 | self.relocs.deinit(allocator); | 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 | fn addNlist(self: *ZigObject, allocator: Allocator) !Symbol.Index { | 100 | fn addNlist(self: *ZigObject, allocator: Allocator) !Symbol.Index { |
| ... | @@ -612,8 +620,7 @@ pub fn updateDecl( | ... | @@ -612,8 +620,7 @@ pub fn updateDecl( |
| 612 | else => false, | 620 | else => false, |
| 613 | }; | 621 | }; |
| 614 | if (is_threadlocal) { | 622 | if (is_threadlocal) { |
| 615 | // TODO: emit TLV | 623 | try self.updateTlv(macho_file, decl_index, sym_index, sect_index, code); |
| 616 | @panic("TODO updateDecl for TLS"); | | |
| 617 | } else { | 624 | } else { |
| 618 | try self.updateDeclCode(macho_file, decl_index, sym_index, sect_index, code); | 625 | try self.updateDeclCode(macho_file, decl_index, sym_index, sect_index, code); |
| 619 | } | 626 | } |
| ... | @@ -715,6 +722,58 @@ fn updateDeclCode( | ... | @@ -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 | fn getDeclOutputSection( | 777 | fn getDeclOutputSection( |
| 719 | self: *ZigObject, | 778 | self: *ZigObject, |
| 720 | macho_file: *MachO, | 779 | macho_file: *MachO, |
| ... | @@ -1244,11 +1303,21 @@ const LazySymbolMetadata = struct { | ... | @@ -1244,11 +1303,21 @@ const LazySymbolMetadata = struct { |
| 1244 | const_state: State = .unused, | 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 | const DeclTable = std.AutoHashMapUnmanaged(InternPool.DeclIndex, DeclMetadata); | 1315 | const DeclTable = std.AutoHashMapUnmanaged(InternPool.DeclIndex, DeclMetadata); |
| 1248 | const UnnamedConstTable = std.AutoHashMapUnmanaged(InternPool.DeclIndex, std.ArrayListUnmanaged(Symbol.Index)); | 1316 | const UnnamedConstTable = std.AutoHashMapUnmanaged(InternPool.DeclIndex, std.ArrayListUnmanaged(Symbol.Index)); |
| 1249 | const AnonDeclTable = std.AutoHashMapUnmanaged(InternPool.Index, DeclMetadata); | 1317 | const AnonDeclTable = std.AutoHashMapUnmanaged(InternPool.Index, DeclMetadata); |
| 1250 | const LazySymbolTable = std.AutoArrayHashMapUnmanaged(InternPool.OptionalDeclIndex, LazySymbolMetadata); | 1318 | const LazySymbolTable = std.AutoArrayHashMapUnmanaged(InternPool.OptionalDeclIndex, LazySymbolMetadata); |
| 1251 | const RelocationTable = std.ArrayListUnmanaged(std.ArrayListUnmanaged(Relocation)); | 1319 | const RelocationTable = std.ArrayListUnmanaged(std.ArrayListUnmanaged(Relocation)); |
| | 1320 | const TlsTable = std.AutoArrayHashMapUnmanaged(Atom.Index, TlsVariable); |
| 1252 | | 1321 | |
| 1253 | const assert = std.debug.assert; | 1322 | const assert = std.debug.assert; |
| 1254 | const builtin = @import("builtin"); | 1323 | const builtin = @import("builtin"); |