authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-01-04 18:13:25-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-01-15 15:11:36-08:00
log1fd708b1bc41878c33db7e2a50433ab1a66d41ee
tree45c743308f17b2ea53d824a4acc19a2d65d1b7a9
parentabdbc38574b9f0fb3a1130285cbf84c2dbd4552c

wasm linker: implement data relocs


2 files changed, 187 insertions(+), 46 deletions(-)

src/link/Wasm.zig+164-29
...@@ -242,7 +242,7 @@ function_imports: std.AutoArrayHashMapUnmanaged(String, FunctionImportId) = .emp...@@ -242,7 +242,7 @@ function_imports: std.AutoArrayHashMapUnmanaged(String, FunctionImportId) = .emp
242data_imports: std.AutoArrayHashMapUnmanaged(String, DataImportId) = .empty,242data_imports: std.AutoArrayHashMapUnmanaged(String, DataImportId) = .empty,
243/// Set of data symbols that will appear in the final binary. Used to populate243/// Set of data symbols that will appear in the final binary. Used to populate
244/// `Flush.data_segments` before sorting.244/// `Flush.data_segments` before sorting.
245data_segments: std.AutoArrayHashMapUnmanaged(DataId, void) = .empty,245data_segments: std.AutoArrayHashMapUnmanaged(DataSegmentId, void) = .empty,
246246
247/// Ordered list of non-import globals that will appear in the final binary.247/// Ordered list of non-import globals that will appear in the final binary.
248/// Empty until prelink.248/// Empty until prelink.
...@@ -1523,27 +1523,120 @@ pub const ObjectDataImport = extern struct {...@@ -1523,27 +1523,120 @@ pub const ObjectDataImport = extern struct {
1523 source_location: SourceLocation,1523 source_location: SourceLocation,
15241524
1525 pub const Resolution = enum(u32) {1525 pub const Resolution = enum(u32) {
1526 unresolved,
1526 __zig_error_names,1527 __zig_error_names,
1527 __zig_error_name_table,1528 __zig_error_name_table,
1528 __heap_base,1529 __heap_base,
1529 __heap_end,1530 __heap_end,
1530 unresolved = std.math.maxInt(u32),1531 /// Next, an `ObjectData.Index`.
1532 /// Next, index into `uavs_obj` or `uavs_exe` depending on whether emitting an object.
1533 /// Next, index into `navs_obj` or `navs_exe` depending on whether emitting an object.
1531 _,1534 _,
15321535
1533 comptime {1536 const first_object = @intFromEnum(Resolution.__heap_end) + 1;
1534 assert(@intFromEnum(Resolution.__zig_error_names) == @intFromEnum(DataId.__zig_error_names));1537
1535 assert(@intFromEnum(Resolution.__zig_error_name_table) == @intFromEnum(DataId.__zig_error_name_table));1538 pub const Unpacked = union(enum) {
1536 assert(@intFromEnum(Resolution.__heap_base) == @intFromEnum(DataId.__heap_base));1539 unresolved,
1537 assert(@intFromEnum(Resolution.__heap_end) == @intFromEnum(DataId.__heap_end));1540 __zig_error_names,
1541 __zig_error_name_table,
1542 __heap_base,
1543 __heap_end,
1544 object: ObjectData.Index,
1545 uav_exe: UavsExeIndex,
1546 uav_obj: UavsObjIndex,
1547 nav_exe: NavsExeIndex,
1548 nav_obj: NavsObjIndex,
1549 };
1550
1551 pub fn unpack(r: Resolution, wasm: *const Wasm) Unpacked {
1552 return switch (r) {
1553 .unresolved => .unresolved,
1554 .__zig_error_names => .__zig_error_names,
1555 .__zig_error_name_table => .__zig_error_name_table,
1556 .__heap_base => .__heap_base,
1557 .__heap_end => .__heap_end,
1558 _ => {
1559 const object_index = @intFromEnum(r) - first_object;
1560
1561 const uav_index = if (object_index < wasm.object_datas.items.len)
1562 return .{ .object = @enumFromInt(object_index) }
1563 else
1564 object_index - wasm.object_datas.items.len;
1565
1566 const comp = wasm.base.comp;
1567 const is_obj = comp.config.output_mode == .Obj;
1568 if (is_obj) {
1569 const nav_index = if (uav_index < wasm.uavs_obj.entries.len)
1570 return .{ .uav_obj = @enumFromInt(uav_index) }
1571 else
1572 uav_index - wasm.uavs_obj.entries.len;
1573
1574 return .{ .nav_obj = @enumFromInt(nav_index) };
1575 } else {
1576 const nav_index = if (uav_index < wasm.uavs_exe.entries.len)
1577 return .{ .uav_exe = @enumFromInt(uav_index) }
1578 else
1579 uav_index - wasm.uavs_exe.entries.len;
1580
1581 return .{ .nav_exe = @enumFromInt(nav_index) };
1582 }
1583 },
1584 };
1538 }1585 }
15391586
1540 pub fn toDataId(r: Resolution) ?DataId {1587 pub fn pack(wasm: *const Wasm, unpacked: Unpacked) Resolution {
1541 if (r == .unresolved) return null;1588 return switch (unpacked) {
1542 return @enumFromInt(@intFromEnum(r));1589 .unresolved => .unresolved,
1590 .__zig_error_names => .__zig_error_names,
1591 .__zig_error_name_table => .__zig_error_name_table,
1592 .__heap_base => .__heap_base,
1593 .__heap_end => .__heap_end,
1594 .object => |i| @enumFromInt(first_object + @intFromEnum(i)),
1595 inline .uav_exe, .uav_obj => |i| @enumFromInt(first_object + wasm.object_datas.items.len + @intFromEnum(i)),
1596 .nav_exe => |i| @enumFromInt(first_object + wasm.object_datas.items.len + wasm.uavs_exe.entries.len + @intFromEnum(i)),
1597 .nav_obj => |i| @enumFromInt(first_object + wasm.object_datas.items.len + wasm.uavs_obj.entries.len + @intFromEnum(i)),
1598 };
1543 }1599 }
15441600
1545 pub fn fromObjectDataIndex(wasm: *const Wasm, object_data_index: ObjectData.Index) Resolution {1601 pub fn fromObjectDataIndex(wasm: *const Wasm, object_data_index: ObjectData.Index) Resolution {
1546 return @enumFromInt(@intFromEnum(DataId.pack(wasm, .{ .object = object_data_index.ptr(wasm).segment })));1602 return pack(wasm, .{ .object = object_data_index });
1603 }
1604
1605 pub fn objectDataSegment(r: Resolution, wasm: *const Wasm) ?ObjectDataSegment.Index {
1606 return switch (unpack(r, wasm)) {
1607 .unresolved => unreachable,
1608 .object => |i| i.ptr(wasm).segment,
1609 .__zig_error_names,
1610 .__zig_error_name_table,
1611 .__heap_base,
1612 .__heap_end,
1613 .uav_exe,
1614 .uav_obj,
1615 .nav_exe,
1616 .nav_obj,
1617 => null,
1618 };
1619 }
1620
1621 pub fn dataLoc(r: Resolution, wasm: *const Wasm) DataLoc {
1622 return switch (unpack(r, wasm)) {
1623 .unresolved => unreachable,
1624 .object => |i| {
1625 const ptr = i.ptr(wasm);
1626 return .{
1627 .segment = .fromObjectDataSegment(wasm, ptr.segment),
1628 .offset = ptr.offset,
1629 };
1630 },
1631 .__zig_error_names => .{ .segment = .__zig_error_names, .offset = 0 },
1632 .__zig_error_name_table => .{ .segment = .__zig_error_name_table, .offset = 0 },
1633 .__heap_base => .{ .segment = .__heap_base, .offset = 0 },
1634 .__heap_end => .{ .segment = .__heap_end, .offset = 0 },
1635 .uav_exe => @panic("TODO"),
1636 .uav_obj => @panic("TODO"),
1637 .nav_exe => @panic("TODO"),
1638 .nav_obj => @panic("TODO"),
1639 };
1547 }1640 }
1548 };1641 };
15491642
...@@ -1583,7 +1676,7 @@ pub const DataPayload = extern struct {...@@ -1583,7 +1676,7 @@ pub const DataPayload = extern struct {
1583};1676};
15841677
1585/// A reference to a local or exported global const.1678/// A reference to a local or exported global const.
1586pub const DataId = enum(u32) {1679pub const DataSegmentId = enum(u32) {
1587 __zig_error_names,1680 __zig_error_names,
1588 __zig_error_name_table,1681 __zig_error_name_table,
1589 /// This and `__heap_end` are better retrieved via a global, but there is1682 /// This and `__heap_end` are better retrieved via a global, but there is
...@@ -1596,7 +1689,7 @@ pub const DataId = enum(u32) {...@@ -1596,7 +1689,7 @@ pub const DataId = enum(u32) {
1596 /// Next, index into `navs_obj` or `navs_exe` depending on whether emitting an object.1689 /// Next, index into `navs_obj` or `navs_exe` depending on whether emitting an object.
1597 _,1690 _,
15981691
1599 const first_object = @intFromEnum(DataId.__heap_end) + 1;1692 const first_object = @intFromEnum(DataSegmentId.__heap_end) + 1;
16001693
1601 pub const Category = enum {1694 pub const Category = enum {
1602 /// Thread-local variables.1695 /// Thread-local variables.
...@@ -1620,7 +1713,7 @@ pub const DataId = enum(u32) {...@@ -1620,7 +1713,7 @@ pub const DataId = enum(u32) {
1620 nav_obj: NavsObjIndex,1713 nav_obj: NavsObjIndex,
1621 };1714 };
16221715
1623 pub fn pack(wasm: *const Wasm, unpacked: Unpacked) DataId {1716 pub fn pack(wasm: *const Wasm, unpacked: Unpacked) DataSegmentId {
1624 return switch (unpacked) {1717 return switch (unpacked) {
1625 .__zig_error_names => .__zig_error_names,1718 .__zig_error_names => .__zig_error_names,
1626 .__zig_error_name_table => .__zig_error_name_table,1719 .__zig_error_name_table => .__zig_error_name_table,
...@@ -1633,7 +1726,7 @@ pub const DataId = enum(u32) {...@@ -1633,7 +1726,7 @@ pub const DataId = enum(u32) {
1633 };1726 };
1634 }1727 }
16351728
1636 pub fn unpack(id: DataId, wasm: *const Wasm) Unpacked {1729 pub fn unpack(id: DataSegmentId, wasm: *const Wasm) Unpacked {
1637 return switch (id) {1730 return switch (id) {
1638 .__zig_error_names => .__zig_error_names,1731 .__zig_error_names => .__zig_error_names,
1639 .__zig_error_name_table => .__zig_error_name_table,1732 .__zig_error_name_table => .__zig_error_name_table,
...@@ -1668,11 +1761,21 @@ pub const DataId = enum(u32) {...@@ -1668,11 +1761,21 @@ pub const DataId = enum(u32) {
1668 };1761 };
1669 }1762 }
16701763
1671 pub fn fromObjectDataSegment(wasm: *const Wasm, object_data_segment: ObjectDataSegment.Index) DataId {1764 pub fn fromNav(wasm: *const Wasm, nav_index: InternPool.Nav.Index) DataSegmentId {
1765 const comp = wasm.base.comp;
1766 const is_obj = comp.config.output_mode == .Obj;
1767 return pack(wasm, if (is_obj) .{
1768 .nav_obj = @enumFromInt(wasm.navs_obj.getIndex(nav_index).?),
1769 } else .{
1770 .nav_exe = @enumFromInt(wasm.navs_exe.getIndex(nav_index).?),
1771 });
1772 }
1773
1774 pub fn fromObjectDataSegment(wasm: *const Wasm, object_data_segment: ObjectDataSegment.Index) DataSegmentId {
1672 return pack(wasm, .{ .object = object_data_segment });1775 return pack(wasm, .{ .object = object_data_segment });
1673 }1776 }
16741777
1675 pub fn category(id: DataId, wasm: *const Wasm) Category {1778 pub fn category(id: DataSegmentId, wasm: *const Wasm) Category {
1676 return switch (unpack(id, wasm)) {1779 return switch (unpack(id, wasm)) {
1677 .__zig_error_names, .__zig_error_name_table, .__heap_base, .__heap_end => .data,1780 .__zig_error_names, .__zig_error_name_table, .__heap_base, .__heap_end => .data,
1678 .object => |i| {1781 .object => |i| {
...@@ -1693,7 +1796,7 @@ pub const DataId = enum(u32) {...@@ -1693,7 +1796,7 @@ pub const DataId = enum(u32) {
1693 };1796 };
1694 }1797 }
16951798
1696 pub fn isTls(id: DataId, wasm: *const Wasm) bool {1799 pub fn isTls(id: DataSegmentId, wasm: *const Wasm) bool {
1697 return switch (unpack(id, wasm)) {1800 return switch (unpack(id, wasm)) {
1698 .__zig_error_names, .__zig_error_name_table, .__heap_base, .__heap_end => false,1801 .__zig_error_names, .__zig_error_name_table, .__heap_base, .__heap_end => false,
1699 .object => |i| i.ptr(wasm).flags.tls,1802 .object => |i| i.ptr(wasm).flags.tls,
...@@ -1707,11 +1810,11 @@ pub const DataId = enum(u32) {...@@ -1707,11 +1810,11 @@ pub const DataId = enum(u32) {
1707 };1810 };
1708 }1811 }
17091812
1710 pub fn isBss(id: DataId, wasm: *const Wasm) bool {1813 pub fn isBss(id: DataSegmentId, wasm: *const Wasm) bool {
1711 return id.category(wasm) == .zero;1814 return id.category(wasm) == .zero;
1712 }1815 }
17131816
1714 pub fn name(id: DataId, wasm: *const Wasm) []const u8 {1817 pub fn name(id: DataSegmentId, wasm: *const Wasm) []const u8 {
1715 return switch (unpack(id, wasm)) {1818 return switch (unpack(id, wasm)) {
1716 .__zig_error_names, .__zig_error_name_table, .uav_exe, .uav_obj, .__heap_base, .__heap_end => ".data",1819 .__zig_error_names, .__zig_error_name_table, .uav_exe, .uav_obj, .__heap_base, .__heap_end => ".data",
1717 .object => |i| i.ptr(wasm).name.unwrap().?.slice(wasm),1820 .object => |i| i.ptr(wasm).name.unwrap().?.slice(wasm),
...@@ -1724,7 +1827,7 @@ pub const DataId = enum(u32) {...@@ -1724,7 +1827,7 @@ pub const DataId = enum(u32) {
1724 };1827 };
1725 }1828 }
17261829
1727 pub fn alignment(id: DataId, wasm: *const Wasm) Alignment {1830 pub fn alignment(id: DataSegmentId, wasm: *const Wasm) Alignment {
1728 return switch (unpack(id, wasm)) {1831 return switch (unpack(id, wasm)) {
1729 .__zig_error_names => .@"1",1832 .__zig_error_names => .@"1",
1730 .__zig_error_name_table, .__heap_base, .__heap_end => wasm.pointerAlignment(),1833 .__zig_error_name_table, .__heap_base, .__heap_end => wasm.pointerAlignment(),
...@@ -1752,7 +1855,7 @@ pub const DataId = enum(u32) {...@@ -1752,7 +1855,7 @@ pub const DataId = enum(u32) {
1752 };1855 };
1753 }1856 }
17541857
1755 pub fn refCount(id: DataId, wasm: *const Wasm) u32 {1858 pub fn refCount(id: DataSegmentId, wasm: *const Wasm) u32 {
1756 return switch (unpack(id, wasm)) {1859 return switch (unpack(id, wasm)) {
1757 .__zig_error_names => @intCast(wasm.error_name_offs.items.len),1860 .__zig_error_names => @intCast(wasm.error_name_offs.items.len),
1758 .__zig_error_name_table => wasm.error_name_table_ref_count,1861 .__zig_error_name_table => wasm.error_name_table_ref_count,
...@@ -1761,7 +1864,7 @@ pub const DataId = enum(u32) {...@@ -1761,7 +1864,7 @@ pub const DataId = enum(u32) {
1761 };1864 };
1762 }1865 }
17631866
1764 pub fn isPassive(id: DataId, wasm: *const Wasm) bool {1867 pub fn isPassive(id: DataSegmentId, wasm: *const Wasm) bool {
1765 const comp = wasm.base.comp;1868 const comp = wasm.base.comp;
1766 if (comp.config.import_memory and !id.isBss(wasm)) return true;1869 if (comp.config.import_memory and !id.isBss(wasm)) return true;
1767 return switch (unpack(id, wasm)) {1870 return switch (unpack(id, wasm)) {
...@@ -1771,7 +1874,7 @@ pub const DataId = enum(u32) {...@@ -1771,7 +1874,7 @@ pub const DataId = enum(u32) {
1771 };1874 };
1772 }1875 }
17731876
1774 pub fn isEmpty(id: DataId, wasm: *const Wasm) bool {1877 pub fn isEmpty(id: DataSegmentId, wasm: *const Wasm) bool {
1775 return switch (unpack(id, wasm)) {1878 return switch (unpack(id, wasm)) {
1776 .__zig_error_names, .__zig_error_name_table, .__heap_base, .__heap_end => false,1879 .__zig_error_names, .__zig_error_name_table, .__heap_base, .__heap_end => false,
1777 .object => |i| i.ptr(wasm).payload.off == .none,1880 .object => |i| i.ptr(wasm).payload.off == .none,
...@@ -1779,7 +1882,7 @@ pub const DataId = enum(u32) {...@@ -1779,7 +1882,7 @@ pub const DataId = enum(u32) {
1779 };1882 };
1780 }1883 }
17811884
1782 pub fn size(id: DataId, wasm: *const Wasm) u32 {1885 pub fn size(id: DataSegmentId, wasm: *const Wasm) u32 {
1783 return switch (unpack(id, wasm)) {1886 return switch (unpack(id, wasm)) {
1784 .__zig_error_names => @intCast(wasm.error_name_bytes.items.len),1887 .__zig_error_names => @intCast(wasm.error_name_bytes.items.len),
1785 .__zig_error_name_table => {1888 .__zig_error_name_table => {
...@@ -1796,6 +1899,38 @@ pub const DataId = enum(u32) {...@@ -1796,6 +1899,38 @@ pub const DataId = enum(u32) {
1796 }1899 }
1797};1900};
17981901
1902pub const DataLoc = struct {
1903 segment: Wasm.DataSegmentId,
1904 offset: u32,
1905
1906 pub fn fromObjectDataIndex(wasm: *const Wasm, i: Wasm.ObjectData.Index) DataLoc {
1907 const ptr = i.ptr(wasm);
1908 return .{
1909 .segment = .fromObjectDataSegment(wasm, ptr.segment),
1910 .offset = ptr.offset,
1911 };
1912 }
1913
1914 pub fn fromDataImportId(wasm: *const Wasm, id: Wasm.DataImportId) DataLoc {
1915 return switch (id.unpack(wasm)) {
1916 .object_data_import => |i| .fromObjectDataImportIndex(wasm, i),
1917 .zcu_import => |i| .fromZcuImport(wasm, i),
1918 };
1919 }
1920
1921 pub fn fromObjectDataImportIndex(wasm: *const Wasm, i: Wasm.ObjectDataImport.Index) DataLoc {
1922 return i.value(wasm).resolution.dataLoc(wasm);
1923 }
1924
1925 pub fn fromZcuImport(wasm: *const Wasm, zcu_import: ZcuImportIndex) DataLoc {
1926 const nav_index = zcu_import.ptr(wasm).*;
1927 return .{
1928 .segment = .fromNav(wasm, nav_index),
1929 .offset = 0,
1930 };
1931 }
1932};
1933
1799/// Index into `Wasm.uavs`.1934/// Index into `Wasm.uavs`.
1800pub const UavIndex = enum(u32) {1935pub const UavIndex = enum(u32) {
1801 _,1936 _,
...@@ -3330,8 +3465,8 @@ fn markDataImport(...@@ -3330,8 +3465,8 @@ fn markDataImport(
3330 } else {3465 } else {
3331 try wasm.data_imports.put(gpa, name, .fromObject(data_index, wasm));3466 try wasm.data_imports.put(gpa, name, .fromObject(data_index, wasm));
3332 }3467 }
3333 } else {3468 } else if (import.resolution.objectDataSegment(wasm)) |segment_index| {
3334 try markDataSegment(wasm, import.resolution.toDataId().?.unpack(wasm).object);3469 try markDataSegment(wasm, segment_index);
3335 }3470 }
3336}3471}
33373472
...@@ -4144,7 +4279,7 @@ pub fn uavAddr(wasm: *Wasm, uav_index: UavsExeIndex) u32 {...@@ -4144,7 +4279,7 @@ pub fn uavAddr(wasm: *Wasm, uav_index: UavsExeIndex) u32 {
4144 assert(wasm.flush_buffer.memory_layout_finished);4279 assert(wasm.flush_buffer.memory_layout_finished);
4145 const comp = wasm.base.comp;4280 const comp = wasm.base.comp;
4146 assert(comp.config.output_mode != .Obj);4281 assert(comp.config.output_mode != .Obj);
4147 const ds_id: DataId = .pack(wasm, .{ .uav_exe = uav_index });4282 const ds_id: DataSegmentId = .pack(wasm, .{ .uav_exe = uav_index });
4148 return wasm.flush_buffer.data_segments.get(ds_id).?;4283 return wasm.flush_buffer.data_segments.get(ds_id).?;
4149}4284}
41504285
...@@ -4155,7 +4290,7 @@ pub fn navAddr(wasm: *Wasm, nav_index: InternPool.Nav.Index) u32 {...@@ -4155,7 +4290,7 @@ pub fn navAddr(wasm: *Wasm, nav_index: InternPool.Nav.Index) u32 {
4155 assert(comp.config.output_mode != .Obj);4290 assert(comp.config.output_mode != .Obj);
4156 const navs_exe_index: NavsExeIndex = @enumFromInt(wasm.navs_exe.getIndex(nav_index).?);4291 const navs_exe_index: NavsExeIndex = @enumFromInt(wasm.navs_exe.getIndex(nav_index).?);
4157 log.debug("navAddr {s} {}", .{ navs_exe_index.name(wasm), nav_index });4292 log.debug("navAddr {s} {}", .{ navs_exe_index.name(wasm), nav_index });
4158 const ds_id: DataId = .pack(wasm, .{ .nav_exe = navs_exe_index });4293 const ds_id: DataSegmentId = .pack(wasm, .{ .nav_exe = navs_exe_index });
4159 return wasm.flush_buffer.data_segments.get(ds_id).?;4294 return wasm.flush_buffer.data_segments.get(ds_id).?;
4160}4295}
41614296
src/link/Wasm/Flush.zig+23-17
...@@ -22,7 +22,7 @@ const assert = std.debug.assert;...@@ -22,7 +22,7 @@ const assert = std.debug.assert;
22/// Ordered list of data segments that will appear in the final binary.22/// Ordered list of data segments that will appear in the final binary.
23/// When sorted, to-be-merged segments will be made adjacent.23/// When sorted, to-be-merged segments will be made adjacent.
24/// Values are virtual address.24/// Values are virtual address.
25data_segments: std.AutoArrayHashMapUnmanaged(Wasm.DataId, u32) = .empty,25data_segments: std.AutoArrayHashMapUnmanaged(Wasm.DataSegmentId, u32) = .empty,
26/// Each time a `data_segment` offset equals zero it indicates a new group, and26/// Each time a `data_segment` offset equals zero it indicates a new group, and
27/// the next element in this array will contain the total merged segment size.27/// the next element in this array will contain the total merged segment size.
28/// Value is the virtual memory address of the end of the segment.28/// Value is the virtual memory address of the end of the segment.
...@@ -228,7 +228,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -228,7 +228,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
228 // For the purposes of sorting, they are implicitly all named ".data".228 // For the purposes of sorting, they are implicitly all named ".data".
229 const Sort = struct {229 const Sort = struct {
230 wasm: *const Wasm,230 wasm: *const Wasm,
231 segments: []const Wasm.DataId,231 segments: []const Wasm.DataSegmentId,
232 pub fn lessThan(ctx: @This(), lhs: usize, rhs: usize) bool {232 pub fn lessThan(ctx: @This(), lhs: usize, rhs: usize) bool {
233 const lhs_segment = ctx.segments[lhs];233 const lhs_segment = ctx.segments[lhs];
234 const rhs_segment = ctx.segments[rhs];234 const rhs_segment = ctx.segments[rhs];
...@@ -311,7 +311,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -311,7 +311,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
311 const data_vaddr: u32 = @intCast(memory_ptr);311 const data_vaddr: u32 = @intCast(memory_ptr);
312 {312 {
313 var seen_tls: enum { before, during, after } = .before;313 var seen_tls: enum { before, during, after } = .before;
314 var category: Wasm.DataId.Category = undefined;314 var category: Wasm.DataSegmentId.Category = undefined;
315 for (segment_ids, segment_vaddrs, 0..) |segment_id, *segment_vaddr, i| {315 for (segment_ids, segment_vaddrs, 0..) |segment_id, *segment_vaddr, i| {
316 const alignment = segment_id.alignment(wasm);316 const alignment = segment_id.alignment(wasm);
317 category = segment_id.category(wasm);317 category = segment_id.category(wasm);
...@@ -710,7 +710,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -710,7 +710,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
710710
711 if (!is_obj) {711 if (!is_obj) {
712 for (wasm.uav_fixups.items) |uav_fixup| {712 for (wasm.uav_fixups.items) |uav_fixup| {
713 const ds_id: Wasm.DataId = .pack(wasm, .{ .uav_exe = uav_fixup.uavs_exe_index });713 const ds_id: Wasm.DataSegmentId = .pack(wasm, .{ .uav_exe = uav_fixup.uavs_exe_index });
714 const vaddr = f.data_segments.get(ds_id).?;714 const vaddr = f.data_segments.get(ds_id).?;
715 if (!is64) {715 if (!is64) {
716 mem.writeInt(u32, wasm.string_bytes.items[uav_fixup.offset..][0..4], vaddr, .little);716 mem.writeInt(u32, wasm.string_bytes.items[uav_fixup.offset..][0..4], vaddr, .little);
...@@ -719,7 +719,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -719,7 +719,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
719 }719 }
720 }720 }
721 for (wasm.nav_fixups.items) |nav_fixup| {721 for (wasm.nav_fixups.items) |nav_fixup| {
722 const ds_id: Wasm.DataId = .pack(wasm, .{ .nav_exe = nav_fixup.navs_exe_index });722 const ds_id: Wasm.DataSegmentId = .pack(wasm, .{ .nav_exe = nav_fixup.navs_exe_index });
723 const vaddr = f.data_segments.get(ds_id).?;723 const vaddr = f.data_segments.get(ds_id).?;
724 if (!is64) {724 if (!is64) {
725 mem.writeInt(u32, wasm.string_bytes.items[nav_fixup.offset..][0..4], vaddr, .little);725 mem.writeInt(u32, wasm.string_bytes.items[nav_fixup.offset..][0..4], vaddr, .little);
...@@ -867,7 +867,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -867,7 +867,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
867867
868fn emitNameSection(868fn emitNameSection(
869 wasm: *Wasm,869 wasm: *Wasm,
870 data_segments: *const std.AutoArrayHashMapUnmanaged(Wasm.DataId, u32),870 data_segments: *const std.AutoArrayHashMapUnmanaged(Wasm.DataSegmentId, u32),
871 binary_bytes: *std.ArrayListUnmanaged(u8),871 binary_bytes: *std.ArrayListUnmanaged(u8),
872) !void {872) !void {
873 const f = &wasm.flush_buffer;873 const f = &wasm.flush_buffer;
...@@ -1142,9 +1142,9 @@ fn splitSegmentName(name: []const u8) struct { []const u8, []const u8 } {...@@ -1142,9 +1142,9 @@ fn splitSegmentName(name: []const u8) struct { []const u8, []const u8 } {
11421142
1143fn wantSegmentMerge(1143fn wantSegmentMerge(
1144 wasm: *const Wasm,1144 wasm: *const Wasm,
1145 a_id: Wasm.DataId,1145 a_id: Wasm.DataSegmentId,
1146 b_id: Wasm.DataId,1146 b_id: Wasm.DataSegmentId,
1147 b_category: Wasm.DataId.Category,1147 b_category: Wasm.DataSegmentId.Category,
1148) bool {1148) bool {
1149 const a_category = a_id.category(wasm);1149 const a_category = a_id.category(wasm);
1150 if (a_category != b_category) return false;1150 if (a_category != b_category) return false;
...@@ -1519,17 +1519,23 @@ const RelocAddr = struct {...@@ -1519,17 +1519,23 @@ const RelocAddr = struct {
1519 addr: u32,1519 addr: u32,
15201520
1521 fn fromObjectData(wasm: *const Wasm, i: Wasm.ObjectData.Index, addend: i32) RelocAddr {1521 fn fromObjectData(wasm: *const Wasm, i: Wasm.ObjectData.Index, addend: i32) RelocAddr {
1522 const ptr = i.ptr(wasm);1522 return fromDataLoc(&wasm.flush_buffer, .fromObjectDataIndex(wasm, i), addend);
1523 const f = &wasm.flush_buffer;
1524 const addr = f.data_segments.get(.fromObjectDataSegment(wasm, ptr.segment)).?;
1525 return .{ .addr = @intCast(@as(i64, addr) + addend) };
1526 }1523 }
15271524
1528 fn fromSymbolName(wasm: *const Wasm, name: String, addend: i32) RelocAddr {1525 fn fromSymbolName(wasm: *const Wasm, name: String, addend: i32) RelocAddr {
1529 _ = wasm;1526 const flush = &wasm.flush_buffer;
1530 _ = name;1527 if (wasm.object_data_imports.getPtr(name)) |import| {
1531 _ = addend;1528 return fromDataLoc(flush, import.resolution.dataLoc(wasm), addend);
1532 @panic("TODO implement data symbol resolution");1529 } else if (wasm.data_imports.get(name)) |id| {
1530 return fromDataLoc(flush, .fromDataImportId(wasm, id), addend);
1531 } else {
1532 unreachable;
1533 }
1534 }
1535
1536 fn fromDataLoc(flush: *const Flush, data_loc: Wasm.DataLoc, addend: i32) RelocAddr {
1537 const base_addr: i64 = flush.data_segments.get(data_loc.segment).?;
1538 return .{ .addr = @intCast(base_addr + data_loc.offset + addend) };
1533 }1539 }
1534};1540};
15351541