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 {
793793 const val = (try func.air.value(ref, pt)).?;
794794 const ty = func.typeOf(ref);
795795 if (!ty.hasRuntimeBitsIgnoreComptime(pt) and !ty.isInt(mod) and !ty.isError(mod)) {
796 gop.value_ptr.* = WValue{ .none = {} };
796 gop.value_ptr.* = .none;
797797 return gop.value_ptr.*;
798798 }
799799
......@@ -803,16 +803,17 @@ fn resolveInst(func: *CodeGen, ref: Air.Inst.Ref) InnerError!WValue {
803803 //
804804 // In the other cases, we will simply lower the constant to a value that fits
805805 // into a single local (such as a pointer, integer, bool, etc).
806 const result = if (isByRef(ty, pt)) blk: {
807 const sym_index = try func.bin_file.lowerUnnamedConst(pt, val, func.decl_index);
808 break :blk WValue{ .memory = sym_index };
809 } else try func.lowerConstant(val, ty);
806 const result: WValue = if (isByRef(ty, pt))
807 .{ .memory = try func.bin_file.lowerUnnamedConst(pt, val, func.decl_index) }
808 else
809 try func.lowerConstant(val, ty);
810810
811811 gop.value_ptr.* = result;
812812 return result;
813813}
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 {
816817 assert(operands.len <= Liveness.bpi - 1);
817818 var tomb_bits = func.liveness.getTombBits(inst);
818819 for (operands) |operand| {
......@@ -824,9 +825,12 @@ fn finishAir(func: *CodeGen, inst: Air.Inst.Index, result: WValue, operands: []c
824825
825826 // results of `none` can never be referenced.
826827 if (result != .none) {
827 assert(result != .stack); // it's illegal to store a stack value as we cannot track its position
828 const trackable_result = if (result != .stack)
829 result
830 else
831 try result.toLocal(func, func.typeOfIndex(inst));
828832 const branch = func.currentBranch();
829 branch.values.putAssumeCapacityNoClobber(inst.toRef(), result);
833 branch.values.putAssumeCapacityNoClobber(inst.toRef(), trackable_result);
830834 }
831835
832836 if (std.debug.runtime_safety) {
......@@ -1105,30 +1109,18 @@ fn getResolvedInst(func: *CodeGen, ref: Air.Inst.Ref) *WValue {
11051109fn allocLocal(func: *CodeGen, ty: Type) InnerError!WValue {
11061110 const pt = func.pt;
11071111 const valtype = typeToValtype(ty, pt);
1108 switch (valtype) {
1109 .i32 => if (func.free_locals_i32.popOrNull()) |index| {
1110 log.debug("reusing local ({d}) of type {}", .{ index, valtype });
1111 return WValue{ .local = .{ .value = index, .references = 1 } };
1112 },
1113 .i64 => if (func.free_locals_i64.popOrNull()) |index| {
1114 log.debug("reusing local ({d}) of type {}", .{ index, valtype });
1115 return WValue{ .local = .{ .value = index, .references = 1 } };
1116 },
1117 .f32 => if (func.free_locals_f32.popOrNull()) |index| {
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 },
1112 const index_or_null = switch (valtype) {
1113 .i32 => func.free_locals_i32.popOrNull(),
1114 .i64 => func.free_locals_i64.popOrNull(),
1115 .f32 => func.free_locals_f32.popOrNull(),
1116 .f64 => func.free_locals_f64.popOrNull(),
1117 .v128 => func.free_locals_v128.popOrNull(),
1118 };
1119 if (index_or_null) |index| {
1120 log.debug("reusing local ({d}) of type {}", .{ index, valtype });
1121 return .{ .local = .{ .value = index, .references = 1 } };
11291122 }
11301123 log.debug("new local of type {}", .{valtype});
1131 // no local was free to be re-used, so allocate a new local instead
11321124 return func.ensureAllocLocal(ty);
11331125}
11341126
......@@ -1139,7 +1131,7 @@ fn ensureAllocLocal(func: *CodeGen, ty: Type) InnerError!WValue {
11391131 try func.locals.append(func.gpa, genValtype(ty, pt));
11401132 const initial_index = func.local_index;
11411133 func.local_index += 1;
1142 return WValue{ .local = .{ .value = initial_index, .references = 1 } };
1134 return .{ .local = .{ .value = initial_index, .references = 1 } };
11431135}
11441136
11451137/// Generates a `wasm.Type` from a given function type.
......@@ -1539,7 +1531,7 @@ fn allocStack(func: *CodeGen, ty: Type) !WValue {
15391531 const offset: u32 = @intCast(abi_align.forward(func.stack_size));
15401532 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 } };
15431535}
15441536
15451537/// 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 {
15711563 const offset: u32 = @intCast(abi_alignment.forward(func.stack_size));
15721564 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 } };
15751567}
15761568
15771569/// From given zig bitsize, returns the wasm bitsize
......@@ -2135,7 +2127,7 @@ fn airRet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
21352127 try func.restoreStackPointer();
21362128 try func.addTag(.@"return");
21372129
2138 func.finishAir(inst, .none, &.{un_op});
2130 return func.finishAir(inst, .none, &.{un_op});
21392131}
21402132
21412133fn airRetPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
......@@ -2156,7 +2148,7 @@ fn airRetPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
21562148 break :result try func.allocStackPtr(inst);
21572149 };
21582150
2159 func.finishAir(inst, result, &.{});
2151 return func.finishAir(inst, result, &.{});
21602152}
21612153
21622154fn 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
22342226 return func.fail("Expected a function, but instead found '{s}'", .{@tagName(ip.indexToKey(func_val.toIntern()))});
22352227 };
22362228
2237 const sret = if (first_param_sret) blk: {
2229 const sret: WValue = if (first_param_sret) blk: {
22382230 const sret_local = try func.allocStack(ret_ty);
22392231 try func.lowerToStack(sret_local);
22402232 break :blk sret_local;
2241 } else WValue{ .none = {} };
2233 } else .none;
22422234
22432235 for (args) |arg| {
22442236 const arg_val = try func.resolveInst(arg);
......@@ -2268,10 +2260,10 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
22682260
22692261 const result_value = result_value: {
22702262 if (!ret_ty.hasRuntimeBitsIgnoreComptime(pt) and !ret_ty.isError(mod)) {
2271 break :result_value WValue{ .none = {} };
2263 break :result_value .none;
22722264 } else if (ret_ty.isNoReturn(mod)) {
22732265 try func.addTag(.@"unreachable");
2274 break :result_value WValue{ .none = {} };
2266 break :result_value .none;
22752267 } else if (first_param_sret) {
22762268 break :result_value sret;
22772269 // TODO: Make this less fragile and optimize
......@@ -2297,7 +2289,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
22972289
22982290fn airAlloc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
22992291 const value = try func.allocStackPtr(inst);
2300 func.finishAir(inst, value, &.{});
2292 return func.finishAir(inst, value, &.{});
23012293}
23022294
23032295fn 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
23302322 var mask = @as(u64, @intCast((@as(u65, 1) << @as(u7, @intCast(ty.bitSize(pt)))) - 1));
23312323 mask <<= @as(u6, @intCast(ptr_info.packed_offset.bit_offset));
23322324 mask ^= ~@as(u64, 0);
2333 const shift_val = if (ptr_info.packed_offset.host_size <= 4)
2334 WValue{ .imm32 = ptr_info.packed_offset.bit_offset }
2325 const shift_val: WValue = if (ptr_info.packed_offset.host_size <= 4)
2326 .{ .imm32 = ptr_info.packed_offset.bit_offset }
23352327 else
2336 WValue{ .imm64 = ptr_info.packed_offset.bit_offset };
2337 const mask_val = if (ptr_info.packed_offset.host_size <= 4)
2338 WValue{ .imm32 = @as(u32, @truncate(mask)) }
2328 .{ .imm64 = ptr_info.packed_offset.bit_offset };
2329 const mask_val: WValue = if (ptr_info.packed_offset.host_size <= 4)
2330 .{ .imm32 = @as(u32, @truncate(mask)) }
23392331 else
2340 WValue{ .imm64 = mask };
2341 const wrap_mask_val = if (ptr_info.packed_offset.host_size <= 4)
2342 WValue{ .imm32 = @truncate(~@as(u64, 0) >> @intCast(64 - ty.bitSize(pt))) }
2332 .{ .imm64 = mask };
2333 const wrap_mask_val: WValue = if (ptr_info.packed_offset.host_size <= 4)
2334 .{ .imm32 = @truncate(~@as(u64, 0) >> @intCast(64 - ty.bitSize(pt))) }
23432335 else
2344 WValue{ .imm64 = ~@as(u64, 0) >> @intCast(64 - ty.bitSize(pt)) };
2336 .{ .imm64 = ~@as(u64, 0) >> @intCast(64 - ty.bitSize(pt)) };
23452337
23462338 try func.emitWValue(lhs);
23472339 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
23562348 try func.store(.stack, result, int_elem_ty, lhs.offset());
23572349 }
23582350
2359 func.finishAir(inst, .none, &.{ bin_op.lhs, bin_op.rhs });
2351 return func.finishAir(inst, .none, &.{ bin_op.lhs, bin_op.rhs });
23602352}
23612353
23622354fn 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
24182410 // lower it to the stack so we do not have to store rhs into a local first
24192411 try func.emitWValue(lhs);
24202412 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
24232415 // retrieve length from rhs, and store that alongside lhs as well
24242416 try func.emitWValue(lhs);
24252417 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());
24272419 return;
24282420 }
24292421 },
24302422 .Int, .Enum, .Float => if (abi_size > 8 and abi_size <= 16) {
24312423 try func.emitWValue(lhs);
24322424 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
24352427 try func.emitWValue(lhs);
24362428 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());
24382430 return;
24392431 } else if (abi_size > 16) {
24402432 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 {
24872479 }
24882480
24892481 if (ptr_info.packed_offset.host_size == 0) {
2490 const stack_loaded = try func.load(operand, ty, 0);
2491 break :result try stack_loaded.toLocal(func, ty);
2482 break :result try func.load(operand, ty, 0);
24922483 }
24932484
24942485 // at this point we have a non-natural alignment, we must
24952486 // shift the value to obtain the correct bit.
24962487 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)
2498 WValue{ .imm32 = ptr_info.packed_offset.bit_offset }
2488 const shift_val: WValue = if (ptr_info.packed_offset.host_size <= 4)
2489 .{ .imm32 = ptr_info.packed_offset.bit_offset }
24992490 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 }
25012492 else
25022493 return func.fail("TODO: airLoad where ptr to bitfield exceeds 64 bits", .{});
25032494
25042495 const stack_loaded = try func.load(operand, int_elem_ty, 0);
25052496 const shifted = try func.binOp(stack_loaded, shift_val, int_elem_ty, .shr);
2506 const 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);
2497 break :result try func.trunc(shifted, ty, int_elem_ty);
25092498 };
2510 func.finishAir(inst, result, &.{ty_op.operand});
2499 return func.finishAir(inst, result, &.{ty_op.operand});
25112500}
25122501
25132502/// Loads an operand from the linear memory section.
......@@ -2528,7 +2517,7 @@ fn load(func: *CodeGen, operand: WValue, ty: Type, offset: u32) InnerError!WValu
25282517 @intCast(ty.abiAlignment(pt).toByteUnits().?),
25292518 });
25302519 try func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } });
2531 return WValue{ .stack = {} };
2520 return .stack;
25322521 }
25332522
25342523 const abi_size: u8 = @intCast(ty.abiSize(pt));
......@@ -2547,7 +2536,7 @@ fn load(func: *CodeGen, operand: WValue, ty: Type, offset: u32) InnerError!WValu
25472536 },
25482537 );
25492538
2550 return WValue{ .stack = {} };
2539 return .stack;
25512540}
25522541
25532542fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
......@@ -2596,7 +2585,7 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
25962585 else => {},
25972586 }
25982587
2599 func.finishAir(inst, arg, &.{});
2588 return func.finishAir(inst, arg, &.{});
26002589}
26012590
26022591fn 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 {
26132602 // case we first coerce the operands to the same type before performing the operation.
26142603 // For big integers we can ignore this as we will call into compiler-rt which handles this.
26152604 const result = switch (op) {
2616 .shr, .shl => res: {
2605 .shr, .shl => result: {
26172606 const lhs_wasm_bits = toWasmBits(@intCast(lhs_ty.bitSize(pt))) orelse {
26182607 return func.fail("TODO: implement '{s}' for types larger than 128 bits", .{@tagName(op)});
26192608 };
26202609 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: {
2622 const tmp = try func.intcast(rhs, rhs_ty, lhs_ty);
2623 break :blk try tmp.toLocal(func, lhs_ty);
2624 } else rhs;
2625 const stack_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);
2610 const new_rhs = if (lhs_wasm_bits != rhs_wasm_bits and lhs_wasm_bits != 128)
2611 try (try func.intcast(rhs, rhs_ty, lhs_ty)).toLocal(func, lhs_ty)
2612 else
2613 rhs;
2614 break :result try func.binOp(lhs, new_rhs, lhs_ty, op);
26312615 },
2616 else => try func.binOp(lhs, rhs, lhs_ty, op),
26322617 };
26332618
2634 func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });
2619 return func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });
26352620}
26362621
26372622/// 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!
26672652
26682653 try func.addTag(Mir.Inst.Tag.fromOpcode(opcode));
26692654
2670 return WValue{ .stack = {} };
2655 return .stack;
26712656}
26722657
26732658fn 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 {
28392824 try func.addTag(.i32_xor);
28402825 try func.emitWValue(tmp);
28412826 try func.addTag(.i32_sub);
2827 return func.finishAir(inst, .stack, &.{ty_op.operand});
28422828 },
28432829 64 => {
28442830 try func.emitWValue(operand);
......@@ -2854,6 +2840,7 @@ fn airAbs(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
28542840 try func.addTag(.i64_xor);
28552841 try func.emitWValue(tmp);
28562842 try func.addTag(.i64_sub);
2843 return func.finishAir(inst, .stack, &.{ty_op.operand});
28572844 },
28582845 128 => {
28592846 const mask = try func.allocStack(Type.u128);
......@@ -2874,18 +2861,14 @@ fn airAbs(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
28742861 const a = try func.binOpBigInt(operand, mask, Type.u128, .xor);
28752862 const b = try func.binOpBigInt(a, mask, Type.u128, .sub);
28762863
2877 func.finishAir(inst, b, &.{ty_op.operand});
2878 return;
2864 return func.finishAir(inst, b, &.{ty_op.operand});
28792865 },
28802866 else => unreachable,
28812867 }
2882
2883 const result = try (WValue{ .stack = {} }).toLocal(func, ty);
2884 func.finishAir(inst, result, &.{ty_op.operand});
28852868 },
28862869 .Float => {
2887 const result = try (try func.floatOp(.fabs, ty, &.{operand})).toLocal(func, ty);
2888 func.finishAir(inst, result, &.{ty_op.operand});
2870 const result = try func.floatOp(.fabs, ty, &.{operand});
2871 return func.finishAir(inst, result, &.{ty_op.operand});
28892872 },
28902873 else => unreachable,
28912874 }
......@@ -2896,8 +2879,8 @@ fn airUnaryFloatOp(func: *CodeGen, inst: Air.Inst.Index, op: FloatOp) InnerError
28962879 const operand = try func.resolveInst(un_op);
28972880 const ty = func.typeOf(un_op);
28982881
2899 const result = try (try func.floatOp(op, ty, &.{operand})).toLocal(func, ty);
2900 func.finishAir(inst, result, &.{un_op});
2882 const result = try func.floatOp(op, ty, &.{operand});
2883 return func.finishAir(inst, result, &.{un_op});
29012884}
29022885
29032886fn 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 {
30273010 // case we first coerce the operands to the same type before performing the operation.
30283011 // For big integers we can ignore this as we will call into compiler-rt which handles this.
30293012 const result = switch (op) {
3030 .shr, .shl => res: {
3013 .shr, .shl => result: {
30313014 const lhs_wasm_bits = toWasmBits(@intCast(lhs_ty.bitSize(pt))) orelse {
30323015 return func.fail("TODO: implement '{s}' for types larger than 128 bits", .{@tagName(op)});
30333016 };
30343017 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: {
3036 const tmp = try func.intcast(rhs, rhs_ty, lhs_ty);
3037 break :blk try tmp.toLocal(func, lhs_ty);
3038 } else rhs;
3039 const stack_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);
3018 const new_rhs = if (lhs_wasm_bits != rhs_wasm_bits and lhs_wasm_bits != 128)
3019 try (try func.intcast(rhs, rhs_ty, lhs_ty)).toLocal(func, lhs_ty)
3020 else
3021 rhs;
3022 break :result try func.wrapBinOp(lhs, new_rhs, lhs_ty, op);
30453023 },
3024 else => try func.wrapBinOp(lhs, rhs, lhs_ty, op),
30463025 };
30473026
30483027 return func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });
......@@ -3187,7 +3166,7 @@ fn lowerAnonDeclRef(
31873166
31883167 const is_fn_body = ty.zigTypeTag(mod) == .Fn;
31893168 if (!is_fn_body and !ty.hasRuntimeBitsIgnoreComptime(pt)) {
3190 return WValue{ .imm32 = 0xaaaaaaaa };
3169 return .{ .imm32 = 0xaaaaaaaa };
31913170 }
31923171
31933172 const decl_align = mod.intern_pool.indexToKey(anon_decl.orig_ty).ptr_type.flags.alignment;
......@@ -3202,10 +3181,10 @@ fn lowerAnonDeclRef(
32023181 const target_atom_index = func.bin_file.zigObjectPtr().?.anon_decls.get(decl_val).?;
32033182 const target_sym_index = @intFromEnum(func.bin_file.getAtom(target_atom_index).sym_index);
32043183 if (is_fn_body) {
3205 return WValue{ .function_index = target_sym_index };
3184 return .{ .function_index = target_sym_index };
32063185 } else if (offset == 0) {
3207 return WValue{ .memory = target_sym_index };
3208 } else return WValue{ .memory_offset = .{ .pointer = target_sym_index, .offset = offset } };
3186 return .{ .memory = target_sym_index };
3187 } else return .{ .memory_offset = .{ .pointer = target_sym_index, .offset = offset } };
32093188}
32103189
32113190fn 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
32263205 }
32273206 const decl_ty = decl.typeOf(mod);
32283207 if (decl_ty.zigTypeTag(mod) != .Fn and !decl_ty.hasRuntimeBitsIgnoreComptime(pt)) {
3229 return WValue{ .imm32 = 0xaaaaaaaa };
3208 return .{ .imm32 = 0xaaaaaaaa };
32303209 }
32313210
32323211 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
32343213
32353214 const target_sym_index = @intFromEnum(atom.sym_index);
32363215 if (decl_ty.zigTypeTag(mod) == .Fn) {
3237 return WValue{ .function_index = target_sym_index };
3216 return .{ .function_index = target_sym_index };
32383217 } else if (offset == 0) {
3239 return WValue{ .memory = target_sym_index };
3240 } else return WValue{ .memory_offset = .{ .pointer = target_sym_index, .offset = offset } };
3218 return .{ .memory = target_sym_index };
3219 } else return .{ .memory_offset = .{ .pointer = target_sym_index, .offset = offset } };
32413220}
32423221
32433222/// Asserts that `isByRef` returns `false` for `ty`.
......@@ -3276,7 +3255,7 @@ fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue {
32763255 .@"unreachable",
32773256 .generic_poison,
32783257 => unreachable, // non-runtime values
3279 .false, .true => return WValue{ .imm32 = switch (simple_value) {
3258 .false, .true => return .{ .imm32 = switch (simple_value) {
32803259 .false => 0,
32813260 .true => 1,
32823261 else => unreachable,
......@@ -3292,20 +3271,20 @@ fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue {
32923271 const int_info = ty.intInfo(mod);
32933272 switch (int_info.signedness) {
32943273 .signed => switch (int_info.bits) {
3295 0...32 => return WValue{ .imm32 = @bitCast(@as(i32, @intCast(val.toSignedInt(pt)))) },
3296 33...64 => return WValue{ .imm64 = @bitCast(val.toSignedInt(pt)) },
3274 0...32 => return .{ .imm32 = @bitCast(@as(i32, @intCast(val.toSignedInt(pt)))) },
3275 33...64 => return .{ .imm64 = @bitCast(val.toSignedInt(pt)) },
32973276 else => unreachable,
32983277 },
32993278 .unsigned => switch (int_info.bits) {
3300 0...32 => return WValue{ .imm32 = @intCast(val.toUnsignedInt(pt)) },
3301 33...64 => return WValue{ .imm64 = val.toUnsignedInt(pt) },
3279 0...32 => return .{ .imm32 = @intCast(val.toUnsignedInt(pt)) },
3280 33...64 => return .{ .imm64 = val.toUnsignedInt(pt) },
33023281 else => unreachable,
33033282 },
33043283 }
33053284 },
33063285 .err => |err| {
33073286 const int = try pt.getErrorValue(err.name);
3308 return WValue{ .imm32 = int };
3287 return .{ .imm32 = int };
33093288 },
33103289 .error_union => |error_union| {
33113290 const err_int_ty = try pt.errorIntType();
......@@ -3335,9 +3314,9 @@ fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue {
33353314 return func.lowerConstant(Value.fromInterned(enum_tag.int), Type.fromInterned(int_tag_ty));
33363315 },
33373316 .float => |float| switch (float.storage) {
3338 .f16 => |f16_val| return WValue{ .imm32 = @as(u16, @bitCast(f16_val)) },
3339 .f32 => |f32_val| return WValue{ .float32 = f32_val },
3340 .f64 => |f64_val| return WValue{ .float64 = f64_val },
3317 .f16 => |f16_val| return .{ .imm32 = @as(u16, @bitCast(f16_val)) },
3318 .f32 => |f32_val| return .{ .float32 = f32_val },
3319 .f64 => |f64_val| return .{ .float64 = f64_val },
33413320 else => unreachable,
33423321 },
33433322 .slice => |slice| {
......@@ -3357,10 +3336,10 @@ fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue {
33573336 if (val.optionalValue(mod)) |payload| {
33583337 return func.lowerConstant(payload, pl_ty);
33593338 } else {
3360 return WValue{ .imm32 = 0 };
3339 return .{ .imm32 = 0 };
33613340 }
33623341 } else {
3363 return WValue{ .imm32 = @intFromBool(!val.isNull(mod)) };
3342 return .{ .imm32 = @intFromBool(!val.isNull(mod)) };
33643343 },
33653344 .aggregate => switch (ip.indexToKey(ty.ip_index)) {
33663345 .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 {
34063385fn storeSimdImmd(func: *CodeGen, value: [16]u8) !WValue {
34073386 const index = @as(u32, @intCast(func.simd_immediates.items.len));
34083387 try func.simd_immediates.append(func.gpa, value);
3409 return WValue{ .imm128 = index };
3388 return .{ .imm128 = index };
34103389}
34113390
34123391fn emitUndefined(func: *CodeGen, ty: Type) InnerError!WValue {
......@@ -3414,21 +3393,21 @@ fn emitUndefined(func: *CodeGen, ty: Type) InnerError!WValue {
34143393 const mod = pt.zcu;
34153394 const ip = &mod.intern_pool;
34163395 switch (ty.zigTypeTag(mod)) {
3417 .Bool, .ErrorSet => return WValue{ .imm32 = 0xaaaaaaaa },
3396 .Bool, .ErrorSet => return .{ .imm32 = 0xaaaaaaaa },
34183397 .Int, .Enum => switch (ty.intInfo(mod).bits) {
3419 0...32 => return WValue{ .imm32 = 0xaaaaaaaa },
3420 33...64 => return WValue{ .imm64 = 0xaaaaaaaaaaaaaaaa },
3398 0...32 => return .{ .imm32 = 0xaaaaaaaa },
3399 33...64 => return .{ .imm64 = 0xaaaaaaaaaaaaaaaa },
34213400 else => unreachable,
34223401 },
34233402 .Float => switch (ty.floatBits(func.target)) {
3424 16 => return WValue{ .imm32 = 0xaaaaaaaa },
3425 32 => return WValue{ .float32 = @as(f32, @bitCast(@as(u32, 0xaaaaaaaa))) },
3426 64 => return WValue{ .float64 = @as(f64, @bitCast(@as(u64, 0xaaaaaaaaaaaaaaaa))) },
3403 16 => return .{ .imm32 = 0xaaaaaaaa },
3404 32 => return .{ .float32 = @as(f32, @bitCast(@as(u32, 0xaaaaaaaa))) },
3405 64 => return .{ .float64 = @as(f64, @bitCast(@as(u64, 0xaaaaaaaaaaaaaaaa))) },
34273406 else => unreachable,
34283407 },
34293408 .Pointer => switch (func.arch()) {
3430 .wasm32 => return WValue{ .imm32 = 0xaaaaaaaa },
3431 .wasm64 => return WValue{ .imm64 = 0xaaaaaaaaaaaaaaaa },
3409 .wasm32 => return .{ .imm32 = 0xaaaaaaaa },
3410 .wasm64 => return .{ .imm64 = 0xaaaaaaaaaaaaaaaa },
34323411 else => unreachable,
34333412 },
34343413 .Optional => {
......@@ -3436,10 +3415,10 @@ fn emitUndefined(func: *CodeGen, ty: Type) InnerError!WValue {
34363415 if (ty.optionalReprIsPayload(mod)) {
34373416 return func.emitUndefined(pl_ty);
34383417 }
3439 return WValue{ .imm32 = 0xaaaaaaaa };
3418 return .{ .imm32 = 0xaaaaaaaa };
34403419 },
34413420 .ErrorUnion => {
3442 return WValue{ .imm32 = 0xaaaaaaaa };
3421 return .{ .imm32 = 0xaaaaaaaa };
34433422 },
34443423 .Struct => {
34453424 const packed_struct = mod.typeToPackedStruct(ty).?;
......@@ -3501,7 +3480,7 @@ fn lowerBlock(func: *CodeGen, inst: Air.Inst.Index, block_ty: Type, body: []cons
35013480 const block_result: WValue = if (wasm_block_ty != wasm.block_empty) blk: {
35023481 const ty: Type = if (isByRef(block_ty, pt)) Type.u32 else block_ty;
35033482 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
35063485 try func.startBlock(.block, wasm.block_empty);
35073486 // 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
35173496 const liveness = func.liveness.getBlock(inst);
35183497 try func.currentBranch().values.ensureUnusedCapacity(func.gpa, liveness.deaths.len);
35193498
3520 func.finishAir(inst, block_result, &.{});
3499 return func.finishAir(inst, block_result, &.{});
35213500}
35223501
35233502/// 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 {
35493528 try func.addLabel(.br, 0);
35503529 try func.endBlock();
35513530
3552 func.finishAir(inst, .none, &.{});
3531 return func.finishAir(inst, .none, &.{});
35533532}
35543533
35553534fn airCondBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
......@@ -3593,7 +3572,7 @@ fn airCondBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
35933572 try func.genBody(then_body);
35943573 }
35953574
3596 func.finishAir(inst, .none, &.{});
3575 return func.finishAir(inst, .none, &.{});
35973576}
35983577
35993578fn 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
36023581 const lhs = try func.resolveInst(bin_op.lhs);
36033582 const rhs = try func.resolveInst(bin_op.rhs);
36043583 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 bits
3606 func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });
3584 const result = try func.cmp(lhs, rhs, operand_ty, op);
3585 return func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });
36073586}
36083587
36093588/// Compares two operands.
......@@ -3654,7 +3633,7 @@ fn cmp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: std.math.CompareO
36543633 });
36553634 try func.addTag(Mir.Inst.Tag.fromOpcode(opcode));
36563635
3657 return WValue{ .stack = {} };
3636 return .stack;
36583637}
36593638
36603639/// Compares two floats.
......@@ -3694,7 +3673,7 @@ fn cmpFloat(func: *CodeGen, ty: Type, lhs: WValue, rhs: WValue, cmp_op: std.math
36943673 }) catch unreachable;
36953674
36963675 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);
36983677 },
36993678 else => unreachable,
37003679 }
......@@ -3709,7 +3688,7 @@ fn airCmpLtErrorsLen(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
37093688 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
37103689 const operand = try func.resolveInst(un_op);
37113690 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
37143693 try func.emitWValue(operand);
37153694 const pt = func.pt;
......@@ -3717,7 +3696,7 @@ fn airCmpLtErrorsLen(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
37173696 const errors_len_val = try func.load(errors_len, err_int_ty, 0);
37183697 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});
37213700}
37223701
37233702fn airBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
......@@ -3740,7 +3719,7 @@ fn airBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
37403719 const idx: u32 = func.block_depth - block.label;
37413720 try func.addLabel(.br, idx);
37423721
3743 func.finishAir(inst, .none, &.{br.operand});
3722 return func.finishAir(inst, .none, &.{br.operand});
37443723}
37453724
37463725fn airNot(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
......@@ -3772,7 +3751,7 @@ fn airNot(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
37723751 .signed => ~@as(u32, 0),
37733752 });
37743753 try func.addTag(.i32_xor);
3775 break :result try @as(WValue, .stack).toLocal(func, operand_ty);
3754 break :result .stack;
37763755 },
37773756 64 => {
37783757 try func.emitWValue(operand);
......@@ -3781,7 +3760,7 @@ fn airNot(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
37813760 .signed => ~@as(u64, 0),
37823761 });
37833762 try func.addTag(.i64_xor);
3784 break :result try @as(WValue, .stack).toLocal(func, operand_ty);
3763 break :result .stack;
37853764 },
37863765 128 => {
37873766 const ptr = try func.allocStack(operand_ty);
......@@ -3807,24 +3786,24 @@ fn airNot(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
38073786 }
38083787 }
38093788 };
3810 func.finishAir(inst, result, &.{ty_op.operand});
3789 return func.finishAir(inst, result, &.{ty_op.operand});
38113790}
38123791
38133792fn airTrap(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
38143793 try func.addTag(.@"unreachable");
3815 func.finishAir(inst, .none, &.{});
3794 return func.finishAir(inst, .none, &.{});
38163795}
38173796
38183797fn airBreakpoint(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
38193798 // unsupported by wasm itfunc. Can be implemented once we support DWARF
38203799 // for wasm
38213800 try func.addTag(.@"unreachable");
3822 func.finishAir(inst, .none, &.{});
3801 return func.finishAir(inst, .none, &.{});
38233802}
38243803
38253804fn airUnreachable(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
38263805 try func.addTag(.@"unreachable");
3827 func.finishAir(inst, .none, &.{});
3806 return func.finishAir(inst, .none, &.{});
38283807}
38293808
38303809fn airBitcast(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
......@@ -3841,35 +3820,34 @@ fn airBitcast(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
38413820
38423821 const result = result: {
38433822 if (given_ty.isAnyFloat() or wanted_ty.isAnyFloat()) {
3844 const bitcast_result = try func.bitcast(wanted_ty, given_ty, operand);
3845 break :result try bitcast_result.toLocal(func, wanted_ty);
3823 break :result try func.bitcast(wanted_ty, given_ty, operand);
38463824 }
38473825
38483826 if (isByRef(given_ty, pt) and !isByRef(wanted_ty, pt)) {
38493827 const loaded_memory = try func.load(operand, wanted_ty, 0);
38503828 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);
38523830 } else {
3853 break :result try loaded_memory.toLocal(func, wanted_ty);
3831 break :result loaded_memory;
38543832 }
38553833 }
38563834 if (!isByRef(given_ty, pt) and isByRef(wanted_ty, pt)) {
38573835 const stack_memory = try func.allocStack(wanted_ty);
38583836 try func.store(stack_memory, operand, given_ty, 0);
38593837 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);
38613839 } else {
38623840 break :result stack_memory;
38633841 }
38643842 }
38653843
38663844 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);
38683846 }
38693847
38703848 break :result func.reuseOperand(ty_op.operand, operand);
38713849 };
3872 func.finishAir(inst, result, &.{ty_op.operand});
3850 return func.finishAir(inst, result, &.{ty_op.operand});
38733851}
38743852
38753853fn 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
38883866 });
38893867 try func.emitWValue(operand);
38903868 try func.addTag(Mir.Inst.Tag.fromOpcode(opcode));
3891 return WValue{ .stack = {} };
3869 return .stack;
38923870}
38933871
38943872fn airStructFieldPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
......@@ -3901,7 +3879,7 @@ fn airStructFieldPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
39013879 const struct_ptr_ty = func.typeOf(extra.data.struct_operand);
39023880 const struct_ty = struct_ptr_ty.childType(mod);
39033881 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});
39053883}
39063884
39073885fn 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
39133891 const struct_ty = struct_ptr_ty.childType(mod);
39143892
39153893 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});
39173895}
39183896
39193897fn structFieldPtr(
......@@ -3950,7 +3928,7 @@ fn structFieldPtr(
39503928 }
39513929 switch (struct_ptr) {
39523930 .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 } };
39543932 },
39553933 else => return func.buildPointerOffset(struct_ptr, offset, .new),
39563934 }
......@@ -3969,7 +3947,7 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
39693947 const field_ty = struct_ty.structFieldType(field_index, mod);
39703948 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)) {
39733951 .@"packed" => switch (struct_ty.zigTypeTag(mod)) {
39743952 .Struct => result: {
39753953 const packed_struct = mod.typeToPackedStruct(struct_ty).?;
......@@ -3978,10 +3956,10 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
39783956 const wasm_bits = toWasmBits(backing_ty.intInfo(mod).bits) orelse {
39793957 return func.fail("TODO: airStructFieldVal for packed structs larger than 128 bits", .{});
39803958 };
3981 const const_wvalue = if (wasm_bits == 32)
3982 WValue{ .imm32 = offset }
3959 const const_wvalue: WValue = if (wasm_bits == 32)
3960 .{ .imm32 = offset }
39833961 else if (wasm_bits == 64)
3984 WValue{ .imm64 = offset }
3962 .{ .imm64 = offset }
39853963 else
39863964 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 {
39943972 if (field_ty.zigTypeTag(mod) == .Float) {
39953973 const int_type = try pt.intType(.unsigned, @as(u16, @intCast(field_ty.bitSize(pt))));
39963974 const truncated = try func.trunc(shifted_value, int_type, backing_ty);
3997 const bitcasted = try func.bitcast(field_ty, int_type, truncated);
3998 break :result try bitcasted.toLocal(func, field_ty);
3975 break :result try func.bitcast(field_ty, int_type, truncated);
39993976 } else if (field_ty.isPtrAtRuntime(mod) and packed_struct.field_types.len == 1) {
40003977 // In this case we do not have to perform any transformations,
40013978 // we can simply reuse the operand.
40023979 break :result func.reuseOperand(struct_field.struct_operand, operand);
40033980 } else if (field_ty.isPtrAtRuntime(mod)) {
40043981 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);
4006 break :result try truncated.toLocal(func, field_ty);
3982 break :result try func.trunc(shifted_value, int_type, backing_ty);
40073983 }
4008 const truncated = try func.trunc(shifted_value, field_ty, backing_ty);
4009 break :result try truncated.toLocal(func, field_ty);
3984 break :result try func.trunc(shifted_value, field_ty, backing_ty);
40103985 },
40113986 .Union => result: {
40123987 if (isByRef(struct_ty, pt)) {
40133988 if (!isByRef(field_ty, pt)) {
4014 const val = try func.load(operand, field_ty, 0);
4015 break :result try val.toLocal(func, field_ty);
3989 break :result try func.load(operand, field_ty, 0);
40163990 } else {
40173991 const new_stack_val = try func.allocStack(field_ty);
40183992 try func.store(new_stack_val, operand, field_ty, 0);
......@@ -4024,15 +3998,12 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
40243998 if (field_ty.zigTypeTag(mod) == .Float) {
40253999 const int_type = try pt.intType(.unsigned, @as(u16, @intCast(field_ty.bitSize(pt))));
40264000 const truncated = try func.trunc(operand, int_type, union_int_type);
4027 const bitcasted = try func.bitcast(field_ty, int_type, truncated);
4028 break :result try bitcasted.toLocal(func, field_ty);
4001 break :result try func.bitcast(field_ty, int_type, truncated);
40294002 } else if (field_ty.isPtrAtRuntime(mod)) {
40304003 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);
4032 break :result try truncated.toLocal(func, field_ty);
4004 break :result try func.trunc(operand, int_type, union_int_type);
40334005 }
4034 const truncated = try func.trunc(operand, field_ty, union_int_type);
4035 break :result try truncated.toLocal(func, field_ty);
4006 break :result try func.trunc(operand, field_ty, union_int_type);
40364007 },
40374008 else => unreachable,
40384009 },
......@@ -4043,17 +4014,16 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
40434014 if (isByRef(field_ty, pt)) {
40444015 switch (operand) {
40454016 .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 } };
40474018 },
40484019 else => break :result try func.buildPointerOffset(operand, offset, .new),
40494020 }
40504021 }
4051 const field = try func.load(operand, field_ty, offset);
4052 break :result try field.toLocal(func, field_ty);
4022 break :result try func.load(operand, field_ty, offset);
40534023 },
40544024 };
40554025
4056 func.finishAir(inst, result, &.{struct_field.struct_operand});
4026 return func.finishAir(inst, result, &.{struct_field.struct_operand});
40574027}
40584028
40594029fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
......@@ -4234,7 +4204,7 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
42344204 try func.genBody(else_body);
42354205 try func.endBlock();
42364206 }
4237 func.finishAir(inst, .none, &.{});
4207 return func.finishAir(inst, .none, &.{});
42384208}
42394209
42404210fn 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
42454215 const err_union_ty = func.typeOf(un_op);
42464216 const pl_ty = err_union_ty.errorUnionPayload(mod);
42474217
4248 const result = result: {
4218 const result: WValue = result: {
42494219 if (err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {
42504220 switch (opcode) {
4251 .i32_ne => break :result WValue{ .imm32 = 0 },
4252 .i32_eq => break :result WValue{ .imm32 = 1 },
4221 .i32_ne => break :result .{ .imm32 = 0 },
4222 .i32_eq => break :result .{ .imm32 = 1 },
42534223 else => unreachable,
42544224 }
42554225 }
......@@ -4265,12 +4235,9 @@ fn airIsErr(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerErro
42654235 // Compare the error value with '0'
42664236 try func.addImm32(0);
42674237 try func.addTag(Mir.Inst.Tag.fromOpcode(opcode));
4268
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;
4238 break :result .stack;
42724239 };
4273 func.finishAir(inst, result, &.{un_op});
4240 return func.finishAir(inst, result, &.{un_op});
42744241}
42754242
42764243fn 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
42834250 const err_ty = if (op_is_ptr) op_ty.childType(mod) else op_ty;
42844251 const payload_ty = err_ty.errorUnionPayload(mod);
42854252
4286 const result = result: {
4253 const result: WValue = result: {
42874254 if (!payload_ty.hasRuntimeBitsIgnoreComptime(pt)) {
42884255 if (op_is_ptr) {
42894256 break :result func.reuseOperand(ty_op.operand, operand);
42904257 }
4291 break :result WValue{ .none = {} };
4258 break :result .none;
42924259 }
42934260
42944261 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
42964263 break :result try func.buildPointerOffset(operand, pl_offset, .new);
42974264 }
42984265
4299 const payload = try func.load(operand, payload_ty, pl_offset);
4300 break :result try payload.toLocal(func, payload_ty);
4266 break :result try func.load(operand, payload_ty, pl_offset);
43014267 };
4302 func.finishAir(inst, result, &.{ty_op.operand});
4268 return func.finishAir(inst, result, &.{ty_op.operand});
43034269}
43044270
43054271fn 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)
43124278 const err_ty = if (op_is_ptr) op_ty.childType(mod) else op_ty;
43134279 const payload_ty = err_ty.errorUnionPayload(mod);
43144280
4315 const result = result: {
4281 const result: WValue = result: {
43164282 if (err_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {
4317 break :result WValue{ .imm32 = 0 };
4283 break :result .{ .imm32 = 0 };
43184284 }
43194285
43204286 if (op_is_ptr or !payload_ty.hasRuntimeBitsIgnoreComptime(pt)) {
43214287 break :result func.reuseOperand(ty_op.operand, operand);
43224288 }
43234289
4324 const error_val = try func.load(operand, Type.anyerror, @intCast(errUnionErrorOffset(payload_ty, pt)));
4325 break :result try error_val.toLocal(func, Type.anyerror);
4290 break :result try func.load(operand, Type.anyerror, @intCast(errUnionErrorOffset(payload_ty, pt)));
43264291 };
4327 func.finishAir(inst, result, &.{ty_op.operand});
4292 return func.finishAir(inst, result, &.{ty_op.operand});
43284293}
43294294
43304295fn airWrapErrUnionPayload(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
......@@ -4354,7 +4319,7 @@ fn airWrapErrUnionPayload(func: *CodeGen, inst: Air.Inst.Index) InnerError!void
43544319 });
43554320 break :result err_union;
43564321 };
4357 func.finishAir(inst, result, &.{ty_op.operand});
4322 return func.finishAir(inst, result, &.{ty_op.operand});
43584323}
43594324
43604325fn airWrapErrUnionErr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
......@@ -4382,7 +4347,7 @@ fn airWrapErrUnionErr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
43824347
43834348 break :result err_union;
43844349 };
4385 func.finishAir(inst, result, &.{ty_op.operand});
4350 return func.finishAir(inst, result, &.{ty_op.operand});
43864351}
43874352
43884353fn airIntcast(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
......@@ -4405,9 +4370,9 @@ fn airIntcast(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
44054370 const result = if (op_bits == wanted_bits)
44064371 func.reuseOperand(ty_op.operand, operand)
44074372 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, &.{});
44114376}
44124377
44134378/// 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:
44724437
44734438 const op_ty = func.typeOf(un_op);
44744439 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);
4476 const result = try is_null.toLocal(func, optional_ty);
4477 func.finishAir(inst, result, &.{un_op});
4440 const result = try func.isNull(operand, optional_ty, opcode);
4441 return func.finishAir(inst, result, &.{un_op});
44784442}
44794443
44804444/// 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
45054469 try func.addImm32(0);
45064470 try func.addTag(Mir.Inst.Tag.fromOpcode(opcode));
45074471
4508 return WValue{ .stack = {} };
4472 return .stack;
45094473}
45104474
45114475fn airOptionalPayload(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
......@@ -4526,10 +4490,9 @@ fn airOptionalPayload(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
45264490 break :result try func.buildPointerOffset(operand, 0, .new);
45274491 }
45284492
4529 const payload = try func.load(operand, payload_ty, 0);
4530 break :result try payload.toLocal(func, payload_ty);
4493 break :result try func.load(operand, payload_ty, 0);
45314494 };
4532 func.finishAir(inst, result, &.{ty_op.operand});
4495 return func.finishAir(inst, result, &.{ty_op.operand});
45334496}
45344497
45354498fn airOptionalPayloadPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
......@@ -4547,7 +4510,7 @@ fn airOptionalPayloadPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
45474510
45484511 break :result try func.buildPointerOffset(operand, 0, .new);
45494512 };
4550 func.finishAir(inst, result, &.{ty_op.operand});
4513 return func.finishAir(inst, result, &.{ty_op.operand});
45514514}
45524515
45534516fn airOptionalPayloadPtrSet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
......@@ -4612,7 +4575,7 @@ fn airWrapOptional(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
46124575 break :result result_ptr;
46134576 };
46144577
4615 func.finishAir(inst, result, &.{ty_op.operand});
4578 return func.finishAir(inst, result, &.{ty_op.operand});
46164579}
46174580
46184581fn airSlice(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
......@@ -4627,14 +4590,14 @@ fn airSlice(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
46274590 try func.store(slice, lhs, Type.usize, 0);
46284591 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 });
46314594}
46324595
46334596fn airSliceLen(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
46344597 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
46354598
46364599 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});
46384601}
46394602
46404603fn airSliceElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
......@@ -4657,15 +4620,12 @@ fn airSliceElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
46574620 try func.addTag(.i32_mul);
46584621 try func.addTag(.i32_add);
46594622
4660 const result_ptr = try func.allocLocal(Type.usize);
4661 try func.addLabel(.local_set, result_ptr.local.value);
4662
4663 const result = if (!isByRef(elem_ty, pt)) result: {
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;
4623 const elem_result = if (isByRef(elem_ty, pt))
4624 .stack
4625 else
4626 try func.load(.stack, elem_ty, 0);
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 });
46694629}
46704630
46714631fn airSliceElemPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
......@@ -4688,15 +4648,13 @@ fn airSliceElemPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
46884648 try func.addTag(.i32_mul);
46894649 try func.addTag(.i32_add);
46904650
4691 const result = try func.allocLocal(Type.i32);
4692 try func.addLabel(.local_set, result.local.value);
4693 func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });
4651 return func.finishAir(inst, .stack, &.{ bin_op.lhs, bin_op.rhs });
46944652}
46954653
46964654fn airSlicePtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
46974655 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
46984656 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});
47004658}
47014659
47024660fn slicePtr(func: *CodeGen, operand: WValue) InnerError!WValue {
......@@ -4717,7 +4675,7 @@ fn airTrunc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
47174675 const op_ty = func.typeOf(ty_op.operand);
47184676
47194677 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});
47214679}
47224680
47234681/// 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 {
47434701 const operand = try func.resolveInst(un_op);
47444702 const result = func.reuseOperand(un_op, operand);
47454703
4746 func.finishAir(inst, result, &.{un_op});
4704 return func.finishAir(inst, result, &.{un_op});
47474705}
47484706
47494707fn airArrayToSlice(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
......@@ -4764,10 +4722,10 @@ fn airArrayToSlice(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
47644722 }
47654723
47664724 // store the length of the array in the slice
4767 const len = WValue{ .imm32 = @as(u32, @intCast(array_ty.arrayLen(mod))) };
4768 try func.store(slice_local, len, Type.usize, func.ptrSize());
4725 const array_len: u32 = @intCast(array_ty.arrayLen(mod));
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});
47714729}
47724730
47734731fn airIntFromPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
......@@ -4783,7 +4741,7 @@ fn airIntFromPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
47834741 .stack_offset => try func.buildPointerOffset(operand, 0, .new),
47844742 else => func.reuseOperand(un_op, operand),
47854743 };
4786 func.finishAir(inst, result, &.{un_op});
4744 return func.finishAir(inst, result, &.{un_op});
47874745}
47884746
47894747fn airPtrElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
......@@ -4810,18 +4768,12 @@ fn airPtrElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
48104768 try func.addTag(.i32_mul);
48114769 try func.addTag(.i32_add);
48124770
4813 const elem_result = val: {
4814 var result = try func.allocLocal(Type.usize);
4815 try func.addLabel(.local_set, result.local.value);
4816 if (isByRef(elem_ty, pt)) {
4817 break :val result;
4818 }
4819 defer result.free(func); // only free if it's not returned like above
4771 const elem_result = if (isByRef(elem_ty, pt))
4772 .stack
4773 else
4774 try func.load(.stack, elem_ty, 0);
48204775
4821 const elem_val = try func.load(result, elem_ty, 0);
4822 break :val try elem_val.toLocal(func, elem_ty);
4823 };
4824 func.finishAir(inst, elem_result, &.{ bin_op.lhs, bin_op.rhs });
4776 return func.finishAir(inst, elem_result, &.{ bin_op.lhs, bin_op.rhs });
48254777}
48264778
48274779fn airPtrElemPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
......@@ -4850,9 +4802,7 @@ fn airPtrElemPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
48504802 try func.addTag(.i32_mul);
48514803 try func.addTag(.i32_add);
48524804
4853 const result = try func.allocLocal(Type.i32);
4854 try func.addLabel(.local_set, result.local.value);
4855 func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });
4805 return func.finishAir(inst, .stack, &.{ bin_op.lhs, bin_op.rhs });
48564806}
48574807
48584808fn 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 {
48794829 try func.addTag(Mir.Inst.Tag.fromOpcode(mul_opcode));
48804830 try func.addTag(Mir.Inst.Tag.fromOpcode(bin_opcode));
48814831
4882 const result = try func.allocLocal(Type.usize);
4883 try func.addLabel(.local_set, result.local.value);
4884 func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });
4832 return func.finishAir(inst, .stack, &.{ bin_op.lhs, bin_op.rhs });
48854833}
48864834
48874835fn 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
49114859 const dst_ptr = try func.sliceOrArrayPtr(ptr, ptr_ty);
49124860 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 });
49154863}
49164864
49174865/// 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
49324880 return;
49334881 }
49344882
4935 const final_len = switch (len) {
4936 .imm32 => |val| WValue{ .imm32 = val * abi_size },
4937 .imm64 => |val| WValue{ .imm64 = val * abi_size },
4883 const final_len: WValue = switch (len) {
4884 .imm32 => |val| .{ .imm32 = val * abi_size },
4885 .imm64 => |val| .{ .imm64 = val * abi_size },
49384886 else => if (abi_size != 1) blk: {
49394887 const new_len = try func.ensureAllocLocal(Type.usize);
49404888 try func.emitWValue(len);
......@@ -5045,7 +4993,7 @@ fn airArrayElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
50454993 try func.mir_extra.appendSlice(func.gpa, &operands);
50464994 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 });
50494997 },
50504998 else => {
50514999 const stack_vec = try func.allocStack(array_ty);
......@@ -5061,20 +5009,12 @@ fn airArrayElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
50615009 }
50625010 }
50635011
5064 const elem_result = val: {
5065 var result = try func.allocLocal(Type.usize);
5066 try func.addLabel(.local_set, result.local.value);
5067
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 };
5012 const elem_result = if (isByRef(elem_ty, pt))
5013 .stack
5014 else
5015 try func.load(.stack, elem_ty, 0);
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 });
50785018}
50795019
50805020fn airIntFromFloat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
......@@ -5106,7 +5046,7 @@ fn airIntFromFloat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
51065046 target_util.compilerRtIntAbbrev(dest_bitsize),
51075047 }) 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});
51105050 return func.finishAir(inst, result, &.{ty_op.operand});
51115051 }
51125052
......@@ -5118,9 +5058,8 @@ fn airIntFromFloat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
51185058 .signedness = dest_info.signedness,
51195059 });
51205060 try func.addTag(Mir.Inst.Tag.fromOpcode(op));
5121 const wrapped = try func.wrapOperand(.{ .stack = {} }, dest_ty);
5122 const result = try wrapped.toLocal(func, dest_ty);
5123 func.finishAir(inst, result, &.{ty_op.operand});
5061 const result = try func.wrapOperand(.stack, dest_ty);
5062 return func.finishAir(inst, result, &.{ty_op.operand});
51245063}
51255064
51265065fn airFloatFromInt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
......@@ -5152,7 +5091,7 @@ fn airFloatFromInt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
51525091 target_util.compilerRtFloatAbbrev(dest_bits),
51535092 }) 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});
51565095 return func.finishAir(inst, result, &.{ty_op.operand});
51575096 }
51585097
......@@ -5165,9 +5104,7 @@ fn airFloatFromInt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
51655104 });
51665105 try func.addTag(Mir.Inst.Tag.fromOpcode(op));
51675106
5168 const result = try func.allocLocal(dest_ty);
5169 try func.addLabel(.local_set, result.local.value);
5170 func.finishAir(inst, result, &.{ty_op.operand});
5107 return func.finishAir(inst, .stack, &.{ty_op.operand});
51715108}
51725109
51735110fn airSplat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
......@@ -5191,7 +5128,6 @@ fn airSplat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
51915128 64 => std.wasm.simdOpcode(.v128_load64_splat),
51925129 else => break :blk, // Cannot make use of simd-instructions
51935130 };
5194 const result = try func.allocLocal(ty);
51955131 try func.emitWValue(operand);
51965132 // TODO: Add helper functions for simd opcodes
51975133 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 {
52025138 @intCast(elem_ty.abiAlignment(pt).toByteUnits().?),
52035139 });
52045140 try func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } });
5205 try func.addLabel(.local_set, result.local.value);
5206 return func.finishAir(inst, result, &.{ty_op.operand});
5141 return func.finishAir(inst, .stack, &.{ty_op.operand});
52075142 },
52085143 .local => {
52095144 const opcode = switch (elem_ty.bitSize(pt)) {
......@@ -5213,13 +5148,11 @@ fn airSplat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
52135148 64 => if (elem_ty.isInt(mod)) std.wasm.simdOpcode(.i64x2_splat) else std.wasm.simdOpcode(.f64x2_splat),
52145149 else => break :blk, // Cannot make use of simd-instructions
52155150 };
5216 const result = try func.allocLocal(ty);
52175151 try func.emitWValue(operand);
52185152 const extra_index = @as(u32, @intCast(func.mir_extra.items.len));
52195153 try func.mir_extra.append(func.gpa, opcode);
52205154 try func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } });
5221 try func.addLabel(.local_set, result.local.value);
5222 return func.finishAir(inst, result, &.{ty_op.operand});
5155 return func.finishAir(inst, .stack, &.{ty_op.operand});
52235156 },
52245157 else => unreachable,
52255158 }
......@@ -5308,7 +5241,7 @@ fn airShuffle(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
53085241 try func.mir_extra.appendSlice(func.gpa, &operands);
53095242 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 });
53125245 }
53135246}
53145247
......@@ -5392,10 +5325,10 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
53925325 const field_ty = Type.fromInterned(field_types.get(ip)[elem_index]);
53935326 if (!field_ty.hasRuntimeBitsIgnoreComptime(pt)) continue;
53945327
5395 const shift_val = if (backing_type.bitSize(pt) <= 32)
5396 WValue{ .imm32 = current_bit }
5328 const shift_val: WValue = if (backing_type.bitSize(pt) <= 32)
5329 .{ .imm32 = current_bit }
53975330 else
5398 WValue{ .imm64 = current_bit };
5331 .{ .imm64 = current_bit };
53995332
54005333 const value = try func.resolveInst(elem);
54015334 const value_bit_size: u16 = @intCast(field_ty.bitSize(pt));
......@@ -5473,7 +5406,7 @@ fn airUnionInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
54735406 };
54745407 if (layout.payload_size == 0) {
54755408 if (layout.tag_size == 0) {
5476 break :result WValue{ .none = {} };
5409 break :result .none;
54775410 }
54785411 assert(!isByRef(union_ty, pt));
54795412 break :result tag_int;
......@@ -5511,15 +5444,12 @@ fn airUnionInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
55115444 if (field_ty.zigTypeTag(mod) == .Float) {
55125445 const int_type = try pt.intType(.unsigned, @intCast(field_ty.bitSize(pt)));
55135446 const bitcasted = try func.bitcast(field_ty, int_type, operand);
5514 const casted = try func.trunc(bitcasted, int_type, union_int_type);
5515 break :result try casted.toLocal(func, field_ty);
5447 break :result try func.trunc(bitcasted, int_type, union_int_type);
55165448 } else if (field_ty.isPtrAtRuntime(mod)) {
55175449 const int_type = try pt.intType(.unsigned, @intCast(field_ty.bitSize(pt)));
5518 const casted = try func.intcast(operand, int_type, union_int_type);
5519 break :result try casted.toLocal(func, field_ty);
5450 break :result try func.intcast(operand, int_type, union_int_type);
55205451 }
5521 const casted = try func.intcast(operand, field_ty, union_int_type);
5522 break :result try casted.toLocal(func, field_ty);
5452 break :result try func.intcast(operand, field_ty, union_int_type);
55235453 }
55245454 };
55255455
......@@ -5528,27 +5458,23 @@ fn airUnionInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
55285458
55295459fn airPrefetch(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
55305460 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});
55325462}
55335463
55345464fn airWasmMemorySize(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
55355465 const pl_op = func.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
55365466
5537 const result = try func.allocLocal(func.typeOfIndex(inst));
55385467 try func.addLabel(.memory_size, pl_op.payload);
5539 try func.addLabel(.local_set, result.local.value);
5540 func.finishAir(inst, result, &.{pl_op.operand});
5468 return func.finishAir(inst, .stack, &.{pl_op.operand});
55415469}
55425470
55435471fn airWasmMemoryGrow(func: *CodeGen, inst: Air.Inst.Index) !void {
55445472 const pl_op = func.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
55455473
55465474 const operand = try func.resolveInst(pl_op.operand);
5547 const result = try func.allocLocal(func.typeOfIndex(inst));
55485475 try func.emitWValue(operand);
55495476 try func.addLabel(.memory_grow, pl_op.payload);
5550 try func.addLabel(.local_set, result.local.value);
5551 func.finishAir(inst, result, &.{pl_op.operand});
5477 return func.finishAir(inst, .stack, &.{pl_op.operand});
55525478}
55535479
55545480fn 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:
55825508 try func.emitWValue(result);
55835509 try func.addImm32(0);
55845510 try func.addTag(if (op == .eq) .i32_ne else .i32_eq);
5585 return WValue{ .stack = {} };
5511 return .stack;
55865512}
55875513
55885514/// 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
56285554 },
56295555 }
56305556
5631 return WValue{ .stack = {} };
5557 return .stack;
56325558}
56335559
56345560fn airSetUnionTag(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
......@@ -5653,7 +5579,7 @@ fn airSetUnionTag(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
56535579 break :blk @intCast(layout.payload_size);
56545580 } else 0;
56555581 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 });
56575583}
56585584
56595585fn airGetUnionTag(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
......@@ -5668,12 +5594,12 @@ fn airGetUnionTag(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
56685594 const operand = try func.resolveInst(ty_op.operand);
56695595 // when the tag alignment is smaller than the payload, the field will be stored
56705596 // after the payload.
5671 const offset: u32 = if (layout.tag_align.compare(.lt, layout.payload_align)) blk: {
5672 break :blk @intCast(layout.payload_size);
5673 } else 0;
5674 const tag = try func.load(operand, tag_ty, offset);
5675 const result = try tag.toLocal(func, tag_ty);
5676 func.finishAir(inst, result, &.{ty_op.operand});
5597 const offset: u32 = if (layout.tag_align.compare(.lt, layout.payload_align))
5598 @intCast(layout.payload_size)
5599 else
5600 0;
5601 const result = try func.load(operand, tag_ty, offset);
5602 return func.finishAir(inst, result, &.{ty_op.operand});
56775603}
56785604
56795605fn airFpext(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
......@@ -5681,9 +5607,8 @@ fn airFpext(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
56815607
56825608 const dest_ty = func.typeOfIndex(inst);
56835609 const operand = try func.resolveInst(ty_op.operand);
5684 const extended = try func.fpext(operand, func.typeOf(ty_op.operand), dest_ty);
5685 const result = try extended.toLocal(func, dest_ty);
5686 func.finishAir(inst, result, &.{ty_op.operand});
5610 const result = try func.fpext(operand, func.typeOf(ty_op.operand), dest_ty);
5611 return func.finishAir(inst, result, &.{ty_op.operand});
56875612}
56885613
56895614/// 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!
56955620 if (wanted_bits == 64 and given_bits == 32) {
56965621 try func.emitWValue(operand);
56975622 try func.addTag(.f64_promote_f32);
5698 return WValue{ .stack = {} };
5623 return .stack;
56995624 } else if (given_bits == 16 and wanted_bits <= 64) {
57005625 // call __extendhfsf2(f16) f32
57015626 const f32_result = try func.callIntrinsic(
......@@ -5709,7 +5634,7 @@ fn fpext(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerError!
57095634 if (wanted_bits == 64) {
57105635 try func.addTag(.f64_promote_f32);
57115636 }
5712 return WValue{ .stack = {} };
5637 return .stack;
57135638 }
57145639
57155640 var fn_name_buf: [13]u8 = undefined;
......@@ -5726,9 +5651,8 @@ fn airFptrunc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
57265651
57275652 const dest_ty = func.typeOfIndex(inst);
57285653 const operand = try func.resolveInst(ty_op.operand);
5729 const truncated = try func.fptrunc(operand, func.typeOf(ty_op.operand), dest_ty);
5730 const result = try truncated.toLocal(func, dest_ty);
5731 func.finishAir(inst, result, &.{ty_op.operand});
5654 const result = try func.fptrunc(operand, func.typeOf(ty_op.operand), dest_ty);
5655 return func.finishAir(inst, result, &.{ty_op.operand});
57325656}
57335657
57345658/// 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
57405664 if (wanted_bits == 32 and given_bits == 64) {
57415665 try func.emitWValue(operand);
57425666 try func.addTag(.f32_demote_f64);
5743 return WValue{ .stack = {} };
5667 return .stack;
57445668 } else if (wanted_bits == 16 and given_bits <= 64) {
57455669 const op: WValue = if (given_bits == 64) blk: {
57465670 try func.emitWValue(operand);
57475671 try func.addTag(.f32_demote_f64);
5748 break :blk WValue{ .stack = {} };
5672 break :blk .stack;
57495673 } else operand;
57505674
57515675 // call __truncsfhf2(f32) f16
......@@ -5785,7 +5709,7 @@ fn airErrUnionPayloadPtrSet(func: *CodeGen, inst: Air.Inst.Index) InnerError!voi
57855709
57865710 break :result try func.buildPointerOffset(operand, @as(u32, @intCast(errUnionPayloadOffset(payload_ty, pt))), .new);
57875711 };
5788 func.finishAir(inst, result, &.{ty_op.operand});
5712 return func.finishAir(inst, result, &.{ty_op.operand});
57895713}
57905714
57915715fn airFieldParentPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
......@@ -5807,7 +5731,7 @@ fn airFieldParentPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
58075731 break :result base;
58085732 } 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});
58115735}
58125736
58135737fn sliceOrArrayPtr(func: *CodeGen, ptr: WValue, ptr_ty: Type) InnerError!WValue {
......@@ -5849,12 +5773,12 @@ fn airMemcpy(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
58495773 const src_ptr = try func.sliceOrArrayPtr(src, src_ty);
58505774 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 });
58535777}
58545778
58555779fn airRetAddr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
58565780 // TODO: Implement this properly once stack serialization is solved
5857 func.finishAir(inst, switch (func.arch()) {
5781 return func.finishAir(inst, switch (func.arch()) {
58585782 .wasm32 => .{ .imm32 = 0 },
58595783 .wasm64 => .{ .imm64 = 0 },
58605784 else => unreachable,
......@@ -5868,7 +5792,6 @@ fn airPopcount(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
58685792
58695793 const operand = try func.resolveInst(ty_op.operand);
58705794 const op_ty = func.typeOf(ty_op.operand);
5871 const result_ty = func.typeOfIndex(inst);
58725795
58735796 if (op_ty.zigTypeTag(mod) == .Vector) {
58745797 return func.fail("TODO: Implement @popCount for vectors", .{});
......@@ -5911,9 +5834,7 @@ fn airPopcount(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
59115834 else => unreachable,
59125835 }
59135836
5914 const result = try func.allocLocal(result_ty);
5915 try func.addLabel(.local_set, result.local.value);
5916 func.finishAir(inst, result, &.{ty_op.operand});
5837 return func.finishAir(inst, .stack, &.{ty_op.operand});
59175838}
59185839
59195840fn airBitReverse(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
......@@ -5942,12 +5863,11 @@ fn airBitReverse(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
59425863 Type.u32,
59435864 &.{operand},
59445865 );
5945 const reversed = if (bits == 32)
5866 const result = if (bits == 32)
59465867 intrin_ret
59475868 else
59485869 try func.binOp(intrin_ret, .{ .imm32 = 32 - bits }, ty, .shr);
5949 const result = try reversed.toLocal(func, ty);
5950 func.finishAir(inst, result, &.{ty_op.operand});
5870 return func.finishAir(inst, result, &.{ty_op.operand});
59515871 },
59525872 64 => {
59535873 const intrin_ret = try func.callIntrinsic(
......@@ -5956,12 +5876,11 @@ fn airBitReverse(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
59565876 Type.u64,
59575877 &.{operand},
59585878 );
5959 const reversed = if (bits == 64)
5879 const result = if (bits == 64)
59605880 intrin_ret
59615881 else
59625882 try func.binOp(intrin_ret, .{ .imm64 = 64 - bits }, ty, .shr);
5963 const result = try reversed.toLocal(func, ty);
5964 func.finishAir(inst, result, &.{ty_op.operand});
5883 return func.finishAir(inst, result, &.{ty_op.operand});
59655884 },
59665885 128 => {
59675886 const result = try func.allocStack(ty);
......@@ -6008,7 +5927,7 @@ fn airBitReverse(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
60085927 try func.addTag(.i64_or);
60095928 try func.store(.stack, .stack, Type.u64, result.offset());
60105929 }
6011 func.finishAir(inst, result, &.{ty_op.operand});
5930 return func.finishAir(inst, result, &.{ty_op.operand});
60125931 },
60135932 else => unreachable,
60145933 }
......@@ -6051,16 +5970,14 @@ fn airErrorName(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
60515970 else => unreachable,
60525971 }
60535972
6054 const result_ptr = try func.allocLocal(Type.usize);
6055 try func.addLabel(.local_set, result_ptr.local.value);
6056 func.finishAir(inst, result_ptr, &.{un_op});
5973 return func.finishAir(inst, .stack, &.{un_op});
60575974}
60585975
60595976fn airPtrSliceFieldPtr(func: *CodeGen, inst: Air.Inst.Index, offset: u32) InnerError!void {
60605977 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
60615978 const slice_ptr = try func.resolveInst(ty_op.operand);
60625979 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});
60645981}
60655982
60665983fn 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
60896006 return func.finishAir(inst, result, &.{ extra.lhs, extra.rhs });
60906007 }
60916008
6092 const zero = switch (wasm_bits) {
6093 32 => WValue{ .imm32 = 0 },
6094 64 => WValue{ .imm64 = 0 },
6009 const zero: WValue = switch (wasm_bits) {
6010 32 => .{ .imm32 = 0 },
6011 64 => .{ .imm64 = 0 },
60956012 else => unreachable,
60966013 };
60976014
......@@ -6121,7 +6038,7 @@ fn airAddSubWithOverflow(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerErro
61216038 const offset = @as(u32, @intCast(lhs_ty.abiSize(pt)));
61226039 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 });
61256042}
61266043
61276044fn 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,
61776094 _ = try func.cmp(tmp_op, lhs_low_bit, Type.u64, .eq);
61786095 try func.addTag(.select);
61796096
6180 break :blk WValue{ .stack = {} };
6097 break :blk .stack;
61816098 };
61826099 var overflow_local = try overflow_bit.toLocal(func, Type.u1);
61836100 defer overflow_local.free(func);
......@@ -6228,7 +6145,7 @@ fn airShlWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
62286145 const overflow_bit = blk: {
62296146 try func.emitWValue(lhs);
62306147 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);
62326149 };
62336150 var overflow_local = try overflow_bit.toLocal(func, Type.u1);
62346151 defer overflow_local.free(func);
......@@ -6238,7 +6155,7 @@ fn airShlWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
62386155 const offset = @as(u32, @intCast(lhs_ty.abiSize(pt)));
62396156 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 });
62426159}
62436160
62446161fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
......@@ -6265,9 +6182,9 @@ fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
62656182 return func.fail("TODO: Implement `@mulWithOverflow` for integer bitsize: {d}", .{int_info.bits});
62666183 };
62676184
6268 const zero = switch (wasm_bits) {
6269 32 => WValue{ .imm32 = 0 },
6270 64, 128 => WValue{ .imm64 = 0 },
6185 const zero: WValue = switch (wasm_bits) {
6186 32 => .{ .imm32 = 0 },
6187 64, 128 => .{ .imm64 = 0 },
62716188 else => unreachable,
62726189 };
62736190
......@@ -6303,10 +6220,10 @@ fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
63036220 } else if (wasm_bits == 32) blk: {
63046221 var bin_op = try (try func.binOp(lhs, rhs, lhs_ty, .mul)).toLocal(func, lhs_ty);
63056222 defer bin_op.free(func);
6306 const shift_imm = if (wasm_bits == 32)
6307 WValue{ .imm32 = int_info.bits }
6223 const shift_imm: WValue = if (wasm_bits == 32)
6224 .{ .imm32 = int_info.bits }
63086225 else
6309 WValue{ .imm64 = int_info.bits };
6226 .{ .imm64 = int_info.bits };
63106227 const shr = try func.binOp(bin_op, shift_imm, lhs_ty, .shr);
63116228 _ = try func.cmp(shr, zero, lhs_ty, .neq);
63126229 try func.addLabel(.local_set, overflow_bit.local.value);
......@@ -6412,7 +6329,7 @@ fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
64126329 const offset = @as(u32, @intCast(lhs_ty.abiSize(pt)));
64136330 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 });
64166333}
64176334
64186335fn 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 {
64546371 try func.addTag(.select);
64556372 }
64566373
6457 // store result in local
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 });
6374 return func.finishAir(inst, .stack, &.{ bin_op.lhs, bin_op.rhs });
64626375}
64636376
64646377fn airMulAdd(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
......@@ -6487,13 +6400,13 @@ fn airMulAdd(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
64876400 Type.f32,
64886401 &.{ rhs_ext, lhs_ext, addend_ext },
64896402 );
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);
64916404 } else result: {
64926405 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);
64946407 };
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 });
64976410}
64986411
64996412fn airClz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
......@@ -6502,7 +6415,6 @@ fn airClz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
65026415 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
65036416
65046417 const ty = func.typeOf(ty_op.operand);
6505 const result_ty = func.typeOfIndex(inst);
65066418 if (ty.zigTypeTag(mod) == .Vector) {
65076419 return func.fail("TODO: `@clz` for vectors", .{});
65086420 }
......@@ -6545,9 +6457,7 @@ fn airClz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
65456457 try func.addTag(.i32_sub);
65466458 }
65476459
6548 const result = try func.allocLocal(result_ty);
6549 try func.addLabel(.local_set, result.local.value);
6550 func.finishAir(inst, result, &.{ty_op.operand});
6460 return func.finishAir(inst, .stack, &.{ty_op.operand});
65516461}
65526462
65536463fn airCtz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
......@@ -6556,7 +6466,6 @@ fn airCtz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
65566466 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
65576467
65586468 const ty = func.typeOf(ty_op.operand);
6559 const result_ty = func.typeOfIndex(inst);
65606469
65616470 if (ty.zigTypeTag(mod) == .Vector) {
65626471 return func.fail("TODO: `@ctz` for vectors", .{});
......@@ -6611,9 +6520,7 @@ fn airCtz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
66116520 else => unreachable,
66126521 }
66136522
6614 const result = try func.allocLocal(result_ty);
6615 try func.addLabel(.local_set, result.local.value);
6616 func.finishAir(inst, result, &.{ty_op.operand});
6523 return func.finishAir(inst, .stack, &.{ty_op.operand});
66176524}
66186525
66196526fn airDbgStmt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
......@@ -6626,7 +6533,7 @@ fn airDbgStmt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
66266533 .column = dbg_stmt.column,
66276534 }),
66286535 } });
6629 func.finishAir(inst, .none, &.{});
6536 return func.finishAir(inst, .none, &.{});
66306537}
66316538
66326539fn 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
66596566 };
66606567 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, &.{});
66636570}
66646571
66656572fn airTry(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
......@@ -6669,7 +6576,7 @@ fn airTry(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
66696576 const body: []const Air.Inst.Index = @ptrCast(func.air.extra[extra.end..][0..extra.data.body_len]);
66706577 const err_union_ty = func.typeOf(pl_op.operand);
66716578 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});
66736580}
66746581
66756582fn airTryPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
......@@ -6681,7 +6588,7 @@ fn airTryPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
66816588 const body: []const Air.Inst.Index = @ptrCast(func.air.extra[extra.end..][0..extra.data.body_len]);
66826589 const err_union_ty = func.typeOf(extra.data.ptr).childType(mod);
66836590 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});
66856592}
66866593
66876594fn lowerTry(
......@@ -6730,7 +6637,7 @@ fn lowerTry(
67306637
67316638 // if we reach here it means error was not set, and we want the payload
67326639 if (!pl_has_bits) {
6733 return WValue{ .none = {} };
6640 return .none;
67346641 }
67356642
67366643 const pl_offset: u32 = @intCast(errUnionPayloadOffset(pl_ty, pt));
......@@ -6771,12 +6678,10 @@ fn airByteSwap(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
67716678 Type.u32,
67726679 &.{operand},
67736680 );
6774 const swapped = if (int_info.bits == 32)
6681 break :result if (int_info.bits == 32)
67756682 intrin_ret
67766683 else
67776684 try func.binOp(intrin_ret, .{ .imm32 = 32 - int_info.bits }, ty, .shr);
6778
6779 break :result try swapped.toLocal(func, ty);
67806685 },
67816686 64 => {
67826687 const intrin_ret = try func.callIntrinsic(
......@@ -6785,17 +6690,15 @@ fn airByteSwap(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
67856690 Type.u64,
67866691 &.{operand},
67876692 );
6788 const swapped = if (int_info.bits == 64)
6693 break :result if (int_info.bits == 64)
67896694 intrin_ret
67906695 else
67916696 try func.binOp(intrin_ret, .{ .imm64 = 64 - int_info.bits }, ty, .shr);
6792
6793 break :result try swapped.toLocal(func, ty);
67946697 },
67956698 else => return func.fail("TODO: @byteSwap for integers with bitsize {d}", .{int_info.bits}),
67966699 }
67976700 };
6798 func.finishAir(inst, result, &.{ty_op.operand});
6701 return func.finishAir(inst, result, &.{ty_op.operand});
67996702}
68006703
68016704fn airDiv(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
......@@ -6805,8 +6708,8 @@ fn airDiv(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
68056708 const lhs = try func.resolveInst(bin_op.lhs);
68066709 const rhs = try func.resolveInst(bin_op.rhs);
68076710
6808 const result = try (try func.binOp(lhs, rhs, ty, .div)).toLocal(func, ty);
6809 func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });
6711 const result = try func.binOp(lhs, rhs, ty, .div);
6712 return func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });
68106713}
68116714
68126715fn airDivTrunc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
......@@ -6816,10 +6719,10 @@ fn airDivTrunc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
68166719 const lhs = try func.resolveInst(bin_op.lhs);
68176720 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
68216724 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});
68236726 return func.finishAir(inst, trunc_result, &.{ bin_op.lhs, bin_op.rhs });
68246727 }
68256728
......@@ -6847,9 +6750,9 @@ fn airDivFloor(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
68476750 return func.fail("TODO: `@divFloor` for signed integers larger than 64 bits ({d} bits requested)", .{int_bits});
68486751 }
68496752
6850 const zero = switch (wasm_bits) {
6851 32 => WValue{ .imm32 = 0 },
6852 64 => WValue{ .imm64 = 0 },
6753 const zero: WValue = switch (wasm_bits) {
6754 32 => .{ .imm32 = 0 },
6755 64 => .{ .imm64 = 0 },
68536756 else => unreachable,
68546757 };
68556758
......@@ -6895,7 +6798,7 @@ fn airDivFloor(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
68956798 // TODO: Should we be zeroing the high bits here or should we be ignoring the high bits
68966799 // when performing comparisons?
68976800 if (int_bits != wasm_bits) {
6898 _ = try func.wrapOperand(.{ .stack = {} }, ty);
6801 _ = try func.wrapOperand(.stack, ty);
68996802 }
69006803 } else {
69016804 const float_bits = ty.floatBits(func.target);
......@@ -6923,13 +6826,11 @@ fn airDivFloor(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
69236826 }
69246827
69256828 if (is_f16) {
6926 _ = try func.fptrunc(.{ .stack = {} }, Type.f32, Type.f16);
6829 _ = try func.fptrunc(.stack, Type.f32, Type.f16);
69276830 }
69286831 }
69296832
6930 const result = try func.allocLocal(ty);
6931 try func.addLabel(.local_set, result.local.value);
6932 func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });
6833 return func.finishAir(inst, .stack, &.{ bin_op.lhs, bin_op.rhs });
69336834}
69346835
69356836fn airRem(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
......@@ -6941,8 +6842,7 @@ fn airRem(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
69416842
69426843 const result = try func.binOp(lhs, rhs, ty, .rem);
69436844
6944 const return_local = try result.toLocal(func, ty);
6945 func.finishAir(inst, return_local, &.{ bin_op.lhs, bin_op.rhs });
6845 return func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });
69466846}
69476847
69486848/// Remainder after floor division, defined by:
......@@ -6979,9 +6879,7 @@ fn airMod(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
69796879 return func.fail("TODO: implement `@mod` on floating point types for {}", .{func.target.cpu.arch});
69806880 }
69816881
6982 const result = try func.allocLocal(ty);
6983 try func.addLabel(.local_set, result.local.value);
6984 func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });
6882 return func.finishAir(inst, .stack, &.{ bin_op.lhs, bin_op.rhs });
69856883}
69866884
69876885fn 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 {
70116909 defer bin_result.free(func);
70126910 if (wasm_bits != int_info.bits and op == .add) {
70136911 const val: u64 = @as(u64, @intCast((@as(u65, 1) << @as(u7, @intCast(int_info.bits))) - 1));
7014 const imm_val = switch (wasm_bits) {
7015 32 => WValue{ .imm32 = @intCast(val) },
7016 64 => WValue{ .imm64 = val },
6912 const imm_val: WValue = switch (wasm_bits) {
6913 32 => .{ .imm32 = @intCast(val) },
6914 64 => .{ .imm64 = val },
70176915 else => unreachable,
70186916 };
70196917
......@@ -7031,9 +6929,7 @@ fn airSatBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {
70316929 }
70326930
70336931 try func.addTag(.select);
7034 const result = try func.allocLocal(ty);
7035 try func.addLabel(.local_set, result.local.value);
7036 return func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });
6932 return func.finishAir(inst, .stack, &.{ bin_op.lhs, bin_op.rhs });
70376933}
70386934
70396935fn 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
70466942
70476943 const max_val: u64 = @as(u64, @intCast((@as(u65, 1) << @as(u7, @intCast(int_info.bits - 1))) - 1));
70486944 const min_val: i64 = (-@as(i64, @intCast(@as(u63, @intCast(max_val))))) - 1;
7049 const max_wvalue = switch (wasm_bits) {
7050 32 => WValue{ .imm32 = @as(u32, @truncate(max_val)) },
7051 64 => WValue{ .imm64 = max_val },
6945 const max_wvalue: WValue = switch (wasm_bits) {
6946 32 => .{ .imm32 = @truncate(max_val) },
6947 64 => .{ .imm64 = max_val },
70526948 else => unreachable,
70536949 };
7054 const min_wvalue = switch (wasm_bits) {
7055 32 => WValue{ .imm32 = @as(u32, @bitCast(@as(i32, @truncate(min_val)))) },
7056 64 => WValue{ .imm64 = @as(u64, @bitCast(min_val)) },
6950 const min_wvalue: WValue = switch (wasm_bits) {
6951 32 => .{ .imm32 = @bitCast(@as(i32, @truncate(min_val))) },
6952 64 => .{ .imm64 = @bitCast(min_val) },
70576953 else => unreachable,
70586954 };
70596955
......@@ -7073,9 +6969,9 @@ fn signedSat(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerEr
70736969 try func.addLabel(.local_set, bin_result.local.value); // re-use local
70746970 return (try func.wrapOperand(bin_result, ty)).toLocal(func, ty);
70756971 } else {
7076 const zero = switch (wasm_bits) {
7077 32 => WValue{ .imm32 = 0 },
7078 64 => WValue{ .imm64 = 0 },
6972 const zero: WValue = switch (wasm_bits) {
6973 32 => .{ .imm32 = 0 },
6974 64 => .{ .imm64 = 0 },
70796975 else => unreachable,
70806976 };
70816977 try func.emitWValue(max_wvalue);
......@@ -7110,7 +7006,7 @@ fn airShlSat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
71107006 const wasm_bits = toWasmBits(int_info.bits).?;
71117007 const result = try func.allocLocal(ty);
71127008
7113 if (wasm_bits == int_info.bits) outer_blk: {
7009 if (wasm_bits == int_info.bits) {
71147010 var shl = try (try func.binOp(lhs, rhs, ty, .shl)).toLocal(func, ty);
71157011 defer shl.free(func);
71167012 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 {
71437039 _ = try func.cmp(lhs, shr, ty, .neq);
71447040 try func.addTag(.select);
71457041 try func.addLabel(.local_set, result.local.value);
7146 break :outer_blk;
71477042 } else {
71487043 const shift_size = wasm_bits - int_info.bits;
7149 const shift_value = switch (wasm_bits) {
7150 32 => WValue{ .imm32 = shift_size },
7151 64 => WValue{ .imm64 = shift_size },
7044 const shift_value: WValue = switch (wasm_bits) {
7045 32 => .{ .imm32 = shift_size },
7046 64 => .{ .imm64 = shift_size },
71527047 else => unreachable,
71537048 };
71547049 const ext_ty = try pt.intType(int_info.signedness, wasm_bits);
......@@ -7232,7 +7127,7 @@ fn callIntrinsic(
72327127 const sret_local = try func.allocStack(return_type);
72337128 try func.lowerToStack(sret_local);
72347129 break :blk sret_local;
7235 } else WValue{ .none = {} };
7130 } else .none;
72367131
72377132 // Lower all arguments to the stack before we call our function
72387133 for (args, 0..) |arg, arg_i| {
......@@ -7245,14 +7140,14 @@ fn callIntrinsic(
72457140 try func.addLabel(.call, @intFromEnum(symbol_index));
72467141
72477142 if (!return_type.hasRuntimeBitsIgnoreComptime(pt)) {
7248 return WValue.none;
7143 return .none;
72497144 } else if (return_type.isNoReturn(mod)) {
72507145 try func.addTag(.@"unreachable");
7251 return WValue.none;
7146 return .none;
72527147 } else if (want_sret_param) {
72537148 return sret;
72547149 } else {
7255 return WValue{ .stack = {} };
7150 return .stack;
72567151 }
72577152}
72587153
......@@ -7571,7 +7466,7 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
75717466 break :val ptr_val;
75727467 };
75737468
7574 const result_ptr = if (isByRef(result_ty, pt)) val: {
7469 const result = if (isByRef(result_ty, pt)) val: {
75757470 try func.emitWValue(cmp_result);
75767471 try func.addImm32(~@as(u32, 0));
75777472 try func.addTag(.i32_xor);
......@@ -7587,10 +7482,10 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
75877482 try func.emitWValue(ptr_val);
75887483 try func.emitWValue(cmp_result);
75897484 try func.addTag(.select);
7590 break :val try WValue.toLocal(.stack, func, result_ty);
7485 break :val .stack;
75917486 };
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 });
75947489}
75957490
75967491fn airAtomicLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
......@@ -7616,8 +7511,7 @@ fn airAtomicLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
76167511 _ = try func.load(ptr, ty, 0);
76177512 }
76187513
7619 const result = try WValue.toLocal(.stack, func, ty);
7620 return func.finishAir(inst, result, &.{atomic_load.ptr});
7514 return func.finishAir(inst, .stack, &.{atomic_load.ptr});
76217515}
76227516
76237517fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
......@@ -7734,8 +7628,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
77347628 .offset = ptr.offset(),
77357629 .alignment = @intCast(ty.abiAlignment(pt).toByteUnits().?),
77367630 });
7737 const result = try WValue.toLocal(.stack, func, ty);
7738 return func.finishAir(inst, result, &.{ pl_op.operand, extra.operand });
7631 return func.finishAir(inst, .stack, &.{ pl_op.operand, extra.operand });
77397632 },
77407633 }
77417634 } else {
......@@ -7847,8 +7740,7 @@ fn airFrameAddress(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
78477740 try func.initializeStack();
78487741 }
78497742 try func.emitWValue(func.bottom_stack_value);
7850 const result = try WValue.toLocal(.stack, func, Type.usize);
7851 return func.finishAir(inst, result, &.{});
7743 return func.finishAir(inst, .stack, &.{});
78527744}
78537745
78547746fn typeOf(func: *CodeGen, inst: Air.Inst.Ref) Type {