| ... | @@ -123,9 +123,10 @@ object_init_funcs: std.ArrayListUnmanaged(InitFunc) = .empty, | ... | @@ -123,9 +123,10 @@ object_init_funcs: std.ArrayListUnmanaged(InitFunc) = .empty, |
| 123 | /// logically to an object file's .data section, or .rodata section. In | 123 | /// logically to an object file's .data section, or .rodata section. In |
| 124 | /// the case of `-fdata-sections` there will be one segment per data symbol. | 124 | /// the case of `-fdata-sections` there will be one segment per data symbol. |
| 125 | object_data_segments: std.ArrayListUnmanaged(ObjectDataSegment) = .empty, | 125 | object_data_segments: std.ArrayListUnmanaged(ObjectDataSegment) = .empty, |
| 126 | /// Each segment has many data symbols. These correspond logically to global | 126 | /// Each segment has many data symbols, which correspond logically to global |
| 127 | /// constants. | 127 | /// constants. |
| 128 | object_datas: std.ArrayListUnmanaged(ObjectData) = .empty, | 128 | object_datas: std.ArrayListUnmanaged(ObjectData) = .empty, |
| | 129 | object_data_imports: std.AutoArrayHashMapUnmanaged(String, ObjectDataImport) = .empty, |
| 129 | /// Non-synthetic section that can essentially be mem-cpy'd into place after performing relocations. | 130 | /// Non-synthetic section that can essentially be mem-cpy'd into place after performing relocations. |
| 130 | object_custom_segments: std.AutoArrayHashMapUnmanaged(ObjectSectionIndex, CustomSegment) = .empty, | 131 | object_custom_segments: std.AutoArrayHashMapUnmanaged(ObjectSectionIndex, CustomSegment) = .empty, |
| 131 | | 132 | |
| ... | @@ -227,6 +228,22 @@ functions_end_prelink: u32 = 0, | ... | @@ -227,6 +228,22 @@ functions_end_prelink: u32 = 0, |
| 227 | /// symbol errors, or import section entries depending on the output mode. | 228 | /// symbol errors, or import section entries depending on the output mode. |
| 228 | function_imports: std.AutoArrayHashMapUnmanaged(String, FunctionImportId) = .empty, | 229 | function_imports: std.AutoArrayHashMapUnmanaged(String, FunctionImportId) = .empty, |
| 229 | | 230 | |
| | 231 | /// At the end of prelink, this is populated with data symbols needed by |
| | 232 | /// objects. |
| | 233 | /// |
| | 234 | /// During the Zcu phase, entries are not deleted from this table |
| | 235 | /// because doing so would be irreversible when a `deleteExport` call is |
| | 236 | /// handled. However, entries are added during the Zcu phase when extern |
| | 237 | /// functions are passed to `updateNav`. |
| | 238 | /// |
| | 239 | /// `flush` gets a copy of this table, and then Zcu exports are applied to |
| | 240 | /// remove elements from the table, and the remainder are either undefined |
| | 241 | /// symbol errors, or symbol table entries depending on the output mode. |
| | 242 | data_imports: std.AutoArrayHashMapUnmanaged(String, DataImportId) = .empty, |
| | 243 | /// Set of data symbols that will appear in the final binary. Used to populate |
| | 244 | /// `Flush.data_segments` before sorting. |
| | 245 | data_segments: std.AutoArrayHashMapUnmanaged(DataId, void) = .empty, |
| | 246 | |
| 230 | /// 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. |
| 231 | /// Empty until prelink. | 248 | /// Empty until prelink. |
| 232 | globals: std.AutoArrayHashMapUnmanaged(GlobalImport.Resolution, void) = .empty, | 249 | globals: std.AutoArrayHashMapUnmanaged(GlobalImport.Resolution, void) = .empty, |
| ... | @@ -251,6 +268,7 @@ error_name_table_ref_count: u32 = 0, | ... | @@ -251,6 +268,7 @@ error_name_table_ref_count: u32 = 0, |
| 251 | /// value must be this OR'd with the same logic for zig functions | 268 | /// value must be this OR'd with the same logic for zig functions |
| 252 | /// (set to true if any threadlocal global is used). | 269 | /// (set to true if any threadlocal global is used). |
| 253 | any_tls_relocs: bool = false, | 270 | any_tls_relocs: bool = false, |
| | 271 | any_passive_inits: bool = false, |
| 254 | | 272 | |
| 255 | /// All MIR instructions for all Zcu functions. | 273 | /// All MIR instructions for all Zcu functions. |
| 256 | mir_instructions: std.MultiArrayList(Mir.Inst) = .{}, | 274 | mir_instructions: std.MultiArrayList(Mir.Inst) = .{}, |
| ... | @@ -1499,6 +1517,50 @@ pub const ObjectData = extern struct { | ... | @@ -1499,6 +1517,50 @@ pub const ObjectData = extern struct { |
| 1499 | }; | 1517 | }; |
| 1500 | }; | 1518 | }; |
| 1501 | | 1519 | |
| | 1520 | pub const ObjectDataImport = extern struct { |
| | 1521 | resolution: Resolution, |
| | 1522 | flags: SymbolFlags, |
| | 1523 | source_location: SourceLocation, |
| | 1524 | |
| | 1525 | pub const Resolution = enum(u32) { |
| | 1526 | __zig_error_names, |
| | 1527 | __zig_error_name_table, |
| | 1528 | __heap_base, |
| | 1529 | __heap_end, |
| | 1530 | unresolved = std.math.maxInt(u32), |
| | 1531 | _, |
| | 1532 | |
| | 1533 | comptime { |
| | 1534 | assert(@intFromEnum(Resolution.__zig_error_names) == @intFromEnum(DataId.__zig_error_names)); |
| | 1535 | assert(@intFromEnum(Resolution.__zig_error_name_table) == @intFromEnum(DataId.__zig_error_name_table)); |
| | 1536 | assert(@intFromEnum(Resolution.__heap_base) == @intFromEnum(DataId.__heap_base)); |
| | 1537 | assert(@intFromEnum(Resolution.__heap_end) == @intFromEnum(DataId.__heap_end)); |
| | 1538 | } |
| | 1539 | |
| | 1540 | pub fn toDataId(r: Resolution) ?DataId { |
| | 1541 | if (r == .unresolved) return null; |
| | 1542 | return @enumFromInt(@intFromEnum(r)); |
| | 1543 | } |
| | 1544 | |
| | 1545 | 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 }))); |
| | 1547 | } |
| | 1548 | }; |
| | 1549 | |
| | 1550 | /// Points into `Wasm.object_data_imports`. |
| | 1551 | pub const Index = enum(u32) { |
| | 1552 | _, |
| | 1553 | |
| | 1554 | pub fn value(i: @This(), wasm: *const Wasm) *ObjectDataImport { |
| | 1555 | return &wasm.object_data_imports.values()[@intFromEnum(i)]; |
| | 1556 | } |
| | 1557 | |
| | 1558 | pub fn fromSymbolName(wasm: *const Wasm, name: String) ?Index { |
| | 1559 | return @enumFromInt(wasm.object_data_imports.getIndex(name) orelse return null); |
| | 1560 | } |
| | 1561 | }; |
| | 1562 | }; |
| | 1563 | |
| 1502 | pub const DataPayload = extern struct { | 1564 | pub const DataPayload = extern struct { |
| 1503 | off: Off, | 1565 | off: Off, |
| 1504 | /// The size in bytes of the data representing the segment within the section. | 1566 | /// The size in bytes of the data representing the segment within the section. |
| ... | @@ -1524,12 +1586,17 @@ pub const DataPayload = extern struct { | ... | @@ -1524,12 +1586,17 @@ pub const DataPayload = extern struct { |
| 1524 | pub const DataId = enum(u32) { | 1586 | pub const DataId = enum(u32) { |
| 1525 | __zig_error_names, | 1587 | __zig_error_names, |
| 1526 | __zig_error_name_table, | 1588 | __zig_error_name_table, |
| | 1589 | /// This and `__heap_end` are better retrieved via a global, but there is |
| | 1590 | /// some suboptimal code out there (wasi libc) that additionally needs them |
| | 1591 | /// as data symbols. |
| | 1592 | __heap_base, |
| | 1593 | __heap_end, |
| 1527 | /// First, an `ObjectDataSegment.Index`. | 1594 | /// First, an `ObjectDataSegment.Index`. |
| 1528 | /// Next, index into `uavs_obj` or `uavs_exe` depending on whether emitting an object. | 1595 | /// Next, index into `uavs_obj` or `uavs_exe` depending on whether emitting an object. |
| 1529 | /// Next, index into `navs_obj` or `navs_exe` depending on whether emitting an object. | 1596 | /// Next, index into `navs_obj` or `navs_exe` depending on whether emitting an object. |
| 1530 | _, | 1597 | _, |
| 1531 | | 1598 | |
| 1532 | const first_object = @intFromEnum(DataId.__zig_error_name_table) + 1; | 1599 | const first_object = @intFromEnum(DataId.__heap_end) + 1; |
| 1533 | | 1600 | |
| 1534 | pub const Category = enum { | 1601 | pub const Category = enum { |
| 1535 | /// Thread-local variables. | 1602 | /// Thread-local variables. |
| ... | @@ -1544,6 +1611,8 @@ pub const DataId = enum(u32) { | ... | @@ -1544,6 +1611,8 @@ pub const DataId = enum(u32) { |
| 1544 | pub const Unpacked = union(enum) { | 1611 | pub const Unpacked = union(enum) { |
| 1545 | __zig_error_names, | 1612 | __zig_error_names, |
| 1546 | __zig_error_name_table, | 1613 | __zig_error_name_table, |
| | 1614 | __heap_base, |
| | 1615 | __heap_end, |
| 1547 | object: ObjectDataSegment.Index, | 1616 | object: ObjectDataSegment.Index, |
| 1548 | uav_exe: UavsExeIndex, | 1617 | uav_exe: UavsExeIndex, |
| 1549 | uav_obj: UavsObjIndex, | 1618 | uav_obj: UavsObjIndex, |
| ... | @@ -1555,6 +1624,8 @@ pub const DataId = enum(u32) { | ... | @@ -1555,6 +1624,8 @@ pub const DataId = enum(u32) { |
| 1555 | return switch (unpacked) { | 1624 | return switch (unpacked) { |
| 1556 | .__zig_error_names => .__zig_error_names, | 1625 | .__zig_error_names => .__zig_error_names, |
| 1557 | .__zig_error_name_table => .__zig_error_name_table, | 1626 | .__zig_error_name_table => .__zig_error_name_table, |
| | 1627 | .__heap_base => .__heap_base, |
| | 1628 | .__heap_end => .__heap_end, |
| 1558 | .object => |i| @enumFromInt(first_object + @intFromEnum(i)), | 1629 | .object => |i| @enumFromInt(first_object + @intFromEnum(i)), |
| 1559 | inline .uav_exe, .uav_obj => |i| @enumFromInt(first_object + wasm.object_data_segments.items.len + @intFromEnum(i)), | 1630 | inline .uav_exe, .uav_obj => |i| @enumFromInt(first_object + wasm.object_data_segments.items.len + @intFromEnum(i)), |
| 1560 | .nav_exe => |i| @enumFromInt(first_object + wasm.object_data_segments.items.len + wasm.uavs_exe.entries.len + @intFromEnum(i)), | 1631 | .nav_exe => |i| @enumFromInt(first_object + wasm.object_data_segments.items.len + wasm.uavs_exe.entries.len + @intFromEnum(i)), |
| ... | @@ -1566,6 +1637,8 @@ pub const DataId = enum(u32) { | ... | @@ -1566,6 +1637,8 @@ pub const DataId = enum(u32) { |
| 1566 | return switch (id) { | 1637 | return switch (id) { |
| 1567 | .__zig_error_names => .__zig_error_names, | 1638 | .__zig_error_names => .__zig_error_names, |
| 1568 | .__zig_error_name_table => .__zig_error_name_table, | 1639 | .__zig_error_name_table => .__zig_error_name_table, |
| | 1640 | .__heap_base => .__heap_base, |
| | 1641 | .__heap_end => .__heap_end, |
| 1569 | _ => { | 1642 | _ => { |
| 1570 | const object_index = @intFromEnum(id) - first_object; | 1643 | const object_index = @intFromEnum(id) - first_object; |
| 1571 | | 1644 | |
| ... | @@ -1601,7 +1674,7 @@ pub const DataId = enum(u32) { | ... | @@ -1601,7 +1674,7 @@ pub const DataId = enum(u32) { |
| 1601 | | 1674 | |
| 1602 | pub fn category(id: DataId, wasm: *const Wasm) Category { | 1675 | pub fn category(id: DataId, wasm: *const Wasm) Category { |
| 1603 | return switch (unpack(id, wasm)) { | 1676 | return switch (unpack(id, wasm)) { |
| 1604 | .__zig_error_names, .__zig_error_name_table => .data, | 1677 | .__zig_error_names, .__zig_error_name_table, .__heap_base, .__heap_end => .data, |
| 1605 | .object => |i| { | 1678 | .object => |i| { |
| 1606 | const ptr = i.ptr(wasm); | 1679 | const ptr = i.ptr(wasm); |
| 1607 | if (ptr.flags.tls) return .tls; | 1680 | if (ptr.flags.tls) return .tls; |
| ... | @@ -1622,7 +1695,7 @@ pub const DataId = enum(u32) { | ... | @@ -1622,7 +1695,7 @@ pub const DataId = enum(u32) { |
| 1622 | | 1695 | |
| 1623 | pub fn isTls(id: DataId, wasm: *const Wasm) bool { | 1696 | pub fn isTls(id: DataId, wasm: *const Wasm) bool { |
| 1624 | return switch (unpack(id, wasm)) { | 1697 | return switch (unpack(id, wasm)) { |
| 1625 | .__zig_error_names, .__zig_error_name_table => false, | 1698 | .__zig_error_names, .__zig_error_name_table, .__heap_base, .__heap_end => false, |
| 1626 | .object => |i| i.ptr(wasm).flags.tls, | 1699 | .object => |i| i.ptr(wasm).flags.tls, |
| 1627 | .uav_exe, .uav_obj => false, | 1700 | .uav_exe, .uav_obj => false, |
| 1628 | inline .nav_exe, .nav_obj => |i| { | 1701 | inline .nav_exe, .nav_obj => |i| { |
| ... | @@ -1640,7 +1713,7 @@ pub const DataId = enum(u32) { | ... | @@ -1640,7 +1713,7 @@ pub const DataId = enum(u32) { |
| 1640 | | 1713 | |
| 1641 | pub fn name(id: DataId, wasm: *const Wasm) []const u8 { | 1714 | pub fn name(id: DataId, wasm: *const Wasm) []const u8 { |
| 1642 | return switch (unpack(id, wasm)) { | 1715 | return switch (unpack(id, wasm)) { |
| 1643 | .__zig_error_names, .__zig_error_name_table, .uav_exe, .uav_obj => ".data", | 1716 | .__zig_error_names, .__zig_error_name_table, .uav_exe, .uav_obj, .__heap_base, .__heap_end => ".data", |
| 1644 | .object => |i| i.ptr(wasm).name.unwrap().?.slice(wasm), | 1717 | .object => |i| i.ptr(wasm).name.unwrap().?.slice(wasm), |
| 1645 | inline .nav_exe, .nav_obj => |i| { | 1718 | inline .nav_exe, .nav_obj => |i| { |
| 1646 | const zcu = wasm.base.comp.zcu.?; | 1719 | const zcu = wasm.base.comp.zcu.?; |
| ... | @@ -1654,7 +1727,7 @@ pub const DataId = enum(u32) { | ... | @@ -1654,7 +1727,7 @@ pub const DataId = enum(u32) { |
| 1654 | pub fn alignment(id: DataId, wasm: *const Wasm) Alignment { | 1727 | pub fn alignment(id: DataId, wasm: *const Wasm) Alignment { |
| 1655 | return switch (unpack(id, wasm)) { | 1728 | return switch (unpack(id, wasm)) { |
| 1656 | .__zig_error_names => .@"1", | 1729 | .__zig_error_names => .@"1", |
| 1657 | .__zig_error_name_table => wasm.pointerAlignment(), | 1730 | .__zig_error_name_table, .__heap_base, .__heap_end => wasm.pointerAlignment(), |
| 1658 | .object => |i| i.ptr(wasm).flags.alignment, | 1731 | .object => |i| i.ptr(wasm).flags.alignment, |
| 1659 | inline .uav_exe, .uav_obj => |i| { | 1732 | inline .uav_exe, .uav_obj => |i| { |
| 1660 | const zcu = wasm.base.comp.zcu.?; | 1733 | const zcu = wasm.base.comp.zcu.?; |
| ... | @@ -1683,7 +1756,7 @@ pub const DataId = enum(u32) { | ... | @@ -1683,7 +1756,7 @@ pub const DataId = enum(u32) { |
| 1683 | return switch (unpack(id, wasm)) { | 1756 | return switch (unpack(id, wasm)) { |
| 1684 | .__zig_error_names => @intCast(wasm.error_name_offs.items.len), | 1757 | .__zig_error_names => @intCast(wasm.error_name_offs.items.len), |
| 1685 | .__zig_error_name_table => wasm.error_name_table_ref_count, | 1758 | .__zig_error_name_table => wasm.error_name_table_ref_count, |
| 1686 | .object, .uav_obj, .nav_obj => 0, | 1759 | .object, .uav_obj, .nav_obj, .__heap_base, .__heap_end => 0, |
| 1687 | inline .uav_exe, .nav_exe => |i| i.value(wasm).count, | 1760 | inline .uav_exe, .nav_exe => |i| i.value(wasm).count, |
| 1688 | }; | 1761 | }; |
| 1689 | } | 1762 | } |
| ... | @@ -1692,7 +1765,7 @@ pub const DataId = enum(u32) { | ... | @@ -1692,7 +1765,7 @@ pub const DataId = enum(u32) { |
| 1692 | const comp = wasm.base.comp; | 1765 | const comp = wasm.base.comp; |
| 1693 | if (comp.config.import_memory and !id.isBss(wasm)) return true; | 1766 | if (comp.config.import_memory and !id.isBss(wasm)) return true; |
| 1694 | return switch (unpack(id, wasm)) { | 1767 | return switch (unpack(id, wasm)) { |
| 1695 | .__zig_error_names, .__zig_error_name_table => false, | 1768 | .__zig_error_names, .__zig_error_name_table, .__heap_base, .__heap_end => false, |
| 1696 | .object => |i| i.ptr(wasm).flags.is_passive, | 1769 | .object => |i| i.ptr(wasm).flags.is_passive, |
| 1697 | .uav_exe, .uav_obj, .nav_exe, .nav_obj => false, | 1770 | .uav_exe, .uav_obj, .nav_exe, .nav_obj => false, |
| 1698 | }; | 1771 | }; |
| ... | @@ -1700,7 +1773,7 @@ pub const DataId = enum(u32) { | ... | @@ -1700,7 +1773,7 @@ pub const DataId = enum(u32) { |
| 1700 | | 1773 | |
| 1701 | pub fn isEmpty(id: DataId, wasm: *const Wasm) bool { | 1774 | pub fn isEmpty(id: DataId, wasm: *const Wasm) bool { |
| 1702 | return switch (unpack(id, wasm)) { | 1775 | return switch (unpack(id, wasm)) { |
| 1703 | .__zig_error_names, .__zig_error_name_table => false, | 1776 | .__zig_error_names, .__zig_error_name_table, .__heap_base, .__heap_end => false, |
| 1704 | .object => |i| i.ptr(wasm).payload.off == .none, | 1777 | .object => |i| i.ptr(wasm).payload.off == .none, |
| 1705 | inline .uav_exe, .uav_obj, .nav_exe, .nav_obj => |i| i.value(wasm).code.off == .none, | 1778 | inline .uav_exe, .uav_obj, .nav_exe, .nav_obj => |i| i.value(wasm).code.off == .none, |
| 1706 | }; | 1779 | }; |
| ... | @@ -1716,6 +1789,7 @@ pub const DataId = enum(u32) { | ... | @@ -1716,6 +1789,7 @@ pub const DataId = enum(u32) { |
| 1716 | const elem_size = ZcuType.slice_const_u8_sentinel_0.abiSize(zcu); | 1789 | const elem_size = ZcuType.slice_const_u8_sentinel_0.abiSize(zcu); |
| 1717 | return @intCast(errors_len * elem_size); | 1790 | return @intCast(errors_len * elem_size); |
| 1718 | }, | 1791 | }, |
| | 1792 | .__heap_base, .__heap_end => wasm.pointerSize(), |
| 1719 | .object => |i| i.ptr(wasm).payload.len, | 1793 | .object => |i| i.ptr(wasm).payload.len, |
| 1720 | inline .uav_exe, .uav_obj, .nav_exe, .nav_obj => |i| i.value(wasm).code.len, | 1794 | inline .uav_exe, .uav_obj, .nav_exe, .nav_obj => |i| i.value(wasm).code.len, |
| 1721 | }; | 1795 | }; |
| ... | @@ -2110,6 +2184,55 @@ pub const GlobalImportId = enum(u32) { | ... | @@ -2110,6 +2184,55 @@ pub const GlobalImportId = enum(u32) { |
| 2110 | } | 2184 | } |
| 2111 | }; | 2185 | }; |
| 2112 | | 2186 | |
| | 2187 | /// 0. Index into `Wasm.object_data_imports`. |
| | 2188 | /// 1. Index into `Wasm.imports`. |
| | 2189 | pub const DataImportId = enum(u32) { |
| | 2190 | _, |
| | 2191 | |
| | 2192 | pub const Unpacked = union(enum) { |
| | 2193 | object_data_import: ObjectDataImport.Index, |
| | 2194 | zcu_import: ZcuImportIndex, |
| | 2195 | }; |
| | 2196 | |
| | 2197 | pub fn pack(unpacked: Unpacked, wasm: *const Wasm) DataImportId { |
| | 2198 | return switch (unpacked) { |
| | 2199 | .object_data_import => |i| @enumFromInt(@intFromEnum(i)), |
| | 2200 | .zcu_import => |i| @enumFromInt(@intFromEnum(i) - wasm.object_data_imports.entries.len), |
| | 2201 | }; |
| | 2202 | } |
| | 2203 | |
| | 2204 | pub fn unpack(id: DataImportId, wasm: *const Wasm) Unpacked { |
| | 2205 | const i = @intFromEnum(id); |
| | 2206 | if (i < wasm.object_data_imports.entries.len) return .{ .object_data_import = @enumFromInt(i) }; |
| | 2207 | const zcu_import_i = i - wasm.object_data_imports.entries.len; |
| | 2208 | return .{ .zcu_import = @enumFromInt(zcu_import_i) }; |
| | 2209 | } |
| | 2210 | |
| | 2211 | pub fn fromZcuImport(zcu_import: ZcuImportIndex, wasm: *const Wasm) DataImportId { |
| | 2212 | return pack(.{ .zcu_import = zcu_import }, wasm); |
| | 2213 | } |
| | 2214 | |
| | 2215 | pub fn fromObject(object_data_import: ObjectDataImport.Index, wasm: *const Wasm) DataImportId { |
| | 2216 | return pack(.{ .object_data_import = object_data_import }, wasm); |
| | 2217 | } |
| | 2218 | |
| | 2219 | pub fn sourceLocation(id: DataImportId, wasm: *const Wasm) SourceLocation { |
| | 2220 | switch (id.unpack(wasm)) { |
| | 2221 | .object_data_import => |obj_data_index| { |
| | 2222 | // TODO binary search |
| | 2223 | for (wasm.objects.items, 0..) |o, i| { |
| | 2224 | if (o.data_imports.off <= @intFromEnum(obj_data_index) and |
| | 2225 | o.data_imports.off + o.data_imports.len > @intFromEnum(obj_data_index)) |
| | 2226 | { |
| | 2227 | return .pack(.{ .object_index = @enumFromInt(i) }, wasm); |
| | 2228 | } |
| | 2229 | } else unreachable; |
| | 2230 | }, |
| | 2231 | .zcu_import => return .zig_object_nofile, // TODO give a better source location |
| | 2232 | } |
| | 2233 | } |
| | 2234 | }; |
| | 2235 | |
| 2113 | /// Index into `Wasm.symbol_table`. | 2236 | /// Index into `Wasm.symbol_table`. |
| 2114 | pub const SymbolTableIndex = enum(u32) { | 2237 | pub const SymbolTableIndex = enum(u32) { |
| 2115 | _, | 2238 | _, |
| ... | @@ -2716,6 +2839,7 @@ pub fn deinit(wasm: *Wasm) void { | ... | @@ -2716,6 +2839,7 @@ pub fn deinit(wasm: *Wasm) void { |
| 2716 | wasm.object_memory_imports.deinit(gpa); | 2839 | wasm.object_memory_imports.deinit(gpa); |
| 2717 | wasm.object_memories.deinit(gpa); | 2840 | wasm.object_memories.deinit(gpa); |
| 2718 | wasm.object_relocations.deinit(gpa); | 2841 | wasm.object_relocations.deinit(gpa); |
| | 2842 | wasm.object_data_imports.deinit(gpa); |
| 2719 | wasm.object_data_segments.deinit(gpa); | 2843 | wasm.object_data_segments.deinit(gpa); |
| 2720 | wasm.object_datas.deinit(gpa); | 2844 | wasm.object_datas.deinit(gpa); |
| 2721 | wasm.object_custom_segments.deinit(gpa); | 2845 | wasm.object_custom_segments.deinit(gpa); |
| ... | @@ -2734,6 +2858,8 @@ pub fn deinit(wasm: *Wasm) void { | ... | @@ -2734,6 +2858,8 @@ pub fn deinit(wasm: *Wasm) void { |
| 2734 | wasm.global_imports.deinit(gpa); | 2858 | wasm.global_imports.deinit(gpa); |
| 2735 | wasm.table_imports.deinit(gpa); | 2859 | wasm.table_imports.deinit(gpa); |
| 2736 | wasm.tables.deinit(gpa); | 2860 | wasm.tables.deinit(gpa); |
| | 2861 | wasm.data_imports.deinit(gpa); |
| | 2862 | wasm.data_segments.deinit(gpa); |
| 2737 | wasm.symbol_table.deinit(gpa); | 2863 | wasm.symbol_table.deinit(gpa); |
| 2738 | wasm.out_relocs.deinit(gpa); | 2864 | wasm.out_relocs.deinit(gpa); |
| 2739 | wasm.uav_fixups.deinit(gpa); | 2865 | wasm.uav_fixups.deinit(gpa); |
| ... | @@ -2805,15 +2931,16 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index | ... | @@ -2805,15 +2931,16 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index |
| 2805 | const name = try wasm.internString(ext.name.toSlice(ip)); | 2931 | const name = try wasm.internString(ext.name.toSlice(ip)); |
| 2806 | if (ext.lib_name.toSlice(ip)) |ext_name| _ = try wasm.internString(ext_name); | 2932 | if (ext.lib_name.toSlice(ip)) |ext_name| _ = try wasm.internString(ext_name); |
| 2807 | try wasm.imports.ensureUnusedCapacity(gpa, 1); | 2933 | try wasm.imports.ensureUnusedCapacity(gpa, 1); |
| | 2934 | try wasm.function_imports.ensureUnusedCapacity(gpa, 1); |
| | 2935 | try wasm.data_imports.ensureUnusedCapacity(gpa, 1); |
| | 2936 | const zcu_import = wasm.addZcuImportReserved(ext.owner_nav); |
| 2808 | if (ip.isFunctionType(nav.typeOf(ip))) { | 2937 | if (ip.isFunctionType(nav.typeOf(ip))) { |
| 2809 | try wasm.function_imports.ensureUnusedCapacity(gpa, 1); | | |
| 2810 | const zcu_import = wasm.addZcuImportReserved(ext.owner_nav); | | |
| 2811 | wasm.function_imports.putAssumeCapacity(name, .fromZcuImport(zcu_import, wasm)); | 2938 | wasm.function_imports.putAssumeCapacity(name, .fromZcuImport(zcu_import, wasm)); |
| 2812 | // Ensure there is a corresponding function type table entry. | 2939 | // Ensure there is a corresponding function type table entry. |
| 2813 | const fn_info = zcu.typeToFunc(.fromInterned(ext.ty)).?; | 2940 | const fn_info = zcu.typeToFunc(.fromInterned(ext.ty)).?; |
| 2814 | _ = try internFunctionType(wasm, fn_info.cc, fn_info.param_types.get(ip), .fromInterned(fn_info.return_type), target); | 2941 | _ = try internFunctionType(wasm, fn_info.cc, fn_info.param_types.get(ip), .fromInterned(fn_info.return_type), target); |
| 2815 | } else { | 2942 | } else { |
| 2816 | @panic("TODO extern data"); | 2943 | wasm.data_imports.putAssumeCapacity(name, .fromZcuImport(zcu_import, wasm)); |
| 2817 | } | 2944 | } |
| 2818 | return; | 2945 | return; |
| 2819 | }, | 2946 | }, |
| ... | @@ -3023,6 +3150,12 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.File.FlushError!v | ... | @@ -3023,6 +3150,12 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.File.FlushError!v |
| 3023 | try markTableImport(wasm, name, import, @enumFromInt(i)); | 3150 | try markTableImport(wasm, name, import, @enumFromInt(i)); |
| 3024 | } | 3151 | } |
| 3025 | } | 3152 | } |
| | 3153 | |
| | 3154 | for (wasm.object_data_imports.keys(), wasm.object_data_imports.values(), 0..) |name, *import, i| { |
| | 3155 | if (import.flags.isIncluded(rdynamic)) { |
| | 3156 | try markDataImport(wasm, name, import, @enumFromInt(i)); |
| | 3157 | } |
| | 3158 | } |
| 3026 | } | 3159 | } |
| 3027 | | 3160 | |
| 3028 | fn markFunctionImport( | 3161 | fn markFunctionImport( |
| ... | @@ -3163,13 +3296,45 @@ fn markTableImport( | ... | @@ -3163,13 +3296,45 @@ fn markTableImport( |
| 3163 | } | 3296 | } |
| 3164 | | 3297 | |
| 3165 | fn markDataSegment(wasm: *Wasm, segment_index: ObjectDataSegment.Index) link.File.FlushError!void { | 3298 | fn markDataSegment(wasm: *Wasm, segment_index: ObjectDataSegment.Index) link.File.FlushError!void { |
| | 3299 | const comp = wasm.base.comp; |
| 3166 | const segment = segment_index.ptr(wasm); | 3300 | const segment = segment_index.ptr(wasm); |
| 3167 | if (segment.flags.alive) return; | 3301 | if (segment.flags.alive) return; |
| 3168 | segment.flags.alive = true; | 3302 | segment.flags.alive = true; |
| 3169 | | 3303 | |
| | 3304 | wasm.any_passive_inits = wasm.any_passive_inits or segment.flags.is_passive or |
| | 3305 | (comp.config.import_memory and !wasm.isBss(segment.name)); |
| | 3306 | |
| | 3307 | try wasm.data_segments.put(comp.gpa, .pack(wasm, .{ .object = segment_index }), {}); |
| 3170 | try wasm.markRelocations(segment.relocations(wasm)); | 3308 | try wasm.markRelocations(segment.relocations(wasm)); |
| 3171 | } | 3309 | } |
| 3172 | | 3310 | |
| | 3311 | fn markDataImport( |
| | 3312 | wasm: *Wasm, |
| | 3313 | name: String, |
| | 3314 | import: *ObjectDataImport, |
| | 3315 | data_index: ObjectDataImport.Index, |
| | 3316 | ) link.File.FlushError!void { |
| | 3317 | if (import.flags.alive) return; |
| | 3318 | import.flags.alive = true; |
| | 3319 | |
| | 3320 | const comp = wasm.base.comp; |
| | 3321 | const gpa = comp.gpa; |
| | 3322 | |
| | 3323 | if (import.resolution == .unresolved) { |
| | 3324 | if (name == wasm.preloaded_strings.__heap_base) { |
| | 3325 | import.resolution = .__heap_base; |
| | 3326 | wasm.data_segments.putAssumeCapacity(.__heap_base, {}); |
| | 3327 | } else if (name == wasm.preloaded_strings.__heap_end) { |
| | 3328 | import.resolution = .__heap_end; |
| | 3329 | wasm.data_segments.putAssumeCapacity(.__heap_end, {}); |
| | 3330 | } else { |
| | 3331 | try wasm.data_imports.put(gpa, name, .fromObject(data_index, wasm)); |
| | 3332 | } |
| | 3333 | } else { |
| | 3334 | try markDataSegment(wasm, import.resolution.toDataId().?.unpack(wasm).object); |
| | 3335 | } |
| | 3336 | } |
| | 3337 | |
| 3173 | fn markRelocations(wasm: *Wasm, relocs: ObjectRelocation.IterableSlice) link.File.FlushError!void { | 3338 | fn markRelocations(wasm: *Wasm, relocs: ObjectRelocation.IterableSlice) link.File.FlushError!void { |
| 3174 | for (relocs.slice.tags(wasm), relocs.slice.pointees(wasm), relocs.slice.offsets(wasm)) |tag, pointee, offset| { | 3339 | for (relocs.slice.tags(wasm), relocs.slice.pointees(wasm), relocs.slice.offsets(wasm)) |tag, pointee, offset| { |
| 3175 | if (offset >= relocs.end) break; | 3340 | if (offset >= relocs.end) break; |
| ... | @@ -3199,6 +3364,22 @@ fn markRelocations(wasm: *Wasm, relocs: ObjectRelocation.IterableSlice) link.Fil | ... | @@ -3199,6 +3364,22 @@ fn markRelocations(wasm: *Wasm, relocs: ObjectRelocation.IterableSlice) link.Fil |
| 3199 | const i: TableImport.Index = @enumFromInt(wasm.object_table_imports.getIndex(name).?); | 3364 | const i: TableImport.Index = @enumFromInt(wasm.object_table_imports.getIndex(name).?); |
| 3200 | try markTableImport(wasm, name, i.value(wasm), i); | 3365 | try markTableImport(wasm, name, i.value(wasm), i); |
| 3201 | }, | 3366 | }, |
| | 3367 | .memory_addr_import_leb, |
| | 3368 | .memory_addr_import_sleb, |
| | 3369 | .memory_addr_import_i32, |
| | 3370 | .memory_addr_import_rel_sleb, |
| | 3371 | .memory_addr_import_leb64, |
| | 3372 | .memory_addr_import_sleb64, |
| | 3373 | .memory_addr_import_i64, |
| | 3374 | .memory_addr_import_rel_sleb64, |
| | 3375 | .memory_addr_import_tls_sleb, |
| | 3376 | .memory_addr_import_locrel_i32, |
| | 3377 | .memory_addr_import_tls_sleb64, |
| | 3378 | => { |
| | 3379 | const name = pointee.symbol_name; |
| | 3380 | const i = ObjectDataImport.Index.fromSymbolName(wasm, name).?; |
| | 3381 | try markDataImport(wasm, name, i.value(wasm), i); |
| | 3382 | }, |
| 3202 | | 3383 | |
| 3203 | .function_index_leb, | 3384 | .function_index_leb, |
| 3204 | .function_index_i32, | 3385 | .function_index_i32, |
| ... | @@ -3220,26 +3401,6 @@ fn markRelocations(wasm: *Wasm, relocs: ObjectRelocation.IterableSlice) link.Fil | ... | @@ -3220,26 +3401,6 @@ fn markRelocations(wasm: *Wasm, relocs: ObjectRelocation.IterableSlice) link.Fil |
| 3220 | .section_offset_i32 => { | 3401 | .section_offset_i32 => { |
| 3221 | log.warn("TODO: ensure section {d} is included in output", .{pointee.section}); | 3402 | log.warn("TODO: ensure section {d} is included in output", .{pointee.section}); |
| 3222 | }, | 3403 | }, |
| 3223 | .memory_addr_import_leb, | | |
| 3224 | .memory_addr_import_sleb, | | |
| 3225 | .memory_addr_import_i32, | | |
| 3226 | .memory_addr_import_rel_sleb, | | |
| 3227 | .memory_addr_import_leb64, | | |
| 3228 | .memory_addr_import_sleb64, | | |
| 3229 | .memory_addr_import_i64, | | |
| 3230 | .memory_addr_import_rel_sleb64, | | |
| 3231 | .memory_addr_import_tls_sleb, | | |
| 3232 | .memory_addr_import_locrel_i32, | | |
| 3233 | .memory_addr_import_tls_sleb64, | | |
| 3234 | => { | | |
| 3235 | const name = pointee.symbol_name; | | |
| 3236 | if (name == wasm.preloaded_strings.__heap_end or | | |
| 3237 | name == wasm.preloaded_strings.__heap_base) | | |
| 3238 | { | | |
| 3239 | continue; | | |
| 3240 | } | | |
| 3241 | log.warn("TODO: ensure data symbol {s} is included in output", .{name.slice(wasm)}); | | |
| 3242 | }, | | |
| 3243 | | 3404 | |
| 3244 | .memory_addr_leb, | 3405 | .memory_addr_leb, |
| 3245 | .memory_addr_sleb, | 3406 | .memory_addr_sleb, |
| ... | @@ -3309,6 +3470,7 @@ pub fn flushModule( | ... | @@ -3309,6 +3470,7 @@ pub fn flushModule( |
| 3309 | try wasm.flush_buffer.missing_exports.reinit(gpa, wasm.missing_exports.keys(), &.{}); | 3470 | try wasm.flush_buffer.missing_exports.reinit(gpa, wasm.missing_exports.keys(), &.{}); |
| 3310 | try wasm.flush_buffer.function_imports.reinit(gpa, wasm.function_imports.keys(), wasm.function_imports.values()); | 3471 | try wasm.flush_buffer.function_imports.reinit(gpa, wasm.function_imports.keys(), wasm.function_imports.values()); |
| 3311 | try wasm.flush_buffer.global_imports.reinit(gpa, wasm.global_imports.keys(), wasm.global_imports.values()); | 3472 | try wasm.flush_buffer.global_imports.reinit(gpa, wasm.global_imports.keys(), wasm.global_imports.values()); |
| | 3473 | try wasm.flush_buffer.data_imports.reinit(gpa, wasm.data_imports.keys(), wasm.data_imports.values()); |
| 3312 | | 3474 | |
| 3313 | return wasm.flush_buffer.finish(wasm) catch |err| switch (err) { | 3475 | return wasm.flush_buffer.finish(wasm) catch |err| switch (err) { |
| 3314 | error.OutOfMemory => return error.OutOfMemory, | 3476 | error.OutOfMemory => return error.OutOfMemory, |
| ... | @@ -4117,6 +4279,15 @@ fn pointerAlignment(wasm: *const Wasm) Alignment { | ... | @@ -4117,6 +4279,15 @@ fn pointerAlignment(wasm: *const Wasm) Alignment { |
| 4117 | }; | 4279 | }; |
| 4118 | } | 4280 | } |
| 4119 | | 4281 | |
| | 4282 | fn pointerSize(wasm: *const Wasm) u32 { |
| | 4283 | const target = &wasm.base.comp.root_mod.resolved_target.result; |
| | 4284 | return switch (target.cpu.arch) { |
| | 4285 | .wasm32 => 4, |
| | 4286 | .wasm64 => 8, |
| | 4287 | else => unreachable, |
| | 4288 | }; |
| | 4289 | } |
| | 4290 | |
| 4120 | fn addZcuImportReserved(wasm: *Wasm, nav_index: InternPool.Nav.Index) ZcuImportIndex { | 4291 | fn addZcuImportReserved(wasm: *Wasm, nav_index: InternPool.Nav.Index) ZcuImportIndex { |
| 4121 | const gop = wasm.imports.getOrPutAssumeCapacity(nav_index); | 4292 | const gop = wasm.imports.getOrPutAssumeCapacity(nav_index); |
| 4122 | gop.value_ptr.* = {}; | 4293 | gop.value_ptr.* = {}; |