authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-06-24 22:01:41+02:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-06-24 22:01:41+02:00
loge32a5ba78b5e42788cba57720ce88cbfd30d434b
treeda6d60b9ae93eb592f8330ddefd582ab77a11d32
parent905a18849f7f2c3f269fbf425170e0c86b12524a
signaturelock-open Commit is signed but in an unrecognized format.

link/wasm: Put decls into the correct segments

Decls will now be put into their respective segment. e.g. a constant decl will be inserted into the "rodata" segment, whereas an uninitialized decl will be put in the "bss" segment instead.

2 files changed, 38 insertions(+), 10 deletions(-)

src/link/Wasm.zig+35-8
......@@ -1143,9 +1143,29 @@ pub fn addOrUpdateImport(
11431143 } else @panic("TODO: Implement undefined symbols for non-function declarations");
11441144}
11451145
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.
11461149const 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 },
11481158 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 }
11491169};
11501170
11511171/// Parses an Atom and inserts its metadata into the corresponding sections.
......@@ -1174,9 +1194,8 @@ fn parseAtom(self: *Wasm, atom: *Atom, kind: Kind) !void {
11741194 break :result self.code_section_index.?;
11751195 },
11761196 .data => result: {
1177 // TODO: Add mutables global decls to .bss section instead
11781197 const segment_name = try std.mem.concat(self.base.allocator, u8, &.{
1179 ".rodata.",
1198 kind.segmentName(),
11801199 self.string_table.get(symbol.name),
11811200 });
11821201 errdefer self.base.allocator.free(segment_name);
......@@ -1722,8 +1741,8 @@ fn populateErrorNameTable(self: *Wasm) !void {
17221741
17231742 // link the atoms with the rest of the binary so they can be allocated
17241743 // and relocations will be performed.
1725 try self.parseAtom(atom, .data);
1726 try self.parseAtom(names_atom, .data);
1744 try self.parseAtom(atom, .{ .data = .read_only });
1745 try self.parseAtom(names_atom, .{ .data = .read_only });
17271746}
17281747
17291748pub fn getDebugInfoIndex(self: *Wasm) !u32 {
......@@ -1866,13 +1885,21 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
18661885 const atom = &decl.*.link.wasm;
18671886 if (decl.ty.zigTypeTag() == .Fn) {
18681887 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 }
18691896 } else {
1870 try self.parseAtom(atom, .data);
1897 try self.parseAtom(atom, .{ .data = .read_only });
18711898 }
18721899
18731900 // also parse atoms for a decl's locals
18741901 for (atom.locals.items) |*local_atom| {
1875 try self.parseAtom(local_atom, .data);
1902 try self.parseAtom(local_atom, .{ .data = .read_only });
18761903 }
18771904 }
18781905
......@@ -2167,7 +2194,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
21672194 while (it.next()) |entry| {
21682195 // do not output 'bss' section unless we import memory and therefore
21692196 // 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;
21712198 segment_count += 1;
21722199 const atom_index = entry.value_ptr.*;
21732200 var atom: *Atom = self.atoms.getPtr(atom_index).?.*.getFirst();
src/link/Wasm/types.zig+3-2
......@@ -125,14 +125,15 @@ pub const Segment = struct {
125125 /// Bitfield containing flags for a segment
126126 flags: u32,
127127
128 /// Returns the name as how it will be output into the final object
129 /// file or binary. When `merge_segments` is true, this will return the
130 /// short name. i.e. ".rodata". When false, it returns the entire name instead.
128131 pub fn outputName(self: Segment, merge_segments: bool) []const u8 {
129132 if (!merge_segments) return self.name;
130133 if (std.mem.startsWith(u8, self.name, ".rodata.")) {
131134 return ".rodata";
132135 } else if (std.mem.startsWith(u8, self.name, ".text.")) {
133136 return ".text";
134 } else if (std.mem.startsWith(u8, self.name, ".rodata.")) {
135 return ".rodata";
136137 } else if (std.mem.startsWith(u8, self.name, ".data.")) {
137138 return ".data";
138139 } else if (std.mem.startsWith(u8, self.name, ".bss.")) {