authorgravatar for paul.verigo@gmail.comPavel Verigo <paul.verigo@gmail.com> 2026-08-21 12:43:10+02:00
committergravatar for paul.verigo@gmail.comPavel Verigo <paul.verigo@gmail.com> 2026-09-17 00:04:51+02:00
logd12892e8904bbb27aac7baa69f483348e516a30e
treed129832a30921a505603594390425a2c45fdcdb1
parent5ec1668eb4cee3ce3069f6ff7b2e3af0d52f43a6

wasm: store/load use memarg, support alignment


4 files changed, 288 insertions(+), 246 deletions(-)

src/codegen/wasm/CodeGen.zig+274-237
......@@ -584,7 +584,7 @@ fn addCallIntrinsic(cg: *CodeGen, intrinsic: Mir.Intrinsic) error{OutOfMemory}!v
584584/// Returns the index into `mir_extra`
585585fn addExtra(cg: *CodeGen, extra: anytype) error{OutOfMemory}!u32 {
586586 const field_count = @typeInfo(@TypeOf(extra)).@"struct".field_names.len;
587 try cg.mir_extra.ensureUnusedCapacity(cg.gpa, field_count);
587 try cg.mir_extra.ensureUnusedCapacity(cg.gpa, field_count * 2);
588588 return cg.addExtraAssumeCapacity(extra);
589589}
590590
......@@ -594,14 +594,22 @@ fn addExtraAssumeCapacity(cg: *CodeGen, extra: anytype) error{OutOfMemory}!u32 {
594594 const info = @typeInfo(@TypeOf(extra)).@"struct";
595595 const result: u32 = @intCast(cg.mir_extra.items.len);
596596 inline for (info.field_names, info.field_types) |field_name, field_type| {
597 cg.mir_extra.appendAssumeCapacity(switch (field_type) {
598 u32 => @field(extra, field_name),
599 i32 => @bitCast(@field(extra, field_name)),
600 InternPool.Index,
601 InternPool.Nav.Index,
602 => @backingInt(@field(extra, field_name)),
603 else => @compileError("Unsupported field type " ++ @typeName(field_type)),
604 });
597 switch (field_type) {
598 u64 => {
599 const value = @field(extra, field_name);
600 cg.mir_extra.appendAssumeCapacity(@truncate(value));
601 cg.mir_extra.appendAssumeCapacity(@truncate(value >> 32));
602 },
603 else => cg.mir_extra.appendAssumeCapacity(switch (field_type) {
604 u32 => @field(extra, field_name),
605 i32 => @bitCast(@field(extra, field_name)),
606 InternPool.Index,
607 InternPool.Nav.Index,
608 mem.Alignment,
609 => @backingInt(@field(extra, field_name)),
610 else => @compileError("Unsupported field type " ++ @typeName(field_type)),
611 }),
612 }
605613 }
606614 return result;
607615}
......@@ -991,26 +999,26 @@ fn lowerArg(cg: *CodeGen, cc: std.lang.CallingConvention, ty: Type, value: WValu
991999 if (!isByRef(ty, zcu, cg.target)) {
9921000 return cg.lowerToStack(value);
9931001 } else {
994 _ = try cg.load(value, scalar_ty, 0);
1002 _ = try cg.load(value, scalar_ty, .{});
9951003 }
9961004 },
9971005 .double_i64 => {
9981006 assert(ty.abiSize(zcu) == 16);
9991007 // in this case we have an integer or float that must be lowered as 2 i64's.
10001008 try cg.emitWValue(value);
1001 try cg.addMemArg(.i64_load, .{ .offset = value.offset(), .alignment = 8 });
1009 try cg.addMemArg(.i64_load, .{ .offset = value.offset(), .alignment = .@"8" });
10021010 try cg.emitWValue(value);
1003 try cg.addMemArg(.i64_load, .{ .offset = value.offset() + 8, .alignment = 8 });
1011 try cg.addMemArg(.i64_load, .{ .offset = value.offset() + 8, .alignment = .@"8" });
10041012 },
10051013 .indirect => {
10061014 const stack_copy = try cg.allocStack(ty);
1007 try cg.store(stack_copy, value, ty, 0);
1015 try cg.store(stack_copy, value, ty, .{});
10081016 return cg.lowerToStack(stack_copy);
10091017 },
10101018 .unrolled => |vector| {
1011 const elem_size: u32 = @intCast(vector.elem_type.abiSize(zcu));
1019 const elem_size = vector.elem_type.abiSize(zcu);
10121020 for (0..vector.len) |index| {
1013 _ = try cg.load(value, vector.elem_type, @intCast(index * elem_size));
1021 _ = try cg.load(value, vector.elem_type, .{ .offset = index * elem_size });
10141022 }
10151023 },
10161024 }
......@@ -1330,7 +1338,7 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
13301338 try cg.addTag(.i32_add);
13311339 const ptr = try WValue.toLocal(.stack, cg, Type.usize);
13321340
1333 try cg.store(ptr, elem_val, elem_ty, 0);
1341 try cg.store(ptr, elem_val, elem_ty, .{});
13341342
13351343 return cg.finishAir(inst, .none, &.{ pl_op.operand, bin_op.lhs, bin_op.rhs });
13361344 },
......@@ -1507,8 +1515,8 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
15071515 const result = try cg.allocStack(cg.typeOfIndex(inst));
15081516 const offset: u32 = @intCast(ty.abiSize(cg.pt.zcu));
15091517
1510 try cg.store(result, res_tmp, ty, 0);
1511 try cg.store(result, ov_tmp, Type.u1, offset);
1518 try cg.store(result, res_tmp, ty, .{});
1519 try cg.store(result, ov_tmp, .u1, .{ .offset = offset });
15121520
15131521 try cg.finishAir(inst, result, &.{ extra.lhs, extra.rhs });
15141522 },
......@@ -1939,20 +1947,20 @@ fn airRet(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
19391947 // result must be stored in the stack and we return a pointer
19401948 // to the stack instead
19411949 if (cg.return_value != .none) {
1942 try cg.store(cg.return_value, operand, ret_ty, 0);
1950 try cg.store(cg.return_value, operand, ret_ty, .{});
19431951 } else if (fn_info.cc == .wasm_mvp and ret_ty.hasRuntimeBits(zcu)) {
19441952 switch (abi.classifyType(ret_ty, zcu, cg.target)) {
19451953 .direct => |scalar_type| {
19461954 if (!isByRef(ret_ty, zcu, cg.target)) {
19471955 try cg.emitWValue(operand);
19481956 } else {
1949 _ = try cg.load(operand, scalar_type, 0);
1957 _ = try cg.load(operand, scalar_type, .{});
19501958 }
19511959 },
19521960 .double_i64, .indirect => unreachable,
19531961 .unrolled => |vector| {
19541962 assert(vector.len == 1);
1955 _ = try cg.load(operand, vector.elem_type, 0);
1963 _ = try cg.load(operand, vector.elem_type, .{});
19561964 },
19571965 }
19581966 } else {
......@@ -2002,15 +2010,15 @@ fn airRetLoad(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
20022010 } else if (!firstParamSRet(fn_info.cc, Type.fromInterned(fn_info.return_type), zcu, cg.target)) {
20032011 if (fn_info.cc == .wasm_mvp) {
20042012 switch (abi.classifyType(ret_ty, zcu, cg.target)) {
2005 .direct => |scalar_type| _ = try cg.load(operand, scalar_type, 0),
2013 .direct => |scalar_type| _ = try cg.load(operand, scalar_type, .{}),
20062014 .double_i64, .indirect => unreachable,
20072015 .unrolled => |vector| {
20082016 assert(vector.len == 1);
2009 _ = try cg.load(operand, vector.elem_type, 0);
2017 _ = try cg.load(operand, vector.elem_type, .{});
20102018 },
20112019 }
20122020 } else {
2013 _ = try cg.load(operand, ret_ty, 0);
2021 _ = try cg.load(operand, ret_ty, .{});
20142022 }
20152023 }
20162024
......@@ -2092,7 +2100,7 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier)
20922100 const arg_align = arg_ty.abiAlignment(zcu);
20932101
20942102 offset = @intCast(arg_align.forward(offset));
2095 try cg.store(buffer, arg_val, arg_ty, offset);
2103 try cg.store(buffer, arg_val, arg_ty, .{ .offset = offset });
20962104 offset += arg_size;
20972105 }
20982106
......@@ -2149,7 +2157,7 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier)
21492157 const result_local = try cg.allocLocal(scalar_type);
21502158 try cg.addLocal(.local_set, result_local.local.value);
21512159 const result = try cg.allocStack(ret_ty);
2152 try cg.store(result, result_local, scalar_type, 0);
2160 try cg.store(result, result_local, scalar_type, .{});
21532161 break :result_value result;
21542162 }
21552163 },
......@@ -2160,7 +2168,7 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier)
21602168 // save call result from operand stack
21612169 try cg.addLocal(.local_set, result_local.local.value);
21622170 const result = try cg.allocStack(ret_ty);
2163 try cg.store(result, result_local, vector.elem_type, 0);
2171 try cg.store(result, result_local, vector.elem_type, .{});
21642172 break :result_value result;
21652173 },
21662174 }
......@@ -2191,7 +2199,7 @@ fn airVaCopy(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
21912199 const ty_op = cg.air.instructions.items(.data)[@backingInt(inst)].ty_op;
21922200 const operand = try cg.resolveInst(ty_op.operand);
21932201
2194 const result = try cg.load(operand, .usize, 0);
2202 const result = try cg.load(operand, .usize, .{});
21952203
21962204 return cg.finishAir(inst, result, &.{ty_op.operand});
21972205}
......@@ -2214,7 +2222,7 @@ fn airVaArg(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
22142222 const abi_align: u32 = @intCast(load_ty.abiAlignment(zcu).toByteUnits().?);
22152223
22162224 const arg_ptr = try cg.allocLocal(.usize);
2217 _ = try cg.load(operand, .usize, 0);
2225 _ = try cg.load(operand, .usize, .{});
22182226
22192227 if (abi_align > 1) {
22202228 switch (cg.ptr_size) {
......@@ -2247,17 +2255,17 @@ fn airVaArg(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
22472255 try cg.addTag(.i64_add);
22482256 },
22492257 }
2250 try cg.store(.stack, .stack, .usize, 0);
2258 try cg.store(.stack, .stack, .usize, .{});
22512259
22522260 const result = if (is_f32_va_arg) result: {
2253 const promoted = try cg.load(arg_ptr, Type.f64, 0);
2261 const promoted = try cg.load(arg_ptr, .f64, .{});
22542262 try cg.emitWValue(promoted);
22552263 try cg.addTag(.f32_demote_f64);
22562264
22572265 const result_local = try cg.allocLocal(Type.f32);
22582266 try cg.addLocal(.local_set, result_local.local.value);
22592267 break :result result_local;
2260 } else try cg.load(arg_ptr, ty, 0);
2268 } else try cg.load(arg_ptr, ty, .{});
22612269
22622270 return cg.finishAir(inst, result, &.{ty_op.operand});
22632271}
......@@ -2282,18 +2290,26 @@ fn airStore(cg: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void {
22822290 return cg.finishAir(inst, .none, &.{ bin_op.lhs, bin_op.rhs });
22832291 }
22842292
2285 const offset: u32 = switch (ptr_info.flags.vector_index) {
2293 const offset: u64 = switch (ptr_info.flags.vector_index) {
22862294 .none => offset: {
22872295 assert(ptr_info.packed_offset.host_size == 0); // legalize .expand_packed_store
22882296 break :offset 0;
22892297 },
2290 else => |index| @intCast(@backingInt(index) * elem_ty.abiSize(zcu)),
2298 else => |index| @backingInt(index) * elem_ty.abiSize(zcu),
22912299 };
2292 try cg.store(lhs, rhs, elem_ty, offset);
2300 try cg.store(lhs, rhs, elem_ty, .{
2301 .offset = offset,
2302 .alignment = ptr_ty.ptrAlignment(zcu),
2303 });
22932304 return cg.finishAir(inst, .none, &.{ bin_op.lhs, bin_op.rhs });
22942305}
22952306
2296fn store(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerError!void {
2307const MemArg = struct {
2308 offset: u64 = 0,
2309 alignment: Alignment = .none,
2310};
2311
2312fn store(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, memarg: MemArg) InnerError!void {
22972313 assert(!(lhs != .stack and rhs == .stack));
22982314 const pt = cg.pt;
22992315 const zcu = pt.zcu;
......@@ -2301,12 +2317,19 @@ fn store(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErr
23012317
23022318 if (!ty.hasRuntimeBits(zcu)) return;
23032319
2320 const natural_alignment = ty.abiAlignment(zcu);
2321 // wasm memory instruction alignment is <= access width
2322 const alignment = if (memarg.alignment == .none)
2323 natural_alignment
2324 else
2325 natural_alignment.minStrict(memarg.alignment);
2326
23042327 if (isByRef(ty, zcu, cg.target)) {
2305 const offset_ptr: WValue = switch (offset + lhs.offset()) {
2328 const offset_ptr: WValue = switch (memarg.offset + lhs.offset()) {
23062329 0 => lhs,
23072330 else => |total_offset| ptr: {
23082331 try cg.emitWValue(lhs);
2309 try cg.addImm32(total_offset);
2332 try cg.addImm32(@intCast(total_offset));
23102333 try cg.addTag(.i32_add);
23112334 break :ptr .stack;
23122335 },
......@@ -2320,10 +2343,11 @@ fn store(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErr
23202343 // TODO: Add helper functions for simd opcodes
23212344 const extra_index: u32 = @intCast(cg.mir_extra.items.len);
23222345 // stores as := opcode, offset, alignment (opcode::memarg)
2323 try cg.mir_extra.appendSlice(cg.gpa, &[_]u32{
2324 @backingInt(std.wasm.SimdOpcode.v128_store),
2325 offset + lhs.offset(),
2326 @intCast(ty.abiAlignment(zcu).toByteUnits().?),
2346 try cg.mir_extra.ensureUnusedCapacity(cg.gpa, 4);
2347 cg.mir_extra.appendAssumeCapacity(@backingInt(std.wasm.SimdOpcode.v128_store));
2348 _ = try cg.addExtraAssumeCapacity(Mir.MemArg{
2349 .offset = memarg.offset + lhs.offset(),
2350 .alignment = alignment.toStdMem(),
23272351 });
23282352 return cg.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } });
23292353 }
......@@ -2353,8 +2377,8 @@ fn store(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErr
23532377 try cg.addMemArg(
23542378 store_opcode,
23552379 .{
2356 .offset = offset + lhs.offset(),
2357 .alignment = @intCast(ty.abiAlignment(zcu).toByteUnits().?),
2380 .offset = memarg.offset + lhs.offset(),
2381 .alignment = alignment.toStdMem(),
23582382 },
23592383 );
23602384}
......@@ -2370,34 +2394,45 @@ fn airLoad(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
23702394
23712395 assert(elem_ty.hasRuntimeBits(zcu));
23722396
2373 const offset: u32 = switch (ptr_info.flags.vector_index) {
2397 const offset: u64 = switch (ptr_info.flags.vector_index) {
23742398 .none => offset: {
23752399 assert(ptr_info.packed_offset.host_size == 0); // legalize .expand_packed_load
23762400 break :offset 0;
23772401 },
2378 else => |index| @intCast(@backingInt(index) * elem_ty.abiSize(zcu)),
2402 else => |index| @backingInt(index) * elem_ty.abiSize(zcu),
23792403 };
2380 const result = try cg.load(operand, elem_ty, offset);
2404 const result = try cg.load(operand, elem_ty, .{
2405 .offset = offset,
2406 .alignment = ptr_ty.ptrAlignment(zcu),
2407 });
23812408 return cg.finishAir(inst, result, &.{ty_op.operand});
23822409}
23832410
23842411/// Loads an operand from the linear memory section.
23852412/// NOTE: Leaves the value on the stack, if isByRef == false.
2386fn load(cg: *CodeGen, operand: WValue, ty: Type, offset: u32) InnerError!WValue {
2413fn load(cg: *CodeGen, operand: WValue, ty: Type, memarg: MemArg) InnerError!WValue {
23872414 const zcu = cg.pt.zcu;
2415
2416 const natural_alignment = ty.abiAlignment(zcu);
2417 // wasm memory instruction alignment is <= access width
2418 const alignment = if (memarg.alignment == .none)
2419 natural_alignment
2420 else
2421 natural_alignment.minStrict(memarg.alignment);
2422
23882423 if (isByRef(ty, zcu, cg.target)) {
2389 const src_ptr_maybe_stack: WValue = switch (offset + operand.offset()) {
2424 const src_ptr_maybe_stack: WValue = switch (memarg.offset + operand.offset()) {
23902425 0 => operand,
23912426 else => |total_offset| ptr: {
23922427 try cg.emitWValue(operand);
2393 try cg.addImm32(total_offset);
2428 try cg.addImm32(@intCast(total_offset));
23942429 try cg.addTag(.i32_add);
23952430 break :ptr .stack;
23962431 },
23972432 };
23982433 const src_ptr = try src_ptr_maybe_stack.toLocal(cg, .usize);
23992434 const new_ptr = try cg.allocStack(ty);
2400 try cg.store(new_ptr, src_ptr, ty, 0);
2435 try cg.store(new_ptr, src_ptr, ty, .{});
24012436 return new_ptr;
24022437 }
24032438
......@@ -2408,10 +2443,11 @@ fn load(cg: *CodeGen, operand: WValue, ty: Type, offset: u32) InnerError!WValue
24082443 // TODO: Add helper functions for simd opcodes
24092444 const extra_index: u32 = @intCast(cg.mir_extra.items.len);
24102445 // stores as := opcode, offset, alignment (opcode::memarg)
2411 try cg.mir_extra.appendSlice(cg.gpa, &[_]u32{
2412 @backingInt(std.wasm.SimdOpcode.v128_load),
2413 offset + operand.offset(),
2414 @intCast(ty.abiAlignment(zcu).toByteUnits().?),
2446 try cg.mir_extra.ensureUnusedCapacity(cg.gpa, 4);
2447 cg.mir_extra.appendAssumeCapacity(@backingInt(std.wasm.SimdOpcode.v128_load));
2448 _ = try cg.addExtraAssumeCapacity(Mir.MemArg{
2449 .offset = memarg.offset + operand.offset(),
2450 .alignment = alignment.toStdMem(),
24152451 });
24162452 try cg.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } });
24172453 return .stack;
......@@ -2441,8 +2477,8 @@ fn load(cg: *CodeGen, operand: WValue, ty: Type, offset: u32) InnerError!WValue
24412477 try cg.addMemArg(
24422478 load_opcode,
24432479 .{
2444 .offset = offset + operand.offset(),
2445 .alignment = @intCast(ty.abiAlignment(zcu).toByteUnits().?),
2480 .offset = memarg.offset + operand.offset(),
2481 .alignment = alignment.toStdMem(),
24462482 },
24472483 );
24482484
......@@ -2470,7 +2506,7 @@ fn airArg(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
24702506 cg.arg_index += 1;
24712507 if (isByRef(arg_ty, zcu, cg.target)) {
24722508 const result = try cg.allocStack(arg_ty);
2473 try cg.store(result, arg, scalar_type, 0);
2509 try cg.store(result, arg, scalar_type, .{});
24742510 return cg.finishAir(inst, result, &.{});
24752511 }
24762512 },
......@@ -2478,15 +2514,15 @@ fn airArg(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
24782514 .double_i64 => {
24792515 cg.arg_index += 2;
24802516 const result = try cg.allocStack(arg_ty);
2481 try cg.store(result, arg, Type.u64, 0);
2482 try cg.store(result, cg.args[arg_index + 1], Type.u64, 8);
2517 try cg.store(result, arg, .u64, .{});
2518 try cg.store(result, cg.args[arg_index + 1], .u64, .{ .offset = 8 });
24832519 return cg.finishAir(inst, result, &.{});
24842520 },
24852521 .unrolled => |vector| {
24862522 const result = try cg.allocStack(arg_ty);
2487 const elem_size: u32 = @intCast(vector.elem_type.abiSize(zcu));
2523 const elem_size = vector.elem_type.abiSize(zcu);
24882524 for (0..vector.len) |index| {
2489 try cg.store(result, cg.args[cg.arg_index], vector.elem_type, @intCast(index * elem_size));
2525 try cg.store(result, cg.args[cg.arg_index], vector.elem_type, .{ .offset = index * elem_size });
24902526 cg.arg_index += 1;
24912527 }
24922528 return cg.finishAir(inst, result, &.{});
......@@ -2588,15 +2624,15 @@ fn intAdd(cg: *CodeGen, ty: IntType, lhs: WValue, rhs: WValue) InnerError!WValue
25882624 65...128 => {
25892625 const result = try cg.allocStack(Type.u128);
25902626
2591 var lhs_lsb = try (try cg.load(lhs, Type.u64, 0)).toLocal(cg, Type.u64);
2627 var lhs_lsb = try (try cg.load(lhs, .u64, .{})).toLocal(cg, Type.u64);
25922628 defer lhs_lsb.free(cg);
2593 var rhs_lsb = try (try cg.load(rhs, Type.u64, 0)).toLocal(cg, Type.u64);
2629 var rhs_lsb = try (try cg.load(rhs, .u64, .{})).toLocal(cg, Type.u64);
25942630 defer rhs_lsb.free(cg);
25952631 var op_lsb = try (try cg.intAdd(.u64, lhs_lsb, rhs_lsb)).toLocal(cg, Type.u64);
25962632 defer op_lsb.free(cg);
25972633
2598 const lhs_msb = try cg.load(lhs, Type.u64, 8);
2599 const rhs_msb = try cg.load(rhs, Type.u64, 8);
2634 const lhs_msb = try cg.load(lhs, .u64, .{ .offset = 8 });
2635 const rhs_msb = try cg.load(rhs, .u64, .{ .offset = 8 });
26002636 const op_msb = try cg.intAdd(.u64, lhs_msb, rhs_msb);
26012637
26022638 const lt = try cg.intCmp(.u64, .lt, op_lsb, rhs_lsb);
......@@ -2604,8 +2640,8 @@ fn intAdd(cg: *CodeGen, ty: IntType, lhs: WValue, rhs: WValue) InnerError!WValue
26042640 var tmp_op = try (try cg.intAdd(.u64, op_msb, tmp)).toLocal(cg, Type.u64);
26052641 defer tmp_op.free(cg);
26062642
2607 try cg.store(result, op_lsb, Type.u64, 0);
2608 try cg.store(result, tmp_op, Type.u64, 8);
2643 try cg.store(result, op_lsb, .u64, .{});
2644 try cg.store(result, tmp_op, .u64, .{ .offset = 8 });
26092645 return result;
26102646 },
26112647 else => {
......@@ -2641,15 +2677,15 @@ fn intSub(cg: *CodeGen, ty: IntType, lhs: WValue, rhs: WValue) InnerError!WValue
26412677 65...128 => {
26422678 const result = try cg.allocStack(Type.u128);
26432679
2644 var lhs_lsb = try (try cg.load(lhs, Type.u64, 0)).toLocal(cg, Type.u64);
2680 var lhs_lsb = try (try cg.load(lhs, .u64, .{})).toLocal(cg, Type.u64);
26452681 defer lhs_lsb.free(cg);
2646 var rhs_lsb = try (try cg.load(rhs, Type.u64, 0)).toLocal(cg, Type.u64);
2682 var rhs_lsb = try (try cg.load(rhs, .u64, .{})).toLocal(cg, Type.u64);
26472683 defer rhs_lsb.free(cg);
26482684 var op_lsb = try (try cg.intSub(.u64, lhs_lsb, rhs_lsb)).toLocal(cg, Type.u64);
26492685 defer op_lsb.free(cg);
26502686
2651 const lhs_msb = try cg.load(lhs, Type.u64, 8);
2652 const rhs_msb = try cg.load(rhs, Type.u64, 8);
2687 const lhs_msb = try cg.load(lhs, .u64, .{ .offset = 8 });
2688 const rhs_msb = try cg.load(rhs, .u64, .{ .offset = 8 });
26532689 const op_msb = try cg.intSub(.u64, lhs_msb, rhs_msb);
26542690
26552691 const lt = try cg.intCmp(.u64, .lt, lhs_lsb, rhs_lsb);
......@@ -2657,8 +2693,8 @@ fn intSub(cg: *CodeGen, ty: IntType, lhs: WValue, rhs: WValue) InnerError!WValue
26572693 var tmp_op = try (try cg.intSub(.u64, op_msb, tmp)).toLocal(cg, Type.u64);
26582694 defer tmp_op.free(cg);
26592695
2660 try cg.store(result, op_lsb, Type.u64, 0);
2661 try cg.store(result, tmp_op, Type.u64, 8);
2696 try cg.store(result, op_lsb, .u64, .{});
2697 try cg.store(result, tmp_op, .u64, .{ .offset = 8 });
26622698 return result;
26632699 },
26642700 else => {
......@@ -2990,15 +3026,15 @@ fn intAnd(cg: *CodeGen, ty: IntType, lhs: WValue, rhs: WValue) InnerError!WValue
29903026 65...128 => {
29913027 const result = try cg.allocStack(Type.u128);
29923028
2993 const lhs_lsb = try cg.load(lhs, Type.u64, 0);
2994 const rhs_lsb = try cg.load(rhs, Type.u64, 0);
3029 const lhs_lsb = try cg.load(lhs, .u64, .{});
3030 const rhs_lsb = try cg.load(rhs, .u64, .{});
29953031 const and_lsb = try (try cg.intAnd(.u64, lhs_lsb, rhs_lsb)).toLocal(cg, Type.u64);
2996 try cg.store(result, and_lsb, Type.u64, 0);
3032 try cg.store(result, and_lsb, .u64, .{});
29973033
2998 const lhs_msb = try cg.load(lhs, Type.u64, 8);
2999 const rhs_msb = try cg.load(rhs, Type.u64, 8);
3034 const lhs_msb = try cg.load(lhs, .u64, .{ .offset = 8 });
3035 const rhs_msb = try cg.load(rhs, .u64, .{ .offset = 8 });
30003036 const and_msb = try (try cg.intAnd(.u64, lhs_msb, rhs_msb)).toLocal(cg, Type.u64);
3001 try cg.store(result, and_msb, Type.u64, 8);
3037 try cg.store(result, and_msb, .u64, .{ .offset = 8 });
30023038
30033039 return result;
30043040 },
......@@ -3034,15 +3070,15 @@ fn intOr(cg: *CodeGen, ty: IntType, lhs: WValue, rhs: WValue) InnerError!WValue
30343070 65...128 => {
30353071 const result = try cg.allocStack(Type.u128);
30363072
3037 const lhs_lsb = try cg.load(lhs, Type.u64, 0);
3038 const rhs_lsb = try cg.load(rhs, Type.u64, 0);
3073 const lhs_lsb = try cg.load(lhs, .u64, .{});
3074 const rhs_lsb = try cg.load(rhs, .u64, .{});
30393075 const or_lsb = try (try cg.intOr(.u64, lhs_lsb, rhs_lsb)).toLocal(cg, Type.u64);
3040 try cg.store(result, or_lsb, Type.u64, 0);
3076 try cg.store(result, or_lsb, .u64, .{});
30413077
3042 const lhs_msb = try cg.load(lhs, Type.u64, 8);
3043 const rhs_msb = try cg.load(rhs, Type.u64, 8);
3078 const lhs_msb = try cg.load(lhs, .u64, .{ .offset = 8 });
3079 const rhs_msb = try cg.load(rhs, .u64, .{ .offset = 8 });
30443080 const or_msb = try (try cg.intOr(.u64, lhs_msb, rhs_msb)).toLocal(cg, Type.u64);
3045 try cg.store(result, or_msb, Type.u64, 8);
3081 try cg.store(result, or_msb, .u64, .{ .offset = 8 });
30463082
30473083 return result;
30483084 },
......@@ -3078,15 +3114,15 @@ fn intXor(cg: *CodeGen, ty: IntType, lhs: WValue, rhs: WValue) InnerError!WValue
30783114 65...128 => {
30793115 const result = try cg.allocStack(Type.u128);
30803116
3081 const lhs_lsb = try cg.load(lhs, Type.u64, 0);
3082 const rhs_lsb = try cg.load(rhs, Type.u64, 0);
3117 const lhs_lsb = try cg.load(lhs, .u64, .{});
3118 const rhs_lsb = try cg.load(rhs, .u64, .{});
30833119 const xor_lsb = try (try cg.intXor(.u64, lhs_lsb, rhs_lsb)).toLocal(cg, Type.u64);
3084 try cg.store(result, xor_lsb, Type.u64, 0);
3120 try cg.store(result, xor_lsb, .u64, .{});
30853121
3086 const lhs_msb = try cg.load(lhs, Type.u64, 8);
3087 const rhs_msb = try cg.load(rhs, Type.u64, 8);
3122 const lhs_msb = try cg.load(lhs, .u64, .{ .offset = 8 });
3123 const rhs_msb = try cg.load(rhs, .u64, .{ .offset = 8 });
30883124 const xor_msb = try (try cg.intXor(.u64, lhs_msb, rhs_msb)).toLocal(cg, Type.u64);
3089 try cg.store(result, xor_msb, Type.u64, 8);
3125 try cg.store(result, xor_msb, .u64, .{ .offset = 8 });
30903126
30913127 return result;
30923128 },
......@@ -3141,20 +3177,20 @@ fn intNot(cg: *CodeGen, ty: IntType, operand: WValue) InnerError!WValue {
31413177 const result = try cg.allocStack(Type.u128);
31423178
31433179 try cg.emitWValue(result);
3144 _ = try cg.load(operand, Type.u64, 0);
3180 _ = try cg.load(operand, .u64, .{});
31453181 try cg.addImm64(~@as(u64, 0));
31463182 try cg.addTag(.i64_xor);
3147 try cg.store(.stack, .stack, Type.u64, result.offset());
3183 try cg.store(.stack, .stack, .u64, .{ .offset = result.offset() });
31483184
31493185 try cg.emitWValue(result);
3150 _ = try cg.load(operand, Type.u64, 8);
3186 _ = try cg.load(operand, .u64, .{ .offset = 8 });
31513187 const high_mask: u64 = if (ty.is_signed)
31523188 ~@as(u64, 0)
31533189 else
31543190 ~@as(u64, 0) >> @intCast(128 - ty.bits);
31553191 try cg.addImm64(high_mask);
31563192 try cg.addTag(.i64_xor);
3157 try cg.store(.stack, .stack, Type.u64, result.offset() + 8);
3193 try cg.store(.stack, .stack, .u64, .{ .offset = result.offset() + 8 });
31583194
31593195 return result;
31603196 },
......@@ -3287,16 +3323,16 @@ fn intAbs(cg: *CodeGen, ty: IntType, operand: WValue) InnerError!WValue {
32873323 try cg.emitWValue(mask);
32883324 try cg.emitWValue(mask);
32893325
3290 _ = try cg.load(operand, Type.u64, 8);
3326 _ = try cg.load(operand, .u64, .{ .offset = 8 });
32913327 try cg.addImm64(63);
32923328 try cg.addTag(.i64_shr_s);
32933329
32943330 var tmp = try cg.allocLocal(Type.u64);
32953331 defer tmp.free(cg);
32963332 try cg.addLocal(.local_tee, tmp.local.value);
3297 try cg.store(.stack, .stack, Type.u64, mask.offset() + 0);
3333 try cg.store(.stack, .stack, .u64, .{ .offset = mask.offset() + 0 });
32983334 try cg.emitWValue(tmp);
3299 try cg.store(.stack, .stack, Type.u64, mask.offset() + 8);
3335 try cg.store(.stack, .stack, .u64, .{ .offset = mask.offset() + 8 });
33003336
33013337 const a = try cg.intXor(u128_ty, operand, mask);
33023338 const b = try cg.intSub(u128_ty, a, mask);
......@@ -3364,7 +3400,7 @@ fn intClz(cg: *CodeGen, ty: IntType, operand: WValue) InnerError!WValue {
33643400 return .stack;
33653401 },
33663402 65...128 => {
3367 var msb = try (try cg.load(operand, Type.u64, 8)).toLocal(cg, Type.u64);
3403 var msb = try (try cg.load(operand, .u64, .{ .offset = 8 })).toLocal(cg, Type.u64);
33683404 defer msb.free(cg);
33693405
33703406 if (ty.is_signed and ty.bits < 128) {
......@@ -3375,7 +3411,7 @@ fn intClz(cg: *CodeGen, ty: IntType, operand: WValue) InnerError!WValue {
33753411 }
33763412
33773413 try cg.addTag(.i64_clz);
3378 _ = try cg.load(operand, Type.u64, 0);
3414 _ = try cg.load(operand, .u64, .{});
33793415 try cg.addTag(.i64_clz);
33803416 try cg.emitWValue(.{ .imm64 = 64 });
33813417 try cg.addTag(.i64_add);
......@@ -3423,13 +3459,13 @@ fn intCtz(cg: *CodeGen, ty: IntType, operand: WValue) InnerError!WValue {
34233459 return .stack;
34243460 },
34253461 65...128 => {
3426 var lsb = try (try cg.load(operand, Type.u64, 0)).toLocal(cg, Type.u64);
3462 var lsb = try (try cg.load(operand, .u64, .{})).toLocal(cg, Type.u64);
34273463 defer lsb.free(cg);
34283464
34293465 try cg.emitWValue(lsb);
34303466 try cg.addTag(.i64_ctz);
34313467
3432 _ = try cg.load(operand, Type.u64, 8);
3468 _ = try cg.load(operand, .u64, .{ .offset = 8 });
34333469 if (ty.bits < 128) {
34343470 try cg.addImm64(@as(u64, 1) << @intCast(ty.bits - 64));
34353471 try cg.addTag(.i64_or);
......@@ -3475,9 +3511,9 @@ fn intPopCount(cg: *CodeGen, ty: IntType, operand: WValue) InnerError!WValue {
34753511 return .stack;
34763512 },
34773513 65...128 => {
3478 _ = try cg.load(operand, Type.u64, 0);
3514 _ = try cg.load(operand, .u64, .{});
34793515 try cg.addTag(.i64_popcnt);
3480 _ = try cg.load(operand, Type.u64, 8);
3516 _ = try cg.load(operand, .u64, .{ .offset = 8 });
34813517 if (ty.is_signed and ty.bits < 128) {
34823518 try cg.addImm64(128 - ty.bits);
34833519 try cg.addTag(.i64_shl);
......@@ -3525,7 +3561,7 @@ fn intBitReverse(cg: *CodeGen, ty: IntType, operand: WValue) InnerError!WValue {
35253561 const tmp = try cg.allocStack(Type.u128);
35263562
35273563 try cg.emitWValue(tmp);
3528 const hi = try cg.load(operand, Type.u64, 8);
3564 const hi = try cg.load(operand, .u64, .{ .offset = 8 });
35293565 const hi_rev = try cg.callIntrinsic(
35303566 .__bitreversedi2,
35313567 &.{.u64_type},
......@@ -3533,10 +3569,10 @@ fn intBitReverse(cg: *CodeGen, ty: IntType, operand: WValue) InnerError!WValue {
35333569 &.{hi},
35343570 );
35353571 try cg.emitWValue(hi_rev);
3536 try cg.store(.stack, .stack, Type.u64, tmp.offset());
3572 try cg.store(.stack, .stack, .u64, .{ .offset = tmp.offset() });
35373573
35383574 try cg.emitWValue(tmp);
3539 const lo = try cg.load(operand, Type.u64, 0);
3575 const lo = try cg.load(operand, .u64, .{});
35403576 const lo_rev = try cg.callIntrinsic(
35413577 .__bitreversedi2,
35423578 &.{.u64_type},
......@@ -3544,7 +3580,7 @@ fn intBitReverse(cg: *CodeGen, ty: IntType, operand: WValue) InnerError!WValue {
35443580 &.{lo},
35453581 );
35463582 try cg.emitWValue(lo_rev);
3547 try cg.store(.stack, .stack, Type.u64, tmp.offset() + 8);
3583 try cg.store(.stack, .stack, .u64, .{ .offset = tmp.offset() + 8 });
35483584
35493585 if (ty.bits < 128) {
35503586 const shift_ty: IntType = .{ .is_signed = ty.is_signed, .bits = 128 };
......@@ -3595,25 +3631,25 @@ fn intByteSwap(cg: *CodeGen, ty: IntType, operand: WValue) InnerError!WValue {
35953631
35963632 try cg.emitWValue(result);
35973633
3598 const low = try cg.load(operand, Type.u64, 0);
3634 const low = try cg.load(operand, .u64, .{});
35993635 const swap_low = try cg.callIntrinsic(
36003636 .__bswapdi2,
36013637 &.{.u64_type},
36023638 Type.u64,
36033639 &.{low},
36043640 );
3605 try cg.store(.stack, swap_low, Type.u64, result.offset() + 8);
3641 try cg.store(.stack, swap_low, .u64, .{ .offset = result.offset() + 8 });
36063642
36073643 try cg.emitWValue(result);
36083644
3609 const high = try cg.load(operand, Type.u64, 8);
3645 const high = try cg.load(operand, .u64, .{ .offset = 8 });
36103646 const swap_high = try cg.callIntrinsic(
36113647 .__bswapdi2,
36123648 &.{.u64_type},
36133649 Type.u64,
36143650 &.{high},
36153651 );
3616 try cg.store(.stack, swap_high, Type.u64, result.offset());
3652 try cg.store(.stack, swap_high, .u64, .{ .offset = result.offset() });
36173653
36183654 if (ty.bits < 128) {
36193655 const shift_ty: IntType = .{ .is_signed = ty.is_signed, .bits = 128 };
......@@ -3671,11 +3707,11 @@ fn intWrap(cg: *CodeGen, ty: IntType, operand: WValue) InnerError!WValue {
36713707 const result = try cg.allocStack(Type.u128);
36723708
36733709 try cg.emitWValue(result);
3674 _ = try cg.load(operand, Type.u64, 0);
3675 try cg.store(.stack, .stack, Type.u64, result.offset());
3710 _ = try cg.load(operand, .u64, .{});
3711 try cg.store(.stack, .stack, .u64, .{ .offset = result.offset() });
36763712
36773713 try cg.emitWValue(result);
3678 _ = try cg.load(operand, Type.u64, 8);
3714 _ = try cg.load(operand, .u64, .{ .offset = 8 });
36793715 if (ty.is_signed) {
36803716 try cg.addImm64(128 - ty.bits);
36813717 try cg.addTag(.i64_shl);
......@@ -3685,7 +3721,7 @@ fn intWrap(cg: *CodeGen, ty: IntType, operand: WValue) InnerError!WValue {
36853721 try cg.addImm64(~@as(u64, 0) >> @intCast(128 - ty.bits));
36863722 try cg.addTag(.i64_and);
36873723 }
3688 try cg.store(.stack, .stack, Type.u64, result.offset() + 8);
3724 try cg.store(.stack, .stack, .u64, .{ .offset = result.offset() + 8 });
36893725
36903726 return result;
36913727 },
......@@ -3703,7 +3739,7 @@ fn intWrap(cg: *CodeGen, ty: IntType, operand: WValue) InnerError!WValue {
37033739 const pad = 64 - ty.bits % 64;
37043740
37053741 try cg.emitWValue(result);
3706 _ = try cg.load(operand, Type.u64, used_len - 8);
3742 _ = try cg.load(operand, .u64, .{ .offset = used_len - 8 });
37073743 if (ty.is_signed) {
37083744 try cg.addImm64(pad);
37093745 try cg.addTag(.i64_shl);
......@@ -3713,7 +3749,7 @@ fn intWrap(cg: *CodeGen, ty: IntType, operand: WValue) InnerError!WValue {
37133749 try cg.addImm64(~@as(u64, 0) >> @intCast(pad));
37143750 try cg.addTag(.i64_and);
37153751 }
3716 try cg.store(.stack, .stack, Type.u64, result.offset() + used_len - 8);
3752 try cg.store(.stack, .stack, .u64, .{ .offset = result.offset() + used_len - 8 });
37173753 } else {
37183754 try cg.memcpy(result, operand, .{ .imm32 = used_len });
37193755 }
......@@ -3722,13 +3758,13 @@ fn intWrap(cg: *CodeGen, ty: IntType, operand: WValue) InnerError!WValue {
37223758 if (used_len + 8 == full_len) { // last limb needs sign extended
37233759 try cg.emitWValue(result);
37243760 if (ty.is_signed) {
3725 _ = try cg.load(result, Type.u64, used_len - 8);
3761 _ = try cg.load(result, .u64, .{ .offset = used_len - 8 });
37263762 try cg.addImm64(63);
37273763 try cg.addTag(.i64_shr_s);
37283764 } else {
37293765 try cg.addImm64(0);
37303766 }
3731 try cg.store(.stack, .stack, Type.u64, result.offset() + used_len);
3767 try cg.store(.stack, .stack, .u64, .{ .offset = result.offset() + used_len });
37323768 }
37333769
37343770 return result;
......@@ -3751,12 +3787,12 @@ fn intMaxValue(cg: *CodeGen, int_ty: IntType) InnerError!WValue {
37513787 }
37523788 } else if (int_ty.bits <= 128) {
37533789 const result = try cg.allocInt(int_ty);
3754 try cg.store(result, .{ .imm64 = ~@as(u64, 0) }, Type.u64, 0);
3790 try cg.store(result, .{ .imm64 = ~@as(u64, 0) }, .u64, .{});
37553791
37563792 if (int_ty.is_signed) {
3757 try cg.store(result, .{ .imm64 = (~@as(u64, 0) >> @intCast(128 - int_ty.bits)) >> 1 }, Type.u64, 8);
3793 try cg.store(result, .{ .imm64 = (~@as(u64, 0) >> @intCast(128 - int_ty.bits)) >> 1 }, .u64, .{ .offset = 8 });
37583794 } else {
3759 try cg.store(result, .{ .imm64 = ~@as(u64, 0) >> @intCast(128 - int_ty.bits) }, Type.u64, 8);
3795 try cg.store(result, .{ .imm64 = ~@as(u64, 0) >> @intCast(128 - int_ty.bits) }, .u64, .{ .offset = 8 });
37603796 }
37613797 return result;
37623798 } else {
......@@ -3767,13 +3803,13 @@ fn intMaxValue(cg: *CodeGen, int_ty: IntType) InnerError!WValue {
37673803 try cg.memset(Type.u8, result, .{ .imm32 = used_len - 8 }, .{ .imm32 = 0xFF });
37683804
37693805 if (int_ty.is_signed) {
3770 try cg.store(result, .{ .imm64 = (~@as(u64, 0) >> @intCast(used_len * 8 - int_ty.bits)) >> 1 }, Type.u64, used_len - 8);
3806 try cg.store(result, .{ .imm64 = (~@as(u64, 0) >> @intCast(used_len * 8 - int_ty.bits)) >> 1 }, .u64, .{ .offset = used_len - 8 });
37713807 } else {
3772 try cg.store(result, .{ .imm64 = ~@as(u64, 0) >> @intCast(used_len * 8 - int_ty.bits) }, Type.u64, used_len - 8);
3808 try cg.store(result, .{ .imm64 = ~@as(u64, 0) >> @intCast(used_len * 8 - int_ty.bits) }, .u64, .{ .offset = used_len - 8 });
37733809 }
37743810
37753811 if (used_len + 8 == full_len) {
3776 try cg.store(result, .{ .imm64 = 0 }, Type.u64, full_len - 8);
3812 try cg.store(result, .{ .imm64 = 0 }, .u64, .{ .offset = full_len - 8 });
37773813 }
37783814
37793815 return result;
......@@ -3790,8 +3826,8 @@ fn intMinValue(cg: *CodeGen, int_ty: IntType) InnerError!WValue {
37903826 return .{ .imm64 = ~@as(u64, 0) << @intCast(int_ty.bits - 1) };
37913827 } else if (int_ty.bits <= 128) {
37923828 const result = try cg.allocInt(int_ty);
3793 try cg.store(result, .{ .imm64 = 0 }, Type.u64, 0);
3794 try cg.store(result, .{ .imm64 = ~@as(u64, 0) << @intCast(int_ty.bits - 65) }, Type.u64, 8);
3829 try cg.store(result, .{ .imm64 = 0 }, .u64, .{});
3830 try cg.store(result, .{ .imm64 = ~@as(u64, 0) << @intCast(int_ty.bits - 65) }, .u64, .{ .offset = 8 });
37953831 return result;
37963832 } else {
37973833 const result = try cg.allocInt(int_ty);
......@@ -3799,10 +3835,10 @@ fn intMinValue(cg: *CodeGen, int_ty: IntType) InnerError!WValue {
37993835 const used_len = @divCeil(int_ty.bits, 64) * 8;
38003836
38013837 try cg.memset(Type.u8, result, .{ .imm32 = used_len - 8 }, .{ .imm32 = 0 });
3802 try cg.store(result, .{ .imm64 = ~@as(u64, 0) << @intCast(int_ty.bits - (used_len - 8) * 8 - 1) }, Type.u64, used_len - 8);
3838 try cg.store(result, .{ .imm64 = ~@as(u64, 0) << @intCast(int_ty.bits - (used_len - 8) * 8 - 1) }, .u64, .{ .offset = used_len - 8 });
38033839
38043840 if (used_len + 8 == full_len) {
3805 try cg.store(result, .{ .imm64 = ~@as(u64, 0) }, Type.u64, full_len - 8);
3841 try cg.store(result, .{ .imm64 = ~@as(u64, 0) }, .u64, .{ .offset = full_len - 8 });
38063842 }
38073843
38083844 return result;
......@@ -3962,8 +3998,8 @@ fn intZeroValue(cg: *CodeGen, int_ty: IntType) InnerError!WValue {
39623998 33...64 => return .{ .imm64 = 0 },
39633999 65...128 => {
39644000 const result = try cg.allocInt(int_ty);
3965 try cg.store(result, .{ .imm64 = 0 }, Type.u64, 0);
3966 try cg.store(result, .{ .imm64 = 0 }, Type.u64, 8);
4001 try cg.store(result, .{ .imm64 = 0 }, .u64, .{});
4002 try cg.store(result, .{ .imm64 = 0 }, .u64, .{ .offset = 8 });
39674003 return result;
39684004 },
39694005 else => {
......@@ -4103,7 +4139,7 @@ fn intMulOverflow(cg: *CodeGen, int_ty: IntType, lhs: WValue, rhs: WValue) Inner
41034139 Type.i128,
41044140 &.{ lhs, rhs, overflow_ret },
41054141 );
4106 _ = try cg.load(overflow_ret, Type.i32, 0);
4142 _ = try cg.load(overflow_ret, .i32, .{});
41074143 try cg.addLocal(.local_set, overflow_bit.local.value);
41084144 break :blk res;
41094145 } else {
......@@ -4180,12 +4216,12 @@ fn intCast(cg: *CodeGen, dest_ty: IntType, src_ty: IntType, operand: WValue) Inn
41804216 try cg.emitWValue(result);
41814217 try cg.emitWValue(operand);
41824218 try cg.addTag(if (src_ty.is_signed) .i64_extend_i32_s else .i64_extend_i32_u);
4183 try cg.store(.stack, .stack, Type.u64, result.offset());
4219 try cg.store(.stack, .stack, .u64, .{ .offset = result.offset() });
41844220 src_len = 8;
41854221 } else if (src_bits == 64) {
41864222 try cg.emitWValue(result);
41874223 try cg.emitWValue(operand);
4188 try cg.store(.stack, .stack, Type.u64, result.offset());
4224 try cg.store(.stack, .stack, .u64, .{ .offset = result.offset() });
41894225 src_len = 8;
41904226 } else {
41914227 src_len = src_bits / 8;
......@@ -4202,9 +4238,9 @@ fn intCast(cg: *CodeGen, dest_ty: IntType, src_ty: IntType, operand: WValue) Inn
42024238 try cg.emitWValue(operand);
42034239 } else unreachable;
42044240 const shr = try cg.intShr(IntType.i64, .stack, .{ .imm32 = 63 });
4205 try cg.store(.stack, shr, Type.u64, 8 + result.offset());
4241 try cg.store(.stack, shr, .u64, .{ .offset = 8 + result.offset() });
42064242 } else {
4207 try cg.store(result, .{ .imm64 = 0 }, Type.u64, 8);
4243 try cg.store(result, .{ .imm64 = 0 }, .u64, .{ .offset = 8 });
42084244 }
42094245 } else {
42104246 var pad = result;
......@@ -4219,7 +4255,7 @@ fn intCast(cg: *CodeGen, dest_ty: IntType, src_ty: IntType, operand: WValue) Inn
42194255 _ = try cg.intShr(IntType.i64, .stack, .{ .imm32 = 63 });
42204256 try cg.addTag(.i32_wrap_i64);
42214257 } else {
4222 _ = try cg.load(operand, Type.u64, src_len - 8);
4258 _ = try cg.load(operand, .u64, .{ .offset = src_len - 8 });
42234259 _ = try cg.intShr(IntType.i64, .stack, .{ .imm32 = 63 });
42244260 try cg.addTag(.i32_wrap_i64);
42254261 }
......@@ -4237,7 +4273,7 @@ fn intCast(cg: *CodeGen, dest_ty: IntType, src_ty: IntType, operand: WValue) Inn
42374273 assert(dest_bits <= 64);
42384274 assert(src_bits >= 128);
42394275 const load_ty = if (dest_bits == 32) Type.u32 else Type.u64;
4240 return cg.load(operand, load_ty, 0);
4276 return cg.load(operand, load_ty, .{});
42414277 }
42424278}
42434279
......@@ -4608,18 +4644,18 @@ fn floatNeg(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {
46084644 const result = try cg.allocStack(Type.f128);
46094645 try cg.emitWValue(result);
46104646 try cg.emitWValue(arg);
4611 try cg.addMemArg(.i64_load, .{ .offset = 0 + arg.offset(), .alignment = 2 });
4612 try cg.addMemArg(.i64_store, .{ .offset = 0 + result.offset(), .alignment = 2 });
4647 try cg.addMemArg(.i64_load, .{ .offset = 0 + arg.offset(), .alignment = .@"2" });
4648 try cg.addMemArg(.i64_store, .{ .offset = 0 + result.offset(), .alignment = .@"2" });
46134649 try cg.emitWValue(result);
46144650 try cg.emitWValue(arg);
4615 try cg.addMemArg(.i64_load, .{ .offset = 8 + arg.offset(), .alignment = 2 });
4651 try cg.addMemArg(.i64_load, .{ .offset = 8 + arg.offset(), .alignment = .@"2" });
46164652 if (ty == .f80) {
46174653 try cg.addImm64(0x8000);
46184654 } else {
46194655 try cg.addImm64(0x8000000000000000);
46204656 }
46214657 try cg.addTag(.i64_xor);
4622 try cg.addMemArg(.i64_store, .{ .offset = 8 + result.offset(), .alignment = 2 });
4658 try cg.addMemArg(.i64_store, .{ .offset = 8 + result.offset(), .alignment = .@"2" });
46234659 return result;
46244660 },
46254661 }
......@@ -4647,18 +4683,18 @@ fn floatAbs(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue {
46474683 const result = try cg.allocStack(Type.f128);
46484684 try cg.emitWValue(result);
46494685 try cg.emitWValue(arg);
4650 try cg.addMemArg(.i64_load, .{ .offset = 0 + arg.offset(), .alignment = 2 });
4651 try cg.addMemArg(.i64_store, .{ .offset = 0 + result.offset(), .alignment = 2 });
4686 try cg.addMemArg(.i64_load, .{ .offset = 0 + arg.offset(), .alignment = .@"2" });
4687 try cg.addMemArg(.i64_store, .{ .offset = 0 + result.offset(), .alignment = .@"2" });
46524688 try cg.emitWValue(result);
46534689 try cg.emitWValue(arg);
4654 try cg.addMemArg(.i64_load, .{ .offset = 8 + arg.offset(), .alignment = 2 });
4690 try cg.addMemArg(.i64_load, .{ .offset = 8 + arg.offset(), .alignment = .@"2" });
46554691 if (ty == .f80) {
46564692 try cg.addImm64(0x7FFF);
46574693 } else {
46584694 try cg.addImm64(0x7FFFFFFFFFFFFFFF);
46594695 }
46604696 try cg.addTag(.i64_and);
4661 try cg.addMemArg(.i64_store, .{ .offset = 8 + result.offset(), .alignment = 2 });
4697 try cg.addMemArg(.i64_store, .{ .offset = 8 + result.offset(), .alignment = .@"2" });
46624698 return result;
46634699 },
46644700 }
......@@ -5309,8 +5345,8 @@ fn airCmp(cg: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) Inne
53095345 try cg.addLocal(.local_get, lhs_null.local.value);
53105346 try cg.addLabel(.br_if, 0);
53115347
5312 _ = try cg.load(lhs, payload_ty, 0);
5313 _ = try cg.load(rhs, payload_ty, 0);
5348 _ = try cg.load(lhs, payload_ty, .{});
5349 _ = try cg.load(rhs, payload_ty, .{});
53145350
53155351 if (payload_ty.isAnyFloat()) {
53165352 _ = try cg.floatCmp(.fromType(cg, payload_ty), op, .stack, .stack);
......@@ -5370,16 +5406,16 @@ fn intCmp(cg: *CodeGen, ty: IntType, op: std.math.CompareOperator, lhs: WValue,
53705406 return .stack;
53715407 },
53725408 65...128 => {
5373 var lhs_msb = try (try cg.load(lhs, Type.u64, 8)).toLocal(cg, Type.u64);
5409 var lhs_msb = try (try cg.load(lhs, .u64, .{ .offset = 8 })).toLocal(cg, Type.u64);
53745410 defer lhs_msb.free(cg);
5375 var rhs_msb = try (try cg.load(rhs, Type.u64, 8)).toLocal(cg, Type.u64);
5411 var rhs_msb = try (try cg.load(rhs, .u64, .{ .offset = 8 })).toLocal(cg, Type.u64);
53765412 defer rhs_msb.free(cg);
53775413
53785414 switch (op) {
53795415 .eq, .neq => {
53805416 const xor_high = try cg.intXor(.u64, lhs_msb, rhs_msb);
5381 const lhs_lsb = try cg.load(lhs, Type.u64, 0);
5382 const rhs_lsb = try cg.load(rhs, Type.u64, 0);
5417 const lhs_lsb = try cg.load(lhs, .u64, .{});
5418 const rhs_lsb = try cg.load(rhs, .u64, .{});
53835419 const xor_low = try cg.intXor(.u64, lhs_lsb, rhs_lsb);
53845420 const or_result = try cg.intOr(.u64, xor_high, xor_low);
53855421
......@@ -5392,8 +5428,8 @@ fn intCmp(cg: *CodeGen, ty: IntType, op: std.math.CompareOperator, lhs: WValue,
53925428 else => {
53935429 const word_int_ty: IntType = if (ty.is_signed) .i64 else .u64;
53945430
5395 const lhs_lsb = try cg.load(lhs, Type.u64, 0);
5396 const rhs_lsb = try cg.load(rhs, Type.u64, 0);
5431 const lhs_lsb = try cg.load(lhs, .u64, .{});
5432 const rhs_lsb = try cg.load(rhs, .u64, .{});
53975433
53985434 // leave values on stack for 'select'
53995435 _ = try cg.intCmp(.u64, op, lhs_lsb, rhs_lsb);
......@@ -5599,7 +5635,7 @@ fn airUnionFromEnum(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
55995635
56005636 const enum_value = try cg.resolveInst(ty_op.operand);
56015637 const result = try cg.allocStack(union_ty);
5602 try cg.store(result, enum_value, enum_ty, @intCast(layout.tagOffset()));
5638 try cg.store(result, enum_value, enum_ty, .{ .offset = layout.tagOffset() });
56035639
56045640 return cg.finishAir(inst, result, &.{ty_op.operand});
56055641}
......@@ -5662,12 +5698,12 @@ fn bitcast(cg: *CodeGen, dest_ty: Type, src_ty: Type, operand: WValue) InnerErro
56625698
56635699 if (dest_by_ref) {
56645700 const result = try cg.allocStack(src_ty);
5665 try cg.store(result, operand, src_ty, 0);
5701 try cg.store(result, operand, src_ty, .{});
56665702 return result;
56675703 }
56685704
56695705 if (src_by_ref) {
5670 return try cg.load(operand, dest_ty, 0);
5706 return try cg.load(operand, dest_ty, .{});
56715707 }
56725708
56735709 switch (src_class) {
......@@ -5803,7 +5839,7 @@ fn airAggFieldVal(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
58035839 else => break :result try cg.buildPointerOffset(operand, offset, .new),
58045840 }
58055841 }
5806 break :result try cg.load(operand, field_ty, offset);
5842 break :result try cg.load(operand, field_ty, .{ .offset = offset });
58075843 },
58085844 };
58095845
......@@ -6048,7 +6084,7 @@ fn airIsErr(cg: *CodeGen, inst: Air.Inst.Index, opcode: std.wasm.Opcode, op_kind
60486084 if (op_kind == .ptr or pl_ty.hasRuntimeBits(zcu)) {
60496085 try cg.addMemArg(.i32_load16_u, .{
60506086 .offset = operand.offset() + @as(u32, @intCast(errUnionErrorOffset(pl_ty, zcu))),
6051 .alignment = @intCast(Type.anyerror.abiAlignment(zcu).toByteUnits().?),
6087 .alignment = Type.anyerror.abiAlignment(zcu).toStdMem(),
60526088 });
60536089 }
60546090
......@@ -6085,7 +6121,7 @@ fn airUnwrapErrUnionPayload(cg: *CodeGen, inst: Air.Inst.Index, op_is_ptr: bool)
60856121 break :result try cg.buildPointerOffset(operand, pl_offset, .new);
60866122 } else {
60876123 assert(isByRef(eu_ty, zcu, cg.target));
6088 break :result try cg.load(operand, payload_ty, pl_offset);
6124 break :result try cg.load(operand, payload_ty, .{ .offset = pl_offset });
60896125 }
60906126 };
60916127 return cg.finishAir(inst, result, &.{ty_op.operand});
......@@ -6110,7 +6146,7 @@ fn airUnwrapErrUnionError(cg: *CodeGen, inst: Air.Inst.Index, op_is_ptr: bool) I
61106146
61116147 const err_offset: u32 = @intCast(errUnionErrorOffset(payload_ty, zcu));
61126148 if (op_is_ptr or isByRef(eu_ty, zcu, cg.target)) {
6113 break :result try cg.load(operand, Type.anyerror, err_offset);
6149 break :result try cg.load(operand, .anyerror, .{ .offset = err_offset });
61146150 } else {
61156151 assert(!payload_ty.hasRuntimeBits(zcu));
61166152 break :result operand;
......@@ -6134,7 +6170,7 @@ fn airWrapErrUnionPayload(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
61346170
61356171 const err_union = try cg.allocStack(err_ty);
61366172 const payload_ptr = try cg.buildPointerOffset(err_union, @as(u32, @intCast(errUnionPayloadOffset(pl_ty, zcu))), .new);
6137 try cg.store(payload_ptr, operand, pl_ty, 0);
6173 try cg.store(payload_ptr, operand, pl_ty, .{});
61386174
61396175 // ensure we also write '0' to the error part, so any present stack value gets overwritten by it.
61406176 try cg.emitWValue(err_union);
......@@ -6142,7 +6178,7 @@ fn airWrapErrUnionPayload(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
61426178 const err_val_offset: u32 = @intCast(errUnionErrorOffset(pl_ty, zcu));
61436179 try cg.addMemArg(.i32_store16, .{
61446180 .offset = err_union.offset() + err_val_offset,
6145 .alignment = 2,
6181 .alignment = .@"2",
61466182 });
61476183 break :result err_union;
61486184 };
......@@ -6164,7 +6200,7 @@ fn airWrapErrUnionErr(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
61646200
61656201 const err_union = try cg.allocStack(err_ty);
61666202 // store error value
6167 try cg.store(err_union, operand, Type.anyerror, @intCast(errUnionErrorOffset(pl_ty, zcu)));
6203 try cg.store(err_union, operand, .anyerror, .{ .offset = errUnionErrorOffset(pl_ty, zcu) });
61686204
61696205 // write 'undefined' to the payload
61706206 const payload_ptr = try cg.buildPointerOffset(err_union, @as(u32, @intCast(errUnionPayloadOffset(pl_ty, zcu))), .new);
......@@ -6205,18 +6241,18 @@ fn isNull(cg: *CodeGen, operand: WValue, op_ty: Type, opcode: std.wasm.Opcode, o
62056241 const offset = std.math.cast(u32, payload_ty.abiSize(zcu)) orelse {
62066242 return cg.fail("Optional type {f} too big to fit into stack frame", .{optional_ty.fmt(pt)});
62076243 };
6208 try cg.addMemArg(.i32_load8_u, .{ .offset = operand.offset() + offset, .alignment = 1 });
6244 try cg.addMemArg(.i32_load8_u, .{ .offset = operand.offset() + offset, .alignment = .@"1" });
62096245 }
62106246 } else if (payload_ty.isSlice(zcu)) {
62116247 switch (cg.ptr_size) {
6212 .wasm32 => try cg.addMemArg(.i32_load, .{ .offset = operand.offset(), .alignment = 4 }),
6213 .wasm64 => try cg.addMemArg(.i64_load, .{ .offset = operand.offset(), .alignment = 8 }),
6248 .wasm32 => try cg.addMemArg(.i32_load, .{ .offset = operand.offset(), .alignment = .@"4" }),
6249 .wasm64 => try cg.addMemArg(.i64_load, .{ .offset = operand.offset(), .alignment = .@"8" }),
62146250 }
62156251 } else {
62166252 if (op_kind == .ptr) {
62176253 try cg.addMemArg(.i32_load, .{
62186254 .offset = operand.offset(),
6219 .alignment = 4,
6255 .alignment = .@"4",
62206256 });
62216257 }
62226258 }
......@@ -6245,7 +6281,7 @@ fn airOptionalPayload(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
62456281 break :result try cg.buildPointerOffset(operand, 0, .new);
62466282 }
62476283
6248 break :result try cg.load(operand, payload_ty, 0);
6284 break :result try cg.load(operand, payload_ty, .{});
62496285 };
62506286 return cg.finishAir(inst, result, &.{ty_op.operand});
62516287}
......@@ -6285,7 +6321,7 @@ fn airOptionalPayloadPtrSet(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void
62856321
62866322 try cg.emitWValue(operand);
62876323 try cg.addImm32(1);
6288 try cg.addMemArg(.i32_store8, .{ .offset = operand.offset() + offset, .alignment = 1 });
6324 try cg.addMemArg(.i32_store8, .{ .offset = operand.offset() + offset, .alignment = .@"1" });
62896325
62906326 const result = try cg.buildPointerOffset(operand, 0, .new);
62916327 return cg.finishAir(inst, result, &.{ty_op.operand});
......@@ -6302,7 +6338,7 @@ fn airWrapOptional(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
63026338 const non_null_bit = try cg.allocStack(Type.u1);
63036339 try cg.emitWValue(non_null_bit);
63046340 try cg.addImm32(1);
6305 try cg.addMemArg(.i32_store8, .{ .offset = non_null_bit.offset(), .alignment = 1 });
6341 try cg.addMemArg(.i32_store8, .{ .offset = non_null_bit.offset(), .alignment = .@"1" });
63066342 break :result non_null_bit;
63076343 }
63086344
......@@ -6319,10 +6355,10 @@ fn airWrapOptional(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
63196355 const result_ptr = try cg.allocStack(op_ty);
63206356 try cg.emitWValue(result_ptr);
63216357 try cg.addImm32(1);
6322 try cg.addMemArg(.i32_store8, .{ .offset = result_ptr.offset() + offset, .alignment = 1 });
6358 try cg.addMemArg(.i32_store8, .{ .offset = result_ptr.offset() + offset, .alignment = .@"1" });
63236359
63246360 const payload_ptr = try cg.buildPointerOffset(result_ptr, 0, .new);
6325 try cg.store(payload_ptr, operand, payload_ty, 0);
6361 try cg.store(payload_ptr, operand, payload_ty, .{});
63266362 break :result result_ptr;
63276363 };
63286364
......@@ -6338,8 +6374,8 @@ fn airSlice(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
63386374 const slice_ty = cg.typeOfIndex(inst);
63396375
63406376 const slice = try cg.allocStack(slice_ty);
6341 try cg.store(slice, lhs, Type.usize, 0);
6342 try cg.store(slice, rhs, Type.usize, cg.ptrSize());
6377 try cg.store(slice, lhs, .usize, .{});
6378 try cg.store(slice, rhs, .usize, .{ .offset = cg.ptrSize() });
63436379
63446380 return cg.finishAir(inst, slice, &.{ bin_op.lhs, bin_op.rhs });
63456381}
......@@ -6362,7 +6398,7 @@ fn airSliceElemVal(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
63626398 const elem_size = elem_ty.abiSize(zcu);
63636399
63646400 // load pointer onto stack
6365 _ = try cg.load(slice, Type.usize, 0);
6401 _ = try cg.load(slice, .usize, .{});
63666402
63676403 // calculate index into slice
63686404 try cg.emitWValue(index);
......@@ -6370,7 +6406,7 @@ fn airSliceElemVal(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
63706406 try cg.addTag(.i32_mul);
63716407 try cg.addTag(.i32_add);
63726408
6373 const elem_result = try cg.load(.stack, elem_ty, 0);
6409 const elem_result = try cg.load(.stack, elem_ty, .{});
63746410
63756411 return cg.finishAir(inst, elem_result, &.{ bin_op.lhs, bin_op.rhs });
63766412}
......@@ -6386,7 +6422,7 @@ fn airSliceElemPtr(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
63866422 const slice = try cg.resolveInst(bin_op.lhs);
63876423 const index = try cg.resolveInst(bin_op.rhs);
63886424
6389 _ = try cg.load(slice, Type.usize, 0);
6425 _ = try cg.load(slice, .usize, .{});
63906426
63916427 // calculate index into slice
63926428 try cg.emitWValue(index);
......@@ -6404,12 +6440,12 @@ fn airSlicePtr(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
64046440}
64056441
64066442fn slicePtr(cg: *CodeGen, operand: WValue) InnerError!WValue {
6407 const ptr = try cg.load(operand, Type.usize, 0);
6443 const ptr = try cg.load(operand, .usize, .{});
64086444 return ptr.toLocal(cg, Type.usize);
64096445}
64106446
64116447fn sliceLen(cg: *CodeGen, operand: WValue) InnerError!WValue {
6412 const len = try cg.load(operand, Type.usize, cg.ptrSize());
6448 const len = try cg.load(operand, .usize, .{ .offset = cg.ptrSize() });
64136449 return len.toLocal(cg, Type.usize);
64146450}
64156451
......@@ -6424,11 +6460,11 @@ fn airArrayToSlice(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
64246460 // create a slice on the stack
64256461 const slice_local = try cg.allocStack(slice_ty);
64266462
6427 try cg.store(slice_local, operand, Type.usize, 0);
6463 try cg.store(slice_local, operand, .usize, .{});
64286464
64296465 // store the length of the array in the slice
64306466 const array_len: u32 = @intCast(array_ty.arrayLen(zcu));
6431 try cg.store(slice_local, .{ .imm32 = array_len }, Type.usize, cg.ptrSize());
6467 try cg.store(slice_local, .{ .imm32 = array_len }, .usize, .{ .offset = cg.ptrSize() });
64326468
64336469 return cg.finishAir(inst, slice_local, &.{ty_op.operand});
64346470}
......@@ -6445,7 +6481,7 @@ fn airPtrElemVal(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
64456481
64466482 // load pointer onto the stack
64476483 if (ptr_ty.isSlice(zcu)) {
6448 _ = try cg.load(ptr, Type.usize, 0);
6484 _ = try cg.load(ptr, .usize, .{});
64496485 } else {
64506486 try cg.lowerToStack(ptr);
64516487 }
......@@ -6456,7 +6492,7 @@ fn airPtrElemVal(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
64566492 try cg.addTag(.i32_mul);
64576493 try cg.addTag(.i32_add);
64586494
6459 const elem_result = try cg.load(.stack, elem_ty, 0);
6495 const elem_result = try cg.load(.stack, elem_ty, .{});
64606496
64616497 return cg.finishAir(inst, elem_result, &.{ bin_op.lhs, bin_op.rhs });
64626498}
......@@ -6475,7 +6511,7 @@ fn airPtrElemPtr(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
64756511
64766512 // load pointer onto the stack
64776513 if (ptr_ty.isSlice(zcu)) {
6478 _ = try cg.load(ptr, Type.usize, 0);
6514 _ = try cg.load(ptr, .usize, .{});
64796515 } else {
64806516 try cg.lowerToStack(ptr);
64816517 }
......@@ -6645,7 +6681,7 @@ fn memset(cg: *CodeGen, elem_ty: Type, ptr: WValue, len: WValue, value: WValue)
66456681 try cg.addLabel(.br_if, 1); // jump out of loop into outer block (finished)
66466682
66476683 // store the value at the current position of the pointer
6648 try cg.store(new_ptr, value, elem_ty, 0);
6684 try cg.store(new_ptr, value, elem_ty, .{});
66496685
66506686 // move the pointer to the next element
66516687 try cg.emitWValue(new_ptr);
......@@ -6708,7 +6744,7 @@ fn airArrayElemVal(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
67086744 },
67096745 else => {
67106746 const stack_vec = try cg.allocStack(array_ty);
6711 try cg.store(stack_vec, array, array_ty, 0);
6747 try cg.store(stack_vec, array, array_ty, .{});
67126748
67136749 // Is a non-unrolled vector (v128)
67146750 try cg.lowerToStack(stack_vec);
......@@ -6723,7 +6759,7 @@ fn airArrayElemVal(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
67236759 const result = if (isByRef(elem_ty, zcu, cg.target))
67246760 .stack
67256761 else
6726 try cg.load(.stack, elem_ty, 0);
6762 try cg.load(.stack, elem_ty, .{});
67276763 return cg.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });
67286764}
67296765
......@@ -6750,10 +6786,11 @@ fn airSplat(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
67506786 try cg.emitWValue(operand);
67516787 const extra_index: u32 = @intCast(cg.mir_extra.items.len);
67526788 // stores as := opcode, offset, alignment (opcode::memarg)
6753 try cg.mir_extra.appendSlice(cg.gpa, &[_]u32{
6754 opcode,
6755 operand.offset(),
6756 @intCast(elem_ty.abiAlignment(zcu).toByteUnits().?),
6789 try cg.mir_extra.ensureUnusedCapacity(cg.gpa, 4);
6790 cg.mir_extra.appendAssumeCapacity(opcode);
6791 _ = try cg.addExtraAssumeCapacity(Mir.MemArg{
6792 .offset = operand.offset(),
6793 .alignment = elem_ty.abiAlignment(zcu).toStdMem(),
67576794 });
67586795 try cg.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } });
67596796 return cg.finishAir(inst, .stack, &.{ty_op.operand});
......@@ -6782,7 +6819,7 @@ fn airSplat(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
67826819 var index: usize = 0;
67836820 var offset: u32 = 0;
67846821 while (index < vector_len) : (index += 1) {
6785 try cg.store(result, operand, elem_ty, offset);
6822 try cg.store(result, operand, elem_ty, .{ .offset = offset });
67866823 offset += elem_byte_size;
67876824 }
67886825
......@@ -6821,10 +6858,10 @@ fn airShuffleOne(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
68216858 for (mask, 0..) |mask_elem, out_idx| {
68226859 try cg.emitWValue(dest_alloc);
68236860 const elem_val = switch (mask_elem.unwrap()) {
6824 .elem => |idx| try cg.load(operand, elem_ty, @intCast(elem_size * idx)),
6861 .elem => |idx| try cg.load(operand, elem_ty, .{ .offset = elem_size * idx }),
68256862 .value => |val| try cg.lowerConstant(.fromInterned(val)),
68266863 };
6827 try cg.store(.stack, elem_val, elem_ty, @intCast(dest_alloc.offset() + elem_size * out_idx));
6864 try cg.store(.stack, elem_val, elem_ty, .{ .offset = dest_alloc.offset() + elem_size * out_idx });
68286865 }
68296866 return cg.finishAir(inst, dest_alloc, &.{unwrapped.operand});
68306867}
......@@ -6889,11 +6926,11 @@ fn airShuffleTwo(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
68896926 for (mask, 0..) |mask_elem, out_idx| {
68906927 try cg.emitWValue(dest_alloc);
68916928 const elem_val = switch (mask_elem.unwrap()) {
6892 .a_elem => |idx| try cg.load(operand_a, elem_ty, @intCast(elem_size * idx)),
6893 .b_elem => |idx| try cg.load(operand_b, elem_ty, @intCast(elem_size * idx)),
6929 .a_elem => |idx| try cg.load(operand_a, elem_ty, .{ .offset = elem_size * idx }),
6930 .b_elem => |idx| try cg.load(operand_b, elem_ty, .{ .offset = elem_size * idx }),
68946931 .undef => try cg.emitUndefined(elem_ty),
68956932 };
6896 try cg.store(.stack, elem_val, elem_ty, @intCast(dest_alloc.offset() + elem_size * out_idx));
6933 try cg.store(.stack, elem_val, elem_ty, .{ .offset = dest_alloc.offset() + elem_size * out_idx });
68976934 }
68986935 return cg.finishAir(inst, dest_alloc, &.{ unwrapped.operand_a, unwrapped.operand_b });
68996936}
......@@ -6931,7 +6968,7 @@ fn airAggregateInit(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
69316968 const offset = try cg.buildPointerOffset(result, 0, .new);
69326969 for (elements, 0..) |elem, elem_index| {
69336970 const elem_val = try cg.resolveInst(elem);
6934 try cg.store(offset, elem_val, elem_ty, 0);
6971 try cg.store(offset, elem_val, elem_ty, .{});
69356972
69366973 if (elem_index < elements.len - 1 or sentinel != null) {
69376974 _ = try cg.buildPointerOffset(offset, elem_size, .modify);
......@@ -6939,18 +6976,18 @@ fn airAggregateInit(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
69396976 }
69406977 if (sentinel) |s| {
69416978 const val = try cg.resolveValue(s);
6942 try cg.store(offset, val, elem_ty, 0);
6979 try cg.store(offset, val, elem_ty, .{});
69436980 }
69446981 } else {
69456982 var offset: u32 = 0;
69466983 for (elements) |elem| {
69476984 const elem_val = try cg.resolveInst(elem);
6948 try cg.store(result, elem_val, elem_ty, offset);
6985 try cg.store(result, elem_val, elem_ty, .{ .offset = offset });
69496986 offset += elem_size;
69506987 }
69516988 if (sentinel) |s| {
69526989 const val = try cg.resolveValue(s);
6953 try cg.store(result, val, elem_ty, offset);
6990 try cg.store(result, val, elem_ty, .{ .offset = offset });
69546991 }
69556992 }
69566993 break :result_value result;
......@@ -6967,7 +7004,7 @@ fn airAggregateInit(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
69677004 const offset = try cg.buildPointerOffset(result, field_offset, .new);
69687005
69697006 const value = try cg.resolveInst(elem);
6970 try cg.store(offset, value, elem_ty, 0);
7007 try cg.store(offset, value, elem_ty, .{});
69717008 }
69727009
69737010 break :result_value result;
......@@ -7016,22 +7053,22 @@ fn airUnionInit(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
70167053 if (layout.tag_align.compare(.gte, layout.payload_align)) {
70177054 if (isByRef(field_ty, zcu, cg.target)) {
70187055 const payload_ptr = try cg.buildPointerOffset(result_ptr, layout.tag_size, .new);
7019 try cg.store(payload_ptr, payload, field_ty, 0);
7056 try cg.store(payload_ptr, payload, field_ty, .{});
70207057 } else {
7021 try cg.store(result_ptr, payload, field_ty, @intCast(layout.tag_size));
7058 try cg.store(result_ptr, payload, field_ty, .{ .offset = layout.tag_size });
70227059 }
70237060
70247061 if (layout.tag_size > 0) {
7025 try cg.store(result_ptr, tag_int, .fromInterned(union_obj.enum_tag_type), 0);
7062 try cg.store(result_ptr, tag_int, .fromInterned(union_obj.enum_tag_type), .{});
70267063 }
70277064 } else {
7028 try cg.store(result_ptr, payload, field_ty, 0);
7065 try cg.store(result_ptr, payload, field_ty, .{});
70297066 if (layout.tag_size > 0) {
70307067 try cg.store(
70317068 result_ptr,
70327069 tag_int,
70337070 .fromInterned(union_obj.enum_tag_type),
7034 @intCast(layout.payload_size),
7071 .{ .offset = layout.payload_size },
70357072 );
70367073 }
70377074 }
......@@ -7077,7 +7114,7 @@ fn airSetUnionTag(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
70777114 const union_ptr = try cg.resolveInst(bin_op.lhs);
70787115 const new_tag = try cg.resolveInst(bin_op.rhs);
70797116 if (layout.payload_size == 0) {
7080 try cg.store(union_ptr, new_tag, tag_ty, 0);
7117 try cg.store(union_ptr, new_tag, tag_ty, .{});
70817118 return cg.finishAir(inst, .none, &.{ bin_op.lhs, bin_op.rhs });
70827119 }
70837120
......@@ -7086,7 +7123,7 @@ fn airSetUnionTag(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
70867123 const offset: u32 = if (layout.tag_align.compare(.lt, layout.payload_align)) blk: {
70877124 break :blk @intCast(layout.payload_size);
70887125 } else 0;
7089 try cg.store(union_ptr, new_tag, tag_ty, offset);
7126 try cg.store(union_ptr, new_tag, tag_ty, .{ .offset = offset });
70907127 return cg.finishAir(inst, .none, &.{ bin_op.lhs, bin_op.rhs });
70917128}
70927129
......@@ -7106,7 +7143,7 @@ fn airGetUnionTag(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
71067143 @intCast(layout.payload_size)
71077144 else
71087145 0;
7109 const result = try cg.load(operand, tag_ty, offset);
7146 const result = try cg.load(operand, tag_ty, .{ .offset = offset });
71107147 return cg.finishAir(inst, result, &.{ty_op.operand});
71117148}
71127149
......@@ -7122,8 +7159,8 @@ fn airErrUnionPayloadPtrSet(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void
71227159 try cg.store(
71237160 operand,
71247161 .{ .imm32 = 0 },
7125 Type.anyerror,
7126 @intCast(errUnionErrorOffset(payload_ty, zcu)),
7162 .anyerror,
7163 .{ .offset = errUnionErrorOffset(payload_ty, zcu) },
71277164 );
71287165
71297166 const result = result: {
......@@ -7360,7 +7397,7 @@ fn lowerTry(
73607397 const err_offset: u32 = @intCast(errUnionErrorOffset(pl_ty, zcu));
73617398 try cg.addMemArg(.i32_load16_u, .{
73627399 .offset = err_union.offset() + err_offset,
7363 .alignment = @intCast(Type.anyerror.abiAlignment(zcu).toByteUnits().?),
7400 .alignment = Type.anyerror.abiAlignment(zcu).toStdMem(),
73647401 });
73657402 }
73667403 try cg.addTag(.i32_eqz);
......@@ -7384,7 +7421,7 @@ fn lowerTry(
73847421 if (operand_is_ptr or isByRef(pl_ty, zcu, cg.target)) {
73857422 return buildPointerOffset(cg, err_union, pl_offset, .new);
73867423 }
7387 const payload = try cg.load(err_union, pl_ty, pl_offset);
7424 const payload = try cg.load(err_union, pl_ty, .{ .offset = pl_offset });
73887425 return payload.toLocal(cg, pl_ty);
73897426}
73907427
......@@ -7588,7 +7625,7 @@ fn airCmpxchg(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
75887625 else => |size| return cg.fail("TODO: implement `@cmpxchg` for types with abi size '{d}'", .{size}),
75897626 }, .{
75907627 .offset = ptr_operand.offset(),
7591 .alignment = @intCast(ty.abiAlignment(zcu).toByteUnits().?),
7628 .alignment = ty.abiAlignment(zcu).toStdMem(),
75927629 });
75937630 try cg.addLocal(.local_tee, val_local.local.value);
75947631 _ = try cg.intCmp(int_ty, .eq, .stack, expected_val);
......@@ -7598,7 +7635,7 @@ fn airCmpxchg(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
75987635 if (ty.abiSize(zcu) > 8) {
75997636 return cg.fail("TODO: Implement `@cmpxchg` for types larger than abi size of 8 bytes", .{});
76007637 }
7601 const ptr_val = try WValue.toLocal(try cg.load(ptr_operand, ty, 0), cg, ty);
7638 const ptr_val = try WValue.toLocal(try cg.load(ptr_operand, ty, .{}), cg, ty);
76027639
76037640 try cg.lowerToStack(ptr_operand);
76047641 try cg.lowerToStack(new_val);
......@@ -7606,7 +7643,7 @@ fn airCmpxchg(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
76067643 _ = try cg.intCmp(int_ty, .eq, ptr_val, expected_val);
76077644 try cg.addLocal(.local_tee, cmp_result.local.value);
76087645 try cg.addTag(.select);
7609 try cg.store(.stack, .stack, ty, 0);
7646 try cg.store(.stack, .stack, ty, .{});
76107647
76117648 break :val ptr_val;
76127649 };
......@@ -7619,8 +7656,8 @@ fn airCmpxchg(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
76197656 try cg.addTag(.i32_and);
76207657 const and_result = try WValue.toLocal(.stack, cg, Type.bool);
76217658 const result_ptr = try cg.allocStack(result_ty);
7622 try cg.store(result_ptr, and_result, Type.bool, @as(u32, @intCast(ty.abiSize(zcu))));
7623 try cg.store(result_ptr, ptr_val, ty, 0);
7659 try cg.store(result_ptr, and_result, .bool, .{ .offset = ty.abiSize(zcu) });
7660 try cg.store(result_ptr, ptr_val, ty, .{});
76247661 break :val result_ptr;
76257662 } else val: {
76267663 try cg.addImm32(0);
......@@ -7650,10 +7687,10 @@ fn airAtomicLoad(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
76507687 try cg.emitWValue(ptr);
76517688 try cg.addAtomicMemArg(tag, .{
76527689 .offset = ptr.offset(),
7653 .alignment = @intCast(ty.abiAlignment(zcu).toByteUnits().?),
7690 .alignment = ty.abiAlignment(zcu).toStdMem(),
76547691 });
76557692 } else {
7656 _ = try cg.load(ptr, ty, 0);
7693 _ = try cg.load(ptr, ty, .{});
76577694 }
76587695
76597696 return cg.finishAir(inst, .stack, &.{atomic_load.ptr});
......@@ -7676,7 +7713,7 @@ fn airAtomicRmw(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
76767713 .Min,
76777714 .Nand,
76787715 => {
7679 const tmp = try cg.load(ptr, ty, 0);
7716 const tmp = try cg.load(ptr, ty, .{});
76807717 const value = try tmp.toLocal(cg, ty);
76817718
76827719 // create a loop to cmpxchg the new value
......@@ -7710,7 +7747,7 @@ fn airAtomicRmw(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
77107747 },
77117748 .{
77127749 .offset = ptr.offset(),
7713 .alignment = @intCast(ty.abiAlignment(zcu).toByteUnits().?),
7750 .alignment = ty.abiAlignment(zcu).toStdMem(),
77147751 },
77157752 );
77167753 const select_res = try cg.allocLocal(ty);
......@@ -7770,18 +7807,18 @@ fn airAtomicRmw(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
77707807 };
77717808 try cg.addAtomicMemArg(tag, .{
77727809 .offset = ptr.offset(),
7773 .alignment = @intCast(ty.abiAlignment(zcu).toByteUnits().?),
7810 .alignment = ty.abiAlignment(zcu).toStdMem(),
77747811 });
77757812 return cg.finishAir(inst, .stack, &.{ pl_op.operand, extra.operand });
77767813 },
77777814 }
77787815 } else {
7779 const loaded = try cg.load(ptr, ty, 0);
7816 const loaded = try cg.load(ptr, ty, .{});
77807817 const result = try loaded.toLocal(cg, ty);
77817818
77827819 switch (op) {
77837820 .Xchg => {
7784 try cg.store(ptr, operand, ty, 0);
7821 try cg.store(ptr, operand, ty, .{});
77857822 },
77867823 .Add,
77877824 .Sub,
......@@ -7794,7 +7831,7 @@ fn airAtomicRmw(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
77947831 .Sub => try cg.floatSub(float_ty, result, operand),
77957832 else => unreachable,
77967833 };
7797 try cg.store(.stack, .stack, ty, ptr.offset());
7834 try cg.store(.stack, .stack, ty, .{ .offset = ptr.offset() });
77987835 } else {
77997836 const int_ty: IntType = .fromType(cg, ty);
78007837 try cg.emitWValue(ptr);
......@@ -7804,7 +7841,7 @@ fn airAtomicRmw(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
78047841 else => unreachable,
78057842 };
78067843 _ = try cg.intWrap(int_ty, .stack);
7807 try cg.store(.stack, .stack, ty, ptr.offset());
7844 try cg.store(.stack, .stack, ty, .{ .offset = ptr.offset() });
78087845 }
78097846 },
78107847 .And,
......@@ -7819,7 +7856,7 @@ fn airAtomicRmw(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
78197856 .Xor => try cg.intXor(int_ty, result, operand),
78207857 else => unreachable,
78217858 };
7822 try cg.store(.stack, .stack, ty, ptr.offset());
7859 try cg.store(.stack, .stack, ty, .{ .offset = ptr.offset() });
78237860 },
78247861 .Max,
78257862 .Min,
......@@ -7831,7 +7868,7 @@ fn airAtomicRmw(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
78317868 try cg.emitWValue(operand);
78327869 _ = try cg.floatCmp(float_ty, if (op == .Max) .gt else .lt, result, operand);
78337870 try cg.addTag(.select);
7834 try cg.store(.stack, .stack, ty, ptr.offset());
7871 try cg.store(.stack, .stack, ty, .{ .offset = ptr.offset() });
78357872 } else {
78367873 const int_ty: IntType = .fromType(cg, ty);
78377874 try cg.emitWValue(ptr);
......@@ -7839,7 +7876,7 @@ fn airAtomicRmw(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
78397876 try cg.emitWValue(operand);
78407877 _ = try cg.intCmp(int_ty, if (op == .Max) .gt else .lt, result, operand);
78417878 try cg.addTag(.select);
7842 try cg.store(.stack, .stack, ty, ptr.offset());
7879 try cg.store(.stack, .stack, ty, .{ .offset = ptr.offset() });
78437880 }
78447881 },
78457882 .Nand => {
......@@ -7854,7 +7891,7 @@ fn airAtomicRmw(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
78547891 return cg.fail("TODO: `@atomicRmw` with operator `Nand` for types larger than 64 bits", .{});
78557892 }
78567893 _ = try cg.intXor(int_ty, and_res, .stack);
7857 try cg.store(.stack, .stack, ty, ptr.offset());
7894 try cg.store(.stack, .stack, ty, .{ .offset = ptr.offset() });
78587895 },
78597896 }
78607897
......@@ -7883,10 +7920,10 @@ fn airAtomicStore(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
78837920 try cg.lowerToStack(operand);
78847921 try cg.addAtomicMemArg(tag, .{
78857922 .offset = ptr.offset(),
7886 .alignment = @intCast(ty.abiAlignment(zcu).toByteUnits().?),
7923 .alignment = ty.abiAlignment(zcu).toStdMem(),
78877924 });
78887925 } else {
7889 try cg.store(ptr, operand, ty, 0);
7926 try cg.store(ptr, operand, ty, .{});
78907927 }
78917928
78927929 return cg.finishAir(inst, .none, &.{ bin_op.lhs, bin_op.rhs });
src/codegen/wasm/Emit.zig+1-3
......@@ -988,9 +988,7 @@ pub fn lower(emit: *Emit) Error!void {
988988/// Asserts 20 unused capacity.
989989fn encodeMemArg(code: *ArrayList(u8), mem_arg: Mir.MemArg) void {
990990 assert(code.unusedCapacitySlice().len >= 20);
991 // Wasm encodes alignment as power of 2, rather than natural alignment.
992 const encoded_alignment = @ctz(mem_arg.alignment);
993 writeUleb128(code, encoded_alignment);
991 writeUleb128(code, @backingInt(mem_arg.alignment));
994992 writeUleb128(code, mem_arg.offset);
995993}
996994
src/codegen/wasm/Mir.zig+9-2
......@@ -694,11 +694,18 @@ pub fn extraData(self: *const Mir, comptime T: type, index: usize) struct { data
694694 inline for (info.field_names, info.field_types) |field_name, field_type| {
695695 @field(result, field_name) = switch (field_type) {
696696 u32 => self.extra[i],
697 u64 => value: {
698 const lo = @as(u64, self.extra[i]);
699 const hi = @as(u64, self.extra[i + 1]) << 32;
700 i += 1;
701 break :value hi | lo;
702 },
697703 i32 => @bitCast(self.extra[i]),
698704 Wasm.UavsObjIndex,
699705 Wasm.UavsExeIndex,
700706 InternPool.Nav.Index,
701707 InternPool.Index,
708 std.mem.Alignment,
702709 => @fromBackingInt(@intCast(self.extra[i])),
703710 else => @compileError("Unsupported field type " ++ @typeName(field_type)),
704711 };
......@@ -747,8 +754,8 @@ pub const Float64 = struct {
747754};
748755
749756pub const MemArg = struct {
750 offset: u32,
751 alignment: u32,
757 offset: u64,
758 alignment: std.mem.Alignment,
752759};
753760
754761pub const UavRefOff = struct {
src/codegen/wasm/assembly.zig+4-4
......@@ -679,20 +679,20 @@ fn parseMemArg(cg: *CodeGen, inst: []const u8, word_it: *mem.TokenIterator(u8, .
679679 const offset_str = oa[0];
680680 const alignment_str = oa[1];
681681
682 const offset = std.fmt.parseInt(i32, offset_str, 0) catch {
682 const offset = std.fmt.parseInt(i64, offset_str, 0) catch {
683683 return cg.fail("Malformed assembly, malformed offset \"{s}\"", .{offset_str});
684684 };
685685 const alignment_p2 = std.fmt.parseInt(u5, alignment_str, 0) catch {
686686 return cg.fail("Malformed assembly, malformed offset \"{s}\"", .{alignment_str});
687687 };
688688
689 return .{ .offset = @bitCast(offset), .alignment = @as(u32, 1) << alignment_p2 };
689 return .{ .offset = @bitCast(offset), .alignment = @fromBackingInt(@intCast(alignment_p2)) };
690690 } else {
691691 const offset_str = mem_arg_str;
692 const offset = std.fmt.parseInt(i32, offset_str, 0) catch {
692 const offset = std.fmt.parseInt(i64, offset_str, 0) catch {
693693 return cg.fail("Malformed assembly, malformed offset \"{s}\"", .{offset_str});
694694 };
695 return .{ .offset = @bitCast(offset), .alignment = 1 };
695 return .{ .offset = @bitCast(offset), .alignment = .@"1" };
696696 }
697697}
698698