| ... | @@ -130,7 +130,7 @@ bindings: BindingTable = .{}, | ... | @@ -130,7 +130,7 @@ bindings: BindingTable = .{}, |
| 130 | lazy_syms: LazySymbolTable = .{}, | 130 | lazy_syms: LazySymbolTable = .{}, |
| 131 | | 131 | |
| 132 | /// Table of tracked Decls. | 132 | /// Table of tracked Decls. |
| 133 | decls: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, DeclMetadata) = .{}, | 133 | decls: DeclTable = .{}, |
| 134 | | 134 | |
| 135 | /// Table of threadlocal variables descriptors. | 135 | /// Table of threadlocal variables descriptors. |
| 136 | /// They are emitted in the `__thread_vars` section. | 136 | /// They are emitted in the `__thread_vars` section. |
| ... | @@ -1904,6 +1904,7 @@ pub fn deinit(self: *MachO) void { | ... | @@ -1904,6 +1904,7 @@ pub fn deinit(self: *MachO) void { |
| 1904 | m.exports.deinit(gpa); | 1904 | m.exports.deinit(gpa); |
| 1905 | } | 1905 | } |
| 1906 | self.decls.deinit(gpa); | 1906 | self.decls.deinit(gpa); |
| | 1907 | |
| 1907 | self.lazy_syms.deinit(gpa); | 1908 | self.lazy_syms.deinit(gpa); |
| 1908 | self.tlv_table.deinit(gpa); | 1909 | self.tlv_table.deinit(gpa); |
| 1909 | | 1910 | |
| ... | @@ -1911,7 +1912,14 @@ pub fn deinit(self: *MachO) void { | ... | @@ -1911,7 +1912,14 @@ pub fn deinit(self: *MachO) void { |
| 1911 | atoms.deinit(gpa); | 1912 | atoms.deinit(gpa); |
| 1912 | } | 1913 | } |
| 1913 | self.unnamed_const_atoms.deinit(gpa); | 1914 | self.unnamed_const_atoms.deinit(gpa); |
| 1914 | self.anon_decls.deinit(gpa); | 1915 | |
| | 1916 | { |
| | 1917 | var it = self.anon_decls.iterator(); |
| | 1918 | while (it.next()) |entry| { |
| | 1919 | entry.value_ptr.exports.deinit(gpa); |
| | 1920 | } |
| | 1921 | self.anon_decls.deinit(gpa); |
| | 1922 | } |
| 1915 | | 1923 | |
| 1916 | self.atom_by_index_table.deinit(gpa); | 1924 | self.atom_by_index_table.deinit(gpa); |
| 1917 | | 1925 | |
| ... | @@ -2689,18 +2697,30 @@ pub fn updateExports( | ... | @@ -2689,18 +2697,30 @@ pub fn updateExports( |
| 2689 | | 2697 | |
| 2690 | const gpa = self.base.allocator; | 2698 | const gpa = self.base.allocator; |
| 2691 | | 2699 | |
| 2692 | const decl_index = switch (exported) { | 2700 | const metadata = switch (exported) { |
| 2693 | .decl_index => |i| i, | 2701 | .decl_index => |decl_index| blk: { |
| 2694 | .value => |val| { | 2702 | _ = try self.getOrCreateAtomForDecl(decl_index); |
| 2695 | _ = val; | 2703 | break :blk self.decls.getPtr(decl_index).?; |
| 2696 | @panic("TODO: implement MachO linker code for exporting a constant value"); | 2704 | }, |
| | 2705 | .value => |value| self.anon_decls.getPtr(value) orelse blk: { |
| | 2706 | const first_exp = exports[0]; |
| | 2707 | const res = try self.lowerAnonDecl(value, .none, first_exp.getSrcLoc(mod)); |
| | 2708 | switch (res) { |
| | 2709 | .ok => {}, |
| | 2710 | .fail => |em| { |
| | 2711 | // TODO maybe it's enough to return an error here and let Module.processExportsInner |
| | 2712 | // handle the error? |
| | 2713 | try mod.failed_exports.ensureUnusedCapacity(mod.gpa, 1); |
| | 2714 | mod.failed_exports.putAssumeCapacityNoClobber(first_exp, em); |
| | 2715 | return; |
| | 2716 | }, |
| | 2717 | } |
| | 2718 | break :blk self.anon_decls.getPtr(value).?; |
| 2697 | }, | 2719 | }, |
| 2698 | }; | 2720 | }; |
| 2699 | const decl = mod.declPtr(decl_index); | 2721 | const atom_index = metadata.atom; |
| 2700 | const atom_index = try self.getOrCreateAtomForDecl(decl_index); | | |
| 2701 | const atom = self.getAtom(atom_index); | 2722 | const atom = self.getAtom(atom_index); |
| 2702 | const decl_sym = atom.getSymbol(self); | 2723 | const sym = atom.getSymbol(self); |
| 2703 | const decl_metadata = self.decls.getPtr(decl_index).?; | | |
| 2704 | | 2724 | |
| 2705 | for (exports) |exp| { | 2725 | for (exports) |exp| { |
| 2706 | const exp_name = try std.fmt.allocPrint(gpa, "_{}", .{ | 2726 | const exp_name = try std.fmt.allocPrint(gpa, "_{}", .{ |
| ... | @@ -2712,73 +2732,65 @@ pub fn updateExports( | ... | @@ -2712,73 +2732,65 @@ pub fn updateExports( |
| 2712 | | 2732 | |
| 2713 | if (exp.opts.section.unwrap()) |section_name| { | 2733 | if (exp.opts.section.unwrap()) |section_name| { |
| 2714 | if (!mod.intern_pool.stringEqlSlice(section_name, "__text")) { | 2734 | if (!mod.intern_pool.stringEqlSlice(section_name, "__text")) { |
| 2715 | try mod.failed_exports.putNoClobber( | 2735 | try mod.failed_exports.putNoClobber(mod.gpa, exp, try Module.ErrorMsg.create( |
| 2716 | mod.gpa, | 2736 | gpa, |
| 2717 | exp, | 2737 | exp.getSrcLoc(mod), |
| 2718 | try Module.ErrorMsg.create( | 2738 | "Unimplemented: ExportOptions.section", |
| 2719 | gpa, | 2739 | .{}, |
| 2720 | decl.srcLoc(mod), | 2740 | )); |
| 2721 | "Unimplemented: ExportOptions.section", | | |
| 2722 | .{}, | | |
| 2723 | ), | | |
| 2724 | ); | | |
| 2725 | continue; | 2741 | continue; |
| 2726 | } | 2742 | } |
| 2727 | } | 2743 | } |
| 2728 | | 2744 | |
| 2729 | if (exp.opts.linkage == .LinkOnce) { | 2745 | if (exp.opts.linkage == .LinkOnce) { |
| 2730 | try mod.failed_exports.putNoClobber( | 2746 | try mod.failed_exports.putNoClobber(mod.gpa, exp, try Module.ErrorMsg.create( |
| 2731 | mod.gpa, | 2747 | gpa, |
| 2732 | exp, | 2748 | exp.getSrcLoc(mod), |
| 2733 | try Module.ErrorMsg.create( | 2749 | "Unimplemented: GlobalLinkage.LinkOnce", |
| 2734 | gpa, | 2750 | .{}, |
| 2735 | decl.srcLoc(mod), | 2751 | )); |
| 2736 | "Unimplemented: GlobalLinkage.LinkOnce", | | |
| 2737 | .{}, | | |
| 2738 | ), | | |
| 2739 | ); | | |
| 2740 | continue; | 2752 | continue; |
| 2741 | } | 2753 | } |
| 2742 | | 2754 | |
| 2743 | const sym_index = decl_metadata.getExport(self, exp_name) orelse blk: { | 2755 | const global_sym_index = metadata.getExport(self, exp_name) orelse blk: { |
| 2744 | const sym_index = try self.allocateSymbol(); | 2756 | const global_sym_index = try self.allocateSymbol(); |
| 2745 | try decl_metadata.exports.append(gpa, sym_index); | 2757 | try metadata.exports.append(gpa, global_sym_index); |
| 2746 | break :blk sym_index; | 2758 | break :blk global_sym_index; |
| 2747 | }; | 2759 | }; |
| 2748 | const sym_loc = SymbolWithLoc{ .sym_index = sym_index }; | 2760 | const global_sym_loc = SymbolWithLoc{ .sym_index = global_sym_index }; |
| 2749 | const sym = self.getSymbolPtr(sym_loc); | 2761 | const global_sym = self.getSymbolPtr(global_sym_loc); |
| 2750 | sym.* = .{ | 2762 | global_sym.* = .{ |
| 2751 | .n_strx = try self.strtab.insert(gpa, exp_name), | 2763 | .n_strx = try self.strtab.insert(gpa, exp_name), |
| 2752 | .n_type = macho.N_SECT | macho.N_EXT, | 2764 | .n_type = macho.N_SECT | macho.N_EXT, |
| 2753 | .n_sect = self.text_section_index.? + 1, // TODO what if we export a variable? | 2765 | .n_sect = metadata.section + 1, |
| 2754 | .n_desc = 0, | 2766 | .n_desc = 0, |
| 2755 | .n_value = decl_sym.n_value, | 2767 | .n_value = sym.n_value, |
| 2756 | }; | 2768 | }; |
| 2757 | | 2769 | |
| 2758 | switch (exp.opts.linkage) { | 2770 | switch (exp.opts.linkage) { |
| 2759 | .Internal => { | 2771 | .Internal => { |
| 2760 | // Symbol should be hidden, or in MachO lingo, private extern. | 2772 | // Symbol should be hidden, or in MachO lingo, private extern. |
| 2761 | // We should also mark the symbol as Weak: n_desc == N_WEAK_DEF. | 2773 | // We should also mark the symbol as Weak: n_desc == N_WEAK_DEF. |
| 2762 | sym.n_type |= macho.N_PEXT; | 2774 | global_sym.n_type |= macho.N_PEXT; |
| 2763 | sym.n_desc |= macho.N_WEAK_DEF; | 2775 | global_sym.n_desc |= macho.N_WEAK_DEF; |
| 2764 | }, | 2776 | }, |
| 2765 | .Strong => {}, | 2777 | .Strong => {}, |
| 2766 | .Weak => { | 2778 | .Weak => { |
| 2767 | // Weak linkage is specified as part of n_desc field. | 2779 | // Weak linkage is specified as part of n_desc field. |
| 2768 | // Symbol's n_type is like for a symbol with strong linkage. | 2780 | // Symbol's n_type is like for a symbol with strong linkage. |
| 2769 | sym.n_desc |= macho.N_WEAK_DEF; | 2781 | global_sym.n_desc |= macho.N_WEAK_DEF; |
| 2770 | }, | 2782 | }, |
| 2771 | else => unreachable, | 2783 | else => unreachable, |
| 2772 | } | 2784 | } |
| 2773 | | 2785 | |
| 2774 | self.resolveGlobalSymbol(sym_loc) catch |err| switch (err) { | 2786 | self.resolveGlobalSymbol(global_sym_loc) catch |err| switch (err) { |
| 2775 | error.MultipleSymbolDefinitions => { | 2787 | error.MultipleSymbolDefinitions => { |
| 2776 | // TODO: this needs rethinking | 2788 | // TODO: this needs rethinking |
| 2777 | const global = self.getGlobal(exp_name).?; | 2789 | const global = self.getGlobal(exp_name).?; |
| 2778 | if (sym_loc.sym_index != global.sym_index and global.getFile() != null) { | 2790 | if (global_sym_loc.sym_index != global.sym_index and global.getFile() != null) { |
| 2779 | _ = try mod.failed_exports.put(mod.gpa, exp, try Module.ErrorMsg.create( | 2791 | _ = try mod.failed_exports.put(mod.gpa, exp, try Module.ErrorMsg.create( |
| 2780 | gpa, | 2792 | gpa, |
| 2781 | decl.srcLoc(mod), | 2793 | exp.getSrcLoc(mod), |
| 2782 | \\LinkError: symbol '{s}' defined multiple times | 2794 | \\LinkError: symbol '{s}' defined multiple times |
| 2783 | , | 2795 | , |
| 2784 | .{exp_name}, | 2796 | .{exp_name}, |
| ... | @@ -2886,8 +2898,8 @@ pub fn lowerAnonDecl( | ... | @@ -2886,8 +2898,8 @@ pub fn lowerAnonDecl( |
| 2886 | .none => ty.abiAlignment(mod), | 2898 | .none => ty.abiAlignment(mod), |
| 2887 | else => explicit_alignment, | 2899 | else => explicit_alignment, |
| 2888 | }; | 2900 | }; |
| 2889 | if (self.anon_decls.get(decl_val)) |atom_index| { | 2901 | if (self.anon_decls.get(decl_val)) |metadata| { |
| 2890 | const existing_addr = self.getAtom(atom_index).getSymbol(self).n_value; | 2902 | const existing_addr = self.getAtom(metadata.atom).getSymbol(self).n_value; |
| 2891 | if (decl_alignment.check(existing_addr)) | 2903 | if (decl_alignment.check(existing_addr)) |
| 2892 | return .ok; | 2904 | return .ok; |
| 2893 | } | 2905 | } |
| ... | @@ -2917,14 +2929,17 @@ pub fn lowerAnonDecl( | ... | @@ -2917,14 +2929,17 @@ pub fn lowerAnonDecl( |
| 2917 | .ok => |atom_index| atom_index, | 2929 | .ok => |atom_index| atom_index, |
| 2918 | .fail => |em| return .{ .fail = em }, | 2930 | .fail => |em| return .{ .fail = em }, |
| 2919 | }; | 2931 | }; |
| 2920 | try self.anon_decls.put(gpa, decl_val, atom_index); | 2932 | try self.anon_decls.put(gpa, decl_val, .{ |
| | 2933 | .atom = atom_index, |
| | 2934 | .section = self.data_const_section_index.?, |
| | 2935 | }); |
| 2921 | return .ok; | 2936 | return .ok; |
| 2922 | } | 2937 | } |
| 2923 | | 2938 | |
| 2924 | pub fn getAnonDeclVAddr(self: *MachO, decl_val: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 { | 2939 | pub fn getAnonDeclVAddr(self: *MachO, decl_val: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 { |
| 2925 | assert(self.llvm_object == null); | 2940 | assert(self.llvm_object == null); |
| 2926 | | 2941 | |
| 2927 | const this_atom_index = self.anon_decls.get(decl_val).?; | 2942 | const this_atom_index = self.anon_decls.get(decl_val).?.atom; |
| 2928 | const sym_index = self.getAtom(this_atom_index).getSymbolIndex().?; | 2943 | const sym_index = self.getAtom(this_atom_index).getSymbolIndex().?; |
| 2929 | const atom_index = self.getAtomIndexForSymbol(.{ .sym_index = reloc_info.parent_atom_index }).?; | 2944 | const atom_index = self.getAtomIndexForSymbol(.{ .sym_index = reloc_info.parent_atom_index }).?; |
| 2930 | try Atom.addRelocation(self, atom_index, .{ | 2945 | try Atom.addRelocation(self, atom_index, .{ |
| ... | @@ -5489,7 +5504,8 @@ const DeclMetadata = struct { | ... | @@ -5489,7 +5504,8 @@ const DeclMetadata = struct { |
| 5489 | } | 5504 | } |
| 5490 | }; | 5505 | }; |
| 5491 | | 5506 | |
| 5492 | const AnonDeclTable = std.AutoHashMapUnmanaged(InternPool.Index, Atom.Index); | 5507 | const DeclTable = std.AutoArrayHashMapUnmanaged(Module.Decl.Index, DeclMetadata); |
| | 5508 | const AnonDeclTable = std.AutoHashMapUnmanaged(InternPool.Index, DeclMetadata); |
| 5493 | const BindingTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(Atom.Binding)); | 5509 | const BindingTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(Atom.Binding)); |
| 5494 | const UnnamedConstTable = std.AutoArrayHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(Atom.Index)); | 5510 | const UnnamedConstTable = std.AutoArrayHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(Atom.Index)); |
| 5495 | const RebaseTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(u32)); | 5511 | const RebaseTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(u32)); |