authorgravatar for paul.verigo@gmail.comPavel Verigo <paul.verigo@gmail.com> 2024-07-05 20:25:39+02:00
committergravatar for paul.verigo@gmail.comPavel Verigo <paul.verigo@gmail.com> 2024-07-18 00:57:45+02:00
log31706dc31acdc875899ca18cf92a2fccb3a2f0c7
tree6ef1e3268f32dded4c1af4c356a370986842a3f0
parent6eb76f930defb86d09469f73196b374c90f7f8a5

stage2-wasm: finishAir handle .stack result

By allowing finishAir to handle .stack results, we simplify a lot of code in air*** functions, which try to handle this case. Also this changes will result in optimization, if one of operands is dead after instruction its place could be reused by result. The only downside to this change is that finishAir now can return error, though it handled by returning finishAir result, because it always needs to be final in air*** functions. Additionally I migrated WValue{ to .{ inside CodeGen.zig.

1 files changed, 320 insertions(+), 428 deletions(-)

src/arch/wasm/CodeGen.zig+320-428
...@@ -793,7 +793,7 @@ fn resolveInst(func: *CodeGen, ref: Air.Inst.Ref) InnerError!WValue {...@@ -793,7 +793,7 @@ fn resolveInst(func: *CodeGen, ref: Air.Inst.Ref) InnerError!WValue {
793 const val = (try func.air.value(ref, pt)).?;793 const val = (try func.air.value(ref, pt)).?;
794 const ty = func.typeOf(ref);794 const ty = func.typeOf(ref);
795 if (!ty.hasRuntimeBitsIgnoreComptime(pt) and !ty.isInt(mod) and !ty.isError(mod)) {795 if (!ty.hasRuntimeBitsIgnoreComptime(pt) and !ty.isInt(mod) and !ty.isError(mod)) {
796 gop.value_ptr.* = WValue{ .none = {} };796 gop.value_ptr.* = .none;
797 return gop.value_ptr.*;797 return gop.value_ptr.*;
798 }798 }
799799
...@@ -803,16 +803,17 @@ fn resolveInst(func: *CodeGen, ref: Air.Inst.Ref) InnerError!WValue {...@@ -803,16 +803,17 @@ fn resolveInst(func: *CodeGen, ref: Air.Inst.Ref) InnerError!WValue {
803 //803 //
804 // In the other cases, we will simply lower the constant to a value that fits804 // In the other cases, we will simply lower the constant to a value that fits
805 // into a single local (such as a pointer, integer, bool, etc).805 // into a single local (such as a pointer, integer, bool, etc).
806 const result = if (isByRef(ty, pt)) blk: {806 const result: WValue = if (isByRef(ty, pt))
807 const sym_index = try func.bin_file.lowerUnnamedConst(pt, val, func.decl_index);807 .{ .memory = try func.bin_file.lowerUnnamedConst(pt, val, func.decl_index) }
808 break :blk WValue{ .memory = sym_index };808 else
809 } else try func.lowerConstant(val, ty);809 try func.lowerConstant(val, ty);
810810
811 gop.value_ptr.* = result;811 gop.value_ptr.* = result;
812 return result;812 return result;
813}813}
814814
815fn finishAir(func: *CodeGen, inst: Air.Inst.Index, result: WValue, operands: []const Air.Inst.Ref) void {815/// NOTE: if result == .stack, it will be stored in .local
816fn finishAir(func: *CodeGen, inst: Air.Inst.Index, result: WValue, operands: []const Air.Inst.Ref) InnerError!void {
816 assert(operands.len <= Liveness.bpi - 1);817 assert(operands.len <= Liveness.bpi - 1);
817 var tomb_bits = func.liveness.getTombBits(inst);818 var tomb_bits = func.liveness.getTombBits(inst);
818 for (operands) |operand| {819 for (operands) |operand| {
...@@ -824,9 +825,12 @@ fn finishAir(func: *CodeGen, inst: Air.Inst.Index, result: WValue, operands: []c...@@ -824,9 +825,12 @@ fn finishAir(func: *CodeGen, inst: Air.Inst.Index, result: WValue, operands: []c
824825
825 // results of `none` can never be referenced.826 // results of `none` can never be referenced.
826 if (result != .none) {827 if (result != .none) {
827 assert(result != .stack); // it's illegal to store a stack value as we cannot track its position828 const trackable_result = if (result != .stack)
829 result
830 else
831 try result.toLocal(func, func.typeOfIndex(inst));
828 const branch = func.currentBranch();832 const branch = func.currentBranch();
829 branch.values.putAssumeCapacityNoClobber(inst.toRef(), result);833 branch.values.putAssumeCapacityNoClobber(inst.toRef(), trackable_result);
830 }834 }
831835
832 if (std.debug.runtime_safety) {836 if (std.debug.runtime_safety) {
...@@ -1105,30 +1109,18 @@ fn getResolvedInst(func: *CodeGen, ref: Air.Inst.Ref) *WValue {...@@ -1105,30 +1109,18 @@ fn getResolvedInst(func: *CodeGen, ref: Air.Inst.Ref) *WValue {
1105fn allocLocal(func: *CodeGen, ty: Type) InnerError!WValue {1109fn allocLocal(func: *CodeGen, ty: Type) InnerError!WValue {
1106 const pt = func.pt;1110 const pt = func.pt;
1107 const valtype = typeToValtype(ty, pt);1111 const valtype = typeToValtype(ty, pt);
1108 switch (valtype) {1112 const index_or_null = switch (valtype) {
1109 .i32 => if (func.free_locals_i32.popOrNull()) |index| {1113 .i32 => func.free_locals_i32.popOrNull(),
1110 log.debug("reusing local ({d}) of type {}", .{ index, valtype });1114 .i64 => func.free_locals_i64.popOrNull(),
1111 return WValue{ .local = .{ .value = index, .references = 1 } };1115 .f32 => func.free_locals_f32.popOrNull(),
1112 },1116 .f64 => func.free_locals_f64.popOrNull(),
1113 .i64 => if (func.free_locals_i64.popOrNull()) |index| {1117 .v128 => func.free_locals_v128.popOrNull(),
1114 log.debug("reusing local ({d}) of type {}", .{ index, valtype });1118 };
1115 return WValue{ .local = .{ .value = index, .references = 1 } };1119 if (index_or_null) |index| {
1116 },1120 log.debug("reusing local ({d}) of type {}", .{ index, valtype });
1117 .f32 => if (func.free_locals_f32.popOrNull()) |index| {1121 return .{ .local = .{ .value = index, .references = 1 } };
1118 log.debug("reusing local ({d}) of type {}", .{ index, valtype });
1119 return WValue{ .local = .{ .value = index, .references = 1 } };
1120 },
1121 .f64 => if (func.free_locals_f64.popOrNull()) |index| {
1122 log.debug("reusing local ({d}) of type {}", .{ index, valtype });
1123 return WValue{ .local = .{ .value = index, .references = 1 } };
1124 },
1125 .v128 => if (func.free_locals_v128.popOrNull()) |index| {
1126 log.debug("reusing local ({d}) of type {}", .{ index, valtype });
1127 return WValue{ .local = .{ .value = index, .references = 1 } };
1128 },
1129 }1122 }
1130 log.debug("new local of type {}", .{valtype});1123 log.debug("new local of type {}", .{valtype});
1131 // no local was free to be re-used, so allocate a new local instead
1132 return func.ensureAllocLocal(ty);1124 return func.ensureAllocLocal(ty);
1133}1125}
11341126
...@@ -1139,7 +1131,7 @@ fn ensureAllocLocal(func: *CodeGen, ty: Type) InnerError!WValue {...@@ -1139,7 +1131,7 @@ fn ensureAllocLocal(func: *CodeGen, ty: Type) InnerError!WValue {
1139 try func.locals.append(func.gpa, genValtype(ty, pt));1131 try func.locals.append(func.gpa, genValtype(ty, pt));
1140 const initial_index = func.local_index;1132 const initial_index = func.local_index;
1141 func.local_index += 1;1133 func.local_index += 1;
1142 return WValue{ .local = .{ .value = initial_index, .references = 1 } };1134 return .{ .local = .{ .value = initial_index, .references = 1 } };
1143}1135}
11441136
1145/// Generates a `wasm.Type` from a given function type.1137/// Generates a `wasm.Type` from a given function type.
...@@ -1539,7 +1531,7 @@ fn allocStack(func: *CodeGen, ty: Type) !WValue {...@@ -1539,7 +1531,7 @@ fn allocStack(func: *CodeGen, ty: Type) !WValue {
1539 const offset: u32 = @intCast(abi_align.forward(func.stack_size));1531 const offset: u32 = @intCast(abi_align.forward(func.stack_size));
1540 defer func.stack_size = offset + abi_size;1532 defer func.stack_size = offset + abi_size;
15411533
1542 return WValue{ .stack_offset = .{ .value = offset, .references = 1 } };1534 return .{ .stack_offset = .{ .value = offset, .references = 1 } };
1543}1535}
15441536
1545/// From a given AIR instruction generates a pointer to the stack where1537/// From a given AIR instruction generates a pointer to the stack where
...@@ -1571,7 +1563,7 @@ fn allocStackPtr(func: *CodeGen, inst: Air.Inst.Index) !WValue {...@@ -1571,7 +1563,7 @@ fn allocStackPtr(func: *CodeGen, inst: Air.Inst.Index) !WValue {
1571 const offset: u32 = @intCast(abi_alignment.forward(func.stack_size));1563 const offset: u32 = @intCast(abi_alignment.forward(func.stack_size));
1572 defer func.stack_size = offset + abi_size;1564 defer func.stack_size = offset + abi_size;
15731565
1574 return WValue{ .stack_offset = .{ .value = offset, .references = 1 } };1566 return .{ .stack_offset = .{ .value = offset, .references = 1 } };
1575}1567}
15761568
1577/// From given zig bitsize, returns the wasm bitsize1569/// From given zig bitsize, returns the wasm bitsize
...@@ -2135,7 +2127,7 @@ fn airRet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -2135,7 +2127,7 @@ fn airRet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
2135 try func.restoreStackPointer();2127 try func.restoreStackPointer();
2136 try func.addTag(.@"return");2128 try func.addTag(.@"return");
21372129
2138 func.finishAir(inst, .none, &.{un_op});2130 return func.finishAir(inst, .none, &.{un_op});
2139}2131}
21402132
2141fn airRetPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {2133fn airRetPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -2156,7 +2148,7 @@ fn airRetPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -2156,7 +2148,7 @@ fn airRetPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
2156 break :result try func.allocStackPtr(inst);2148 break :result try func.allocStackPtr(inst);
2157 };2149 };
21582150
2159 func.finishAir(inst, result, &.{});2151 return func.finishAir(inst, result, &.{});
2160}2152}
21612153
2162fn airRetLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {2154fn airRetLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -2234,11 +2226,11 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif...@@ -2234,11 +2226,11 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
2234 return func.fail("Expected a function, but instead found '{s}'", .{@tagName(ip.indexToKey(func_val.toIntern()))});2226 return func.fail("Expected a function, but instead found '{s}'", .{@tagName(ip.indexToKey(func_val.toIntern()))});
2235 };2227 };
22362228
2237 const sret = if (first_param_sret) blk: {2229 const sret: WValue = if (first_param_sret) blk: {
2238 const sret_local = try func.allocStack(ret_ty);2230 const sret_local = try func.allocStack(ret_ty);
2239 try func.lowerToStack(sret_local);2231 try func.lowerToStack(sret_local);
2240 break :blk sret_local;2232 break :blk sret_local;
2241 } else WValue{ .none = {} };2233 } else .none;
22422234
2243 for (args) |arg| {2235 for (args) |arg| {
2244 const arg_val = try func.resolveInst(arg);2236 const arg_val = try func.resolveInst(arg);
...@@ -2268,10 +2260,10 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif...@@ -2268,10 +2260,10 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
22682260
2269 const result_value = result_value: {2261 const result_value = result_value: {
2270 if (!ret_ty.hasRuntimeBitsIgnoreComptime(pt) and !ret_ty.isError(mod)) {2262 if (!ret_ty.hasRuntimeBitsIgnoreComptime(pt) and !ret_ty.isError(mod)) {
2271 break :result_value WValue{ .none = {} };2263 break :result_value .none;
2272 } else if (ret_ty.isNoReturn(mod)) {2264 } else if (ret_ty.isNoReturn(mod)) {
2273 try func.addTag(.@"unreachable");2265 try func.addTag(.@"unreachable");
2274 break :result_value WValue{ .none = {} };2266 break :result_value .none;
2275 } else if (first_param_sret) {2267 } else if (first_param_sret) {
2276 break :result_value sret;2268 break :result_value sret;
2277 // TODO: Make this less fragile and optimize2269 // TODO: Make this less fragile and optimize
...@@ -2297,7 +2289,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif...@@ -2297,7 +2289,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
22972289
2298fn airAlloc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {2290fn airAlloc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
2299 const value = try func.allocStackPtr(inst);2291 const value = try func.allocStackPtr(inst);
2300 func.finishAir(inst, value, &.{});2292 return func.finishAir(inst, value, &.{});
2301}2293}
23022294
2303fn airStore(func: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void {2295fn airStore(func: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void {
...@@ -2330,18 +2322,18 @@ fn airStore(func: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void...@@ -2330,18 +2322,18 @@ fn airStore(func: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void
2330 var mask = @as(u64, @intCast((@as(u65, 1) << @as(u7, @intCast(ty.bitSize(pt)))) - 1));2322 var mask = @as(u64, @intCast((@as(u65, 1) << @as(u7, @intCast(ty.bitSize(pt)))) - 1));
2331 mask <<= @as(u6, @intCast(ptr_info.packed_offset.bit_offset));2323 mask <<= @as(u6, @intCast(ptr_info.packed_offset.bit_offset));
2332 mask ^= ~@as(u64, 0);2324 mask ^= ~@as(u64, 0);
2333 const shift_val = if (ptr_info.packed_offset.host_size <= 4)2325 const shift_val: WValue = if (ptr_info.packed_offset.host_size <= 4)
2334 WValue{ .imm32 = ptr_info.packed_offset.bit_offset }2326 .{ .imm32 = ptr_info.packed_offset.bit_offset }
2335 else2327 else
2336 WValue{ .imm64 = ptr_info.packed_offset.bit_offset };2328 .{ .imm64 = ptr_info.packed_offset.bit_offset };
2337 const mask_val = if (ptr_info.packed_offset.host_size <= 4)2329 const mask_val: WValue = if (ptr_info.packed_offset.host_size <= 4)
2338 WValue{ .imm32 = @as(u32, @truncate(mask)) }2330 .{ .imm32 = @as(u32, @truncate(mask)) }
2339 else2331 else
2340 WValue{ .imm64 = mask };2332 .{ .imm64 = mask };
2341 const wrap_mask_val = if (ptr_info.packed_offset.host_size <= 4)2333 const wrap_mask_val: WValue = if (ptr_info.packed_offset.host_size <= 4)
2342 WValue{ .imm32 = @truncate(~@as(u64, 0) >> @intCast(64 - ty.bitSize(pt))) }2334 .{ .imm32 = @truncate(~@as(u64, 0) >> @intCast(64 - ty.bitSize(pt))) }
2343 else2335 else
2344 WValue{ .imm64 = ~@as(u64, 0) >> @intCast(64 - ty.bitSize(pt)) };2336 .{ .imm64 = ~@as(u64, 0) >> @intCast(64 - ty.bitSize(pt)) };
23452337
2346 try func.emitWValue(lhs);2338 try func.emitWValue(lhs);
2347 const loaded = try func.load(lhs, int_elem_ty, 0);2339 const loaded = try func.load(lhs, int_elem_ty, 0);
...@@ -2356,7 +2348,7 @@ fn airStore(func: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void...@@ -2356,7 +2348,7 @@ fn airStore(func: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void
2356 try func.store(.stack, result, int_elem_ty, lhs.offset());2348 try func.store(.stack, result, int_elem_ty, lhs.offset());
2357 }2349 }
23582350
2359 func.finishAir(inst, .none, &.{ bin_op.lhs, bin_op.rhs });2351 return func.finishAir(inst, .none, &.{ bin_op.lhs, bin_op.rhs });
2360}2352}
23612353
2362fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerError!void {2354fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerError!void {
...@@ -2418,23 +2410,23 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE...@@ -2418,23 +2410,23 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE
2418 // lower it to the stack so we do not have to store rhs into a local first2410 // lower it to the stack so we do not have to store rhs into a local first
2419 try func.emitWValue(lhs);2411 try func.emitWValue(lhs);
2420 const ptr_local = try func.load(rhs, Type.usize, 0);2412 const ptr_local = try func.load(rhs, Type.usize, 0);
2421 try func.store(.{ .stack = {} }, ptr_local, Type.usize, 0 + lhs.offset());2413 try func.store(.stack, ptr_local, Type.usize, 0 + lhs.offset());
24222414
2423 // retrieve length from rhs, and store that alongside lhs as well2415 // retrieve length from rhs, and store that alongside lhs as well
2424 try func.emitWValue(lhs);2416 try func.emitWValue(lhs);
2425 const len_local = try func.load(rhs, Type.usize, func.ptrSize());2417 const len_local = try func.load(rhs, Type.usize, func.ptrSize());
2426 try func.store(.{ .stack = {} }, len_local, Type.usize, func.ptrSize() + lhs.offset());2418 try func.store(.stack, len_local, Type.usize, func.ptrSize() + lhs.offset());
2427 return;2419 return;
2428 }2420 }
2429 },2421 },
2430 .Int, .Enum, .Float => if (abi_size > 8 and abi_size <= 16) {2422 .Int, .Enum, .Float => if (abi_size > 8 and abi_size <= 16) {
2431 try func.emitWValue(lhs);2423 try func.emitWValue(lhs);
2432 const lsb = try func.load(rhs, Type.u64, 0);2424 const lsb = try func.load(rhs, Type.u64, 0);
2433 try func.store(.{ .stack = {} }, lsb, Type.u64, 0 + lhs.offset());2425 try func.store(.stack, lsb, Type.u64, 0 + lhs.offset());
24342426
2435 try func.emitWValue(lhs);2427 try func.emitWValue(lhs);
2436 const msb = try func.load(rhs, Type.u64, 8);2428 const msb = try func.load(rhs, Type.u64, 8);
2437 try func.store(.{ .stack = {} }, msb, Type.u64, 8 + lhs.offset());2429 try func.store(.stack, msb, Type.u64, 8 + lhs.offset());
2438 return;2430 return;
2439 } else if (abi_size > 16) {2431 } else if (abi_size > 16) {
2440 try func.memcpy(lhs, rhs, .{ .imm32 = @as(u32, @intCast(ty.abiSize(pt))) });2432 try func.memcpy(lhs, rhs, .{ .imm32 = @as(u32, @intCast(ty.abiSize(pt))) });
...@@ -2487,27 +2479,24 @@ fn airLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -2487,27 +2479,24 @@ fn airLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
2487 }2479 }
24882480
2489 if (ptr_info.packed_offset.host_size == 0) {2481 if (ptr_info.packed_offset.host_size == 0) {
2490 const stack_loaded = try func.load(operand, ty, 0);2482 break :result try func.load(operand, ty, 0);
2491 break :result try stack_loaded.toLocal(func, ty);
2492 }2483 }
24932484
2494 // at this point we have a non-natural alignment, we must2485 // at this point we have a non-natural alignment, we must
2495 // shift the value to obtain the correct bit.2486 // shift the value to obtain the correct bit.
2496 const int_elem_ty = try pt.intType(.unsigned, ptr_info.packed_offset.host_size * 8);2487 const int_elem_ty = try pt.intType(.unsigned, ptr_info.packed_offset.host_size * 8);
2497 const shift_val = if (ptr_info.packed_offset.host_size <= 4)2488 const shift_val: WValue = if (ptr_info.packed_offset.host_size <= 4)
2498 WValue{ .imm32 = ptr_info.packed_offset.bit_offset }2489 .{ .imm32 = ptr_info.packed_offset.bit_offset }
2499 else if (ptr_info.packed_offset.host_size <= 8)2490 else if (ptr_info.packed_offset.host_size <= 8)
2500 WValue{ .imm64 = ptr_info.packed_offset.bit_offset }2491 .{ .imm64 = ptr_info.packed_offset.bit_offset }
2501 else2492 else
2502 return func.fail("TODO: airLoad where ptr to bitfield exceeds 64 bits", .{});2493 return func.fail("TODO: airLoad where ptr to bitfield exceeds 64 bits", .{});
25032494
2504 const stack_loaded = try func.load(operand, int_elem_ty, 0);2495 const stack_loaded = try func.load(operand, int_elem_ty, 0);
2505 const shifted = try func.binOp(stack_loaded, shift_val, int_elem_ty, .shr);2496 const shifted = try func.binOp(stack_loaded, shift_val, int_elem_ty, .shr);
2506 const result = try func.trunc(shifted, ty, int_elem_ty);2497 break :result try func.trunc(shifted, ty, int_elem_ty);
2507 // const wrapped = try func.wrapOperand(shifted, ty);
2508 break :result try result.toLocal(func, ty);
2509 };2498 };
2510 func.finishAir(inst, result, &.{ty_op.operand});2499 return func.finishAir(inst, result, &.{ty_op.operand});
2511}2500}
25122501
2513/// Loads an operand from the linear memory section.2502/// Loads an operand from the linear memory section.
...@@ -2528,7 +2517,7 @@ fn load(func: *CodeGen, operand: WValue, ty: Type, offset: u32) InnerError!WValu...@@ -2528,7 +2517,7 @@ fn load(func: *CodeGen, operand: WValue, ty: Type, offset: u32) InnerError!WValu
2528 @intCast(ty.abiAlignment(pt).toByteUnits().?),2517 @intCast(ty.abiAlignment(pt).toByteUnits().?),
2529 });2518 });
2530 try func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } });2519 try func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } });
2531 return WValue{ .stack = {} };2520 return .stack;
2532 }2521 }
25332522
2534 const abi_size: u8 = @intCast(ty.abiSize(pt));2523 const abi_size: u8 = @intCast(ty.abiSize(pt));
...@@ -2547,7 +2536,7 @@ fn load(func: *CodeGen, operand: WValue, ty: Type, offset: u32) InnerError!WValu...@@ -2547,7 +2536,7 @@ fn load(func: *CodeGen, operand: WValue, ty: Type, offset: u32) InnerError!WValu
2547 },2536 },
2548 );2537 );
25492538
2550 return WValue{ .stack = {} };2539 return .stack;
2551}2540}
25522541
2553fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {2542fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -2596,7 +2585,7 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -2596,7 +2585,7 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
2596 else => {},2585 else => {},
2597 }2586 }
25982587
2599 func.finishAir(inst, arg, &.{});2588 return func.finishAir(inst, arg, &.{});
2600}2589}
26012590
2602fn airBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {2591fn airBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {
...@@ -2613,25 +2602,21 @@ fn airBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {...@@ -2613,25 +2602,21 @@ fn airBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {
2613 // case we first coerce the operands to the same type before performing the operation.2602 // case we first coerce the operands to the same type before performing the operation.
2614 // For big integers we can ignore this as we will call into compiler-rt which handles this.2603 // For big integers we can ignore this as we will call into compiler-rt which handles this.
2615 const result = switch (op) {2604 const result = switch (op) {
2616 .shr, .shl => res: {2605 .shr, .shl => result: {
2617 const lhs_wasm_bits = toWasmBits(@intCast(lhs_ty.bitSize(pt))) orelse {2606 const lhs_wasm_bits = toWasmBits(@intCast(lhs_ty.bitSize(pt))) orelse {
2618 return func.fail("TODO: implement '{s}' for types larger than 128 bits", .{@tagName(op)});2607 return func.fail("TODO: implement '{s}' for types larger than 128 bits", .{@tagName(op)});
2619 };2608 };
2620 const rhs_wasm_bits = toWasmBits(@intCast(rhs_ty.bitSize(pt))).?;2609 const rhs_wasm_bits = toWasmBits(@intCast(rhs_ty.bitSize(pt))).?;
2621 const new_rhs = if (lhs_wasm_bits != rhs_wasm_bits and lhs_wasm_bits != 128) blk: {2610 const new_rhs = if (lhs_wasm_bits != rhs_wasm_bits and lhs_wasm_bits != 128)
2622 const tmp = try func.intcast(rhs, rhs_ty, lhs_ty);2611 try (try func.intcast(rhs, rhs_ty, lhs_ty)).toLocal(func, lhs_ty)
2623 break :blk try tmp.toLocal(func, lhs_ty);2612 else
2624 } else rhs;2613 rhs;
2625 const stack_result = try func.binOp(lhs, new_rhs, lhs_ty, op);2614 break :result try func.binOp(lhs, new_rhs, lhs_ty, op);
2626 break :res try stack_result.toLocal(func, lhs_ty);
2627 },
2628 else => res: {
2629 const stack_result = try func.binOp(lhs, rhs, lhs_ty, op);
2630 break :res try stack_result.toLocal(func, lhs_ty);
2631 },2615 },
2616 else => try func.binOp(lhs, rhs, lhs_ty, op),
2632 };2617 };
26332618
2634 func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });2619 return func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });
2635}2620}
26362621
2637/// Performs a binary operation on the given `WValue`'s2622/// Performs a binary operation on the given `WValue`'s
...@@ -2667,7 +2652,7 @@ fn binOp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError!...@@ -2667,7 +2652,7 @@ fn binOp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError!
26672652
2668 try func.addTag(Mir.Inst.Tag.fromOpcode(opcode));2653 try func.addTag(Mir.Inst.Tag.fromOpcode(opcode));
26692654
2670 return WValue{ .stack = {} };2655 return .stack;
2671}2656}
26722657
2673fn binOpBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError!WValue {2658fn binOpBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError!WValue {
...@@ -2839,6 +2824,7 @@ fn airAbs(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -2839,6 +2824,7 @@ fn airAbs(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
2839 try func.addTag(.i32_xor);2824 try func.addTag(.i32_xor);
2840 try func.emitWValue(tmp);2825 try func.emitWValue(tmp);
2841 try func.addTag(.i32_sub);2826 try func.addTag(.i32_sub);
2827 return func.finishAir(inst, .stack, &.{ty_op.operand});
2842 },2828 },
2843 64 => {2829 64 => {
2844 try func.emitWValue(operand);2830 try func.emitWValue(operand);
...@@ -2854,6 +2840,7 @@ fn airAbs(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -2854,6 +2840,7 @@ fn airAbs(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
2854 try func.addTag(.i64_xor);2840 try func.addTag(.i64_xor);
2855 try func.emitWValue(tmp);2841 try func.emitWValue(tmp);
2856 try func.addTag(.i64_sub);2842 try func.addTag(.i64_sub);
2843 return func.finishAir(inst, .stack, &.{ty_op.operand});
2857 },2844 },
2858 128 => {2845 128 => {
2859 const mask = try func.allocStack(Type.u128);2846 const mask = try func.allocStack(Type.u128);
...@@ -2874,18 +2861,14 @@ fn airAbs(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -2874,18 +2861,14 @@ fn airAbs(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
2874 const a = try func.binOpBigInt(operand, mask, Type.u128, .xor);2861 const a = try func.binOpBigInt(operand, mask, Type.u128, .xor);
2875 const b = try func.binOpBigInt(a, mask, Type.u128, .sub);2862 const b = try func.binOpBigInt(a, mask, Type.u128, .sub);
28762863
2877 func.finishAir(inst, b, &.{ty_op.operand});2864 return func.finishAir(inst, b, &.{ty_op.operand});
2878 return;
2879 },2865 },
2880 else => unreachable,2866 else => unreachable,
2881 }2867 }
2882
2883 const result = try (WValue{ .stack = {} }).toLocal(func, ty);
2884 func.finishAir(inst, result, &.{ty_op.operand});
2885 },2868 },
2886 .Float => {2869 .Float => {
2887 const result = try (try func.floatOp(.fabs, ty, &.{operand})).toLocal(func, ty);2870 const result = try func.floatOp(.fabs, ty, &.{operand});
2888 func.finishAir(inst, result, &.{ty_op.operand});2871 return func.finishAir(inst, result, &.{ty_op.operand});
2889 },2872 },
2890 else => unreachable,2873 else => unreachable,
2891 }2874 }
...@@ -2896,8 +2879,8 @@ fn airUnaryFloatOp(func: *CodeGen, inst: Air.Inst.Index, op: FloatOp) InnerError...@@ -2896,8 +2879,8 @@ fn airUnaryFloatOp(func: *CodeGen, inst: Air.Inst.Index, op: FloatOp) InnerError
2896 const operand = try func.resolveInst(un_op);2879 const operand = try func.resolveInst(un_op);
2897 const ty = func.typeOf(un_op);2880 const ty = func.typeOf(un_op);
28982881
2899 const result = try (try func.floatOp(op, ty, &.{operand})).toLocal(func, ty);2882 const result = try func.floatOp(op, ty, &.{operand});
2900 func.finishAir(inst, result, &.{un_op});2883 return func.finishAir(inst, result, &.{un_op});
2901}2884}
29022885
2903fn floatOp(func: *CodeGen, float_op: FloatOp, ty: Type, args: []const WValue) InnerError!WValue {2886fn floatOp(func: *CodeGen, float_op: FloatOp, ty: Type, args: []const WValue) InnerError!WValue {
...@@ -3027,22 +3010,18 @@ fn airWrapBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {...@@ -3027,22 +3010,18 @@ fn airWrapBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {
3027 // case we first coerce the operands to the same type before performing the operation.3010 // case we first coerce the operands to the same type before performing the operation.
3028 // For big integers we can ignore this as we will call into compiler-rt which handles this.3011 // For big integers we can ignore this as we will call into compiler-rt which handles this.
3029 const result = switch (op) {3012 const result = switch (op) {
3030 .shr, .shl => res: {3013 .shr, .shl => result: {
3031 const lhs_wasm_bits = toWasmBits(@intCast(lhs_ty.bitSize(pt))) orelse {3014 const lhs_wasm_bits = toWasmBits(@intCast(lhs_ty.bitSize(pt))) orelse {
3032 return func.fail("TODO: implement '{s}' for types larger than 128 bits", .{@tagName(op)});3015 return func.fail("TODO: implement '{s}' for types larger than 128 bits", .{@tagName(op)});
3033 };3016 };
3034 const rhs_wasm_bits = toWasmBits(@intCast(rhs_ty.bitSize(pt))).?;3017 const rhs_wasm_bits = toWasmBits(@intCast(rhs_ty.bitSize(pt))).?;
3035 const new_rhs = if (lhs_wasm_bits != rhs_wasm_bits and lhs_wasm_bits != 128) blk: {3018 const new_rhs = if (lhs_wasm_bits != rhs_wasm_bits and lhs_wasm_bits != 128)
3036 const tmp = try func.intcast(rhs, rhs_ty, lhs_ty);3019 try (try func.intcast(rhs, rhs_ty, lhs_ty)).toLocal(func, lhs_ty)
3037 break :blk try tmp.toLocal(func, lhs_ty);3020 else
3038 } else rhs;3021 rhs;
3039 const stack_result = try func.wrapBinOp(lhs, new_rhs, lhs_ty, op);3022 break :result try func.wrapBinOp(lhs, new_rhs, lhs_ty, op);
3040 break :res try stack_result.toLocal(func, lhs_ty);
3041 },
3042 else => res: {
3043 const stack_result = try func.wrapBinOp(lhs, rhs, lhs_ty, op);
3044 break :res try stack_result.toLocal(func, lhs_ty);
3045 },3023 },
3024 else => try func.wrapBinOp(lhs, rhs, lhs_ty, op),
3046 };3025 };
30473026
3048 return func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });3027 return func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });
...@@ -3187,7 +3166,7 @@ fn lowerAnonDeclRef(...@@ -3187,7 +3166,7 @@ fn lowerAnonDeclRef(
31873166
3188 const is_fn_body = ty.zigTypeTag(mod) == .Fn;3167 const is_fn_body = ty.zigTypeTag(mod) == .Fn;
3189 if (!is_fn_body and !ty.hasRuntimeBitsIgnoreComptime(pt)) {3168 if (!is_fn_body and !ty.hasRuntimeBitsIgnoreComptime(pt)) {
3190 return WValue{ .imm32 = 0xaaaaaaaa };3169 return .{ .imm32 = 0xaaaaaaaa };
3191 }3170 }
31923171
3193 const decl_align = mod.intern_pool.indexToKey(anon_decl.orig_ty).ptr_type.flags.alignment;3172 const decl_align = mod.intern_pool.indexToKey(anon_decl.orig_ty).ptr_type.flags.alignment;
...@@ -3202,10 +3181,10 @@ fn lowerAnonDeclRef(...@@ -3202,10 +3181,10 @@ fn lowerAnonDeclRef(
3202 const target_atom_index = func.bin_file.zigObjectPtr().?.anon_decls.get(decl_val).?;3181 const target_atom_index = func.bin_file.zigObjectPtr().?.anon_decls.get(decl_val).?;
3203 const target_sym_index = @intFromEnum(func.bin_file.getAtom(target_atom_index).sym_index);3182 const target_sym_index = @intFromEnum(func.bin_file.getAtom(target_atom_index).sym_index);
3204 if (is_fn_body) {3183 if (is_fn_body) {
3205 return WValue{ .function_index = target_sym_index };3184 return .{ .function_index = target_sym_index };
3206 } else if (offset == 0) {3185 } else if (offset == 0) {
3207 return WValue{ .memory = target_sym_index };3186 return .{ .memory = target_sym_index };
3208 } else return WValue{ .memory_offset = .{ .pointer = target_sym_index, .offset = offset } };3187 } else return .{ .memory_offset = .{ .pointer = target_sym_index, .offset = offset } };
3209}3188}
32103189
3211fn lowerDeclRefValue(func: *CodeGen, decl_index: InternPool.DeclIndex, offset: u32) InnerError!WValue {3190fn lowerDeclRefValue(func: *CodeGen, decl_index: InternPool.DeclIndex, offset: u32) InnerError!WValue {
...@@ -3226,7 +3205,7 @@ fn lowerDeclRefValue(func: *CodeGen, decl_index: InternPool.DeclIndex, offset: u...@@ -3226,7 +3205,7 @@ fn lowerDeclRefValue(func: *CodeGen, decl_index: InternPool.DeclIndex, offset: u
3226 }3205 }
3227 const decl_ty = decl.typeOf(mod);3206 const decl_ty = decl.typeOf(mod);
3228 if (decl_ty.zigTypeTag(mod) != .Fn and !decl_ty.hasRuntimeBitsIgnoreComptime(pt)) {3207 if (decl_ty.zigTypeTag(mod) != .Fn and !decl_ty.hasRuntimeBitsIgnoreComptime(pt)) {
3229 return WValue{ .imm32 = 0xaaaaaaaa };3208 return .{ .imm32 = 0xaaaaaaaa };
3230 }3209 }
32313210
3232 const atom_index = try func.bin_file.getOrCreateAtomForDecl(pt, decl_index);3211 const atom_index = try func.bin_file.getOrCreateAtomForDecl(pt, decl_index);
...@@ -3234,10 +3213,10 @@ fn lowerDeclRefValue(func: *CodeGen, decl_index: InternPool.DeclIndex, offset: u...@@ -3234,10 +3213,10 @@ fn lowerDeclRefValue(func: *CodeGen, decl_index: InternPool.DeclIndex, offset: u
32343213
3235 const target_sym_index = @intFromEnum(atom.sym_index);3214 const target_sym_index = @intFromEnum(atom.sym_index);
3236 if (decl_ty.zigTypeTag(mod) == .Fn) {3215 if (decl_ty.zigTypeTag(mod) == .Fn) {
3237 return WValue{ .function_index = target_sym_index };3216 return .{ .function_index = target_sym_index };
3238 } else if (offset == 0) {3217 } else if (offset == 0) {
3239 return WValue{ .memory = target_sym_index };3218 return .{ .memory = target_sym_index };
3240 } else return WValue{ .memory_offset = .{ .pointer = target_sym_index, .offset = offset } };3219 } else return .{ .memory_offset = .{ .pointer = target_sym_index, .offset = offset } };
3241}3220}
32423221
3243/// Asserts that `isByRef` returns `false` for `ty`.3222/// Asserts that `isByRef` returns `false` for `ty`.
...@@ -3276,7 +3255,7 @@ fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue {...@@ -3276,7 +3255,7 @@ fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue {
3276 .@"unreachable",3255 .@"unreachable",
3277 .generic_poison,3256 .generic_poison,
3278 => unreachable, // non-runtime values3257 => unreachable, // non-runtime values
3279 .false, .true => return WValue{ .imm32 = switch (simple_value) {3258 .false, .true => return .{ .imm32 = switch (simple_value) {
3280 .false => 0,3259 .false => 0,
3281 .true => 1,3260 .true => 1,
3282 else => unreachable,3261 else => unreachable,
...@@ -3292,20 +3271,20 @@ fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue {...@@ -3292,20 +3271,20 @@ fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue {
3292 const int_info = ty.intInfo(mod);3271 const int_info = ty.intInfo(mod);
3293 switch (int_info.signedness) {3272 switch (int_info.signedness) {
3294 .signed => switch (int_info.bits) {3273 .signed => switch (int_info.bits) {
3295 0...32 => return WValue{ .imm32 = @bitCast(@as(i32, @intCast(val.toSignedInt(pt)))) },3274 0...32 => return .{ .imm32 = @bitCast(@as(i32, @intCast(val.toSignedInt(pt)))) },
3296 33...64 => return WValue{ .imm64 = @bitCast(val.toSignedInt(pt)) },3275 33...64 => return .{ .imm64 = @bitCast(val.toSignedInt(pt)) },
3297 else => unreachable,3276 else => unreachable,
3298 },3277 },
3299 .unsigned => switch (int_info.bits) {3278 .unsigned => switch (int_info.bits) {
3300 0...32 => return WValue{ .imm32 = @intCast(val.toUnsignedInt(pt)) },3279 0...32 => return .{ .imm32 = @intCast(val.toUnsignedInt(pt)) },
3301 33...64 => return WValue{ .imm64 = val.toUnsignedInt(pt) },3280 33...64 => return .{ .imm64 = val.toUnsignedInt(pt) },
3302 else => unreachable,3281 else => unreachable,
3303 },3282 },
3304 }3283 }
3305 },3284 },
3306 .err => |err| {3285 .err => |err| {
3307 const int = try pt.getErrorValue(err.name);3286 const int = try pt.getErrorValue(err.name);
3308 return WValue{ .imm32 = int };3287 return .{ .imm32 = int };
3309 },3288 },
3310 .error_union => |error_union| {3289 .error_union => |error_union| {
3311 const err_int_ty = try pt.errorIntType();3290 const err_int_ty = try pt.errorIntType();
...@@ -3335,9 +3314,9 @@ fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue {...@@ -3335,9 +3314,9 @@ fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue {
3335 return func.lowerConstant(Value.fromInterned(enum_tag.int), Type.fromInterned(int_tag_ty));3314 return func.lowerConstant(Value.fromInterned(enum_tag.int), Type.fromInterned(int_tag_ty));
3336 },3315 },
3337 .float => |float| switch (float.storage) {3316 .float => |float| switch (float.storage) {
3338 .f16 => |f16_val| return WValue{ .imm32 = @as(u16, @bitCast(f16_val)) },3317 .f16 => |f16_val| return .{ .imm32 = @as(u16, @bitCast(f16_val)) },
3339 .f32 => |f32_val| return WValue{ .float32 = f32_val },3318 .f32 => |f32_val| return .{ .float32 = f32_val },
3340 .f64 => |f64_val| return WValue{ .float64 = f64_val },3319 .f64 => |f64_val| return .{ .float64 = f64_val },
3341 else => unreachable,3320 else => unreachable,
3342 },3321 },
3343 .slice => |slice| {3322 .slice => |slice| {
...@@ -3357,10 +3336,10 @@ fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue {...@@ -3357,10 +3336,10 @@ fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue {
3357 if (val.optionalValue(mod)) |payload| {3336 if (val.optionalValue(mod)) |payload| {
3358 return func.lowerConstant(payload, pl_ty);3337 return func.lowerConstant(payload, pl_ty);
3359 } else {3338 } else {
3360 return WValue{ .imm32 = 0 };3339 return .{ .imm32 = 0 };
3361 }3340 }
3362 } else {3341 } else {
3363 return WValue{ .imm32 = @intFromBool(!val.isNull(mod)) };3342 return .{ .imm32 = @intFromBool(!val.isNull(mod)) };
3364 },3343 },
3365 .aggregate => switch (ip.indexToKey(ty.ip_index)) {3344 .aggregate => switch (ip.indexToKey(ty.ip_index)) {
3366 .array_type => return func.fail("Wasm TODO: LowerConstant for {}", .{ty.fmt(pt)}),3345 .array_type => return func.fail("Wasm TODO: LowerConstant for {}", .{ty.fmt(pt)}),
...@@ -3406,7 +3385,7 @@ fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue {...@@ -3406,7 +3385,7 @@ fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue {
3406fn storeSimdImmd(func: *CodeGen, value: [16]u8) !WValue {3385fn storeSimdImmd(func: *CodeGen, value: [16]u8) !WValue {
3407 const index = @as(u32, @intCast(func.simd_immediates.items.len));3386 const index = @as(u32, @intCast(func.simd_immediates.items.len));
3408 try func.simd_immediates.append(func.gpa, value);3387 try func.simd_immediates.append(func.gpa, value);
3409 return WValue{ .imm128 = index };3388 return .{ .imm128 = index };
3410}3389}
34113390
3412fn emitUndefined(func: *CodeGen, ty: Type) InnerError!WValue {3391fn emitUndefined(func: *CodeGen, ty: Type) InnerError!WValue {
...@@ -3414,21 +3393,21 @@ fn emitUndefined(func: *CodeGen, ty: Type) InnerError!WValue {...@@ -3414,21 +3393,21 @@ fn emitUndefined(func: *CodeGen, ty: Type) InnerError!WValue {
3414 const mod = pt.zcu;3393 const mod = pt.zcu;
3415 const ip = &mod.intern_pool;3394 const ip = &mod.intern_pool;
3416 switch (ty.zigTypeTag(mod)) {3395 switch (ty.zigTypeTag(mod)) {
3417 .Bool, .ErrorSet => return WValue{ .imm32 = 0xaaaaaaaa },3396 .Bool, .ErrorSet => return .{ .imm32 = 0xaaaaaaaa },
3418 .Int, .Enum => switch (ty.intInfo(mod).bits) {3397 .Int, .Enum => switch (ty.intInfo(mod).bits) {
3419 0...32 => return WValue{ .imm32 = 0xaaaaaaaa },3398 0...32 => return .{ .imm32 = 0xaaaaaaaa },
3420 33...64 => return WValue{ .imm64 = 0xaaaaaaaaaaaaaaaa },3399 33...64 => return .{ .imm64 = 0xaaaaaaaaaaaaaaaa },
3421 else => unreachable,3400 else => unreachable,
3422 },3401 },
3423 .Float => switch (ty.floatBits(func.target)) {3402 .Float => switch (ty.floatBits(func.target)) {
3424 16 => return WValue{ .imm32 = 0xaaaaaaaa },3403 16 => return .{ .imm32 = 0xaaaaaaaa },
3425 32 => return WValue{ .float32 = @as(f32, @bitCast(@as(u32, 0xaaaaaaaa))) },3404 32 => return .{ .float32 = @as(f32, @bitCast(@as(u32, 0xaaaaaaaa))) },
3426 64 => return WValue{ .float64 = @as(f64, @bitCast(@as(u64, 0xaaaaaaaaaaaaaaaa))) },3405 64 => return .{ .float64 = @as(f64, @bitCast(@as(u64, 0xaaaaaaaaaaaaaaaa))) },
3427 else => unreachable,3406 else => unreachable,
3428 },3407 },
3429 .Pointer => switch (func.arch()) {3408 .Pointer => switch (func.arch()) {
3430 .wasm32 => return WValue{ .imm32 = 0xaaaaaaaa },3409 .wasm32 => return .{ .imm32 = 0xaaaaaaaa },
3431 .wasm64 => return WValue{ .imm64 = 0xaaaaaaaaaaaaaaaa },3410 .wasm64 => return .{ .imm64 = 0xaaaaaaaaaaaaaaaa },
3432 else => unreachable,3411 else => unreachable,
3433 },3412 },
3434 .Optional => {3413 .Optional => {
...@@ -3436,10 +3415,10 @@ fn emitUndefined(func: *CodeGen, ty: Type) InnerError!WValue {...@@ -3436,10 +3415,10 @@ fn emitUndefined(func: *CodeGen, ty: Type) InnerError!WValue {
3436 if (ty.optionalReprIsPayload(mod)) {3415 if (ty.optionalReprIsPayload(mod)) {
3437 return func.emitUndefined(pl_ty);3416 return func.emitUndefined(pl_ty);
3438 }3417 }
3439 return WValue{ .imm32 = 0xaaaaaaaa };3418 return .{ .imm32 = 0xaaaaaaaa };
3440 },3419 },
3441 .ErrorUnion => {3420 .ErrorUnion => {
3442 return WValue{ .imm32 = 0xaaaaaaaa };3421 return .{ .imm32 = 0xaaaaaaaa };
3443 },3422 },
3444 .Struct => {3423 .Struct => {
3445 const packed_struct = mod.typeToPackedStruct(ty).?;3424 const packed_struct = mod.typeToPackedStruct(ty).?;
...@@ -3501,7 +3480,7 @@ fn lowerBlock(func: *CodeGen, inst: Air.Inst.Index, block_ty: Type, body: []cons...@@ -3501,7 +3480,7 @@ fn lowerBlock(func: *CodeGen, inst: Air.Inst.Index, block_ty: Type, body: []cons
3501 const block_result: WValue = if (wasm_block_ty != wasm.block_empty) blk: {3480 const block_result: WValue = if (wasm_block_ty != wasm.block_empty) blk: {
3502 const ty: Type = if (isByRef(block_ty, pt)) Type.u32 else block_ty;3481 const ty: Type = if (isByRef(block_ty, pt)) Type.u32 else block_ty;
3503 break :blk try func.ensureAllocLocal(ty); // make sure it's a clean local as it may never get overwritten3482 break :blk try func.ensureAllocLocal(ty); // make sure it's a clean local as it may never get overwritten
3504 } else WValue.none;3483 } else .none;
35053484
3506 try func.startBlock(.block, wasm.block_empty);3485 try func.startBlock(.block, wasm.block_empty);
3507 // Here we set the current block idx, so breaks know the depth to jump3486 // Here we set the current block idx, so breaks know the depth to jump
...@@ -3517,7 +3496,7 @@ fn lowerBlock(func: *CodeGen, inst: Air.Inst.Index, block_ty: Type, body: []cons...@@ -3517,7 +3496,7 @@ fn lowerBlock(func: *CodeGen, inst: Air.Inst.Index, block_ty: Type, body: []cons
3517 const liveness = func.liveness.getBlock(inst);3496 const liveness = func.liveness.getBlock(inst);
3518 try func.currentBranch().values.ensureUnusedCapacity(func.gpa, liveness.deaths.len);3497 try func.currentBranch().values.ensureUnusedCapacity(func.gpa, liveness.deaths.len);
35193498
3520 func.finishAir(inst, block_result, &.{});3499 return func.finishAir(inst, block_result, &.{});
3521}3500}
35223501
3523/// appends a new wasm block to the code section and increases the `block_depth` by 13502/// appends a new wasm block to the code section and increases the `block_depth` by 1
...@@ -3549,7 +3528,7 @@ fn airLoop(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -3549,7 +3528,7 @@ fn airLoop(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3549 try func.addLabel(.br, 0);3528 try func.addLabel(.br, 0);
3550 try func.endBlock();3529 try func.endBlock();
35513530
3552 func.finishAir(inst, .none, &.{});3531 return func.finishAir(inst, .none, &.{});
3553}3532}
35543533
3555fn airCondBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {3534fn airCondBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -3593,7 +3572,7 @@ fn airCondBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -3593,7 +3572,7 @@ fn airCondBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3593 try func.genBody(then_body);3572 try func.genBody(then_body);
3594 }3573 }
35953574
3596 func.finishAir(inst, .none, &.{});3575 return func.finishAir(inst, .none, &.{});
3597}3576}
35983577
3599fn airCmp(func: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) InnerError!void {3578fn airCmp(func: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) InnerError!void {
...@@ -3602,8 +3581,8 @@ fn airCmp(func: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) In...@@ -3602,8 +3581,8 @@ fn airCmp(func: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) In
3602 const lhs = try func.resolveInst(bin_op.lhs);3581 const lhs = try func.resolveInst(bin_op.lhs);
3603 const rhs = try func.resolveInst(bin_op.rhs);3582 const rhs = try func.resolveInst(bin_op.rhs);
3604 const operand_ty = func.typeOf(bin_op.lhs);3583 const operand_ty = func.typeOf(bin_op.lhs);
3605 const result = try (try func.cmp(lhs, rhs, operand_ty, op)).toLocal(func, Type.u32); // comparison result is always 32 bits3584 const result = try func.cmp(lhs, rhs, operand_ty, op);
3606 func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });3585 return func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });
3607}3586}
36083587
3609/// Compares two operands.3588/// Compares two operands.
...@@ -3654,7 +3633,7 @@ fn cmp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: std.math.CompareO...@@ -3654,7 +3633,7 @@ fn cmp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: std.math.CompareO
3654 });3633 });
3655 try func.addTag(Mir.Inst.Tag.fromOpcode(opcode));3634 try func.addTag(Mir.Inst.Tag.fromOpcode(opcode));
36563635
3657 return WValue{ .stack = {} };3636 return .stack;
3658}3637}
36593638
3660/// Compares two floats.3639/// Compares two floats.
...@@ -3694,7 +3673,7 @@ fn cmpFloat(func: *CodeGen, ty: Type, lhs: WValue, rhs: WValue, cmp_op: std.math...@@ -3694,7 +3673,7 @@ fn cmpFloat(func: *CodeGen, ty: Type, lhs: WValue, rhs: WValue, cmp_op: std.math
3694 }) catch unreachable;3673 }) catch unreachable;
36953674
3696 const result = try func.callIntrinsic(fn_name, &.{ ty.ip_index, ty.ip_index }, Type.bool, &.{ lhs, rhs });3675 const result = try func.callIntrinsic(fn_name, &.{ ty.ip_index, ty.ip_index }, Type.bool, &.{ lhs, rhs });
3697 return func.cmp(result, WValue{ .imm32 = 0 }, Type.i32, cmp_op);3676 return func.cmp(result, .{ .imm32 = 0 }, Type.i32, cmp_op);
3698 },3677 },
3699 else => unreachable,3678 else => unreachable,
3700 }3679 }
...@@ -3709,7 +3688,7 @@ fn airCmpLtErrorsLen(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -3709,7 +3688,7 @@ fn airCmpLtErrorsLen(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3709 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;3688 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
3710 const operand = try func.resolveInst(un_op);3689 const operand = try func.resolveInst(un_op);
3711 const sym_index = try func.bin_file.getGlobalSymbol("__zig_errors_len", null);3690 const sym_index = try func.bin_file.getGlobalSymbol("__zig_errors_len", null);
3712 const errors_len = WValue{ .memory = @intFromEnum(sym_index) };3691 const errors_len = .{ .memory = @intFromEnum(sym_index) };
37133692
3714 try func.emitWValue(operand);3693 try func.emitWValue(operand);
3715 const pt = func.pt;3694 const pt = func.pt;
...@@ -3717,7 +3696,7 @@ fn airCmpLtErrorsLen(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -3717,7 +3696,7 @@ fn airCmpLtErrorsLen(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3717 const errors_len_val = try func.load(errors_len, err_int_ty, 0);3696 const errors_len_val = try func.load(errors_len, err_int_ty, 0);
3718 const result = try func.cmp(.stack, errors_len_val, err_int_ty, .lt);3697 const result = try func.cmp(.stack, errors_len_val, err_int_ty, .lt);
37193698
3720 return func.finishAir(inst, try result.toLocal(func, Type.bool), &.{un_op});3699 return func.finishAir(inst, result, &.{un_op});
3721}3700}
37223701
3723fn airBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {3702fn airBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -3740,7 +3719,7 @@ fn airBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -3740,7 +3719,7 @@ fn airBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3740 const idx: u32 = func.block_depth - block.label;3719 const idx: u32 = func.block_depth - block.label;
3741 try func.addLabel(.br, idx);3720 try func.addLabel(.br, idx);
37423721
3743 func.finishAir(inst, .none, &.{br.operand});3722 return func.finishAir(inst, .none, &.{br.operand});
3744}3723}
37453724
3746fn airNot(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {3725fn airNot(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -3772,7 +3751,7 @@ fn airNot(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -3772,7 +3751,7 @@ fn airNot(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3772 .signed => ~@as(u32, 0),3751 .signed => ~@as(u32, 0),
3773 });3752 });
3774 try func.addTag(.i32_xor);3753 try func.addTag(.i32_xor);
3775 break :result try @as(WValue, .stack).toLocal(func, operand_ty);3754 break :result .stack;
3776 },3755 },
3777 64 => {3756 64 => {
3778 try func.emitWValue(operand);3757 try func.emitWValue(operand);
...@@ -3781,7 +3760,7 @@ fn airNot(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -3781,7 +3760,7 @@ fn airNot(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3781 .signed => ~@as(u64, 0),3760 .signed => ~@as(u64, 0),
3782 });3761 });
3783 try func.addTag(.i64_xor);3762 try func.addTag(.i64_xor);
3784 break :result try @as(WValue, .stack).toLocal(func, operand_ty);3763 break :result .stack;
3785 },3764 },
3786 128 => {3765 128 => {
3787 const ptr = try func.allocStack(operand_ty);3766 const ptr = try func.allocStack(operand_ty);
...@@ -3807,24 +3786,24 @@ fn airNot(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -3807,24 +3786,24 @@ fn airNot(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3807 }3786 }
3808 }3787 }
3809 };3788 };
3810 func.finishAir(inst, result, &.{ty_op.operand});3789 return func.finishAir(inst, result, &.{ty_op.operand});
3811}3790}
38123791
3813fn airTrap(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {3792fn airTrap(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3814 try func.addTag(.@"unreachable");3793 try func.addTag(.@"unreachable");
3815 func.finishAir(inst, .none, &.{});3794 return func.finishAir(inst, .none, &.{});
3816}3795}
38173796
3818fn airBreakpoint(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {3797fn airBreakpoint(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3819 // unsupported by wasm itfunc. Can be implemented once we support DWARF3798 // unsupported by wasm itfunc. Can be implemented once we support DWARF
3820 // for wasm3799 // for wasm
3821 try func.addTag(.@"unreachable");3800 try func.addTag(.@"unreachable");
3822 func.finishAir(inst, .none, &.{});3801 return func.finishAir(inst, .none, &.{});
3823}3802}
38243803
3825fn airUnreachable(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {3804fn airUnreachable(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3826 try func.addTag(.@"unreachable");3805 try func.addTag(.@"unreachable");
3827 func.finishAir(inst, .none, &.{});3806 return func.finishAir(inst, .none, &.{});
3828}3807}
38293808
3830fn airBitcast(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {3809fn airBitcast(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -3841,35 +3820,34 @@ fn airBitcast(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -3841,35 +3820,34 @@ fn airBitcast(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
38413820
3842 const result = result: {3821 const result = result: {
3843 if (given_ty.isAnyFloat() or wanted_ty.isAnyFloat()) {3822 if (given_ty.isAnyFloat() or wanted_ty.isAnyFloat()) {
3844 const bitcast_result = try func.bitcast(wanted_ty, given_ty, operand);3823 break :result try func.bitcast(wanted_ty, given_ty, operand);
3845 break :result try bitcast_result.toLocal(func, wanted_ty);
3846 }3824 }
38473825
3848 if (isByRef(given_ty, pt) and !isByRef(wanted_ty, pt)) {3826 if (isByRef(given_ty, pt) and !isByRef(wanted_ty, pt)) {
3849 const loaded_memory = try func.load(operand, wanted_ty, 0);3827 const loaded_memory = try func.load(operand, wanted_ty, 0);
3850 if (needs_wrapping) {3828 if (needs_wrapping) {
3851 break :result try (try func.wrapOperand(loaded_memory, wanted_ty)).toLocal(func, wanted_ty);3829 break :result try func.wrapOperand(loaded_memory, wanted_ty);
3852 } else {3830 } else {
3853 break :result try loaded_memory.toLocal(func, wanted_ty);3831 break :result loaded_memory;
3854 }3832 }
3855 }3833 }
3856 if (!isByRef(given_ty, pt) and isByRef(wanted_ty, pt)) {3834 if (!isByRef(given_ty, pt) and isByRef(wanted_ty, pt)) {
3857 const stack_memory = try func.allocStack(wanted_ty);3835 const stack_memory = try func.allocStack(wanted_ty);
3858 try func.store(stack_memory, operand, given_ty, 0);3836 try func.store(stack_memory, operand, given_ty, 0);
3859 if (needs_wrapping) {3837 if (needs_wrapping) {
3860 break :result try (try func.wrapOperand(stack_memory, wanted_ty)).toLocal(func, wanted_ty);3838 break :result try func.wrapOperand(stack_memory, wanted_ty);
3861 } else {3839 } else {
3862 break :result stack_memory;3840 break :result stack_memory;
3863 }3841 }
3864 }3842 }
38653843
3866 if (needs_wrapping) {3844 if (needs_wrapping) {
3867 break :result try (try func.wrapOperand(operand, wanted_ty)).toLocal(func, wanted_ty);3845 break :result try func.wrapOperand(operand, wanted_ty);
3868 }3846 }
38693847
3870 break :result func.reuseOperand(ty_op.operand, operand);3848 break :result func.reuseOperand(ty_op.operand, operand);
3871 };3849 };
3872 func.finishAir(inst, result, &.{ty_op.operand});3850 return func.finishAir(inst, result, &.{ty_op.operand});
3873}3851}
38743852
3875fn bitcast(func: *CodeGen, wanted_ty: Type, given_ty: Type, operand: WValue) InnerError!WValue {3853fn bitcast(func: *CodeGen, wanted_ty: Type, given_ty: Type, operand: WValue) InnerError!WValue {
...@@ -3888,7 +3866,7 @@ fn bitcast(func: *CodeGen, wanted_ty: Type, given_ty: Type, operand: WValue) Inn...@@ -3888,7 +3866,7 @@ fn bitcast(func: *CodeGen, wanted_ty: Type, given_ty: Type, operand: WValue) Inn
3888 });3866 });
3889 try func.emitWValue(operand);3867 try func.emitWValue(operand);
3890 try func.addTag(Mir.Inst.Tag.fromOpcode(opcode));3868 try func.addTag(Mir.Inst.Tag.fromOpcode(opcode));
3891 return WValue{ .stack = {} };3869 return .stack;
3892}3870}
38933871
3894fn airStructFieldPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {3872fn airStructFieldPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -3901,7 +3879,7 @@ fn airStructFieldPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -3901,7 +3879,7 @@ fn airStructFieldPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3901 const struct_ptr_ty = func.typeOf(extra.data.struct_operand);3879 const struct_ptr_ty = func.typeOf(extra.data.struct_operand);
3902 const struct_ty = struct_ptr_ty.childType(mod);3880 const struct_ty = struct_ptr_ty.childType(mod);
3903 const result = try func.structFieldPtr(inst, extra.data.struct_operand, struct_ptr, struct_ptr_ty, struct_ty, extra.data.field_index);3881 const result = try func.structFieldPtr(inst, extra.data.struct_operand, struct_ptr, struct_ptr_ty, struct_ty, extra.data.field_index);
3904 func.finishAir(inst, result, &.{extra.data.struct_operand});3882 return func.finishAir(inst, result, &.{extra.data.struct_operand});
3905}3883}
39063884
3907fn airStructFieldPtrIndex(func: *CodeGen, inst: Air.Inst.Index, index: u32) InnerError!void {3885fn airStructFieldPtrIndex(func: *CodeGen, inst: Air.Inst.Index, index: u32) InnerError!void {
...@@ -3913,7 +3891,7 @@ fn airStructFieldPtrIndex(func: *CodeGen, inst: Air.Inst.Index, index: u32) Inne...@@ -3913,7 +3891,7 @@ fn airStructFieldPtrIndex(func: *CodeGen, inst: Air.Inst.Index, index: u32) Inne
3913 const struct_ty = struct_ptr_ty.childType(mod);3891 const struct_ty = struct_ptr_ty.childType(mod);
39143892
3915 const result = try func.structFieldPtr(inst, ty_op.operand, struct_ptr, struct_ptr_ty, struct_ty, index);3893 const result = try func.structFieldPtr(inst, ty_op.operand, struct_ptr, struct_ptr_ty, struct_ty, index);
3916 func.finishAir(inst, result, &.{ty_op.operand});3894 return func.finishAir(inst, result, &.{ty_op.operand});
3917}3895}
39183896
3919fn structFieldPtr(3897fn structFieldPtr(
...@@ -3950,7 +3928,7 @@ fn structFieldPtr(...@@ -3950,7 +3928,7 @@ fn structFieldPtr(
3950 }3928 }
3951 switch (struct_ptr) {3929 switch (struct_ptr) {
3952 .stack_offset => |stack_offset| {3930 .stack_offset => |stack_offset| {
3953 return WValue{ .stack_offset = .{ .value = stack_offset.value + @as(u32, @intCast(offset)), .references = 1 } };3931 return .{ .stack_offset = .{ .value = stack_offset.value + @as(u32, @intCast(offset)), .references = 1 } };
3954 },3932 },
3955 else => return func.buildPointerOffset(struct_ptr, offset, .new),3933 else => return func.buildPointerOffset(struct_ptr, offset, .new),
3956 }3934 }
...@@ -3969,7 +3947,7 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -3969,7 +3947,7 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3969 const field_ty = struct_ty.structFieldType(field_index, mod);3947 const field_ty = struct_ty.structFieldType(field_index, mod);
3970 if (!field_ty.hasRuntimeBitsIgnoreComptime(pt)) return func.finishAir(inst, .none, &.{struct_field.struct_operand});3948 if (!field_ty.hasRuntimeBitsIgnoreComptime(pt)) return func.finishAir(inst, .none, &.{struct_field.struct_operand});
39713949
3972 const result = switch (struct_ty.containerLayout(mod)) {3950 const result: WValue = switch (struct_ty.containerLayout(mod)) {
3973 .@"packed" => switch (struct_ty.zigTypeTag(mod)) {3951 .@"packed" => switch (struct_ty.zigTypeTag(mod)) {
3974 .Struct => result: {3952 .Struct => result: {
3975 const packed_struct = mod.typeToPackedStruct(struct_ty).?;3953 const packed_struct = mod.typeToPackedStruct(struct_ty).?;
...@@ -3978,10 +3956,10 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -3978,10 +3956,10 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3978 const wasm_bits = toWasmBits(backing_ty.intInfo(mod).bits) orelse {3956 const wasm_bits = toWasmBits(backing_ty.intInfo(mod).bits) orelse {
3979 return func.fail("TODO: airStructFieldVal for packed structs larger than 128 bits", .{});3957 return func.fail("TODO: airStructFieldVal for packed structs larger than 128 bits", .{});
3980 };3958 };
3981 const const_wvalue = if (wasm_bits == 32)3959 const const_wvalue: WValue = if (wasm_bits == 32)
3982 WValue{ .imm32 = offset }3960 .{ .imm32 = offset }
3983 else if (wasm_bits == 64)3961 else if (wasm_bits == 64)
3984 WValue{ .imm64 = offset }3962 .{ .imm64 = offset }
3985 else3963 else
3986 return func.fail("TODO: airStructFieldVal for packed structs larger than 64 bits", .{});3964 return func.fail("TODO: airStructFieldVal for packed structs larger than 64 bits", .{});
39873965
...@@ -3994,25 +3972,21 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -3994,25 +3972,21 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3994 if (field_ty.zigTypeTag(mod) == .Float) {3972 if (field_ty.zigTypeTag(mod) == .Float) {
3995 const int_type = try pt.intType(.unsigned, @as(u16, @intCast(field_ty.bitSize(pt))));3973 const int_type = try pt.intType(.unsigned, @as(u16, @intCast(field_ty.bitSize(pt))));
3996 const truncated = try func.trunc(shifted_value, int_type, backing_ty);3974 const truncated = try func.trunc(shifted_value, int_type, backing_ty);
3997 const bitcasted = try func.bitcast(field_ty, int_type, truncated);3975 break :result try func.bitcast(field_ty, int_type, truncated);
3998 break :result try bitcasted.toLocal(func, field_ty);
3999 } else if (field_ty.isPtrAtRuntime(mod) and packed_struct.field_types.len == 1) {3976 } else if (field_ty.isPtrAtRuntime(mod) and packed_struct.field_types.len == 1) {
4000 // In this case we do not have to perform any transformations,3977 // In this case we do not have to perform any transformations,
4001 // we can simply reuse the operand.3978 // we can simply reuse the operand.
4002 break :result func.reuseOperand(struct_field.struct_operand, operand);3979 break :result func.reuseOperand(struct_field.struct_operand, operand);
4003 } else if (field_ty.isPtrAtRuntime(mod)) {3980 } else if (field_ty.isPtrAtRuntime(mod)) {
4004 const int_type = try pt.intType(.unsigned, @as(u16, @intCast(field_ty.bitSize(pt))));3981 const int_type = try pt.intType(.unsigned, @as(u16, @intCast(field_ty.bitSize(pt))));
4005 const truncated = try func.trunc(shifted_value, int_type, backing_ty);3982 break :result try func.trunc(shifted_value, int_type, backing_ty);
4006 break :result try truncated.toLocal(func, field_ty);
4007 }3983 }
4008 const truncated = try func.trunc(shifted_value, field_ty, backing_ty);3984 break :result try func.trunc(shifted_value, field_ty, backing_ty);
4009 break :result try truncated.toLocal(func, field_ty);
4010 },3985 },
4011 .Union => result: {3986 .Union => result: {
4012 if (isByRef(struct_ty, pt)) {3987 if (isByRef(struct_ty, pt)) {
4013 if (!isByRef(field_ty, pt)) {3988 if (!isByRef(field_ty, pt)) {
4014 const val = try func.load(operand, field_ty, 0);3989 break :result try func.load(operand, field_ty, 0);
4015 break :result try val.toLocal(func, field_ty);
4016 } else {3990 } else {
4017 const new_stack_val = try func.allocStack(field_ty);3991 const new_stack_val = try func.allocStack(field_ty);
4018 try func.store(new_stack_val, operand, field_ty, 0);3992 try func.store(new_stack_val, operand, field_ty, 0);
...@@ -4024,15 +3998,12 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4024,15 +3998,12 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4024 if (field_ty.zigTypeTag(mod) == .Float) {3998 if (field_ty.zigTypeTag(mod) == .Float) {
4025 const int_type = try pt.intType(.unsigned, @as(u16, @intCast(field_ty.bitSize(pt))));3999 const int_type = try pt.intType(.unsigned, @as(u16, @intCast(field_ty.bitSize(pt))));
4026 const truncated = try func.trunc(operand, int_type, union_int_type);4000 const truncated = try func.trunc(operand, int_type, union_int_type);
4027 const bitcasted = try func.bitcast(field_ty, int_type, truncated);4001 break :result try func.bitcast(field_ty, int_type, truncated);
4028 break :result try bitcasted.toLocal(func, field_ty);
4029 } else if (field_ty.isPtrAtRuntime(mod)) {4002 } else if (field_ty.isPtrAtRuntime(mod)) {
4030 const int_type = try pt.intType(.unsigned, @as(u16, @intCast(field_ty.bitSize(pt))));4003 const int_type = try pt.intType(.unsigned, @as(u16, @intCast(field_ty.bitSize(pt))));
4031 const truncated = try func.trunc(operand, int_type, union_int_type);4004 break :result try func.trunc(operand, int_type, union_int_type);
4032 break :result try truncated.toLocal(func, field_ty);
4033 }4005 }
4034 const truncated = try func.trunc(operand, field_ty, union_int_type);4006 break :result try func.trunc(operand, field_ty, union_int_type);
4035 break :result try truncated.toLocal(func, field_ty);
4036 },4007 },
4037 else => unreachable,4008 else => unreachable,
4038 },4009 },
...@@ -4043,17 +4014,16 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4043,17 +4014,16 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4043 if (isByRef(field_ty, pt)) {4014 if (isByRef(field_ty, pt)) {
4044 switch (operand) {4015 switch (operand) {
4045 .stack_offset => |stack_offset| {4016 .stack_offset => |stack_offset| {
4046 break :result WValue{ .stack_offset = .{ .value = stack_offset.value + offset, .references = 1 } };4017 break :result .{ .stack_offset = .{ .value = stack_offset.value + offset, .references = 1 } };
4047 },4018 },
4048 else => break :result try func.buildPointerOffset(operand, offset, .new),4019 else => break :result try func.buildPointerOffset(operand, offset, .new),
4049 }4020 }
4050 }4021 }
4051 const field = try func.load(operand, field_ty, offset);4022 break :result try func.load(operand, field_ty, offset);
4052 break :result try field.toLocal(func, field_ty);
4053 },4023 },
4054 };4024 };
40554025
4056 func.finishAir(inst, result, &.{struct_field.struct_operand});4026 return func.finishAir(inst, result, &.{struct_field.struct_operand});
4057}4027}
40584028
4059fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {4029fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -4234,7 +4204,7 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4234,7 +4204,7 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4234 try func.genBody(else_body);4204 try func.genBody(else_body);
4235 try func.endBlock();4205 try func.endBlock();
4236 }4206 }
4237 func.finishAir(inst, .none, &.{});4207 return func.finishAir(inst, .none, &.{});
4238}4208}
42394209
4240fn airIsErr(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerError!void {4210fn airIsErr(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerError!void {
...@@ -4245,11 +4215,11 @@ fn airIsErr(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerErro...@@ -4245,11 +4215,11 @@ fn airIsErr(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerErro
4245 const err_union_ty = func.typeOf(un_op);4215 const err_union_ty = func.typeOf(un_op);
4246 const pl_ty = err_union_ty.errorUnionPayload(mod);4216 const pl_ty = err_union_ty.errorUnionPayload(mod);
42474217
4248 const result = result: {4218 const result: WValue = result: {
4249 if (err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {4219 if (err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {
4250 switch (opcode) {4220 switch (opcode) {
4251 .i32_ne => break :result WValue{ .imm32 = 0 },4221 .i32_ne => break :result .{ .imm32 = 0 },
4252 .i32_eq => break :result WValue{ .imm32 = 1 },4222 .i32_eq => break :result .{ .imm32 = 1 },
4253 else => unreachable,4223 else => unreachable,
4254 }4224 }
4255 }4225 }
...@@ -4265,12 +4235,9 @@ fn airIsErr(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerErro...@@ -4265,12 +4235,9 @@ fn airIsErr(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerErro
4265 // Compare the error value with '0'4235 // Compare the error value with '0'
4266 try func.addImm32(0);4236 try func.addImm32(0);
4267 try func.addTag(Mir.Inst.Tag.fromOpcode(opcode));4237 try func.addTag(Mir.Inst.Tag.fromOpcode(opcode));
42684238 break :result .stack;
4269 const is_err_tmp = try func.allocLocal(Type.i32);
4270 try func.addLabel(.local_set, is_err_tmp.local.value);
4271 break :result is_err_tmp;
4272 };4239 };
4273 func.finishAir(inst, result, &.{un_op});4240 return func.finishAir(inst, result, &.{un_op});
4274}4241}
42754242
4276fn airUnwrapErrUnionPayload(func: *CodeGen, inst: Air.Inst.Index, op_is_ptr: bool) InnerError!void {4243fn airUnwrapErrUnionPayload(func: *CodeGen, inst: Air.Inst.Index, op_is_ptr: bool) InnerError!void {
...@@ -4283,12 +4250,12 @@ fn airUnwrapErrUnionPayload(func: *CodeGen, inst: Air.Inst.Index, op_is_ptr: boo...@@ -4283,12 +4250,12 @@ fn airUnwrapErrUnionPayload(func: *CodeGen, inst: Air.Inst.Index, op_is_ptr: boo
4283 const err_ty = if (op_is_ptr) op_ty.childType(mod) else op_ty;4250 const err_ty = if (op_is_ptr) op_ty.childType(mod) else op_ty;
4284 const payload_ty = err_ty.errorUnionPayload(mod);4251 const payload_ty = err_ty.errorUnionPayload(mod);
42854252
4286 const result = result: {4253 const result: WValue = result: {
4287 if (!payload_ty.hasRuntimeBitsIgnoreComptime(pt)) {4254 if (!payload_ty.hasRuntimeBitsIgnoreComptime(pt)) {
4288 if (op_is_ptr) {4255 if (op_is_ptr) {
4289 break :result func.reuseOperand(ty_op.operand, operand);4256 break :result func.reuseOperand(ty_op.operand, operand);
4290 }4257 }
4291 break :result WValue{ .none = {} };4258 break :result .none;
4292 }4259 }
42934260
4294 const pl_offset = @as(u32, @intCast(errUnionPayloadOffset(payload_ty, pt)));4261 const pl_offset = @as(u32, @intCast(errUnionPayloadOffset(payload_ty, pt)));
...@@ -4296,10 +4263,9 @@ fn airUnwrapErrUnionPayload(func: *CodeGen, inst: Air.Inst.Index, op_is_ptr: boo...@@ -4296,10 +4263,9 @@ fn airUnwrapErrUnionPayload(func: *CodeGen, inst: Air.Inst.Index, op_is_ptr: boo
4296 break :result try func.buildPointerOffset(operand, pl_offset, .new);4263 break :result try func.buildPointerOffset(operand, pl_offset, .new);
4297 }4264 }
42984265
4299 const payload = try func.load(operand, payload_ty, pl_offset);4266 break :result try func.load(operand, payload_ty, pl_offset);
4300 break :result try payload.toLocal(func, payload_ty);
4301 };4267 };
4302 func.finishAir(inst, result, &.{ty_op.operand});4268 return func.finishAir(inst, result, &.{ty_op.operand});
4303}4269}
43044270
4305fn airUnwrapErrUnionError(func: *CodeGen, inst: Air.Inst.Index, op_is_ptr: bool) InnerError!void {4271fn airUnwrapErrUnionError(func: *CodeGen, inst: Air.Inst.Index, op_is_ptr: bool) InnerError!void {
...@@ -4312,19 +4278,18 @@ fn airUnwrapErrUnionError(func: *CodeGen, inst: Air.Inst.Index, op_is_ptr: bool)...@@ -4312,19 +4278,18 @@ fn airUnwrapErrUnionError(func: *CodeGen, inst: Air.Inst.Index, op_is_ptr: bool)
4312 const err_ty = if (op_is_ptr) op_ty.childType(mod) else op_ty;4278 const err_ty = if (op_is_ptr) op_ty.childType(mod) else op_ty;
4313 const payload_ty = err_ty.errorUnionPayload(mod);4279 const payload_ty = err_ty.errorUnionPayload(mod);
43144280
4315 const result = result: {4281 const result: WValue = result: {
4316 if (err_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {4282 if (err_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {
4317 break :result WValue{ .imm32 = 0 };4283 break :result .{ .imm32 = 0 };
4318 }4284 }
43194285
4320 if (op_is_ptr or !payload_ty.hasRuntimeBitsIgnoreComptime(pt)) {4286 if (op_is_ptr or !payload_ty.hasRuntimeBitsIgnoreComptime(pt)) {
4321 break :result func.reuseOperand(ty_op.operand, operand);4287 break :result func.reuseOperand(ty_op.operand, operand);
4322 }4288 }
43234289
4324 const error_val = try func.load(operand, Type.anyerror, @intCast(errUnionErrorOffset(payload_ty, pt)));4290 break :result try func.load(operand, Type.anyerror, @intCast(errUnionErrorOffset(payload_ty, pt)));
4325 break :result try error_val.toLocal(func, Type.anyerror);
4326 };4291 };
4327 func.finishAir(inst, result, &.{ty_op.operand});4292 return func.finishAir(inst, result, &.{ty_op.operand});
4328}4293}
43294294
4330fn airWrapErrUnionPayload(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {4295fn airWrapErrUnionPayload(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -4354,7 +4319,7 @@ fn airWrapErrUnionPayload(func: *CodeGen, inst: Air.Inst.Index) InnerError!void...@@ -4354,7 +4319,7 @@ fn airWrapErrUnionPayload(func: *CodeGen, inst: Air.Inst.Index) InnerError!void
4354 });4319 });
4355 break :result err_union;4320 break :result err_union;
4356 };4321 };
4357 func.finishAir(inst, result, &.{ty_op.operand});4322 return func.finishAir(inst, result, &.{ty_op.operand});
4358}4323}
43594324
4360fn airWrapErrUnionErr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {4325fn airWrapErrUnionErr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -4382,7 +4347,7 @@ fn airWrapErrUnionErr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4382,7 +4347,7 @@ fn airWrapErrUnionErr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
43824347
4383 break :result err_union;4348 break :result err_union;
4384 };4349 };
4385 func.finishAir(inst, result, &.{ty_op.operand});4350 return func.finishAir(inst, result, &.{ty_op.operand});
4386}4351}
43874352
4388fn airIntcast(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {4353fn airIntcast(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -4405,9 +4370,9 @@ fn airIntcast(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4405,9 +4370,9 @@ fn airIntcast(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4405 const result = if (op_bits == wanted_bits)4370 const result = if (op_bits == wanted_bits)
4406 func.reuseOperand(ty_op.operand, operand)4371 func.reuseOperand(ty_op.operand, operand)
4407 else4372 else
4408 try (try func.intcast(operand, operand_ty, ty)).toLocal(func, ty);4373 try func.intcast(operand, operand_ty, ty);
44094374
4410 func.finishAir(inst, result, &.{});4375 return func.finishAir(inst, result, &.{});
4411}4376}
44124377
4413/// Upcasts or downcasts an integer based on the given and wanted types,4378/// Upcasts or downcasts an integer based on the given and wanted types,
...@@ -4472,9 +4437,8 @@ fn airIsNull(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode, op_kind:...@@ -4472,9 +4437,8 @@ fn airIsNull(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode, op_kind:
44724437
4473 const op_ty = func.typeOf(un_op);4438 const op_ty = func.typeOf(un_op);
4474 const optional_ty = if (op_kind == .ptr) op_ty.childType(mod) else op_ty;4439 const optional_ty = if (op_kind == .ptr) op_ty.childType(mod) else op_ty;
4475 const is_null = try func.isNull(operand, optional_ty, opcode);4440 const result = try func.isNull(operand, optional_ty, opcode);
4476 const result = try is_null.toLocal(func, optional_ty);4441 return func.finishAir(inst, result, &.{un_op});
4477 func.finishAir(inst, result, &.{un_op});
4478}4442}
44794443
4480/// For a given type and operand, checks if it's considered `null`.4444/// For a given type and operand, checks if it's considered `null`.
...@@ -4505,7 +4469,7 @@ fn isNull(func: *CodeGen, operand: WValue, optional_ty: Type, opcode: wasm.Opcod...@@ -4505,7 +4469,7 @@ fn isNull(func: *CodeGen, operand: WValue, optional_ty: Type, opcode: wasm.Opcod
4505 try func.addImm32(0);4469 try func.addImm32(0);
4506 try func.addTag(Mir.Inst.Tag.fromOpcode(opcode));4470 try func.addTag(Mir.Inst.Tag.fromOpcode(opcode));
45074471
4508 return WValue{ .stack = {} };4472 return .stack;
4509}4473}
45104474
4511fn airOptionalPayload(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {4475fn airOptionalPayload(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -4526,10 +4490,9 @@ fn airOptionalPayload(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4526,10 +4490,9 @@ fn airOptionalPayload(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4526 break :result try func.buildPointerOffset(operand, 0, .new);4490 break :result try func.buildPointerOffset(operand, 0, .new);
4527 }4491 }
45284492
4529 const payload = try func.load(operand, payload_ty, 0);4493 break :result try func.load(operand, payload_ty, 0);
4530 break :result try payload.toLocal(func, payload_ty);
4531 };4494 };
4532 func.finishAir(inst, result, &.{ty_op.operand});4495 return func.finishAir(inst, result, &.{ty_op.operand});
4533}4496}
45344497
4535fn airOptionalPayloadPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {4498fn airOptionalPayloadPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -4547,7 +4510,7 @@ fn airOptionalPayloadPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4547,7 +4510,7 @@ fn airOptionalPayloadPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
45474510
4548 break :result try func.buildPointerOffset(operand, 0, .new);4511 break :result try func.buildPointerOffset(operand, 0, .new);
4549 };4512 };
4550 func.finishAir(inst, result, &.{ty_op.operand});4513 return func.finishAir(inst, result, &.{ty_op.operand});
4551}4514}
45524515
4553fn airOptionalPayloadPtrSet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {4516fn airOptionalPayloadPtrSet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -4612,7 +4575,7 @@ fn airWrapOptional(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4612,7 +4575,7 @@ fn airWrapOptional(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4612 break :result result_ptr;4575 break :result result_ptr;
4613 };4576 };
46144577
4615 func.finishAir(inst, result, &.{ty_op.operand});4578 return func.finishAir(inst, result, &.{ty_op.operand});
4616}4579}
46174580
4618fn airSlice(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {4581fn airSlice(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -4627,14 +4590,14 @@ fn airSlice(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4627,14 +4590,14 @@ fn airSlice(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4627 try func.store(slice, lhs, Type.usize, 0);4590 try func.store(slice, lhs, Type.usize, 0);
4628 try func.store(slice, rhs, Type.usize, func.ptrSize());4591 try func.store(slice, rhs, Type.usize, func.ptrSize());
46294592
4630 func.finishAir(inst, slice, &.{ bin_op.lhs, bin_op.rhs });4593 return func.finishAir(inst, slice, &.{ bin_op.lhs, bin_op.rhs });
4631}4594}
46324595
4633fn airSliceLen(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {4596fn airSliceLen(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4634 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;4597 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
46354598
4636 const operand = try func.resolveInst(ty_op.operand);4599 const operand = try func.resolveInst(ty_op.operand);
4637 func.finishAir(inst, try func.sliceLen(operand), &.{ty_op.operand});4600 return func.finishAir(inst, try func.sliceLen(operand), &.{ty_op.operand});
4638}4601}
46394602
4640fn airSliceElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {4603fn airSliceElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -4657,15 +4620,12 @@ fn airSliceElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4657,15 +4620,12 @@ fn airSliceElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4657 try func.addTag(.i32_mul);4620 try func.addTag(.i32_mul);
4658 try func.addTag(.i32_add);4621 try func.addTag(.i32_add);
46594622
4660 const result_ptr = try func.allocLocal(Type.usize);4623 const elem_result = if (isByRef(elem_ty, pt))
4661 try func.addLabel(.local_set, result_ptr.local.value);4624 .stack
46624625 else
4663 const result = if (!isByRef(elem_ty, pt)) result: {4626 try func.load(.stack, elem_ty, 0);
4664 const elem_val = try func.load(result_ptr, elem_ty, 0);
4665 break :result try elem_val.toLocal(func, elem_ty);
4666 } else result_ptr;
46674627
4668 func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });4628 return func.finishAir(inst, elem_result, &.{ bin_op.lhs, bin_op.rhs });
4669}4629}
46704630
4671fn airSliceElemPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {4631fn airSliceElemPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -4688,15 +4648,13 @@ fn airSliceElemPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4688,15 +4648,13 @@ fn airSliceElemPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4688 try func.addTag(.i32_mul);4648 try func.addTag(.i32_mul);
4689 try func.addTag(.i32_add);4649 try func.addTag(.i32_add);
46904650
4691 const result = try func.allocLocal(Type.i32);4651 return func.finishAir(inst, .stack, &.{ bin_op.lhs, bin_op.rhs });
4692 try func.addLabel(.local_set, result.local.value);
4693 func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });
4694}4652}
46954653
4696fn airSlicePtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {4654fn airSlicePtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4697 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;4655 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
4698 const operand = try func.resolveInst(ty_op.operand);4656 const operand = try func.resolveInst(ty_op.operand);
4699 func.finishAir(inst, try func.slicePtr(operand), &.{ty_op.operand});4657 return func.finishAir(inst, try func.slicePtr(operand), &.{ty_op.operand});
4700}4658}
47014659
4702fn slicePtr(func: *CodeGen, operand: WValue) InnerError!WValue {4660fn slicePtr(func: *CodeGen, operand: WValue) InnerError!WValue {
...@@ -4717,7 +4675,7 @@ fn airTrunc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4717,7 +4675,7 @@ fn airTrunc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4717 const op_ty = func.typeOf(ty_op.operand);4675 const op_ty = func.typeOf(ty_op.operand);
47184676
4719 const result = try func.trunc(operand, wanted_ty, op_ty);4677 const result = try func.trunc(operand, wanted_ty, op_ty);
4720 func.finishAir(inst, try result.toLocal(func, wanted_ty), &.{ty_op.operand});4678 return func.finishAir(inst, result, &.{ty_op.operand});
4721}4679}
47224680
4723/// Truncates a given operand to a given type, discarding any overflown bits.4681/// Truncates a given operand to a given type, discarding any overflown bits.
...@@ -4743,7 +4701,7 @@ fn airIntFromBool(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4743,7 +4701,7 @@ fn airIntFromBool(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4743 const operand = try func.resolveInst(un_op);4701 const operand = try func.resolveInst(un_op);
4744 const result = func.reuseOperand(un_op, operand);4702 const result = func.reuseOperand(un_op, operand);
47454703
4746 func.finishAir(inst, result, &.{un_op});4704 return func.finishAir(inst, result, &.{un_op});
4747}4705}
47484706
4749fn airArrayToSlice(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {4707fn airArrayToSlice(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -4764,10 +4722,10 @@ fn airArrayToSlice(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4764,10 +4722,10 @@ fn airArrayToSlice(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4764 }4722 }
47654723
4766 // store the length of the array in the slice4724 // store the length of the array in the slice
4767 const len = WValue{ .imm32 = @as(u32, @intCast(array_ty.arrayLen(mod))) };4725 const array_len: u32 = @intCast(array_ty.arrayLen(mod));
4768 try func.store(slice_local, len, Type.usize, func.ptrSize());4726 try func.store(slice_local, .{ .imm32 = array_len }, Type.usize, func.ptrSize());
47694727
4770 func.finishAir(inst, slice_local, &.{ty_op.operand});4728 return func.finishAir(inst, slice_local, &.{ty_op.operand});
4771}4729}
47724730
4773fn airIntFromPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {4731fn airIntFromPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -4783,7 +4741,7 @@ fn airIntFromPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4783,7 +4741,7 @@ fn airIntFromPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4783 .stack_offset => try func.buildPointerOffset(operand, 0, .new),4741 .stack_offset => try func.buildPointerOffset(operand, 0, .new),
4784 else => func.reuseOperand(un_op, operand),4742 else => func.reuseOperand(un_op, operand),
4785 };4743 };
4786 func.finishAir(inst, result, &.{un_op});4744 return func.finishAir(inst, result, &.{un_op});
4787}4745}
47884746
4789fn airPtrElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {4747fn airPtrElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -4810,18 +4768,12 @@ fn airPtrElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4810,18 +4768,12 @@ fn airPtrElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4810 try func.addTag(.i32_mul);4768 try func.addTag(.i32_mul);
4811 try func.addTag(.i32_add);4769 try func.addTag(.i32_add);
48124770
4813 const elem_result = val: {4771 const elem_result = if (isByRef(elem_ty, pt))
4814 var result = try func.allocLocal(Type.usize);4772 .stack
4815 try func.addLabel(.local_set, result.local.value);4773 else
4816 if (isByRef(elem_ty, pt)) {4774 try func.load(.stack, elem_ty, 0);
4817 break :val result;
4818 }
4819 defer result.free(func); // only free if it's not returned like above
48204775
4821 const elem_val = try func.load(result, elem_ty, 0);4776 return func.finishAir(inst, elem_result, &.{ bin_op.lhs, bin_op.rhs });
4822 break :val try elem_val.toLocal(func, elem_ty);
4823 };
4824 func.finishAir(inst, elem_result, &.{ bin_op.lhs, bin_op.rhs });
4825}4777}
48264778
4827fn airPtrElemPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {4779fn airPtrElemPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -4850,9 +4802,7 @@ fn airPtrElemPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4850,9 +4802,7 @@ fn airPtrElemPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4850 try func.addTag(.i32_mul);4802 try func.addTag(.i32_mul);
4851 try func.addTag(.i32_add);4803 try func.addTag(.i32_add);
48524804
4853 const result = try func.allocLocal(Type.i32);4805 return func.finishAir(inst, .stack, &.{ bin_op.lhs, bin_op.rhs });
4854 try func.addLabel(.local_set, result.local.value);
4855 func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });
4856}4806}
48574807
4858fn airPtrBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {4808fn airPtrBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {
...@@ -4879,9 +4829,7 @@ fn airPtrBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {...@@ -4879,9 +4829,7 @@ fn airPtrBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {
4879 try func.addTag(Mir.Inst.Tag.fromOpcode(mul_opcode));4829 try func.addTag(Mir.Inst.Tag.fromOpcode(mul_opcode));
4880 try func.addTag(Mir.Inst.Tag.fromOpcode(bin_opcode));4830 try func.addTag(Mir.Inst.Tag.fromOpcode(bin_opcode));
48814831
4882 const result = try func.allocLocal(Type.usize);4832 return func.finishAir(inst, .stack, &.{ bin_op.lhs, bin_op.rhs });
4883 try func.addLabel(.local_set, result.local.value);
4884 func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });
4885}4833}
48864834
4887fn airMemset(func: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void {4835fn airMemset(func: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void {
...@@ -4911,7 +4859,7 @@ fn airMemset(func: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void...@@ -4911,7 +4859,7 @@ fn airMemset(func: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void
4911 const dst_ptr = try func.sliceOrArrayPtr(ptr, ptr_ty);4859 const dst_ptr = try func.sliceOrArrayPtr(ptr, ptr_ty);
4912 try func.memset(elem_ty, dst_ptr, len, value);4860 try func.memset(elem_ty, dst_ptr, len, value);
49134861
4914 func.finishAir(inst, .none, &.{ bin_op.lhs, bin_op.rhs });4862 return func.finishAir(inst, .none, &.{ bin_op.lhs, bin_op.rhs });
4915}4863}
49164864
4917/// Sets a region of memory at `ptr` to the value of `value`4865/// Sets a region of memory at `ptr` to the value of `value`
...@@ -4932,9 +4880,9 @@ fn memset(func: *CodeGen, elem_ty: Type, ptr: WValue, len: WValue, value: WValue...@@ -4932,9 +4880,9 @@ fn memset(func: *CodeGen, elem_ty: Type, ptr: WValue, len: WValue, value: WValue
4932 return;4880 return;
4933 }4881 }
49344882
4935 const final_len = switch (len) {4883 const final_len: WValue = switch (len) {
4936 .imm32 => |val| WValue{ .imm32 = val * abi_size },4884 .imm32 => |val| .{ .imm32 = val * abi_size },
4937 .imm64 => |val| WValue{ .imm64 = val * abi_size },4885 .imm64 => |val| .{ .imm64 = val * abi_size },
4938 else => if (abi_size != 1) blk: {4886 else => if (abi_size != 1) blk: {
4939 const new_len = try func.ensureAllocLocal(Type.usize);4887 const new_len = try func.ensureAllocLocal(Type.usize);
4940 try func.emitWValue(len);4888 try func.emitWValue(len);
...@@ -5045,7 +4993,7 @@ fn airArrayElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5045,7 +4993,7 @@ fn airArrayElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5045 try func.mir_extra.appendSlice(func.gpa, &operands);4993 try func.mir_extra.appendSlice(func.gpa, &operands);
5046 try func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } });4994 try func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } });
50474995
5048 return func.finishAir(inst, try WValue.toLocal(.stack, func, elem_ty), &.{ bin_op.lhs, bin_op.rhs });4996 return func.finishAir(inst, .stack, &.{ bin_op.lhs, bin_op.rhs });
5049 },4997 },
5050 else => {4998 else => {
5051 const stack_vec = try func.allocStack(array_ty);4999 const stack_vec = try func.allocStack(array_ty);
...@@ -5061,20 +5009,12 @@ fn airArrayElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5061,20 +5009,12 @@ fn airArrayElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5061 }5009 }
5062 }5010 }
50635011
5064 const elem_result = val: {5012 const elem_result = if (isByRef(elem_ty, pt))
5065 var result = try func.allocLocal(Type.usize);5013 .stack
5066 try func.addLabel(.local_set, result.local.value);5014 else
50675015 try func.load(.stack, elem_ty, 0);
5068 if (isByRef(elem_ty, pt)) {
5069 break :val result;
5070 }
5071 defer result.free(func); // only free if no longer needed and not returned like above
5072
5073 const elem_val = try func.load(result, elem_ty, 0);
5074 break :val try elem_val.toLocal(func, elem_ty);
5075 };
50765016
5077 func.finishAir(inst, elem_result, &.{ bin_op.lhs, bin_op.rhs });5017 return func.finishAir(inst, elem_result, &.{ bin_op.lhs, bin_op.rhs });
5078}5018}
50795019
5080fn airIntFromFloat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {5020fn airIntFromFloat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -5106,7 +5046,7 @@ fn airIntFromFloat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5106,7 +5046,7 @@ fn airIntFromFloat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5106 target_util.compilerRtIntAbbrev(dest_bitsize),5046 target_util.compilerRtIntAbbrev(dest_bitsize),
5107 }) catch unreachable;5047 }) catch unreachable;
51085048
5109 const result = try (try func.callIntrinsic(fn_name, &.{op_ty.ip_index}, dest_ty, &.{operand})).toLocal(func, dest_ty);5049 const result = try func.callIntrinsic(fn_name, &.{op_ty.ip_index}, dest_ty, &.{operand});
5110 return func.finishAir(inst, result, &.{ty_op.operand});5050 return func.finishAir(inst, result, &.{ty_op.operand});
5111 }5051 }
51125052
...@@ -5118,9 +5058,8 @@ fn airIntFromFloat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5118,9 +5058,8 @@ fn airIntFromFloat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5118 .signedness = dest_info.signedness,5058 .signedness = dest_info.signedness,
5119 });5059 });
5120 try func.addTag(Mir.Inst.Tag.fromOpcode(op));5060 try func.addTag(Mir.Inst.Tag.fromOpcode(op));
5121 const wrapped = try func.wrapOperand(.{ .stack = {} }, dest_ty);5061 const result = try func.wrapOperand(.stack, dest_ty);
5122 const result = try wrapped.toLocal(func, dest_ty);5062 return func.finishAir(inst, result, &.{ty_op.operand});
5123 func.finishAir(inst, result, &.{ty_op.operand});
5124}5063}
51255064
5126fn airFloatFromInt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {5065fn airFloatFromInt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -5152,7 +5091,7 @@ fn airFloatFromInt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5152,7 +5091,7 @@ fn airFloatFromInt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5152 target_util.compilerRtFloatAbbrev(dest_bits),5091 target_util.compilerRtFloatAbbrev(dest_bits),
5153 }) catch unreachable;5092 }) catch unreachable;
51545093
5155 const result = try (try func.callIntrinsic(fn_name, &.{op_ty.ip_index}, dest_ty, &.{operand})).toLocal(func, dest_ty);5094 const result = try func.callIntrinsic(fn_name, &.{op_ty.ip_index}, dest_ty, &.{operand});
5156 return func.finishAir(inst, result, &.{ty_op.operand});5095 return func.finishAir(inst, result, &.{ty_op.operand});
5157 }5096 }
51585097
...@@ -5165,9 +5104,7 @@ fn airFloatFromInt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5165,9 +5104,7 @@ fn airFloatFromInt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5165 });5104 });
5166 try func.addTag(Mir.Inst.Tag.fromOpcode(op));5105 try func.addTag(Mir.Inst.Tag.fromOpcode(op));
51675106
5168 const result = try func.allocLocal(dest_ty);5107 return func.finishAir(inst, .stack, &.{ty_op.operand});
5169 try func.addLabel(.local_set, result.local.value);
5170 func.finishAir(inst, result, &.{ty_op.operand});
5171}5108}
51725109
5173fn airSplat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {5110fn airSplat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -5191,7 +5128,6 @@ fn airSplat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5191,7 +5128,6 @@ fn airSplat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5191 64 => std.wasm.simdOpcode(.v128_load64_splat),5128 64 => std.wasm.simdOpcode(.v128_load64_splat),
5192 else => break :blk, // Cannot make use of simd-instructions5129 else => break :blk, // Cannot make use of simd-instructions
5193 };5130 };
5194 const result = try func.allocLocal(ty);
5195 try func.emitWValue(operand);5131 try func.emitWValue(operand);
5196 // TODO: Add helper functions for simd opcodes5132 // TODO: Add helper functions for simd opcodes
5197 const extra_index = @as(u32, @intCast(func.mir_extra.items.len));5133 const extra_index = @as(u32, @intCast(func.mir_extra.items.len));
...@@ -5202,8 +5138,7 @@ fn airSplat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5202,8 +5138,7 @@ fn airSplat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5202 @intCast(elem_ty.abiAlignment(pt).toByteUnits().?),5138 @intCast(elem_ty.abiAlignment(pt).toByteUnits().?),
5203 });5139 });
5204 try func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } });5140 try func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } });
5205 try func.addLabel(.local_set, result.local.value);5141 return func.finishAir(inst, .stack, &.{ty_op.operand});
5206 return func.finishAir(inst, result, &.{ty_op.operand});
5207 },5142 },
5208 .local => {5143 .local => {
5209 const opcode = switch (elem_ty.bitSize(pt)) {5144 const opcode = switch (elem_ty.bitSize(pt)) {
...@@ -5213,13 +5148,11 @@ fn airSplat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5213,13 +5148,11 @@ fn airSplat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5213 64 => if (elem_ty.isInt(mod)) std.wasm.simdOpcode(.i64x2_splat) else std.wasm.simdOpcode(.f64x2_splat),5148 64 => if (elem_ty.isInt(mod)) std.wasm.simdOpcode(.i64x2_splat) else std.wasm.simdOpcode(.f64x2_splat),
5214 else => break :blk, // Cannot make use of simd-instructions5149 else => break :blk, // Cannot make use of simd-instructions
5215 };5150 };
5216 const result = try func.allocLocal(ty);
5217 try func.emitWValue(operand);5151 try func.emitWValue(operand);
5218 const extra_index = @as(u32, @intCast(func.mir_extra.items.len));5152 const extra_index = @as(u32, @intCast(func.mir_extra.items.len));
5219 try func.mir_extra.append(func.gpa, opcode);5153 try func.mir_extra.append(func.gpa, opcode);
5220 try func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } });5154 try func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } });
5221 try func.addLabel(.local_set, result.local.value);5155 return func.finishAir(inst, .stack, &.{ty_op.operand});
5222 return func.finishAir(inst, result, &.{ty_op.operand});
5223 },5156 },
5224 else => unreachable,5157 else => unreachable,
5225 }5158 }
...@@ -5308,7 +5241,7 @@ fn airShuffle(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5308,7 +5241,7 @@ fn airShuffle(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5308 try func.mir_extra.appendSlice(func.gpa, &operands);5241 try func.mir_extra.appendSlice(func.gpa, &operands);
5309 try func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } });5242 try func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } });
53105243
5311 return func.finishAir(inst, try WValue.toLocal(.stack, func, inst_ty), &.{ extra.a, extra.b });5244 return func.finishAir(inst, .stack, &.{ extra.a, extra.b });
5312 }5245 }
5313}5246}
53145247
...@@ -5392,10 +5325,10 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5392,10 +5325,10 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5392 const field_ty = Type.fromInterned(field_types.get(ip)[elem_index]);5325 const field_ty = Type.fromInterned(field_types.get(ip)[elem_index]);
5393 if (!field_ty.hasRuntimeBitsIgnoreComptime(pt)) continue;5326 if (!field_ty.hasRuntimeBitsIgnoreComptime(pt)) continue;
53945327
5395 const shift_val = if (backing_type.bitSize(pt) <= 32)5328 const shift_val: WValue = if (backing_type.bitSize(pt) <= 32)
5396 WValue{ .imm32 = current_bit }5329 .{ .imm32 = current_bit }
5397 else5330 else
5398 WValue{ .imm64 = current_bit };5331 .{ .imm64 = current_bit };
53995332
5400 const value = try func.resolveInst(elem);5333 const value = try func.resolveInst(elem);
5401 const value_bit_size: u16 = @intCast(field_ty.bitSize(pt));5334 const value_bit_size: u16 = @intCast(field_ty.bitSize(pt));
...@@ -5473,7 +5406,7 @@ fn airUnionInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5473,7 +5406,7 @@ fn airUnionInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5473 };5406 };
5474 if (layout.payload_size == 0) {5407 if (layout.payload_size == 0) {
5475 if (layout.tag_size == 0) {5408 if (layout.tag_size == 0) {
5476 break :result WValue{ .none = {} };5409 break :result .none;
5477 }5410 }
5478 assert(!isByRef(union_ty, pt));5411 assert(!isByRef(union_ty, pt));
5479 break :result tag_int;5412 break :result tag_int;
...@@ -5511,15 +5444,12 @@ fn airUnionInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5511,15 +5444,12 @@ fn airUnionInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5511 if (field_ty.zigTypeTag(mod) == .Float) {5444 if (field_ty.zigTypeTag(mod) == .Float) {
5512 const int_type = try pt.intType(.unsigned, @intCast(field_ty.bitSize(pt)));5445 const int_type = try pt.intType(.unsigned, @intCast(field_ty.bitSize(pt)));
5513 const bitcasted = try func.bitcast(field_ty, int_type, operand);5446 const bitcasted = try func.bitcast(field_ty, int_type, operand);
5514 const casted = try func.trunc(bitcasted, int_type, union_int_type);5447 break :result try func.trunc(bitcasted, int_type, union_int_type);
5515 break :result try casted.toLocal(func, field_ty);
5516 } else if (field_ty.isPtrAtRuntime(mod)) {5448 } else if (field_ty.isPtrAtRuntime(mod)) {
5517 const int_type = try pt.intType(.unsigned, @intCast(field_ty.bitSize(pt)));5449 const int_type = try pt.intType(.unsigned, @intCast(field_ty.bitSize(pt)));
5518 const casted = try func.intcast(operand, int_type, union_int_type);5450 break :result try func.intcast(operand, int_type, union_int_type);
5519 break :result try casted.toLocal(func, field_ty);
5520 }5451 }
5521 const casted = try func.intcast(operand, field_ty, union_int_type);5452 break :result try func.intcast(operand, field_ty, union_int_type);
5522 break :result try casted.toLocal(func, field_ty);
5523 }5453 }
5524 };5454 };
55255455
...@@ -5528,27 +5458,23 @@ fn airUnionInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5528,27 +5458,23 @@ fn airUnionInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
55285458
5529fn airPrefetch(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {5459fn airPrefetch(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5530 const prefetch = func.air.instructions.items(.data)[@intFromEnum(inst)].prefetch;5460 const prefetch = func.air.instructions.items(.data)[@intFromEnum(inst)].prefetch;
5531 func.finishAir(inst, .none, &.{prefetch.ptr});5461 return func.finishAir(inst, .none, &.{prefetch.ptr});
5532}5462}
55335463
5534fn airWasmMemorySize(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {5464fn airWasmMemorySize(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5535 const pl_op = func.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;5465 const pl_op = func.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
55365466
5537 const result = try func.allocLocal(func.typeOfIndex(inst));
5538 try func.addLabel(.memory_size, pl_op.payload);5467 try func.addLabel(.memory_size, pl_op.payload);
5539 try func.addLabel(.local_set, result.local.value);5468 return func.finishAir(inst, .stack, &.{pl_op.operand});
5540 func.finishAir(inst, result, &.{pl_op.operand});
5541}5469}
55425470
5543fn airWasmMemoryGrow(func: *CodeGen, inst: Air.Inst.Index) !void {5471fn airWasmMemoryGrow(func: *CodeGen, inst: Air.Inst.Index) !void {
5544 const pl_op = func.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;5472 const pl_op = func.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
55455473
5546 const operand = try func.resolveInst(pl_op.operand);5474 const operand = try func.resolveInst(pl_op.operand);
5547 const result = try func.allocLocal(func.typeOfIndex(inst));
5548 try func.emitWValue(operand);5475 try func.emitWValue(operand);
5549 try func.addLabel(.memory_grow, pl_op.payload);5476 try func.addLabel(.memory_grow, pl_op.payload);
5550 try func.addLabel(.local_set, result.local.value);5477 return func.finishAir(inst, .stack, &.{pl_op.operand});
5551 func.finishAir(inst, result, &.{pl_op.operand});
5552}5478}
55535479
5554fn cmpOptionals(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: std.math.CompareOperator) InnerError!WValue {5480fn cmpOptionals(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: std.math.CompareOperator) InnerError!WValue {
...@@ -5582,7 +5508,7 @@ fn cmpOptionals(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op:...@@ -5582,7 +5508,7 @@ fn cmpOptionals(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op:
5582 try func.emitWValue(result);5508 try func.emitWValue(result);
5583 try func.addImm32(0);5509 try func.addImm32(0);
5584 try func.addTag(if (op == .eq) .i32_ne else .i32_eq);5510 try func.addTag(if (op == .eq) .i32_ne else .i32_eq);
5585 return WValue{ .stack = {} };5511 return .stack;
5586}5512}
55875513
5588/// Compares big integers by checking both its high bits and low bits.5514/// Compares big integers by checking both its high bits and low bits.
...@@ -5628,7 +5554,7 @@ fn cmpBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: std...@@ -5628,7 +5554,7 @@ fn cmpBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: std
5628 },5554 },
5629 }5555 }
56305556
5631 return WValue{ .stack = {} };5557 return .stack;
5632}5558}
56335559
5634fn airSetUnionTag(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {5560fn airSetUnionTag(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -5653,7 +5579,7 @@ fn airSetUnionTag(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5653,7 +5579,7 @@ fn airSetUnionTag(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5653 break :blk @intCast(layout.payload_size);5579 break :blk @intCast(layout.payload_size);
5654 } else 0;5580 } else 0;
5655 try func.store(union_ptr, new_tag, tag_ty, offset);5581 try func.store(union_ptr, new_tag, tag_ty, offset);
5656 func.finishAir(inst, .none, &.{ bin_op.lhs, bin_op.rhs });5582 return func.finishAir(inst, .none, &.{ bin_op.lhs, bin_op.rhs });
5657}5583}
56585584
5659fn airGetUnionTag(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {5585fn airGetUnionTag(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -5668,12 +5594,12 @@ fn airGetUnionTag(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5668,12 +5594,12 @@ fn airGetUnionTag(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5668 const operand = try func.resolveInst(ty_op.operand);5594 const operand = try func.resolveInst(ty_op.operand);
5669 // when the tag alignment is smaller than the payload, the field will be stored5595 // when the tag alignment is smaller than the payload, the field will be stored
5670 // after the payload.5596 // after the payload.
5671 const offset: u32 = if (layout.tag_align.compare(.lt, layout.payload_align)) blk: {5597 const offset: u32 = if (layout.tag_align.compare(.lt, layout.payload_align))
5672 break :blk @intCast(layout.payload_size);5598 @intCast(layout.payload_size)
5673 } else 0;5599 else
5674 const tag = try func.load(operand, tag_ty, offset);5600 0;
5675 const result = try tag.toLocal(func, tag_ty);5601 const result = try func.load(operand, tag_ty, offset);
5676 func.finishAir(inst, result, &.{ty_op.operand});5602 return func.finishAir(inst, result, &.{ty_op.operand});
5677}5603}
56785604
5679fn airFpext(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {5605fn airFpext(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -5681,9 +5607,8 @@ fn airFpext(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5681,9 +5607,8 @@ fn airFpext(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
56815607
5682 const dest_ty = func.typeOfIndex(inst);5608 const dest_ty = func.typeOfIndex(inst);
5683 const operand = try func.resolveInst(ty_op.operand);5609 const operand = try func.resolveInst(ty_op.operand);
5684 const extended = try func.fpext(operand, func.typeOf(ty_op.operand), dest_ty);5610 const result = try func.fpext(operand, func.typeOf(ty_op.operand), dest_ty);
5685 const result = try extended.toLocal(func, dest_ty);5611 return func.finishAir(inst, result, &.{ty_op.operand});
5686 func.finishAir(inst, result, &.{ty_op.operand});
5687}5612}
56885613
5689/// Extends a float from a given `Type` to a larger wanted `Type`5614/// Extends a float from a given `Type` to a larger wanted `Type`
...@@ -5695,7 +5620,7 @@ fn fpext(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerError!...@@ -5695,7 +5620,7 @@ fn fpext(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerError!
5695 if (wanted_bits == 64 and given_bits == 32) {5620 if (wanted_bits == 64 and given_bits == 32) {
5696 try func.emitWValue(operand);5621 try func.emitWValue(operand);
5697 try func.addTag(.f64_promote_f32);5622 try func.addTag(.f64_promote_f32);
5698 return WValue{ .stack = {} };5623 return .stack;
5699 } else if (given_bits == 16 and wanted_bits <= 64) {5624 } else if (given_bits == 16 and wanted_bits <= 64) {
5700 // call __extendhfsf2(f16) f325625 // call __extendhfsf2(f16) f32
5701 const f32_result = try func.callIntrinsic(5626 const f32_result = try func.callIntrinsic(
...@@ -5709,7 +5634,7 @@ fn fpext(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerError!...@@ -5709,7 +5634,7 @@ fn fpext(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerError!
5709 if (wanted_bits == 64) {5634 if (wanted_bits == 64) {
5710 try func.addTag(.f64_promote_f32);5635 try func.addTag(.f64_promote_f32);
5711 }5636 }
5712 return WValue{ .stack = {} };5637 return .stack;
5713 }5638 }
57145639
5715 var fn_name_buf: [13]u8 = undefined;5640 var fn_name_buf: [13]u8 = undefined;
...@@ -5726,9 +5651,8 @@ fn airFptrunc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5726,9 +5651,8 @@ fn airFptrunc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
57265651
5727 const dest_ty = func.typeOfIndex(inst);5652 const dest_ty = func.typeOfIndex(inst);
5728 const operand = try func.resolveInst(ty_op.operand);5653 const operand = try func.resolveInst(ty_op.operand);
5729 const truncated = try func.fptrunc(operand, func.typeOf(ty_op.operand), dest_ty);5654 const result = try func.fptrunc(operand, func.typeOf(ty_op.operand), dest_ty);
5730 const result = try truncated.toLocal(func, dest_ty);5655 return func.finishAir(inst, result, &.{ty_op.operand});
5731 func.finishAir(inst, result, &.{ty_op.operand});
5732}5656}
57335657
5734/// Truncates a float from a given `Type` to its wanted `Type`5658/// Truncates a float from a given `Type` to its wanted `Type`
...@@ -5740,12 +5664,12 @@ fn fptrunc(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerErro...@@ -5740,12 +5664,12 @@ fn fptrunc(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerErro
5740 if (wanted_bits == 32 and given_bits == 64) {5664 if (wanted_bits == 32 and given_bits == 64) {
5741 try func.emitWValue(operand);5665 try func.emitWValue(operand);
5742 try func.addTag(.f32_demote_f64);5666 try func.addTag(.f32_demote_f64);
5743 return WValue{ .stack = {} };5667 return .stack;
5744 } else if (wanted_bits == 16 and given_bits <= 64) {5668 } else if (wanted_bits == 16 and given_bits <= 64) {
5745 const op: WValue = if (given_bits == 64) blk: {5669 const op: WValue = if (given_bits == 64) blk: {
5746 try func.emitWValue(operand);5670 try func.emitWValue(operand);
5747 try func.addTag(.f32_demote_f64);5671 try func.addTag(.f32_demote_f64);
5748 break :blk WValue{ .stack = {} };5672 break :blk .stack;
5749 } else operand;5673 } else operand;
57505674
5751 // call __truncsfhf2(f32) f165675 // call __truncsfhf2(f32) f16
...@@ -5785,7 +5709,7 @@ fn airErrUnionPayloadPtrSet(func: *CodeGen, inst: Air.Inst.Index) InnerError!voi...@@ -5785,7 +5709,7 @@ fn airErrUnionPayloadPtrSet(func: *CodeGen, inst: Air.Inst.Index) InnerError!voi
57855709
5786 break :result try func.buildPointerOffset(operand, @as(u32, @intCast(errUnionPayloadOffset(payload_ty, pt))), .new);5710 break :result try func.buildPointerOffset(operand, @as(u32, @intCast(errUnionPayloadOffset(payload_ty, pt))), .new);
5787 };5711 };
5788 func.finishAir(inst, result, &.{ty_op.operand});5712 return func.finishAir(inst, result, &.{ty_op.operand});
5789}5713}
57905714
5791fn airFieldParentPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {5715fn airFieldParentPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -5807,7 +5731,7 @@ fn airFieldParentPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5807,7 +5731,7 @@ fn airFieldParentPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5807 break :result base;5731 break :result base;
5808 } else func.reuseOperand(extra.field_ptr, field_ptr);5732 } else func.reuseOperand(extra.field_ptr, field_ptr);
58095733
5810 func.finishAir(inst, result, &.{extra.field_ptr});5734 return func.finishAir(inst, result, &.{extra.field_ptr});
5811}5735}
58125736
5813fn sliceOrArrayPtr(func: *CodeGen, ptr: WValue, ptr_ty: Type) InnerError!WValue {5737fn sliceOrArrayPtr(func: *CodeGen, ptr: WValue, ptr_ty: Type) InnerError!WValue {
...@@ -5849,12 +5773,12 @@ fn airMemcpy(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5849,12 +5773,12 @@ fn airMemcpy(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5849 const src_ptr = try func.sliceOrArrayPtr(src, src_ty);5773 const src_ptr = try func.sliceOrArrayPtr(src, src_ty);
5850 try func.memcpy(dst_ptr, src_ptr, len);5774 try func.memcpy(dst_ptr, src_ptr, len);
58515775
5852 func.finishAir(inst, .none, &.{ bin_op.lhs, bin_op.rhs });5776 return func.finishAir(inst, .none, &.{ bin_op.lhs, bin_op.rhs });
5853}5777}
58545778
5855fn airRetAddr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {5779fn airRetAddr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5856 // TODO: Implement this properly once stack serialization is solved5780 // TODO: Implement this properly once stack serialization is solved
5857 func.finishAir(inst, switch (func.arch()) {5781 return func.finishAir(inst, switch (func.arch()) {
5858 .wasm32 => .{ .imm32 = 0 },5782 .wasm32 => .{ .imm32 = 0 },
5859 .wasm64 => .{ .imm64 = 0 },5783 .wasm64 => .{ .imm64 = 0 },
5860 else => unreachable,5784 else => unreachable,
...@@ -5868,7 +5792,6 @@ fn airPopcount(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5868,7 +5792,6 @@ fn airPopcount(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
58685792
5869 const operand = try func.resolveInst(ty_op.operand);5793 const operand = try func.resolveInst(ty_op.operand);
5870 const op_ty = func.typeOf(ty_op.operand);5794 const op_ty = func.typeOf(ty_op.operand);
5871 const result_ty = func.typeOfIndex(inst);
58725795
5873 if (op_ty.zigTypeTag(mod) == .Vector) {5796 if (op_ty.zigTypeTag(mod) == .Vector) {
5874 return func.fail("TODO: Implement @popCount for vectors", .{});5797 return func.fail("TODO: Implement @popCount for vectors", .{});
...@@ -5911,9 +5834,7 @@ fn airPopcount(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5911,9 +5834,7 @@ fn airPopcount(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5911 else => unreachable,5834 else => unreachable,
5912 }5835 }
59135836
5914 const result = try func.allocLocal(result_ty);5837 return func.finishAir(inst, .stack, &.{ty_op.operand});
5915 try func.addLabel(.local_set, result.local.value);
5916 func.finishAir(inst, result, &.{ty_op.operand});
5917}5838}
59185839
5919fn airBitReverse(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {5840fn airBitReverse(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -5942,12 +5863,11 @@ fn airBitReverse(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5942,12 +5863,11 @@ fn airBitReverse(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5942 Type.u32,5863 Type.u32,
5943 &.{operand},5864 &.{operand},
5944 );5865 );
5945 const reversed = if (bits == 32)5866 const result = if (bits == 32)
5946 intrin_ret5867 intrin_ret
5947 else5868 else
5948 try func.binOp(intrin_ret, .{ .imm32 = 32 - bits }, ty, .shr);5869 try func.binOp(intrin_ret, .{ .imm32 = 32 - bits }, ty, .shr);
5949 const result = try reversed.toLocal(func, ty);5870 return func.finishAir(inst, result, &.{ty_op.operand});
5950 func.finishAir(inst, result, &.{ty_op.operand});
5951 },5871 },
5952 64 => {5872 64 => {
5953 const intrin_ret = try func.callIntrinsic(5873 const intrin_ret = try func.callIntrinsic(
...@@ -5956,12 +5876,11 @@ fn airBitReverse(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5956,12 +5876,11 @@ fn airBitReverse(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5956 Type.u64,5876 Type.u64,
5957 &.{operand},5877 &.{operand},
5958 );5878 );
5959 const reversed = if (bits == 64)5879 const result = if (bits == 64)
5960 intrin_ret5880 intrin_ret
5961 else5881 else
5962 try func.binOp(intrin_ret, .{ .imm64 = 64 - bits }, ty, .shr);5882 try func.binOp(intrin_ret, .{ .imm64 = 64 - bits }, ty, .shr);
5963 const result = try reversed.toLocal(func, ty);5883 return func.finishAir(inst, result, &.{ty_op.operand});
5964 func.finishAir(inst, result, &.{ty_op.operand});
5965 },5884 },
5966 128 => {5885 128 => {
5967 const result = try func.allocStack(ty);5886 const result = try func.allocStack(ty);
...@@ -6008,7 +5927,7 @@ fn airBitReverse(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6008,7 +5927,7 @@ fn airBitReverse(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6008 try func.addTag(.i64_or);5927 try func.addTag(.i64_or);
6009 try func.store(.stack, .stack, Type.u64, result.offset());5928 try func.store(.stack, .stack, Type.u64, result.offset());
6010 }5929 }
6011 func.finishAir(inst, result, &.{ty_op.operand});5930 return func.finishAir(inst, result, &.{ty_op.operand});
6012 },5931 },
6013 else => unreachable,5932 else => unreachable,
6014 }5933 }
...@@ -6051,16 +5970,14 @@ fn airErrorName(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6051,16 +5970,14 @@ fn airErrorName(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6051 else => unreachable,5970 else => unreachable,
6052 }5971 }
60535972
6054 const result_ptr = try func.allocLocal(Type.usize);5973 return func.finishAir(inst, .stack, &.{un_op});
6055 try func.addLabel(.local_set, result_ptr.local.value);
6056 func.finishAir(inst, result_ptr, &.{un_op});
6057}5974}
60585975
6059fn airPtrSliceFieldPtr(func: *CodeGen, inst: Air.Inst.Index, offset: u32) InnerError!void {5976fn airPtrSliceFieldPtr(func: *CodeGen, inst: Air.Inst.Index, offset: u32) InnerError!void {
6060 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;5977 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
6061 const slice_ptr = try func.resolveInst(ty_op.operand);5978 const slice_ptr = try func.resolveInst(ty_op.operand);
6062 const result = try func.buildPointerOffset(slice_ptr, offset, .new);5979 const result = try func.buildPointerOffset(slice_ptr, offset, .new);
6063 func.finishAir(inst, result, &.{ty_op.operand});5980 return func.finishAir(inst, result, &.{ty_op.operand});
6064}5981}
60655982
6066fn airAddSubWithOverflow(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {5983fn airAddSubWithOverflow(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {
...@@ -6089,9 +6006,9 @@ fn airAddSubWithOverflow(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerErro...@@ -6089,9 +6006,9 @@ fn airAddSubWithOverflow(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerErro
6089 return func.finishAir(inst, result, &.{ extra.lhs, extra.rhs });6006 return func.finishAir(inst, result, &.{ extra.lhs, extra.rhs });
6090 }6007 }
60916008
6092 const zero = switch (wasm_bits) {6009 const zero: WValue = switch (wasm_bits) {
6093 32 => WValue{ .imm32 = 0 },6010 32 => .{ .imm32 = 0 },
6094 64 => WValue{ .imm64 = 0 },6011 64 => .{ .imm64 = 0 },
6095 else => unreachable,6012 else => unreachable,
6096 };6013 };
60976014
...@@ -6121,7 +6038,7 @@ fn airAddSubWithOverflow(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerErro...@@ -6121,7 +6038,7 @@ fn airAddSubWithOverflow(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerErro
6121 const offset = @as(u32, @intCast(lhs_ty.abiSize(pt)));6038 const offset = @as(u32, @intCast(lhs_ty.abiSize(pt)));
6122 try func.store(result_ptr, overflow_local, Type.u1, offset);6039 try func.store(result_ptr, overflow_local, Type.u1, offset);
61236040
6124 func.finishAir(inst, result_ptr, &.{ extra.lhs, extra.rhs });6041 return func.finishAir(inst, result_ptr, &.{ extra.lhs, extra.rhs });
6125}6042}
61266043
6127fn addSubWithOverflowBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, result_ty: Type, op: Op) InnerError!WValue {6044fn addSubWithOverflowBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, result_ty: Type, op: Op) InnerError!WValue {
...@@ -6177,7 +6094,7 @@ fn addSubWithOverflowBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type,...@@ -6177,7 +6094,7 @@ fn addSubWithOverflowBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type,
6177 _ = try func.cmp(tmp_op, lhs_low_bit, Type.u64, .eq);6094 _ = try func.cmp(tmp_op, lhs_low_bit, Type.u64, .eq);
6178 try func.addTag(.select);6095 try func.addTag(.select);
61796096
6180 break :blk WValue{ .stack = {} };6097 break :blk .stack;
6181 };6098 };
6182 var overflow_local = try overflow_bit.toLocal(func, Type.u1);6099 var overflow_local = try overflow_bit.toLocal(func, Type.u1);
6183 defer overflow_local.free(func);6100 defer overflow_local.free(func);
...@@ -6228,7 +6145,7 @@ fn airShlWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6228,7 +6145,7 @@ fn airShlWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6228 const overflow_bit = blk: {6145 const overflow_bit = blk: {
6229 try func.emitWValue(lhs);6146 try func.emitWValue(lhs);
6230 const shr = try func.binOp(result, rhs_final, lhs_ty, .shr);6147 const shr = try func.binOp(result, rhs_final, lhs_ty, .shr);
6231 break :blk try func.cmp(.{ .stack = {} }, shr, lhs_ty, .neq);6148 break :blk try func.cmp(.stack, shr, lhs_ty, .neq);
6232 };6149 };
6233 var overflow_local = try overflow_bit.toLocal(func, Type.u1);6150 var overflow_local = try overflow_bit.toLocal(func, Type.u1);
6234 defer overflow_local.free(func);6151 defer overflow_local.free(func);
...@@ -6238,7 +6155,7 @@ fn airShlWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6238,7 +6155,7 @@ fn airShlWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6238 const offset = @as(u32, @intCast(lhs_ty.abiSize(pt)));6155 const offset = @as(u32, @intCast(lhs_ty.abiSize(pt)));
6239 try func.store(result_ptr, overflow_local, Type.u1, offset);6156 try func.store(result_ptr, overflow_local, Type.u1, offset);
62406157
6241 func.finishAir(inst, result_ptr, &.{ extra.lhs, extra.rhs });6158 return func.finishAir(inst, result_ptr, &.{ extra.lhs, extra.rhs });
6242}6159}
62436160
6244fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {6161fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -6265,9 +6182,9 @@ fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6265,9 +6182,9 @@ fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6265 return func.fail("TODO: Implement `@mulWithOverflow` for integer bitsize: {d}", .{int_info.bits});6182 return func.fail("TODO: Implement `@mulWithOverflow` for integer bitsize: {d}", .{int_info.bits});
6266 };6183 };
62676184
6268 const zero = switch (wasm_bits) {6185 const zero: WValue = switch (wasm_bits) {
6269 32 => WValue{ .imm32 = 0 },6186 32 => .{ .imm32 = 0 },
6270 64, 128 => WValue{ .imm64 = 0 },6187 64, 128 => .{ .imm64 = 0 },
6271 else => unreachable,6188 else => unreachable,
6272 };6189 };
62736190
...@@ -6303,10 +6220,10 @@ fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6303,10 +6220,10 @@ fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6303 } else if (wasm_bits == 32) blk: {6220 } else if (wasm_bits == 32) blk: {
6304 var bin_op = try (try func.binOp(lhs, rhs, lhs_ty, .mul)).toLocal(func, lhs_ty);6221 var bin_op = try (try func.binOp(lhs, rhs, lhs_ty, .mul)).toLocal(func, lhs_ty);
6305 defer bin_op.free(func);6222 defer bin_op.free(func);
6306 const shift_imm = if (wasm_bits == 32)6223 const shift_imm: WValue = if (wasm_bits == 32)
6307 WValue{ .imm32 = int_info.bits }6224 .{ .imm32 = int_info.bits }
6308 else6225 else
6309 WValue{ .imm64 = int_info.bits };6226 .{ .imm64 = int_info.bits };
6310 const shr = try func.binOp(bin_op, shift_imm, lhs_ty, .shr);6227 const shr = try func.binOp(bin_op, shift_imm, lhs_ty, .shr);
6311 _ = try func.cmp(shr, zero, lhs_ty, .neq);6228 _ = try func.cmp(shr, zero, lhs_ty, .neq);
6312 try func.addLabel(.local_set, overflow_bit.local.value);6229 try func.addLabel(.local_set, overflow_bit.local.value);
...@@ -6412,7 +6329,7 @@ fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6412,7 +6329,7 @@ fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6412 const offset = @as(u32, @intCast(lhs_ty.abiSize(pt)));6329 const offset = @as(u32, @intCast(lhs_ty.abiSize(pt)));
6413 try func.store(result_ptr, overflow_bit, Type.u1, offset);6330 try func.store(result_ptr, overflow_bit, Type.u1, offset);
64146331
6415 func.finishAir(inst, result_ptr, &.{ extra.lhs, extra.rhs });6332 return func.finishAir(inst, result_ptr, &.{ extra.lhs, extra.rhs });
6416}6333}
64176334
6418fn airMaxMin(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {6335fn airMaxMin(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {
...@@ -6454,11 +6371,7 @@ fn airMaxMin(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {...@@ -6454,11 +6371,7 @@ fn airMaxMin(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {
6454 try func.addTag(.select);6371 try func.addTag(.select);
6455 }6372 }
64566373
6457 // store result in local6374 return func.finishAir(inst, .stack, &.{ bin_op.lhs, bin_op.rhs });
6458 const result_ty = if (isByRef(ty, pt)) Type.u32 else ty;
6459 const result = try func.allocLocal(result_ty);
6460 try func.addLabel(.local_set, result.local.value);
6461 func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });
6462}6375}
64636376
6464fn airMulAdd(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {6377fn airMulAdd(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -6487,13 +6400,13 @@ fn airMulAdd(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6487,13 +6400,13 @@ fn airMulAdd(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6487 Type.f32,6400 Type.f32,
6488 &.{ rhs_ext, lhs_ext, addend_ext },6401 &.{ rhs_ext, lhs_ext, addend_ext },
6489 );6402 );
6490 break :fl_result try (try func.fptrunc(result, Type.f32, ty)).toLocal(func, ty);6403 break :fl_result try func.fptrunc(result, Type.f32, ty);
6491 } else result: {6404 } else result: {
6492 const mul_result = try func.binOp(lhs, rhs, ty, .mul);6405 const mul_result = try func.binOp(lhs, rhs, ty, .mul);
6493 break :result try (try func.binOp(mul_result, addend, ty, .add)).toLocal(func, ty);6406 break :result try func.binOp(mul_result, addend, ty, .add);
6494 };6407 };
64956408
6496 func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs, pl_op.operand });6409 return func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs, pl_op.operand });
6497}6410}
64986411
6499fn airClz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {6412fn airClz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -6502,7 +6415,6 @@ fn airClz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6502,7 +6415,6 @@ fn airClz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6502 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;6415 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
65036416
6504 const ty = func.typeOf(ty_op.operand);6417 const ty = func.typeOf(ty_op.operand);
6505 const result_ty = func.typeOfIndex(inst);
6506 if (ty.zigTypeTag(mod) == .Vector) {6418 if (ty.zigTypeTag(mod) == .Vector) {
6507 return func.fail("TODO: `@clz` for vectors", .{});6419 return func.fail("TODO: `@clz` for vectors", .{});
6508 }6420 }
...@@ -6545,9 +6457,7 @@ fn airClz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6545,9 +6457,7 @@ fn airClz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6545 try func.addTag(.i32_sub);6457 try func.addTag(.i32_sub);
6546 }6458 }
65476459
6548 const result = try func.allocLocal(result_ty);6460 return func.finishAir(inst, .stack, &.{ty_op.operand});
6549 try func.addLabel(.local_set, result.local.value);
6550 func.finishAir(inst, result, &.{ty_op.operand});
6551}6461}
65526462
6553fn airCtz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {6463fn airCtz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -6556,7 +6466,6 @@ fn airCtz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6556,7 +6466,6 @@ fn airCtz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6556 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;6466 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
65576467
6558 const ty = func.typeOf(ty_op.operand);6468 const ty = func.typeOf(ty_op.operand);
6559 const result_ty = func.typeOfIndex(inst);
65606469
6561 if (ty.zigTypeTag(mod) == .Vector) {6470 if (ty.zigTypeTag(mod) == .Vector) {
6562 return func.fail("TODO: `@ctz` for vectors", .{});6471 return func.fail("TODO: `@ctz` for vectors", .{});
...@@ -6611,9 +6520,7 @@ fn airCtz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6611,9 +6520,7 @@ fn airCtz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6611 else => unreachable,6520 else => unreachable,
6612 }6521 }
66136522
6614 const result = try func.allocLocal(result_ty);6523 return func.finishAir(inst, .stack, &.{ty_op.operand});
6615 try func.addLabel(.local_set, result.local.value);
6616 func.finishAir(inst, result, &.{ty_op.operand});
6617}6524}
66186525
6619fn airDbgStmt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {6526fn airDbgStmt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -6626,7 +6533,7 @@ fn airDbgStmt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6626,7 +6533,7 @@ fn airDbgStmt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6626 .column = dbg_stmt.column,6533 .column = dbg_stmt.column,
6627 }),6534 }),
6628 } });6535 } });
6629 func.finishAir(inst, .none, &.{});6536 return func.finishAir(inst, .none, &.{});
6630}6537}
66316538
6632fn airDbgInlineBlock(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {6539fn airDbgInlineBlock(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -6659,7 +6566,7 @@ fn airDbgVar(func: *CodeGen, inst: Air.Inst.Index, is_ptr: bool) InnerError!void...@@ -6659,7 +6566,7 @@ fn airDbgVar(func: *CodeGen, inst: Air.Inst.Index, is_ptr: bool) InnerError!void
6659 };6566 };
6660 try func.debug_output.dwarf.genVarDbgInfo(name, ty, mod.funcOwnerDeclIndex(func.func_index), is_ptr, loc);6567 try func.debug_output.dwarf.genVarDbgInfo(name, ty, mod.funcOwnerDeclIndex(func.func_index), is_ptr, loc);
66616568
6662 func.finishAir(inst, .none, &.{});6569 return func.finishAir(inst, .none, &.{});
6663}6570}
66646571
6665fn airTry(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {6572fn airTry(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -6669,7 +6576,7 @@ fn airTry(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6669,7 +6576,7 @@ fn airTry(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6669 const body: []const Air.Inst.Index = @ptrCast(func.air.extra[extra.end..][0..extra.data.body_len]);6576 const body: []const Air.Inst.Index = @ptrCast(func.air.extra[extra.end..][0..extra.data.body_len]);
6670 const err_union_ty = func.typeOf(pl_op.operand);6577 const err_union_ty = func.typeOf(pl_op.operand);
6671 const result = try lowerTry(func, inst, err_union, body, err_union_ty, false);6578 const result = try lowerTry(func, inst, err_union, body, err_union_ty, false);
6672 func.finishAir(inst, result, &.{pl_op.operand});6579 return func.finishAir(inst, result, &.{pl_op.operand});
6673}6580}
66746581
6675fn airTryPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {6582fn airTryPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -6681,7 +6588,7 @@ fn airTryPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6681,7 +6588,7 @@ fn airTryPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6681 const body: []const Air.Inst.Index = @ptrCast(func.air.extra[extra.end..][0..extra.data.body_len]);6588 const body: []const Air.Inst.Index = @ptrCast(func.air.extra[extra.end..][0..extra.data.body_len]);
6682 const err_union_ty = func.typeOf(extra.data.ptr).childType(mod);6589 const err_union_ty = func.typeOf(extra.data.ptr).childType(mod);
6683 const result = try lowerTry(func, inst, err_union_ptr, body, err_union_ty, true);6590 const result = try lowerTry(func, inst, err_union_ptr, body, err_union_ty, true);
6684 func.finishAir(inst, result, &.{extra.data.ptr});6591 return func.finishAir(inst, result, &.{extra.data.ptr});
6685}6592}
66866593
6687fn lowerTry(6594fn lowerTry(
...@@ -6730,7 +6637,7 @@ fn lowerTry(...@@ -6730,7 +6637,7 @@ fn lowerTry(
67306637
6731 // if we reach here it means error was not set, and we want the payload6638 // if we reach here it means error was not set, and we want the payload
6732 if (!pl_has_bits) {6639 if (!pl_has_bits) {
6733 return WValue{ .none = {} };6640 return .none;
6734 }6641 }
67356642
6736 const pl_offset: u32 = @intCast(errUnionPayloadOffset(pl_ty, pt));6643 const pl_offset: u32 = @intCast(errUnionPayloadOffset(pl_ty, pt));
...@@ -6771,12 +6678,10 @@ fn airByteSwap(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6771,12 +6678,10 @@ fn airByteSwap(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6771 Type.u32,6678 Type.u32,
6772 &.{operand},6679 &.{operand},
6773 );6680 );
6774 const swapped = if (int_info.bits == 32)6681 break :result if (int_info.bits == 32)
6775 intrin_ret6682 intrin_ret
6776 else6683 else
6777 try func.binOp(intrin_ret, .{ .imm32 = 32 - int_info.bits }, ty, .shr);6684 try func.binOp(intrin_ret, .{ .imm32 = 32 - int_info.bits }, ty, .shr);
6778
6779 break :result try swapped.toLocal(func, ty);
6780 },6685 },
6781 64 => {6686 64 => {
6782 const intrin_ret = try func.callIntrinsic(6687 const intrin_ret = try func.callIntrinsic(
...@@ -6785,17 +6690,15 @@ fn airByteSwap(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6785,17 +6690,15 @@ fn airByteSwap(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6785 Type.u64,6690 Type.u64,
6786 &.{operand},6691 &.{operand},
6787 );6692 );
6788 const swapped = if (int_info.bits == 64)6693 break :result if (int_info.bits == 64)
6789 intrin_ret6694 intrin_ret
6790 else6695 else
6791 try func.binOp(intrin_ret, .{ .imm64 = 64 - int_info.bits }, ty, .shr);6696 try func.binOp(intrin_ret, .{ .imm64 = 64 - int_info.bits }, ty, .shr);
6792
6793 break :result try swapped.toLocal(func, ty);
6794 },6697 },
6795 else => return func.fail("TODO: @byteSwap for integers with bitsize {d}", .{int_info.bits}),6698 else => return func.fail("TODO: @byteSwap for integers with bitsize {d}", .{int_info.bits}),
6796 }6699 }
6797 };6700 };
6798 func.finishAir(inst, result, &.{ty_op.operand});6701 return func.finishAir(inst, result, &.{ty_op.operand});
6799}6702}
68006703
6801fn airDiv(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {6704fn airDiv(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -6805,8 +6708,8 @@ fn airDiv(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6805,8 +6708,8 @@ fn airDiv(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6805 const lhs = try func.resolveInst(bin_op.lhs);6708 const lhs = try func.resolveInst(bin_op.lhs);
6806 const rhs = try func.resolveInst(bin_op.rhs);6709 const rhs = try func.resolveInst(bin_op.rhs);
68076710
6808 const result = try (try func.binOp(lhs, rhs, ty, .div)).toLocal(func, ty);6711 const result = try func.binOp(lhs, rhs, ty, .div);
6809 func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });6712 return func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });
6810}6713}
68116714
6812fn airDivTrunc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {6715fn airDivTrunc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -6816,10 +6719,10 @@ fn airDivTrunc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6816,10 +6719,10 @@ fn airDivTrunc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6816 const lhs = try func.resolveInst(bin_op.lhs);6719 const lhs = try func.resolveInst(bin_op.lhs);
6817 const rhs = try func.resolveInst(bin_op.rhs);6720 const rhs = try func.resolveInst(bin_op.rhs);
68186721
6819 const div_result = try (try func.binOp(lhs, rhs, ty, .div)).toLocal(func, ty);6722 const div_result = try func.binOp(lhs, rhs, ty, .div);
68206723
6821 if (ty.isAnyFloat()) {6724 if (ty.isAnyFloat()) {
6822 const trunc_result = try (try func.floatOp(.trunc, ty, &.{div_result})).toLocal(func, ty);6725 const trunc_result = try func.floatOp(.trunc, ty, &.{div_result});
6823 return func.finishAir(inst, trunc_result, &.{ bin_op.lhs, bin_op.rhs });6726 return func.finishAir(inst, trunc_result, &.{ bin_op.lhs, bin_op.rhs });
6824 }6727 }
68256728
...@@ -6847,9 +6750,9 @@ fn airDivFloor(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6847,9 +6750,9 @@ fn airDivFloor(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6847 return func.fail("TODO: `@divFloor` for signed integers larger than 64 bits ({d} bits requested)", .{int_bits});6750 return func.fail("TODO: `@divFloor` for signed integers larger than 64 bits ({d} bits requested)", .{int_bits});
6848 }6751 }
68496752
6850 const zero = switch (wasm_bits) {6753 const zero: WValue = switch (wasm_bits) {
6851 32 => WValue{ .imm32 = 0 },6754 32 => .{ .imm32 = 0 },
6852 64 => WValue{ .imm64 = 0 },6755 64 => .{ .imm64 = 0 },
6853 else => unreachable,6756 else => unreachable,
6854 };6757 };
68556758
...@@ -6895,7 +6798,7 @@ fn airDivFloor(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6895,7 +6798,7 @@ fn airDivFloor(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6895 // TODO: Should we be zeroing the high bits here or should we be ignoring the high bits6798 // TODO: Should we be zeroing the high bits here or should we be ignoring the high bits
6896 // when performing comparisons?6799 // when performing comparisons?
6897 if (int_bits != wasm_bits) {6800 if (int_bits != wasm_bits) {
6898 _ = try func.wrapOperand(.{ .stack = {} }, ty);6801 _ = try func.wrapOperand(.stack, ty);
6899 }6802 }
6900 } else {6803 } else {
6901 const float_bits = ty.floatBits(func.target);6804 const float_bits = ty.floatBits(func.target);
...@@ -6923,13 +6826,11 @@ fn airDivFloor(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6923,13 +6826,11 @@ fn airDivFloor(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6923 }6826 }
69246827
6925 if (is_f16) {6828 if (is_f16) {
6926 _ = try func.fptrunc(.{ .stack = {} }, Type.f32, Type.f16);6829 _ = try func.fptrunc(.stack, Type.f32, Type.f16);
6927 }6830 }
6928 }6831 }
69296832
6930 const result = try func.allocLocal(ty);6833 return func.finishAir(inst, .stack, &.{ bin_op.lhs, bin_op.rhs });
6931 try func.addLabel(.local_set, result.local.value);
6932 func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });
6933}6834}
69346835
6935fn airRem(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {6836fn airRem(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -6941,8 +6842,7 @@ fn airRem(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6941,8 +6842,7 @@ fn airRem(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
69416842
6942 const result = try func.binOp(lhs, rhs, ty, .rem);6843 const result = try func.binOp(lhs, rhs, ty, .rem);
69436844
6944 const return_local = try result.toLocal(func, ty);6845 return func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });
6945 func.finishAir(inst, return_local, &.{ bin_op.lhs, bin_op.rhs });
6946}6846}
69476847
6948/// Remainder after floor division, defined by:6848/// Remainder after floor division, defined by:
...@@ -6979,9 +6879,7 @@ fn airMod(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6979,9 +6879,7 @@ fn airMod(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6979 return func.fail("TODO: implement `@mod` on floating point types for {}", .{func.target.cpu.arch});6879 return func.fail("TODO: implement `@mod` on floating point types for {}", .{func.target.cpu.arch});
6980 }6880 }
69816881
6982 const result = try func.allocLocal(ty);6882 return func.finishAir(inst, .stack, &.{ bin_op.lhs, bin_op.rhs });
6983 try func.addLabel(.local_set, result.local.value);
6984 func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });
6985}6883}
69866884
6987fn airSatBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {6885fn airSatBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {
...@@ -7011,9 +6909,9 @@ fn airSatBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {...@@ -7011,9 +6909,9 @@ fn airSatBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {
7011 defer bin_result.free(func);6909 defer bin_result.free(func);
7012 if (wasm_bits != int_info.bits and op == .add) {6910 if (wasm_bits != int_info.bits and op == .add) {
7013 const val: u64 = @as(u64, @intCast((@as(u65, 1) << @as(u7, @intCast(int_info.bits))) - 1));6911 const val: u64 = @as(u64, @intCast((@as(u65, 1) << @as(u7, @intCast(int_info.bits))) - 1));
7014 const imm_val = switch (wasm_bits) {6912 const imm_val: WValue = switch (wasm_bits) {
7015 32 => WValue{ .imm32 = @intCast(val) },6913 32 => .{ .imm32 = @intCast(val) },
7016 64 => WValue{ .imm64 = val },6914 64 => .{ .imm64 = val },
7017 else => unreachable,6915 else => unreachable,
7018 };6916 };
70196917
...@@ -7031,9 +6929,7 @@ fn airSatBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {...@@ -7031,9 +6929,7 @@ fn airSatBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {
7031 }6929 }
70326930
7033 try func.addTag(.select);6931 try func.addTag(.select);
7034 const result = try func.allocLocal(ty);6932 return func.finishAir(inst, .stack, &.{ bin_op.lhs, bin_op.rhs });
7035 try func.addLabel(.local_set, result.local.value);
7036 return func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });
7037}6933}
70386934
7039fn signedSat(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError!WValue {6935fn signedSat(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError!WValue {
...@@ -7046,14 +6942,14 @@ fn signedSat(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerEr...@@ -7046,14 +6942,14 @@ fn signedSat(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerEr
70466942
7047 const max_val: u64 = @as(u64, @intCast((@as(u65, 1) << @as(u7, @intCast(int_info.bits - 1))) - 1));6943 const max_val: u64 = @as(u64, @intCast((@as(u65, 1) << @as(u7, @intCast(int_info.bits - 1))) - 1));
7048 const min_val: i64 = (-@as(i64, @intCast(@as(u63, @intCast(max_val))))) - 1;6944 const min_val: i64 = (-@as(i64, @intCast(@as(u63, @intCast(max_val))))) - 1;
7049 const max_wvalue = switch (wasm_bits) {6945 const max_wvalue: WValue = switch (wasm_bits) {
7050 32 => WValue{ .imm32 = @as(u32, @truncate(max_val)) },6946 32 => .{ .imm32 = @truncate(max_val) },
7051 64 => WValue{ .imm64 = max_val },6947 64 => .{ .imm64 = max_val },
7052 else => unreachable,6948 else => unreachable,
7053 };6949 };
7054 const min_wvalue = switch (wasm_bits) {6950 const min_wvalue: WValue = switch (wasm_bits) {
7055 32 => WValue{ .imm32 = @as(u32, @bitCast(@as(i32, @truncate(min_val)))) },6951 32 => .{ .imm32 = @bitCast(@as(i32, @truncate(min_val))) },
7056 64 => WValue{ .imm64 = @as(u64, @bitCast(min_val)) },6952 64 => .{ .imm64 = @bitCast(min_val) },
7057 else => unreachable,6953 else => unreachable,
7058 };6954 };
70596955
...@@ -7073,9 +6969,9 @@ fn signedSat(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerEr...@@ -7073,9 +6969,9 @@ fn signedSat(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerEr
7073 try func.addLabel(.local_set, bin_result.local.value); // re-use local6969 try func.addLabel(.local_set, bin_result.local.value); // re-use local
7074 return (try func.wrapOperand(bin_result, ty)).toLocal(func, ty);6970 return (try func.wrapOperand(bin_result, ty)).toLocal(func, ty);
7075 } else {6971 } else {
7076 const zero = switch (wasm_bits) {6972 const zero: WValue = switch (wasm_bits) {
7077 32 => WValue{ .imm32 = 0 },6973 32 => .{ .imm32 = 0 },
7078 64 => WValue{ .imm64 = 0 },6974 64 => .{ .imm64 = 0 },
7079 else => unreachable,6975 else => unreachable,
7080 };6976 };
7081 try func.emitWValue(max_wvalue);6977 try func.emitWValue(max_wvalue);
...@@ -7110,7 +7006,7 @@ fn airShlSat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -7110,7 +7006,7 @@ fn airShlSat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
7110 const wasm_bits = toWasmBits(int_info.bits).?;7006 const wasm_bits = toWasmBits(int_info.bits).?;
7111 const result = try func.allocLocal(ty);7007 const result = try func.allocLocal(ty);
71127008
7113 if (wasm_bits == int_info.bits) outer_blk: {7009 if (wasm_bits == int_info.bits) {
7114 var shl = try (try func.binOp(lhs, rhs, ty, .shl)).toLocal(func, ty);7010 var shl = try (try func.binOp(lhs, rhs, ty, .shl)).toLocal(func, ty);
7115 defer shl.free(func);7011 defer shl.free(func);
7116 var shr = try (try func.binOp(shl, rhs, ty, .shr)).toLocal(func, ty);7012 var shr = try (try func.binOp(shl, rhs, ty, .shr)).toLocal(func, ty);
...@@ -7143,12 +7039,11 @@ fn airShlSat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -7143,12 +7039,11 @@ fn airShlSat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
7143 _ = try func.cmp(lhs, shr, ty, .neq);7039 _ = try func.cmp(lhs, shr, ty, .neq);
7144 try func.addTag(.select);7040 try func.addTag(.select);
7145 try func.addLabel(.local_set, result.local.value);7041 try func.addLabel(.local_set, result.local.value);
7146 break :outer_blk;
7147 } else {7042 } else {
7148 const shift_size = wasm_bits - int_info.bits;7043 const shift_size = wasm_bits - int_info.bits;
7149 const shift_value = switch (wasm_bits) {7044 const shift_value: WValue = switch (wasm_bits) {
7150 32 => WValue{ .imm32 = shift_size },7045 32 => .{ .imm32 = shift_size },
7151 64 => WValue{ .imm64 = shift_size },7046 64 => .{ .imm64 = shift_size },
7152 else => unreachable,7047 else => unreachable,
7153 };7048 };
7154 const ext_ty = try pt.intType(int_info.signedness, wasm_bits);7049 const ext_ty = try pt.intType(int_info.signedness, wasm_bits);
...@@ -7232,7 +7127,7 @@ fn callIntrinsic(...@@ -7232,7 +7127,7 @@ fn callIntrinsic(
7232 const sret_local = try func.allocStack(return_type);7127 const sret_local = try func.allocStack(return_type);
7233 try func.lowerToStack(sret_local);7128 try func.lowerToStack(sret_local);
7234 break :blk sret_local;7129 break :blk sret_local;
7235 } else WValue{ .none = {} };7130 } else .none;
72367131
7237 // Lower all arguments to the stack before we call our function7132 // Lower all arguments to the stack before we call our function
7238 for (args, 0..) |arg, arg_i| {7133 for (args, 0..) |arg, arg_i| {
...@@ -7245,14 +7140,14 @@ fn callIntrinsic(...@@ -7245,14 +7140,14 @@ fn callIntrinsic(
7245 try func.addLabel(.call, @intFromEnum(symbol_index));7140 try func.addLabel(.call, @intFromEnum(symbol_index));
72467141
7247 if (!return_type.hasRuntimeBitsIgnoreComptime(pt)) {7142 if (!return_type.hasRuntimeBitsIgnoreComptime(pt)) {
7248 return WValue.none;7143 return .none;
7249 } else if (return_type.isNoReturn(mod)) {7144 } else if (return_type.isNoReturn(mod)) {
7250 try func.addTag(.@"unreachable");7145 try func.addTag(.@"unreachable");
7251 return WValue.none;7146 return .none;
7252 } else if (want_sret_param) {7147 } else if (want_sret_param) {
7253 return sret;7148 return sret;
7254 } else {7149 } else {
7255 return WValue{ .stack = {} };7150 return .stack;
7256 }7151 }
7257}7152}
72587153
...@@ -7571,7 +7466,7 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -7571,7 +7466,7 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
7571 break :val ptr_val;7466 break :val ptr_val;
7572 };7467 };
75737468
7574 const result_ptr = if (isByRef(result_ty, pt)) val: {7469 const result = if (isByRef(result_ty, pt)) val: {
7575 try func.emitWValue(cmp_result);7470 try func.emitWValue(cmp_result);
7576 try func.addImm32(~@as(u32, 0));7471 try func.addImm32(~@as(u32, 0));
7577 try func.addTag(.i32_xor);7472 try func.addTag(.i32_xor);
...@@ -7587,10 +7482,10 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -7587,10 +7482,10 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
7587 try func.emitWValue(ptr_val);7482 try func.emitWValue(ptr_val);
7588 try func.emitWValue(cmp_result);7483 try func.emitWValue(cmp_result);
7589 try func.addTag(.select);7484 try func.addTag(.select);
7590 break :val try WValue.toLocal(.stack, func, result_ty);7485 break :val .stack;
7591 };7486 };
75927487
7593 return func.finishAir(inst, result_ptr, &.{ extra.ptr, extra.expected_value, extra.new_value });7488 return func.finishAir(inst, result, &.{ extra.ptr, extra.expected_value, extra.new_value });
7594}7489}
75957490
7596fn airAtomicLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {7491fn airAtomicLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -7616,8 +7511,7 @@ fn airAtomicLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -7616,8 +7511,7 @@ fn airAtomicLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
7616 _ = try func.load(ptr, ty, 0);7511 _ = try func.load(ptr, ty, 0);
7617 }7512 }
76187513
7619 const result = try WValue.toLocal(.stack, func, ty);7514 return func.finishAir(inst, .stack, &.{atomic_load.ptr});
7620 return func.finishAir(inst, result, &.{atomic_load.ptr});
7621}7515}
76227516
7623fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {7517fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -7734,8 +7628,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -7734,8 +7628,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
7734 .offset = ptr.offset(),7628 .offset = ptr.offset(),
7735 .alignment = @intCast(ty.abiAlignment(pt).toByteUnits().?),7629 .alignment = @intCast(ty.abiAlignment(pt).toByteUnits().?),
7736 });7630 });
7737 const result = try WValue.toLocal(.stack, func, ty);7631 return func.finishAir(inst, .stack, &.{ pl_op.operand, extra.operand });
7738 return func.finishAir(inst, result, &.{ pl_op.operand, extra.operand });
7739 },7632 },
7740 }7633 }
7741 } else {7634 } else {
...@@ -7847,8 +7740,7 @@ fn airFrameAddress(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -7847,8 +7740,7 @@ fn airFrameAddress(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
7847 try func.initializeStack();7740 try func.initializeStack();
7848 }7741 }
7849 try func.emitWValue(func.bottom_stack_value);7742 try func.emitWValue(func.bottom_stack_value);
7850 const result = try WValue.toLocal(.stack, func, Type.usize);7743 return func.finishAir(inst, .stack, &.{});
7851 return func.finishAir(inst, result, &.{});
7852}7744}
78537745
7854fn typeOf(func: *CodeGen, inst: Air.Inst.Ref) Type {7746fn typeOf(func: *CodeGen, inst: Air.Inst.Ref) Type {