| ... | ... | @@ -1209,9 +1209,10 @@ fn resolveLazySymbols(wasm: *Wasm) !void { |
| 1209 | 1209 | try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc); |
| 1210 | 1210 | } |
| 1211 | 1211 | } |
| 1212 | | if (wasm.undefs.fetchSwapRemove("__zig_lt_errors_len")) |kv| { |
| 1213 | | const loc = try wasm.createSyntheticSymbol("__zig_lt_errors_len", .function); |
| 1212 | if (wasm.undefs.fetchSwapRemove("__zig_errors_len")) |kv| { |
| 1213 | const loc = try wasm.createSyntheticSymbol("__zig_errors_len", .data); |
| 1214 | 1214 | try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc); |
| 1215 | _ = wasm.resolved_symbols.swapRemove(kv.value); |
| 1215 | 1216 | } |
| 1216 | 1217 | } |
| 1217 | 1218 | |
| ... | ... | @@ -2189,44 +2190,41 @@ fn setupInitFunctions(wasm: *Wasm) !void { |
| 2189 | 2190 | std.sort.sort(InitFuncLoc, wasm.init_funcs.items, {}, InitFuncLoc.lessThan); |
| 2190 | 2191 | } |
| 2191 | 2192 | |
| 2192 | | /// Generates the function which verifies if an integer value is less than the |
| 2193 | | /// amount of error values. This will only be generated if the symbol exists. |
| 2194 | | fn setupLtErrorsLenFunction(wasm: *Wasm) !void { |
| 2195 | | if (wasm.findGlobalSymbol("__zig_lt_errors_len") == null) return; |
| 2196 | | const errors_len = wasm.base.options.module.?.global_error_set.count(); |
| 2197 | | |
| 2198 | | var body_list = std.ArrayList(u8).init(wasm.base.allocator); |
| 2199 | | defer body_list.deinit(); |
| 2200 | | const writer = body_list.writer(); |
| 2201 | | |
| 2202 | | { |
| 2203 | | // generates bytecode for the following function: |
| 2204 | | // fn (index: u16) bool { |
| 2205 | | // return index < errors_len; |
| 2206 | | // } |
| 2207 | | |
| 2208 | | // no locals |
| 2209 | | try leb.writeULEB128(writer, @as(u32, 0)); |
| 2210 | | |
| 2211 | | // get argument |
| 2212 | | try writer.writeByte(std.wasm.opcode(.local_get)); |
| 2213 | | try leb.writeULEB128(writer, @as(u32, 0)); |
| 2214 | | |
| 2215 | | // get error length |
| 2216 | | try writer.writeByte(std.wasm.opcode(.i32_const)); |
| 2217 | | try leb.writeULEB128(writer, @intCast(u32, errors_len)); |
| 2218 | | |
| 2219 | | try writer.writeByte(std.wasm.opcode(.i32_lt_u)); |
| 2220 | | |
| 2221 | | // stack values are implicit return values so keep the value |
| 2222 | | // on the stack and end the function. |
| 2193 | /// Generates an atom containing the global error set' size. |
| 2194 | /// This will only be generated if the symbol exists. |
| 2195 | fn setupErrorsLen(wasm: *Wasm) !void { |
| 2196 | const loc = wasm.findGlobalSymbol("__zig_errors_len") orelse return; |
| 2223 | 2197 | |
| 2224 | | // end function |
| 2225 | | try writer.writeByte(std.wasm.opcode(.end)); |
| 2226 | | } |
| 2198 | const errors_len = wasm.base.options.module.?.global_error_set.count(); |
| 2199 | // overwrite existing atom if it already exists (maybe the error set has increased) |
| 2200 | // if not, allcoate a new atom. |
| 2201 | const atom_index = if (wasm.symbol_atom.get(loc)) |index| blk: { |
| 2202 | const atom = wasm.getAtomPtr(index); |
| 2203 | if (atom.next) |next_atom_index| { |
| 2204 | const next_atom = wasm.getAtomPtr(next_atom_index); |
| 2205 | next_atom.prev = atom.prev; |
| 2206 | atom.next = null; |
| 2207 | } |
| 2208 | if (atom.prev) |prev_index| { |
| 2209 | const prev_atom = wasm.getAtomPtr(prev_index); |
| 2210 | prev_atom.next = atom.next; |
| 2211 | atom.prev = null; |
| 2212 | } |
| 2213 | atom.deinit(wasm); |
| 2214 | break :blk index; |
| 2215 | } else new_atom: { |
| 2216 | const atom_index = @intCast(Atom.Index, wasm.managed_atoms.items.len); |
| 2217 | try wasm.symbol_atom.put(wasm.base.allocator, loc, atom_index); |
| 2218 | try wasm.managed_atoms.append(wasm.base.allocator, undefined); |
| 2219 | break :new_atom atom_index; |
| 2220 | }; |
| 2221 | const atom = wasm.getAtomPtr(atom_index); |
| 2222 | atom.* = Atom.empty; |
| 2223 | atom.sym_index = loc.index; |
| 2224 | atom.size = 2; |
| 2225 | try atom.code.writer(wasm.base.allocator).writeIntLittle(u16, @intCast(u16, errors_len)); |
| 2227 | 2226 | |
| 2228 | | const func_type: std.wasm.Type = .{ .params = &.{std.wasm.Valtype.i32}, .returns = &.{std.wasm.Valtype.i32} }; |
| 2229 | | try wasm.createSyntheticFunction("__zig_lt_errors_len", func_type, &body_list); |
| 2227 | try wasm.parseAtom(atom_index, .{ .data = .read_only }); |
| 2230 | 2228 | } |
| 2231 | 2229 | |
| 2232 | 2230 | /// Creates a function body for the `__wasm_call_ctors` symbol. |
| ... | ... | @@ -3361,6 +3359,7 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod |
| 3361 | 3359 | // So we can rebuild the binary file on each incremental update |
| 3362 | 3360 | defer wasm.resetState(); |
| 3363 | 3361 | try wasm.setupInitFunctions(); |
| 3362 | try wasm.setupErrorsLen(); |
| 3364 | 3363 | try wasm.setupStart(); |
| 3365 | 3364 | try wasm.setupImports(); |
| 3366 | 3365 | if (wasm.base.options.module) |mod| { |
| ... | ... | @@ -3423,7 +3422,6 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod |
| 3423 | 3422 | try wasm.setupInitMemoryFunction(); |
| 3424 | 3423 | try wasm.setupTLSRelocationsFunction(); |
| 3425 | 3424 | try wasm.initializeTLSFunction(); |
| 3426 | | try wasm.setupLtErrorsLenFunction(); |
| 3427 | 3425 | try wasm.setupExports(); |
| 3428 | 3426 | try wasm.writeToFile(enabled_features, emit_features_count, arena); |
| 3429 | 3427 | } |