| ... | @@ -67,6 +67,18 @@ code_section_index: ?u32 = null, | ... | @@ -67,6 +67,18 @@ code_section_index: ?u32 = null, |
| 67 | debug_info_index: ?u32 = null, | 67 | debug_info_index: ?u32 = null, |
| 68 | /// The index of the segment representing the custom '.debug_line' section. | 68 | /// The index of the segment representing the custom '.debug_line' section. |
| 69 | debug_line_index: ?u32 = null, | 69 | debug_line_index: ?u32 = null, |
| | 70 | /// The index of the segment representing the custom '.debug_loc' section. |
| | 71 | debug_loc_index: ?u32 = null, |
| | 72 | /// The index of the segment representing the custom '.debug_ranges' section. |
| | 73 | debug_ranges_index: ?u32 = null, |
| | 74 | /// The index of the segment representing the custom '.debug_pubnames' section. |
| | 75 | debug_pubnames_index: ?u32 = null, |
| | 76 | /// The index of the segment representing the custom '.debug_pubtypes' section. |
| | 77 | debug_pubtypes_index: ?u32 = null, |
| | 78 | /// The index of the segment representing the custom '.debug_pubtypes' section. |
| | 79 | debug_str_index: ?u32 = null, |
| | 80 | /// The index of the segment representing the custom '.debug_pubtypes' section. |
| | 81 | debug_abbrev_index: ?u32 = null, |
| 70 | /// The count of imported functions. This number will be appended | 82 | /// The count of imported functions. This number will be appended |
| 71 | /// to the function indexes as their index starts at the lowest non-extern function. | 83 | /// to the function indexes as their index starts at the lowest non-extern function. |
| 72 | imported_functions_count: u32 = 0, | 84 | imported_functions_count: u32 = 0, |
| ... | @@ -1753,7 +1765,7 @@ fn setupMemory(self: *Wasm) !void { | ... | @@ -1753,7 +1765,7 @@ fn setupMemory(self: *Wasm) !void { |
| 1753 | /// From a given object's index and the index of the segment, returns the corresponding | 1765 | /// From a given object's index and the index of the segment, returns the corresponding |
| 1754 | /// index of the segment within the final data section. When the segment does not yet | 1766 | /// index of the segment within the final data section. When the segment does not yet |
| 1755 | /// exist, a new one will be initialized and appended. The new index will be returned in that case. | 1767 | /// exist, a new one will be initialized and appended. The new index will be returned in that case. |
| 1756 | pub fn getMatchingSegment(self: *Wasm, object_index: u16, relocatable_index: u32) !u32 { | 1768 | pub fn getMatchingSegment(self: *Wasm, object_index: u16, relocatable_index: u32) !?u32 { |
| 1757 | const object: Object = self.objects.items[object_index]; | 1769 | const object: Object = self.objects.items[object_index]; |
| 1758 | const relocatable_data = object.relocatable_data[relocatable_index]; | 1770 | const relocatable_data = object.relocatable_data[relocatable_index]; |
| 1759 | const index = @intCast(u32, self.segments.items.len); | 1771 | const index = @intCast(u32, self.segments.items.len); |
| ... | @@ -1765,27 +1777,83 @@ pub fn getMatchingSegment(self: *Wasm, object_index: u16, relocatable_index: u32 | ... | @@ -1765,27 +1777,83 @@ pub fn getMatchingSegment(self: *Wasm, object_index: u16, relocatable_index: u32 |
| 1765 | const result = try self.data_segments.getOrPut(self.base.allocator, segment_info.outputName(merge_segment)); | 1777 | const result = try self.data_segments.getOrPut(self.base.allocator, segment_info.outputName(merge_segment)); |
| 1766 | if (!result.found_existing) { | 1778 | if (!result.found_existing) { |
| 1767 | result.value_ptr.* = index; | 1779 | result.value_ptr.* = index; |
| 1768 | try self.segments.append(self.base.allocator, .{ | 1780 | try self.appendDummySegment(); |
| 1769 | .alignment = 1, | | |
| 1770 | .size = 0, | | |
| 1771 | .offset = 0, | | |
| 1772 | }); | | |
| 1773 | return index; | 1781 | return index; |
| 1774 | } else return result.value_ptr.*; | 1782 | } else return result.value_ptr.*; |
| 1775 | }, | 1783 | }, |
| 1776 | .code => return self.code_section_index orelse blk: { | 1784 | .code => return self.code_section_index orelse blk: { |
| 1777 | self.code_section_index = index; | 1785 | self.code_section_index = index; |
| 1778 | try self.segments.append(self.base.allocator, .{ | 1786 | try self.appendDummySegment(); |
| 1779 | .alignment = 1, | | |
| 1780 | .size = 0, | | |
| 1781 | .offset = 0, | | |
| 1782 | }); | | |
| 1783 | break :blk index; | 1787 | break :blk index; |
| 1784 | }, | 1788 | }, |
| 1785 | .debug => return error.@"TODO: Custom section relocations for wasm", | 1789 | .debug => { |
| | 1790 | const debug_name = object.getDebugName(relocatable_data); |
| | 1791 | if (mem.eql(u8, debug_name, ".debug_info")) { |
| | 1792 | return self.debug_info_index orelse blk: { |
| | 1793 | self.debug_info_index = index; |
| | 1794 | try self.appendDummySegment(); |
| | 1795 | break :blk index; |
| | 1796 | }; |
| | 1797 | } else if (mem.eql(u8, debug_name, ".debug_line")) { |
| | 1798 | return self.debug_line_index orelse blk: { |
| | 1799 | self.debug_line_index = index; |
| | 1800 | try self.appendDummySegment(); |
| | 1801 | break :blk index; |
| | 1802 | }; |
| | 1803 | } else if (mem.eql(u8, debug_name, ".debug_loc")) { |
| | 1804 | return self.debug_loc_index orelse blk: { |
| | 1805 | self.debug_loc_index = index; |
| | 1806 | try self.appendDummySegment(); |
| | 1807 | break :blk index; |
| | 1808 | }; |
| | 1809 | } else if (mem.eql(u8, debug_name, ".debug_ranges")) { |
| | 1810 | return self.debug_line_index orelse blk: { |
| | 1811 | self.debug_ranges_index = index; |
| | 1812 | try self.appendDummySegment(); |
| | 1813 | break :blk index; |
| | 1814 | }; |
| | 1815 | } else if (mem.eql(u8, debug_name, ".debug_pubnames")) { |
| | 1816 | return self.debug_pubnames_index orelse blk: { |
| | 1817 | self.debug_pubnames_index = index; |
| | 1818 | try self.appendDummySegment(); |
| | 1819 | break :blk index; |
| | 1820 | }; |
| | 1821 | } else if (mem.eql(u8, debug_name, ".debug_pubtypes")) { |
| | 1822 | return self.debug_pubtypes_index orelse blk: { |
| | 1823 | self.debug_pubtypes_index = index; |
| | 1824 | try self.appendDummySegment(); |
| | 1825 | break :blk index; |
| | 1826 | }; |
| | 1827 | } else if (mem.eql(u8, debug_name, ".debug_abbrev")) { |
| | 1828 | return self.debug_abbrev_index orelse blk: { |
| | 1829 | self.debug_abbrev_index = index; |
| | 1830 | try self.appendDummySegment(); |
| | 1831 | break :blk index; |
| | 1832 | }; |
| | 1833 | } else if (mem.eql(u8, debug_name, ".debug_str")) { |
| | 1834 | return self.debug_str_index orelse blk: { |
| | 1835 | self.debug_str_index = index; |
| | 1836 | try self.appendDummySegment(); |
| | 1837 | break :blk index; |
| | 1838 | }; |
| | 1839 | } else { |
| | 1840 | log.warn("found unknown debug section '{s}'", .{debug_name}); |
| | 1841 | log.warn(" debug section will be skipped", .{}); |
| | 1842 | return null; |
| | 1843 | } |
| | 1844 | }, |
| 1786 | } | 1845 | } |
| 1787 | } | 1846 | } |
| 1788 | | 1847 | |
| | 1848 | /// Appends a new segment with default field values |
| | 1849 | fn appendDummySegment(self: *Wasm) !void { |
| | 1850 | try self.segments.append(self.base.allocator, .{ |
| | 1851 | .alignment = 1, |
| | 1852 | .size = 0, |
| | 1853 | .offset = 0, |
| | 1854 | }); |
| | 1855 | } |
| | 1856 | |
| 1789 | /// Returns the symbol index of the error name table. | 1857 | /// Returns the symbol index of the error name table. |
| 1790 | /// | 1858 | /// |
| 1791 | /// When the symbol does not yet exist, it will create a new one instead. | 1859 | /// When the symbol does not yet exist, it will create a new one instead. |
| ... | @@ -1936,17 +2004,18 @@ fn resetState(self: *Wasm) void { | ... | @@ -1936,17 +2004,18 @@ fn resetState(self: *Wasm) void { |
| 1936 | for (self.segment_info.items) |*segment_info| { | 2004 | for (self.segment_info.items) |*segment_info| { |
| 1937 | self.base.allocator.free(segment_info.name); | 2005 | self.base.allocator.free(segment_info.name); |
| 1938 | } | 2006 | } |
| 1939 | const mod = self.base.options.module.?; | 2007 | if (self.base.options.module) |mod| { |
| 1940 | var decl_it = self.decls.keyIterator(); | 2008 | var decl_it = self.decls.keyIterator(); |
| 1941 | while (decl_it.next()) |decl_index_ptr| { | 2009 | while (decl_it.next()) |decl_index_ptr| { |
| 1942 | const decl = mod.declPtr(decl_index_ptr.*); | 2010 | const decl = mod.declPtr(decl_index_ptr.*); |
| 1943 | const atom = &decl.link.wasm; | 2011 | const atom = &decl.link.wasm; |
| 1944 | atom.next = null; | 2012 | atom.next = null; |
| 1945 | atom.prev = null; | 2013 | atom.prev = null; |
| 1946 | | 2014 | |
| 1947 | for (atom.locals.items) |*local_atom| { | 2015 | for (atom.locals.items) |*local_atom| { |
| 1948 | local_atom.next = null; | 2016 | local_atom.next = null; |
| 1949 | local_atom.prev = null; | 2017 | local_atom.prev = null; |
| | 2018 | } |
| 1950 | } | 2019 | } |
| 1951 | } | 2020 | } |
| 1952 | self.functions.clearRetainingCapacity(); | 2021 | self.functions.clearRetainingCapacity(); |
| ... | @@ -2036,29 +2105,34 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod | ... | @@ -2036,29 +2105,34 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod |
| 2036 | defer self.resetState(); | 2105 | defer self.resetState(); |
| 2037 | try self.setupStart(); | 2106 | try self.setupStart(); |
| 2038 | try self.setupImports(); | 2107 | try self.setupImports(); |
| 2039 | const mod = self.base.options.module.?; | 2108 | if (self.base.options.module) |mod| { |
| 2040 | var decl_it = self.decls.keyIterator(); | 2109 | var decl_it = self.decls.keyIterator(); |
| 2041 | while (decl_it.next()) |decl_index_ptr| { | 2110 | while (decl_it.next()) |decl_index_ptr| { |
| 2042 | const decl = mod.declPtr(decl_index_ptr.*); | 2111 | const decl = mod.declPtr(decl_index_ptr.*); |
| 2043 | if (decl.isExtern()) continue; | 2112 | if (decl.isExtern()) continue; |
| 2044 | const atom = &decl.*.link.wasm; | 2113 | const atom = &decl.*.link.wasm; |
| 2045 | if (decl.ty.zigTypeTag() == .Fn) { | 2114 | if (decl.ty.zigTypeTag() == .Fn) { |
| 2046 | try self.parseAtom(atom, .{ .function = decl.fn_link.wasm }); | 2115 | try self.parseAtom(atom, .{ .function = decl.fn_link.wasm }); |
| 2047 | } else if (decl.getVariable()) |variable| { | 2116 | } else if (decl.getVariable()) |variable| { |
| 2048 | if (!variable.is_mutable) { | 2117 | if (!variable.is_mutable) { |
| 2049 | try self.parseAtom(atom, .{ .data = .read_only }); | 2118 | try self.parseAtom(atom, .{ .data = .read_only }); |
| 2050 | } else if (variable.init.isUndefDeep()) { | 2119 | } else if (variable.init.isUndefDeep()) { |
| 2051 | try self.parseAtom(atom, .{ .data = .uninitialized }); | 2120 | try self.parseAtom(atom, .{ .data = .uninitialized }); |
| | 2121 | } else { |
| | 2122 | try self.parseAtom(atom, .{ .data = .initialized }); |
| | 2123 | } |
| 2052 | } else { | 2124 | } else { |
| 2053 | try self.parseAtom(atom, .{ .data = .initialized }); | 2125 | try self.parseAtom(atom, .{ .data = .read_only }); |
| | 2126 | } |
| | 2127 | |
| | 2128 | // also parse atoms for a decl's locals |
| | 2129 | for (atom.locals.items) |*local_atom| { |
| | 2130 | try self.parseAtom(local_atom, .{ .data = .read_only }); |
| 2054 | } | 2131 | } |
| 2055 | } else { | | |
| 2056 | try self.parseAtom(atom, .{ .data = .read_only }); | | |
| 2057 | } | 2132 | } |
| 2058 | | 2133 | |
| 2059 | // also parse atoms for a decl's locals | 2134 | if (self.dwarf) |*dwarf| { |
| 2060 | for (atom.locals.items) |*local_atom| { | 2135 | try dwarf.flushModule(&self.base, self.base.options.module.?); |
| 2061 | try self.parseAtom(local_atom, .{ .data = .read_only }); | | |
| 2062 | } | 2136 | } |
| 2063 | } | 2137 | } |
| 2064 | | 2138 | |
| ... | @@ -2066,9 +2140,6 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod | ... | @@ -2066,9 +2140,6 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod |
| 2066 | try object.parseIntoAtoms(self.base.allocator, @intCast(u16, object_index), self); | 2140 | try object.parseIntoAtoms(self.base.allocator, @intCast(u16, object_index), self); |
| 2067 | } | 2141 | } |
| 2068 | | 2142 | |
| 2069 | if (self.dwarf) |*dwarf| { | | |
| 2070 | try dwarf.flushModule(&self.base, self.base.options.module.?); | | |
| 2071 | } | | |
| 2072 | try self.allocateAtoms(); | 2143 | try self.allocateAtoms(); |
| 2073 | try self.setupMemory(); | 2144 | try self.setupMemory(); |
| 2074 | self.mapFunctionTable(); | 2145 | self.mapFunctionTable(); |
| ... | @@ -2425,12 +2496,14 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod | ... | @@ -2425,12 +2496,14 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod |
| 2425 | } else if (!self.base.options.strip) { | 2496 | } else if (!self.base.options.strip) { |
| 2426 | if (self.dwarf) |*dwarf| { | 2497 | if (self.dwarf) |*dwarf| { |
| 2427 | if (self.debug_info_index != null) { | 2498 | if (self.debug_info_index != null) { |
| 2428 | try dwarf.writeDbgAbbrev(&self.base); | 2499 | if (self.base.options.module) |mod| { |
| 2429 | // for debug info and ranges, the address is always 0, | 2500 | try dwarf.writeDbgAbbrev(&self.base); |
| 2430 | // as locations are always offsets relative to 'code' section. | 2501 | // for debug info and ranges, the address is always 0, |
| 2431 | try dwarf.writeDbgInfoHeader(&self.base, mod, 0, code_section_size); | 2502 | // as locations are always offsets relative to 'code' section. |
| 2432 | try dwarf.writeDbgAranges(&self.base, 0, code_section_size); | 2503 | try dwarf.writeDbgInfoHeader(&self.base, mod, 0, code_section_size); |
| 2433 | try dwarf.writeDbgLineHeader(&self.base, mod); | 2504 | try dwarf.writeDbgAranges(&self.base, 0, code_section_size); |
| | 2505 | try dwarf.writeDbgLineHeader(&self.base, mod); |
| | 2506 | } |
| 2434 | | 2507 | |
| 2435 | try emitDebugSection(file, self.debug_info.items, ".debug_info"); | 2508 | try emitDebugSection(file, self.debug_info.items, ".debug_info"); |
| 2436 | try emitDebugSection(file, self.debug_aranges.items, ".debug_ranges"); | 2509 | try emitDebugSection(file, self.debug_aranges.items, ".debug_ranges"); |