wasm-link: fix storing decls in the right segment

When a decl is `undefined` is must be stored in the data segment when
the build mode is safe. For unsafe optimize modes, it must be stored
in the bss segment instead.

For mutable decls where the atom contains all zeroes, it must always
be stored in the bss segment. All other values will result in the
atom being stored in the data segment.
This commit is contained in:
Luuk de Gram 2023-03-08 06:27:03 +01:00
parent c31007bb47
commit bddf138e72
No known key found for this signature in database
GPG Key ID: A8CFE58E4DC7D664

View File

@ -2828,22 +2828,31 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
const decl = mod.declPtr(entry.key_ptr.*); const decl = mod.declPtr(entry.key_ptr.*);
if (decl.isExtern()) continue; if (decl.isExtern()) continue;
const atom_index = entry.value_ptr.*; const atom_index = entry.value_ptr.*;
const atom = wasm.getAtomPtr(atom_index);
if (decl.ty.zigTypeTag() == .Fn) { if (decl.ty.zigTypeTag() == .Fn) {
try wasm.parseAtom(atom_index, .function); try wasm.parseAtom(atom_index, .function);
} else if (decl.getVariable()) |variable| { } else if (decl.getVariable()) |variable| {
if (!variable.is_mutable) { if (!variable.is_mutable) {
try wasm.parseAtom(atom_index, .{ .data = .read_only }); try wasm.parseAtom(atom_index, .{ .data = .read_only });
} else if (variable.init.isUndefDeep()) { } else if (variable.init.isUndefDeep()) {
try wasm.parseAtom(atom_index, .{ .data = .uninitialized }); // for safe build modes, we store the atom in the data segment,
// whereas for unsafe build modes we store it in bss.
const is_initialized = wasm.base.options.optimize_mode == .Debug or
wasm.base.options.optimize_mode == .ReleaseSafe;
try wasm.parseAtom(atom_index, .{ .data = if (is_initialized) .initialized else .uninitialized });
} else { } else {
try wasm.parseAtom(atom_index, .{ .data = .initialized }); // when the decl is all zeroes, we store the atom in the bss segment,
// in all other cases it will be in the data segment.
const is_zeroes = for (atom.code.items) |byte| {
if (byte != 0) break false;
} else true;
try wasm.parseAtom(atom_index, .{ .data = if (is_zeroes) .uninitialized else .initialized });
} }
} else { } else {
try wasm.parseAtom(atom_index, .{ .data = .read_only }); try wasm.parseAtom(atom_index, .{ .data = .read_only });
} }
// also parse atoms for a decl's locals // also parse atoms for a decl's locals
const atom = wasm.getAtomPtr(atom_index);
for (atom.locals.items) |local_atom_index| { for (atom.locals.items) |local_atom_index| {
try wasm.parseAtom(local_atom_index, .{ .data = .read_only }); try wasm.parseAtom(local_atom_index, .{ .data = .read_only });
} }