authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-07-17 22:33:29-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-07-17 22:33:29-07:00
loga57479afc2cea1b7c2c6802b7e8a1a7db973a3a3
tree80c37854ba226b83a1ffd964d101178039fe2946
parent8ab70f80cb8943dde41a5e4a8ca73631d44643a2
parent31706dc31acdc875899ca18cf92a2fccb3a2f0c7
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #20652 from pavelverigo/stage2-wasm-finishAir

stage2-wasm: finishAir enhancement

1 files changed, 346 insertions(+), 454 deletions(-)

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