| ... | ... | @@ -185,12 +185,12 @@ misc_errors: std.ArrayListUnmanaged(link.File.ErrorMsg) = .{}, |
| 185 | 185 | lazy_syms: LazySymbolTable = .{}, |
| 186 | 186 | |
| 187 | 187 | /// Table of tracked Decls. |
| 188 | | decls: std.AutoHashMapUnmanaged(Module.Decl.Index, DeclMetadata) = .{}, |
| 188 | decls: DeclTable = .{}, |
| 189 | 189 | |
| 190 | 190 | /// List of atoms that are owned directly by the linker. |
| 191 | 191 | atoms: std.ArrayListUnmanaged(Atom) = .{}, |
| 192 | 192 | /// Table of last atom index in a section and matching atom free list if any. |
| 193 | | last_atom_and_free_list_table: std.AutoArrayHashMapUnmanaged(u16, LastAtomAndFreeList) = .{}, |
| 193 | last_atom_and_free_list_table: LastAtomAndFreeListTable = .{}, |
| 194 | 194 | |
| 195 | 195 | /// Table of unnamed constants associated with a parent `Decl`. |
| 196 | 196 | /// We store them here so that we can free the constants whenever the `Decl` |
| ... | ... | @@ -220,8 +220,10 @@ comdat_groups_table: std.AutoHashMapUnmanaged(u32, ComdatGroupOwner.Index) = .{} |
| 220 | 220 | |
| 221 | 221 | const AtomList = std.ArrayListUnmanaged(Atom.Index); |
| 222 | 222 | const UnnamedConstTable = std.AutoHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(Symbol.Index)); |
| 223 | | const AnonDeclTable = std.AutoHashMapUnmanaged(InternPool.Index, Symbol.Index); |
| 223 | const DeclTable = std.AutoHashMapUnmanaged(Module.Decl.Index, DeclMetadata); |
| 224 | const AnonDeclTable = std.AutoHashMapUnmanaged(InternPool.Index, DeclMetadata); |
| 224 | 225 | const LazySymbolTable = std.AutoArrayHashMapUnmanaged(Module.Decl.OptionalIndex, LazySymbolMetadata); |
| 226 | const LastAtomAndFreeListTable = std.AutoArrayHashMapUnmanaged(u16, LastAtomAndFreeList); |
| 225 | 227 | |
| 226 | 228 | /// When allocating, the ideal_capacity is calculated by |
| 227 | 229 | /// actual_capacity + (actual_capacity / ideal_factor) |
| ... | ... | @@ -445,7 +447,14 @@ pub fn deinit(self: *Elf) void { |
| 445 | 447 | } |
| 446 | 448 | self.unnamed_consts.deinit(gpa); |
| 447 | 449 | } |
| 448 | | self.anon_decls.deinit(gpa); |
| 450 | |
| 451 | { |
| 452 | var it = self.anon_decls.iterator(); |
| 453 | while (it.next()) |entry| { |
| 454 | entry.value_ptr.exports.deinit(gpa); |
| 455 | } |
| 456 | self.anon_decls.deinit(gpa); |
| 457 | } |
| 449 | 458 | |
| 450 | 459 | if (self.dwarf) |*dw| { |
| 451 | 460 | dw.deinit(); |
| ... | ... | @@ -497,8 +506,8 @@ pub fn lowerAnonDecl( |
| 497 | 506 | .none => ty.abiAlignment(mod), |
| 498 | 507 | else => explicit_alignment, |
| 499 | 508 | }; |
| 500 | | if (self.anon_decls.get(decl_val)) |sym_index| { |
| 501 | | const existing_alignment = self.symbol(sym_index).atom(self).?.alignment; |
| 509 | if (self.anon_decls.get(decl_val)) |metadata| { |
| 510 | const existing_alignment = self.symbol(metadata.symbol_index).atom(self).?.alignment; |
| 502 | 511 | if (decl_alignment.order(existing_alignment).compare(.lte)) |
| 503 | 512 | return .ok; |
| 504 | 513 | } |
| ... | ... | @@ -528,13 +537,13 @@ pub fn lowerAnonDecl( |
| 528 | 537 | .ok => |sym_index| sym_index, |
| 529 | 538 | .fail => |em| return .{ .fail = em }, |
| 530 | 539 | }; |
| 531 | | try self.anon_decls.put(gpa, decl_val, sym_index); |
| 540 | try self.anon_decls.put(gpa, decl_val, .{ .symbol_index = sym_index }); |
| 532 | 541 | return .ok; |
| 533 | 542 | } |
| 534 | 543 | |
| 535 | 544 | pub fn getAnonDeclVAddr(self: *Elf, decl_val: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 { |
| 536 | 545 | assert(self.llvm_object == null); |
| 537 | | const sym_index = self.anon_decls.get(decl_val).?; |
| 546 | const sym_index = self.anon_decls.get(decl_val).?.symbol_index; |
| 538 | 547 | const sym = self.symbol(sym_index); |
| 539 | 548 | const vaddr = sym.value; |
| 540 | 549 | const parent_atom = self.symbol(reloc_info.parent_atom_index).atom(self).?; |
| ... | ... | @@ -3122,10 +3131,7 @@ pub fn getOrCreateMetadataForDecl(self: *Elf, decl_index: Module.Decl.Index) !Sy |
| 3122 | 3131 | const gop = try self.decls.getOrPut(self.base.allocator, decl_index); |
| 3123 | 3132 | if (!gop.found_existing) { |
| 3124 | 3133 | const zig_module = self.file(self.zig_module_index.?).?.zig_module; |
| 3125 | | gop.value_ptr.* = .{ |
| 3126 | | .symbol_index = try zig_module.addAtom(self), |
| 3127 | | .exports = .{}, |
| 3128 | | }; |
| 3134 | gop.value_ptr.* = .{ .symbol_index = try zig_module.addAtom(self) }; |
| 3129 | 3135 | } |
| 3130 | 3136 | return gop.value_ptr.symbol_index; |
| 3131 | 3137 | } |
| ... | ... | @@ -3573,31 +3579,30 @@ pub fn updateExports( |
| 3573 | 3579 | defer tracy.end(); |
| 3574 | 3580 | |
| 3575 | 3581 | const gpa = self.base.allocator; |
| 3576 | | |
| 3577 | | const decl_index = switch (exported) { |
| 3578 | | .decl_index => |i| i, |
| 3579 | | .value => |val| { |
| 3580 | | _ = val; |
| 3581 | | @panic("TODO: implement ELF linker code for exporting a constant value"); |
| 3582 | const zig_module = self.file(self.zig_module_index.?).?.zig_module; |
| 3583 | const metadata = switch (exported) { |
| 3584 | .decl_index => |decl_index| blk: { |
| 3585 | _ = try self.getOrCreateMetadataForDecl(decl_index); |
| 3586 | break :blk self.decls.getPtr(decl_index).?; |
| 3582 | 3587 | }, |
| 3588 | // TODO is it possible to request export before const being lowered? |
| 3589 | .value => |value| self.anon_decls.getPtr(value).?, |
| 3583 | 3590 | }; |
| 3584 | | const zig_module = self.file(self.zig_module_index.?).?.zig_module; |
| 3585 | | const decl = mod.declPtr(decl_index); |
| 3586 | | const decl_sym_index = try self.getOrCreateMetadataForDecl(decl_index); |
| 3587 | | const decl_esym_index = self.symbol(decl_sym_index).esym_index; |
| 3588 | | const decl_esym = zig_module.local_esyms.items(.elf_sym)[decl_esym_index]; |
| 3589 | | const decl_esym_shndx = zig_module.local_esyms.items(.shndx)[decl_esym_index]; |
| 3590 | | const decl_metadata = self.decls.getPtr(decl_index).?; |
| 3591 | const sym_index = metadata.symbol_index; |
| 3592 | const esym_index = self.symbol(sym_index).esym_index; |
| 3593 | const esym = zig_module.local_esyms.items(.elf_sym)[esym_index]; |
| 3594 | const esym_shndx = zig_module.local_esyms.items(.shndx)[esym_index]; |
| 3591 | 3595 | |
| 3592 | 3596 | for (exports) |exp| { |
| 3593 | | const exp_name = mod.intern_pool.stringToSlice(exp.opts.name); |
| 3594 | 3597 | if (exp.opts.section.unwrap()) |section_name| { |
| 3595 | 3598 | if (!mod.intern_pool.stringEqlSlice(section_name, ".text")) { |
| 3596 | 3599 | try mod.failed_exports.ensureUnusedCapacity(mod.gpa, 1); |
| 3597 | | mod.failed_exports.putAssumeCapacityNoClobber( |
| 3598 | | exp, |
| 3599 | | try Module.ErrorMsg.create(gpa, decl.srcLoc(mod), "Unimplemented: ExportOptions.section", .{}), |
| 3600 | | ); |
| 3600 | mod.failed_exports.putAssumeCapacityNoClobber(exp, try Module.ErrorMsg.create( |
| 3601 | gpa, |
| 3602 | exp.getSrcLoc(mod), |
| 3603 | "Unimplemented: ExportOptions.section", |
| 3604 | .{}, |
| 3605 | )); |
| 3601 | 3606 | continue; |
| 3602 | 3607 | } |
| 3603 | 3608 | } |
| ... | ... | @@ -3607,34 +3612,37 @@ pub fn updateExports( |
| 3607 | 3612 | .Weak => elf.STB_WEAK, |
| 3608 | 3613 | .LinkOnce => { |
| 3609 | 3614 | try mod.failed_exports.ensureUnusedCapacity(mod.gpa, 1); |
| 3610 | | mod.failed_exports.putAssumeCapacityNoClobber( |
| 3611 | | exp, |
| 3612 | | try Module.ErrorMsg.create(gpa, decl.srcLoc(mod), "Unimplemented: GlobalLinkage.LinkOnce", .{}), |
| 3613 | | ); |
| 3615 | mod.failed_exports.putAssumeCapacityNoClobber(exp, try Module.ErrorMsg.create( |
| 3616 | gpa, |
| 3617 | exp.getSrcLoc(mod), |
| 3618 | "Unimplemented: GlobalLinkage.LinkOnce", |
| 3619 | .{}, |
| 3620 | )); |
| 3614 | 3621 | continue; |
| 3615 | 3622 | }, |
| 3616 | 3623 | }; |
| 3617 | | const stt_bits: u8 = @as(u4, @truncate(decl_esym.st_info)); |
| 3618 | | |
| 3624 | const stt_bits: u8 = @as(u4, @truncate(esym.st_info)); |
| 3625 | const exp_name = mod.intern_pool.stringToSlice(exp.opts.name); |
| 3619 | 3626 | const name_off = try self.strtab.insert(gpa, exp_name); |
| 3620 | | const sym_index = if (decl_metadata.@"export"(self, exp_name)) |exp_index| exp_index.* else blk: { |
| 3621 | | const sym_index = try zig_module.addGlobalEsym(gpa); |
| 3627 | const global_esym_index = if (metadata.@"export"(self, exp_name)) |exp_index| exp_index.* else blk: { |
| 3628 | const global_esym_index = try zig_module.addGlobalEsym(gpa); |
| 3622 | 3629 | const lookup_gop = try zig_module.globals_lookup.getOrPut(gpa, name_off); |
| 3623 | | const esym = zig_module.elfSym(sym_index); |
| 3624 | | esym.st_name = name_off; |
| 3625 | | lookup_gop.value_ptr.* = sym_index; |
| 3626 | | try decl_metadata.exports.append(gpa, sym_index); |
| 3630 | const global_esym = zig_module.elfSym(global_esym_index); |
| 3631 | global_esym.st_name = name_off; |
| 3632 | lookup_gop.value_ptr.* = global_esym_index; |
| 3633 | try metadata.exports.append(gpa, global_esym_index); |
| 3627 | 3634 | const gop = try self.getOrPutGlobal(name_off); |
| 3628 | 3635 | try zig_module.global_symbols.append(gpa, gop.index); |
| 3629 | | break :blk sym_index; |
| 3636 | break :blk global_esym_index; |
| 3630 | 3637 | }; |
| 3631 | | const global_esym_index = sym_index & ZigModule.symbol_mask; |
| 3632 | | const global_esym = &zig_module.global_esyms.items(.elf_sym)[global_esym_index]; |
| 3633 | | global_esym.st_value = self.symbol(decl_sym_index).value; |
| 3634 | | global_esym.st_shndx = decl_esym.st_shndx; |
| 3638 | |
| 3639 | const actual_esym_index = global_esym_index & ZigModule.symbol_mask; |
| 3640 | const global_esym = &zig_module.global_esyms.items(.elf_sym)[actual_esym_index]; |
| 3641 | global_esym.st_value = self.symbol(sym_index).value; |
| 3642 | global_esym.st_shndx = esym.st_shndx; |
| 3635 | 3643 | global_esym.st_info = (stb_bits << 4) | stt_bits; |
| 3636 | 3644 | global_esym.st_name = name_off; |
| 3637 | | zig_module.global_esyms.items(.shndx)[global_esym_index] = decl_esym_shndx; |
| 3645 | zig_module.global_esyms.items(.shndx)[actual_esym_index] = esym_shndx; |
| 3638 | 3646 | } |
| 3639 | 3647 | } |
| 3640 | 3648 | |