| ... | @@ -1143,9 +1143,29 @@ pub fn addOrUpdateImport( | ... | @@ -1143,9 +1143,29 @@ pub fn addOrUpdateImport( |
| 1143 | } else @panic("TODO: Implement undefined symbols for non-function declarations"); | 1143 | } else @panic("TODO: Implement undefined symbols for non-function declarations"); |
| 1144 | } | 1144 | } |
| 1145 | | 1145 | |
| | 1146 | /// Kind represents the type of an Atom, which is only |
| | 1147 | /// used to parse a decl into an Atom to define in which section |
| | 1148 | /// or segment it should be placed. |
| 1146 | const Kind = union(enum) { | 1149 | const Kind = union(enum) { |
| 1147 | data: void, | 1150 | /// Represents the segment the data symbol should |
| | 1151 | /// be inserted into. |
| | 1152 | /// TODO: Add TLS segments |
| | 1153 | data: enum { |
| | 1154 | read_only, |
| | 1155 | uninitialized, |
| | 1156 | initialized, |
| | 1157 | }, |
| 1148 | function: FnData, | 1158 | function: FnData, |
| | 1159 | |
| | 1160 | /// Returns the segment name the data kind represents. |
| | 1161 | /// Asserts `kind` has its active tag set to `data`. |
| | 1162 | fn segmentName(kind: Kind) []const u8 { |
| | 1163 | switch (kind.data) { |
| | 1164 | .read_only => return ".rodata.", |
| | 1165 | .uninitialized => return ".bss.", |
| | 1166 | .initialized => return ".data.", |
| | 1167 | } |
| | 1168 | } |
| 1149 | }; | 1169 | }; |
| 1150 | | 1170 | |
| 1151 | /// Parses an Atom and inserts its metadata into the corresponding sections. | 1171 | /// Parses an Atom and inserts its metadata into the corresponding sections. |
| ... | @@ -1174,9 +1194,8 @@ fn parseAtom(self: *Wasm, atom: *Atom, kind: Kind) !void { | ... | @@ -1174,9 +1194,8 @@ fn parseAtom(self: *Wasm, atom: *Atom, kind: Kind) !void { |
| 1174 | break :result self.code_section_index.?; | 1194 | break :result self.code_section_index.?; |
| 1175 | }, | 1195 | }, |
| 1176 | .data => result: { | 1196 | .data => result: { |
| 1177 | // TODO: Add mutables global decls to .bss section instead | | |
| 1178 | const segment_name = try std.mem.concat(self.base.allocator, u8, &.{ | 1197 | const segment_name = try std.mem.concat(self.base.allocator, u8, &.{ |
| 1179 | ".rodata.", | 1198 | kind.segmentName(), |
| 1180 | self.string_table.get(symbol.name), | 1199 | self.string_table.get(symbol.name), |
| 1181 | }); | 1200 | }); |
| 1182 | errdefer self.base.allocator.free(segment_name); | 1201 | errdefer self.base.allocator.free(segment_name); |
| ... | @@ -1722,8 +1741,8 @@ fn populateErrorNameTable(self: *Wasm) !void { | ... | @@ -1722,8 +1741,8 @@ fn populateErrorNameTable(self: *Wasm) !void { |
| 1722 | | 1741 | |
| 1723 | // link the atoms with the rest of the binary so they can be allocated | 1742 | // link the atoms with the rest of the binary so they can be allocated |
| 1724 | // and relocations will be performed. | 1743 | // and relocations will be performed. |
| 1725 | try self.parseAtom(atom, .data); | 1744 | try self.parseAtom(atom, .{ .data = .read_only }); |
| 1726 | try self.parseAtom(names_atom, .data); | 1745 | try self.parseAtom(names_atom, .{ .data = .read_only }); |
| 1727 | } | 1746 | } |
| 1728 | | 1747 | |
| 1729 | pub fn getDebugInfoIndex(self: *Wasm) !u32 { | 1748 | pub fn getDebugInfoIndex(self: *Wasm) !u32 { |
| ... | @@ -1866,13 +1885,21 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod | ... | @@ -1866,13 +1885,21 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod |
| 1866 | const atom = &decl.*.link.wasm; | 1885 | const atom = &decl.*.link.wasm; |
| 1867 | if (decl.ty.zigTypeTag() == .Fn) { | 1886 | if (decl.ty.zigTypeTag() == .Fn) { |
| 1868 | try self.parseAtom(atom, .{ .function = decl.fn_link.wasm }); | 1887 | try self.parseAtom(atom, .{ .function = decl.fn_link.wasm }); |
| | 1888 | } else if (decl.getVariable()) |variable| { |
| | 1889 | if (!variable.is_mutable) { |
| | 1890 | try self.parseAtom(atom, .{ .data = .read_only }); |
| | 1891 | } else if (variable.init.isUndefDeep()) { |
| | 1892 | try self.parseAtom(atom, .{ .data = .uninitialized }); |
| | 1893 | } else { |
| | 1894 | try self.parseAtom(atom, .{ .data = .initialized }); |
| | 1895 | } |
| 1869 | } else { | 1896 | } else { |
| 1870 | try self.parseAtom(atom, .data); | 1897 | try self.parseAtom(atom, .{ .data = .read_only }); |
| 1871 | } | 1898 | } |
| 1872 | | 1899 | |
| 1873 | // also parse atoms for a decl's locals | 1900 | // also parse atoms for a decl's locals |
| 1874 | for (atom.locals.items) |*local_atom| { | 1901 | for (atom.locals.items) |*local_atom| { |
| 1875 | try self.parseAtom(local_atom, .data); | 1902 | try self.parseAtom(local_atom, .{ .data = .read_only }); |
| 1876 | } | 1903 | } |
| 1877 | } | 1904 | } |
| 1878 | | 1905 | |
| ... | @@ -2167,7 +2194,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod | ... | @@ -2167,7 +2194,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod |
| 2167 | while (it.next()) |entry| { | 2194 | while (it.next()) |entry| { |
| 2168 | // do not output 'bss' section unless we import memory and therefore | 2195 | // do not output 'bss' section unless we import memory and therefore |
| 2169 | // want to guarantee the data is zero initialized | 2196 | // want to guarantee the data is zero initialized |
| 2170 | if (std.mem.eql(u8, entry.key_ptr.*, ".bss") and !import_memory) continue; | 2197 | if (!import_memory and std.mem.eql(u8, entry.key_ptr.*, ".bss")) continue; |
| 2171 | segment_count += 1; | 2198 | segment_count += 1; |
| 2172 | const atom_index = entry.value_ptr.*; | 2199 | const atom_index = entry.value_ptr.*; |
| 2173 | var atom: *Atom = self.atoms.getPtr(atom_index).?.*.getFirst(); | 2200 | var atom: *Atom = self.atoms.getPtr(atom_index).?.*.getFirst(); |