diff options
| author | Luuk de Gram <luuk@degram.dev> | 2022-06-24 22:01:41 +0200 |
|---|---|---|
| committer | Luuk de Gram <luuk@degram.dev> | 2022-06-24 22:01:41 +0200 |
| commit | e32a5ba78b5e42788cba57720ce88cbfd30d434b (patch) | |
| tree | da6d60b9ae93eb592f8330ddefd582ab77a11d32 /src/link | |
| parent | 905a18849f7f2c3f269fbf425170e0c86b12524a (diff) | |
| download | zig-e32a5ba78b5e42788cba57720ce88cbfd30d434b.tar.gz zig-e32a5ba78b5e42788cba57720ce88cbfd30d434b.zip | |
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.
Diffstat (limited to 'src/link')
| -rw-r--r-- | src/link/Wasm.zig | 43 | ||||
| -rw-r--r-- | src/link/Wasm/types.zig | 5 |
2 files changed, 38 insertions, 10 deletions
diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 4357a588a1..834ac3e1e1 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -1143,9 +1143,29 @@ pub fn addOrUpdateImport( } else @panic("TODO: Implement undefined symbols for non-function declarations"); } +/// Kind represents the type of an Atom, which is only +/// used to parse a decl into an Atom to define in which section +/// or segment it should be placed. const Kind = union(enum) { - data: void, + /// Represents the segment the data symbol should + /// be inserted into. + /// TODO: Add TLS segments + data: enum { + read_only, + uninitialized, + initialized, + }, function: FnData, + + /// Returns the segment name the data kind represents. + /// Asserts `kind` has its active tag set to `data`. + fn segmentName(kind: Kind) []const u8 { + switch (kind.data) { + .read_only => return ".rodata.", + .uninitialized => return ".bss.", + .initialized => return ".data.", + } + } }; /// Parses an Atom and inserts its metadata into the corresponding sections. @@ -1174,9 +1194,8 @@ fn parseAtom(self: *Wasm, atom: *Atom, kind: Kind) !void { break :result self.code_section_index.?; }, .data => result: { - // TODO: Add mutables global decls to .bss section instead const segment_name = try std.mem.concat(self.base.allocator, u8, &.{ - ".rodata.", + kind.segmentName(), self.string_table.get(symbol.name), }); errdefer self.base.allocator.free(segment_name); @@ -1722,8 +1741,8 @@ fn populateErrorNameTable(self: *Wasm) !void { // link the atoms with the rest of the binary so they can be allocated // and relocations will be performed. - try self.parseAtom(atom, .data); - try self.parseAtom(names_atom, .data); + try self.parseAtom(atom, .{ .data = .read_only }); + try self.parseAtom(names_atom, .{ .data = .read_only }); } pub fn getDebugInfoIndex(self: *Wasm) !u32 { @@ -1866,13 +1885,21 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod const atom = &decl.*.link.wasm; if (decl.ty.zigTypeTag() == .Fn) { try self.parseAtom(atom, .{ .function = decl.fn_link.wasm }); + } else if (decl.getVariable()) |variable| { + if (!variable.is_mutable) { + try self.parseAtom(atom, .{ .data = .read_only }); + } else if (variable.init.isUndefDeep()) { + try self.parseAtom(atom, .{ .data = .uninitialized }); + } else { + try self.parseAtom(atom, .{ .data = .initialized }); + } } else { - try self.parseAtom(atom, .data); + try self.parseAtom(atom, .{ .data = .read_only }); } // also parse atoms for a decl's locals for (atom.locals.items) |*local_atom| { - try self.parseAtom(local_atom, .data); + try self.parseAtom(local_atom, .{ .data = .read_only }); } } @@ -2167,7 +2194,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod while (it.next()) |entry| { // do not output 'bss' section unless we import memory and therefore // want to guarantee the data is zero initialized - if (std.mem.eql(u8, entry.key_ptr.*, ".bss") and !import_memory) continue; + if (!import_memory and std.mem.eql(u8, entry.key_ptr.*, ".bss")) continue; segment_count += 1; const atom_index = entry.value_ptr.*; var atom: *Atom = self.atoms.getPtr(atom_index).?.*.getFirst(); diff --git a/src/link/Wasm/types.zig b/src/link/Wasm/types.zig index 835c02ea12..a606e3f7b6 100644 --- a/src/link/Wasm/types.zig +++ b/src/link/Wasm/types.zig @@ -125,14 +125,15 @@ pub const Segment = struct { /// Bitfield containing flags for a segment flags: u32, + /// Returns the name as how it will be output into the final object + /// file or binary. When `merge_segments` is true, this will return the + /// short name. i.e. ".rodata". When false, it returns the entire name instead. pub fn outputName(self: Segment, merge_segments: bool) []const u8 { if (!merge_segments) return self.name; if (std.mem.startsWith(u8, self.name, ".rodata.")) { return ".rodata"; } else if (std.mem.startsWith(u8, self.name, ".text.")) { return ".text"; - } else if (std.mem.startsWith(u8, self.name, ".rodata.")) { - return ".rodata"; } else if (std.mem.startsWith(u8, self.name, ".data.")) { return ".data"; } else if (std.mem.startsWith(u8, self.name, ".bss.")) { |
