| ... | ... | @@ -1209,6 +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); |
| 1214 | try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc); |
| 1215 | } |
| 1212 | 1216 | } |
| 1213 | 1217 | |
| 1214 | 1218 | // Tries to find a global symbol by its name. Returns null when not found, |
| ... | ... | @@ -2185,6 +2189,46 @@ fn setupInitFunctions(wasm: *Wasm) !void { |
| 2185 | 2189 | std.sort.sort(InitFuncLoc, wasm.init_funcs.items, {}, InitFuncLoc.lessThan); |
| 2186 | 2190 | } |
| 2187 | 2191 | |
| 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. |
| 2223 | |
| 2224 | // end function |
| 2225 | try writer.writeByte(std.wasm.opcode(.end)); |
| 2226 | } |
| 2227 | |
| 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); |
| 2230 | } |
| 2231 | |
| 2188 | 2232 | /// Creates a function body for the `__wasm_call_ctors` symbol. |
| 2189 | 2233 | /// Loops over all constructors found in `init_funcs` and calls them |
| 2190 | 2234 | /// respectively based on their priority which was sorted by `setupInitFunctions`. |
| ... | ... | @@ -3379,6 +3423,7 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod |
| 3379 | 3423 | try wasm.setupInitMemoryFunction(); |
| 3380 | 3424 | try wasm.setupTLSRelocationsFunction(); |
| 3381 | 3425 | try wasm.initializeTLSFunction(); |
| 3426 | try wasm.setupLtErrorsLenFunction(); |
| 3382 | 3427 | try wasm.setupExports(); |
| 3383 | 3428 | try wasm.writeToFile(enabled_features, emit_features_count, arena); |
| 3384 | 3429 | } |