authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-12-21 15:18:50-05:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-01-16 20:42:08-05:00
logb9c44007762b9b302c263a89b7c2e8a8470b97ec
tree6cea52f080dd0a4df1bd7bc9ee007920b0965ecd
parentc4b93555b0d2c56cbbd85f77bb387ebb43d23369

x86_64: implement fallback for pcmpeqq


8 files changed, 720 insertions(+), 605 deletions(-)

src/Type.zig+14-22
...@@ -962,7 +962,6 @@ pub fn abiAlignmentInner(...@@ -962,7 +962,6 @@ pub fn abiAlignmentInner(
962) SemaError!AbiAlignmentInner {962) SemaError!AbiAlignmentInner {
963 const pt = strat.pt(zcu, tid);963 const pt = strat.pt(zcu, tid);
964 const target = zcu.getTarget();964 const target = zcu.getTarget();
965 const use_llvm = zcu.comp.config.use_llvm;
966 const ip = &zcu.intern_pool;965 const ip = &zcu.intern_pool;
967966
968 switch (ty.toIntern()) {967 switch (ty.toIntern()) {
...@@ -970,7 +969,7 @@ pub fn abiAlignmentInner(...@@ -970,7 +969,7 @@ pub fn abiAlignmentInner(
970 else => switch (ip.indexToKey(ty.toIntern())) {969 else => switch (ip.indexToKey(ty.toIntern())) {
971 .int_type => |int_type| {970 .int_type => |int_type| {
972 if (int_type.bits == 0) return .{ .scalar = .@"1" };971 if (int_type.bits == 0) return .{ .scalar = .@"1" };
973 return .{ .scalar = intAbiAlignment(int_type.bits, target, use_llvm) };972 return .{ .scalar = intAbiAlignment(int_type.bits, target) };
974 },973 },
975 .ptr_type, .anyframe_type => {974 .ptr_type, .anyframe_type => {
976 return .{ .scalar = ptrAbiAlignment(target) };975 return .{ .scalar = ptrAbiAlignment(target) };
...@@ -1023,7 +1022,7 @@ pub fn abiAlignmentInner(...@@ -1023,7 +1022,7 @@ pub fn abiAlignmentInner(
1023 .error_set_type, .inferred_error_set_type => {1022 .error_set_type, .inferred_error_set_type => {
1024 const bits = zcu.errorSetBits();1023 const bits = zcu.errorSetBits();
1025 if (bits == 0) return .{ .scalar = .@"1" };1024 if (bits == 0) return .{ .scalar = .@"1" };
1026 return .{ .scalar = intAbiAlignment(bits, target, use_llvm) };1025 return .{ .scalar = intAbiAlignment(bits, target) };
1027 },1026 },
10281027
1029 // represents machine code; not a pointer1028 // represents machine code; not a pointer
...@@ -1036,7 +1035,7 @@ pub fn abiAlignmentInner(...@@ -1036,7 +1035,7 @@ pub fn abiAlignmentInner(
10361035
1037 .usize,1036 .usize,
1038 .isize,1037 .isize,
1039 => return .{ .scalar = intAbiAlignment(target.ptrBitWidth(), target, use_llvm) },1038 => return .{ .scalar = intAbiAlignment(target.ptrBitWidth(), target) },
10401039
1041 .c_char => return .{ .scalar = cTypeAlign(target, .char) },1040 .c_char => return .{ .scalar = cTypeAlign(target, .char) },
1042 .c_short => return .{ .scalar = cTypeAlign(target, .short) },1041 .c_short => return .{ .scalar = cTypeAlign(target, .short) },
...@@ -1067,7 +1066,7 @@ pub fn abiAlignmentInner(...@@ -1067,7 +1066,7 @@ pub fn abiAlignmentInner(
1067 .anyerror, .adhoc_inferred_error_set => {1066 .anyerror, .adhoc_inferred_error_set => {
1068 const bits = zcu.errorSetBits();1067 const bits = zcu.errorSetBits();
1069 if (bits == 0) return .{ .scalar = .@"1" };1068 if (bits == 0) return .{ .scalar = .@"1" };
1070 return .{ .scalar = intAbiAlignment(bits, target, use_llvm) };1069 return .{ .scalar = intAbiAlignment(bits, target) };
1071 },1070 },
10721071
1073 .void,1072 .void,
...@@ -1291,7 +1290,6 @@ pub fn abiSizeInner(...@@ -1291,7 +1290,6 @@ pub fn abiSizeInner(
1291 tid: strat.Tid(),1290 tid: strat.Tid(),
1292) SemaError!AbiSizeInner {1291) SemaError!AbiSizeInner {
1293 const target = zcu.getTarget();1292 const target = zcu.getTarget();
1294 const use_llvm = zcu.comp.config.use_llvm;
1295 const ip = &zcu.intern_pool;1293 const ip = &zcu.intern_pool;
12961294
1297 switch (ty.toIntern()) {1295 switch (ty.toIntern()) {
...@@ -1300,7 +1298,7 @@ pub fn abiSizeInner(...@@ -1300,7 +1298,7 @@ pub fn abiSizeInner(
1300 else => switch (ip.indexToKey(ty.toIntern())) {1298 else => switch (ip.indexToKey(ty.toIntern())) {
1301 .int_type => |int_type| {1299 .int_type => |int_type| {
1302 if (int_type.bits == 0) return .{ .scalar = 0 };1300 if (int_type.bits == 0) return .{ .scalar = 0 };
1303 return .{ .scalar = intAbiSize(int_type.bits, target, use_llvm) };1301 return .{ .scalar = intAbiSize(int_type.bits, target) };
1304 },1302 },
1305 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {1303 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
1306 .slice => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) * 2 },1304 .slice => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) * 2 },
...@@ -1362,7 +1360,7 @@ pub fn abiSizeInner(...@@ -1362,7 +1360,7 @@ pub fn abiSizeInner(
1362 .error_set_type, .inferred_error_set_type => {1360 .error_set_type, .inferred_error_set_type => {
1363 const bits = zcu.errorSetBits();1361 const bits = zcu.errorSetBits();
1364 if (bits == 0) return .{ .scalar = 0 };1362 if (bits == 0) return .{ .scalar = 0 };
1365 return .{ .scalar = intAbiSize(bits, target, use_llvm) };1363 return .{ .scalar = intAbiSize(bits, target) };
1366 },1364 },
13671365
1368 .error_union_type => |error_union_type| {1366 .error_union_type => |error_union_type| {
...@@ -1455,7 +1453,7 @@ pub fn abiSizeInner(...@@ -1455,7 +1453,7 @@ pub fn abiSizeInner(
1455 .anyerror, .adhoc_inferred_error_set => {1453 .anyerror, .adhoc_inferred_error_set => {
1456 const bits = zcu.errorSetBits();1454 const bits = zcu.errorSetBits();
1457 if (bits == 0) return .{ .scalar = 0 };1455 if (bits == 0) return .{ .scalar = 0 };
1458 return .{ .scalar = intAbiSize(bits, target, use_llvm) };1456 return .{ .scalar = intAbiSize(bits, target) };
1459 },1457 },
14601458
1461 .noreturn => unreachable,1459 .noreturn => unreachable,
...@@ -1609,11 +1607,11 @@ pub fn ptrAbiAlignment(target: Target) Alignment {...@@ -1609,11 +1607,11 @@ pub fn ptrAbiAlignment(target: Target) Alignment {
1609 return Alignment.fromNonzeroByteUnits(@divExact(target.ptrBitWidth(), 8));1607 return Alignment.fromNonzeroByteUnits(@divExact(target.ptrBitWidth(), 8));
1610}1608}
16111609
1612pub fn intAbiSize(bits: u16, target: Target, use_llvm: bool) u64 {1610pub fn intAbiSize(bits: u16, target: Target) u64 {
1613 return intAbiAlignment(bits, target, use_llvm).forward(@as(u16, @intCast((@as(u17, bits) + 7) / 8)));1611 return intAbiAlignment(bits, target).forward(@as(u16, @intCast((@as(u17, bits) + 7) / 8)));
1614}1612}
16151613
1616pub fn intAbiAlignment(bits: u16, target: Target, use_llvm: bool) Alignment {1614pub fn intAbiAlignment(bits: u16, target: Target) Alignment {
1617 return switch (target.cpu.arch) {1615 return switch (target.cpu.arch) {
1618 .x86 => switch (bits) {1616 .x86 => switch (bits) {
1619 0 => .none,1617 0 => .none,
...@@ -1632,19 +1630,16 @@ pub fn intAbiAlignment(bits: u16, target: Target, use_llvm: bool) Alignment {...@@ -1632,19 +1630,16 @@ pub fn intAbiAlignment(bits: u16, target: Target, use_llvm: bool) Alignment {
1632 9...16 => .@"2",1630 9...16 => .@"2",
1633 17...32 => .@"4",1631 17...32 => .@"4",
1634 33...64 => .@"8",1632 33...64 => .@"8",
1635 else => switch (target_util.zigBackend(target, use_llvm)) {1633 else => .@"16",
1636 .stage2_x86_64 => .@"8",
1637 else => .@"16",
1638 },
1639 },1634 },
1640 else => return Alignment.fromByteUnits(@min(1635 else => return Alignment.fromByteUnits(@min(
1641 std.math.ceilPowerOfTwoPromote(u16, @as(u16, @intCast((@as(u17, bits) + 7) / 8))),1636 std.math.ceilPowerOfTwoPromote(u16, @as(u16, @intCast((@as(u17, bits) + 7) / 8))),
1642 maxIntAlignment(target, use_llvm),1637 maxIntAlignment(target),
1643 )),1638 )),
1644 };1639 };
1645}1640}
16461641
1647pub fn maxIntAlignment(target: std.Target, use_llvm: bool) u16 {1642pub fn maxIntAlignment(target: std.Target) u16 {
1648 return switch (target.cpu.arch) {1643 return switch (target.cpu.arch) {
1649 .avr => 1,1644 .avr => 1,
1650 .msp430 => 2,1645 .msp430 => 2,
...@@ -1685,10 +1680,7 @@ pub fn maxIntAlignment(target: std.Target, use_llvm: bool) u16 {...@@ -1685,10 +1680,7 @@ pub fn maxIntAlignment(target: std.Target, use_llvm: bool) u16 {
1685 else => 8,1680 else => 8,
1686 },1681 },
16871682
1688 .x86_64 => switch (target_util.zigBackend(target, use_llvm)) {1683 .x86_64 => 16,
1689 .stage2_x86_64 => 8,
1690 else => 16,
1691 },
16921684
1693 // Even LLVMABIAlignmentOfType(i128) agrees on these targets.1685 // Even LLVMABIAlignmentOfType(i128) agrees on these targets.
1694 .x86,1686 .x86,
src/arch/x86_64/CodeGen.zig+628-548
...@@ -2097,11 +2097,11 @@ fn gen(self: *CodeGen) InnerError!void {...@@ -2097,11 +2097,11 @@ fn gen(self: *CodeGen) InnerError!void {
2097 // The address where to store the return value for the caller is in a2097 // The address where to store the return value for the caller is in a
2098 // register which the callee is free to clobber. Therefore, we purposely2098 // register which the callee is free to clobber. Therefore, we purposely
2099 // spill it to stack immediately.2099 // spill it to stack immediately.
2100 const frame_index = try self.allocFrameIndex(.initSpill(Type.usize, zcu));2100 const frame_index = try self.allocFrameIndex(.initSpill(.usize, zcu));
2101 try self.genSetMem(2101 try self.genSetMem(
2102 .{ .frame = frame_index },2102 .{ .frame = frame_index },
2103 0,2103 0,
2104 Type.usize,2104 .usize,
2105 self.ret_mcv.long.address().offset(-self.ret_mcv.short.indirect.off),2105 self.ret_mcv.long.address().offset(-self.ret_mcv.short.indirect.off),
2106 .{},2106 .{},
2107 );2107 );
...@@ -2122,13 +2122,7 @@ fn gen(self: *CodeGen) InnerError!void {...@@ -2122,13 +2122,7 @@ fn gen(self: *CodeGen) InnerError!void {
2122 info.reg_save_area = .{ .index = reg_save_area_fi };2122 info.reg_save_area = .{ .index = reg_save_area_fi };
21232123
2124 for (abi.SysV.c_abi_int_param_regs[info.gp_count..], info.gp_count..) |reg, reg_i|2124 for (abi.SysV.c_abi_int_param_regs[info.gp_count..], info.gp_count..) |reg, reg_i|
2125 try self.genSetMem(2125 try self.genSetMem(.{ .frame = reg_save_area_fi }, @intCast(reg_i * 8), .usize, .{ .register = reg }, .{});
2126 .{ .frame = reg_save_area_fi },
2127 @intCast(reg_i * 8),
2128 Type.usize,
2129 .{ .register = reg },
2130 .{},
2131 );
21322126
2133 try self.asmRegisterImmediate(.{ ._, .cmp }, .al, .u(info.fp_count));2127 try self.asmRegisterImmediate(.{ ._, .cmp }, .al, .u(info.fp_count));
2134 const skip_sse_reloc = try self.asmJccReloc(.na, undefined);2128 const skip_sse_reloc = try self.asmJccReloc(.na, undefined);
...@@ -2556,6 +2550,16 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -2556,6 +2550,16 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2556 .{ .ops = &.{ .xmm, .xmm, .{ .implicit = 0 } } },2550 .{ .ops = &.{ .xmm, .xmm, .{ .implicit = 0 } } },
2557 },2551 },
2558 },2552 },
2553 .{
2554 .required_features = &.{.sse},
2555 .mir_tag = .{ ._ps, mir_tag },
2556 .patterns = &.{
2557 .{ .ops = &.{ .xmm, .{ .implicit = 0 }, .mem } },
2558 .{ .ops = &.{ .xmm, .mem, .{ .implicit = 0 } } },
2559 .{ .ops = &.{ .xmm, .{ .implicit = 0 }, .xmm } },
2560 .{ .ops = &.{ .xmm, .xmm, .{ .implicit = 0 } } },
2561 },
2562 },
2559 .{2563 .{
2560 .required_features = &.{.mmx},2564 .required_features = &.{.mmx},
2561 .mir_tag = .{ .p_, mir_tag },2565 .mir_tag = .{ .p_, mir_tag },
...@@ -2615,6 +2619,16 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -2615,6 +2619,16 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2615 .{ .ops = &.{ .xmm_limb, .{ .implicit = 0 }, .xmm_limb } },2619 .{ .ops = &.{ .xmm_limb, .{ .implicit = 0 }, .xmm_limb } },
2616 },2620 },
2617 },2621 },
2622 .{
2623 .required_features = &.{.sse},
2624 .loop = .bitwise,
2625 .mir_tag = .{ ._ps, mir_tag },
2626 .patterns = &.{
2627 .{ .ops = &.{ .xmm_limb, .{ .implicit = 0 }, .mem_limb } },
2628 .{ .ops = &.{ .xmm_limb, .mem_limb, .{ .implicit = 0 } } },
2629 .{ .ops = &.{ .xmm_limb, .{ .implicit = 0 }, .xmm_limb } },
2630 },
2631 },
2618 .{2632 .{
2619 .required_features = &.{.mmx},2633 .required_features = &.{.mmx},
2620 .loop = .bitwise,2634 .loop = .bitwise,
...@@ -3070,11 +3084,58 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -3070,11 +3084,58 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3070 .{ .ops = &.{ .gpr_limb, .{ .implicit = 0 }, .gpr_limb } },3084 .{ .ops = &.{ .gpr_limb, .{ .implicit = 0 }, .gpr_limb } },
3071 },3085 },
3072 },3086 },
3073 }, .{ .invert_result = switch (cmp_op) {3087 .{
3074 .eq => false,3088 .scalar = .{ .any_int = .byte },
3075 .neq => true,3089 .clobbers = .{ .eflags = true },
3076 else => unreachable,3090 .loop = .elementwise,
3077 } }),3091 .mir_tag = .{ ._, .cmp },
3092 .patterns = &.{
3093 .{ .ops = &.{ .cc_mask_limb, .mem_limb, .gpr_limb } },
3094 .{ .ops = &.{ .cc_mask_limb, .gpr_limb, .mem_limb } },
3095 .{ .ops = &.{ .cc_mask_limb, .gpr_limb, .gpr_limb } },
3096 },
3097 },
3098 .{
3099 .scalar = .{ .any_int = .word },
3100 .clobbers = .{ .eflags = true },
3101 .loop = .elementwise,
3102 .mir_tag = .{ ._, .cmp },
3103 .patterns = &.{
3104 .{ .ops = &.{ .cc_mask_limb, .mem_limb, .gpr_limb } },
3105 .{ .ops = &.{ .cc_mask_limb, .gpr_limb, .mem_limb } },
3106 .{ .ops = &.{ .cc_mask_limb, .gpr_limb, .gpr_limb } },
3107 },
3108 },
3109 .{
3110 .scalar = .{ .any_int = .dword },
3111 .clobbers = .{ .eflags = true },
3112 .loop = .elementwise,
3113 .mir_tag = .{ ._, .cmp },
3114 .patterns = &.{
3115 .{ .ops = &.{ .cc_mask_limb, .mem_limb, .gpr_limb } },
3116 .{ .ops = &.{ .cc_mask_limb, .gpr_limb, .mem_limb } },
3117 .{ .ops = &.{ .cc_mask_limb, .gpr_limb, .gpr_limb } },
3118 },
3119 },
3120 .{
3121 .scalar = .{ .any_int = .qword },
3122 .clobbers = .{ .eflags = true },
3123 .loop = .elementwise,
3124 .mir_tag = .{ ._, .cmp },
3125 .patterns = &.{
3126 .{ .ops = &.{ .cc_mask_limb, .mem_limb, .gpr_limb } },
3127 .{ .ops = &.{ .cc_mask_limb, .gpr_limb, .mem_limb } },
3128 .{ .ops = &.{ .cc_mask_limb, .gpr_limb, .gpr_limb } },
3129 },
3130 },
3131 }, .{
3132 .cc = .e,
3133 .invert_result = switch (cmp_op) {
3134 .eq => false,
3135 .neq => true,
3136 else => unreachable,
3137 },
3138 }),
3078 .gte => unreachable,3139 .gte => unreachable,
3079 .gt => unreachable,3140 .gt => unreachable,
3080 }3141 }
...@@ -3242,7 +3303,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -3242,7 +3303,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3242 const opt_child_ty = opt_ty.optionalChild(zcu);3303 const opt_child_ty = opt_ty.optionalChild(zcu);
3243 const opt_child_abi_size: i32 = @intCast(opt_child_ty.abiSize(zcu));3304 const opt_child_abi_size: i32 = @intCast(opt_child_ty.abiSize(zcu));
3244 try ops[0].toOffset(opt_child_abi_size, cg);3305 try ops[0].toOffset(opt_child_abi_size, cg);
3245 var has_value = try cg.tempFromValue(Type.bool, .{ .immediate = 1 });3306 var has_value = try cg.tempFromValue(.bool, .{ .immediate = 1 });
3246 try ops[0].store(&has_value, cg);3307 try ops[0].store(&has_value, cg);
3247 try has_value.die(cg);3308 try has_value.die(cg);
3248 try ops[0].toOffset(-opt_child_abi_size, cg);3309 try ops[0].toOffset(-opt_child_abi_size, cg);
...@@ -3426,7 +3487,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -3426,7 +3487,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3426 .array_to_slice => if (use_old) try cg.airArrayToSlice(inst) else {3487 .array_to_slice => if (use_old) try cg.airArrayToSlice(inst) else {
3427 const ty_op = air_datas[@intFromEnum(inst)].ty_op;3488 const ty_op = air_datas[@intFromEnum(inst)].ty_op;
3428 var ops = try cg.tempsFromOperands(inst, .{ty_op.operand});3489 var ops = try cg.tempsFromOperands(inst, .{ty_op.operand});
3429 var len = try cg.tempFromValue(Type.usize, .{3490 var len = try cg.tempFromValue(.usize, .{
3430 .immediate = cg.typeOf(ty_op.operand).childType(zcu).arrayLen(zcu),3491 .immediate = cg.typeOf(ty_op.operand).childType(zcu).arrayLen(zcu),
3431 });3492 });
3432 try ops[0].toPair(&len, cg);3493 try ops[0].toPair(&len, cg);
...@@ -3510,17 +3571,11 @@ fn genLazy(self: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void {...@@ -3510,17 +3571,11 @@ fn genLazy(self: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void {
3510 try self.genSetMem(3571 try self.genSetMem(
3511 .{ .reg = ret_reg },3572 .{ .reg = ret_reg },
3512 0,3573 0,
3513 Type.usize,3574 .usize,
3514 .{ .register_offset = .{ .reg = data_reg, .off = data_off } },3575 .{ .register_offset = .{ .reg = data_reg, .off = data_off } },
3515 .{},3576 .{},
3516 );3577 );
3517 try self.genSetMem(3578 try self.genSetMem(.{ .reg = ret_reg }, 8, .usize, .{ .immediate = tag_name_len }, .{});
3518 .{ .reg = ret_reg },
3519 8,
3520 Type.usize,
3521 .{ .immediate = tag_name_len },
3522 .{},
3523 );
35243579
3525 exitlude_jump_reloc.* = try self.asmJmpReloc(undefined);3580 exitlude_jump_reloc.* = try self.asmJmpReloc(undefined);
3526 self.performReloc(skip_reloc);3581 self.performReloc(skip_reloc);
...@@ -4495,8 +4550,8 @@ fn airIntCast(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -4495,8 +4550,8 @@ fn airIntCast(self: *CodeGen, inst: Air.Inst.Index) !void {
4495 high_mcv.getReg().?4550 high_mcv.getReg().?
4496 else4551 else
4497 try self.copyToTmpRegister(switch (src_int_info.signedness) {4552 try self.copyToTmpRegister(switch (src_int_info.signedness) {
4498 .signed => Type.isize,4553 .signed => .isize,
4499 .unsigned => Type.usize,4554 .unsigned => .usize,
4500 }, high_mcv);4555 }, high_mcv);
4501 const high_lock = self.register_manager.lockRegAssumeUnused(high_reg);4556 const high_lock = self.register_manager.lockRegAssumeUnused(high_reg);
4502 defer self.register_manager.unlockReg(high_lock);4557 defer self.register_manager.unlockReg(high_lock);
...@@ -4504,7 +4559,7 @@ fn airIntCast(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -4504,7 +4559,7 @@ fn airIntCast(self: *CodeGen, inst: Air.Inst.Index) !void {
4504 const high_bits = src_int_info.bits % 64;4559 const high_bits = src_int_info.bits % 64;
4505 if (high_bits > 0) {4560 if (high_bits > 0) {
4506 try self.truncateRegister(src_ty, high_reg);4561 try self.truncateRegister(src_ty, high_reg);
4507 const high_ty = if (dst_int_info.bits >= 64) Type.usize else dst_ty;4562 const high_ty: Type = if (dst_int_info.bits >= 64) .usize else dst_ty;
4508 try self.genCopy(high_ty, high_mcv, .{ .register = high_reg }, .{});4563 try self.genCopy(high_ty, high_mcv, .{ .register = high_reg }, .{});
4509 }4564 }
45104565
...@@ -4513,13 +4568,7 @@ fn airIntCast(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -4513,13 +4568,7 @@ fn airIntCast(self: *CodeGen, inst: Air.Inst.Index) !void {
4513 switch (extend) {4568 switch (extend) {
4514 .signed => extend: {4569 .signed => extend: {
4515 const extend_mcv = MCValue{ .register = high_reg };4570 const extend_mcv = MCValue{ .register = high_reg };
4516 try self.genShiftBinOpMir(4571 try self.genShiftBinOpMir(.{ ._r, .sa }, .isize, extend_mcv, .u8, .{ .immediate = 63 });
4517 .{ ._r, .sa },
4518 Type.isize,
4519 extend_mcv,
4520 Type.u8,
4521 .{ .immediate = 63 },
4522 );
4523 break :extend extend_mcv;4572 break :extend extend_mcv;
4524 },4573 },
4525 .unsigned => .{ .immediate = 0 },4574 .unsigned => .{ .immediate = 0 },
...@@ -4621,7 +4670,7 @@ fn airTrunc(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -4621,7 +4670,7 @@ fn airTrunc(self: *CodeGen, inst: Air.Inst.Index) !void {
4621 const splat_mcv = try self.genTypedValue(.fromInterned(splat_val));4670 const splat_mcv = try self.genTypedValue(.fromInterned(splat_val));
4622 const splat_addr_mcv: MCValue = switch (splat_mcv) {4671 const splat_addr_mcv: MCValue = switch (splat_mcv) {
4623 .memory, .indirect, .load_frame => splat_mcv.address(),4672 .memory, .indirect, .load_frame => splat_mcv.address(),
4624 else => .{ .register = try self.copyToTmpRegister(Type.usize, splat_mcv.address()) },4673 else => .{ .register = try self.copyToTmpRegister(.usize, splat_mcv.address()) },
4625 };4674 };
46264675
4627 const dst_reg = dst_mcv.getReg().?;4676 const dst_reg = dst_mcv.getReg().?;
...@@ -4837,7 +4886,7 @@ fn airMulDivBinOp(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -4837,7 +4886,7 @@ fn airMulDivBinOp(self: *CodeGen, inst: Air.Inst.Index) !void {
4837 state: State,4886 state: State,
4838 reloc: Mir.Inst.Index,4887 reloc: Mir.Inst.Index,
4839 } = if (signed and tag == .div_floor) state: {4888 } = if (signed and tag == .div_floor) state: {
4840 const frame_index = try self.allocFrameIndex(.initType(Type.usize, zcu));4889 const frame_index = try self.allocFrameIndex(.initType(.usize, zcu));
4841 try self.asmMemoryImmediate(4890 try self.asmMemoryImmediate(
4842 .{ ._, .mov },4891 .{ ._, .mov },
4843 .{ .base = .{ .frame = frame_index }, .mod = .{ .rm = .{ .size = .qword } } },4892 .{ .base = .{ .frame = frame_index }, .mod = .{ .rm = .{ .size = .qword } } },
...@@ -4852,7 +4901,7 @@ fn airMulDivBinOp(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -4852,7 +4901,7 @@ fn airMulDivBinOp(self: *CodeGen, inst: Air.Inst.Index) !void {
4852 const mat_lhs_mcv = switch (lhs_mcv) {4901 const mat_lhs_mcv = switch (lhs_mcv) {
4853 .load_symbol => mat_lhs_mcv: {4902 .load_symbol => mat_lhs_mcv: {
4854 // TODO clean this up!4903 // TODO clean this up!
4855 const addr_reg = try self.copyToTmpRegister(Type.usize, lhs_mcv.address());4904 const addr_reg = try self.copyToTmpRegister(.usize, lhs_mcv.address());
4856 break :mat_lhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } };4905 break :mat_lhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } };
4857 },4906 },
4858 else => lhs_mcv,4907 else => lhs_mcv,
...@@ -4876,7 +4925,7 @@ fn airMulDivBinOp(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -4876,7 +4925,7 @@ fn airMulDivBinOp(self: *CodeGen, inst: Air.Inst.Index) !void {
4876 const mat_rhs_mcv = switch (rhs_mcv) {4925 const mat_rhs_mcv = switch (rhs_mcv) {
4877 .load_symbol => mat_rhs_mcv: {4926 .load_symbol => mat_rhs_mcv: {
4878 // TODO clean this up!4927 // TODO clean this up!
4879 const addr_reg = try self.copyToTmpRegister(Type.usize, rhs_mcv.address());4928 const addr_reg = try self.copyToTmpRegister(.usize, rhs_mcv.address());
4880 break :mat_rhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } };4929 break :mat_rhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } };
4881 },4930 },
4882 else => rhs_mcv,4931 else => rhs_mcv,
...@@ -4975,7 +5024,7 @@ fn airMulDivBinOp(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -4975,7 +5024,7 @@ fn airMulDivBinOp(self: *CodeGen, inst: Air.Inst.Index) !void {
4975 const mat_rhs_mcv = switch (rhs_mcv) {5024 const mat_rhs_mcv = switch (rhs_mcv) {
4976 .load_symbol => mat_rhs_mcv: {5025 .load_symbol => mat_rhs_mcv: {
4977 // TODO clean this up!5026 // TODO clean this up!
4978 const addr_reg = try self.copyToTmpRegister(Type.usize, rhs_mcv.address());5027 const addr_reg = try self.copyToTmpRegister(.usize, rhs_mcv.address());
4979 break :mat_rhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } };5028 break :mat_rhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } };
4980 },5029 },
4981 else => rhs_mcv,5030 else => rhs_mcv,
...@@ -5062,22 +5111,10 @@ fn airAddSat(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -5062,22 +5111,10 @@ fn airAddSat(self: *CodeGen, inst: Air.Inst.Index) !void {
5062 const reg_extra_bits = self.regExtraBits(ty);5111 const reg_extra_bits = self.regExtraBits(ty);
5063 const cc: Condition = if (ty.isSignedInt(zcu)) cc: {5112 const cc: Condition = if (ty.isSignedInt(zcu)) cc: {
5064 if (reg_extra_bits > 0) {5113 if (reg_extra_bits > 0) {
5065 try self.genShiftBinOpMir(5114 try self.genShiftBinOpMir(.{ ._l, .sa }, ty, dst_mcv, .u8, .{ .immediate = reg_extra_bits });
5066 .{ ._l, .sa },
5067 ty,
5068 dst_mcv,
5069 Type.u8,
5070 .{ .immediate = reg_extra_bits },
5071 );
5072 }5115 }
5073 try self.genSetReg(limit_reg, ty, dst_mcv, .{});5116 try self.genSetReg(limit_reg, ty, dst_mcv, .{});
5074 try self.genShiftBinOpMir(5117 try self.genShiftBinOpMir(.{ ._r, .sa }, ty, limit_mcv, .u8, .{ .immediate = reg_bits - 1 });
5075 .{ ._r, .sa },
5076 ty,
5077 limit_mcv,
5078 Type.u8,
5079 .{ .immediate = reg_bits - 1 },
5080 );
5081 try self.genBinOpMir(.{ ._, .xor }, ty, limit_mcv, .{5118 try self.genBinOpMir(.{ ._, .xor }, ty, limit_mcv, .{
5082 .immediate = (@as(u64, 1) << @intCast(reg_bits - 1)) - 1,5119 .immediate = (@as(u64, 1) << @intCast(reg_bits - 1)) - 1,
5083 });5120 });
...@@ -5087,13 +5124,7 @@ fn airAddSat(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -5087,13 +5124,7 @@ fn airAddSat(self: *CodeGen, inst: Air.Inst.Index) !void {
5087 const shifted_rhs_lock = self.register_manager.lockRegAssumeUnused(shifted_rhs_reg);5124 const shifted_rhs_lock = self.register_manager.lockRegAssumeUnused(shifted_rhs_reg);
5088 defer self.register_manager.unlockReg(shifted_rhs_lock);5125 defer self.register_manager.unlockReg(shifted_rhs_lock);
50895126
5090 try self.genShiftBinOpMir(5127 try self.genShiftBinOpMir(.{ ._l, .sa }, ty, shifted_rhs_mcv, .u8, .{ .immediate = reg_extra_bits });
5091 .{ ._l, .sa },
5092 ty,
5093 shifted_rhs_mcv,
5094 Type.u8,
5095 .{ .immediate = reg_extra_bits },
5096 );
5097 try self.genBinOpMir(.{ ._, .add }, ty, dst_mcv, shifted_rhs_mcv);5128 try self.genBinOpMir(.{ ._, .add }, ty, dst_mcv, shifted_rhs_mcv);
5098 } else try self.genBinOpMir(.{ ._, .add }, ty, dst_mcv, rhs_mcv);5129 } else try self.genBinOpMir(.{ ._, .add }, ty, dst_mcv, rhs_mcv);
5099 break :cc .o;5130 break :cc .o;
...@@ -5117,13 +5148,8 @@ fn airAddSat(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -5117,13 +5148,8 @@ fn airAddSat(self: *CodeGen, inst: Air.Inst.Index) !void {
5117 registerAlias(limit_reg, cmov_abi_size),5148 registerAlias(limit_reg, cmov_abi_size),
5118 );5149 );
51195150
5120 if (reg_extra_bits > 0 and ty.isSignedInt(zcu)) try self.genShiftBinOpMir(5151 if (reg_extra_bits > 0 and ty.isSignedInt(zcu))
5121 .{ ._r, .sa },5152 try self.genShiftBinOpMir(.{ ._r, .sa }, ty, dst_mcv, .u8, .{ .immediate = reg_extra_bits });
5122 ty,
5123 dst_mcv,
5124 Type.u8,
5125 .{ .immediate = reg_extra_bits },
5126 );
51275153
5128 return self.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none });5154 return self.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none });
5129}5155}
...@@ -5163,22 +5189,10 @@ fn airSubSat(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -5163,22 +5189,10 @@ fn airSubSat(self: *CodeGen, inst: Air.Inst.Index) !void {
5163 const reg_extra_bits = self.regExtraBits(ty);5189 const reg_extra_bits = self.regExtraBits(ty);
5164 const cc: Condition = if (ty.isSignedInt(zcu)) cc: {5190 const cc: Condition = if (ty.isSignedInt(zcu)) cc: {
5165 if (reg_extra_bits > 0) {5191 if (reg_extra_bits > 0) {
5166 try self.genShiftBinOpMir(5192 try self.genShiftBinOpMir(.{ ._l, .sa }, ty, dst_mcv, .u8, .{ .immediate = reg_extra_bits });
5167 .{ ._l, .sa },
5168 ty,
5169 dst_mcv,
5170 Type.u8,
5171 .{ .immediate = reg_extra_bits },
5172 );
5173 }5193 }
5174 try self.genSetReg(limit_reg, ty, dst_mcv, .{});5194 try self.genSetReg(limit_reg, ty, dst_mcv, .{});
5175 try self.genShiftBinOpMir(5195 try self.genShiftBinOpMir(.{ ._r, .sa }, ty, limit_mcv, .u8, .{ .immediate = reg_bits - 1 });
5176 .{ ._r, .sa },
5177 ty,
5178 limit_mcv,
5179 Type.u8,
5180 .{ .immediate = reg_bits - 1 },
5181 );
5182 try self.genBinOpMir(.{ ._, .xor }, ty, limit_mcv, .{5196 try self.genBinOpMir(.{ ._, .xor }, ty, limit_mcv, .{
5183 .immediate = (@as(u64, 1) << @intCast(reg_bits - 1)) - 1,5197 .immediate = (@as(u64, 1) << @intCast(reg_bits - 1)) - 1,
5184 });5198 });
...@@ -5188,13 +5202,7 @@ fn airSubSat(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -5188,13 +5202,7 @@ fn airSubSat(self: *CodeGen, inst: Air.Inst.Index) !void {
5188 const shifted_rhs_lock = self.register_manager.lockRegAssumeUnused(shifted_rhs_reg);5202 const shifted_rhs_lock = self.register_manager.lockRegAssumeUnused(shifted_rhs_reg);
5189 defer self.register_manager.unlockReg(shifted_rhs_lock);5203 defer self.register_manager.unlockReg(shifted_rhs_lock);
51905204
5191 try self.genShiftBinOpMir(5205 try self.genShiftBinOpMir(.{ ._l, .sa }, ty, shifted_rhs_mcv, .u8, .{ .immediate = reg_extra_bits });
5192 .{ ._l, .sa },
5193 ty,
5194 shifted_rhs_mcv,
5195 Type.u8,
5196 .{ .immediate = reg_extra_bits },
5197 );
5198 try self.genBinOpMir(.{ ._, .sub }, ty, dst_mcv, shifted_rhs_mcv);5206 try self.genBinOpMir(.{ ._, .sub }, ty, dst_mcv, shifted_rhs_mcv);
5199 } else try self.genBinOpMir(.{ ._, .sub }, ty, dst_mcv, rhs_mcv);5207 } else try self.genBinOpMir(.{ ._, .sub }, ty, dst_mcv, rhs_mcv);
5200 break :cc .o;5208 break :cc .o;
...@@ -5211,13 +5219,8 @@ fn airSubSat(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -5211,13 +5219,8 @@ fn airSubSat(self: *CodeGen, inst: Air.Inst.Index) !void {
5211 registerAlias(limit_reg, cmov_abi_size),5219 registerAlias(limit_reg, cmov_abi_size),
5212 );5220 );
52135221
5214 if (reg_extra_bits > 0 and ty.isSignedInt(zcu)) try self.genShiftBinOpMir(5222 if (reg_extra_bits > 0 and ty.isSignedInt(zcu))
5215 .{ ._r, .sa },5223 try self.genShiftBinOpMir(.{ ._r, .sa }, ty, dst_mcv, .u8, .{ .immediate = reg_extra_bits });
5216 ty,
5217 dst_mcv,
5218 Type.u8,
5219 .{ .immediate = reg_extra_bits },
5220 );
52215224
5222 return self.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none });5225 return self.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none });
5223}5226}
...@@ -5230,14 +5233,14 @@ fn airMulSat(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -5230,14 +5233,14 @@ fn airMulSat(self: *CodeGen, inst: Air.Inst.Index) !void {
52305233
5231 const result = result: {5234 const result = result: {
5232 if (ty.toIntern() == .i128_type) {5235 if (ty.toIntern() == .i128_type) {
5233 const ptr_c_int = try pt.singleMutPtrType(Type.c_int);5236 const ptr_c_int = try pt.singleMutPtrType(.c_int);
5234 const overflow = try self.allocTempRegOrMem(Type.c_int, false);5237 const overflow = try self.allocTempRegOrMem(.c_int, false);
52355238
5236 const dst_mcv = try self.genCall(.{ .lib = .{5239 const dst_mcv = try self.genCall(.{ .lib = .{
5237 .return_type = .i128_type,5240 .return_type = .i128_type,
5238 .param_types = &.{ .i128_type, .i128_type, ptr_c_int.toIntern() },5241 .param_types = &.{ .i128_type, .i128_type, ptr_c_int.toIntern() },
5239 .callee = "__muloti4",5242 .callee = "__muloti4",
5240 } }, &.{ Type.i128, Type.i128, ptr_c_int }, &.{5243 } }, &.{ .i128, .i128, ptr_c_int }, &.{
5241 .{ .air_ref = bin_op.lhs },5244 .{ .air_ref = bin_op.lhs },
5242 .{ .air_ref = bin_op.rhs },5245 .{ .air_ref = bin_op.rhs },
5243 overflow.address(),5246 overflow.address(),
...@@ -5253,7 +5256,7 @@ fn airMulSat(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -5253,7 +5256,7 @@ fn airMulSat(self: *CodeGen, inst: Air.Inst.Index) !void {
5253 const mat_lhs_mcv = switch (lhs_mcv) {5256 const mat_lhs_mcv = switch (lhs_mcv) {
5254 .load_symbol => mat_lhs_mcv: {5257 .load_symbol => mat_lhs_mcv: {
5255 // TODO clean this up!5258 // TODO clean this up!
5256 const addr_reg = try self.copyToTmpRegister(Type.usize, lhs_mcv.address());5259 const addr_reg = try self.copyToTmpRegister(.usize, lhs_mcv.address());
5257 break :mat_lhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } };5260 break :mat_lhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } };
5258 },5261 },
5259 else => lhs_mcv,5262 else => lhs_mcv,
...@@ -5277,7 +5280,7 @@ fn airMulSat(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -5277,7 +5280,7 @@ fn airMulSat(self: *CodeGen, inst: Air.Inst.Index) !void {
5277 const mat_rhs_mcv = switch (rhs_mcv) {5280 const mat_rhs_mcv = switch (rhs_mcv) {
5278 .load_symbol => mat_rhs_mcv: {5281 .load_symbol => mat_rhs_mcv: {
5279 // TODO clean this up!5282 // TODO clean this up!
5280 const addr_reg = try self.copyToTmpRegister(Type.usize, rhs_mcv.address());5283 const addr_reg = try self.copyToTmpRegister(.usize, rhs_mcv.address());
5281 break :mat_rhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } };5284 break :mat_rhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } };
5282 },5285 },
5283 else => rhs_mcv,5286 else => rhs_mcv,
...@@ -5339,13 +5342,7 @@ fn airMulSat(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -5339,13 +5342,7 @@ fn airMulSat(self: *CodeGen, inst: Air.Inst.Index) !void {
5339 const cc: Condition = if (ty.isSignedInt(zcu)) cc: {5342 const cc: Condition = if (ty.isSignedInt(zcu)) cc: {
5340 try self.genSetReg(limit_reg, ty, lhs_mcv, .{});5343 try self.genSetReg(limit_reg, ty, lhs_mcv, .{});
5341 try self.genBinOpMir(.{ ._, .xor }, ty, limit_mcv, rhs_mcv);5344 try self.genBinOpMir(.{ ._, .xor }, ty, limit_mcv, rhs_mcv);
5342 try self.genShiftBinOpMir(5345 try self.genShiftBinOpMir(.{ ._r, .sa }, ty, limit_mcv, .u8, .{ .immediate = reg_bits - 1 });
5343 .{ ._r, .sa },
5344 ty,
5345 limit_mcv,
5346 Type.u8,
5347 .{ .immediate = reg_bits - 1 },
5348 );
5349 try self.genBinOpMir(.{ ._, .xor }, ty, limit_mcv, .{5346 try self.genBinOpMir(.{ ._, .xor }, ty, limit_mcv, .{
5350 .immediate = (@as(u64, 1) << @intCast(reg_bits - 1)) - 1,5347 .immediate = (@as(u64, 1) << @intCast(reg_bits - 1)) - 1,
5351 });5348 });
...@@ -5410,7 +5407,7 @@ fn airAddSubWithOverflow(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -5410,7 +5407,7 @@ fn airAddSubWithOverflow(self: *CodeGen, inst: Air.Inst.Index) !void {
5410 try self.genSetMem(5407 try self.genSetMem(
5411 .{ .frame = frame_index },5408 .{ .frame = frame_index },
5412 @intCast(tuple_ty.structFieldOffset(1, zcu)),5409 @intCast(tuple_ty.structFieldOffset(1, zcu)),
5413 Type.u1,5410 .u1,
5414 .{ .eflags = cc },5411 .{ .eflags = cc },
5415 .{},5412 .{},
5416 );5413 );
...@@ -5558,12 +5555,7 @@ fn genSetFrameTruncatedOverflowCompare(...@@ -5558,12 +5555,7 @@ fn genSetFrameTruncatedOverflowCompare(
5558 const eq_reg = temp_regs[2];5555 const eq_reg = temp_regs[2];
5559 if (overflow_cc) |_| {5556 if (overflow_cc) |_| {
5560 try self.asmSetccRegister(.ne, eq_reg.to8());5557 try self.asmSetccRegister(.ne, eq_reg.to8());
5561 try self.genBinOpMir(5558 try self.genBinOpMir(.{ ._, .@"or" }, .u8, .{ .register = overflow_reg }, .{ .register = eq_reg });
5562 .{ ._, .@"or" },
5563 Type.u8,
5564 .{ .register = overflow_reg },
5565 .{ .register = eq_reg },
5566 );
5567 }5559 }
55685560
5569 const payload_off: i32 = @intCast(tuple_ty.structFieldOffset(0, zcu));5561 const payload_off: i32 = @intCast(tuple_ty.structFieldOffset(0, zcu));
...@@ -5743,13 +5735,13 @@ fn airMulWithOverflow(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -5743,13 +5735,13 @@ fn airMulWithOverflow(self: *CodeGen, inst: Air.Inst.Index) !void {
5743 if (src_bits > 64 and src_bits <= 128 and5735 if (src_bits > 64 and src_bits <= 128 and
5744 dst_info.bits > 64 and dst_info.bits <= 128) switch (dst_info.signedness) {5736 dst_info.bits > 64 and dst_info.bits <= 128) switch (dst_info.signedness) {
5745 .signed => {5737 .signed => {
5746 const ptr_c_int = try pt.singleMutPtrType(Type.c_int);5738 const ptr_c_int = try pt.singleMutPtrType(.c_int);
5747 const overflow = try self.allocTempRegOrMem(Type.c_int, false);5739 const overflow = try self.allocTempRegOrMem(.c_int, false);
5748 const result = try self.genCall(.{ .lib = .{5740 const result = try self.genCall(.{ .lib = .{
5749 .return_type = .i128_type,5741 .return_type = .i128_type,
5750 .param_types = &.{ .i128_type, .i128_type, ptr_c_int.toIntern() },5742 .param_types = &.{ .i128_type, .i128_type, ptr_c_int.toIntern() },
5751 .callee = "__muloti4",5743 .callee = "__muloti4",
5752 } }, &.{ Type.i128, Type.i128, ptr_c_int }, &.{5744 } }, &.{ .i128, .i128, ptr_c_int }, &.{
5753 .{ .air_ref = bin_op.lhs },5745 .{ .air_ref = bin_op.lhs },
5754 .{ .air_ref = bin_op.rhs },5746 .{ .air_ref = bin_op.rhs },
5755 overflow.address(),5747 overflow.address(),
...@@ -5765,7 +5757,7 @@ fn airMulWithOverflow(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -5765,7 +5757,7 @@ fn airMulWithOverflow(self: *CodeGen, inst: Air.Inst.Index) !void {
5765 );5757 );
5766 try self.asmMemoryImmediate(5758 try self.asmMemoryImmediate(
5767 .{ ._, .cmp },5759 .{ ._, .cmp },
5768 try overflow.mem(self, .{ .size = self.memSize(Type.c_int) }),5760 try overflow.mem(self, .{ .size = self.memSize(.c_int) }),
5769 .s(0),5761 .s(0),
5770 );5762 );
5771 try self.genSetMem(5763 try self.genSetMem(
...@@ -5794,7 +5786,7 @@ fn airMulWithOverflow(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -5794,7 +5786,7 @@ fn airMulWithOverflow(self: *CodeGen, inst: Air.Inst.Index) !void {
5794 const mat_lhs_mcv = switch (lhs_mcv) {5786 const mat_lhs_mcv = switch (lhs_mcv) {
5795 .load_symbol => mat_lhs_mcv: {5787 .load_symbol => mat_lhs_mcv: {
5796 // TODO clean this up!5788 // TODO clean this up!
5797 const addr_reg = try self.copyToTmpRegister(Type.usize, lhs_mcv.address());5789 const addr_reg = try self.copyToTmpRegister(.usize, lhs_mcv.address());
5798 break :mat_lhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } };5790 break :mat_lhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } };
5799 },5791 },
5800 else => lhs_mcv,5792 else => lhs_mcv,
...@@ -5807,7 +5799,7 @@ fn airMulWithOverflow(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -5807,7 +5799,7 @@ fn airMulWithOverflow(self: *CodeGen, inst: Air.Inst.Index) !void {
5807 const mat_rhs_mcv = switch (rhs_mcv) {5799 const mat_rhs_mcv = switch (rhs_mcv) {
5808 .load_symbol => mat_rhs_mcv: {5800 .load_symbol => mat_rhs_mcv: {
5809 // TODO clean this up!5801 // TODO clean this up!
5810 const addr_reg = try self.copyToTmpRegister(Type.usize, rhs_mcv.address());5802 const addr_reg = try self.copyToTmpRegister(.usize, rhs_mcv.address());
5811 break :mat_rhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } };5803 break :mat_rhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } };
5812 },5804 },
5813 else => rhs_mcv,5805 else => rhs_mcv,
...@@ -6100,7 +6092,7 @@ fn airShlShrBinOp(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -6100,7 +6092,7 @@ fn airShlShrBinOp(self: *CodeGen, inst: Air.Inst.Index) !void {
6100 defer self.register_manager.unlockReg(tmp_lock);6092 defer self.register_manager.unlockReg(tmp_lock);
61016093
6102 const lhs_bits: u31 = @intCast(lhs_ty.bitSize(zcu));6094 const lhs_bits: u31 = @intCast(lhs_ty.bitSize(zcu));
6103 const tmp_ty = if (lhs_bits > 64) Type.usize else lhs_ty;6095 const tmp_ty: Type = if (lhs_bits > 64) .usize else lhs_ty;
6104 const off = frame_addr.off + (lhs_bits - 1) / 64 * 8;6096 const off = frame_addr.off + (lhs_bits - 1) / 64 * 8;
6105 try self.genSetReg(6097 try self.genSetReg(
6106 tmp_reg,6098 tmp_reg,
...@@ -6283,13 +6275,12 @@ fn airShlShrBinOp(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -6283,13 +6275,12 @@ fn airShlShrBinOp(self: *CodeGen, inst: Air.Inst.Index) !void {
6283 const mask_mcv = try self.genTypedValue(.fromInterned(try pt.intern(.{ .aggregate = .{6275 const mask_mcv = try self.genTypedValue(.fromInterned(try pt.intern(.{ .aggregate = .{
6284 .ty = mask_ty.toIntern(),6276 .ty = mask_ty.toIntern(),
6285 .storage = .{ .elems = &([1]InternPool.Index{6277 .storage = .{ .elems = &([1]InternPool.Index{
6286 (try rhs_ty.childType(zcu).maxIntScalar(pt, Type.u8)).toIntern(),6278 (try rhs_ty.childType(zcu).maxIntScalar(pt, .u8)).toIntern(),
6287 } ++ [1]InternPool.Index{6279 } ++ [1]InternPool.Index{
6288 (try pt.intValue(Type.u8, 0)).toIntern(),6280 (try pt.intValue(.u8, 0)).toIntern(),
6289 } ** 15) },6281 } ** 15) },
6290 } })));6282 } })));
6291 const mask_addr_reg =6283 const mask_addr_reg = try self.copyToTmpRegister(.usize, mask_mcv.address());
6292 try self.copyToTmpRegister(Type.usize, mask_mcv.address());
6293 const mask_addr_lock = self.register_manager.lockRegAssumeUnused(mask_addr_reg);6284 const mask_addr_lock = self.register_manager.lockRegAssumeUnused(mask_addr_reg);
6294 defer self.register_manager.unlockReg(mask_addr_lock);6285 defer self.register_manager.unlockReg(mask_addr_lock);
62956286
...@@ -6423,7 +6414,7 @@ fn airOptionalPayloadPtrSet(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -6423,7 +6414,7 @@ fn airOptionalPayloadPtrSet(self: *CodeGen, inst: Air.Inst.Index) !void {
6423 try self.genSetMem(6414 try self.genSetMem(
6424 .{ .reg = dst_mcv.getReg().? },6415 .{ .reg = dst_mcv.getReg().? },
6425 pl_abi_size,6416 pl_abi_size,
6426 Type.bool,6417 .bool,
6427 .{ .immediate = 1 },6418 .{ .immediate = 1 },
6428 .{},6419 .{},
6429 );6420 );
...@@ -6462,9 +6453,9 @@ fn airUnwrapErrUnionErr(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -6462,9 +6453,9 @@ fn airUnwrapErrUnionErr(self: *CodeGen, inst: Air.Inst.Index) !void {
6462 .{ ._r, .sh },6453 .{ ._r, .sh },
6463 err_union_ty,6454 err_union_ty,
6464 result,6455 result,
6465 Type.u8,6456 .u8,
6466 .{ .immediate = @as(u6, @intCast(err_off * 8)) },6457 .{ .immediate = @as(u6, @intCast(err_off * 8)) },
6467 ) else try self.truncateRegister(Type.anyerror, result.register);6458 ) else try self.truncateRegister(.anyerror, result.register);
6468 break :result result;6459 break :result result;
6469 },6460 },
6470 .load_frame => |frame_addr| break :result .{ .load_frame = .{6461 .load_frame => |frame_addr| break :result .{ .load_frame = .{
...@@ -6623,7 +6614,7 @@ fn genUnwrapErrUnionPayloadMir(...@@ -6623,7 +6614,7 @@ fn genUnwrapErrUnionPayloadMir(
6623 .{ ._r, .sh },6614 .{ ._r, .sh },
6624 err_union_ty,6615 err_union_ty,
6625 result_mcv,6616 result_mcv,
6626 Type.u8,6617 .u8,
6627 .{ .immediate = @as(u6, @intCast(payload_off * 8)) },6618 .{ .immediate = @as(u6, @intCast(payload_off * 8)) },
6628 ) else try self.truncateRegister(payload_ty, result_mcv.register);6619 ) else try self.truncateRegister(payload_ty, result_mcv.register);
6629 break :result if (payload_in_gp)6620 break :result if (payload_in_gp)
...@@ -6929,7 +6920,7 @@ fn genSliceElemPtr(self: *CodeGen, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValu...@@ -6929,7 +6920,7 @@ fn genSliceElemPtr(self: *CodeGen, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValu
6929 defer self.register_manager.unlockReg(offset_reg_lock);6920 defer self.register_manager.unlockReg(offset_reg_lock);
69306921
6931 const addr_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);6922 const addr_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
6932 try self.genSetReg(addr_reg, Type.usize, slice_mcv, .{});6923 try self.genSetReg(addr_reg, .usize, slice_mcv, .{});
6933 // TODO we could allocate register here, but need to expect addr register and potentially6924 // TODO we could allocate register here, but need to expect addr register and potentially
6934 // offset register.6925 // offset register.
6935 try self.genBinOpMir(.{ ._, .add }, slice_ptr_field_type, .{ .register = addr_reg }, .{6926 try self.genBinOpMir(.{ ._, .add }, slice_ptr_field_type, .{ .register = addr_reg }, .{
...@@ -7064,7 +7055,7 @@ fn airArrayElemVal(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -7064,7 +7055,7 @@ fn airArrayElemVal(self: *CodeGen, inst: Air.Inst.Index) !void {
7064 .{ ._, .bt },7055 .{ ._, .bt },
7065 .{7056 .{
7066 .base = .{7057 .base = .{
7067 .reg = try self.copyToTmpRegister(Type.usize, array_mat_mcv.address()),7058 .reg = try self.copyToTmpRegister(.usize, array_mat_mcv.address()),
7068 },7059 },
7069 .mod = .{ .rm = .{ .size = .qword } },7060 .mod = .{ .rm = .{ .size = .qword } },
7070 },7061 },
...@@ -7074,7 +7065,7 @@ fn airArrayElemVal(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -7074,7 +7065,7 @@ fn airArrayElemVal(self: *CodeGen, inst: Air.Inst.Index) !void {
7074 .{ ._, .bt },7065 .{ ._, .bt },
7075 .{7066 .{
7076 .base = .{7067 .base = .{
7077 .reg = try self.copyToTmpRegister(Type.usize, array_mat_mcv.address()),7068 .reg = try self.copyToTmpRegister(.usize, array_mat_mcv.address()),
7078 },7069 },
7079 .mod = .{ .rm = .{ .size = .qword } },7070 .mod = .{ .rm = .{ .size = .qword } },
7080 },7071 },
...@@ -7122,7 +7113,7 @@ fn airArrayElemVal(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -7122,7 +7113,7 @@ fn airArrayElemVal(self: *CodeGen, inst: Air.Inst.Index) !void {
7122 .load_direct,7113 .load_direct,
7123 .load_got,7114 .load_got,
7124 .load_tlv,7115 .load_tlv,
7125 => try self.genSetReg(addr_reg, Type.usize, array_mcv.address(), .{}),7116 => try self.genSetReg(addr_reg, .usize, array_mcv.address(), .{}),
7126 .lea_symbol, .lea_direct, .lea_tlv => unreachable,7117 .lea_symbol, .lea_direct, .lea_tlv => unreachable,
7127 else => return self.fail("TODO airArrayElemVal_val for {s} of {}", .{7118 else => return self.fail("TODO airArrayElemVal_val for {s} of {}", .{
7128 @tagName(array_mcv), array_ty.fmt(pt),7119 @tagName(array_mcv), array_ty.fmt(pt),
...@@ -7136,12 +7127,7 @@ fn airArrayElemVal(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -7136,12 +7127,7 @@ fn airArrayElemVal(self: *CodeGen, inst: Air.Inst.Index) !void {
7136 // TODO we could allocate register here, but need to expect addr register and potentially7127 // TODO we could allocate register here, but need to expect addr register and potentially
7137 // offset register.7128 // offset register.
7138 const dst_mcv = try self.allocRegOrMem(inst, false);7129 const dst_mcv = try self.allocRegOrMem(inst, false);
7139 try self.genBinOpMir(7130 try self.genBinOpMir(.{ ._, .add }, .usize, .{ .register = addr_reg }, .{ .register = offset_reg });
7140 .{ ._, .add },
7141 Type.usize,
7142 .{ .register = addr_reg },
7143 .{ .register = offset_reg },
7144 );
7145 try self.genCopy(elem_ty, dst_mcv, .{ .indirect = .{ .reg = addr_reg } }, .{});7131 try self.genCopy(elem_ty, dst_mcv, .{ .indirect = .{ .reg = addr_reg } }, .{});
7146 break :result dst_mcv;7132 break :result dst_mcv;
7147 };7133 };
...@@ -7329,13 +7315,7 @@ fn airGetUnionTag(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -7329,13 +7315,7 @@ fn airGetUnionTag(self: *CodeGen, inst: Air.Inst.Index) !void {
7329 .register => {7315 .register => {
7330 const shift: u6 = @intCast(layout.tagOffset() * 8);7316 const shift: u6 = @intCast(layout.tagOffset() * 8);
7331 const result = try self.copyToRegisterWithInstTracking(inst, union_ty, operand);7317 const result = try self.copyToRegisterWithInstTracking(inst, union_ty, operand);
7332 try self.genShiftBinOpMir(7318 try self.genShiftBinOpMir(.{ ._r, .sh }, .usize, result, .u8, .{ .immediate = shift });
7333 .{ ._r, .sh },
7334 Type.usize,
7335 result,
7336 Type.u8,
7337 .{ .immediate = shift },
7338 );
7339 break :blk MCValue{7319 break :blk MCValue{
7340 .register = registerAlias(result.register, @intCast(layout.tag_size)),7320 .register = registerAlias(result.register, @intCast(layout.tag_size)),
7341 };7321 };
...@@ -7444,7 +7424,7 @@ fn airClz(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -7444,7 +7424,7 @@ fn airClz(self: *CodeGen, inst: Air.Inst.Index) !void {
7444 if (src_bits <= 8) {7424 if (src_bits <= 8) {
7445 const wide_reg = try self.copyToTmpRegister(src_ty, mat_src_mcv);7425 const wide_reg = try self.copyToTmpRegister(src_ty, mat_src_mcv);
7446 try self.truncateRegister(src_ty, wide_reg);7426 try self.truncateRegister(src_ty, wide_reg);
7447 try self.genBinOpMir(.{ ._, .lzcnt }, Type.u32, dst_mcv, .{ .register = wide_reg });7427 try self.genBinOpMir(.{ ._, .lzcnt }, .u32, dst_mcv, .{ .register = wide_reg });
7448 try self.genBinOpMir(7428 try self.genBinOpMir(
7449 .{ ._, .sub },7429 .{ ._, .sub },
7450 dst_ty,7430 dst_ty,
...@@ -7464,25 +7444,15 @@ fn airClz(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -7464,25 +7444,15 @@ fn airClz(self: *CodeGen, inst: Air.Inst.Index) !void {
7464 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);7444 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
7465 defer self.register_manager.unlockReg(tmp_lock);7445 defer self.register_manager.unlockReg(tmp_lock);
74667446
7467 try self.genBinOpMir(7447 try self.genBinOpMir(.{ ._, .lzcnt }, .u64, dst_mcv, if (mat_src_mcv.isBase())
7468 .{ ._, .lzcnt },7448 mat_src_mcv
7469 Type.u64,7449 else
7470 dst_mcv,7450 .{ .register = mat_src_mcv.register_pair[0] });
7471 if (mat_src_mcv.isBase())
7472 mat_src_mcv
7473 else
7474 .{ .register = mat_src_mcv.register_pair[0] },
7475 );
7476 try self.genBinOpMir(.{ ._, .add }, dst_ty, dst_mcv, .{ .immediate = 64 });7451 try self.genBinOpMir(.{ ._, .add }, dst_ty, dst_mcv, .{ .immediate = 64 });
7477 try self.genBinOpMir(7452 try self.genBinOpMir(.{ ._, .lzcnt }, .u64, tmp_mcv, if (mat_src_mcv.isBase())
7478 .{ ._, .lzcnt },7453 mat_src_mcv.address().offset(8).deref()
7479 Type.u64,7454 else
7480 tmp_mcv,7455 .{ .register = mat_src_mcv.register_pair[1] });
7481 if (mat_src_mcv.isBase())
7482 mat_src_mcv.address().offset(8).deref()
7483 else
7484 .{ .register = mat_src_mcv.register_pair[1] },
7485 );
7486 try self.asmCmovccRegisterRegister(.nc, dst_reg.to32(), tmp_reg.to32());7456 try self.asmCmovccRegisterRegister(.nc, dst_reg.to32(), tmp_reg.to32());
74877457
7488 if (src_bits < 128) try self.genBinOpMir(7458 if (src_bits < 128) try self.genBinOpMir(
...@@ -7510,7 +7480,7 @@ fn airClz(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -7510,7 +7480,7 @@ fn airClz(self: *CodeGen, inst: Air.Inst.Index) !void {
7510 defer self.register_manager.unlockReg(wide_lock);7480 defer self.register_manager.unlockReg(wide_lock);
75117481
7512 try self.truncateRegister(src_ty, wide_reg);7482 try self.truncateRegister(src_ty, wide_reg);
7513 try self.genBinOpMir(.{ ._, .bsr }, Type.u16, dst_mcv, .{ .register = wide_reg });7483 try self.genBinOpMir(.{ ._, .bsr }, .u16, dst_mcv, .{ .register = wide_reg });
7514 } else try self.genBinOpMir(.{ ._, .bsr }, src_ty, dst_mcv, mat_src_mcv);7484 } else try self.genBinOpMir(.{ ._, .bsr }, src_ty, dst_mcv, mat_src_mcv);
75157485
7516 try self.asmCmovccRegisterRegister(7486 try self.asmCmovccRegisterRegister(
...@@ -7534,7 +7504,7 @@ fn airClz(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -7534,7 +7504,7 @@ fn airClz(self: *CodeGen, inst: Air.Inst.Index) !void {
7534 try self.truncateRegister(src_ty, wide_reg);7504 try self.truncateRegister(src_ty, wide_reg);
7535 try self.genBinOpMir(7505 try self.genBinOpMir(
7536 .{ ._, .bsr },7506 .{ ._, .bsr },
7537 if (src_bits <= 8) Type.u16 else src_ty,7507 if (src_bits <= 8) .u16 else src_ty,
7538 dst_mcv,7508 dst_mcv,
7539 .{ .register = wide_reg },7509 .{ .register = wide_reg },
7540 );7510 );
...@@ -7645,7 +7615,7 @@ fn airCtz(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -7645,7 +7615,7 @@ fn airCtz(self: *CodeGen, inst: Air.Inst.Index) !void {
7645 break :result dst_mcv;7615 break :result dst_mcv;
7646 }7616 }
76477617
7648 const wide_ty = if (src_bits <= 8) Type.u16 else src_ty;7618 const wide_ty: Type = if (src_bits <= 8) .u16 else src_ty;
7649 if (has_bmi) {7619 if (has_bmi) {
7650 if (src_bits <= 64) {7620 if (src_bits <= 64) {
7651 const extra_bits = self.regExtraBits(src_ty) + @as(u64, if (src_bits <= 8) 8 else 0);7621 const extra_bits = self.regExtraBits(src_ty) + @as(u64, if (src_bits <= 8) 8 else 0);
...@@ -7682,18 +7652,18 @@ fn airCtz(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -7682,18 +7652,18 @@ fn airCtz(self: *CodeGen, inst: Air.Inst.Index) !void {
7682 else7652 else
7683 .{ .register = mat_src_mcv.register_pair[1] };7653 .{ .register = mat_src_mcv.register_pair[1] };
7684 const masked_mcv = if (src_bits < 128) masked: {7654 const masked_mcv = if (src_bits < 128) masked: {
7685 try self.genCopy(Type.u64, dst_mcv, hi_mat_src_mcv, .{});7655 try self.genCopy(.u64, dst_mcv, hi_mat_src_mcv, .{});
7686 try self.genBinOpMir(7656 try self.genBinOpMir(
7687 .{ ._, .@"or" },7657 .{ ._, .@"or" },
7688 Type.u64,7658 .u64,
7689 dst_mcv,7659 dst_mcv,
7690 .{ .immediate = @as(u64, std.math.maxInt(u64)) << @intCast(src_bits - 64) },7660 .{ .immediate = @as(u64, std.math.maxInt(u64)) << @intCast(src_bits - 64) },
7691 );7661 );
7692 break :masked dst_mcv;7662 break :masked dst_mcv;
7693 } else hi_mat_src_mcv;7663 } else hi_mat_src_mcv;
7694 try self.genBinOpMir(.{ ._, .tzcnt }, Type.u64, dst_mcv, masked_mcv);7664 try self.genBinOpMir(.{ ._, .tzcnt }, .u64, dst_mcv, masked_mcv);
7695 try self.genBinOpMir(.{ ._, .add }, dst_ty, dst_mcv, .{ .immediate = 64 });7665 try self.genBinOpMir(.{ ._, .add }, dst_ty, dst_mcv, .{ .immediate = 64 });
7696 try self.genBinOpMir(.{ ._, .tzcnt }, Type.u64, tmp_mcv, lo_mat_src_mcv);7666 try self.genBinOpMir(.{ ._, .tzcnt }, .u64, tmp_mcv, lo_mat_src_mcv);
7697 try self.asmCmovccRegisterRegister(.nc, dst_reg.to32(), tmp_reg.to32());7667 try self.asmCmovccRegisterRegister(.nc, dst_reg.to32(), tmp_reg.to32());
7698 }7668 }
7699 break :result dst_mcv;7669 break :result dst_mcv;
...@@ -7766,7 +7736,7 @@ fn airPopCount(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -7766,7 +7736,7 @@ fn airPopCount(self: *CodeGen, inst: Air.Inst.Index) !void {
7766 const tmp_locks = self.register_manager.lockRegsAssumeUnused(2, tmp_regs);7736 const tmp_locks = self.register_manager.lockRegsAssumeUnused(2, tmp_regs);
7767 defer for (tmp_locks) |lock| self.register_manager.unlockReg(lock);7737 defer for (tmp_locks) |lock| self.register_manager.unlockReg(lock);
77687738
7769 try self.genPopCount(tmp_regs[0], Type.usize, if (mat_src_mcv.isBase())7739 try self.genPopCount(tmp_regs[0], .usize, if (mat_src_mcv.isBase())
7770 mat_src_mcv7740 mat_src_mcv
7771 else7741 else
7772 .{ .register = mat_src_mcv.register_pair[0] }, false);7742 .{ .register = mat_src_mcv.register_pair[0] }, false);
...@@ -7794,7 +7764,7 @@ fn genPopCount(...@@ -7794,7 +7764,7 @@ fn genPopCount(
7794 const src_abi_size: u32 = @intCast(src_ty.abiSize(pt.zcu));7764 const src_abi_size: u32 = @intCast(src_ty.abiSize(pt.zcu));
7795 if (self.hasFeature(.popcnt)) return self.genBinOpMir(7765 if (self.hasFeature(.popcnt)) return self.genBinOpMir(
7796 .{ ._, .popcnt },7766 .{ ._, .popcnt },
7797 if (src_abi_size > 1) src_ty else Type.u32,7767 if (src_abi_size > 1) src_ty else .u32,
7798 .{ .register = dst_reg },7768 .{ .register = dst_reg },
7799 if (src_abi_size > 1) src_mcv else src: {7769 if (src_abi_size > 1) src_mcv else src: {
7800 if (!dst_contains_src) try self.genSetReg(dst_reg, src_ty, src_mcv, .{});7770 if (!dst_contains_src) try self.genSetReg(dst_reg, src_ty, src_mcv, .{});
...@@ -8057,7 +8027,7 @@ fn airByteSwap(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -8057,7 +8027,7 @@ fn airByteSwap(self: *CodeGen, inst: Air.Inst.Index) !void {
8057 } },8027 } },
8058 src_ty,8028 src_ty,
8059 dst_mcv,8029 dst_mcv,
8060 if (src_bits > 256) Type.u16 else Type.u8,8030 if (src_bits > 256) .u16 else .u8,
8061 .{ .immediate = src_ty.abiSize(zcu) * 8 - src_bits },8031 .{ .immediate = src_ty.abiSize(zcu) * 8 - src_bits },
8062 );8032 );
8063 return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });8033 return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });
...@@ -8181,7 +8151,7 @@ fn airBitReverse(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -8181,7 +8151,7 @@ fn airBitReverse(self: *CodeGen, inst: Air.Inst.Index) !void {
8181 if (extra_bits > 0) try self.genShiftBinOpMir(switch (signedness) {8151 if (extra_bits > 0) try self.genShiftBinOpMir(switch (signedness) {
8182 .signed => .{ ._r, .sa },8152 .signed => .{ ._r, .sa },
8183 .unsigned => .{ ._r, .sh },8153 .unsigned => .{ ._r, .sh },
8184 }, src_ty, dst_mcv, Type.u8, .{ .immediate = extra_bits });8154 }, src_ty, dst_mcv, .u8, .{ .immediate = extra_bits });
81858155
8186 return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });8156 return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });
8187}8157}
...@@ -8252,7 +8222,7 @@ fn floatSign(self: *CodeGen, inst: Air.Inst.Index, operand: Air.Inst.Ref, ty: Ty...@@ -8252,7 +8222,7 @@ fn floatSign(self: *CodeGen, inst: Air.Inst.Index, operand: Air.Inst.Ref, ty: Ty
8252 try sign_mcv.mem(self, .{ .size = .fromSize(abi_size) })8222 try sign_mcv.mem(self, .{ .size = .fromSize(abi_size) })
8253 else8223 else
8254 .{8224 .{
8255 .base = .{ .reg = try self.copyToTmpRegister(Type.usize, sign_mcv.address()) },8225 .base = .{ .reg = try self.copyToTmpRegister(.usize, sign_mcv.address()) },
8256 .mod = .{ .rm = .{ .size = .fromSize(abi_size) } },8226 .mod = .{ .rm = .{ .size = .fromSize(abi_size) } },
8257 };8227 };
82588228
...@@ -8947,9 +8917,9 @@ fn packedLoad(self: *CodeGen, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue)...@@ -8947,9 +8917,9 @@ fn packedLoad(self: *CodeGen, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue)
8947 defer self.register_manager.unlockReg(tmp_lock);8917 defer self.register_manager.unlockReg(tmp_lock);
89488918
8949 const hi_mcv = dst_mcv.address().offset(@intCast(val_bit_size / 64 * 8)).deref();8919 const hi_mcv = dst_mcv.address().offset(@intCast(val_bit_size / 64 * 8)).deref();
8950 try self.genSetReg(tmp_reg, Type.usize, hi_mcv, .{});8920 try self.genSetReg(tmp_reg, .usize, hi_mcv, .{});
8951 try self.truncateRegister(val_ty, tmp_reg);8921 try self.truncateRegister(val_ty, tmp_reg);
8952 try self.genCopy(Type.usize, hi_mcv, .{ .register = tmp_reg }, .{});8922 try self.genCopy(.usize, hi_mcv, .{ .register = tmp_reg }, .{});
8953 }8923 }
8954 }8924 }
8955 return;8925 return;
...@@ -9104,13 +9074,13 @@ fn airLoad(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -9104,13 +9074,13 @@ fn airLoad(self: *CodeGen, inst: Air.Inst.Index) !void {
9104 const high_reg = if (high_mcv.isRegister())9074 const high_reg = if (high_mcv.isRegister())
9105 high_mcv.getReg().?9075 high_mcv.getReg().?
9106 else9076 else
9107 try self.copyToTmpRegister(Type.usize, high_mcv);9077 try self.copyToTmpRegister(.usize, high_mcv);
9108 const high_lock = self.register_manager.lockReg(high_reg);9078 const high_lock = self.register_manager.lockReg(high_reg);
9109 defer if (high_lock) |lock| self.register_manager.unlockReg(lock);9079 defer if (high_lock) |lock| self.register_manager.unlockReg(lock);
91109080
9111 try self.truncateRegister(elem_ty, high_reg);9081 try self.truncateRegister(elem_ty, high_reg);
9112 if (!high_mcv.isRegister()) try self.genCopy(9082 if (!high_mcv.isRegister()) try self.genCopy(
9113 if (elem_size <= 8) elem_ty else Type.usize,9083 if (elem_size <= 8) elem_ty else .usize,
9114 high_mcv,9084 high_mcv,
9115 .{ .register = high_reg },9085 .{ .register = high_reg },
9116 .{},9086 .{},
...@@ -9183,14 +9153,14 @@ fn packedStore(self: *CodeGen, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue)...@@ -9183,14 +9153,14 @@ fn packedStore(self: *CodeGen, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue)
9183 .{ ._l, .sh },9153 .{ ._l, .sh },
9184 limb_ty,9154 limb_ty,
9185 tmp_mcv,9155 tmp_mcv,
9186 Type.u8,9156 .u8,
9187 .{ .immediate = src_bit_off },9157 .{ .immediate = src_bit_off },
9188 ),9158 ),
9189 1 => try self.genShiftBinOpMir(9159 1 => try self.genShiftBinOpMir(
9190 .{ ._r, .sh },9160 .{ ._r, .sh },
9191 limb_ty,9161 limb_ty,
9192 tmp_mcv,9162 tmp_mcv,
9193 Type.u8,9163 .u8,
9194 .{ .immediate = limb_abi_bits - src_bit_off },9164 .{ .immediate = limb_abi_bits - src_bit_off },
9195 ),9165 ),
9196 else => unreachable,9166 else => unreachable,
...@@ -9355,7 +9325,10 @@ fn airStructFieldVal(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -9355,7 +9325,10 @@ fn airStructFieldVal(self: *CodeGen, inst: Air.Inst.Index) !void {
9355 const src_mcv = try self.resolveInst(operand);9325 const src_mcv = try self.resolveInst(operand);
9356 const field_off: u32 = switch (container_ty.containerLayout(zcu)) {9326 const field_off: u32 = switch (container_ty.containerLayout(zcu)) {
9357 .auto, .@"extern" => @intCast(container_ty.structFieldOffset(extra.field_index, zcu) * 8),9327 .auto, .@"extern" => @intCast(container_ty.structFieldOffset(extra.field_index, zcu) * 8),
9358 .@"packed" => if (zcu.typeToStruct(container_ty)) |struct_obj| pt.structPackedFieldBitOffset(struct_obj, extra.field_index) else 0,9328 .@"packed" => if (zcu.typeToStruct(container_ty)) |struct_obj|
9329 pt.structPackedFieldBitOffset(struct_obj, extra.field_index)
9330 else
9331 0,
9359 };9332 };
93609333
9361 switch (src_mcv) {9334 switch (src_mcv) {
...@@ -9370,20 +9343,14 @@ fn airStructFieldVal(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -9370,20 +9343,14 @@ fn airStructFieldVal(self: *CodeGen, inst: Air.Inst.Index) !void {
9370 else if (field_off == 0)9343 else if (field_off == 0)
9371 (try self.copyToRegisterWithInstTracking(inst, field_ty, src_mcv)).register9344 (try self.copyToRegisterWithInstTracking(inst, field_ty, src_mcv)).register
9372 else9345 else
9373 try self.copyToTmpRegister(Type.usize, .{ .register = src_reg });9346 try self.copyToTmpRegister(.usize, .{ .register = src_reg });
9374 const dst_mcv: MCValue = .{ .register = dst_reg };9347 const dst_mcv: MCValue = .{ .register = dst_reg };
9375 const dst_lock = self.register_manager.lockReg(dst_reg);9348 const dst_lock = self.register_manager.lockReg(dst_reg);
9376 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);9349 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
93779350
9378 if (field_off > 0) {9351 if (field_off > 0) {
9379 try self.spillEflagsIfOccupied();9352 try self.spillEflagsIfOccupied();
9380 try self.genShiftBinOpMir(9353 try self.genShiftBinOpMir(.{ ._r, .sh }, .usize, dst_mcv, .u8, .{ .immediate = field_off });
9381 .{ ._r, .sh },
9382 Type.usize,
9383 dst_mcv,
9384 Type.u8,
9385 .{ .immediate = field_off },
9386 );
9387 }9354 }
9388 if (abi.RegisterClass.gp.isSet(RegisterManager.indexOfRegIntoTracked(dst_reg).?) and9355 if (abi.RegisterClass.gp.isSet(RegisterManager.indexOfRegIntoTracked(dst_reg).?) and
9389 container_ty.abiSize(zcu) * 8 > field_ty.bitSize(zcu))9356 container_ty.abiSize(zcu) * 8 > field_ty.bitSize(zcu))
...@@ -9421,13 +9388,7 @@ fn airStructFieldVal(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -9421,13 +9388,7 @@ fn airStructFieldVal(self: *CodeGen, inst: Air.Inst.Index) !void {
94219388
9422 if (field_off > 0) {9389 if (field_off > 0) {
9423 try self.spillEflagsIfOccupied();9390 try self.spillEflagsIfOccupied();
9424 try self.genShiftBinOpMir(9391 try self.genShiftBinOpMir(.{ ._r, .sh }, .u128, dst_mcv, .u8, .{ .immediate = field_off });
9425 .{ ._r, .sh },
9426 Type.u128,
9427 dst_mcv,
9428 Type.u8,
9429 .{ .immediate = field_off },
9430 );
9431 }9392 }
94329393
9433 if (field_bit_size <= 64) {9394 if (field_bit_size <= 64) {
...@@ -9451,20 +9412,14 @@ fn airStructFieldVal(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -9451,20 +9412,14 @@ fn airStructFieldVal(self: *CodeGen, inst: Air.Inst.Index) !void {
9451 try self.copyToRegisterWithInstTracking(inst, field_ty, dst_mcv);9412 try self.copyToRegisterWithInstTracking(inst, field_ty, dst_mcv);
9452 };9413 };
94539414
9454 const dst_reg = try self.copyToTmpRegister(Type.usize, .{ .register = src_reg });9415 const dst_reg = try self.copyToTmpRegister(.usize, .{ .register = src_reg });
9455 const dst_mcv = MCValue{ .register = dst_reg };9416 const dst_mcv = MCValue{ .register = dst_reg };
9456 const dst_lock = self.register_manager.lockReg(dst_reg);9417 const dst_lock = self.register_manager.lockReg(dst_reg);
9457 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);9418 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
94589419
9459 if (field_off % 64 > 0) {9420 if (field_off % 64 > 0) {
9460 try self.spillEflagsIfOccupied();9421 try self.spillEflagsIfOccupied();
9461 try self.genShiftBinOpMir(9422 try self.genShiftBinOpMir(.{ ._r, .sh }, .usize, dst_mcv, .u8, .{ .immediate = field_off % 64 });
9462 .{ ._r, .sh },
9463 Type.usize,
9464 dst_mcv,
9465 Type.u8,
9466 .{ .immediate = field_off % 64 },
9467 );
9468 }9423 }
9469 if (self.regExtraBits(field_ty) > 0) try self.truncateRegister(field_ty, dst_reg);9424 if (self.regExtraBits(field_ty) > 0) try self.truncateRegister(field_ty, dst_reg);
94709425
...@@ -9479,11 +9434,7 @@ fn airStructFieldVal(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -9479,11 +9434,7 @@ fn airStructFieldVal(self: *CodeGen, inst: Air.Inst.Index) !void {
9479 0 => if (self.reuseOperand(inst, extra.struct_operand, 0, src_mcv)) {9434 0 => if (self.reuseOperand(inst, extra.struct_operand, 0, src_mcv)) {
9480 self.eflags_inst = null; // actually stop tracking the overflow part9435 self.eflags_inst = null; // actually stop tracking the overflow part
9481 break :result .{ .register = ro.reg };9436 break :result .{ .register = ro.reg };
9482 } else break :result try self.copyToRegisterWithInstTracking(9437 } else break :result try self.copyToRegisterWithInstTracking(inst, .usize, .{ .register = ro.reg }),
9483 inst,
9484 Type.usize,
9485 .{ .register = ro.reg },
9486 ),
9487 // Get overflow bit.9438 // Get overflow bit.
9488 1 => if (self.reuseOperandAdvanced(inst, extra.struct_operand, 0, src_mcv, null)) {9439 1 => if (self.reuseOperandAdvanced(inst, extra.struct_operand, 0, src_mcv, null)) {
9489 self.eflags_inst = inst; // actually keep tracking the overflow part9440 self.eflags_inst = inst; // actually keep tracking the overflow part
...@@ -9541,9 +9492,9 @@ fn airStructFieldVal(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -9541,9 +9492,9 @@ fn airStructFieldVal(self: *CodeGen, inst: Air.Inst.Index) !void {
95419492
9542 const hi_mcv =9493 const hi_mcv =
9543 dst_mcv.address().offset(@intCast(field_bit_size / 64 * 8)).deref();9494 dst_mcv.address().offset(@intCast(field_bit_size / 64 * 8)).deref();
9544 try self.genSetReg(tmp_reg, Type.usize, hi_mcv, .{});9495 try self.genSetReg(tmp_reg, .usize, hi_mcv, .{});
9545 try self.truncateRegister(field_ty, tmp_reg);9496 try self.truncateRegister(field_ty, tmp_reg);
9546 try self.genCopy(Type.usize, hi_mcv, .{ .register = tmp_reg }, .{});9497 try self.genCopy(.usize, hi_mcv, .{ .register = tmp_reg }, .{});
9547 }9498 }
9548 break :result dst_mcv;9499 break :result dst_mcv;
9549 }9500 }
...@@ -9684,8 +9635,8 @@ fn genUnOp(self: *CodeGen, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_a...@@ -9684,8 +9635,8 @@ fn genUnOp(self: *CodeGen, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_a
9684 switch (tag) {9635 switch (tag) {
9685 .not => {9636 .not => {
9686 const limb_abi_size: u16 = @min(abi_size, 8);9637 const limb_abi_size: u16 = @min(abi_size, 8);
9687 const int_info = if (src_ty.ip_index == .bool_type)9638 const int_info: InternPool.Key.IntType = if (src_ty.ip_index == .bool_type)
9688 std.builtin.Type.Int{ .signedness = .unsigned, .bits = 1 }9639 .{ .signedness = .unsigned, .bits = 1 }
9689 else9640 else
9690 src_ty.intInfo(zcu);9641 src_ty.intInfo(zcu);
9691 var byte_off: i32 = 0;9642 var byte_off: i32 = 0;
...@@ -9718,9 +9669,9 @@ fn genUnOp(self: *CodeGen, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_a...@@ -9718,9 +9669,9 @@ fn genUnOp(self: *CodeGen, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_a
9718 defer self.register_manager.unlockReg(tmp_lock);9669 defer self.register_manager.unlockReg(tmp_lock);
97199670
9720 const hi_mcv = dst_mcv.address().offset(@intCast(bit_size / 64 * 8)).deref();9671 const hi_mcv = dst_mcv.address().offset(@intCast(bit_size / 64 * 8)).deref();
9721 try self.genSetReg(tmp_reg, Type.usize, hi_mcv, .{});9672 try self.genSetReg(tmp_reg, .usize, hi_mcv, .{});
9722 try self.truncateRegister(src_ty, tmp_reg);9673 try self.truncateRegister(src_ty, tmp_reg);
9723 try self.genCopy(Type.usize, hi_mcv, .{ .register = tmp_reg }, .{});9674 try self.genCopy(.usize, hi_mcv, .{ .register = tmp_reg }, .{});
9724 }9675 }
9725 }9676 }
9726 },9677 },
...@@ -9759,7 +9710,7 @@ fn genUnOpMir(self: *CodeGen, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv:...@@ -9759,7 +9710,7 @@ fn genUnOpMir(self: *CodeGen, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv:
9759 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);9710 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
9760 defer self.register_manager.unlockReg(addr_reg_lock);9711 defer self.register_manager.unlockReg(addr_reg_lock);
97619712
9762 try self.genSetReg(addr_reg, Type.usize, dst_mcv.address(), .{});9713 try self.genSetReg(addr_reg, .usize, dst_mcv.address(), .{});
9763 try self.asmMemory(mir_tag, .{ .base = .{ .reg = addr_reg }, .mod = .{ .rm = .{9714 try self.asmMemory(mir_tag, .{ .base = .{ .reg = addr_reg }, .mod = .{ .rm = .{
9764 .size = .fromSize(abi_size),9715 .size = .fromSize(abi_size),
9765 } } });9716 } } });
...@@ -10495,7 +10446,7 @@ fn genMulDivBinOp(...@@ -10495,7 +10446,7 @@ fn genMulDivBinOp(
10495 const mat_lhs_mcv = switch (lhs_mcv) {10446 const mat_lhs_mcv = switch (lhs_mcv) {
10496 .load_symbol => mat_lhs_mcv: {10447 .load_symbol => mat_lhs_mcv: {
10497 // TODO clean this up!10448 // TODO clean this up!
10498 const addr_reg = try self.copyToTmpRegister(Type.usize, lhs_mcv.address());10449 const addr_reg = try self.copyToTmpRegister(.usize, lhs_mcv.address());
10499 break :mat_lhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } };10450 break :mat_lhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } };
10500 },10451 },
10501 else => lhs_mcv,10452 else => lhs_mcv,
...@@ -10508,7 +10459,7 @@ fn genMulDivBinOp(...@@ -10508,7 +10459,7 @@ fn genMulDivBinOp(
10508 const mat_rhs_mcv = switch (rhs_mcv) {10459 const mat_rhs_mcv = switch (rhs_mcv) {
10509 .load_symbol => mat_rhs_mcv: {10460 .load_symbol => mat_rhs_mcv: {
10510 // TODO clean this up!10461 // TODO clean this up!
10511 const addr_reg = try self.copyToTmpRegister(Type.usize, rhs_mcv.address());10462 const addr_reg = try self.copyToTmpRegister(.usize, rhs_mcv.address());
10512 break :mat_rhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } };10463 break :mat_rhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } };
10513 },10464 },
10514 else => rhs_mcv,10465 else => rhs_mcv,
...@@ -10696,7 +10647,7 @@ fn genMulDivBinOp(...@@ -10696,7 +10647,7 @@ fn genMulDivBinOp(
10696 manyptr_u32_ty,10647 manyptr_u32_ty,
10697 manyptr_const_u32_ty,10648 manyptr_const_u32_ty,
10698 manyptr_const_u32_ty,10649 manyptr_const_u32_ty,
10699 Type.usize,10650 .usize,
10700 }, &.{10651 }, &.{
10701 dst_mcv.address(),10652 dst_mcv.address(),
10702 lhs_mcv.address(),10653 lhs_mcv.address(),
...@@ -12493,7 +12444,7 @@ fn genBinOp(...@@ -12493,7 +12444,7 @@ fn genBinOp(
12493 try not_mcv.mem(self, .{ .size = .fromSize(abi_size) })12444 try not_mcv.mem(self, .{ .size = .fromSize(abi_size) })
12494 else12445 else
12495 .{ .base = .{12446 .{ .base = .{
12496 .reg = try self.copyToTmpRegister(Type.usize, not_mcv.address()),12447 .reg = try self.copyToTmpRegister(.usize, not_mcv.address()),
12497 }, .mod = .{ .rm = .{ .size = .fromSize(abi_size) } } };12448 }, .mod = .{ .rm = .{ .size = .fromSize(abi_size) } } };
12498 switch (mir_tag[0]) {12449 switch (mir_tag[0]) {
12499 .vp_b, .vp_d, .vp_q, .vp_w => try self.asmRegisterRegisterMemory(12450 .vp_b, .vp_d, .vp_q, .vp_w => try self.asmRegisterRegisterMemory(
...@@ -12757,7 +12708,7 @@ fn genBinOpMir(...@@ -12757,7 +12708,7 @@ fn genBinOpMir(
12757 const dst_addr_lock = self.register_manager.lockRegAssumeUnused(dst_addr_reg);12708 const dst_addr_lock = self.register_manager.lockRegAssumeUnused(dst_addr_reg);
12758 errdefer self.register_manager.unlockReg(dst_addr_lock);12709 errdefer self.register_manager.unlockReg(dst_addr_lock);
1275912710
12760 try self.genSetReg(dst_addr_reg, Type.usize, dst_mcv.address(), .{});12711 try self.genSetReg(dst_addr_reg, .usize, dst_mcv.address(), .{});
12761 break :dst .{ .addr_reg = dst_addr_reg, .addr_lock = dst_addr_lock };12712 break :dst .{ .addr_reg = dst_addr_reg, .addr_lock = dst_addr_lock };
12762 },12713 },
12763 .load_frame => null,12714 .load_frame => null,
...@@ -12808,7 +12759,7 @@ fn genBinOpMir(...@@ -12808,7 +12759,7 @@ fn genBinOpMir(
12808 const src_addr_lock = self.register_manager.lockRegAssumeUnused(src_addr_reg);12759 const src_addr_lock = self.register_manager.lockRegAssumeUnused(src_addr_reg);
12809 errdefer self.register_manager.unlockReg(src_addr_lock);12760 errdefer self.register_manager.unlockReg(src_addr_lock);
1281012761
12811 try self.genSetReg(src_addr_reg, Type.usize, resolved_src_mcv.address(), .{});12762 try self.genSetReg(src_addr_reg, .usize, resolved_src_mcv.address(), .{});
12812 break :src .{ .addr_reg = src_addr_reg, .addr_lock = src_addr_lock };12763 break :src .{ .addr_reg = src_addr_reg, .addr_lock = src_addr_lock };
12813 },12764 },
12814 };12765 };
...@@ -12816,9 +12767,9 @@ fn genBinOpMir(...@@ -12816,9 +12767,9 @@ fn genBinOpMir(
1281612767
12817 const ty_signedness =12768 const ty_signedness =
12818 if (ty.isAbiInt(zcu)) ty.intInfo(zcu).signedness else .unsigned;12769 if (ty.isAbiInt(zcu)) ty.intInfo(zcu).signedness else .unsigned;
12819 const limb_ty = if (abi_size <= 8) ty else switch (ty_signedness) {12770 const limb_ty: Type = if (abi_size <= 8) ty else switch (ty_signedness) {
12820 .signed => Type.usize,12771 .signed => .usize,
12821 .unsigned => Type.isize,12772 .unsigned => .isize,
12822 };12773 };
12823 var limb_i: usize = 0;12774 var limb_i: usize = 0;
12824 var off: i32 = 0;12775 var off: i32 = 0;
...@@ -13310,13 +13261,13 @@ fn genLocalDebugInfo(...@@ -13310,13 +13261,13 @@ fn genLocalDebugInfo(
1331013261
13311fn airRetAddr(self: *CodeGen, inst: Air.Inst.Index) !void {13262fn airRetAddr(self: *CodeGen, inst: Air.Inst.Index) !void {
13312 const dst_mcv = try self.allocRegOrMem(inst, true);13263 const dst_mcv = try self.allocRegOrMem(inst, true);
13313 try self.genCopy(Type.usize, dst_mcv, .{ .load_frame = .{ .index = .ret_addr } }, .{});13264 try self.genCopy(.usize, dst_mcv, .{ .load_frame = .{ .index = .ret_addr } }, .{});
13314 return self.finishAir(inst, dst_mcv, .{ .none, .none, .none });13265 return self.finishAir(inst, dst_mcv, .{ .none, .none, .none });
13315}13266}
1331613267
13317fn airFrameAddress(self: *CodeGen, inst: Air.Inst.Index) !void {13268fn airFrameAddress(self: *CodeGen, inst: Air.Inst.Index) !void {
13318 const dst_mcv = try self.allocRegOrMem(inst, true);13269 const dst_mcv = try self.allocRegOrMem(inst, true);
13319 try self.genCopy(Type.usize, dst_mcv, .{ .lea_frame = .{ .index = .base_ptr } }, .{});13270 try self.genCopy(.usize, dst_mcv, .{ .lea_frame = .{ .index = .base_ptr } }, .{});
13320 return self.finishAir(inst, dst_mcv, .{ .none, .none, .none });13271 return self.finishAir(inst, dst_mcv, .{ .none, .none, .none });
13321}13272}
1332213273
...@@ -13461,13 +13412,10 @@ fn genCall(self: *CodeGen, info: union(enum) {...@@ -13461,13 +13412,10 @@ fn genCall(self: *CodeGen, info: union(enum) {
13461 defer self.register_manager.unlockReg(index_lock);13412 defer self.register_manager.unlockReg(index_lock);
1346213413
13463 const src_mem: Memory = if (src_arg.isBase()) try src_arg.mem(self, .{ .size = .dword }) else .{13414 const src_mem: Memory = if (src_arg.isBase()) try src_arg.mem(self, .{ .size = .dword }) else .{
13464 .base = .{ .reg = try self.copyToTmpRegister(13415 .base = .{ .reg = try self.copyToTmpRegister(.usize, switch (src_arg) {
13465 Type.usize,13416 else => src_arg,
13466 switch (src_arg) {13417 .air_ref => |src_ref| try self.resolveInst(src_ref),
13467 else => src_arg,13418 }.address()) },
13468 .air_ref => |src_ref| try self.resolveInst(src_ref),
13469 }.address(),
13470 ) },
13471 .mod = .{ .rm = .{ .size = .dword } },13419 .mod = .{ .rm = .{ .size = .dword } },
13472 };13420 };
13473 const src_lock = switch (src_mem.base) {13421 const src_lock = switch (src_mem.base) {
...@@ -13519,7 +13467,7 @@ fn genCall(self: *CodeGen, info: union(enum) {...@@ -13519,7 +13467,7 @@ fn genCall(self: *CodeGen, info: union(enum) {
13519 .indirect => |reg_off| {13467 .indirect => |reg_off| {
13520 const ret_ty: Type = .fromInterned(fn_info.return_type);13468 const ret_ty: Type = .fromInterned(fn_info.return_type);
13521 const frame_index = try self.allocFrameIndex(.initSpill(ret_ty, zcu));13469 const frame_index = try self.allocFrameIndex(.initSpill(ret_ty, zcu));
13522 try self.genSetReg(reg_off.reg, Type.usize, .{13470 try self.genSetReg(reg_off.reg, .usize, .{
13523 .lea_frame = .{ .index = frame_index, .off = -reg_off.off },13471 .lea_frame = .{ .index = frame_index, .off = -reg_off.off },
13524 }, .{});13472 }, .{});
13525 call_info.return_value.short = .{ .load_frame = .{ .index = frame_index } };13473 call_info.return_value.short = .{ .load_frame = .{ .index = frame_index } };
...@@ -13548,13 +13496,13 @@ fn genCall(self: *CodeGen, info: union(enum) {...@@ -13548,13 +13496,13 @@ fn genCall(self: *CodeGen, info: union(enum) {
13548 },13496 },
13549 },13497 },
13550 .register_pair => try self.genCopy(arg_ty, dst_arg, src_arg, .{}),13498 .register_pair => try self.genCopy(arg_ty, dst_arg, src_arg, .{}),
13551 .indirect => |reg_off| try self.genSetReg(reg_off.reg, Type.usize, .{13499 .indirect => |reg_off| try self.genSetReg(reg_off.reg, .usize, .{
13552 .lea_frame = .{ .index = frame_index, .off = -reg_off.off },13500 .lea_frame = .{ .index = frame_index, .off = -reg_off.off },
13553 }, .{}),13501 }, .{}),
13554 .elementwise_regs_then_frame => |regs_frame_addr| {13502 .elementwise_regs_then_frame => |regs_frame_addr| {
13555 const src_mem: Memory = if (src_arg.isBase()) try src_arg.mem(self, .{ .size = .dword }) else .{13503 const src_mem: Memory = if (src_arg.isBase()) try src_arg.mem(self, .{ .size = .dword }) else .{
13556 .base = .{ .reg = try self.copyToTmpRegister(13504 .base = .{ .reg = try self.copyToTmpRegister(
13557 Type.usize,13505 .usize,
13558 switch (src_arg) {13506 switch (src_arg) {
13559 else => src_arg,13507 else => src_arg,
13560 .air_ref => |src_ref| try self.resolveInst(src_ref),13508 .air_ref => |src_ref| try self.resolveInst(src_ref),
...@@ -13604,7 +13552,7 @@ fn genCall(self: *CodeGen, info: union(enum) {...@@ -13604,7 +13552,7 @@ fn genCall(self: *CodeGen, info: union(enum) {
13604 } else if (self.bin_file.cast(.coff)) |coff_file| {13552 } else if (self.bin_file.cast(.coff)) |coff_file| {
13605 const atom = try coff_file.getOrCreateAtomForNav(func.owner_nav);13553 const atom = try coff_file.getOrCreateAtomForNav(func.owner_nav);
13606 const sym_index = coff_file.getAtom(atom).getSymbolIndex().?;13554 const sym_index = coff_file.getAtom(atom).getSymbolIndex().?;
13607 try self.genSetReg(.rax, Type.usize, .{ .lea_got = sym_index }, .{});13555 try self.genSetReg(.rax, .usize, .{ .lea_got = sym_index }, .{});
13608 try self.asmRegister(.{ ._, .call }, .rax);13556 try self.asmRegister(.{ ._, .call }, .rax);
13609 } else if (self.bin_file.cast(.macho)) |macho_file| {13557 } else if (self.bin_file.cast(.macho)) |macho_file| {
13610 const zo = macho_file.getZigObject().?;13558 const zo = macho_file.getZigObject().?;
...@@ -13644,7 +13592,7 @@ fn genCall(self: *CodeGen, info: union(enum) {...@@ -13644,7 +13592,7 @@ fn genCall(self: *CodeGen, info: union(enum) {
13644 }13592 }
13645 } else {13593 } else {
13646 assert(self.typeOf(callee).zigTypeTag(zcu) == .pointer);13594 assert(self.typeOf(callee).zigTypeTag(zcu) == .pointer);
13647 try self.genSetReg(.rax, Type.usize, .{ .air_ref = callee }, .{});13595 try self.genSetReg(.rax, .usize, .{ .air_ref = callee }, .{});
13648 try self.asmRegister(.{ ._, .call }, .rax);13596 try self.asmRegister(.{ ._, .call }, .rax);
13649 },13597 },
13650 .lib => |lib| if (self.bin_file.cast(.elf)) |elf_file| {13598 .lib => |lib| if (self.bin_file.cast(.elf)) |elf_file| {
...@@ -13676,7 +13624,7 @@ fn airRet(self: *CodeGen, inst: Air.Inst.Index, safety: bool) !void {...@@ -13676,7 +13624,7 @@ fn airRet(self: *CodeGen, inst: Air.Inst.Index, safety: bool) !void {
13676 const lock = self.register_manager.lockRegAssumeUnused(reg_off.reg);13624 const lock = self.register_manager.lockRegAssumeUnused(reg_off.reg);
13677 defer self.register_manager.unlockReg(lock);13625 defer self.register_manager.unlockReg(lock);
1367813626
13679 try self.genSetReg(reg_off.reg, Type.usize, self.ret_mcv.long, .{});13627 try self.genSetReg(reg_off.reg, .usize, self.ret_mcv.long, .{});
13680 try self.genSetMem(13628 try self.genSetMem(
13681 .{ .reg = reg_off.reg },13629 .{ .reg = reg_off.reg },
13682 reg_off.off,13630 reg_off.off,
...@@ -13775,7 +13723,7 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v...@@ -13775,7 +13723,7 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v
13775 floatCompilerRtAbiName(float_bits),13723 floatCompilerRtAbiName(float_bits),
13776 }) catch unreachable,13724 }) catch unreachable,
13777 } }, &.{ ty, ty }, &.{ .{ .air_ref = bin_op.lhs }, .{ .air_ref = bin_op.rhs } });13725 } }, &.{ ty, ty }, &.{ .{ .air_ref = bin_op.lhs }, .{ .air_ref = bin_op.rhs } });
13778 try self.genBinOpMir(.{ ._, .@"test" }, Type.i32, ret, ret);13726 try self.genBinOpMir(.{ ._, .@"test" }, .i32, ret, ret);
13779 break :result switch (op) {13727 break :result switch (op) {
13780 .eq => .e,13728 .eq => .e,
13781 .neq => .ne,13729 .neq => .ne,
...@@ -13938,12 +13886,7 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v...@@ -13938,12 +13886,7 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v
13938 self.register_manager.lockRegAssumeUnused(dst_addr_reg);13886 self.register_manager.lockRegAssumeUnused(dst_addr_reg);
13939 errdefer self.register_manager.unlockReg(dst_addr_lock);13887 errdefer self.register_manager.unlockReg(dst_addr_lock);
1394013888
13941 try self.genSetReg(13889 try self.genSetReg(dst_addr_reg, .usize, resolved_dst_mcv.address(), .{});
13942 dst_addr_reg,
13943 Type.usize,
13944 resolved_dst_mcv.address(),
13945 .{},
13946 );
13947 break :dst .{13890 break :dst .{
13948 .addr_reg = dst_addr_reg,13891 .addr_reg = dst_addr_reg,
13949 .addr_lock = dst_addr_lock,13892 .addr_lock = dst_addr_lock,
...@@ -14000,12 +13943,7 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v...@@ -14000,12 +13943,7 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v
14000 self.register_manager.lockRegAssumeUnused(src_addr_reg);13943 self.register_manager.lockRegAssumeUnused(src_addr_reg);
14001 errdefer self.register_manager.unlockReg(src_addr_lock);13944 errdefer self.register_manager.unlockReg(src_addr_lock);
1400213945
14003 try self.genSetReg(13946 try self.genSetReg(src_addr_reg, .usize, resolved_src_mcv.address(), .{});
14004 src_addr_reg,
14005 Type.usize,
14006 resolved_src_mcv.address(),
14007 .{},
14008 );
14009 break :src .{13947 break :src .{
14010 .addr_reg = src_addr_reg,13948 .addr_reg = src_addr_reg,
14011 .addr_lock = src_addr_lock,13949 .addr_lock = src_addr_lock,
...@@ -14026,7 +13964,7 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v...@@ -14026,7 +13964,7 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v
14026 const off = limb_i * 8;13964 const off = limb_i * 8;
14027 const tmp_reg = regs[@min(limb_i, 1)].to64();13965 const tmp_reg = regs[@min(limb_i, 1)].to64();
1402813966
14029 try self.genSetReg(tmp_reg, Type.usize, if (dst_info) |info| .{13967 try self.genSetReg(tmp_reg, .usize, if (dst_info) |info| .{
14030 .indirect = .{ .reg = info.addr_reg, .off = off },13968 .indirect = .{ .reg = info.addr_reg, .off = off },
14031 } else switch (resolved_dst_mcv) {13969 } else switch (resolved_dst_mcv) {
14032 inline .register_pair,13970 inline .register_pair,
...@@ -14049,7 +13987,7 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v...@@ -14049,7 +13987,7 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v
1404913987
14050 try self.genBinOpMir(13988 try self.genBinOpMir(
14051 .{ ._, .xor },13989 .{ ._, .xor },
14052 Type.usize,13990 .usize,
14053 .{ .register = tmp_reg },13991 .{ .register = tmp_reg },
14054 if (src_info) |info| .{13992 if (src_info) |info| .{
14055 .indirect = .{ .reg = info.addr_reg, .off = off },13993 .indirect = .{ .reg = info.addr_reg, .off = off },
...@@ -14244,7 +14182,7 @@ fn genTry(...@@ -14244,7 +14182,7 @@ fn genTry(
14244 else14182 else
14245 try self.isErr(null, operand_ty, operand_mcv);14183 try self.isErr(null, operand_ty, operand_mcv);
1424614184
14247 const reloc = try self.genCondBrMir(Type.anyerror, is_err_mcv);14185 const reloc = try self.genCondBrMir(.anyerror, is_err_mcv);
1424814186
14249 if (self.liveness.operandDies(inst, 0)) {14187 if (self.liveness.operandDies(inst, 0)) {
14250 if (operand.toIndex()) |operand_inst| try self.processDeath(operand_inst);14188 if (operand.toIndex()) |operand_inst| try self.processDeath(operand_inst);
...@@ -14406,7 +14344,7 @@ fn isNull(self: *CodeGen, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue)...@@ -14406,7 +14344,7 @@ fn isNull(self: *CodeGen, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue)
14406 const some_info: struct { off: u31, ty: Type } = if (opt_ty.optionalReprIsPayload(zcu))14344 const some_info: struct { off: u31, ty: Type } = if (opt_ty.optionalReprIsPayload(zcu))
14407 .{ .off = 0, .ty = if (pl_ty.isSlice(zcu)) pl_ty.slicePtrFieldType(zcu) else pl_ty }14345 .{ .off = 0, .ty = if (pl_ty.isSlice(zcu)) pl_ty.slicePtrFieldType(zcu) else pl_ty }
14408 else14346 else
14409 .{ .off = @intCast(pl_ty.abiSize(zcu)), .ty = Type.bool };14347 .{ .off = @intCast(pl_ty.abiSize(zcu)), .ty = .bool };
1441014348
14411 self.eflags_inst = inst;14349 self.eflags_inst = inst;
14412 switch (opt_mcv) {14350 switch (opt_mcv) {
...@@ -14481,7 +14419,7 @@ fn isNull(self: *CodeGen, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue)...@@ -14481,7 +14419,7 @@ fn isNull(self: *CodeGen, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue)
14481 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);14419 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
14482 defer self.register_manager.unlockReg(addr_reg_lock);14420 defer self.register_manager.unlockReg(addr_reg_lock);
1448314421
14484 try self.genSetReg(addr_reg, Type.usize, opt_mcv.address(), .{});14422 try self.genSetReg(addr_reg, .usize, opt_mcv.address(), .{});
14485 const some_abi_size: u32 = @intCast(some_info.ty.abiSize(zcu));14423 const some_abi_size: u32 = @intCast(some_info.ty.abiSize(zcu));
14486 try self.asmMemoryImmediate(14424 try self.asmMemoryImmediate(
14487 .{ ._, .cmp },14425 .{ ._, .cmp },
...@@ -14536,7 +14474,7 @@ fn isNullPtr(self: *CodeGen, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValu...@@ -14536,7 +14474,7 @@ fn isNullPtr(self: *CodeGen, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValu
14536 const some_info: struct { off: i32, ty: Type } = if (opt_ty.optionalReprIsPayload(zcu))14474 const some_info: struct { off: i32, ty: Type } = if (opt_ty.optionalReprIsPayload(zcu))
14537 .{ .off = 0, .ty = if (pl_ty.isSlice(zcu)) pl_ty.slicePtrFieldType(zcu) else pl_ty }14475 .{ .off = 0, .ty = if (pl_ty.isSlice(zcu)) pl_ty.slicePtrFieldType(zcu) else pl_ty }
14538 else14476 else
14539 .{ .off = @intCast(pl_ty.abiSize(zcu)), .ty = Type.bool };14477 .{ .off = @intCast(pl_ty.abiSize(zcu)), .ty = .bool };
1454014478
14541 const ptr_reg = switch (ptr_mcv) {14479 const ptr_reg = switch (ptr_mcv) {
14542 .register => |reg| reg,14480 .register => |reg| reg,
...@@ -14582,22 +14520,17 @@ fn isErr(self: *CodeGen, maybe_inst: ?Air.Inst.Index, eu_ty: Type, eu_mcv: MCVal...@@ -14582,22 +14520,17 @@ fn isErr(self: *CodeGen, maybe_inst: ?Air.Inst.Index, eu_ty: Type, eu_mcv: MCVal
14582 .{ ._r, .sh },14520 .{ ._r, .sh },
14583 eu_ty,14521 eu_ty,
14584 .{ .register = tmp_reg },14522 .{ .register = tmp_reg },
14585 Type.u8,14523 .u8,
14586 .{ .immediate = @as(u6, @intCast(err_off * 8)) },14524 .{ .immediate = @as(u6, @intCast(err_off * 8)) },
14587 );14525 );
14588 } else {14526 } else {
14589 try self.truncateRegister(Type.anyerror, tmp_reg);14527 try self.truncateRegister(.anyerror, tmp_reg);
14590 }14528 }
14591 try self.genBinOpMir(14529 try self.genBinOpMir(.{ ._, .cmp }, .anyerror, .{ .register = tmp_reg }, .{ .immediate = 0 });
14592 .{ ._, .cmp },
14593 Type.anyerror,
14594 .{ .register = tmp_reg },
14595 .{ .immediate = 0 },
14596 );
14597 },14530 },
14598 .load_frame => |frame_addr| try self.genBinOpMir(14531 .load_frame => |frame_addr| try self.genBinOpMir(
14599 .{ ._, .cmp },14532 .{ ._, .cmp },
14600 Type.anyerror,14533 .anyerror,
14601 .{ .load_frame = .{14534 .{ .load_frame = .{
14602 .index = frame_addr.index,14535 .index = frame_addr.index,
14603 .off = frame_addr.off + err_off,14536 .off = frame_addr.off + err_off,
...@@ -14633,7 +14566,7 @@ fn isErrPtr(self: *CodeGen, maybe_inst: ?Air.Inst.Index, ptr_ty: Type, ptr_mcv:...@@ -14633,7 +14566,7 @@ fn isErrPtr(self: *CodeGen, maybe_inst: ?Air.Inst.Index, ptr_ty: Type, ptr_mcv:
14633 .{14566 .{
14634 .base = .{ .reg = ptr_reg },14567 .base = .{ .reg = ptr_reg },
14635 .mod = .{ .rm = .{14568 .mod = .{ .rm = .{
14636 .size = self.memSize(Type.anyerror),14569 .size = self.memSize(.anyerror),
14637 .disp = err_off,14570 .disp = err_off,
14638 } },14571 } },
14639 },14572 },
...@@ -15200,7 +15133,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -15200,7 +15133,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
15200 .register, .register_offset, .lea_frame => break :arg ptr_mcv.deref(),15133 .register, .register_offset, .lea_frame => break :arg ptr_mcv.deref(),
15201 else => {},15134 else => {},
15202 }15135 }
15203 break :arg .{ .indirect = .{ .reg = try self.copyToTmpRegister(Type.usize, ptr_mcv) } };15136 break :arg .{ .indirect = .{ .reg = try self.copyToTmpRegister(.usize, ptr_mcv) } };
15204 };15137 };
15205 };15138 };
15206 if (arg_mcv.getReg()) |reg| if (RegisterManager.indexOfRegIntoTracked(reg)) |_| {15139 if (arg_mcv.getReg()) |reg| if (RegisterManager.indexOfRegIntoTracked(reg)) |_| {
...@@ -15262,7 +15195,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -15262,7 +15195,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
15262 try self.genCopy(ty, temp_mcv, input_mcv, .{});15195 try self.genCopy(ty, temp_mcv, input_mcv, .{});
15263 break :arg temp_mcv;15196 break :arg temp_mcv;
15264 };15197 };
15265 try self.genSetReg(addr_reg, Type.usize, input_mcv.address(), .{});15198 try self.genSetReg(addr_reg, .usize, input_mcv.address(), .{});
15266 break :arg .{ .indirect = .{ .reg = addr_reg } };15199 break :arg .{ .indirect = .{ .reg = addr_reg } };
15267 } else if (std.mem.eql(u8, constraint, "g") or15200 } else if (std.mem.eql(u8, constraint, "g") or
15268 std.mem.eql(u8, constraint, "rm") or std.mem.eql(u8, constraint, "mr") or15201 std.mem.eql(u8, constraint, "rm") or std.mem.eql(u8, constraint, "mr") or
...@@ -15539,11 +15472,11 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -15539,11 +15472,11 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
15539 else15472 else
15540 return self.fail("invalid modifier: '{s}'", .{modifier}),15473 return self.fail("invalid modifier: '{s}'", .{modifier}),
15541 .lea_got => |sym_index| if (std.mem.eql(u8, modifier, "P"))15474 .lea_got => |sym_index| if (std.mem.eql(u8, modifier, "P"))
15542 .{ .reg = try self.copyToTmpRegister(Type.usize, .{ .lea_got = sym_index }) }15475 .{ .reg = try self.copyToTmpRegister(.usize, .{ .lea_got = sym_index }) }
15543 else15476 else
15544 return self.fail("invalid modifier: '{s}'", .{modifier}),15477 return self.fail("invalid modifier: '{s}'", .{modifier}),
15545 .lea_symbol => |sym_off| if (std.mem.eql(u8, modifier, "P"))15478 .lea_symbol => |sym_off| if (std.mem.eql(u8, modifier, "P"))
15546 .{ .reg = try self.copyToTmpRegister(Type.usize, .{ .lea_symbol = sym_off }) }15479 .{ .reg = try self.copyToTmpRegister(.usize, .{ .lea_symbol = sym_off }) }
15547 else15480 else
15548 return self.fail("invalid modifier: '{s}'", .{modifier}),15481 return self.fail("invalid modifier: '{s}'", .{modifier}),
15549 else => return self.fail("invalid constraint: '{s}'", .{op_str}),15482 else => return self.fail("invalid constraint: '{s}'", .{op_str}),
...@@ -16099,7 +16032,7 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C...@@ -16099,7 +16032,7 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C
16099 const src_addr_lock = self.register_manager.lockRegAssumeUnused(src_addr_reg);16032 const src_addr_lock = self.register_manager.lockRegAssumeUnused(src_addr_reg);
16100 errdefer self.register_manager.unlockReg(src_addr_lock);16033 errdefer self.register_manager.unlockReg(src_addr_lock);
1610116034
16102 try self.genSetReg(src_addr_reg, Type.usize, src_mcv.address(), opts);16035 try self.genSetReg(src_addr_reg, .usize, src_mcv.address(), opts);
16103 break :src .{ .addr_reg = src_addr_reg, .addr_lock = src_addr_lock };16036 break :src .{ .addr_reg = src_addr_reg, .addr_lock = src_addr_lock };
16104 },16037 },
16105 .air_ref => |src_ref| return self.genCopy(16038 .air_ref => |src_ref| return self.genCopy(
...@@ -16146,7 +16079,7 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C...@@ -16146,7 +16079,7 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C
16146 else => unreachable,16079 else => unreachable,
16147 }16080 }
1614816081
16149 const addr_reg = try self.copyToTmpRegister(Type.usize, dst_mcv.address());16082 const addr_reg = try self.copyToTmpRegister(.usize, dst_mcv.address());
16150 const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);16083 const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
16151 defer self.register_manager.unlockReg(addr_lock);16084 defer self.register_manager.unlockReg(addr_lock);
1615216085
...@@ -16445,7 +16378,7 @@ fn genSetReg(...@@ -16445,7 +16378,7 @@ fn genSetReg(
16445 else => unreachable,16378 else => unreachable,
16446 }16379 }
1644716380
16448 const addr_reg = try self.copyToTmpRegister(Type.usize, src_mcv.address());16381 const addr_reg = try self.copyToTmpRegister(.usize, src_mcv.address());
16449 const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);16382 const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
16450 defer self.register_manager.unlockReg(addr_lock);16383 defer self.register_manager.unlockReg(addr_lock);
1645116384
...@@ -16656,7 +16589,7 @@ fn genSetMem(...@@ -16656,7 +16589,7 @@ fn genSetMem(
16656 try self.genSetMem(16589 try self.genSetMem(
16657 base,16590 base,
16658 disp + @as(i32, @intCast(child_ty.abiSize(zcu))),16591 disp + @as(i32, @intCast(child_ty.abiSize(zcu))),
16659 Type.bool,16592 .bool,
16660 .{ .eflags = ro.eflags },16593 .{ .eflags = ro.eflags },
16661 opts,16594 opts,
16662 );16595 );
...@@ -16732,9 +16665,9 @@ fn genSetMem(...@@ -16732,9 +16665,9 @@ fn genSetMem(
1673216665
16733fn genInlineMemcpy(self: *CodeGen, dst_ptr: MCValue, src_ptr: MCValue, len: MCValue) InnerError!void {16666fn genInlineMemcpy(self: *CodeGen, dst_ptr: MCValue, src_ptr: MCValue, len: MCValue) InnerError!void {
16734 try self.spillRegisters(&.{ .rsi, .rdi, .rcx });16667 try self.spillRegisters(&.{ .rsi, .rdi, .rcx });
16735 try self.genSetReg(.rsi, Type.usize, src_ptr, .{});16668 try self.genSetReg(.rsi, .usize, src_ptr, .{});
16736 try self.genSetReg(.rdi, Type.usize, dst_ptr, .{});16669 try self.genSetReg(.rdi, .usize, dst_ptr, .{});
16737 try self.genSetReg(.rcx, Type.usize, len, .{});16670 try self.genSetReg(.rcx, .usize, len, .{});
16738 try self.asmOpOnly(.{ .@"rep _sb", .mov });16671 try self.asmOpOnly(.{ .@"rep _sb", .mov });
16739}16672}
1674016673
...@@ -16746,9 +16679,9 @@ fn genInlineMemset(...@@ -16746,9 +16679,9 @@ fn genInlineMemset(
16746 opts: CopyOptions,16679 opts: CopyOptions,
16747) InnerError!void {16680) InnerError!void {
16748 try self.spillRegisters(&.{ .rdi, .al, .rcx });16681 try self.spillRegisters(&.{ .rdi, .al, .rcx });
16749 try self.genSetReg(.rdi, Type.usize, dst_ptr, .{});16682 try self.genSetReg(.rdi, .usize, dst_ptr, .{});
16750 try self.genSetReg(.al, Type.u8, value, opts);16683 try self.genSetReg(.al, .u8, value, opts);
16751 try self.genSetReg(.rcx, Type.usize, len, .{});16684 try self.genSetReg(.rcx, .usize, len, .{});
16752 try self.asmOpOnly(.{ .@"rep _sb", .sto });16685 try self.asmOpOnly(.{ .@"rep _sb", .sto });
16753}16686}
1675416687
...@@ -16791,10 +16724,10 @@ fn genLazySymbolRef(...@@ -16791,10 +16724,10 @@ fn genLazySymbolRef(
16791 return self.fail("{s} creating lazy symbol", .{@errorName(err)});16724 return self.fail("{s} creating lazy symbol", .{@errorName(err)});
16792 if (self.mod.pic) {16725 if (self.mod.pic) {
16793 switch (tag) {16726 switch (tag) {
16794 .lea, .call => try self.genSetReg(reg, Type.usize, .{16727 .lea, .call => try self.genSetReg(reg, .usize, .{
16795 .lea_symbol = .{ .sym_index = sym_index },16728 .lea_symbol = .{ .sym_index = sym_index },
16796 }, .{}),16729 }, .{}),
16797 .mov => try self.genSetReg(reg, Type.usize, .{16730 .mov => try self.genSetReg(reg, .usize, .{
16798 .load_symbol = .{ .sym_index = sym_index },16731 .load_symbol = .{ .sym_index = sym_index },
16799 }, .{}),16732 }, .{}),
16800 else => unreachable,16733 else => unreachable,
...@@ -16844,8 +16777,8 @@ fn genLazySymbolRef(...@@ -16844,8 +16777,8 @@ fn genLazySymbolRef(
16844 return self.fail("{s} creating lazy symbol", .{@errorName(err)});16777 return self.fail("{s} creating lazy symbol", .{@errorName(err)});
16845 const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?;16778 const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?;
16846 switch (tag) {16779 switch (tag) {
16847 .lea, .call => try self.genSetReg(reg, Type.usize, .{ .lea_got = sym_index }, .{}),16780 .lea, .call => try self.genSetReg(reg, .usize, .{ .lea_got = sym_index }, .{}),
16848 .mov => try self.genSetReg(reg, Type.usize, .{ .load_got = sym_index }, .{}),16781 .mov => try self.genSetReg(reg, .usize, .{ .load_got = sym_index }, .{}),
16849 else => unreachable,16782 else => unreachable,
16850 }16783 }
16851 switch (tag) {16784 switch (tag) {
...@@ -16859,10 +16792,10 @@ fn genLazySymbolRef(...@@ -16859,10 +16792,10 @@ fn genLazySymbolRef(
16859 return self.fail("{s} creating lazy symbol", .{@errorName(err)});16792 return self.fail("{s} creating lazy symbol", .{@errorName(err)});
16860 const sym = zo.symbols.items[sym_index];16793 const sym = zo.symbols.items[sym_index];
16861 switch (tag) {16794 switch (tag) {
16862 .lea, .call => try self.genSetReg(reg, Type.usize, .{16795 .lea, .call => try self.genSetReg(reg, .usize, .{
16863 .lea_symbol = .{ .sym_index = sym.nlist_idx },16796 .lea_symbol = .{ .sym_index = sym.nlist_idx },
16864 }, .{}),16797 }, .{}),
16865 .mov => try self.genSetReg(reg, Type.usize, .{16798 .mov => try self.genSetReg(reg, .usize, .{
16866 .load_symbol = .{ .sym_index = sym.nlist_idx },16799 .load_symbol = .{ .sym_index = sym.nlist_idx },
16867 }, .{}),16800 }, .{}),
16868 else => unreachable,16801 else => unreachable,
...@@ -16932,7 +16865,7 @@ fn airBitCast(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -16932,7 +16865,7 @@ fn airBitCast(self: *CodeGen, inst: Air.Inst.Index) !void {
16932 const bit_size = dst_ty.bitSize(zcu);16865 const bit_size = dst_ty.bitSize(zcu);
16933 if (abi_size * 8 <= bit_size or dst_ty.isVector(zcu)) break :result dst_mcv;16866 if (abi_size * 8 <= bit_size or dst_ty.isVector(zcu)) break :result dst_mcv;
1693416867
16935 const dst_limbs_len = std.math.divCeil(i32, @intCast(bit_size), 64) catch unreachable;16868 const dst_limbs_len = std.math.divCeil(u31, @intCast(bit_size), 64) catch unreachable;
16936 const high_mcv: MCValue = switch (dst_mcv) {16869 const high_mcv: MCValue = switch (dst_mcv) {
16937 .register => |dst_reg| .{ .register = dst_reg },16870 .register => |dst_reg| .{ .register = dst_reg },
16938 .register_pair => |dst_regs| .{ .register = dst_regs[1] },16871 .register_pair => |dst_regs| .{ .register = dst_regs[1] },
...@@ -16941,17 +16874,43 @@ fn airBitCast(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -16941,17 +16874,43 @@ fn airBitCast(self: *CodeGen, inst: Air.Inst.Index) !void {
16941 const high_reg = if (high_mcv.isRegister())16874 const high_reg = if (high_mcv.isRegister())
16942 high_mcv.getReg().?16875 high_mcv.getReg().?
16943 else16876 else
16944 try self.copyToTmpRegister(Type.usize, high_mcv);16877 try self.copyToTmpRegister(.usize, high_mcv);
16945 const high_lock = self.register_manager.lockReg(high_reg);16878 const high_lock = self.register_manager.lockReg(high_reg);
16946 defer if (high_lock) |lock| self.register_manager.unlockReg(lock);16879 defer if (high_lock) |lock| self.register_manager.unlockReg(lock);
16947
16948 try self.truncateRegister(dst_ty, high_reg);16880 try self.truncateRegister(dst_ty, high_reg);
16949 if (!high_mcv.isRegister()) try self.genCopy(16881 if (!high_mcv.isRegister()) try self.genCopy(
16950 if (abi_size <= 8) dst_ty else Type.usize,16882 if (abi_size <= 8) dst_ty else .usize,
16951 high_mcv,16883 high_mcv,
16952 .{ .register = high_reg },16884 .{ .register = high_reg },
16953 .{},16885 .{},
16954 );16886 );
16887 var offset = dst_limbs_len * 8;
16888 if (offset < abi_size) {
16889 const dst_signedness: std.builtin.Signedness = if (dst_ty.isAbiInt(zcu))
16890 dst_ty.intInfo(zcu).signedness
16891 else
16892 .unsigned;
16893 const ext_mcv: MCValue = ext_mcv: switch (dst_signedness) {
16894 .signed => {
16895 try self.asmRegisterImmediate(.{ ._r, .sa }, high_reg, .u(63));
16896 break :ext_mcv .{ .register = high_reg };
16897 },
16898 .unsigned => .{ .immediate = 0 },
16899 };
16900 while (offset < abi_size) : (offset += 8) {
16901 const limb_mcv: MCValue = switch (dst_mcv) {
16902 .register => |dst_reg| .{ .register = dst_reg },
16903 .register_pair => |dst_regs| .{ .register = dst_regs[@divExact(offset, 8)] },
16904 else => dst_mcv.address().offset(offset).deref(),
16905 };
16906 const limb_lock = if (limb_mcv.isRegister())
16907 self.register_manager.lockReg(limb_mcv.getReg().?)
16908 else
16909 null;
16910 defer if (limb_lock) |lock| self.register_manager.unlockReg(lock);
16911 try self.genCopy(.usize, limb_mcv, ext_mcv, .{});
16912 }
16913 }
16955 break :result dst_mcv;16914 break :result dst_mcv;
16956 };16915 };
16957 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });16916 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
...@@ -16973,7 +16932,7 @@ fn airArrayToSlice(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -16973,7 +16932,7 @@ fn airArrayToSlice(self: *CodeGen, inst: Air.Inst.Index) !void {
16973 try self.genSetMem(16932 try self.genSetMem(
16974 .{ .frame = frame_index },16933 .{ .frame = frame_index },
16975 @intCast(ptr_ty.abiSize(zcu)),16934 @intCast(ptr_ty.abiSize(zcu)),
16976 Type.usize,16935 .usize,
16977 .{ .immediate = array_len },16936 .{ .immediate = array_len },
16978 .{},16937 .{},
16979 );16938 );
...@@ -17151,28 +17110,28 @@ fn airCmpxchg(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -17151,28 +17110,28 @@ fn airCmpxchg(self: *CodeGen, inst: Air.Inst.Index) !void {
17151 if (val_abi_size > 8) {17110 if (val_abi_size > 8) {
17152 const exp_addr_mcv: MCValue = switch (exp_mcv) {17111 const exp_addr_mcv: MCValue = switch (exp_mcv) {
17153 .memory, .indirect, .load_frame => exp_mcv.address(),17112 .memory, .indirect, .load_frame => exp_mcv.address(),
17154 else => .{ .register = try self.copyToTmpRegister(Type.usize, exp_mcv.address()) },17113 else => .{ .register = try self.copyToTmpRegister(.usize, exp_mcv.address()) },
17155 };17114 };
17156 const exp_addr_lock =17115 const exp_addr_lock =
17157 if (exp_addr_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null;17116 if (exp_addr_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null;
17158 defer if (exp_addr_lock) |lock| self.register_manager.unlockReg(lock);17117 defer if (exp_addr_lock) |lock| self.register_manager.unlockReg(lock);
1715917118
17160 try self.genSetReg(.rax, Type.usize, exp_addr_mcv.deref(), .{});17119 try self.genSetReg(.rax, .usize, exp_addr_mcv.deref(), .{});
17161 try self.genSetReg(.rdx, Type.usize, exp_addr_mcv.offset(8).deref(), .{});17120 try self.genSetReg(.rdx, .usize, exp_addr_mcv.offset(8).deref(), .{});
17162 } else try self.genSetReg(.rax, val_ty, exp_mcv, .{});17121 } else try self.genSetReg(.rax, val_ty, exp_mcv, .{});
1716317122
17164 const new_mcv = try self.resolveInst(extra.new_value);17123 const new_mcv = try self.resolveInst(extra.new_value);
17165 const new_reg = if (val_abi_size > 8) new: {17124 const new_reg = if (val_abi_size > 8) new: {
17166 const new_addr_mcv: MCValue = switch (new_mcv) {17125 const new_addr_mcv: MCValue = switch (new_mcv) {
17167 .memory, .indirect, .load_frame => new_mcv.address(),17126 .memory, .indirect, .load_frame => new_mcv.address(),
17168 else => .{ .register = try self.copyToTmpRegister(Type.usize, new_mcv.address()) },17127 else => .{ .register = try self.copyToTmpRegister(.usize, new_mcv.address()) },
17169 };17128 };
17170 const new_addr_lock =17129 const new_addr_lock =
17171 if (new_addr_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null;17130 if (new_addr_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null;
17172 defer if (new_addr_lock) |lock| self.register_manager.unlockReg(lock);17131 defer if (new_addr_lock) |lock| self.register_manager.unlockReg(lock);
1717317132
17174 try self.genSetReg(.rbx, Type.usize, new_addr_mcv.deref(), .{});17133 try self.genSetReg(.rbx, .usize, new_addr_mcv.deref(), .{});
17175 try self.genSetReg(.rcx, Type.usize, new_addr_mcv.offset(8).deref(), .{});17134 try self.genSetReg(.rcx, .usize, new_addr_mcv.offset(8).deref(), .{});
17176 break :new null;17135 break :new null;
17177 } else try self.copyToTmpRegister(val_ty, new_mcv);17136 } else try self.copyToTmpRegister(val_ty, new_mcv);
17178 const new_lock = if (new_reg) |reg| self.register_manager.lockRegAssumeUnused(reg) else null;17137 const new_lock = if (new_reg) |reg| self.register_manager.lockRegAssumeUnused(reg) else null;
...@@ -17213,9 +17172,9 @@ fn airCmpxchg(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -17213,9 +17172,9 @@ fn airCmpxchg(self: *CodeGen, inst: Air.Inst.Index) !void {
17213 }17172 }
1721417173
17215 const dst_mcv = try self.allocRegOrMem(inst, false);17174 const dst_mcv = try self.allocRegOrMem(inst, false);
17216 try self.genCopy(Type.usize, dst_mcv, .{ .register = .rax }, .{});17175 try self.genCopy(.usize, dst_mcv, .{ .register = .rax }, .{});
17217 try self.genCopy(Type.usize, dst_mcv.address().offset(8).deref(), .{ .register = .rdx }, .{});17176 try self.genCopy(.usize, dst_mcv.address().offset(8).deref(), .{ .register = .rdx }, .{});
17218 try self.genCopy(Type.bool, dst_mcv.address().offset(16).deref(), .{ .eflags = .ne }, .{});17177 try self.genCopy(.bool, dst_mcv.address().offset(16).deref(), .{ .eflags = .ne }, .{});
17219 break :result dst_mcv;17178 break :result dst_mcv;
17220 };17179 };
17221 return self.finishAir(inst, result, .{ extra.ptr, extra.expected_value, extra.new_value });17180 return self.finishAir(inst, result, .{ extra.ptr, extra.expected_value, extra.new_value });
...@@ -17488,7 +17447,7 @@ fn atomicOp(...@@ -17488,7 +17447,7 @@ fn atomicOp(
17488 const val_mem_mcv: MCValue = switch (val_mcv) {17447 const val_mem_mcv: MCValue = switch (val_mcv) {
17489 .memory, .indirect, .load_frame => val_mcv,17448 .memory, .indirect, .load_frame => val_mcv,
17490 else => .{ .indirect = .{17449 else => .{ .indirect = .{
17491 .reg = try self.copyToTmpRegister(Type.usize, val_mcv.address()),17450 .reg = try self.copyToTmpRegister(.usize, val_mcv.address()),
17492 } },17451 } },
17493 };17452 };
17494 const val_lo_mem = try val_mem_mcv.mem(self, .{ .size = .qword });17453 const val_lo_mem = try val_mem_mcv.mem(self, .{ .size = .qword });
...@@ -17545,7 +17504,7 @@ fn atomicOp(...@@ -17545,7 +17504,7 @@ fn atomicOp(
17545 },17504 },
17546 };17505 };
1754717506
17548 const tmp_reg = try self.copyToTmpRegister(Type.usize, .{ .register = .rcx });17507 const tmp_reg = try self.copyToTmpRegister(.usize, .{ .register = .rcx });
17549 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);17508 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
17550 defer self.register_manager.unlockReg(tmp_lock);17509 defer self.register_manager.unlockReg(tmp_lock);
1755117510
...@@ -17719,7 +17678,7 @@ fn airMemset(self: *CodeGen, inst: Air.Inst.Index, safety: bool) !void {...@@ -17719,7 +17678,7 @@ fn airMemset(self: *CodeGen, inst: Air.Inst.Index, safety: bool) !void {
17719 const len_lock = self.register_manager.lockRegAssumeUnused(len_reg);17678 const len_lock = self.register_manager.lockRegAssumeUnused(len_reg);
17720 defer self.register_manager.unlockReg(len_lock);17679 defer self.register_manager.unlockReg(len_lock);
1772117680
17722 try self.genSetReg(len_reg, Type.usize, len, .{});17681 try self.genSetReg(len_reg, .usize, len, .{});
17723 try self.asmRegisterRegister(.{ ._, .@"test" }, len_reg, len_reg);17682 try self.asmRegisterRegister(.{ ._, .@"test" }, len_reg, len_reg);
1772417683
17725 const skip_reloc = try self.asmJccReloc(.z, undefined);17684 const skip_reloc = try self.asmJccReloc(.z, undefined);
...@@ -17732,12 +17691,12 @@ fn airMemset(self: *CodeGen, inst: Air.Inst.Index, safety: bool) !void {...@@ -17732,12 +17691,12 @@ fn airMemset(self: *CodeGen, inst: Air.Inst.Index, safety: bool) !void {
17732 self.register_manager.lockRegAssumeUnused(second_elem_ptr_reg);17691 self.register_manager.lockRegAssumeUnused(second_elem_ptr_reg);
17733 defer self.register_manager.unlockReg(second_elem_ptr_lock);17692 defer self.register_manager.unlockReg(second_elem_ptr_lock);
1773417693
17735 try self.genSetReg(second_elem_ptr_reg, Type.usize, .{ .register_offset = .{17694 try self.genSetReg(second_elem_ptr_reg, .usize, .{ .register_offset = .{
17736 .reg = try self.copyToTmpRegister(Type.usize, dst_ptr),17695 .reg = try self.copyToTmpRegister(.usize, dst_ptr),
17737 .off = elem_abi_size,17696 .off = elem_abi_size,
17738 } }, .{});17697 } }, .{});
1773917698
17740 try self.genBinOpMir(.{ ._, .sub }, Type.usize, len_mcv, .{ .immediate = 1 });17699 try self.genBinOpMir(.{ ._, .sub }, .usize, len_mcv, .{ .immediate = 1 });
17741 try self.asmRegisterRegisterImmediate(17700 try self.asmRegisterRegisterImmediate(
17742 .{ .i_, .mul },17701 .{ .i_, .mul },
17743 len_reg,17702 len_reg,
...@@ -17763,8 +17722,8 @@ fn airMemset(self: *CodeGen, inst: Air.Inst.Index, safety: bool) !void {...@@ -17763,8 +17722,8 @@ fn airMemset(self: *CodeGen, inst: Air.Inst.Index, safety: bool) !void {
17763 self.register_manager.lockRegAssumeUnused(second_elem_ptr_reg);17722 self.register_manager.lockRegAssumeUnused(second_elem_ptr_reg);
17764 defer self.register_manager.unlockReg(second_elem_ptr_lock);17723 defer self.register_manager.unlockReg(second_elem_ptr_lock);
1776517724
17766 try self.genSetReg(second_elem_ptr_reg, Type.usize, .{ .register_offset = .{17725 try self.genSetReg(second_elem_ptr_reg, .usize, .{ .register_offset = .{
17767 .reg = try self.copyToTmpRegister(Type.usize, dst),17726 .reg = try self.copyToTmpRegister(.usize, dst),
17768 .off = elem_abi_size,17727 .off = elem_abi_size,
17769 } }, .{});17728 } }, .{});
1777017729
...@@ -17886,7 +17845,7 @@ fn airTagName(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -17886,7 +17845,7 @@ fn airTagName(self: *CodeGen, inst: Air.Inst.Index) !void {
17886 const param_regs = abi.getCAbiIntParamRegs(resolved_cc);17845 const param_regs = abi.getCAbiIntParamRegs(resolved_cc);
1788717846
17888 const dst_mcv = try self.allocRegOrMem(inst, false);17847 const dst_mcv = try self.allocRegOrMem(inst, false);
17889 try self.genSetReg(param_regs[0], Type.usize, dst_mcv.address(), .{});17848 try self.genSetReg(param_regs[0], .usize, dst_mcv.address(), .{});
1789017849
17891 const operand = try self.resolveInst(un_op);17850 const operand = try self.resolveInst(un_op);
17892 try self.genSetReg(param_regs[1], enum_ty, operand, .{});17851 try self.genSetReg(param_regs[1], enum_ty, operand, .{});
...@@ -18415,7 +18374,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -18415,7 +18374,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
18415 mask_alias,18374 mask_alias,
18416 if (pred_mcv.isBase()) try pred_mcv.mem(self, .{ .size = .byte }) else .{18375 if (pred_mcv.isBase()) try pred_mcv.mem(self, .{ .size = .byte }) else .{
18417 .base = .{ .reg = (try self.copyToTmpRegister(18376 .base = .{ .reg = (try self.copyToTmpRegister(
18418 Type.usize,18377 .usize,
18419 pred_mcv.address(),18378 pred_mcv.address(),
18420 )).to64() },18379 )).to64() },
18421 .mod = .{ .rm = .{ .size = .byte } },18380 .mod = .{ .rm = .{ .size = .byte } },
...@@ -18478,7 +18437,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -18478,7 +18437,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
18478 .storage = .{ .elems = mask_elems[0..vec_len] },18437 .storage = .{ .elems = mask_elems[0..vec_len] },
18479 } })));18438 } })));
18480 const mask_mem: Memory = .{18439 const mask_mem: Memory = .{
18481 .base = .{ .reg = try self.copyToTmpRegister(Type.usize, mask_mcv.address()) },18440 .base = .{ .reg = try self.copyToTmpRegister(.usize, mask_mcv.address()) },
18482 .mod = .{ .rm = .{ .size = self.memSize(ty) } },18441 .mod = .{ .rm = .{ .size = self.memSize(ty) } },
18483 };18442 };
18484 if (has_avx) try self.asmRegisterRegisterMemory(18443 if (has_avx) try self.asmRegisterRegisterMemory(
...@@ -18503,7 +18462,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -18503,7 +18462,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
18503 .storage = .{ .elems = mask_elems[0..vec_len] },18462 .storage = .{ .elems = mask_elems[0..vec_len] },
18504 } })));18463 } })));
18505 const mask_mem: Memory = .{18464 const mask_mem: Memory = .{
18506 .base = .{ .reg = try self.copyToTmpRegister(Type.usize, mask_mcv.address()) },18465 .base = .{ .reg = try self.copyToTmpRegister(.usize, mask_mcv.address()) },
18507 .mod = .{ .rm = .{ .size = self.memSize(ty) } },18466 .mod = .{ .rm = .{ .size = self.memSize(ty) } },
18508 };18467 };
18509 if (has_avx) {18468 if (has_avx) {
...@@ -19380,7 +19339,7 @@ fn airShuffle(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -19380,7 +19339,7 @@ fn airShuffle(self: *CodeGen, inst: Air.Inst.Index) !void {
19380 .storage = .{ .elems = lhs_mask_elems[0..max_abi_size] },19339 .storage = .{ .elems = lhs_mask_elems[0..max_abi_size] },
19381 } })));19340 } })));
19382 const lhs_mask_mem: Memory = .{19341 const lhs_mask_mem: Memory = .{
19383 .base = .{ .reg = try self.copyToTmpRegister(Type.usize, lhs_mask_mcv.address()) },19342 .base = .{ .reg = try self.copyToTmpRegister(.usize, lhs_mask_mcv.address()) },
19384 .mod = .{ .rm = .{ .size = .fromSize(@max(max_abi_size, 16)) } },19343 .mod = .{ .rm = .{ .size = .fromSize(@max(max_abi_size, 16)) } },
19385 };19344 };
19386 if (has_avx) try self.asmRegisterRegisterMemory(19345 if (has_avx) try self.asmRegisterRegisterMemory(
...@@ -19414,7 +19373,7 @@ fn airShuffle(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -19414,7 +19373,7 @@ fn airShuffle(self: *CodeGen, inst: Air.Inst.Index) !void {
19414 .storage = .{ .elems = rhs_mask_elems[0..max_abi_size] },19373 .storage = .{ .elems = rhs_mask_elems[0..max_abi_size] },
19415 } })));19374 } })));
19416 const rhs_mask_mem: Memory = .{19375 const rhs_mask_mem: Memory = .{
19417 .base = .{ .reg = try self.copyToTmpRegister(Type.usize, rhs_mask_mcv.address()) },19376 .base = .{ .reg = try self.copyToTmpRegister(.usize, rhs_mask_mcv.address()) },
19418 .mod = .{ .rm = .{ .size = .fromSize(@max(max_abi_size, 16)) } },19377 .mod = .{ .rm = .{ .size = .fromSize(@max(max_abi_size, 16)) } },
19419 };19378 };
19420 if (has_avx) try self.asmRegisterRegisterMemory(19379 if (has_avx) try self.asmRegisterRegisterMemory(
...@@ -19634,7 +19593,7 @@ fn airAggregateInit(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -19634,7 +19593,7 @@ fn airAggregateInit(self: *CodeGen, inst: Air.Inst.Index) !void {
19634 .{ ._l, .sh },19593 .{ ._l, .sh },
19635 elem_ty,19594 elem_ty,
19636 .{ .register = temp_alias },19595 .{ .register = temp_alias },
19637 Type.u8,19596 .u8,
19638 .{ .immediate = elem_bit_off },19597 .{ .immediate = elem_bit_off },
19639 );19598 );
19640 try self.genBinOpMir(19599 try self.genBinOpMir(
...@@ -19657,7 +19616,7 @@ fn airAggregateInit(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -19657,7 +19616,7 @@ fn airAggregateInit(self: *CodeGen, inst: Air.Inst.Index) !void {
19657 .{ ._r, .sh },19616 .{ ._r, .sh },
19658 elem_ty,19617 elem_ty,
19659 .{ .register = temp_reg },19618 .{ .register = temp_reg },
19660 Type.u8,19619 .u8,
19661 .{ .immediate = elem_abi_bits - elem_bit_off },19620 .{ .immediate = elem_abi_bits - elem_bit_off },
19662 );19621 );
19663 try self.genBinOpMir(19622 try self.genBinOpMir(
...@@ -19984,7 +19943,7 @@ fn airVaStart(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -19984,7 +19943,7 @@ fn airVaStart(self: *CodeGen, inst: Air.Inst.Index) !void {
19984 const pt = self.pt;19943 const pt = self.pt;
19985 const zcu = pt.zcu;19944 const zcu = pt.zcu;
19986 const va_list_ty = self.air.instructions.items(.data)[@intFromEnum(inst)].ty;19945 const va_list_ty = self.air.instructions.items(.data)[@intFromEnum(inst)].ty;
19987 const ptr_anyopaque_ty = try pt.singleMutPtrType(Type.anyopaque);19946 const ptr_anyopaque_ty = try pt.singleMutPtrType(.anyopaque);
1998819947
19989 const result: MCValue = switch (abi.resolveCallingConvention(19948 const result: MCValue = switch (abi.resolveCallingConvention(
19990 self.fn_type.fnCallingConvention(zcu),19949 self.fn_type.fnCallingConvention(zcu),
...@@ -19998,7 +19957,7 @@ fn airVaStart(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -19998,7 +19957,7 @@ fn airVaStart(self: *CodeGen, inst: Air.Inst.Index) !void {
19998 try self.genSetMem(19957 try self.genSetMem(
19999 .{ .frame = dst_fi },19958 .{ .frame = dst_fi },
20000 field_off,19959 field_off,
20001 Type.c_uint,19960 .c_uint,
20002 .{ .immediate = info.gp_count * 8 },19961 .{ .immediate = info.gp_count * 8 },
20003 .{},19962 .{},
20004 );19963 );
...@@ -20007,7 +19966,7 @@ fn airVaStart(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -20007,7 +19966,7 @@ fn airVaStart(self: *CodeGen, inst: Air.Inst.Index) !void {
20007 try self.genSetMem(19966 try self.genSetMem(
20008 .{ .frame = dst_fi },19967 .{ .frame = dst_fi },
20009 field_off,19968 field_off,
20010 Type.c_uint,19969 .c_uint,
20011 .{ .immediate = abi.SysV.c_abi_int_param_regs.len * 8 + info.fp_count * 16 },19970 .{ .immediate = abi.SysV.c_abi_int_param_regs.len * 8 + info.fp_count * 16 },
20012 .{},19971 .{},
20013 );19972 );
...@@ -20044,7 +20003,7 @@ fn airVaArg(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -20044,7 +20003,7 @@ fn airVaArg(self: *CodeGen, inst: Air.Inst.Index) !void {
20044 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;20003 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
20045 const ty = self.typeOfIndex(inst);20004 const ty = self.typeOfIndex(inst);
20046 const promote_ty = self.promoteVarArg(ty);20005 const promote_ty = self.promoteVarArg(ty);
20047 const ptr_anyopaque_ty = try pt.singleMutPtrType(Type.anyopaque);20006 const ptr_anyopaque_ty = try pt.singleMutPtrType(.anyopaque);
20048 const unused = self.liveness.isUnused(inst);20007 const unused = self.liveness.isUnused(inst);
2004920008
20050 const result: MCValue = switch (abi.resolveCallingConvention(20009 const result: MCValue = switch (abi.resolveCallingConvention(
...@@ -20083,7 +20042,7 @@ fn airVaArg(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -20083,7 +20042,7 @@ fn airVaArg(self: *CodeGen, inst: Air.Inst.Index) !void {
20083 .integer => {20042 .integer => {
20084 assert(classes.len == 1);20043 assert(classes.len == 1);
2008520044
20086 try self.genSetReg(offset_reg, Type.c_uint, gp_offset, .{});20045 try self.genSetReg(offset_reg, .c_uint, gp_offset, .{});
20087 try self.asmRegisterImmediate(.{ ._, .cmp }, offset_reg, .u(20046 try self.asmRegisterImmediate(.{ ._, .cmp }, offset_reg, .u(
20088 abi.SysV.c_abi_int_param_regs.len * 8,20047 abi.SysV.c_abi_int_param_regs.len * 8,
20089 ));20048 ));
...@@ -20104,7 +20063,7 @@ fn airVaArg(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -20104,7 +20063,7 @@ fn airVaArg(self: *CodeGen, inst: Air.Inst.Index) !void {
20104 .disp = 8,20063 .disp = 8,
20105 } },20064 } },
20106 });20065 });
20107 try self.genCopy(Type.c_uint, gp_offset, .{ .register = offset_reg }, .{});20066 try self.genCopy(.c_uint, gp_offset, .{ .register = offset_reg }, .{});
20108 const done_reloc = try self.asmJmpReloc(undefined);20067 const done_reloc = try self.asmJmpReloc(undefined);
2010920068
20110 self.performReloc(mem_reloc);20069 self.performReloc(mem_reloc);
...@@ -20131,7 +20090,7 @@ fn airVaArg(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -20131,7 +20090,7 @@ fn airVaArg(self: *CodeGen, inst: Air.Inst.Index) !void {
20131 .sse => {20090 .sse => {
20132 assert(classes.len == 1);20091 assert(classes.len == 1);
2013320092
20134 try self.genSetReg(offset_reg, Type.c_uint, fp_offset, .{});20093 try self.genSetReg(offset_reg, .c_uint, fp_offset, .{});
20135 try self.asmRegisterImmediate(.{ ._, .cmp }, offset_reg, .u(20094 try self.asmRegisterImmediate(.{ ._, .cmp }, offset_reg, .u(
20136 abi.SysV.c_abi_int_param_regs.len * 8 + abi.SysV.c_abi_sse_param_regs.len * 16,20095 abi.SysV.c_abi_int_param_regs.len * 8 + abi.SysV.c_abi_sse_param_regs.len * 16,
20137 ));20096 ));
...@@ -20152,7 +20111,7 @@ fn airVaArg(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -20152,7 +20111,7 @@ fn airVaArg(self: *CodeGen, inst: Air.Inst.Index) !void {
20152 .disp = 16,20111 .disp = 16,
20153 } },20112 } },
20154 });20113 });
20155 try self.genCopy(Type.c_uint, fp_offset, .{ .register = offset_reg }, .{});20114 try self.genCopy(.c_uint, fp_offset, .{ .register = offset_reg }, .{});
20156 const done_reloc = try self.asmJmpReloc(undefined);20115 const done_reloc = try self.asmJmpReloc(undefined);
2015720116
20158 self.performReloc(mem_reloc);20117 self.performReloc(mem_reloc);
...@@ -20277,7 +20236,7 @@ fn resolveInst(self: *CodeGen, ref: Air.Inst.Ref) InnerError!MCValue {...@@ -20277,7 +20236,7 @@ fn resolveInst(self: *CodeGen, ref: Air.Inst.Ref) InnerError!MCValue {
20277 try self.genSetMem(20236 try self.genSetMem(
20278 .{ .frame = frame_index },20237 .{ .frame = frame_index },
20279 0,20238 0,
20280 Type.usize,20239 .usize,
20281 .{ .lea_symbol = .{ .sym_index = tlv_sym } },20240 .{ .lea_symbol = .{ .sym_index = tlv_sym } },
20282 .{},20241 .{},
20283 );20242 );
...@@ -20318,7 +20277,7 @@ fn limitImmediateType(self: *CodeGen, operand: Air.Inst.Ref, comptime T: type) !...@@ -20318,7 +20277,7 @@ fn limitImmediateType(self: *CodeGen, operand: Air.Inst.Ref, comptime T: type) !
20318 // This immediate is unsigned.20277 // This immediate is unsigned.
20319 const U = std.meta.Int(.unsigned, ti.bits - @intFromBool(ti.signedness == .signed));20278 const U = std.meta.Int(.unsigned, ti.bits - @intFromBool(ti.signedness == .signed));
20320 if (imm >= std.math.maxInt(U)) {20279 if (imm >= std.math.maxInt(U)) {
20321 return MCValue{ .register = try self.copyToTmpRegister(Type.usize, mcv) };20280 return MCValue{ .register = try self.copyToTmpRegister(.usize, mcv) };
20322 }20281 }
20323 },20282 },
20324 else => {},20283 else => {},
...@@ -20764,7 +20723,7 @@ fn splitType(self: *CodeGen, comptime parts_len: usize, ty: Type) ![parts_len]Ty...@@ -20764,7 +20723,7 @@ fn splitType(self: *CodeGen, comptime parts_len: usize, ty: Type) ![parts_len]Ty
20764 if (classes.len == parts_len) for (&parts, classes, 0..) |*part, class, part_i| {20723 if (classes.len == parts_len) for (&parts, classes, 0..) |*part, class, part_i| {
20765 part.* = switch (class) {20724 part.* = switch (class) {
20766 .integer => if (part_i < parts_len - 1)20725 .integer => if (part_i < parts_len - 1)
20767 Type.u6420726 .u64
20768 else part: {20727 else part: {
20769 const elem_size = ty.abiAlignment(zcu).minStrict(.@"8").toByteUnits().?;20728 const elem_size = ty.abiAlignment(zcu).minStrict(.@"8").toByteUnits().?;
20770 const elem_ty = try pt.intType(.unsigned, @intCast(elem_size * 8));20729 const elem_ty = try pt.intType(.unsigned, @intCast(elem_size * 8));
...@@ -20773,9 +20732,9 @@ fn splitType(self: *CodeGen, comptime parts_len: usize, ty: Type) ![parts_len]Ty...@@ -20773,9 +20732,9 @@ fn splitType(self: *CodeGen, comptime parts_len: usize, ty: Type) ![parts_len]Ty
20773 else => |array_len| try pt.arrayType(.{ .len = array_len, .child = elem_ty.toIntern() }),20732 else => |array_len| try pt.arrayType(.{ .len = array_len, .child = elem_ty.toIntern() }),
20774 };20733 };
20775 },20734 },
20776 .float => Type.f32,20735 .float => .f32,
20777 .float_combine => try pt.arrayType(.{ .len = 2, .child = .f32_type }),20736 .float_combine => try pt.arrayType(.{ .len = 2, .child = .f32_type }),
20778 .sse => Type.f64,20737 .sse => .f64,
20779 else => break,20738 else => break,
20780 };20739 };
20781 } else {20740 } else {
...@@ -20791,7 +20750,7 @@ fn splitType(self: *CodeGen, comptime parts_len: usize, ty: Type) ![parts_len]Ty...@@ -20791,7 +20750,7 @@ fn splitType(self: *CodeGen, comptime parts_len: usize, ty: Type) ![parts_len]Ty
20791fn truncateRegister(self: *CodeGen, ty: Type, reg: Register) !void {20750fn truncateRegister(self: *CodeGen, ty: Type, reg: Register) !void {
20792 const pt = self.pt;20751 const pt = self.pt;
20793 const zcu = pt.zcu;20752 const zcu = pt.zcu;
20794 const int_info = if (ty.isAbiInt(zcu)) ty.intInfo(zcu) else std.builtin.Type.Int{20753 const int_info: InternPool.Key.IntType = if (ty.isAbiInt(zcu)) ty.intInfo(zcu) else .{
20795 .signedness = .unsigned,20754 .signedness = .unsigned,
20796 .bits = @intCast(ty.bitSize(zcu)),20755 .bits = @intCast(ty.bitSize(zcu)),
20797 };20756 };
...@@ -20799,38 +20758,16 @@ fn truncateRegister(self: *CodeGen, ty: Type, reg: Register) !void {...@@ -20799,38 +20758,16 @@ fn truncateRegister(self: *CodeGen, ty: Type, reg: Register) !void {
20799 try self.spillEflagsIfOccupied();20758 try self.spillEflagsIfOccupied();
20800 switch (int_info.signedness) {20759 switch (int_info.signedness) {
20801 .signed => {20760 .signed => {
20802 try self.genShiftBinOpMir(20761 try self.genShiftBinOpMir(.{ ._l, .sa }, .isize, .{ .register = reg }, .u8, .{ .immediate = shift });
20803 .{ ._l, .sa },20762 try self.genShiftBinOpMir(.{ ._r, .sa }, .isize, .{ .register = reg }, .u8, .{ .immediate = shift });
20804 Type.isize,
20805 .{ .register = reg },
20806 Type.u8,
20807 .{ .immediate = shift },
20808 );
20809 try self.genShiftBinOpMir(
20810 .{ ._r, .sa },
20811 Type.isize,
20812 .{ .register = reg },
20813 Type.u8,
20814 .{ .immediate = shift },
20815 );
20816 },20763 },
20817 .unsigned => {20764 .unsigned => {
20818 const mask = ~@as(u64, 0) >> shift;20765 const mask = ~@as(u64, 0) >> shift;
20819 if (int_info.bits <= 32) {20766 if (int_info.bits <= 32) {
20820 try self.genBinOpMir(20767 try self.genBinOpMir(.{ ._, .@"and" }, .u32, .{ .register = reg }, .{ .immediate = mask });
20821 .{ ._, .@"and" },
20822 Type.u32,
20823 .{ .register = reg },
20824 .{ .immediate = mask },
20825 );
20826 } else {20768 } else {
20827 const tmp_reg = try self.copyToTmpRegister(Type.usize, .{ .immediate = mask });20769 const tmp_reg = try self.copyToTmpRegister(.usize, .{ .immediate = mask });
20828 try self.genBinOpMir(20770 try self.genBinOpMir(.{ ._, .@"and" }, .usize, .{ .register = reg }, .{ .register = tmp_reg });
20829 .{ ._, .@"and" },
20830 Type.usize,
20831 .{ .register = reg },
20832 .{ .register = tmp_reg },
20833 );
20834 }20771 }
20835 },20772 },
20836 }20773 }
...@@ -20911,7 +20848,7 @@ fn floatCompilerRtAbiName(float_bits: u32) u8 {...@@ -20911,7 +20848,7 @@ fn floatCompilerRtAbiName(float_bits: u32) u8 {
20911fn floatCompilerRtAbiType(self: *CodeGen, ty: Type, other_ty: Type) Type {20848fn floatCompilerRtAbiType(self: *CodeGen, ty: Type, other_ty: Type) Type {
20912 if (ty.toIntern() == .f16_type and20849 if (ty.toIntern() == .f16_type and
20913 (other_ty.toIntern() == .f32_type or other_ty.toIntern() == .f64_type) and20850 (other_ty.toIntern() == .f32_type or other_ty.toIntern() == .f64_type) and
20914 self.target.isDarwin()) return Type.u16;20851 self.target.isDarwin()) return .u16;
20915 return ty;20852 return ty;
20916}20853}
2091720854
...@@ -20943,9 +20880,9 @@ fn promoteInt(self: *CodeGen, ty: Type) Type {...@@ -20943,9 +20880,9 @@ fn promoteInt(self: *CodeGen, ty: Type) Type {
20943 else => if (ty.isAbiInt(zcu)) ty.intInfo(zcu) else return ty,20880 else => if (ty.isAbiInt(zcu)) ty.intInfo(zcu) else return ty,
20944 };20881 };
20945 for ([_]Type{20882 for ([_]Type{
20946 Type.c_int, Type.c_uint,20883 .c_int, .c_uint,
20947 Type.c_long, Type.c_ulong,20884 .c_long, .c_ulong,
20948 Type.c_longlong, Type.c_ulonglong,20885 .c_longlong, .c_ulonglong,
20949 }) |promote_ty| {20886 }) |promote_ty| {
20950 const promote_info = promote_ty.intInfo(zcu);20887 const promote_info = promote_ty.intInfo(zcu);
20951 if (int_info.signedness == .signed and promote_info.signedness == .unsigned) continue;20888 if (int_info.signedness == .signed and promote_info.signedness == .unsigned) continue;
...@@ -20958,10 +20895,10 @@ fn promoteInt(self: *CodeGen, ty: Type) Type {...@@ -20958,10 +20895,10 @@ fn promoteInt(self: *CodeGen, ty: Type) Type {
20958fn promoteVarArg(self: *CodeGen, ty: Type) Type {20895fn promoteVarArg(self: *CodeGen, ty: Type) Type {
20959 if (!ty.isRuntimeFloat()) return self.promoteInt(ty);20896 if (!ty.isRuntimeFloat()) return self.promoteInt(ty);
20960 switch (ty.floatBits(self.target.*)) {20897 switch (ty.floatBits(self.target.*)) {
20961 32, 64 => return Type.f64,20898 32, 64 => return .f64,
20962 else => |float_bits| {20899 else => |float_bits| {
20963 assert(float_bits == self.target.cTypeBitSize(.longdouble));20900 assert(float_bits == self.target.cTypeBitSize(.longdouble));
20964 return Type.c_longdouble;20901 return .c_longdouble;
20965 },20902 },
20966 }20903 }
20967}20904}
...@@ -21036,7 +20973,7 @@ const Temp = struct {...@@ -21036,7 +20973,7 @@ const Temp = struct {
2103620973
21037 fn getOffset(temp: Temp, off: i32, cg: *CodeGen) !Temp {20974 fn getOffset(temp: Temp, off: i32, cg: *CodeGen) !Temp {
21038 const new_temp_index = cg.next_temp_index;20975 const new_temp_index = cg.next_temp_index;
21039 cg.temp_type[@intFromEnum(new_temp_index)] = Type.usize;20976 cg.temp_type[@intFromEnum(new_temp_index)] = .usize;
21040 cg.next_temp_index = @enumFromInt(@intFromEnum(new_temp_index) + 1);20977 cg.next_temp_index = @enumFromInt(@intFromEnum(new_temp_index) + 1);
21041 switch (temp.tracking(cg).short) {20978 switch (temp.tracking(cg).short) {
21042 else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }),20979 else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }),
...@@ -21141,7 +21078,7 @@ const Temp = struct {...@@ -21141,7 +21078,7 @@ const Temp = struct {
2114121078
21142 fn getLimb(temp: Temp, limb_index: u28, cg: *CodeGen) !Temp {21079 fn getLimb(temp: Temp, limb_index: u28, cg: *CodeGen) !Temp {
21143 const new_temp_index = cg.next_temp_index;21080 const new_temp_index = cg.next_temp_index;
21144 cg.temp_type[@intFromEnum(new_temp_index)] = Type.usize;21081 cg.temp_type[@intFromEnum(new_temp_index)] = .usize;
21145 switch (temp.tracking(cg).short) {21082 switch (temp.tracking(cg).short) {
21146 else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }),21083 else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }),
21147 .immediate => |imm| {21084 .immediate => |imm| {
...@@ -21220,7 +21157,7 @@ const Temp = struct {...@@ -21220,7 +21157,7 @@ const Temp = struct {
21220 else => {},21157 else => {},
21221 .register, .lea_symbol, .lea_frame => {21158 .register, .lea_symbol, .lea_frame => {
21222 assert(limb_index == 0);21159 assert(limb_index == 0);
21223 cg.temp_type[@intFromEnum(temp_index)] = Type.usize;21160 cg.temp_type[@intFromEnum(temp_index)] = .usize;
21224 return;21161 return;
21225 },21162 },
21226 .register_pair => |regs| {21163 .register_pair => |regs| {
...@@ -21232,7 +21169,7 @@ const Temp = struct {...@@ -21232,7 +21169,7 @@ const Temp = struct {
21232 for (regs, 0..) |reg, reg_index| if (reg_index != limb_index)21169 for (regs, 0..) |reg, reg_index| if (reg_index != limb_index)
21233 cg.register_manager.freeReg(reg);21170 cg.register_manager.freeReg(reg);
21234 temp_tracking.* = .init(.{ .register = regs[limb_index] });21171 temp_tracking.* = .init(.{ .register = regs[limb_index] });
21235 cg.temp_type[@intFromEnum(temp_index)] = Type.usize;21172 cg.temp_type[@intFromEnum(temp_index)] = .usize;
21236 return;21173 return;
21237 },21174 },
21238 .load_symbol => |sym_off| {21175 .load_symbol => |sym_off| {
...@@ -21241,7 +21178,7 @@ const Temp = struct {...@@ -21241,7 +21178,7 @@ const Temp = struct {
21241 .sym_index = sym_off.sym_index,21178 .sym_index = sym_off.sym_index,
21242 .off = sym_off.off + @as(u31, limb_index) * 8,21179 .off = sym_off.off + @as(u31, limb_index) * 8,
21243 } });21180 } });
21244 cg.temp_type[@intFromEnum(temp_index)] = Type.usize;21181 cg.temp_type[@intFromEnum(temp_index)] = .usize;
21245 return;21182 return;
21246 },21183 },
21247 .load_frame => |frame_addr| if (!frame_addr.index.isNamed()) {21184 .load_frame => |frame_addr| if (!frame_addr.index.isNamed()) {
...@@ -21250,7 +21187,7 @@ const Temp = struct {...@@ -21250,7 +21187,7 @@ const Temp = struct {
21250 .index = frame_addr.index,21187 .index = frame_addr.index,
21251 .off = frame_addr.off + @as(u31, limb_index) * 8,21188 .off = frame_addr.off + @as(u31, limb_index) * 8,
21252 } });21189 } });
21253 cg.temp_type[@intFromEnum(temp_index)] = Type.usize;21190 cg.temp_type[@intFromEnum(temp_index)] = .usize;
21254 return;21191 return;
21255 },21192 },
21256 }21193 }
...@@ -21339,7 +21276,7 @@ const Temp = struct {...@@ -21339,7 +21276,7 @@ const Temp = struct {
21339 const result_temp: Temp = .{ .index = result_temp_index.toIndex() };21276 const result_temp: Temp = .{ .index = result_temp_index.toIndex() };
21340 assert(cg.reuseTemp(result_temp.index, first_temp.index, first_temp_tracking));21277 assert(cg.reuseTemp(result_temp.index, first_temp.index, first_temp_tracking));
21341 assert(cg.reuseTemp(result_temp.index, second_temp.index, second_temp_tracking));21278 assert(cg.reuseTemp(result_temp.index, second_temp.index, second_temp_tracking));
21342 cg.temp_type[@intFromEnum(result_temp_index)] = Type.slice_const_u8;21279 cg.temp_type[@intFromEnum(result_temp_index)] = .slice_const_u8;
21343 result_temp_index.tracking(cg).* = .init(result);21280 result_temp_index.tracking(cg).* = .init(result);
21344 first_temp.* = result_temp;21281 first_temp.* = result_temp;
21345 }21282 }
...@@ -21405,7 +21342,7 @@ const Temp = struct {...@@ -21405,7 +21342,7 @@ const Temp = struct {
21405 cg.temp_type[@intFromEnum(new_temp_index)] = temp.typeOf(cg);21342 cg.temp_type[@intFromEnum(new_temp_index)] = temp.typeOf(cg);
21406 const new_reg =21343 const new_reg =
21407 try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);21344 try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
21408 try cg.genSetReg(new_reg, Type.usize, temp_tracking.short.address(), .{});21345 try cg.genSetReg(new_reg, .usize, temp_tracking.short.address(), .{});
21409 new_temp_index.tracking(cg).* = .init(.{ .indirect = .{ .reg = new_reg } });21346 new_temp_index.tracking(cg).* = .init(.{ .indirect = .{ .reg = new_reg } });
21410 try temp.die(cg);21347 try temp.die(cg);
21411 cg.next_temp_index = @enumFromInt(@intFromEnum(new_temp_index) + 1);21348 cg.next_temp_index = @enumFromInt(@intFromEnum(new_temp_index) + 1);
...@@ -21430,8 +21367,8 @@ const Temp = struct {...@@ -21430,8 +21367,8 @@ const Temp = struct {
21430 }21367 }
21431 },21368 },
21432 .load_frame => |val_frame_addr| {21369 .load_frame => |val_frame_addr| {
21433 var val_ptr = try cg.tempFromValue(Type.usize, .{ .lea_frame = val_frame_addr });21370 var val_ptr = try cg.tempFromValue(.usize, .{ .lea_frame = val_frame_addr });
21434 var len = try cg.tempFromValue(Type.usize, .{ .immediate = val_abi_size });21371 var len = try cg.tempFromValue(.usize, .{ .immediate = val_abi_size });
21435 try val_ptr.memcpy(ptr, &len, cg);21372 try val_ptr.memcpy(ptr, &len, cg);
21436 try val_ptr.die(cg);21373 try val_ptr.die(cg);
21437 try len.die(cg);21374 try len.die(cg);
...@@ -21668,11 +21605,12 @@ fn tempFromOperand(...@@ -21668,11 +21605,12 @@ fn tempFromOperand(
21668 inst: Air.Inst.Index,21605 inst: Air.Inst.Index,
21669 op_index: Liveness.OperandInt,21606 op_index: Liveness.OperandInt,
21670 op_ref: Air.Inst.Ref,21607 op_ref: Air.Inst.Ref,
21608 ignore_death: bool,
21671) !Temp {21609) !Temp {
21672 const zcu = cg.pt.zcu;21610 const zcu = cg.pt.zcu;
21673 const ip = &zcu.intern_pool;21611 const ip = &zcu.intern_pool;
2167421612
21675 if (!cg.liveness.operandDies(inst, op_index)) {21613 if (ignore_death or !cg.liveness.operandDies(inst, op_index)) {
21676 if (op_ref.toIndex()) |op_inst| return .{ .index = op_inst };21614 if (op_ref.toIndex()) |op_inst| return .{ .index = op_inst };
21677 const val = op_ref.toInterned().?;21615 const val = op_ref.toInterned().?;
21678 const gop = try cg.const_tracking.getOrPut(cg.gpa, val);21616 const gop = try cg.const_tracking.getOrPut(cg.gpa, val);
...@@ -21693,7 +21631,7 @@ fn tempFromOperand(...@@ -21693,7 +21631,7 @@ fn tempFromOperand(
21693 try cg.genSetMem(21631 try cg.genSetMem(
21694 .{ .frame = frame_index },21632 .{ .frame = frame_index },
21695 0,21633 0,
21696 Type.usize,21634 .usize,
21697 .{ .lea_symbol = .{ .sym_index = tlv_sym } },21635 .{ .lea_symbol = .{ .sym_index = tlv_sym } },
21698 .{},21636 .{},
21699 );21637 );
...@@ -21721,7 +21659,9 @@ fn tempFromOperand(...@@ -21721,7 +21659,9 @@ fn tempFromOperand(
21721inline fn tempsFromOperands(cg: *CodeGen, inst: Air.Inst.Index, op_refs: anytype) ![op_refs.len]Temp {21659inline fn tempsFromOperands(cg: *CodeGen, inst: Air.Inst.Index, op_refs: anytype) ![op_refs.len]Temp {
21722 var temps: [op_refs.len]Temp = undefined;21660 var temps: [op_refs.len]Temp = undefined;
21723 inline for (&temps, 0.., op_refs) |*temp, op_index, op_ref| {21661 inline for (&temps, 0.., op_refs) |*temp, op_index, op_ref| {
21724 temp.* = try cg.tempFromOperand(inst, op_index, op_ref);21662 temp.* = try cg.tempFromOperand(inst, op_index, op_ref, inline for (0..op_index) |prev_op_index| {
21663 if (op_ref == op_refs[prev_op_index]) break true;
21664 } else false);
21725 }21665 }
21726 return temps;21666 return temps;
21727}21667}
...@@ -21776,6 +21716,8 @@ const Pattern = struct {...@@ -21776,6 +21716,8 @@ const Pattern = struct {
21776 implicit: u8,21716 implicit: u8,
21777 /// repeat another operand21717 /// repeat another operand
21778 explicit: u8,21718 explicit: u8,
21719 /// a condition code
21720 cc,
21779 /// any general purpose register21721 /// any general purpose register
21780 gpr,21722 gpr,
21781 /// any 64-bit mmx register21723 /// any 64-bit mmx register
...@@ -21808,6 +21750,8 @@ const Pattern = struct {...@@ -21808,6 +21750,8 @@ const Pattern = struct {
21808 ymm_limb,21750 ymm_limb,
21809 /// a limb stored in memory21751 /// a limb stored in memory
21810 mem_limb,21752 mem_limb,
21753 /// a limb stored in a condition code
21754 cc_mask_limb,
21811 /// a limb stored in a 64-bit mmx register mask21755 /// a limb stored in a 64-bit mmx register mask
21812 mm_mask_limb,21756 mm_mask_limb,
21813 /// a limb stored in a 128-bit sse register masuk21757 /// a limb stored in a 128-bit sse register masuk
...@@ -21829,7 +21773,7 @@ const Pattern = struct {...@@ -21829,7 +21773,7 @@ const Pattern = struct {
2182921773
21830 fn matches(op: Op, is_mut: bool, temp: Temp, cg: *CodeGen) bool {21774 fn matches(op: Op, is_mut: bool, temp: Temp, cg: *CodeGen) bool {
21831 switch (op) {21775 switch (op) {
21832 .implicit, .explicit => unreachable,21776 .implicit, .explicit, .cc, .cc_mask_limb => unreachable,
21833 else => {},21777 else => {},
21834 // temp is undefined21778 // temp is undefined
21835 .umax_gpr, .umax_mm, .umax_xmm, .umax_ymm => return true,21779 .umax_gpr, .umax_mm, .umax_xmm, .umax_ymm => return true,
...@@ -21837,7 +21781,7 @@ const Pattern = struct {...@@ -21837,7 +21781,7 @@ const Pattern = struct {
21837 const temp_ty = temp.typeOf(cg);21781 const temp_ty = temp.typeOf(cg);
21838 const abi_size = temp_ty.abiSize(cg.pt.zcu);21782 const abi_size = temp_ty.abiSize(cg.pt.zcu);
21839 return switch (op) {21783 return switch (op) {
21840 .implicit, .explicit, .umax_gpr, .umax_mm, .umax_xmm, .umax_ymm => unreachable,21784 .implicit, .explicit, .cc, .cc_mask_limb, .umax_gpr, .umax_mm, .umax_xmm, .umax_ymm => unreachable,
21841 .gpr => abi_size <= 8 and switch (temp.tracking(cg).short) {21785 .gpr => abi_size <= 8 and switch (temp.tracking(cg).short) {
21842 .register => |reg| reg.class() == .general_purpose,21786 .register => |reg| reg.class() == .general_purpose,
21843 .register_offset => |reg_off| reg_off.reg.class() == .general_purpose and21787 .register_offset => |reg_off| reg_off.reg.class() == .general_purpose and
...@@ -21861,9 +21805,7 @@ const Pattern = struct {...@@ -21861,9 +21805,7 @@ const Pattern = struct {
21861 },21805 },
21862 .mem, .mem_limb => (!is_mut or temp.isMut(cg)) and temp.tracking(cg).short.isMemory(),21806 .mem, .mem_limb => (!is_mut or temp.isMut(cg)) and temp.tracking(cg).short.isMemory(),
21863 .gpr_limb => abi_size > 8 and switch (temp.tracking(cg).short) {21807 .gpr_limb => abi_size > 8 and switch (temp.tracking(cg).short) {
21864 inline .register_pair, .register_triple, .register_quadruple => |regs| for (regs) |reg| {21808 .register, .register_pair, .register_triple, .register_quadruple => true,
21865 if (reg.class() != .general_purpose) break false;
21866 } else true,
21867 else => |mcv| mcv.isMemory(),21809 else => |mcv| mcv.isMemory(),
21868 },21810 },
21869 .mm_limb, .mm_mask_limb => abi_size > 8 and switch (temp.tracking(cg).short) {21811 .mm_limb, .mm_mask_limb => abi_size > 8 and switch (temp.tracking(cg).short) {
...@@ -21897,6 +21839,7 @@ const Pattern = struct {...@@ -21897,6 +21839,7 @@ const Pattern = struct {
21897 };21839 };
21898};21840};
21899const SelectOptions = struct {21841const SelectOptions = struct {
21842 cc: ?Condition = null,
21900 invert_result: bool = false,21843 invert_result: bool = false,
21901};21844};
21902fn select(21845fn select(
...@@ -21914,6 +21857,7 @@ fn select(...@@ -21914,6 +21857,7 @@ fn select(
21914 limb_reloc: Mir.Inst.Index,21857 limb_reloc: Mir.Inst.Index,
21915 limb_offset: Offset,21858 limb_offset: Offset,
21916 limb_size: ?u8,21859 limb_size: ?u8,
21860 shuffle_temp: ?Temp,
21917 mask_limb_temp: ?Temp,21861 mask_limb_temp: ?Temp,
21918 mask_limb_offset: Offset,21862 mask_limb_offset: Offset,
21919 mask_limb_offset_lock: ?RegisterLock,21863 mask_limb_offset_lock: ?RegisterLock,
...@@ -21935,6 +21879,7 @@ fn select(...@@ -21935,6 +21879,7 @@ fn select(
21935 .limb_reloc = undefined,21879 .limb_reloc = undefined,
21936 .limb_offset = .unused,21880 .limb_offset = .unused,
21937 .limb_size = null,21881 .limb_size = null,
21882 .shuffle_temp = null,
21938 .mask_limb_temp = null,21883 .mask_limb_temp = null,
21939 .mask_limb_offset = .unused,21884 .mask_limb_offset = .unused,
21940 .mask_limb_offset_lock = null,21885 .mask_limb_offset_lock = null,
...@@ -21992,12 +21937,23 @@ fn select(...@@ -21992,12 +21937,23 @@ fn select(
21992 if (!ref_src_op.matches(is_mut, src_temp, cg)) continue :patterns;21937 if (!ref_src_op.matches(is_mut, src_temp, cg)) continue :patterns;
21993 }21938 }
2199421939
21940 for (pattern.ops) |op| switch (op) {
21941 else => {},
21942 .cc_mask_limb,
21943 .mm_mask_limb,
21944 .xmm_mask_limb,
21945 .ymm_mask_limb,
21946 => if (loop.mask_limb_offset_lock == null and !cg.hasFeature(.bmi2)) {
21947 try cg.register_manager.getKnownReg(.rcx, null);
21948 loop.mask_limb_offset_lock = cg.register_manager.lockKnownRegAssumeUnused(.rcx);
21949 },
21950 };
21995 while (true) for (src_temps, pattern.ops[dst_temps.len..]) |*src_temp, src_op| {21951 while (true) for (src_temps, pattern.ops[dst_temps.len..]) |*src_temp, src_op| {
21996 if (changed: switch (switch (src_op) {21952 if (switch (switch (src_op) {
21997 .implicit, .explicit => |linked_index| pattern.ops[linked_index],21953 .implicit, .explicit => |linked_index| pattern.ops[linked_index],
21998 else => src_op,21954 else => src_op,
21999 }) {21955 }) {
22000 .implicit, .explicit => unreachable,21956 .implicit, .explicit, .cc, .cc_mask_limb => unreachable,
22001 .gpr => try src_temp.toRegClass(.general_purpose, cg),21957 .gpr => try src_temp.toRegClass(.general_purpose, cg),
22002 .mm, .mm_mask, .mm_sign_mask => try src_temp.toRegClass(.mmx, cg),21958 .mm, .mm_mask, .mm_sign_mask => try src_temp.toRegClass(.mmx, cg),
22003 .xmm,21959 .xmm,
...@@ -22015,23 +21971,22 @@ fn select(...@@ -22015,23 +21971,22 @@ fn select(
22015 .ymm_limb,21971 .ymm_limb,
22016 .mem_limb,21972 .mem_limb,
22017 => switch (src_temp.tracking(cg).short) {21973 => switch (src_temp.tracking(cg).short) {
22018 .register_pair, .register_triple, .register_quadruple => false,21974 .register, .register_pair, .register_triple, .register_quadruple => false,
22019 else => try src_temp.toBase(cg),21975 else => try src_temp.toBase(cg),
22020 },21976 },
22021 .mm_mask_limb,21977 .mm_mask_limb, .xmm_mask_limb, .ymm_mask_limb => false,
22022 .xmm_mask_limb,
22023 .ymm_mask_limb,
22024 => if (!cg.hasFeature(.bmi2) and !cg.register_manager.isKnownRegFree(.rcx)) {
22025 try cg.register_manager.getKnownReg(.rcx, null);
22026 loop.mask_limb_offset_lock = cg.register_manager.lockKnownRegAssumeUnused(.rcx);
22027 break :changed true;
22028 } else false,
22029 .umax_gpr, .umax_mm, .umax_xmm, .umax_ymm => false,21978 .umax_gpr, .umax_mm, .umax_xmm, .umax_ymm => false,
22030 }) break;21979 }) break;
22031 } else break;21980 } else break;
2203221981
21982 const invert_result = opts.invert_result != pattern_set.invert_result;
22033 var dst_is_linked: std.StaticBitSet(4) = .initEmpty();21983 var dst_is_linked: std.StaticBitSet(4) = .initEmpty();
22034 var mir_ops_len = dst_temps.len;21984 var mir_ops_len: usize = 0;
21985 for (pattern.ops[0..dst_temps.len]) |dst_op| switch (dst_op) {
21986 else => mir_ops_len += 1,
21987 .cc, .cc_mask_limb => {},
21988 };
21989 const dst_mir_ops_len = mir_ops_len;
22035 for (src_temps, pattern.ops[dst_temps.len..]) |src_temp, src_op| {21990 for (src_temps, pattern.ops[dst_temps.len..]) |src_temp, src_op| {
22036 defer mir_ops_len += @intFromBool(src_op != .implicit);21991 defer mir_ops_len += @intFromBool(src_op != .implicit);
22037 const linked_src_op, const extra_temp = op: switch (src_op) {21992 const linked_src_op, const extra_temp = op: switch (src_op) {
...@@ -22046,13 +22001,17 @@ fn select(...@@ -22046,13 +22001,17 @@ fn select(
22046 };22001 };
22047 const limb_size: u8, const rc = switch (linked_src_op) {22002 const limb_size: u8, const rc = switch (linked_src_op) {
22048 else => continue,22003 else => continue,
22049 .gpr_limb => .{ 8, abi.RegisterClass.gp },22004 .gpr_limb => .{ @intCast(@divExact(@as(Memory.Size, switch (pattern_set.scalar) {
22005 .any => .qword,
22006 .bool => unreachable,
22007 .float, .any_int, .signed_int, .unsigned_int, .any_float_or_int => |size| size,
22008 }).bitSize(), 8)), abi.RegisterClass.gp },
22050 .mm_limb, .mm_mask_limb => .{ 8, @panic("TODO") },22009 .mm_limb, .mm_mask_limb => .{ 8, @panic("TODO") },
22051 .xmm_limb, .xmm_mask_limb => .{ 16, abi.RegisterClass.sse },22010 .xmm_limb, .xmm_mask_limb => .{ 16, abi.RegisterClass.sse },
22052 .ymm_limb, .ymm_mask_limb => .{ 32, abi.RegisterClass.sse },22011 .ymm_limb, .ymm_mask_limb => .{ 32, abi.RegisterClass.sse },
22053 .umax_gpr, .umax_mm, .umax_xmm, .umax_ymm => {22012 .umax_gpr, .umax_mm, .umax_xmm, .umax_ymm => {
22054 assert(extra_temp.* == null);22013 assert(extra_temp.* == null);
22055 extra_temp.* = try cg.tempAllocReg(Type.usize, switch (linked_src_op) {22014 extra_temp.* = try cg.tempAllocReg(.noreturn, switch (linked_src_op) {
22056 else => unreachable,22015 else => unreachable,
22057 .umax_gpr => abi.RegisterClass.gp,22016 .umax_gpr => abi.RegisterClass.gp,
22058 .umax_mm => @panic("TODO"),22017 .umax_mm => @panic("TODO"),
...@@ -22064,10 +22023,18 @@ fn select(...@@ -22064,10 +22023,18 @@ fn select(
22064 assert(loop.limb_size == null or loop.limb_size == limb_size);22023 assert(loop.limb_size == null or loop.limb_size == limb_size);
22065 loop.limb_size = limb_size;22024 loop.limb_size = limb_size;
22066 loop.remaining_size = loop.remaining_size orelse src_temp.typeOf(cg).abiSize(cg.pt.zcu);22025 loop.remaining_size = loop.remaining_size orelse src_temp.typeOf(cg).abiSize(cg.pt.zcu);
22067 switch (src_temp.tracking(cg).short) {22026 const src_mcv = src_temp.tracking(cg).short;
22068 .register_pair, .register_triple, .register_quadruple => switch (loop.limb_offset) {22027 switch (src_mcv) {
22069 .unused, .temp => loop.limb_offset = .{ .known = 0 },22028 .register, .register_pair, .register_triple, .register_quadruple => {
22070 .known => {},22029 switch (loop.limb_offset) {
22030 .unused, .temp => loop.limb_offset = .{ .known = 0 },
22031 .known => {},
22032 }
22033 if (!rc.isSet(RegisterManager.indexOfRegIntoTracked(src_mcv.getRegs()[0]).?)) {
22034 if (loop.shuffle_temp == null) loop.shuffle_temp = try cg.tempAllocReg(.noreturn, abi.RegisterClass.sse);
22035 assert(extra_temp.* == null);
22036 extra_temp.* = try cg.tempAllocReg(.usize, rc);
22037 }
22071 },22038 },
22072 else => {22039 else => {
22073 switch (loop.limb_offset) {22040 switch (loop.limb_offset) {
...@@ -22075,7 +22042,7 @@ fn select(...@@ -22075,7 +22042,7 @@ fn select(
22075 .known, .temp => {},22042 .known, .temp => {},
22076 }22043 }
22077 assert(extra_temp.* == null);22044 assert(extra_temp.* == null);
22078 extra_temp.* = try cg.tempAllocReg(Type.usize, rc);22045 extra_temp.* = try cg.tempAllocReg(.usize, rc);
22079 },22046 },
22080 }22047 }
22081 }22048 }
...@@ -22090,13 +22057,17 @@ fn select(...@@ -22090,13 +22057,17 @@ fn select(
22090 dst_temp.* = dst_temp: switch (dst_op) {22057 dst_temp.* = dst_temp: switch (dst_op) {
22091 .implicit => unreachable,22058 .implicit => unreachable,
22092 .explicit => |linked_index| dst_temps[linked_index],22059 .explicit => |linked_index| dst_temps[linked_index],
22060 .cc => try cg.tempFromValue(.bool, .{ .eflags = switch (invert_result) {
22061 false => opts.cc.?,
22062 true => opts.cc.?.negate(),
22063 } }),
22093 .gpr => try cg.tempAllocReg(dst_ty, abi.RegisterClass.gp),22064 .gpr => try cg.tempAllocReg(dst_ty, abi.RegisterClass.gp),
22094 .mm, .mm_mask, .mm_sign_mask => @panic("TODO"),22065 .mm, .mm_mask, .mm_sign_mask => @panic("TODO"),
22095 .xmm, .xmm_mask, .xmm_sign_mask => try cg.tempAllocReg(dst_ty, abi.RegisterClass.sse),22066 .xmm, .xmm_mask, .xmm_sign_mask => try cg.tempAllocReg(dst_ty, abi.RegisterClass.sse),
22096 .ymm, .ymm_mask, .ymm_sign_mask => try cg.tempAllocReg(dst_ty, abi.RegisterClass.sse),22067 .ymm, .ymm_mask, .ymm_sign_mask => try cg.tempAllocReg(dst_ty, abi.RegisterClass.sse),
22097 .mem => @panic("TODO"),22068 .mem => @panic("TODO"),
22098 .gpr_limb, .mm_limb, .xmm_limb, .ymm_limb => {22069 .gpr_limb, .mm_limb, .xmm_limb, .ymm_limb => {
22099 if (extra_temp.* == null) extra_temp.* = try cg.tempAllocReg(Type.usize, switch (dst_op) {22070 if (extra_temp.* == null) extra_temp.* = try cg.tempAllocReg(.noreturn, switch (dst_op) {
22100 else => unreachable,22071 else => unreachable,
22101 .gpr_limb => abi.RegisterClass.gp,22072 .gpr_limb => abi.RegisterClass.gp,
22102 .mm_limb => @panic("TODO"),22073 .mm_limb => @panic("TODO"),
...@@ -22105,11 +22076,11 @@ fn select(...@@ -22105,11 +22076,11 @@ fn select(
22105 break :dst_temp try cg.tempAlloc(dst_ty);22076 break :dst_temp try cg.tempAlloc(dst_ty);
22106 },22077 },
22107 .mem_limb => try cg.tempAlloc(dst_ty),22078 .mem_limb => try cg.tempAlloc(dst_ty),
22108 .mm_mask_limb, .xmm_mask_limb, .ymm_mask_limb => unreachable, // already checked22079 .cc_mask_limb, .mm_mask_limb, .xmm_mask_limb, .ymm_mask_limb => unreachable, // already checked
22109 .imm, .simm32, .umax_gpr, .umax_mm, .umax_xmm, .umax_ymm => unreachable, // unmodifiable destination22080 .imm, .simm32, .umax_gpr, .umax_mm, .umax_xmm, .umax_ymm => unreachable, // unmodifiable destination
22110 };22081 };
22111 },22082 },
22112 .mm_mask_limb, .xmm_mask_limb, .ymm_mask_limb => {22083 .cc_mask_limb, .mm_mask_limb, .xmm_mask_limb, .ymm_mask_limb => {
22113 const scalar_size = @divExact(switch (pattern_set.scalar) {22084 const scalar_size = @divExact(switch (pattern_set.scalar) {
22114 .any, .bool => unreachable,22085 .any, .bool => unreachable,
22115 .float, .any_int, .signed_int, .unsigned_int, .any_float_or_int => |size| size,22086 .float, .any_int, .signed_int, .unsigned_int, .any_float_or_int => |size| size,
...@@ -22131,14 +22102,17 @@ fn select(...@@ -22131,14 +22102,17 @@ fn select(
22131 assert(loop.mask_store_bit_size == null or loop.mask_store_bit_size == mask_store_bit_size);22102 assert(loop.mask_store_bit_size == null or loop.mask_store_bit_size == mask_store_bit_size);
22132 loop.mask_store_bit_size = mask_store_bit_size;22103 loop.mask_store_bit_size = mask_store_bit_size;
22133 loop.mask_limb_offset = loop.limb_offset;22104 loop.mask_limb_offset = loop.limb_offset;
22134 if (extra_temp.* == null) extra_temp.* = try cg.tempAllocReg(Type.usize, switch (dst_op) {22105 if (loop.mask_limb_temp == null) {
22135 else => unreachable,22106 loop.mask_limb_temp = try cg.tempAllocReg(.usize, abi.RegisterClass.gp);
22136 .mm_mask_limb => @panic("TODO"),22107 if (dst_op == .cc_mask_limb and mask_store_bit_size > 8) {
22137 .xmm_mask_limb, .ymm_mask_limb => abi.RegisterClass.sse,22108 // setcc only clears 8 bits
22138 });22109 const mask_limb_alias = loop.mask_limb_temp.?.tracking(cg).short.register.to32();
22139 if (loop.mask_limb_temp == null) loop.mask_limb_temp = try cg.tempAllocReg(Type.usize, abi.RegisterClass.gp);22110 try cg.spillEflagsIfOccupied();
22111 try cg.asmRegisterRegister(.{ ._, .xor }, mask_limb_alias, mask_limb_alias);
22112 }
22113 }
22140 if (mask_limb_bit_size < mask_store_bit_size and loop.mask_store_reg == null) {22114 if (mask_limb_bit_size < mask_store_bit_size and loop.mask_store_reg == null) {
22141 loop.mask_store_temp = try cg.tempAllocReg(Type.usize, abi.RegisterClass.gp);22115 loop.mask_store_temp = try cg.tempAllocReg(.usize, abi.RegisterClass.gp);
22142 loop.mask_store_reg = loop.mask_store_temp.?.tracking(cg).short.register;22116 loop.mask_store_reg = loop.mask_store_temp.?.tracking(cg).short.register;
22143 }22117 }
22144 dst_temp.* = if (mask_store_bit_size < mask_bit_size)22118 dst_temp.* = if (mask_store_bit_size < mask_bit_size)
...@@ -22152,28 +22126,26 @@ fn select(...@@ -22152,28 +22126,26 @@ fn select(
22152 switch (loop.mask_limb_offset) {22126 switch (loop.mask_limb_offset) {
22153 .unused, .known => {},22127 .unused, .known => {},
22154 .temp => |*mask_limb_offset| {22128 .temp => |*mask_limb_offset| {
22155 if (cg.hasFeature(.bmi2)) {22129 mask_limb_offset.* = if (cg.hasFeature(.bmi2))
22156 assert(loop.mask_limb_offset_lock == null);22130 try cg.tempAllocReg(.usize, abi.RegisterClass.gp)
22157 mask_limb_offset.* = try cg.tempAllocReg(Type.usize, abi.RegisterClass.gp);22131 else if (loop.mask_limb_offset_lock != null)
22158 } else {22132 try cg.tempFromValue(.usize, .{ .register = .rcx })
22159 if (loop.mask_limb_offset_lock) |lock| cg.register_manager.unlockReg(lock);22133 else
22160 loop.mask_limb_offset_lock = null;22134 unreachable;
22161 mask_limb_offset.* = try cg.tempFromValue(Type.usize, .{ .register = .rcx });
22162 }
22163 if (loop.mask_store_reg) |mask_store_reg| {22135 if (loop.mask_store_reg) |mask_store_reg| {
22164 const mask_store_alias = registerAlias(22136 const mask_store_alias =
22165 mask_store_reg,22137 if (loop.mask_store_bit_size.? > 8) mask_store_reg.to32() else mask_store_reg.to8();
22166 @min(std.math.divCeil(u7, loop.mask_store_bit_size.?, 8) catch unreachable, 4),
22167 );
22168 try cg.spillEflagsIfOccupied();22138 try cg.spillEflagsIfOccupied();
22169 try cg.asmRegisterRegister(.{ ._, .xor }, mask_store_alias, mask_store_alias);22139 try cg.asmRegisterRegister(.{ ._, .xor }, mask_store_alias, mask_store_alias);
22170 }22140 }
22171 },22141 },
22172 }22142 }
22143 if (loop.mask_limb_offset_lock) |lock| cg.register_manager.unlockReg(lock);
22144 loop.mask_limb_offset_lock = null;
22173 switch (loop.element_offset) {22145 switch (loop.element_offset) {
22174 .unused, .known => {},22146 .unused, .known => {},
22175 .temp => |*element_offset| {22147 .temp => |*element_offset| {
22176 element_offset.* = try cg.tempAllocReg(Type.usize, abi.RegisterClass.gp);22148 element_offset.* = try cg.tempAllocReg(.usize, abi.RegisterClass.gp);
22177 const element_offset_reg = element_offset.tracking(cg).short.register;22149 const element_offset_reg = element_offset.tracking(cg).short.register;
22178 try cg.spillEflagsIfOccupied();22150 try cg.spillEflagsIfOccupied();
22179 try cg.asmRegisterRegister(.{ ._, .xor }, element_offset_reg.to32(), element_offset_reg.to32());22151 try cg.asmRegisterRegister(.{ ._, .xor }, element_offset_reg.to32(), element_offset_reg.to32());
...@@ -22182,7 +22154,7 @@ fn select(...@@ -22182,7 +22154,7 @@ fn select(
22182 }22154 }
22183 switch (loop.limb_offset) {22155 switch (loop.limb_offset) {
22184 .unused, .known => {},22156 .unused, .known => {},
22185 .temp => |*limb_offset| limb_offset.* = try cg.tempAllocReg(Type.usize, abi.RegisterClass.gp),22157 .temp => |*limb_offset| limb_offset.* = try cg.tempAllocReg(.usize, abi.RegisterClass.gp),
22186 }22158 }
22187 while (true) {22159 while (true) {
22188 switch (loop.mask_limb_offset) {22160 switch (loop.mask_limb_offset) {
...@@ -22204,7 +22176,7 @@ fn select(...@@ -22204,7 +22176,7 @@ fn select(
22204 }22176 }
22205 while (true) {22177 while (true) {
22206 var mir_ops: [4]Operand = @splat(.none);22178 var mir_ops: [4]Operand = @splat(.none);
22207 mir_ops_len = dst_temps.len;22179 mir_ops_len = dst_mir_ops_len;
22208 for (src_temps, pattern.ops[dst_temps.len..]) |src_temp, src_op| {22180 for (src_temps, pattern.ops[dst_temps.len..]) |src_temp, src_op| {
22209 defer mir_ops_len += @intFromBool(src_op != .implicit);22181 defer mir_ops_len += @intFromBool(src_op != .implicit);
22210 const mir_op, const linked_src_op, const extra_temp = switch (src_op) {22182 const mir_op, const linked_src_op, const extra_temp = switch (src_op) {
...@@ -22217,35 +22189,146 @@ fn select(...@@ -22217,35 +22189,146 @@ fn select(
22217 // src_temp is undefined22189 // src_temp is undefined
22218 .umax_gpr, .umax_mm, .umax_xmm, .umax_ymm => extra_temp.?,22190 .umax_gpr, .umax_mm, .umax_xmm, .umax_ymm => extra_temp.?,
22219 }.tracking(cg).short;22191 }.tracking(cg).short;
22220 copy_limb: switch (src_mcv) {22192 switch (linked_src_op) {
22221 .register_pair, .register_triple, .register_quadruple => {},22193 else => {},
22222 else => try cg.asmRegisterMemory(22194 .gpr_limb,
22223 switch (linked_src_op) {22195 .mm_limb,
22224 else => break :copy_limb,22196 .xmm_limb,
22225 .gpr_limb => .{ ._, .mov },22197 .ymm_limb,
22226 .mm_limb, .mm_mask_limb => .{ ._q, .mov },22198 .mm_mask_limb,
22227 .xmm_limb,22199 .xmm_mask_limb,
22228 .ymm_limb,22200 .ymm_mask_limb,
22229 .xmm_mask_limb,22201 => if (extra_temp) |limb_temp| switch (src_mcv) {
22230 .ymm_mask_limb,22202 .register, .register_pair, .register_triple, .register_quadruple => {
22231 => .{ if (cg.hasFeature(.avx)) .v_ else ._, .movdqu },22203 const limb_reg = registerAlias(limb_temp.tracking(cg).short.register, loop.limb_size.?);
22204 const src_regs = src_mcv.getRegs();
22205 const src_reg_size: u32 = @intCast(switch (src_mcv) {
22206 .register => src_temp.typeOf(cg).abiSize(cg.pt.zcu),
22207 else => @divExact(src_regs[0].bitSize(), 8),
22208 });
22209 const src_reg = src_regs[loop.limb_offset.known / src_reg_size];
22210 assert(src_mcv == .register or src_reg.bitSize() == 8 * src_reg_size);
22211 switch (src_reg.class()) {
22212 else => unreachable,
22213 .general_purpose => try cg.asmRegisterRegister(
22214 .{ ._, .mov },
22215 limb_reg,
22216 registerAlias(src_reg, src_reg_size),
22217 ),
22218 .sse => {
22219 assert(src_reg_size == 16);
22220 const limb_alias_size = @max(loop.limb_size.?, 4);
22221 const limb_alias = registerAlias(limb_reg, limb_alias_size);
22222 const src_reg_offset = loop.limb_offset.known % src_reg_size;
22223 switch (limb_reg_offset: {
22224 extr: {
22225 const limb_size = if (cg.hasFeature(.sse4_1)) loop.limb_size.? else 2;
22226 if (loop.limb_size.? > limb_size) break :extr;
22227 const limb_offset = src_reg_offset / limb_size;
22228 if (limb_offset == 0) break :extr;
22229 try cg.asmRegisterRegisterImmediate(.{ switch (limb_size) {
22230 else => unreachable,
22231 1 => if (cg.hasFeature(.avx)) .vp_b else .p_b,
22232 2 => if (cg.hasFeature(.avx)) .vp_w else .p_w,
22233 4 => if (cg.hasFeature(.avx)) .vp_d else .p_d,
22234 8 => if (cg.hasFeature(.avx)) .vp_q else .p_q,
22235 }, .extr }, limb_alias, src_reg.to128(), .u(limb_offset));
22236 break :limb_reg_offset src_reg_offset % limb_size;
22237 }
22238 try cg.asmRegisterRegister(
22239 .{ switch (limb_alias_size) {
22240 else => unreachable,
22241 4 => ._d,
22242 8 => ._q,
22243 }, .mov },
22244 limb_alias,
22245 if (src_reg_offset < limb_alias_size) src_reg.to128() else shuffle_reg: {
22246 const shuffle_reg = loop.shuffle_temp.?.tracking(cg).short.register.to128();
22247 const mir_fixes: Mir.Inst.Fixes = if (cg.hasFeature(.sse2))
22248 if (src_temp.typeOf(cg).scalarType(cg.pt.zcu).isRuntimeFloat()) switch (limb_alias_size) {
22249 else => unreachable,
22250 4 => if (cg.hasFeature(.avx)) .v_ps else ._ps,
22251 8 => if (cg.hasFeature(.avx)) .v_pd else ._pd,
22252 } else if (cg.hasFeature(.avx)) .vp_d else .p_d
22253 else
22254 ._ps;
22255 try cg.asmRegisterRegisterImmediate(
22256 .{ mir_fixes, .shuf },
22257 shuffle_reg,
22258 src_reg: switch (mir_fixes) {
22259 else => unreachable,
22260 ._ps, ._pd => {
22261 try cg.asmRegisterRegister(.{ mir_fixes, .mova }, shuffle_reg, src_reg.to128());
22262 break :src_reg shuffle_reg;
22263 },
22264 .p_d => src_reg.to128(),
22265 },
22266 .u(switch (mir_fixes) {
22267 else => unreachable,
22268 .v_ps, ._ps, .vp_d, .p_d => switch (limb_alias_size) {
22269 else => unreachable,
22270 4 => switch (src_reg_offset) {
22271 else => unreachable,
22272 4...7 => 0b01_01_01_01,
22273 8...11 => 0b10_10_10_10,
22274 12...15 => 0b11_11_11_11,
22275 },
22276 8 => switch (src_reg_offset) {
22277 else => unreachable,
22278 8...15 => 0b11_10_11_10,
22279 },
22280 },
22281 .v_pd, ._pd => switch (limb_alias_size) {
22282 else => unreachable,
22283 8 => switch (src_reg_offset) {
22284 else => unreachable,
22285 8...15 => 0b1_1,
22286 },
22287 },
22288 }),
22289 );
22290 break :shuffle_reg shuffle_reg;
22291 },
22292 );
22293 break :limb_reg_offset src_reg_offset % limb_alias_size;
22294 }) {
22295 0 => {},
22296 else => |limb_reg_offset| {
22297 try cg.spillEflagsIfOccupied();
22298 try cg.asmRegisterImmediate(.{ ._r, .sh }, limb_alias, .u(limb_reg_offset * 8));
22299 },
22300 }
22301 },
22302 }
22232 },22303 },
22233 registerAlias(extra_temp.?.tracking(cg).short.register, loop.limb_size.?),22304 else => try cg.asmRegisterMemory(
22234 try src_mcv.mem(cg, switch (loop.limb_offset) {22305 switch (linked_src_op) {
22235 .unused => unreachable,22306 else => unreachable,
22236 .known => |limb_offset| .{22307 .gpr_limb => .{ ._, .mov },
22237 .size = .fromSize(loop.limb_size.?),22308 .mm_limb, .mm_mask_limb => .{ ._q, .mov },
22238 .disp = limb_offset,22309 .xmm_limb,
22239 },22310 .ymm_limb,
22240 .temp => |limb_offset| .{22311 .xmm_mask_limb,
22241 .size = .fromSize(loop.limb_size.?),22312 .ymm_mask_limb,
22242 .index = limb_offset.tracking(cg).short.register.to64(),22313 => .{ if (cg.hasFeature(.avx)) .v_ else ._, .movdqu },
22243 },22314 },
22244 }),22315 registerAlias(limb_temp.tracking(cg).short.register, loop.limb_size.?),
22245 ),22316 try src_mcv.mem(cg, switch (loop.limb_offset) {
22317 .unused => unreachable,
22318 .known => |limb_offset| .{
22319 .size = .fromSize(loop.limb_size.?),
22320 .disp = limb_offset,
22321 },
22322 .temp => |limb_offset| .{
22323 .size = .fromSize(loop.limb_size.?),
22324 .index = limb_offset.tracking(cg).short.register.to64(),
22325 },
22326 }),
22327 ),
22328 },
22246 }22329 }
22247 mir_op.* = switch (linked_src_op) {22330 mir_op.* = switch (linked_src_op) {
22248 .implicit, .explicit => unreachable,22331 .implicit, .explicit, .cc, .cc_mask_limb => unreachable,
22249 .gpr => .{ .reg = registerAlias(22332 .gpr => .{ .reg = registerAlias(
22250 src_mcv.register,22333 src_mcv.register,
22251 @intCast(src_temp.typeOf(cg).abiSize(cg.pt.zcu)),22334 @intCast(src_temp.typeOf(cg).abiSize(cg.pt.zcu)),
...@@ -22262,25 +22345,12 @@ fn select(...@@ -22262,25 +22345,12 @@ fn select(
22262 .mm_mask_limb,22345 .mm_mask_limb,
22263 .xmm_mask_limb,22346 .xmm_mask_limb,
22264 .ymm_mask_limb,22347 .ymm_mask_limb,
22265 => switch (src_mcv) {22348 => .{ .reg = registerAlias(if (extra_temp) |limb_temp|
22266 inline .register_pair,22349 limb_temp.tracking(cg).short.register
22267 .register_triple,22350 else
22268 .register_quadruple,22351 src_mcv.getRegs()[@divExact(loop.limb_offset.known, loop.limb_size.?)], loop.limb_size.?) },
22269 => |src_regs| switch (loop.limb_offset) {
22270 .unused => unreachable,
22271 .known => |limb_offset| .{ .reg = registerAlias(
22272 src_regs[@divExact(limb_offset, loop.limb_size.?)],
22273 loop.limb_size.?,
22274 ) },
22275 .temp => unreachable,
22276 },
22277 else => .{ .reg = registerAlias(
22278 extra_temp.?.tracking(cg).short.register,
22279 loop.limb_size.?,
22280 ) },
22281 },
22282 .mem_limb => .{ .mem = switch (src_mcv) {22352 .mem_limb => .{ .mem = switch (src_mcv) {
22283 .register_pair, .register_triple, .register_quadruple => unreachable,22353 .register, .register_pair, .register_triple, .register_quadruple => unreachable,
22284 else => switch (loop.limb_offset) {22354 else => switch (loop.limb_offset) {
22285 .unused => unreachable,22355 .unused => unreachable,
22286 .known => |limb_offset| try src_mcv.mem(cg, .{22356 .known => |limb_offset| try src_mcv.mem(cg, .{
...@@ -22316,15 +22386,15 @@ fn select(...@@ -22316,15 +22386,15 @@ fn select(
22316 }22386 }
22317 }22387 }
22318 for (22388 for (
22319 mir_ops[0..dst_temps.len],22389 mir_ops[0..dst_mir_ops_len],
22320 pattern.ops[0..dst_temps.len],22390 pattern.ops[0..dst_mir_ops_len],
22321 dst_temps,22391 dst_temps[0..dst_mir_ops_len],
22322 dst_tys,22392 dst_tys[0..dst_mir_ops_len],
22323 extra_temps[0..dst_temps.len],22393 extra_temps[0..dst_mir_ops_len],
22324 ) |*mir_op, dst_op, dst_temp, dst_ty, extra_temp| {22394 ) |*mir_op, dst_op, dst_temp, dst_ty, extra_temp| {
22325 if (mir_op.* != .none) continue;22395 if (mir_op.* != .none) continue;
22326 mir_op.* = switch (dst_op) {22396 mir_op.* = switch (dst_op) {
22327 .implicit => unreachable,22397 .implicit, .cc, .cc_mask_limb => unreachable,
22328 .explicit => |linked_index| mir_ops[linked_index],22398 .explicit => |linked_index| mir_ops[linked_index],
22329 .gpr => .{ .reg = registerAlias(22399 .gpr => .{ .reg = registerAlias(
22330 dst_temp.tracking(cg).short.register,22400 dst_temp.tracking(cg).short.register,
...@@ -22334,7 +22404,14 @@ fn select(...@@ -22334,7 +22404,14 @@ fn select(
22334 .xmm, .xmm_mask, .xmm_sign_mask => .{ .reg = dst_temp.tracking(cg).short.register.to128() },22404 .xmm, .xmm_mask, .xmm_sign_mask => .{ .reg = dst_temp.tracking(cg).short.register.to128() },
22335 .ymm, .ymm_mask, .ymm_sign_mask => .{ .reg = dst_temp.tracking(cg).short.register.to256() },22405 .ymm, .ymm_mask, .ymm_sign_mask => .{ .reg = dst_temp.tracking(cg).short.register.to256() },
22336 .mem => @panic("TODO"),22406 .mem => @panic("TODO"),
22337 .gpr_limb => .{ .reg = extra_temp.?.tracking(cg).short.register.to64() },22407 .gpr_limb => .{ .reg = registerAlias(
22408 extra_temp.?.tracking(cg).short.register,
22409 @intCast(@divExact(@as(Memory.Size, switch (pattern_set.scalar) {
22410 .any => .qword,
22411 .bool => unreachable,
22412 .float, .any_int, .signed_int, .unsigned_int, .any_float_or_int => |size| size,
22413 }).bitSize(), 8)),
22414 ) },
22338 .mm_limb => .{ .reg = extra_temp.?.tracking(cg).short.register },22415 .mm_limb => .{ .reg = extra_temp.?.tracking(cg).short.register },
22339 .xmm_limb => .{ .reg = extra_temp.?.tracking(cg).short.register.to128() },22416 .xmm_limb => .{ .reg = extra_temp.?.tracking(cg).short.register.to128() },
22340 .ymm_limb => .{ .reg = extra_temp.?.tracking(cg).short.register.to256() },22417 .ymm_limb => .{ .reg = extra_temp.?.tracking(cg).short.register.to256() },
...@@ -22376,7 +22453,6 @@ fn select(...@@ -22376,7 +22453,6 @@ fn select(
22376 },22453 },
22377 else => |e| return e,22454 else => |e| return e,
22378 };22455 };
22379 const invert_result = opts.invert_result != pattern_set.invert_result;
22380 for (22456 for (
22381 extra_temps[0..dst_temps.len],22457 extra_temps[0..dst_temps.len],
22382 pattern.ops[0..dst_temps.len],22458 pattern.ops[0..dst_temps.len],
...@@ -22410,21 +22486,15 @@ fn select(...@@ -22410,21 +22486,15 @@ fn select(
22410 .any, .bool => unreachable,22486 .any, .bool => unreachable,
22411 .float, .any_int, .signed_int, .unsigned_int, .any_float_or_int => |size| size,22487 .float, .any_int, .signed_int, .unsigned_int, .any_float_or_int => |size| size,
22412 }, cg),22488 }, cg),
22413 .gpr_limb, .mm_limb, .xmm_limb, .ymm_limb => if (extra_temp) |limb_temp|22489 .gpr_limb, .mm_limb, .xmm_limb, .ymm_limb => if (extra_temp) |limb_temp| {
22414 switch (dst_temp.tracking(cg).short) {22490 const dst_mcv = dst_temp.tracking(cg).short;
22415 inline .register_pair,22491 switch (dst_mcv) {
22416 .register_triple,22492 .register_pair, .register_triple, .register_quadruple => try cg.asmRegisterRegister(
22417 .register_quadruple,22493 .{ ._, .mov },
22418 => |dst_regs| switch (loop.limb_offset) {22494 dst_mcv.getRegs()[@divExact(loop.limb_offset.known, loop.limb_size.?)].to64(),
22419 .unused => unreachable,22495 limb_temp.tracking(cg).short.register.to64(),
22420 .known => |limb_offset| try cg.asmRegisterRegister(22496 ),
22421 .{ ._, .mov },22497 else => try cg.asmMemoryRegister(
22422 dst_regs[@divExact(limb_offset, loop.limb_size.?)].to64(),
22423 limb_temp.tracking(cg).short.register.to64(),
22424 ),
22425 .temp => unreachable,
22426 },
22427 else => |dst_mcv| try cg.asmMemoryRegister(
22428 switch (dst_op) {22498 switch (dst_op) {
22429 else => unreachable,22499 else => unreachable,
22430 .gpr_limb => .{ ._, .mov },22500 .gpr_limb => .{ ._, .mov },
...@@ -22444,57 +22514,66 @@ fn select(...@@ -22444,57 +22514,66 @@ fn select(
22444 }),22514 }),
22445 registerAlias(limb_temp.tracking(cg).short.register, loop.limb_size.?),22515 registerAlias(limb_temp.tracking(cg).short.register, loop.limb_size.?),
22446 ),22516 ),
22447 },22517 }
22448 .mm_mask_limb, .xmm_mask_limb, .ymm_mask_limb => {22518 },
22519 .cc_mask_limb, .mm_mask_limb, .xmm_mask_limb, .ymm_mask_limb => {
22449 const scalar_size = switch (pattern_set.scalar) {22520 const scalar_size = switch (pattern_set.scalar) {
22450 .any, .bool => unreachable,22521 .any, .bool => unreachable,
22451 .float, .any_int, .signed_int, .unsigned_int, .any_float_or_int => |size| size,22522 .float, .any_int, .signed_int, .unsigned_int, .any_float_or_int => |size| size,
22452 };22523 };
22453 switch (scalar_size) {
22454 else => {},
22455 .word => if (cg.hasFeature(.avx)) try cg.asmRegisterRegisterRegister(
22456 .{ .vp_b, .ackssw },
22457 mir_op.reg,
22458 mir_op.reg,
22459 mir_op.reg,
22460 ) else try cg.asmRegisterRegister(
22461 .{ .p_b, .ackssw },
22462 mir_op.reg,
22463 mir_op.reg,
22464 ),
22465 }
22466 const mask_store_size: u4 =22524 const mask_store_size: u4 =
22467 @intCast(std.math.divCeil(u7, loop.mask_store_bit_size.?, 8) catch unreachable);22525 @intCast(std.math.divCeil(u7, loop.mask_store_bit_size.?, 8) catch unreachable);
22468 const mask_limb_reg = registerAlias(22526 const known_shl_count = if (loop.mask_store_reg) |_| switch (loop.mask_limb_offset) {
22469 loop.mask_limb_temp.?.tracking(cg).short.register,22527 .unused => unreachable,
22470 mask_store_size,22528 .known => |mask_limb_offset| mask_limb_offset & (loop.mask_store_bit_size.? - 1),
22471 );22529 .temp => null,
22472 try cg.asmRegisterRegister(switch (scalar_size) {22530 } else null;
22531 const mask_limb_reg = registerAlias(if (known_shl_count != 0)
22532 loop.mask_limb_temp.?.tracking(cg).short.register
22533 else
22534 loop.mask_store_reg.?, mask_store_size);
22535 switch (dst_op) {
22473 else => unreachable,22536 else => unreachable,
22474 .byte, .word => .{ if (cg.hasFeature(.avx)) .vp_b else .p_b, .movmsk },22537 .cc_mask_limb => try cg.asmSetccRegister(switch (invert_result) {
22475 .dword => .{ if (cg.hasFeature(.avx)) .v_ps else ._ps, .movmsk },22538 false => opts.cc.?,
22476 .qword => .{ if (cg.hasFeature(.avx)) .v_pd else ._pd, .movmsk },22539 true => opts.cc.?.negate(),
22477 }, mask_limb_reg.to32(), mir_op.reg);22540 }, mask_limb_reg.to8()),
22478 if (invert_result) if (loop.mask_store_reg) |_| {22541 .mm_mask_limb, .xmm_mask_limb, .ymm_mask_limb => {
22479 try cg.spillEflagsIfOccupied();22542 if (scalar_size == .word) if (cg.hasFeature(.avx)) try cg.asmRegisterRegisterRegister(
22480 try cg.asmRegisterImmediate(22543 .{ .vp_b, .ackssw },
22481 .{ ._, .xor },22544 mir_op.reg,
22482 registerAlias(mask_limb_reg, @min(mask_store_size, 4)),22545 mir_op.reg,
22483 .u((@as(u32, 1) << @intCast(loop.mask_limb_bit_size.?)) - 1),22546 mir_op.reg,
22484 );22547 ) else try cg.asmRegisterRegister(
22485 } else try cg.asmRegister(.{ ._, .not }, mask_limb_reg);22548 .{ .p_b, .ackssw },
22549 mir_op.reg,
22550 mir_op.reg,
22551 );
22552 try cg.asmRegisterRegister(switch (scalar_size) {
22553 else => unreachable,
22554 .byte, .word => .{ if (cg.hasFeature(.avx)) .vp_b else .p_b, .movmsk },
22555 .dword => .{ if (cg.hasFeature(.avx)) .v_ps else ._ps, .movmsk },
22556 .qword => .{ if (cg.hasFeature(.avx)) .v_pd else ._pd, .movmsk },
22557 }, mask_limb_reg.to32(), mir_op.reg);
22558 if (invert_result) if (loop.mask_store_reg) |_| {
22559 try cg.spillEflagsIfOccupied();
22560 try cg.asmRegisterImmediate(
22561 .{ ._, .xor },
22562 registerAlias(mask_limb_reg, @min(mask_store_size, 4)),
22563 .u((@as(u32, 1) << @intCast(loop.mask_limb_bit_size.?)) - 1),
22564 );
22565 } else try cg.asmRegister(.{ ._, .not }, mask_limb_reg);
22566 },
22567 }
22486 if (loop.mask_store_reg) |mask_store_reg| {22568 if (loop.mask_store_reg) |mask_store_reg| {
22487 const mask_store_alias = registerAlias(mask_store_reg, mask_store_size);22569 const mask_store_alias = registerAlias(mask_store_reg, mask_store_size);
22488 switch (loop.mask_limb_offset) {22570 switch (loop.mask_limb_offset) {
22489 .unused => unreachable,22571 .unused => unreachable,
22490 .known => |mask_limb_offset| switch (mask_limb_offset & (loop.mask_store_bit_size.? - 1)) {22572 .known => if (known_shl_count.? != 0) {
22491 0 => try cg.asmRegisterRegister(.{ ._, .mov }, mask_store_alias, mask_limb_reg),22573 try cg.spillEflagsIfOccupied();
22492 else => |shl_count| {22574 try cg.asmRegisterImmediate(.{ ._l, .sh }, mask_limb_reg, .u(known_shl_count.?));
22493 try cg.spillEflagsIfOccupied();22575 try cg.spillEflagsIfOccupied();
22494 try cg.asmRegisterImmediate(.{ ._l, .sh }, mask_limb_reg, .u(shl_count));22576 try cg.asmRegisterRegister(.{ ._, .@"or" }, mask_store_alias, mask_limb_reg);
22495 try cg.spillEflagsIfOccupied();
22496 try cg.asmRegisterRegister(.{ ._, .@"or" }, mask_store_alias, mask_limb_reg);
22497 },
22498 },22577 },
22499 .temp => |mask_limb_offset| {22578 .temp => |mask_limb_offset| {
22500 if (cg.hasFeature(.bmi2)) {22579 if (cg.hasFeature(.bmi2)) {
...@@ -22524,23 +22603,23 @@ fn select(...@@ -22524,23 +22603,23 @@ fn select(
22524 .unused => unreachable,22603 .unused => unreachable,
22525 .known => |*mask_limb_offset| {22604 .known => |*mask_limb_offset| {
22526 mask_limb_offset.* += loop.mask_limb_bit_size.?;22605 mask_limb_offset.* += loop.mask_limb_bit_size.?;
22527 if (mask_limb_offset.* & (loop.mask_store_bit_size.? - 1) == 0) {22606 if (mask_limb_offset.* & (loop.mask_store_bit_size.? - 1) == 0) switch (dst_mcv) {
22528 switch (dst_mcv) {22607 .register => {},
22529 .register => {},22608 else => {
22530 else => try cg.asmMemoryRegister(22609 try cg.asmMemoryRegister(
22531 .{ ._, .mov },22610 .{ ._, .mov },
22532 try dst_mcv.mem(cg, .{22611 try dst_mcv.mem(cg, .{
22533 .size = .fromSize(mask_store_size),22612 .size = .fromSize(mask_store_size),
22534 .disp = @divExact(mask_limb_offset.*, 8) - mask_store_size,22613 .disp = @divExact(mask_limb_offset.*, 8) - mask_store_size,
22535 }),22614 }),
22536 registerAlias(loop.mask_store_reg orelse mask_limb_reg, mask_store_size),22615 registerAlias(loop.mask_store_reg orelse mask_limb_reg, mask_store_size),
22537 ),22616 );
22538 }22617 if (loop.mask_store_reg) |mask_store_reg| {
22539 if (loop.mask_store_reg) |mask_store_reg| {22618 const mask_store_alias = registerAlias(mask_store_reg, @min(mask_store_size, 4));
22540 const mask_store_alias = registerAlias(mask_store_reg, @min(mask_store_size, 4));22619 try cg.asmRegisterRegister(.{ ._, .xor }, mask_store_alias, mask_store_alias);
22541 try cg.asmRegisterRegister(.{ ._, .xor }, mask_store_alias, mask_store_alias);22620 }
22542 }22621 },
22543 }22622 };
22544 },22623 },
22545 .temp => |mask_limb_offset| {22624 .temp => |mask_limb_offset| {
22546 const mask_limb_offset_reg = mask_limb_offset.tracking(cg).short.register.to32();22625 const mask_limb_offset_reg = mask_limb_offset.tracking(cg).short.register.to32();
...@@ -22641,6 +22720,7 @@ fn select(...@@ -22641,6 +22720,7 @@ fn select(
22641 },22720 },
22642 }22721 }
22643 }22722 }
22723 if (loop.shuffle_temp) |shuffle_temp| try shuffle_temp.die(cg);
22644 if (loop.mask_limb_temp) |mask_limb_temp| try mask_limb_temp.die(cg);22724 if (loop.mask_limb_temp) |mask_limb_temp| try mask_limb_temp.die(cg);
22645 if (loop.mask_store_temp) |mask_store_temp| try mask_store_temp.die(cg);22725 if (loop.mask_store_temp) |mask_store_temp| try mask_store_temp.die(cg);
22646 switch (loop.mask_limb_offset) {22726 switch (loop.mask_limb_offset) {
src/arch/x86_64/encoder.zig+2-2
...@@ -677,11 +677,11 @@ pub const Instruction = struct {...@@ -677,11 +677,11 @@ pub const Instruction = struct {
677 else => unreachable,677 else => unreachable,
678 },678 },
679 .frame => if (@TypeOf(encoder).options.allow_frame_locs) {679 .frame => if (@TypeOf(encoder).options.allow_frame_locs) {
680 try encoder.modRm_indirectDisp32(operand_enc, undefined);680 try encoder.modRm_indirectDisp32(operand_enc, 0);
681 try encoder.disp32(undefined);681 try encoder.disp32(undefined);
682 } else return error.CannotEncode,682 } else return error.CannotEncode,
683 .reloc => if (@TypeOf(encoder).options.allow_symbols) {683 .reloc => if (@TypeOf(encoder).options.allow_symbols) {
684 try encoder.modRm_indirectDisp32(operand_enc, undefined);684 try encoder.modRm_indirectDisp32(operand_enc, 0);
685 try encoder.disp32(undefined);685 try encoder.disp32(undefined);
686 } else return error.CannotEncode,686 } else return error.CannotEncode,
687 },687 },
src/codegen/c/Type.zig+5-5
...@@ -1312,10 +1312,10 @@ pub const Pool = struct {...@@ -1312,10 +1312,10 @@ pub const Pool = struct {
1312 },1312 },
1313 else => {1313 else => {
1314 const target = &mod.resolved_target.result;1314 const target = &mod.resolved_target.result;
1315 const abi_align = Type.intAbiAlignment(int_info.bits, target.*, false);1315 const abi_align = Type.intAbiAlignment(int_info.bits, target.*);
1316 const abi_align_bytes = abi_align.toByteUnits().?;1316 const abi_align_bytes = abi_align.toByteUnits().?;
1317 const array_ctype = try pool.getArray(allocator, .{1317 const array_ctype = try pool.getArray(allocator, .{
1318 .len = @divExact(Type.intAbiSize(int_info.bits, target.*, false), abi_align_bytes),1318 .len = @divExact(Type.intAbiSize(int_info.bits, target.*), abi_align_bytes),
1319 .elem_ctype = try pool.fromIntInfo(allocator, .{1319 .elem_ctype = try pool.fromIntInfo(allocator, .{
1320 .signedness = .unsigned,1320 .signedness = .unsigned,
1321 .bits = @intCast(abi_align_bytes * 8),1321 .bits = @intCast(abi_align_bytes * 8),
...@@ -1429,7 +1429,7 @@ pub const Pool = struct {...@@ -1429,7 +1429,7 @@ pub const Pool = struct {
1429 .name = .{ .index = .len },1429 .name = .{ .index = .len },
1430 .ctype = CType.usize,1430 .ctype = CType.usize,
1431 .alignas = AlignAs.fromAbiAlignment(1431 .alignas = AlignAs.fromAbiAlignment(
1432 Type.intAbiAlignment(target.ptrBitWidth(), target.*, false),1432 Type.intAbiAlignment(target.ptrBitWidth(), target.*),
1433 ),1433 ),
1434 },1434 },
1435 };1435 };
...@@ -1524,7 +1524,7 @@ pub const Pool = struct {...@@ -1524,7 +1524,7 @@ pub const Pool = struct {
1524 .name = .{ .index = .len },1524 .name = .{ .index = .len },
1525 .ctype = CType.usize,1525 .ctype = CType.usize,
1526 .alignas = AlignAs.fromAbiAlignment(1526 .alignas = AlignAs.fromAbiAlignment(
1527 Type.intAbiAlignment(target.ptrBitWidth(), target.*, false),1527 Type.intAbiAlignment(target.ptrBitWidth(), target.*),
1528 ),1528 ),
1529 },1529 },
1530 };1530 };
...@@ -1644,7 +1644,7 @@ pub const Pool = struct {...@@ -1644,7 +1644,7 @@ pub const Pool = struct {
1644 .name = .{ .index = .@"error" },1644 .name = .{ .index = .@"error" },
1645 .ctype = error_set_ctype,1645 .ctype = error_set_ctype,
1646 .alignas = AlignAs.fromAbiAlignment(1646 .alignas = AlignAs.fromAbiAlignment(
1647 Type.intAbiAlignment(error_set_bits, target.*, false),1647 Type.intAbiAlignment(error_set_bits, target.*),
1648 ),1648 ),
1649 },1649 },
1650 .{1650 .{
src/codegen/llvm.zig+1-1
...@@ -581,7 +581,7 @@ const DataLayoutBuilder = struct {...@@ -581,7 +581,7 @@ const DataLayoutBuilder = struct {
581 switch (kind) {581 switch (kind) {
582 .integer => {582 .integer => {
583 if (self.target.ptrBitWidth() <= 16 and size >= 128) return;583 if (self.target.ptrBitWidth() <= 16 and size >= 128) return;
584 abi = @min(abi, Type.maxIntAlignment(self.target, true) * 8);584 abi = @min(abi, Type.maxIntAlignment(self.target) * 8);
585 switch (self.target.cpu.arch) {585 switch (self.target.cpu.arch) {
586 .aarch64,586 .aarch64,
587 .aarch64_be,587 .aarch64_be,
src/link/C.zig+1-1
...@@ -396,7 +396,7 @@ fn abiDefines(self: *C, target: std.Target) !std.ArrayList(u8) {...@@ -396,7 +396,7 @@ fn abiDefines(self: *C, target: std.Target) !std.ArrayList(u8) {
396 else => {},396 else => {},
397 }397 }
398 try writer.print("#define ZIG_TARGET_MAX_INT_ALIGNMENT {d}\n", .{398 try writer.print("#define ZIG_TARGET_MAX_INT_ALIGNMENT {d}\n", .{
399 Type.maxIntAlignment(target, false),399 Type.maxIntAlignment(target),
400 });400 });
401 return defines;401 return defines;
402}402}
test/behavior/align.zig+9-23
...@@ -144,31 +144,17 @@ test "alignment and size of structs with 128-bit fields" {...@@ -144,31 +144,17 @@ test "alignment and size of structs with 128-bit fields" {
144 },144 },
145 },145 },
146146
147 .x86_64 => switch (builtin.zig_backend) {147 .x86_64 => .{
148 .stage2_x86_64 => .{148 .a_align = 16,
149 .a_align = 8,149 .a_size = 16,
150 .a_size = 16,
151
152 .b_align = 16,
153 .b_size = 32,
154
155 .u128_align = 8,
156 .u128_size = 16,
157 .u129_align = 8,
158 .u129_size = 24,
159 },
160 else => .{
161 .a_align = 16,
162 .a_size = 16,
163150
164 .b_align = 16,151 .b_align = 16,
165 .b_size = 32,152 .b_size = 32,
166153
167 .u128_align = 16,154 .u128_align = 16,
168 .u128_size = 16,155 .u128_size = 16,
169 .u129_align = 16,156 .u129_align = 16,
170 .u129_size = 32,157 .u129_size = 32,
171 },
172 },158 },
173159
174 .x86,160 .x86,
test/behavior/x86_64/math.zig+60-3
...@@ -31,7 +31,37 @@ fn testBinary(comptime op: anytype) !void {...@@ -31,7 +31,37 @@ fn testBinary(comptime op: anytype) !void {
31 try testType(u32, 0x80d7a2c6, 0xbff6a402);31 try testType(u32, 0x80d7a2c6, 0xbff6a402);
32 try testType(u64, 0x71138bc6b4a38898, 0x1bc4043de9438c7b);32 try testType(u64, 0x71138bc6b4a38898, 0x1bc4043de9438c7b);
33 try testType(u128, 0xe05fc132ef2cd8affee00a907f0a851f, 0x29f912a72cfc6a7c6973426a9636da9a);33 try testType(u128, 0xe05fc132ef2cd8affee00a907f0a851f, 0x29f912a72cfc6a7c6973426a9636da9a);
34 try testType(
35 u256,
36 0xb7935f5c2f3b1ae7a422c0a7c446884294b7d5370bada307d2fe5a4c4284a999,
37 0x310e6e196ba4f143b8d285ca6addf7f3bb3344224aff221b27607a31e148be08,
38 );
39 try testType(
40 u512,
41 0xe5b1fedca3c77db765e517aabd05ffc524a3a8aff1784bbf67c45b894447ede32b65b9940e78173c591e56e078932d465f235aece7ad47b7f229df7ba8f12295,
42 0x8b4bb7c2969e3b121cc1082c442f8b4330f0a50058438fed56447175bb10178607ecfe425cb54dacc25ef26810f3e04681de1844f1aa8d029aca75d658634806,
43 );
3444
45 try testType(@Vector(1, u8), .{
46 0x1f,
47 }, .{
48 0x06,
49 });
50 try testType(@Vector(2, u8), .{
51 0x80, 0x63,
52 }, .{
53 0xe4, 0x28,
54 });
55 try testType(@Vector(4, u8), .{
56 0x83, 0x9e, 0x1e, 0xc1,
57 }, .{
58 0xf0, 0x5c, 0x46, 0x85,
59 });
60 try testType(@Vector(8, u8), .{
61 0x1e, 0x4d, 0x9d, 0x2a, 0x4c, 0x74, 0x0a, 0x83,
62 }, .{
63 0x28, 0x60, 0xa9, 0xb5, 0xd9, 0xa6, 0xf1, 0xb6,
64 });
35 try testType(@Vector(16, u8), .{65 try testType(@Vector(16, u8), .{
36 0xea, 0x80, 0xbb, 0xe8, 0x74, 0x81, 0xc8, 0x66, 0x7b, 0x41, 0x90, 0xcb, 0x30, 0x70, 0x4b, 0x0f,66 0xea, 0x80, 0xbb, 0xe8, 0x74, 0x81, 0xc8, 0x66, 0x7b, 0x41, 0x90, 0xcb, 0x30, 0x70, 0x4b, 0x0f,
37 }, .{67 }, .{
...@@ -75,6 +105,21 @@ fn testBinary(comptime op: anytype) !void {...@@ -75,6 +105,21 @@ fn testBinary(comptime op: anytype) !void {
75 0x56, 0x4f, 0xf1, 0xaa, 0x0a, 0x0f, 0xdb, 0x1b, 0xc8, 0x45, 0x9b, 0x12, 0xb4, 0x1a, 0xe4, 0xa3,105 0x56, 0x4f, 0xf1, 0xaa, 0x0a, 0x0f, 0xdb, 0x1b, 0xc8, 0x45, 0x9b, 0x12, 0xb4, 0x1a, 0xe4, 0xa3,
76 });106 });
77107
108 try testType(@Vector(1, u16), .{
109 0x9d6f,
110 }, .{
111 0x44b1,
112 });
113 try testType(@Vector(2, u16), .{
114 0xa0fa, 0xc365,
115 }, .{
116 0xe736, 0xc394,
117 });
118 try testType(@Vector(4, u16), .{
119 0x9608, 0xa558, 0x161b, 0x206f,
120 }, .{
121 0x3088, 0xf25c, 0x7837, 0x9b3f,
122 });
78 try testType(@Vector(8, u16), .{123 try testType(@Vector(8, u16), .{
79 0xcf61, 0xb121, 0x3cf1, 0x3e9f, 0x43a7, 0x8d69, 0x96f5, 0xc11e,124 0xcf61, 0xb121, 0x3cf1, 0x3e9f, 0x43a7, 0x8d69, 0x96f5, 0xc11e,
80 }, .{125 }, .{
...@@ -118,6 +163,16 @@ fn testBinary(comptime op: anytype) !void {...@@ -118,6 +163,16 @@ fn testBinary(comptime op: anytype) !void {
118 0x2c02, 0xff5b, 0x19ca, 0xbbf5, 0x870e, 0xc9ca, 0x47bb, 0xcfcc,163 0x2c02, 0xff5b, 0x19ca, 0xbbf5, 0x870e, 0xc9ca, 0x47bb, 0xcfcc,
119 });164 });
120165
166 try testType(@Vector(1, u32), .{
167 0x1d0d9cc4,
168 }, .{
169 0xce2d0ab6,
170 });
171 try testType(@Vector(2, u32), .{
172 0x5ab78c03, 0xd21bb513,
173 }, .{
174 0x8a6664eb, 0x79eac37d,
175 });
121 try testType(@Vector(4, u32), .{176 try testType(@Vector(4, u32), .{
122 0x234d576e, 0x4151cc9c, 0x39f558e4, 0xba935a32,177 0x234d576e, 0x4151cc9c, 0x39f558e4, 0xba935a32,
123 }, .{178 }, .{
...@@ -161,9 +216,11 @@ fn testBinary(comptime op: anytype) !void {...@@ -161,9 +216,11 @@ fn testBinary(comptime op: anytype) !void {
161 0xf080e943, 0xc8718d14, 0x3f920382, 0x18d101b5,216 0xf080e943, 0xc8718d14, 0x3f920382, 0x18d101b5,
162 });217 });
163218
164 // TODO: implement fallback for pcmpeqq219 try testType(@Vector(1, u64), .{
165 if (!comptime @import("std").Target.x86.featureSetHas(@import("builtin").cpu.features, .sse4_1)) return;220 0x333f593bf9d08546,
166221 }, .{
222 0x6918bd767e730778,
223 });
167 try testType(@Vector(2, u64), .{224 try testType(@Vector(2, u64), .{
168 0x4cd89a317b03d430, 0x28998f61842f63a9,225 0x4cd89a317b03d430, 0x28998f61842f63a9,
169 }, .{226 }, .{