| author | |
| committer | |
| log | 0483b4a5126c0d07b1e9ad298729e8d34b5d2272 |
| tree | e1db1a4302556a4f7c25695ee81b90d8882ea2aa |
| parent | c4b0b7a30bf96590f9849f64a3d86fe2ebbc6a26 |
7 files changed, 159 insertions(+), 13 deletions(-)
src/codegen.zig+40-13| ... | @@ -643,19 +643,9 @@ fn lowerParentPtr( | ... | @@ -643,19 +643,9 @@ fn lowerParentPtr( |
| 643 | const ptr = mod.intern_pool.indexToKey(parent_ptr).ptr; | 643 | const ptr = mod.intern_pool.indexToKey(parent_ptr).ptr; |
| 644 | assert(ptr.len == .none); | 644 | assert(ptr.len == .none); |
| 645 | return switch (ptr.addr) { | 645 | return switch (ptr.addr) { |
| 646 | .decl, .mut_decl => try lowerDeclRef( | 646 | .decl => |decl| try lowerDeclRef(bin_file, src_loc, decl, code, debug_output, reloc_info), |
| 647 | bin_file, | 647 | .mut_decl => |md| try lowerDeclRef(bin_file, src_loc, md.decl, code, debug_output, reloc_info), |
| 648 | src_loc, | 648 | .anon_decl => |ad| try lowerAnonDeclRef(bin_file, src_loc, ad, code, debug_output, reloc_info), |
| 649 | switch (ptr.addr) { | ||
| 650 | .decl => |decl| decl, | ||
| 651 | .mut_decl => |mut_decl| mut_decl.decl, | ||
| 652 | else => unreachable, | ||
| 653 | }, | ||
| 654 | code, | ||
| 655 | debug_output, | ||
| 656 | reloc_info, | ||
| 657 | ), | ||
| 658 | .anon_decl => @panic("TODO"), | ||
| 659 | .int => |int| try generateSymbol(bin_file, src_loc, .{ | 649 | .int => |int| try generateSymbol(bin_file, src_loc, .{ |
| 660 | .ty = Type.usize, | 650 | .ty = Type.usize, |
| 661 | .val = int.toValue(), | 651 | .val = int.toValue(), |
| ... | @@ -741,6 +731,43 @@ const RelocInfo = struct { | ... | @@ -741,6 +731,43 @@ const RelocInfo = struct { |
| 741 | } | 731 | } |
| 742 | }; | 732 | }; |
| 743 | 733 | ||
| 734 | fn lowerAnonDeclRef( | ||
| 735 | bin_file: *link.File, | ||
| 736 | src_loc: Module.SrcLoc, | ||
| 737 | decl_val: InternPool.Index, | ||
| 738 | code: *std.ArrayList(u8), | ||
| 739 | debug_output: DebugInfoOutput, | ||
| 740 | reloc_info: RelocInfo, | ||
| 741 | ) CodeGenError!Result { | ||
| 742 | _ = src_loc; | ||
| 743 | _ = debug_output; | ||
| 744 | const target = bin_file.options.target; | ||
| 745 | const mod = bin_file.options.module.?; | ||
| 746 | |||
| 747 | const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8); | ||
| 748 | const decl_ty = mod.intern_pool.typeOf(decl_val).toType(); | ||
| 749 | const is_fn_body = decl_ty.zigTypeTag(mod) == .Fn; | ||
| 750 | if (!is_fn_body and !decl_ty.hasRuntimeBits(mod)) { | ||
| 751 | try code.appendNTimes(0xaa, ptr_width_bytes); | ||
| 752 | return Result.ok; | ||
| 753 | } | ||
| 754 | |||
| 755 | const vaddr = try bin_file.getAnonDeclVAddr(decl_val, .{ | ||
| 756 | .parent_atom_index = reloc_info.parent_atom_index, | ||
| 757 | .offset = code.items.len, | ||
| 758 | .addend = reloc_info.addend orelse 0, | ||
| 759 | }); | ||
| 760 | const endian = target.cpu.arch.endian(); | ||
| 761 | switch (ptr_width_bytes) { | ||
| 762 | 2 => mem.writeInt(u16, try code.addManyAsArray(2), @intCast(vaddr), endian), | ||
| 763 | 4 => mem.writeInt(u32, try code.addManyAsArray(4), @intCast(vaddr), endian), | ||
| 764 | 8 => mem.writeInt(u64, try code.addManyAsArray(8), vaddr, endian), | ||
| 765 | else => unreachable, | ||
| 766 | } | ||
| 767 | |||
| 768 | return Result.ok; | ||
| 769 | } | ||
| 770 | |||
| 744 | fn lowerDeclRef( | 771 | fn lowerDeclRef( |
| 745 | bin_file: *link.File, | 772 | bin_file: *link.File, |
| 746 | src_loc: Module.SrcLoc, | 773 | src_loc: Module.SrcLoc, |
src/link.zig+14| ... | @@ -937,6 +937,20 @@ pub const File = struct { | ... | @@ -937,6 +937,20 @@ pub const File = struct { |
| 937 | } | 937 | } |
| 938 | } | 938 | } |
| 939 | 939 | ||
| 940 | pub fn getAnonDeclVAddr(base: *File, decl_val: InternPool.Index, reloc_info: RelocInfo) !u64 { | ||
| 941 | if (build_options.only_c) unreachable; | ||
| 942 | switch (base.tag) { | ||
| 943 | .coff => return @fieldParentPtr(Coff, "base", base).getAnonDeclVAddr(decl_val, reloc_info), | ||
| 944 | .elf => return @fieldParentPtr(Elf, "base", base).getAnonDeclVAddr(decl_val, reloc_info), | ||
| 945 | .macho => return @fieldParentPtr(MachO, "base", base).getAnonDeclVAddr(decl_val, reloc_info), | ||
| 946 | .plan9 => return @fieldParentPtr(Plan9, "base", base).getAnonDeclVAddr(decl_val, reloc_info), | ||
| 947 | .c => unreachable, | ||
| 948 | .wasm => return @fieldParentPtr(Wasm, "base", base).getAnonDeclVAddr(decl_val, reloc_info), | ||
| 949 | .spirv => unreachable, | ||
| 950 | .nvptx => unreachable, | ||
| 951 | } | ||
| 952 | } | ||
| 953 | |||
| 940 | /// This function is called by the frontend before flush(). It communicates that | 954 | /// This function is called by the frontend before flush(). It communicates that |
| 941 | /// `options.bin_file.emit` directory needs to be renamed from | 955 | /// `options.bin_file.emit` directory needs to be renamed from |
| 942 | /// `[zig-cache]/tmp/[random]` to `[zig-cache]/o/[digest]`. | 956 | /// `[zig-cache]/tmp/[random]` to `[zig-cache]/o/[digest]`. |
src/link/Coff.zig+21| ... | @@ -1727,6 +1727,27 @@ pub fn getDeclVAddr(self: *Coff, decl_index: Module.Decl.Index, reloc_info: link | ... | @@ -1727,6 +1727,27 @@ pub fn getDeclVAddr(self: *Coff, decl_index: Module.Decl.Index, reloc_info: link |
| 1727 | return 0; | 1727 | return 0; |
| 1728 | } | 1728 | } |
| 1729 | 1729 | ||
| 1730 | pub fn getAnonDeclVAddr( | ||
| 1731 | self: *Coff, | ||
| 1732 | decl_val: InternPool.Index, | ||
| 1733 | reloc_info: link.File.RelocInfo, | ||
| 1734 | ) !u64 { | ||
| 1735 | // This is basically the same as lowerUnnamedConst except it needs | ||
| 1736 | // to return the same thing as `getDeclVAddr` | ||
| 1737 | // example: | ||
| 1738 | // const ty = mod.intern_pool.typeOf(decl_val).toType(); | ||
| 1739 | // const val = decl_val.toValue(); | ||
| 1740 | // The symbol name can be something like `__anon_{d}` with `@intFromEnum(decl_val)`. | ||
| 1741 | // It doesn't have an owner decl because it's just an unnamed constant that might | ||
| 1742 | // be used by more than one function, however, its address is being used so we need | ||
| 1743 | // to put it in some location. | ||
| 1744 | // ... | ||
| 1745 | _ = self; | ||
| 1746 | _ = decl_val; | ||
| 1747 | _ = reloc_info; | ||
| 1748 | _ = @panic("TODO: link/Coff getAnonDeclVAddr"); | ||
| 1749 | } | ||
| 1750 | |||
| 1730 | pub fn getGlobalSymbol(self: *Coff, name: []const u8, lib_name_name: ?[]const u8) !u32 { | 1751 | pub fn getGlobalSymbol(self: *Coff, name: []const u8, lib_name_name: ?[]const u8) !u32 { |
| 1731 | const gop = try self.getOrPutGlobalPtr(name); | 1752 | const gop = try self.getOrPutGlobalPtr(name); |
| 1732 | const global_index = self.getGlobalIndex(name).?; | 1753 | const global_index = self.getGlobalIndex(name).?; |
src/link/Elf.zig+21| ... | @@ -348,6 +348,27 @@ pub fn getDeclVAddr(self: *Elf, decl_index: Module.Decl.Index, reloc_info: link. | ... | @@ -348,6 +348,27 @@ pub fn getDeclVAddr(self: *Elf, decl_index: Module.Decl.Index, reloc_info: link. |
| 348 | return vaddr; | 348 | return vaddr; |
| 349 | } | 349 | } |
| 350 | 350 | ||
| 351 | pub fn getAnonDeclVAddr( | ||
| 352 | self: *Elf, | ||
| 353 | decl_val: InternPool.Index, | ||
| 354 | reloc_info: link.File.RelocInfo, | ||
| 355 | ) !u64 { | ||
| 356 | // This is basically the same as lowerUnnamedConst except it needs | ||
| 357 | // to return the same thing as `getDeclVAddr` | ||
| 358 | // example: | ||
| 359 | // const ty = mod.intern_pool.typeOf(decl_val).toType(); | ||
| 360 | // const val = decl_val.toValue(); | ||
| 361 | // The symbol name can be something like `__anon_{d}` with `@intFromEnum(decl_val)`. | ||
| 362 | // It doesn't have an owner decl because it's just an unnamed constant that might | ||
| 363 | // be used by more than one function, however, its address is being used so we need | ||
| 364 | // to put it in some location. | ||
| 365 | // ... | ||
| 366 | _ = self; | ||
| 367 | _ = decl_val; | ||
| 368 | _ = reloc_info; | ||
| 369 | _ = @panic("TODO: link/Elf getAnonDeclVAddr"); | ||
| 370 | } | ||
| 371 | |||
| 351 | /// Returns end pos of collision, if any. | 372 | /// Returns end pos of collision, if any. |
| 352 | fn detectAllocCollision(self: *Elf, start: u64, size: u64) ?u64 { | 373 | fn detectAllocCollision(self: *Elf, start: u64, size: u64) ?u64 { |
| 353 | const small_ptr = self.ptr_width == .p32; | 374 | const small_ptr = self.ptr_width == .p32; |
src/link/MachO.zig+21| ... | @@ -2840,6 +2840,27 @@ pub fn getDeclVAddr(self: *MachO, decl_index: Module.Decl.Index, reloc_info: Fil | ... | @@ -2840,6 +2840,27 @@ pub fn getDeclVAddr(self: *MachO, decl_index: Module.Decl.Index, reloc_info: Fil |
| 2840 | return 0; | 2840 | return 0; |
| 2841 | } | 2841 | } |
| 2842 | 2842 | ||
| 2843 | pub fn getAnonDeclVAddr( | ||
| 2844 | self: *MachO, | ||
| 2845 | decl_val: InternPool.Index, | ||
| 2846 | reloc_info: link.File.RelocInfo, | ||
| 2847 | ) !u64 { | ||
| 2848 | // This is basically the same as lowerUnnamedConst except it needs | ||
| 2849 | // to return the same thing as `getDeclVAddr` | ||
| 2850 | // example: | ||
| 2851 | // const ty = mod.intern_pool.typeOf(decl_val).toType(); | ||
| 2852 | // const val = decl_val.toValue(); | ||
| 2853 | // The symbol name can be something like `__anon_{d}` with `@intFromEnum(decl_val)`. | ||
| 2854 | // It doesn't have an owner decl because it's just an unnamed constant that might | ||
| 2855 | // be used by more than one function, however, its address is being used so we need | ||
| 2856 | // to put it in some location. | ||
| 2857 | // ... | ||
| 2858 | _ = self; | ||
| 2859 | _ = decl_val; | ||
| 2860 | _ = reloc_info; | ||
| 2861 | _ = @panic("TODO: link/MachO getAnonDeclVAddr"); | ||
| 2862 | } | ||
| 2863 | |||
| 2843 | fn populateMissingMetadata(self: *MachO) !void { | 2864 | fn populateMissingMetadata(self: *MachO) !void { |
| 2844 | assert(self.mode == .incremental); | 2865 | assert(self.mode == .incremental); |
| 2845 | 2866 |
src/link/Plan9.zig+21| ... | @@ -1418,6 +1418,27 @@ pub fn getDeclVAddr( | ... | @@ -1418,6 +1418,27 @@ pub fn getDeclVAddr( |
| 1418 | return undefined; | 1418 | return undefined; |
| 1419 | } | 1419 | } |
| 1420 | 1420 | ||
| 1421 | pub fn getAnonDeclVAddr( | ||
| 1422 | self: *Plan9, | ||
| 1423 | decl_val: InternPool.Index, | ||
| 1424 | reloc_info: link.File.RelocInfo, | ||
| 1425 | ) !u64 { | ||
| 1426 | // This is basically the same as lowerUnnamedConst except it needs | ||
| 1427 | // to return the same thing as `getDeclVAddr` | ||
| 1428 | // example: | ||
| 1429 | // const ty = mod.intern_pool.typeOf(decl_val).toType(); | ||
| 1430 | // const val = decl_val.toValue(); | ||
| 1431 | // The symbol name can be something like `__anon_{d}` with `@intFromEnum(decl_val)`. | ||
| 1432 | // It doesn't have an owner decl because it's just an unnamed constant that might | ||
| 1433 | // be used by more than one function, however, its address is being used so we need | ||
| 1434 | // to put it in some location. | ||
| 1435 | // ... | ||
| 1436 | _ = self; | ||
| 1437 | _ = decl_val; | ||
| 1438 | _ = reloc_info; | ||
| 1439 | _ = @panic("TODO: link/Plan9 getAnonDeclVAddr"); | ||
| 1440 | } | ||
| 1441 | |||
| 1421 | pub fn addReloc(self: *Plan9, parent_index: Atom.Index, reloc: Reloc) !void { | 1442 | pub fn addReloc(self: *Plan9, parent_index: Atom.Index, reloc: Reloc) !void { |
| 1422 | const gop = try self.relocs.getOrPut(self.base.allocator, parent_index); | 1443 | const gop = try self.relocs.getOrPut(self.base.allocator, parent_index); |
| 1423 | if (!gop.found_existing) { | 1444 | if (!gop.found_existing) { |
src/link/Wasm.zig+21| ... | @@ -1679,6 +1679,27 @@ pub fn getDeclVAddr( | ... | @@ -1679,6 +1679,27 @@ pub fn getDeclVAddr( |
| 1679 | return target_symbol_index; | 1679 | return target_symbol_index; |
| 1680 | } | 1680 | } |
| 1681 | 1681 | ||
| 1682 | pub fn getAnonDeclVAddr( | ||
| 1683 | wasm: *Wasm, | ||
| 1684 | decl_val: InternPool.Index, | ||
| 1685 | reloc_info: link.File.RelocInfo, | ||
| 1686 | ) !u64 { | ||
| 1687 | // This is basically the same as lowerUnnamedConst except it needs | ||
| 1688 | // to return the same thing as `getDeclVAddr` | ||
| 1689 | // example: | ||
| 1690 | // const ty = mod.intern_pool.typeOf(decl_val).toType(); | ||
| 1691 | // const val = decl_val.toValue(); | ||
| 1692 | // The symbol name can be something like `__anon_{d}` with `@intFromEnum(decl_val)`. | ||
| 1693 | // It doesn't have an owner decl because it's just an unnamed constant that might | ||
| 1694 | // be used by more than one function, however, its address is being used so we need | ||
| 1695 | // to put it in some location. | ||
| 1696 | // ... | ||
| 1697 | _ = wasm; | ||
| 1698 | _ = decl_val; | ||
| 1699 | _ = reloc_info; | ||
| 1700 | _ = @panic("TODO: link/Wasm getAnonDeclVAddr"); | ||
| 1701 | } | ||
| 1702 | |||
| 1682 | pub fn deleteDeclExport(wasm: *Wasm, decl_index: Module.Decl.Index) void { | 1703 | pub fn deleteDeclExport(wasm: *Wasm, decl_index: Module.Decl.Index) void { |
| 1683 | if (wasm.llvm_object) |_| return; | 1704 | if (wasm.llvm_object) |_| return; |
| 1684 | const atom_index = wasm.decls.get(decl_index) orelse return; | 1705 | const atom_index = wasm.decls.get(decl_index) orelse return; |