| ... | ... | @@ -2097,11 +2097,11 @@ fn gen(self: *CodeGen) InnerError!void { |
| 2097 | 2097 | // The address where to store the return value for the caller is in a |
| 2098 | 2098 | // register which the callee is free to clobber. Therefore, we purposely |
| 2099 | 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 | 2101 | try self.genSetMem( |
| 2102 | 2102 | .{ .frame = frame_index }, |
| 2103 | 2103 | 0, |
| 2104 | | Type.usize, |
| 2104 | .usize, |
| 2105 | 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 | 2122 | info.reg_save_area = .{ .index = reg_save_area_fi }; |
| 2123 | 2123 | |
| 2124 | 2124 | for (abi.SysV.c_abi_int_param_regs[info.gp_count..], info.gp_count..) |reg, reg_i| |
| 2125 | | try self.genSetMem( |
| 2126 | | .{ .frame = reg_save_area_fi }, |
| 2127 | | @intCast(reg_i * 8), |
| 2128 | | Type.usize, |
| 2129 | | .{ .register = reg }, |
| 2130 | | .{}, |
| 2131 | | ); |
| 2125 | try self.genSetMem(.{ .frame = reg_save_area_fi }, @intCast(reg_i * 8), .usize, .{ .register = reg }, .{}); |
| 2132 | 2126 | |
| 2133 | 2127 | try self.asmRegisterImmediate(.{ ._, .cmp }, .al, .u(info.fp_count)); |
| 2134 | 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 | 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 | 2564 | .required_features = &.{.mmx}, |
| 2561 | 2565 | .mir_tag = .{ .p_, mir_tag }, |
| ... | ... | @@ -2615,6 +2619,16 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 2615 | 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 | 2633 | .required_features = &.{.mmx}, |
| 2620 | 2634 | .loop = .bitwise, |
| ... | ... | @@ -3070,11 +3084,58 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 3070 | 3084 | .{ .ops = &.{ .gpr_limb, .{ .implicit = 0 }, .gpr_limb } }, |
| 3071 | 3085 | }, |
| 3072 | 3086 | }, |
| 3073 | | }, .{ .invert_result = switch (cmp_op) { |
| 3074 | | .eq => false, |
| 3075 | | .neq => true, |
| 3076 | | else => unreachable, |
| 3077 | | } }), |
| 3087 | .{ |
| 3088 | .scalar = .{ .any_int = .byte }, |
| 3089 | .clobbers = .{ .eflags = true }, |
| 3090 | .loop = .elementwise, |
| 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 | 3139 | .gte => unreachable, |
| 3079 | 3140 | .gt => unreachable, |
| 3080 | 3141 | } |
| ... | ... | @@ -3242,7 +3303,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 3242 | 3303 | const opt_child_ty = opt_ty.optionalChild(zcu); |
| 3243 | 3304 | const opt_child_abi_size: i32 = @intCast(opt_child_ty.abiSize(zcu)); |
| 3244 | 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 | 3307 | try ops[0].store(&has_value, cg); |
| 3247 | 3308 | try has_value.die(cg); |
| 3248 | 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 | 3487 | .array_to_slice => if (use_old) try cg.airArrayToSlice(inst) else { |
| 3427 | 3488 | const ty_op = air_datas[@intFromEnum(inst)].ty_op; |
| 3428 | 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 | 3491 | .immediate = cg.typeOf(ty_op.operand).childType(zcu).arrayLen(zcu), |
| 3431 | 3492 | }); |
| 3432 | 3493 | try ops[0].toPair(&len, cg); |
| ... | ... | @@ -3510,17 +3571,11 @@ fn genLazy(self: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void { |
| 3510 | 3571 | try self.genSetMem( |
| 3511 | 3572 | .{ .reg = ret_reg }, |
| 3512 | 3573 | 0, |
| 3513 | | Type.usize, |
| 3574 | .usize, |
| 3514 | 3575 | .{ .register_offset = .{ .reg = data_reg, .off = data_off } }, |
| 3515 | 3576 | .{}, |
| 3516 | 3577 | ); |
| 3517 | | try self.genSetMem( |
| 3518 | | .{ .reg = ret_reg }, |
| 3519 | | 8, |
| 3520 | | Type.usize, |
| 3521 | | .{ .immediate = tag_name_len }, |
| 3522 | | .{}, |
| 3523 | | ); |
| 3578 | try self.genSetMem(.{ .reg = ret_reg }, 8, .usize, .{ .immediate = tag_name_len }, .{}); |
| 3524 | 3579 | |
| 3525 | 3580 | exitlude_jump_reloc.* = try self.asmJmpReloc(undefined); |
| 3526 | 3581 | self.performReloc(skip_reloc); |
| ... | ... | @@ -4495,8 +4550,8 @@ fn airIntCast(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 4495 | 4550 | high_mcv.getReg().? |
| 4496 | 4551 | else |
| 4497 | 4552 | try self.copyToTmpRegister(switch (src_int_info.signedness) { |
| 4498 | | .signed => Type.isize, |
| 4499 | | .unsigned => Type.usize, |
| 4553 | .signed => .isize, |
| 4554 | .unsigned => .usize, |
| 4500 | 4555 | }, high_mcv); |
| 4501 | 4556 | const high_lock = self.register_manager.lockRegAssumeUnused(high_reg); |
| 4502 | 4557 | defer self.register_manager.unlockReg(high_lock); |
| ... | ... | @@ -4504,7 +4559,7 @@ fn airIntCast(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 4504 | 4559 | const high_bits = src_int_info.bits % 64; |
| 4505 | 4560 | if (high_bits > 0) { |
| 4506 | 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 | 4563 | try self.genCopy(high_ty, high_mcv, .{ .register = high_reg }, .{}); |
| 4509 | 4564 | } |
| 4510 | 4565 | |
| ... | ... | @@ -4513,13 +4568,7 @@ fn airIntCast(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 4513 | 4568 | switch (extend) { |
| 4514 | 4569 | .signed => extend: { |
| 4515 | 4570 | const extend_mcv = MCValue{ .register = high_reg }; |
| 4516 | | try self.genShiftBinOpMir( |
| 4517 | | .{ ._r, .sa }, |
| 4518 | | Type.isize, |
| 4519 | | extend_mcv, |
| 4520 | | Type.u8, |
| 4521 | | .{ .immediate = 63 }, |
| 4522 | | ); |
| 4571 | try self.genShiftBinOpMir(.{ ._r, .sa }, .isize, extend_mcv, .u8, .{ .immediate = 63 }); |
| 4523 | 4572 | break :extend extend_mcv; |
| 4524 | 4573 | }, |
| 4525 | 4574 | .unsigned => .{ .immediate = 0 }, |
| ... | ... | @@ -4621,7 +4670,7 @@ fn airTrunc(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 4621 | 4670 | const splat_mcv = try self.genTypedValue(.fromInterned(splat_val)); |
| 4622 | 4671 | const splat_addr_mcv: MCValue = switch (splat_mcv) { |
| 4623 | 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 | }; |
| 4626 | 4675 | |
| 4627 | 4676 | const dst_reg = dst_mcv.getReg().?; |
| ... | ... | @@ -4837,7 +4886,7 @@ fn airMulDivBinOp(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 4837 | 4886 | state: State, |
| 4838 | 4887 | reloc: Mir.Inst.Index, |
| 4839 | 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 | 4890 | try self.asmMemoryImmediate( |
| 4842 | 4891 | .{ ._, .mov }, |
| 4843 | 4892 | .{ .base = .{ .frame = frame_index }, .mod = .{ .rm = .{ .size = .qword } } }, |
| ... | ... | @@ -4852,7 +4901,7 @@ fn airMulDivBinOp(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 4852 | 4901 | const mat_lhs_mcv = switch (lhs_mcv) { |
| 4853 | 4902 | .load_symbol => mat_lhs_mcv: { |
| 4854 | 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 | 4905 | break :mat_lhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } }; |
| 4857 | 4906 | }, |
| 4858 | 4907 | else => lhs_mcv, |
| ... | ... | @@ -4876,7 +4925,7 @@ fn airMulDivBinOp(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 4876 | 4925 | const mat_rhs_mcv = switch (rhs_mcv) { |
| 4877 | 4926 | .load_symbol => mat_rhs_mcv: { |
| 4878 | 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 | 4929 | break :mat_rhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } }; |
| 4881 | 4930 | }, |
| 4882 | 4931 | else => rhs_mcv, |
| ... | ... | @@ -4975,7 +5024,7 @@ fn airMulDivBinOp(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 4975 | 5024 | const mat_rhs_mcv = switch (rhs_mcv) { |
| 4976 | 5025 | .load_symbol => mat_rhs_mcv: { |
| 4977 | 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 | 5028 | break :mat_rhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } }; |
| 4980 | 5029 | }, |
| 4981 | 5030 | else => rhs_mcv, |
| ... | ... | @@ -5062,22 +5111,10 @@ fn airAddSat(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 5062 | 5111 | const reg_extra_bits = self.regExtraBits(ty); |
| 5063 | 5112 | const cc: Condition = if (ty.isSignedInt(zcu)) cc: { |
| 5064 | 5113 | if (reg_extra_bits > 0) { |
| 5065 | | try self.genShiftBinOpMir( |
| 5066 | | .{ ._l, .sa }, |
| 5067 | | ty, |
| 5068 | | dst_mcv, |
| 5069 | | Type.u8, |
| 5070 | | .{ .immediate = reg_extra_bits }, |
| 5071 | | ); |
| 5114 | try self.genShiftBinOpMir(.{ ._l, .sa }, ty, dst_mcv, .u8, .{ .immediate = reg_extra_bits }); |
| 5072 | 5115 | } |
| 5073 | 5116 | try self.genSetReg(limit_reg, ty, dst_mcv, .{}); |
| 5074 | | try self.genShiftBinOpMir( |
| 5075 | | .{ ._r, .sa }, |
| 5076 | | ty, |
| 5077 | | limit_mcv, |
| 5078 | | Type.u8, |
| 5079 | | .{ .immediate = reg_bits - 1 }, |
| 5080 | | ); |
| 5117 | try self.genShiftBinOpMir(.{ ._r, .sa }, ty, limit_mcv, .u8, .{ .immediate = reg_bits - 1 }); |
| 5081 | 5118 | try self.genBinOpMir(.{ ._, .xor }, ty, limit_mcv, .{ |
| 5082 | 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 | 5124 | const shifted_rhs_lock = self.register_manager.lockRegAssumeUnused(shifted_rhs_reg); |
| 5088 | 5125 | defer self.register_manager.unlockReg(shifted_rhs_lock); |
| 5089 | 5126 | |
| 5090 | | try self.genShiftBinOpMir( |
| 5091 | | .{ ._l, .sa }, |
| 5092 | | ty, |
| 5093 | | shifted_rhs_mcv, |
| 5094 | | Type.u8, |
| 5095 | | .{ .immediate = reg_extra_bits }, |
| 5096 | | ); |
| 5127 | try self.genShiftBinOpMir(.{ ._l, .sa }, ty, shifted_rhs_mcv, .u8, .{ .immediate = reg_extra_bits }); |
| 5097 | 5128 | try self.genBinOpMir(.{ ._, .add }, ty, dst_mcv, shifted_rhs_mcv); |
| 5098 | 5129 | } else try self.genBinOpMir(.{ ._, .add }, ty, dst_mcv, rhs_mcv); |
| 5099 | 5130 | break :cc .o; |
| ... | ... | @@ -5117,13 +5148,8 @@ fn airAddSat(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 5117 | 5148 | registerAlias(limit_reg, cmov_abi_size), |
| 5118 | 5149 | ); |
| 5119 | 5150 | |
| 5120 | | if (reg_extra_bits > 0 and ty.isSignedInt(zcu)) try self.genShiftBinOpMir( |
| 5121 | | .{ ._r, .sa }, |
| 5122 | | ty, |
| 5123 | | dst_mcv, |
| 5124 | | Type.u8, |
| 5125 | | .{ .immediate = reg_extra_bits }, |
| 5126 | | ); |
| 5151 | if (reg_extra_bits > 0 and ty.isSignedInt(zcu)) |
| 5152 | try self.genShiftBinOpMir(.{ ._r, .sa }, ty, dst_mcv, .u8, .{ .immediate = reg_extra_bits }); |
| 5127 | 5153 | |
| 5128 | 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 | 5189 | const reg_extra_bits = self.regExtraBits(ty); |
| 5164 | 5190 | const cc: Condition = if (ty.isSignedInt(zcu)) cc: { |
| 5165 | 5191 | if (reg_extra_bits > 0) { |
| 5166 | | try self.genShiftBinOpMir( |
| 5167 | | .{ ._l, .sa }, |
| 5168 | | ty, |
| 5169 | | dst_mcv, |
| 5170 | | Type.u8, |
| 5171 | | .{ .immediate = reg_extra_bits }, |
| 5172 | | ); |
| 5192 | try self.genShiftBinOpMir(.{ ._l, .sa }, ty, dst_mcv, .u8, .{ .immediate = reg_extra_bits }); |
| 5173 | 5193 | } |
| 5174 | 5194 | try self.genSetReg(limit_reg, ty, dst_mcv, .{}); |
| 5175 | | try self.genShiftBinOpMir( |
| 5176 | | .{ ._r, .sa }, |
| 5177 | | ty, |
| 5178 | | limit_mcv, |
| 5179 | | Type.u8, |
| 5180 | | .{ .immediate = reg_bits - 1 }, |
| 5181 | | ); |
| 5195 | try self.genShiftBinOpMir(.{ ._r, .sa }, ty, limit_mcv, .u8, .{ .immediate = reg_bits - 1 }); |
| 5182 | 5196 | try self.genBinOpMir(.{ ._, .xor }, ty, limit_mcv, .{ |
| 5183 | 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 | 5202 | const shifted_rhs_lock = self.register_manager.lockRegAssumeUnused(shifted_rhs_reg); |
| 5189 | 5203 | defer self.register_manager.unlockReg(shifted_rhs_lock); |
| 5190 | 5204 | |
| 5191 | | try self.genShiftBinOpMir( |
| 5192 | | .{ ._l, .sa }, |
| 5193 | | ty, |
| 5194 | | shifted_rhs_mcv, |
| 5195 | | Type.u8, |
| 5196 | | .{ .immediate = reg_extra_bits }, |
| 5197 | | ); |
| 5205 | try self.genShiftBinOpMir(.{ ._l, .sa }, ty, shifted_rhs_mcv, .u8, .{ .immediate = reg_extra_bits }); |
| 5198 | 5206 | try self.genBinOpMir(.{ ._, .sub }, ty, dst_mcv, shifted_rhs_mcv); |
| 5199 | 5207 | } else try self.genBinOpMir(.{ ._, .sub }, ty, dst_mcv, rhs_mcv); |
| 5200 | 5208 | break :cc .o; |
| ... | ... | @@ -5211,13 +5219,8 @@ fn airSubSat(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 5211 | 5219 | registerAlias(limit_reg, cmov_abi_size), |
| 5212 | 5220 | ); |
| 5213 | 5221 | |
| 5214 | | if (reg_extra_bits > 0 and ty.isSignedInt(zcu)) try self.genShiftBinOpMir( |
| 5215 | | .{ ._r, .sa }, |
| 5216 | | ty, |
| 5217 | | dst_mcv, |
| 5218 | | Type.u8, |
| 5219 | | .{ .immediate = reg_extra_bits }, |
| 5220 | | ); |
| 5222 | if (reg_extra_bits > 0 and ty.isSignedInt(zcu)) |
| 5223 | try self.genShiftBinOpMir(.{ ._r, .sa }, ty, dst_mcv, .u8, .{ .immediate = reg_extra_bits }); |
| 5221 | 5224 | |
| 5222 | 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 | 5233 | |
| 5231 | 5234 | const result = result: { |
| 5232 | 5235 | if (ty.toIntern() == .i128_type) { |
| 5233 | | const ptr_c_int = try pt.singleMutPtrType(Type.c_int); |
| 5234 | | const overflow = try self.allocTempRegOrMem(Type.c_int, false); |
| 5236 | const ptr_c_int = try pt.singleMutPtrType(.c_int); |
| 5237 | const overflow = try self.allocTempRegOrMem(.c_int, false); |
| 5235 | 5238 | |
| 5236 | 5239 | const dst_mcv = try self.genCall(.{ .lib = .{ |
| 5237 | 5240 | .return_type = .i128_type, |
| 5238 | 5241 | .param_types = &.{ .i128_type, .i128_type, ptr_c_int.toIntern() }, |
| 5239 | 5242 | .callee = "__muloti4", |
| 5240 | | } }, &.{ Type.i128, Type.i128, ptr_c_int }, &.{ |
| 5243 | } }, &.{ .i128, .i128, ptr_c_int }, &.{ |
| 5241 | 5244 | .{ .air_ref = bin_op.lhs }, |
| 5242 | 5245 | .{ .air_ref = bin_op.rhs }, |
| 5243 | 5246 | overflow.address(), |
| ... | ... | @@ -5253,7 +5256,7 @@ fn airMulSat(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 5253 | 5256 | const mat_lhs_mcv = switch (lhs_mcv) { |
| 5254 | 5257 | .load_symbol => mat_lhs_mcv: { |
| 5255 | 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 | 5260 | break :mat_lhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } }; |
| 5258 | 5261 | }, |
| 5259 | 5262 | else => lhs_mcv, |
| ... | ... | @@ -5277,7 +5280,7 @@ fn airMulSat(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 5277 | 5280 | const mat_rhs_mcv = switch (rhs_mcv) { |
| 5278 | 5281 | .load_symbol => mat_rhs_mcv: { |
| 5279 | 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 | 5284 | break :mat_rhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } }; |
| 5282 | 5285 | }, |
| 5283 | 5286 | else => rhs_mcv, |
| ... | ... | @@ -5339,13 +5342,7 @@ fn airMulSat(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 5339 | 5342 | const cc: Condition = if (ty.isSignedInt(zcu)) cc: { |
| 5340 | 5343 | try self.genSetReg(limit_reg, ty, lhs_mcv, .{}); |
| 5341 | 5344 | try self.genBinOpMir(.{ ._, .xor }, ty, limit_mcv, rhs_mcv); |
| 5342 | | try self.genShiftBinOpMir( |
| 5343 | | .{ ._r, .sa }, |
| 5344 | | ty, |
| 5345 | | limit_mcv, |
| 5346 | | Type.u8, |
| 5347 | | .{ .immediate = reg_bits - 1 }, |
| 5348 | | ); |
| 5345 | try self.genShiftBinOpMir(.{ ._r, .sa }, ty, limit_mcv, .u8, .{ .immediate = reg_bits - 1 }); |
| 5349 | 5346 | try self.genBinOpMir(.{ ._, .xor }, ty, limit_mcv, .{ |
| 5350 | 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 | 5407 | try self.genSetMem( |
| 5411 | 5408 | .{ .frame = frame_index }, |
| 5412 | 5409 | @intCast(tuple_ty.structFieldOffset(1, zcu)), |
| 5413 | | Type.u1, |
| 5410 | .u1, |
| 5414 | 5411 | .{ .eflags = cc }, |
| 5415 | 5412 | .{}, |
| 5416 | 5413 | ); |
| ... | ... | @@ -5558,12 +5555,7 @@ fn genSetFrameTruncatedOverflowCompare( |
| 5558 | 5555 | const eq_reg = temp_regs[2]; |
| 5559 | 5556 | if (overflow_cc) |_| { |
| 5560 | 5557 | try self.asmSetccRegister(.ne, eq_reg.to8()); |
| 5561 | | try self.genBinOpMir( |
| 5562 | | .{ ._, .@"or" }, |
| 5563 | | Type.u8, |
| 5564 | | .{ .register = overflow_reg }, |
| 5565 | | .{ .register = eq_reg }, |
| 5566 | | ); |
| 5558 | try self.genBinOpMir(.{ ._, .@"or" }, .u8, .{ .register = overflow_reg }, .{ .register = eq_reg }); |
| 5567 | 5559 | } |
| 5568 | 5560 | |
| 5569 | 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 | 5735 | if (src_bits > 64 and src_bits <= 128 and |
| 5744 | 5736 | dst_info.bits > 64 and dst_info.bits <= 128) switch (dst_info.signedness) { |
| 5745 | 5737 | .signed => { |
| 5746 | | const ptr_c_int = try pt.singleMutPtrType(Type.c_int); |
| 5747 | | const overflow = try self.allocTempRegOrMem(Type.c_int, false); |
| 5738 | const ptr_c_int = try pt.singleMutPtrType(.c_int); |
| 5739 | const overflow = try self.allocTempRegOrMem(.c_int, false); |
| 5748 | 5740 | const result = try self.genCall(.{ .lib = .{ |
| 5749 | 5741 | .return_type = .i128_type, |
| 5750 | 5742 | .param_types = &.{ .i128_type, .i128_type, ptr_c_int.toIntern() }, |
| 5751 | 5743 | .callee = "__muloti4", |
| 5752 | | } }, &.{ Type.i128, Type.i128, ptr_c_int }, &.{ |
| 5744 | } }, &.{ .i128, .i128, ptr_c_int }, &.{ |
| 5753 | 5745 | .{ .air_ref = bin_op.lhs }, |
| 5754 | 5746 | .{ .air_ref = bin_op.rhs }, |
| 5755 | 5747 | overflow.address(), |
| ... | ... | @@ -5765,7 +5757,7 @@ fn airMulWithOverflow(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 5765 | 5757 | ); |
| 5766 | 5758 | try self.asmMemoryImmediate( |
| 5767 | 5759 | .{ ._, .cmp }, |
| 5768 | | try overflow.mem(self, .{ .size = self.memSize(Type.c_int) }), |
| 5760 | try overflow.mem(self, .{ .size = self.memSize(.c_int) }), |
| 5769 | 5761 | .s(0), |
| 5770 | 5762 | ); |
| 5771 | 5763 | try self.genSetMem( |
| ... | ... | @@ -5794,7 +5786,7 @@ fn airMulWithOverflow(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 5794 | 5786 | const mat_lhs_mcv = switch (lhs_mcv) { |
| 5795 | 5787 | .load_symbol => mat_lhs_mcv: { |
| 5796 | 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 | 5790 | break :mat_lhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } }; |
| 5799 | 5791 | }, |
| 5800 | 5792 | else => lhs_mcv, |
| ... | ... | @@ -5807,7 +5799,7 @@ fn airMulWithOverflow(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 5807 | 5799 | const mat_rhs_mcv = switch (rhs_mcv) { |
| 5808 | 5800 | .load_symbol => mat_rhs_mcv: { |
| 5809 | 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 | 5803 | break :mat_rhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } }; |
| 5812 | 5804 | }, |
| 5813 | 5805 | else => rhs_mcv, |
| ... | ... | @@ -6100,7 +6092,7 @@ fn airShlShrBinOp(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 6100 | 6092 | defer self.register_manager.unlockReg(tmp_lock); |
| 6101 | 6093 | |
| 6102 | 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 | 6096 | const off = frame_addr.off + (lhs_bits - 1) / 64 * 8; |
| 6105 | 6097 | try self.genSetReg( |
| 6106 | 6098 | tmp_reg, |
| ... | ... | @@ -6283,13 +6275,12 @@ fn airShlShrBinOp(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 6283 | 6275 | const mask_mcv = try self.genTypedValue(.fromInterned(try pt.intern(.{ .aggregate = .{ |
| 6284 | 6276 | .ty = mask_ty.toIntern(), |
| 6285 | 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 | 6279 | } ++ [1]InternPool.Index{ |
| 6288 | | (try pt.intValue(Type.u8, 0)).toIntern(), |
| 6280 | (try pt.intValue(.u8, 0)).toIntern(), |
| 6289 | 6281 | } ** 15) }, |
| 6290 | 6282 | } }))); |
| 6291 | | const mask_addr_reg = |
| 6292 | | try self.copyToTmpRegister(Type.usize, mask_mcv.address()); |
| 6283 | const mask_addr_reg = try self.copyToTmpRegister(.usize, mask_mcv.address()); |
| 6293 | 6284 | const mask_addr_lock = self.register_manager.lockRegAssumeUnused(mask_addr_reg); |
| 6294 | 6285 | defer self.register_manager.unlockReg(mask_addr_lock); |
| 6295 | 6286 | |
| ... | ... | @@ -6423,7 +6414,7 @@ fn airOptionalPayloadPtrSet(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 6423 | 6414 | try self.genSetMem( |
| 6424 | 6415 | .{ .reg = dst_mcv.getReg().? }, |
| 6425 | 6416 | pl_abi_size, |
| 6426 | | Type.bool, |
| 6417 | .bool, |
| 6427 | 6418 | .{ .immediate = 1 }, |
| 6428 | 6419 | .{}, |
| 6429 | 6420 | ); |
| ... | ... | @@ -6462,9 +6453,9 @@ fn airUnwrapErrUnionErr(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 6462 | 6453 | .{ ._r, .sh }, |
| 6463 | 6454 | err_union_ty, |
| 6464 | 6455 | result, |
| 6465 | | Type.u8, |
| 6456 | .u8, |
| 6466 | 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 | 6459 | break :result result; |
| 6469 | 6460 | }, |
| 6470 | 6461 | .load_frame => |frame_addr| break :result .{ .load_frame = .{ |
| ... | ... | @@ -6623,7 +6614,7 @@ fn genUnwrapErrUnionPayloadMir( |
| 6623 | 6614 | .{ ._r, .sh }, |
| 6624 | 6615 | err_union_ty, |
| 6625 | 6616 | result_mcv, |
| 6626 | | Type.u8, |
| 6617 | .u8, |
| 6627 | 6618 | .{ .immediate = @as(u6, @intCast(payload_off * 8)) }, |
| 6628 | 6619 | ) else try self.truncateRegister(payload_ty, result_mcv.register); |
| 6629 | 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 | 6920 | defer self.register_manager.unlockReg(offset_reg_lock); |
| 6930 | 6921 | |
| 6931 | 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 | 6924 | // TODO we could allocate register here, but need to expect addr register and potentially |
| 6934 | 6925 | // offset register. |
| 6935 | 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 | 7055 | .{ ._, .bt }, |
| 7065 | 7056 | .{ |
| 7066 | 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 | 7060 | .mod = .{ .rm = .{ .size = .qword } }, |
| 7070 | 7061 | }, |
| ... | ... | @@ -7074,7 +7065,7 @@ fn airArrayElemVal(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 7074 | 7065 | .{ ._, .bt }, |
| 7075 | 7066 | .{ |
| 7076 | 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 | 7070 | .mod = .{ .rm = .{ .size = .qword } }, |
| 7080 | 7071 | }, |
| ... | ... | @@ -7122,7 +7113,7 @@ fn airArrayElemVal(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 7122 | 7113 | .load_direct, |
| 7123 | 7114 | .load_got, |
| 7124 | 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 | 7117 | .lea_symbol, .lea_direct, .lea_tlv => unreachable, |
| 7127 | 7118 | else => return self.fail("TODO airArrayElemVal_val for {s} of {}", .{ |
| 7128 | 7119 | @tagName(array_mcv), array_ty.fmt(pt), |
| ... | ... | @@ -7136,12 +7127,7 @@ fn airArrayElemVal(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 7136 | 7127 | // TODO we could allocate register here, but need to expect addr register and potentially |
| 7137 | 7128 | // offset register. |
| 7138 | 7129 | const dst_mcv = try self.allocRegOrMem(inst, false); |
| 7139 | | try self.genBinOpMir( |
| 7140 | | .{ ._, .add }, |
| 7141 | | Type.usize, |
| 7142 | | .{ .register = addr_reg }, |
| 7143 | | .{ .register = offset_reg }, |
| 7144 | | ); |
| 7130 | try self.genBinOpMir(.{ ._, .add }, .usize, .{ .register = addr_reg }, .{ .register = offset_reg }); |
| 7145 | 7131 | try self.genCopy(elem_ty, dst_mcv, .{ .indirect = .{ .reg = addr_reg } }, .{}); |
| 7146 | 7132 | break :result dst_mcv; |
| 7147 | 7133 | }; |
| ... | ... | @@ -7329,13 +7315,7 @@ fn airGetUnionTag(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 7329 | 7315 | .register => { |
| 7330 | 7316 | const shift: u6 = @intCast(layout.tagOffset() * 8); |
| 7331 | 7317 | const result = try self.copyToRegisterWithInstTracking(inst, union_ty, operand); |
| 7332 | | try self.genShiftBinOpMir( |
| 7333 | | .{ ._r, .sh }, |
| 7334 | | Type.usize, |
| 7335 | | result, |
| 7336 | | Type.u8, |
| 7337 | | .{ .immediate = shift }, |
| 7338 | | ); |
| 7318 | try self.genShiftBinOpMir(.{ ._r, .sh }, .usize, result, .u8, .{ .immediate = shift }); |
| 7339 | 7319 | break :blk MCValue{ |
| 7340 | 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 | 7424 | if (src_bits <= 8) { |
| 7445 | 7425 | const wide_reg = try self.copyToTmpRegister(src_ty, mat_src_mcv); |
| 7446 | 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 | 7428 | try self.genBinOpMir( |
| 7449 | 7429 | .{ ._, .sub }, |
| 7450 | 7430 | dst_ty, |
| ... | ... | @@ -7464,25 +7444,15 @@ fn airClz(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 7464 | 7444 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 7465 | 7445 | defer self.register_manager.unlockReg(tmp_lock); |
| 7466 | 7446 | |
| 7467 | | try self.genBinOpMir( |
| 7468 | | .{ ._, .lzcnt }, |
| 7469 | | Type.u64, |
| 7470 | | dst_mcv, |
| 7471 | | if (mat_src_mcv.isBase()) |
| 7472 | | mat_src_mcv |
| 7473 | | else |
| 7474 | | .{ .register = mat_src_mcv.register_pair[0] }, |
| 7475 | | ); |
| 7447 | try self.genBinOpMir(.{ ._, .lzcnt }, .u64, dst_mcv, if (mat_src_mcv.isBase()) |
| 7448 | mat_src_mcv |
| 7449 | else |
| 7450 | .{ .register = mat_src_mcv.register_pair[0] }); |
| 7476 | 7451 | try self.genBinOpMir(.{ ._, .add }, dst_ty, dst_mcv, .{ .immediate = 64 }); |
| 7477 | | try self.genBinOpMir( |
| 7478 | | .{ ._, .lzcnt }, |
| 7479 | | Type.u64, |
| 7480 | | tmp_mcv, |
| 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 | | ); |
| 7452 | try self.genBinOpMir(.{ ._, .lzcnt }, .u64, tmp_mcv, if (mat_src_mcv.isBase()) |
| 7453 | mat_src_mcv.address().offset(8).deref() |
| 7454 | else |
| 7455 | .{ .register = mat_src_mcv.register_pair[1] }); |
| 7486 | 7456 | try self.asmCmovccRegisterRegister(.nc, dst_reg.to32(), tmp_reg.to32()); |
| 7487 | 7457 | |
| 7488 | 7458 | if (src_bits < 128) try self.genBinOpMir( |
| ... | ... | @@ -7510,7 +7480,7 @@ fn airClz(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 7510 | 7480 | defer self.register_manager.unlockReg(wide_lock); |
| 7511 | 7481 | |
| 7512 | 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 | 7484 | } else try self.genBinOpMir(.{ ._, .bsr }, src_ty, dst_mcv, mat_src_mcv); |
| 7515 | 7485 | |
| 7516 | 7486 | try self.asmCmovccRegisterRegister( |
| ... | ... | @@ -7534,7 +7504,7 @@ fn airClz(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 7534 | 7504 | try self.truncateRegister(src_ty, wide_reg); |
| 7535 | 7505 | try self.genBinOpMir( |
| 7536 | 7506 | .{ ._, .bsr }, |
| 7537 | | if (src_bits <= 8) Type.u16 else src_ty, |
| 7507 | if (src_bits <= 8) .u16 else src_ty, |
| 7538 | 7508 | dst_mcv, |
| 7539 | 7509 | .{ .register = wide_reg }, |
| 7540 | 7510 | ); |
| ... | ... | @@ -7645,7 +7615,7 @@ fn airCtz(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 7645 | 7615 | break :result dst_mcv; |
| 7646 | 7616 | } |
| 7647 | 7617 | |
| 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 | 7619 | if (has_bmi) { |
| 7650 | 7620 | if (src_bits <= 64) { |
| 7651 | 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 | 7652 | else |
| 7683 | 7653 | .{ .register = mat_src_mcv.register_pair[1] }; |
| 7684 | 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 | 7656 | try self.genBinOpMir( |
| 7687 | 7657 | .{ ._, .@"or" }, |
| 7688 | | Type.u64, |
| 7658 | .u64, |
| 7689 | 7659 | dst_mcv, |
| 7690 | 7660 | .{ .immediate = @as(u64, std.math.maxInt(u64)) << @intCast(src_bits - 64) }, |
| 7691 | 7661 | ); |
| 7692 | 7662 | break :masked dst_mcv; |
| 7693 | 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 | 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 | 7667 | try self.asmCmovccRegisterRegister(.nc, dst_reg.to32(), tmp_reg.to32()); |
| 7698 | 7668 | } |
| 7699 | 7669 | break :result dst_mcv; |
| ... | ... | @@ -7766,7 +7736,7 @@ fn airPopCount(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 7766 | 7736 | const tmp_locks = self.register_manager.lockRegsAssumeUnused(2, tmp_regs); |
| 7767 | 7737 | defer for (tmp_locks) |lock| self.register_manager.unlockReg(lock); |
| 7768 | 7738 | |
| 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 | 7740 | mat_src_mcv |
| 7771 | 7741 | else |
| 7772 | 7742 | .{ .register = mat_src_mcv.register_pair[0] }, false); |
| ... | ... | @@ -7794,7 +7764,7 @@ fn genPopCount( |
| 7794 | 7764 | const src_abi_size: u32 = @intCast(src_ty.abiSize(pt.zcu)); |
| 7795 | 7765 | if (self.hasFeature(.popcnt)) return self.genBinOpMir( |
| 7796 | 7766 | .{ ._, .popcnt }, |
| 7797 | | if (src_abi_size > 1) src_ty else Type.u32, |
| 7767 | if (src_abi_size > 1) src_ty else .u32, |
| 7798 | 7768 | .{ .register = dst_reg }, |
| 7799 | 7769 | if (src_abi_size > 1) src_mcv else src: { |
| 7800 | 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 | 8027 | } }, |
| 8058 | 8028 | src_ty, |
| 8059 | 8029 | dst_mcv, |
| 8060 | | if (src_bits > 256) Type.u16 else Type.u8, |
| 8030 | if (src_bits > 256) .u16 else .u8, |
| 8061 | 8031 | .{ .immediate = src_ty.abiSize(zcu) * 8 - src_bits }, |
| 8062 | 8032 | ); |
| 8063 | 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 | 8151 | if (extra_bits > 0) try self.genShiftBinOpMir(switch (signedness) { |
| 8182 | 8152 | .signed => .{ ._r, .sa }, |
| 8183 | 8153 | .unsigned => .{ ._r, .sh }, |
| 8184 | | }, src_ty, dst_mcv, Type.u8, .{ .immediate = extra_bits }); |
| 8154 | }, src_ty, dst_mcv, .u8, .{ .immediate = extra_bits }); |
| 8185 | 8155 | |
| 8186 | 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 | 8222 | try sign_mcv.mem(self, .{ .size = .fromSize(abi_size) }) |
| 8253 | 8223 | 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 | 8226 | .mod = .{ .rm = .{ .size = .fromSize(abi_size) } }, |
| 8257 | 8227 | }; |
| 8258 | 8228 | |
| ... | ... | @@ -8947,9 +8917,9 @@ fn packedLoad(self: *CodeGen, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) |
| 8947 | 8917 | defer self.register_manager.unlockReg(tmp_lock); |
| 8948 | 8918 | |
| 8949 | 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 | 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 | 8925 | return; |
| ... | ... | @@ -9104,13 +9074,13 @@ fn airLoad(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 9104 | 9074 | const high_reg = if (high_mcv.isRegister()) |
| 9105 | 9075 | high_mcv.getReg().? |
| 9106 | 9076 | else |
| 9107 | | try self.copyToTmpRegister(Type.usize, high_mcv); |
| 9077 | try self.copyToTmpRegister(.usize, high_mcv); |
| 9108 | 9078 | const high_lock = self.register_manager.lockReg(high_reg); |
| 9109 | 9079 | defer if (high_lock) |lock| self.register_manager.unlockReg(lock); |
| 9110 | 9080 | |
| 9111 | 9081 | try self.truncateRegister(elem_ty, high_reg); |
| 9112 | 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 | 9084 | high_mcv, |
| 9115 | 9085 | .{ .register = high_reg }, |
| 9116 | 9086 | .{}, |
| ... | ... | @@ -9183,14 +9153,14 @@ fn packedStore(self: *CodeGen, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) |
| 9183 | 9153 | .{ ._l, .sh }, |
| 9184 | 9154 | limb_ty, |
| 9185 | 9155 | tmp_mcv, |
| 9186 | | Type.u8, |
| 9156 | .u8, |
| 9187 | 9157 | .{ .immediate = src_bit_off }, |
| 9188 | 9158 | ), |
| 9189 | 9159 | 1 => try self.genShiftBinOpMir( |
| 9190 | 9160 | .{ ._r, .sh }, |
| 9191 | 9161 | limb_ty, |
| 9192 | 9162 | tmp_mcv, |
| 9193 | | Type.u8, |
| 9163 | .u8, |
| 9194 | 9164 | .{ .immediate = limb_abi_bits - src_bit_off }, |
| 9195 | 9165 | ), |
| 9196 | 9166 | else => unreachable, |
| ... | ... | @@ -9355,7 +9325,10 @@ fn airStructFieldVal(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 9355 | 9325 | const src_mcv = try self.resolveInst(operand); |
| 9356 | 9326 | const field_off: u32 = switch (container_ty.containerLayout(zcu)) { |
| 9357 | 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 | }; |
| 9360 | 9333 | |
| 9361 | 9334 | switch (src_mcv) { |
| ... | ... | @@ -9370,20 +9343,14 @@ fn airStructFieldVal(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 9370 | 9343 | else if (field_off == 0) |
| 9371 | 9344 | (try self.copyToRegisterWithInstTracking(inst, field_ty, src_mcv)).register |
| 9372 | 9345 | else |
| 9373 | | try self.copyToTmpRegister(Type.usize, .{ .register = src_reg }); |
| 9346 | try self.copyToTmpRegister(.usize, .{ .register = src_reg }); |
| 9374 | 9347 | const dst_mcv: MCValue = .{ .register = dst_reg }; |
| 9375 | 9348 | const dst_lock = self.register_manager.lockReg(dst_reg); |
| 9376 | 9349 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); |
| 9377 | 9350 | |
| 9378 | 9351 | if (field_off > 0) { |
| 9379 | 9352 | try self.spillEflagsIfOccupied(); |
| 9380 | | try self.genShiftBinOpMir( |
| 9381 | | .{ ._r, .sh }, |
| 9382 | | Type.usize, |
| 9383 | | dst_mcv, |
| 9384 | | Type.u8, |
| 9385 | | .{ .immediate = field_off }, |
| 9386 | | ); |
| 9353 | try self.genShiftBinOpMir(.{ ._r, .sh }, .usize, dst_mcv, .u8, .{ .immediate = field_off }); |
| 9387 | 9354 | } |
| 9388 | 9355 | if (abi.RegisterClass.gp.isSet(RegisterManager.indexOfRegIntoTracked(dst_reg).?) and |
| 9389 | 9356 | container_ty.abiSize(zcu) * 8 > field_ty.bitSize(zcu)) |
| ... | ... | @@ -9421,13 +9388,7 @@ fn airStructFieldVal(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 9421 | 9388 | |
| 9422 | 9389 | if (field_off > 0) { |
| 9423 | 9390 | try self.spillEflagsIfOccupied(); |
| 9424 | | try self.genShiftBinOpMir( |
| 9425 | | .{ ._r, .sh }, |
| 9426 | | Type.u128, |
| 9427 | | dst_mcv, |
| 9428 | | Type.u8, |
| 9429 | | .{ .immediate = field_off }, |
| 9430 | | ); |
| 9391 | try self.genShiftBinOpMir(.{ ._r, .sh }, .u128, dst_mcv, .u8, .{ .immediate = field_off }); |
| 9431 | 9392 | } |
| 9432 | 9393 | |
| 9433 | 9394 | if (field_bit_size <= 64) { |
| ... | ... | @@ -9451,20 +9412,14 @@ fn airStructFieldVal(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 9451 | 9412 | try self.copyToRegisterWithInstTracking(inst, field_ty, dst_mcv); |
| 9452 | 9413 | }; |
| 9453 | 9414 | |
| 9454 | | const dst_reg = try self.copyToTmpRegister(Type.usize, .{ .register = src_reg }); |
| 9415 | const dst_reg = try self.copyToTmpRegister(.usize, .{ .register = src_reg }); |
| 9455 | 9416 | const dst_mcv = MCValue{ .register = dst_reg }; |
| 9456 | 9417 | const dst_lock = self.register_manager.lockReg(dst_reg); |
| 9457 | 9418 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); |
| 9458 | 9419 | |
| 9459 | 9420 | if (field_off % 64 > 0) { |
| 9460 | 9421 | try self.spillEflagsIfOccupied(); |
| 9461 | | try self.genShiftBinOpMir( |
| 9462 | | .{ ._r, .sh }, |
| 9463 | | Type.usize, |
| 9464 | | dst_mcv, |
| 9465 | | Type.u8, |
| 9466 | | .{ .immediate = field_off % 64 }, |
| 9467 | | ); |
| 9422 | try self.genShiftBinOpMir(.{ ._r, .sh }, .usize, dst_mcv, .u8, .{ .immediate = field_off % 64 }); |
| 9468 | 9423 | } |
| 9469 | 9424 | if (self.regExtraBits(field_ty) > 0) try self.truncateRegister(field_ty, dst_reg); |
| 9470 | 9425 | |
| ... | ... | @@ -9479,11 +9434,7 @@ fn airStructFieldVal(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 9479 | 9434 | 0 => if (self.reuseOperand(inst, extra.struct_operand, 0, src_mcv)) { |
| 9480 | 9435 | self.eflags_inst = null; // actually stop tracking the overflow part |
| 9481 | 9436 | break :result .{ .register = ro.reg }; |
| 9482 | | } else break :result try self.copyToRegisterWithInstTracking( |
| 9483 | | inst, |
| 9484 | | Type.usize, |
| 9485 | | .{ .register = ro.reg }, |
| 9486 | | ), |
| 9437 | } else break :result try self.copyToRegisterWithInstTracking(inst, .usize, .{ .register = ro.reg }), |
| 9487 | 9438 | // Get overflow bit. |
| 9488 | 9439 | 1 => if (self.reuseOperandAdvanced(inst, extra.struct_operand, 0, src_mcv, null)) { |
| 9489 | 9440 | self.eflags_inst = inst; // actually keep tracking the overflow part |
| ... | ... | @@ -9541,9 +9492,9 @@ fn airStructFieldVal(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 9541 | 9492 | |
| 9542 | 9493 | const hi_mcv = |
| 9543 | 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 | 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 | 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 | 9635 | switch (tag) { |
| 9685 | 9636 | .not => { |
| 9686 | 9637 | const limb_abi_size: u16 = @min(abi_size, 8); |
| 9687 | | const int_info = if (src_ty.ip_index == .bool_type) |
| 9688 | | std.builtin.Type.Int{ .signedness = .unsigned, .bits = 1 } |
| 9638 | const int_info: InternPool.Key.IntType = if (src_ty.ip_index == .bool_type) |
| 9639 | .{ .signedness = .unsigned, .bits = 1 } |
| 9689 | 9640 | else |
| 9690 | 9641 | src_ty.intInfo(zcu); |
| 9691 | 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 | 9669 | defer self.register_manager.unlockReg(tmp_lock); |
| 9719 | 9670 | |
| 9720 | 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 | 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 | 9710 | const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 9760 | 9711 | defer self.register_manager.unlockReg(addr_reg_lock); |
| 9761 | 9712 | |
| 9762 | | try self.genSetReg(addr_reg, Type.usize, dst_mcv.address(), .{}); |
| 9713 | try self.genSetReg(addr_reg, .usize, dst_mcv.address(), .{}); |
| 9763 | 9714 | try self.asmMemory(mir_tag, .{ .base = .{ .reg = addr_reg }, .mod = .{ .rm = .{ |
| 9764 | 9715 | .size = .fromSize(abi_size), |
| 9765 | 9716 | } } }); |
| ... | ... | @@ -10495,7 +10446,7 @@ fn genMulDivBinOp( |
| 10495 | 10446 | const mat_lhs_mcv = switch (lhs_mcv) { |
| 10496 | 10447 | .load_symbol => mat_lhs_mcv: { |
| 10497 | 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 | 10450 | break :mat_lhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } }; |
| 10500 | 10451 | }, |
| 10501 | 10452 | else => lhs_mcv, |
| ... | ... | @@ -10508,7 +10459,7 @@ fn genMulDivBinOp( |
| 10508 | 10459 | const mat_rhs_mcv = switch (rhs_mcv) { |
| 10509 | 10460 | .load_symbol => mat_rhs_mcv: { |
| 10510 | 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 | 10463 | break :mat_rhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } }; |
| 10513 | 10464 | }, |
| 10514 | 10465 | else => rhs_mcv, |
| ... | ... | @@ -10696,7 +10647,7 @@ fn genMulDivBinOp( |
| 10696 | 10647 | manyptr_u32_ty, |
| 10697 | 10648 | manyptr_const_u32_ty, |
| 10698 | 10649 | manyptr_const_u32_ty, |
| 10699 | | Type.usize, |
| 10650 | .usize, |
| 10700 | 10651 | }, &.{ |
| 10701 | 10652 | dst_mcv.address(), |
| 10702 | 10653 | lhs_mcv.address(), |
| ... | ... | @@ -12493,7 +12444,7 @@ fn genBinOp( |
| 12493 | 12444 | try not_mcv.mem(self, .{ .size = .fromSize(abi_size) }) |
| 12494 | 12445 | else |
| 12495 | 12446 | .{ .base = .{ |
| 12496 | | .reg = try self.copyToTmpRegister(Type.usize, not_mcv.address()), |
| 12447 | .reg = try self.copyToTmpRegister(.usize, not_mcv.address()), |
| 12497 | 12448 | }, .mod = .{ .rm = .{ .size = .fromSize(abi_size) } } }; |
| 12498 | 12449 | switch (mir_tag[0]) { |
| 12499 | 12450 | .vp_b, .vp_d, .vp_q, .vp_w => try self.asmRegisterRegisterMemory( |
| ... | ... | @@ -12757,7 +12708,7 @@ fn genBinOpMir( |
| 12757 | 12708 | const dst_addr_lock = self.register_manager.lockRegAssumeUnused(dst_addr_reg); |
| 12758 | 12709 | errdefer self.register_manager.unlockReg(dst_addr_lock); |
| 12759 | 12710 | |
| 12760 | | try self.genSetReg(dst_addr_reg, Type.usize, dst_mcv.address(), .{}); |
| 12711 | try self.genSetReg(dst_addr_reg, .usize, dst_mcv.address(), .{}); |
| 12761 | 12712 | break :dst .{ .addr_reg = dst_addr_reg, .addr_lock = dst_addr_lock }; |
| 12762 | 12713 | }, |
| 12763 | 12714 | .load_frame => null, |
| ... | ... | @@ -12808,7 +12759,7 @@ fn genBinOpMir( |
| 12808 | 12759 | const src_addr_lock = self.register_manager.lockRegAssumeUnused(src_addr_reg); |
| 12809 | 12760 | errdefer self.register_manager.unlockReg(src_addr_lock); |
| 12810 | 12761 | |
| 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 | 12763 | break :src .{ .addr_reg = src_addr_reg, .addr_lock = src_addr_lock }; |
| 12813 | 12764 | }, |
| 12814 | 12765 | }; |
| ... | ... | @@ -12816,9 +12767,9 @@ fn genBinOpMir( |
| 12816 | 12767 | |
| 12817 | 12768 | const ty_signedness = |
| 12818 | 12769 | if (ty.isAbiInt(zcu)) ty.intInfo(zcu).signedness else .unsigned; |
| 12819 | | const limb_ty = if (abi_size <= 8) ty else switch (ty_signedness) { |
| 12820 | | .signed => Type.usize, |
| 12821 | | .unsigned => Type.isize, |
| 12770 | const limb_ty: Type = if (abi_size <= 8) ty else switch (ty_signedness) { |
| 12771 | .signed => .usize, |
| 12772 | .unsigned => .isize, |
| 12822 | 12773 | }; |
| 12823 | 12774 | var limb_i: usize = 0; |
| 12824 | 12775 | var off: i32 = 0; |
| ... | ... | @@ -13310,13 +13261,13 @@ fn genLocalDebugInfo( |
| 13310 | 13261 | |
| 13311 | 13262 | fn airRetAddr(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 13312 | 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 | 13265 | return self.finishAir(inst, dst_mcv, .{ .none, .none, .none }); |
| 13315 | 13266 | } |
| 13316 | 13267 | |
| 13317 | 13268 | fn airFrameAddress(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 13318 | 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 | 13271 | return self.finishAir(inst, dst_mcv, .{ .none, .none, .none }); |
| 13321 | 13272 | } |
| 13322 | 13273 | |
| ... | ... | @@ -13461,13 +13412,10 @@ fn genCall(self: *CodeGen, info: union(enum) { |
| 13461 | 13412 | defer self.register_manager.unlockReg(index_lock); |
| 13462 | 13413 | |
| 13463 | 13414 | const src_mem: Memory = if (src_arg.isBase()) try src_arg.mem(self, .{ .size = .dword }) else .{ |
| 13464 | | .base = .{ .reg = try self.copyToTmpRegister( |
| 13465 | | Type.usize, |
| 13466 | | switch (src_arg) { |
| 13467 | | else => src_arg, |
| 13468 | | .air_ref => |src_ref| try self.resolveInst(src_ref), |
| 13469 | | }.address(), |
| 13470 | | ) }, |
| 13415 | .base = .{ .reg = try self.copyToTmpRegister(.usize, switch (src_arg) { |
| 13416 | else => src_arg, |
| 13417 | .air_ref => |src_ref| try self.resolveInst(src_ref), |
| 13418 | }.address()) }, |
| 13471 | 13419 | .mod = .{ .rm = .{ .size = .dword } }, |
| 13472 | 13420 | }; |
| 13473 | 13421 | const src_lock = switch (src_mem.base) { |
| ... | ... | @@ -13519,7 +13467,7 @@ fn genCall(self: *CodeGen, info: union(enum) { |
| 13519 | 13467 | .indirect => |reg_off| { |
| 13520 | 13468 | const ret_ty: Type = .fromInterned(fn_info.return_type); |
| 13521 | 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 | 13471 | .lea_frame = .{ .index = frame_index, .off = -reg_off.off }, |
| 13524 | 13472 | }, .{}); |
| 13525 | 13473 | call_info.return_value.short = .{ .load_frame = .{ .index = frame_index } }; |
| ... | ... | @@ -13548,13 +13496,13 @@ fn genCall(self: *CodeGen, info: union(enum) { |
| 13548 | 13496 | }, |
| 13549 | 13497 | }, |
| 13550 | 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 | 13500 | .lea_frame = .{ .index = frame_index, .off = -reg_off.off }, |
| 13553 | 13501 | }, .{}), |
| 13554 | 13502 | .elementwise_regs_then_frame => |regs_frame_addr| { |
| 13555 | 13503 | const src_mem: Memory = if (src_arg.isBase()) try src_arg.mem(self, .{ .size = .dword }) else .{ |
| 13556 | 13504 | .base = .{ .reg = try self.copyToTmpRegister( |
| 13557 | | Type.usize, |
| 13505 | .usize, |
| 13558 | 13506 | switch (src_arg) { |
| 13559 | 13507 | else => src_arg, |
| 13560 | 13508 | .air_ref => |src_ref| try self.resolveInst(src_ref), |
| ... | ... | @@ -13604,7 +13552,7 @@ fn genCall(self: *CodeGen, info: union(enum) { |
| 13604 | 13552 | } else if (self.bin_file.cast(.coff)) |coff_file| { |
| 13605 | 13553 | const atom = try coff_file.getOrCreateAtomForNav(func.owner_nav); |
| 13606 | 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 | 13556 | try self.asmRegister(.{ ._, .call }, .rax); |
| 13609 | 13557 | } else if (self.bin_file.cast(.macho)) |macho_file| { |
| 13610 | 13558 | const zo = macho_file.getZigObject().?; |
| ... | ... | @@ -13644,7 +13592,7 @@ fn genCall(self: *CodeGen, info: union(enum) { |
| 13644 | 13592 | } |
| 13645 | 13593 | } else { |
| 13646 | 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 | 13596 | try self.asmRegister(.{ ._, .call }, .rax); |
| 13649 | 13597 | }, |
| 13650 | 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 | 13624 | const lock = self.register_manager.lockRegAssumeUnused(reg_off.reg); |
| 13677 | 13625 | defer self.register_manager.unlockReg(lock); |
| 13678 | 13626 | |
| 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 | 13628 | try self.genSetMem( |
| 13681 | 13629 | .{ .reg = reg_off.reg }, |
| 13682 | 13630 | reg_off.off, |
| ... | ... | @@ -13775,7 +13723,7 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v |
| 13775 | 13723 | floatCompilerRtAbiName(float_bits), |
| 13776 | 13724 | }) catch unreachable, |
| 13777 | 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 | 13727 | break :result switch (op) { |
| 13780 | 13728 | .eq => .e, |
| 13781 | 13729 | .neq => .ne, |
| ... | ... | @@ -13938,12 +13886,7 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v |
| 13938 | 13886 | self.register_manager.lockRegAssumeUnused(dst_addr_reg); |
| 13939 | 13887 | errdefer self.register_manager.unlockReg(dst_addr_lock); |
| 13940 | 13888 | |
| 13941 | | try self.genSetReg( |
| 13942 | | dst_addr_reg, |
| 13943 | | Type.usize, |
| 13944 | | resolved_dst_mcv.address(), |
| 13945 | | .{}, |
| 13946 | | ); |
| 13889 | try self.genSetReg(dst_addr_reg, .usize, resolved_dst_mcv.address(), .{}); |
| 13947 | 13890 | break :dst .{ |
| 13948 | 13891 | .addr_reg = dst_addr_reg, |
| 13949 | 13892 | .addr_lock = dst_addr_lock, |
| ... | ... | @@ -14000,12 +13943,7 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v |
| 14000 | 13943 | self.register_manager.lockRegAssumeUnused(src_addr_reg); |
| 14001 | 13944 | errdefer self.register_manager.unlockReg(src_addr_lock); |
| 14002 | 13945 | |
| 14003 | | try self.genSetReg( |
| 14004 | | src_addr_reg, |
| 14005 | | Type.usize, |
| 14006 | | resolved_src_mcv.address(), |
| 14007 | | .{}, |
| 14008 | | ); |
| 13946 | try self.genSetReg(src_addr_reg, .usize, resolved_src_mcv.address(), .{}); |
| 14009 | 13947 | break :src .{ |
| 14010 | 13948 | .addr_reg = src_addr_reg, |
| 14011 | 13949 | .addr_lock = src_addr_lock, |
| ... | ... | @@ -14026,7 +13964,7 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v |
| 14026 | 13964 | const off = limb_i * 8; |
| 14027 | 13965 | const tmp_reg = regs[@min(limb_i, 1)].to64(); |
| 14028 | 13966 | |
| 14029 | | try self.genSetReg(tmp_reg, Type.usize, if (dst_info) |info| .{ |
| 13967 | try self.genSetReg(tmp_reg, .usize, if (dst_info) |info| .{ |
| 14030 | 13968 | .indirect = .{ .reg = info.addr_reg, .off = off }, |
| 14031 | 13969 | } else switch (resolved_dst_mcv) { |
| 14032 | 13970 | inline .register_pair, |
| ... | ... | @@ -14049,7 +13987,7 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v |
| 14049 | 13987 | |
| 14050 | 13988 | try self.genBinOpMir( |
| 14051 | 13989 | .{ ._, .xor }, |
| 14052 | | Type.usize, |
| 13990 | .usize, |
| 14053 | 13991 | .{ .register = tmp_reg }, |
| 14054 | 13992 | if (src_info) |info| .{ |
| 14055 | 13993 | .indirect = .{ .reg = info.addr_reg, .off = off }, |
| ... | ... | @@ -14244,7 +14182,7 @@ fn genTry( |
| 14244 | 14182 | else |
| 14245 | 14183 | try self.isErr(null, operand_ty, operand_mcv); |
| 14246 | 14184 | |
| 14247 | | const reloc = try self.genCondBrMir(Type.anyerror, is_err_mcv); |
| 14185 | const reloc = try self.genCondBrMir(.anyerror, is_err_mcv); |
| 14248 | 14186 | |
| 14249 | 14187 | if (self.liveness.operandDies(inst, 0)) { |
| 14250 | 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 | 14344 | const some_info: struct { off: u31, ty: Type } = if (opt_ty.optionalReprIsPayload(zcu)) |
| 14407 | 14345 | .{ .off = 0, .ty = if (pl_ty.isSlice(zcu)) pl_ty.slicePtrFieldType(zcu) else pl_ty } |
| 14408 | 14346 | else |
| 14409 | | .{ .off = @intCast(pl_ty.abiSize(zcu)), .ty = Type.bool }; |
| 14347 | .{ .off = @intCast(pl_ty.abiSize(zcu)), .ty = .bool }; |
| 14410 | 14348 | |
| 14411 | 14349 | self.eflags_inst = inst; |
| 14412 | 14350 | switch (opt_mcv) { |
| ... | ... | @@ -14481,7 +14419,7 @@ fn isNull(self: *CodeGen, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) |
| 14481 | 14419 | const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 14482 | 14420 | defer self.register_manager.unlockReg(addr_reg_lock); |
| 14483 | 14421 | |
| 14484 | | try self.genSetReg(addr_reg, Type.usize, opt_mcv.address(), .{}); |
| 14422 | try self.genSetReg(addr_reg, .usize, opt_mcv.address(), .{}); |
| 14485 | 14423 | const some_abi_size: u32 = @intCast(some_info.ty.abiSize(zcu)); |
| 14486 | 14424 | try self.asmMemoryImmediate( |
| 14487 | 14425 | .{ ._, .cmp }, |
| ... | ... | @@ -14536,7 +14474,7 @@ fn isNullPtr(self: *CodeGen, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValu |
| 14536 | 14474 | const some_info: struct { off: i32, ty: Type } = if (opt_ty.optionalReprIsPayload(zcu)) |
| 14537 | 14475 | .{ .off = 0, .ty = if (pl_ty.isSlice(zcu)) pl_ty.slicePtrFieldType(zcu) else pl_ty } |
| 14538 | 14476 | else |
| 14539 | | .{ .off = @intCast(pl_ty.abiSize(zcu)), .ty = Type.bool }; |
| 14477 | .{ .off = @intCast(pl_ty.abiSize(zcu)), .ty = .bool }; |
| 14540 | 14478 | |
| 14541 | 14479 | const ptr_reg = switch (ptr_mcv) { |
| 14542 | 14480 | .register => |reg| reg, |
| ... | ... | @@ -14582,22 +14520,17 @@ fn isErr(self: *CodeGen, maybe_inst: ?Air.Inst.Index, eu_ty: Type, eu_mcv: MCVal |
| 14582 | 14520 | .{ ._r, .sh }, |
| 14583 | 14521 | eu_ty, |
| 14584 | 14522 | .{ .register = tmp_reg }, |
| 14585 | | Type.u8, |
| 14523 | .u8, |
| 14586 | 14524 | .{ .immediate = @as(u6, @intCast(err_off * 8)) }, |
| 14587 | 14525 | ); |
| 14588 | 14526 | } else { |
| 14589 | | try self.truncateRegister(Type.anyerror, tmp_reg); |
| 14527 | try self.truncateRegister(.anyerror, tmp_reg); |
| 14590 | 14528 | } |
| 14591 | | try self.genBinOpMir( |
| 14592 | | .{ ._, .cmp }, |
| 14593 | | Type.anyerror, |
| 14594 | | .{ .register = tmp_reg }, |
| 14595 | | .{ .immediate = 0 }, |
| 14596 | | ); |
| 14529 | try self.genBinOpMir(.{ ._, .cmp }, .anyerror, .{ .register = tmp_reg }, .{ .immediate = 0 }); |
| 14597 | 14530 | }, |
| 14598 | 14531 | .load_frame => |frame_addr| try self.genBinOpMir( |
| 14599 | 14532 | .{ ._, .cmp }, |
| 14600 | | Type.anyerror, |
| 14533 | .anyerror, |
| 14601 | 14534 | .{ .load_frame = .{ |
| 14602 | 14535 | .index = frame_addr.index, |
| 14603 | 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 | 14566 | .{ |
| 14634 | 14567 | .base = .{ .reg = ptr_reg }, |
| 14635 | 14568 | .mod = .{ .rm = .{ |
| 14636 | | .size = self.memSize(Type.anyerror), |
| 14569 | .size = self.memSize(.anyerror), |
| 14637 | 14570 | .disp = err_off, |
| 14638 | 14571 | } }, |
| 14639 | 14572 | }, |
| ... | ... | @@ -15200,7 +15133,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 15200 | 15133 | .register, .register_offset, .lea_frame => break :arg ptr_mcv.deref(), |
| 15201 | 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 | 15139 | if (arg_mcv.getReg()) |reg| if (RegisterManager.indexOfRegIntoTracked(reg)) |_| { |
| ... | ... | @@ -15262,7 +15195,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 15262 | 15195 | try self.genCopy(ty, temp_mcv, input_mcv, .{}); |
| 15263 | 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 | 15199 | break :arg .{ .indirect = .{ .reg = addr_reg } }; |
| 15267 | 15200 | } else if (std.mem.eql(u8, constraint, "g") or |
| 15268 | 15201 | 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 | 15472 | else |
| 15540 | 15473 | return self.fail("invalid modifier: '{s}'", .{modifier}), |
| 15541 | 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 | 15476 | else |
| 15544 | 15477 | return self.fail("invalid modifier: '{s}'", .{modifier}), |
| 15545 | 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 | 15480 | else |
| 15548 | 15481 | return self.fail("invalid modifier: '{s}'", .{modifier}), |
| 15549 | 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 | 16032 | const src_addr_lock = self.register_manager.lockRegAssumeUnused(src_addr_reg); |
| 16100 | 16033 | errdefer self.register_manager.unlockReg(src_addr_lock); |
| 16101 | 16034 | |
| 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 | 16036 | break :src .{ .addr_reg = src_addr_reg, .addr_lock = src_addr_lock }; |
| 16104 | 16037 | }, |
| 16105 | 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 | 16079 | else => unreachable, |
| 16147 | 16080 | } |
| 16148 | 16081 | |
| 16149 | | const addr_reg = try self.copyToTmpRegister(Type.usize, dst_mcv.address()); |
| 16082 | const addr_reg = try self.copyToTmpRegister(.usize, dst_mcv.address()); |
| 16150 | 16083 | const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 16151 | 16084 | defer self.register_manager.unlockReg(addr_lock); |
| 16152 | 16085 | |
| ... | ... | @@ -16445,7 +16378,7 @@ fn genSetReg( |
| 16445 | 16378 | else => unreachable, |
| 16446 | 16379 | } |
| 16447 | 16380 | |
| 16448 | | const addr_reg = try self.copyToTmpRegister(Type.usize, src_mcv.address()); |
| 16381 | const addr_reg = try self.copyToTmpRegister(.usize, src_mcv.address()); |
| 16449 | 16382 | const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 16450 | 16383 | defer self.register_manager.unlockReg(addr_lock); |
| 16451 | 16384 | |
| ... | ... | @@ -16656,7 +16589,7 @@ fn genSetMem( |
| 16656 | 16589 | try self.genSetMem( |
| 16657 | 16590 | base, |
| 16658 | 16591 | disp + @as(i32, @intCast(child_ty.abiSize(zcu))), |
| 16659 | | Type.bool, |
| 16592 | .bool, |
| 16660 | 16593 | .{ .eflags = ro.eflags }, |
| 16661 | 16594 | opts, |
| 16662 | 16595 | ); |
| ... | ... | @@ -16732,9 +16665,9 @@ fn genSetMem( |
| 16732 | 16665 | |
| 16733 | 16666 | fn genInlineMemcpy(self: *CodeGen, dst_ptr: MCValue, src_ptr: MCValue, len: MCValue) InnerError!void { |
| 16734 | 16667 | try self.spillRegisters(&.{ .rsi, .rdi, .rcx }); |
| 16735 | | try self.genSetReg(.rsi, Type.usize, src_ptr, .{}); |
| 16736 | | try self.genSetReg(.rdi, Type.usize, dst_ptr, .{}); |
| 16737 | | try self.genSetReg(.rcx, Type.usize, len, .{}); |
| 16668 | try self.genSetReg(.rsi, .usize, src_ptr, .{}); |
| 16669 | try self.genSetReg(.rdi, .usize, dst_ptr, .{}); |
| 16670 | try self.genSetReg(.rcx, .usize, len, .{}); |
| 16738 | 16671 | try self.asmOpOnly(.{ .@"rep _sb", .mov }); |
| 16739 | 16672 | } |
| 16740 | 16673 | |
| ... | ... | @@ -16746,9 +16679,9 @@ fn genInlineMemset( |
| 16746 | 16679 | opts: CopyOptions, |
| 16747 | 16680 | ) InnerError!void { |
| 16748 | 16681 | try self.spillRegisters(&.{ .rdi, .al, .rcx }); |
| 16749 | | try self.genSetReg(.rdi, Type.usize, dst_ptr, .{}); |
| 16750 | | try self.genSetReg(.al, Type.u8, value, opts); |
| 16751 | | try self.genSetReg(.rcx, Type.usize, len, .{}); |
| 16682 | try self.genSetReg(.rdi, .usize, dst_ptr, .{}); |
| 16683 | try self.genSetReg(.al, .u8, value, opts); |
| 16684 | try self.genSetReg(.rcx, .usize, len, .{}); |
| 16752 | 16685 | try self.asmOpOnly(.{ .@"rep _sb", .sto }); |
| 16753 | 16686 | } |
| 16754 | 16687 | |
| ... | ... | @@ -16791,10 +16724,10 @@ fn genLazySymbolRef( |
| 16791 | 16724 | return self.fail("{s} creating lazy symbol", .{@errorName(err)}); |
| 16792 | 16725 | if (self.mod.pic) { |
| 16793 | 16726 | switch (tag) { |
| 16794 | | .lea, .call => try self.genSetReg(reg, Type.usize, .{ |
| 16727 | .lea, .call => try self.genSetReg(reg, .usize, .{ |
| 16795 | 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 | 16731 | .load_symbol = .{ .sym_index = sym_index }, |
| 16799 | 16732 | }, .{}), |
| 16800 | 16733 | else => unreachable, |
| ... | ... | @@ -16844,8 +16777,8 @@ fn genLazySymbolRef( |
| 16844 | 16777 | return self.fail("{s} creating lazy symbol", .{@errorName(err)}); |
| 16845 | 16778 | const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?; |
| 16846 | 16779 | switch (tag) { |
| 16847 | | .lea, .call => try self.genSetReg(reg, Type.usize, .{ .lea_got = sym_index }, .{}), |
| 16848 | | .mov => try self.genSetReg(reg, Type.usize, .{ .load_got = sym_index }, .{}), |
| 16780 | .lea, .call => try self.genSetReg(reg, .usize, .{ .lea_got = sym_index }, .{}), |
| 16781 | .mov => try self.genSetReg(reg, .usize, .{ .load_got = sym_index }, .{}), |
| 16849 | 16782 | else => unreachable, |
| 16850 | 16783 | } |
| 16851 | 16784 | switch (tag) { |
| ... | ... | @@ -16859,10 +16792,10 @@ fn genLazySymbolRef( |
| 16859 | 16792 | return self.fail("{s} creating lazy symbol", .{@errorName(err)}); |
| 16860 | 16793 | const sym = zo.symbols.items[sym_index]; |
| 16861 | 16794 | switch (tag) { |
| 16862 | | .lea, .call => try self.genSetReg(reg, Type.usize, .{ |
| 16795 | .lea, .call => try self.genSetReg(reg, .usize, .{ |
| 16863 | 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 | 16799 | .load_symbol = .{ .sym_index = sym.nlist_idx }, |
| 16867 | 16800 | }, .{}), |
| 16868 | 16801 | else => unreachable, |
| ... | ... | @@ -16932,7 +16865,7 @@ fn airBitCast(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 16932 | 16865 | const bit_size = dst_ty.bitSize(zcu); |
| 16933 | 16866 | if (abi_size * 8 <= bit_size or dst_ty.isVector(zcu)) break :result dst_mcv; |
| 16934 | 16867 | |
| 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 | 16869 | const high_mcv: MCValue = switch (dst_mcv) { |
| 16937 | 16870 | .register => |dst_reg| .{ .register = dst_reg }, |
| 16938 | 16871 | .register_pair => |dst_regs| .{ .register = dst_regs[1] }, |
| ... | ... | @@ -16941,17 +16874,43 @@ fn airBitCast(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 16941 | 16874 | const high_reg = if (high_mcv.isRegister()) |
| 16942 | 16875 | high_mcv.getReg().? |
| 16943 | 16876 | else |
| 16944 | | try self.copyToTmpRegister(Type.usize, high_mcv); |
| 16877 | try self.copyToTmpRegister(.usize, high_mcv); |
| 16945 | 16878 | const high_lock = self.register_manager.lockReg(high_reg); |
| 16946 | 16879 | defer if (high_lock) |lock| self.register_manager.unlockReg(lock); |
| 16947 | | |
| 16948 | 16880 | try self.truncateRegister(dst_ty, high_reg); |
| 16949 | 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 | 16883 | high_mcv, |
| 16952 | 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 | 16914 | break :result dst_mcv; |
| 16956 | 16915 | }; |
| 16957 | 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 | 16932 | try self.genSetMem( |
| 16974 | 16933 | .{ .frame = frame_index }, |
| 16975 | 16934 | @intCast(ptr_ty.abiSize(zcu)), |
| 16976 | | Type.usize, |
| 16935 | .usize, |
| 16977 | 16936 | .{ .immediate = array_len }, |
| 16978 | 16937 | .{}, |
| 16979 | 16938 | ); |
| ... | ... | @@ -17151,28 +17110,28 @@ fn airCmpxchg(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 17151 | 17110 | if (val_abi_size > 8) { |
| 17152 | 17111 | const exp_addr_mcv: MCValue = switch (exp_mcv) { |
| 17153 | 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 | 17115 | const exp_addr_lock = |
| 17157 | 17116 | if (exp_addr_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null; |
| 17158 | 17117 | defer if (exp_addr_lock) |lock| self.register_manager.unlockReg(lock); |
| 17159 | 17118 | |
| 17160 | | try self.genSetReg(.rax, Type.usize, exp_addr_mcv.deref(), .{}); |
| 17161 | | try self.genSetReg(.rdx, Type.usize, exp_addr_mcv.offset(8).deref(), .{}); |
| 17119 | try self.genSetReg(.rax, .usize, exp_addr_mcv.deref(), .{}); |
| 17120 | try self.genSetReg(.rdx, .usize, exp_addr_mcv.offset(8).deref(), .{}); |
| 17162 | 17121 | } else try self.genSetReg(.rax, val_ty, exp_mcv, .{}); |
| 17163 | 17122 | |
| 17164 | 17123 | const new_mcv = try self.resolveInst(extra.new_value); |
| 17165 | 17124 | const new_reg = if (val_abi_size > 8) new: { |
| 17166 | 17125 | const new_addr_mcv: MCValue = switch (new_mcv) { |
| 17167 | 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 | 17129 | const new_addr_lock = |
| 17171 | 17130 | if (new_addr_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null; |
| 17172 | 17131 | defer if (new_addr_lock) |lock| self.register_manager.unlockReg(lock); |
| 17173 | 17132 | |
| 17174 | | try self.genSetReg(.rbx, Type.usize, new_addr_mcv.deref(), .{}); |
| 17175 | | try self.genSetReg(.rcx, Type.usize, new_addr_mcv.offset(8).deref(), .{}); |
| 17133 | try self.genSetReg(.rbx, .usize, new_addr_mcv.deref(), .{}); |
| 17134 | try self.genSetReg(.rcx, .usize, new_addr_mcv.offset(8).deref(), .{}); |
| 17176 | 17135 | break :new null; |
| 17177 | 17136 | } else try self.copyToTmpRegister(val_ty, new_mcv); |
| 17178 | 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 | 17172 | } |
| 17214 | 17173 | |
| 17215 | 17174 | const dst_mcv = try self.allocRegOrMem(inst, false); |
| 17216 | | try self.genCopy(Type.usize, dst_mcv, .{ .register = .rax }, .{}); |
| 17217 | | try self.genCopy(Type.usize, dst_mcv.address().offset(8).deref(), .{ .register = .rdx }, .{}); |
| 17218 | | try self.genCopy(Type.bool, dst_mcv.address().offset(16).deref(), .{ .eflags = .ne }, .{}); |
| 17175 | try self.genCopy(.usize, dst_mcv, .{ .register = .rax }, .{}); |
| 17176 | try self.genCopy(.usize, dst_mcv.address().offset(8).deref(), .{ .register = .rdx }, .{}); |
| 17177 | try self.genCopy(.bool, dst_mcv.address().offset(16).deref(), .{ .eflags = .ne }, .{}); |
| 17219 | 17178 | break :result dst_mcv; |
| 17220 | 17179 | }; |
| 17221 | 17180 | return self.finishAir(inst, result, .{ extra.ptr, extra.expected_value, extra.new_value }); |
| ... | ... | @@ -17488,7 +17447,7 @@ fn atomicOp( |
| 17488 | 17447 | const val_mem_mcv: MCValue = switch (val_mcv) { |
| 17489 | 17448 | .memory, .indirect, .load_frame => val_mcv, |
| 17490 | 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 | 17453 | const val_lo_mem = try val_mem_mcv.mem(self, .{ .size = .qword }); |
| ... | ... | @@ -17545,7 +17504,7 @@ fn atomicOp( |
| 17545 | 17504 | }, |
| 17546 | 17505 | }; |
| 17547 | 17506 | |
| 17548 | | const tmp_reg = try self.copyToTmpRegister(Type.usize, .{ .register = .rcx }); |
| 17507 | const tmp_reg = try self.copyToTmpRegister(.usize, .{ .register = .rcx }); |
| 17549 | 17508 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 17550 | 17509 | defer self.register_manager.unlockReg(tmp_lock); |
| 17551 | 17510 | |
| ... | ... | @@ -17719,7 +17678,7 @@ fn airMemset(self: *CodeGen, inst: Air.Inst.Index, safety: bool) !void { |
| 17719 | 17678 | const len_lock = self.register_manager.lockRegAssumeUnused(len_reg); |
| 17720 | 17679 | defer self.register_manager.unlockReg(len_lock); |
| 17721 | 17680 | |
| 17722 | | try self.genSetReg(len_reg, Type.usize, len, .{}); |
| 17681 | try self.genSetReg(len_reg, .usize, len, .{}); |
| 17723 | 17682 | try self.asmRegisterRegister(.{ ._, .@"test" }, len_reg, len_reg); |
| 17724 | 17683 | |
| 17725 | 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 | 17691 | self.register_manager.lockRegAssumeUnused(second_elem_ptr_reg); |
| 17733 | 17692 | defer self.register_manager.unlockReg(second_elem_ptr_lock); |
| 17734 | 17693 | |
| 17735 | | try self.genSetReg(second_elem_ptr_reg, Type.usize, .{ .register_offset = .{ |
| 17736 | | .reg = try self.copyToTmpRegister(Type.usize, dst_ptr), |
| 17694 | try self.genSetReg(second_elem_ptr_reg, .usize, .{ .register_offset = .{ |
| 17695 | .reg = try self.copyToTmpRegister(.usize, dst_ptr), |
| 17737 | 17696 | .off = elem_abi_size, |
| 17738 | 17697 | } }, .{}); |
| 17739 | 17698 | |
| 17740 | | try self.genBinOpMir(.{ ._, .sub }, Type.usize, len_mcv, .{ .immediate = 1 }); |
| 17699 | try self.genBinOpMir(.{ ._, .sub }, .usize, len_mcv, .{ .immediate = 1 }); |
| 17741 | 17700 | try self.asmRegisterRegisterImmediate( |
| 17742 | 17701 | .{ .i_, .mul }, |
| 17743 | 17702 | len_reg, |
| ... | ... | @@ -17763,8 +17722,8 @@ fn airMemset(self: *CodeGen, inst: Air.Inst.Index, safety: bool) !void { |
| 17763 | 17722 | self.register_manager.lockRegAssumeUnused(second_elem_ptr_reg); |
| 17764 | 17723 | defer self.register_manager.unlockReg(second_elem_ptr_lock); |
| 17765 | 17724 | |
| 17766 | | try self.genSetReg(second_elem_ptr_reg, Type.usize, .{ .register_offset = .{ |
| 17767 | | .reg = try self.copyToTmpRegister(Type.usize, dst), |
| 17725 | try self.genSetReg(second_elem_ptr_reg, .usize, .{ .register_offset = .{ |
| 17726 | .reg = try self.copyToTmpRegister(.usize, dst), |
| 17768 | 17727 | .off = elem_abi_size, |
| 17769 | 17728 | } }, .{}); |
| 17770 | 17729 | |
| ... | ... | @@ -17886,7 +17845,7 @@ fn airTagName(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 17886 | 17845 | const param_regs = abi.getCAbiIntParamRegs(resolved_cc); |
| 17887 | 17846 | |
| 17888 | 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(), .{}); |
| 17890 | 17849 | |
| 17891 | 17850 | const operand = try self.resolveInst(un_op); |
| 17892 | 17851 | try self.genSetReg(param_regs[1], enum_ty, operand, .{}); |
| ... | ... | @@ -18415,7 +18374,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 18415 | 18374 | mask_alias, |
| 18416 | 18375 | if (pred_mcv.isBase()) try pred_mcv.mem(self, .{ .size = .byte }) else .{ |
| 18417 | 18376 | .base = .{ .reg = (try self.copyToTmpRegister( |
| 18418 | | Type.usize, |
| 18377 | .usize, |
| 18419 | 18378 | pred_mcv.address(), |
| 18420 | 18379 | )).to64() }, |
| 18421 | 18380 | .mod = .{ .rm = .{ .size = .byte } }, |
| ... | ... | @@ -18478,7 +18437,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 18478 | 18437 | .storage = .{ .elems = mask_elems[0..vec_len] }, |
| 18479 | 18438 | } }))); |
| 18480 | 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 | 18441 | .mod = .{ .rm = .{ .size = self.memSize(ty) } }, |
| 18483 | 18442 | }; |
| 18484 | 18443 | if (has_avx) try self.asmRegisterRegisterMemory( |
| ... | ... | @@ -18503,7 +18462,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 18503 | 18462 | .storage = .{ .elems = mask_elems[0..vec_len] }, |
| 18504 | 18463 | } }))); |
| 18505 | 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 | 18466 | .mod = .{ .rm = .{ .size = self.memSize(ty) } }, |
| 18508 | 18467 | }; |
| 18509 | 18468 | if (has_avx) { |
| ... | ... | @@ -19380,7 +19339,7 @@ fn airShuffle(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 19380 | 19339 | .storage = .{ .elems = lhs_mask_elems[0..max_abi_size] }, |
| 19381 | 19340 | } }))); |
| 19382 | 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 | 19343 | .mod = .{ .rm = .{ .size = .fromSize(@max(max_abi_size, 16)) } }, |
| 19385 | 19344 | }; |
| 19386 | 19345 | if (has_avx) try self.asmRegisterRegisterMemory( |
| ... | ... | @@ -19414,7 +19373,7 @@ fn airShuffle(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 19414 | 19373 | .storage = .{ .elems = rhs_mask_elems[0..max_abi_size] }, |
| 19415 | 19374 | } }))); |
| 19416 | 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 | 19377 | .mod = .{ .rm = .{ .size = .fromSize(@max(max_abi_size, 16)) } }, |
| 19419 | 19378 | }; |
| 19420 | 19379 | if (has_avx) try self.asmRegisterRegisterMemory( |
| ... | ... | @@ -19634,7 +19593,7 @@ fn airAggregateInit(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 19634 | 19593 | .{ ._l, .sh }, |
| 19635 | 19594 | elem_ty, |
| 19636 | 19595 | .{ .register = temp_alias }, |
| 19637 | | Type.u8, |
| 19596 | .u8, |
| 19638 | 19597 | .{ .immediate = elem_bit_off }, |
| 19639 | 19598 | ); |
| 19640 | 19599 | try self.genBinOpMir( |
| ... | ... | @@ -19657,7 +19616,7 @@ fn airAggregateInit(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 19657 | 19616 | .{ ._r, .sh }, |
| 19658 | 19617 | elem_ty, |
| 19659 | 19618 | .{ .register = temp_reg }, |
| 19660 | | Type.u8, |
| 19619 | .u8, |
| 19661 | 19620 | .{ .immediate = elem_abi_bits - elem_bit_off }, |
| 19662 | 19621 | ); |
| 19663 | 19622 | try self.genBinOpMir( |
| ... | ... | @@ -19984,7 +19943,7 @@ fn airVaStart(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 19984 | 19943 | const pt = self.pt; |
| 19985 | 19944 | const zcu = pt.zcu; |
| 19986 | 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); |
| 19988 | 19947 | |
| 19989 | 19948 | const result: MCValue = switch (abi.resolveCallingConvention( |
| 19990 | 19949 | self.fn_type.fnCallingConvention(zcu), |
| ... | ... | @@ -19998,7 +19957,7 @@ fn airVaStart(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 19998 | 19957 | try self.genSetMem( |
| 19999 | 19958 | .{ .frame = dst_fi }, |
| 20000 | 19959 | field_off, |
| 20001 | | Type.c_uint, |
| 19960 | .c_uint, |
| 20002 | 19961 | .{ .immediate = info.gp_count * 8 }, |
| 20003 | 19962 | .{}, |
| 20004 | 19963 | ); |
| ... | ... | @@ -20007,7 +19966,7 @@ fn airVaStart(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 20007 | 19966 | try self.genSetMem( |
| 20008 | 19967 | .{ .frame = dst_fi }, |
| 20009 | 19968 | field_off, |
| 20010 | | Type.c_uint, |
| 19969 | .c_uint, |
| 20011 | 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 | 20003 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 20045 | 20004 | const ty = self.typeOfIndex(inst); |
| 20046 | 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 | 20007 | const unused = self.liveness.isUnused(inst); |
| 20049 | 20008 | |
| 20050 | 20009 | const result: MCValue = switch (abi.resolveCallingConvention( |
| ... | ... | @@ -20083,7 +20042,7 @@ fn airVaArg(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 20083 | 20042 | .integer => { |
| 20084 | 20043 | assert(classes.len == 1); |
| 20085 | 20044 | |
| 20086 | | try self.genSetReg(offset_reg, Type.c_uint, gp_offset, .{}); |
| 20045 | try self.genSetReg(offset_reg, .c_uint, gp_offset, .{}); |
| 20087 | 20046 | try self.asmRegisterImmediate(.{ ._, .cmp }, offset_reg, .u( |
| 20088 | 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 | 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 | 20067 | const done_reloc = try self.asmJmpReloc(undefined); |
| 20109 | 20068 | |
| 20110 | 20069 | self.performReloc(mem_reloc); |
| ... | ... | @@ -20131,7 +20090,7 @@ fn airVaArg(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 20131 | 20090 | .sse => { |
| 20132 | 20091 | assert(classes.len == 1); |
| 20133 | 20092 | |
| 20134 | | try self.genSetReg(offset_reg, Type.c_uint, fp_offset, .{}); |
| 20093 | try self.genSetReg(offset_reg, .c_uint, fp_offset, .{}); |
| 20135 | 20094 | try self.asmRegisterImmediate(.{ ._, .cmp }, offset_reg, .u( |
| 20136 | 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 | 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 | 20115 | const done_reloc = try self.asmJmpReloc(undefined); |
| 20157 | 20116 | |
| 20158 | 20117 | self.performReloc(mem_reloc); |
| ... | ... | @@ -20277,7 +20236,7 @@ fn resolveInst(self: *CodeGen, ref: Air.Inst.Ref) InnerError!MCValue { |
| 20277 | 20236 | try self.genSetMem( |
| 20278 | 20237 | .{ .frame = frame_index }, |
| 20279 | 20238 | 0, |
| 20280 | | Type.usize, |
| 20239 | .usize, |
| 20281 | 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 | 20277 | // This immediate is unsigned. |
| 20319 | 20278 | const U = std.meta.Int(.unsigned, ti.bits - @intFromBool(ti.signedness == .signed)); |
| 20320 | 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 | 20283 | else => {}, |
| ... | ... | @@ -20764,7 +20723,7 @@ fn splitType(self: *CodeGen, comptime parts_len: usize, ty: Type) ![parts_len]Ty |
| 20764 | 20723 | if (classes.len == parts_len) for (&parts, classes, 0..) |*part, class, part_i| { |
| 20765 | 20724 | part.* = switch (class) { |
| 20766 | 20725 | .integer => if (part_i < parts_len - 1) |
| 20767 | | Type.u64 |
| 20726 | .u64 |
| 20768 | 20727 | else part: { |
| 20769 | 20728 | const elem_size = ty.abiAlignment(zcu).minStrict(.@"8").toByteUnits().?; |
| 20770 | 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 | 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 | 20736 | .float_combine => try pt.arrayType(.{ .len = 2, .child = .f32_type }), |
| 20778 | | .sse => Type.f64, |
| 20737 | .sse => .f64, |
| 20779 | 20738 | else => break, |
| 20780 | 20739 | }; |
| 20781 | 20740 | } else { |
| ... | ... | @@ -20791,7 +20750,7 @@ fn splitType(self: *CodeGen, comptime parts_len: usize, ty: Type) ![parts_len]Ty |
| 20791 | 20750 | fn truncateRegister(self: *CodeGen, ty: Type, reg: Register) !void { |
| 20792 | 20751 | const pt = self.pt; |
| 20793 | 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 | 20754 | .signedness = .unsigned, |
| 20796 | 20755 | .bits = @intCast(ty.bitSize(zcu)), |
| 20797 | 20756 | }; |
| ... | ... | @@ -20799,38 +20758,16 @@ fn truncateRegister(self: *CodeGen, ty: Type, reg: Register) !void { |
| 20799 | 20758 | try self.spillEflagsIfOccupied(); |
| 20800 | 20759 | switch (int_info.signedness) { |
| 20801 | 20760 | .signed => { |
| 20802 | | try self.genShiftBinOpMir( |
| 20803 | | .{ ._l, .sa }, |
| 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 | | ); |
| 20761 | try self.genShiftBinOpMir(.{ ._l, .sa }, .isize, .{ .register = reg }, .u8, .{ .immediate = shift }); |
| 20762 | try self.genShiftBinOpMir(.{ ._r, .sa }, .isize, .{ .register = reg }, .u8, .{ .immediate = shift }); |
| 20816 | 20763 | }, |
| 20817 | 20764 | .unsigned => { |
| 20818 | 20765 | const mask = ~@as(u64, 0) >> shift; |
| 20819 | 20766 | if (int_info.bits <= 32) { |
| 20820 | | try self.genBinOpMir( |
| 20821 | | .{ ._, .@"and" }, |
| 20822 | | Type.u32, |
| 20823 | | .{ .register = reg }, |
| 20824 | | .{ .immediate = mask }, |
| 20825 | | ); |
| 20767 | try self.genBinOpMir(.{ ._, .@"and" }, .u32, .{ .register = reg }, .{ .immediate = mask }); |
| 20826 | 20768 | } else { |
| 20827 | | const tmp_reg = try self.copyToTmpRegister(Type.usize, .{ .immediate = mask }); |
| 20828 | | try self.genBinOpMir( |
| 20829 | | .{ ._, .@"and" }, |
| 20830 | | Type.usize, |
| 20831 | | .{ .register = reg }, |
| 20832 | | .{ .register = tmp_reg }, |
| 20833 | | ); |
| 20769 | const tmp_reg = try self.copyToTmpRegister(.usize, .{ .immediate = mask }); |
| 20770 | try self.genBinOpMir(.{ ._, .@"and" }, .usize, .{ .register = reg }, .{ .register = tmp_reg }); |
| 20834 | 20771 | } |
| 20835 | 20772 | }, |
| 20836 | 20773 | } |
| ... | ... | @@ -20911,7 +20848,7 @@ fn floatCompilerRtAbiName(float_bits: u32) u8 { |
| 20911 | 20848 | fn floatCompilerRtAbiType(self: *CodeGen, ty: Type, other_ty: Type) Type { |
| 20912 | 20849 | if (ty.toIntern() == .f16_type and |
| 20913 | 20850 | (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 | 20852 | return ty; |
| 20916 | 20853 | } |
| 20917 | 20854 | |
| ... | ... | @@ -20943,9 +20880,9 @@ fn promoteInt(self: *CodeGen, ty: Type) Type { |
| 20943 | 20880 | else => if (ty.isAbiInt(zcu)) ty.intInfo(zcu) else return ty, |
| 20944 | 20881 | }; |
| 20945 | 20882 | for ([_]Type{ |
| 20946 | | Type.c_int, Type.c_uint, |
| 20947 | | Type.c_long, Type.c_ulong, |
| 20948 | | Type.c_longlong, Type.c_ulonglong, |
| 20883 | .c_int, .c_uint, |
| 20884 | .c_long, .c_ulong, |
| 20885 | .c_longlong, .c_ulonglong, |
| 20949 | 20886 | }) |promote_ty| { |
| 20950 | 20887 | const promote_info = promote_ty.intInfo(zcu); |
| 20951 | 20888 | if (int_info.signedness == .signed and promote_info.signedness == .unsigned) continue; |
| ... | ... | @@ -20958,10 +20895,10 @@ fn promoteInt(self: *CodeGen, ty: Type) Type { |
| 20958 | 20895 | fn promoteVarArg(self: *CodeGen, ty: Type) Type { |
| 20959 | 20896 | if (!ty.isRuntimeFloat()) return self.promoteInt(ty); |
| 20960 | 20897 | switch (ty.floatBits(self.target.*)) { |
| 20961 | | 32, 64 => return Type.f64, |
| 20898 | 32, 64 => return .f64, |
| 20962 | 20899 | else => |float_bits| { |
| 20963 | 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 | 20973 | |
| 21037 | 20974 | fn getOffset(temp: Temp, off: i32, cg: *CodeGen) !Temp { |
| 21038 | 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 | 20977 | cg.next_temp_index = @enumFromInt(@intFromEnum(new_temp_index) + 1); |
| 21041 | 20978 | switch (temp.tracking(cg).short) { |
| 21042 | 20979 | else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }), |
| ... | ... | @@ -21141,7 +21078,7 @@ const Temp = struct { |
| 21141 | 21078 | |
| 21142 | 21079 | fn getLimb(temp: Temp, limb_index: u28, cg: *CodeGen) !Temp { |
| 21143 | 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 | 21082 | switch (temp.tracking(cg).short) { |
| 21146 | 21083 | else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }), |
| 21147 | 21084 | .immediate => |imm| { |
| ... | ... | @@ -21220,7 +21157,7 @@ const Temp = struct { |
| 21220 | 21157 | else => {}, |
| 21221 | 21158 | .register, .lea_symbol, .lea_frame => { |
| 21222 | 21159 | assert(limb_index == 0); |
| 21223 | | cg.temp_type[@intFromEnum(temp_index)] = Type.usize; |
| 21160 | cg.temp_type[@intFromEnum(temp_index)] = .usize; |
| 21224 | 21161 | return; |
| 21225 | 21162 | }, |
| 21226 | 21163 | .register_pair => |regs| { |
| ... | ... | @@ -21232,7 +21169,7 @@ const Temp = struct { |
| 21232 | 21169 | for (regs, 0..) |reg, reg_index| if (reg_index != limb_index) |
| 21233 | 21170 | cg.register_manager.freeReg(reg); |
| 21234 | 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 | 21173 | return; |
| 21237 | 21174 | }, |
| 21238 | 21175 | .load_symbol => |sym_off| { |
| ... | ... | @@ -21241,7 +21178,7 @@ const Temp = struct { |
| 21241 | 21178 | .sym_index = sym_off.sym_index, |
| 21242 | 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 | 21182 | return; |
| 21246 | 21183 | }, |
| 21247 | 21184 | .load_frame => |frame_addr| if (!frame_addr.index.isNamed()) { |
| ... | ... | @@ -21250,7 +21187,7 @@ const Temp = struct { |
| 21250 | 21187 | .index = frame_addr.index, |
| 21251 | 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 | 21191 | return; |
| 21255 | 21192 | }, |
| 21256 | 21193 | } |
| ... | ... | @@ -21339,7 +21276,7 @@ const Temp = struct { |
| 21339 | 21276 | const result_temp: Temp = .{ .index = result_temp_index.toIndex() }; |
| 21340 | 21277 | assert(cg.reuseTemp(result_temp.index, first_temp.index, first_temp_tracking)); |
| 21341 | 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 | 21280 | result_temp_index.tracking(cg).* = .init(result); |
| 21344 | 21281 | first_temp.* = result_temp; |
| 21345 | 21282 | } |
| ... | ... | @@ -21405,7 +21342,7 @@ const Temp = struct { |
| 21405 | 21342 | cg.temp_type[@intFromEnum(new_temp_index)] = temp.typeOf(cg); |
| 21406 | 21343 | const new_reg = |
| 21407 | 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 | 21346 | new_temp_index.tracking(cg).* = .init(.{ .indirect = .{ .reg = new_reg } }); |
| 21410 | 21347 | try temp.die(cg); |
| 21411 | 21348 | cg.next_temp_index = @enumFromInt(@intFromEnum(new_temp_index) + 1); |
| ... | ... | @@ -21430,8 +21367,8 @@ const Temp = struct { |
| 21430 | 21367 | } |
| 21431 | 21368 | }, |
| 21432 | 21369 | .load_frame => |val_frame_addr| { |
| 21433 | | var val_ptr = try cg.tempFromValue(Type.usize, .{ .lea_frame = val_frame_addr }); |
| 21434 | | var len = try cg.tempFromValue(Type.usize, .{ .immediate = val_abi_size }); |
| 21370 | var val_ptr = try cg.tempFromValue(.usize, .{ .lea_frame = val_frame_addr }); |
| 21371 | var len = try cg.tempFromValue(.usize, .{ .immediate = val_abi_size }); |
| 21435 | 21372 | try val_ptr.memcpy(ptr, &len, cg); |
| 21436 | 21373 | try val_ptr.die(cg); |
| 21437 | 21374 | try len.die(cg); |
| ... | ... | @@ -21668,11 +21605,12 @@ fn tempFromOperand( |
| 21668 | 21605 | inst: Air.Inst.Index, |
| 21669 | 21606 | op_index: Liveness.OperandInt, |
| 21670 | 21607 | op_ref: Air.Inst.Ref, |
| 21608 | ignore_death: bool, |
| 21671 | 21609 | ) !Temp { |
| 21672 | 21610 | const zcu = cg.pt.zcu; |
| 21673 | 21611 | const ip = &zcu.intern_pool; |
| 21674 | 21612 | |
| 21675 | | if (!cg.liveness.operandDies(inst, op_index)) { |
| 21613 | if (ignore_death or !cg.liveness.operandDies(inst, op_index)) { |
| 21676 | 21614 | if (op_ref.toIndex()) |op_inst| return .{ .index = op_inst }; |
| 21677 | 21615 | const val = op_ref.toInterned().?; |
| 21678 | 21616 | const gop = try cg.const_tracking.getOrPut(cg.gpa, val); |
| ... | ... | @@ -21693,7 +21631,7 @@ fn tempFromOperand( |
| 21693 | 21631 | try cg.genSetMem( |
| 21694 | 21632 | .{ .frame = frame_index }, |
| 21695 | 21633 | 0, |
| 21696 | | Type.usize, |
| 21634 | .usize, |
| 21697 | 21635 | .{ .lea_symbol = .{ .sym_index = tlv_sym } }, |
| 21698 | 21636 | .{}, |
| 21699 | 21637 | ); |
| ... | ... | @@ -21721,7 +21659,9 @@ fn tempFromOperand( |
| 21721 | 21659 | inline fn tempsFromOperands(cg: *CodeGen, inst: Air.Inst.Index, op_refs: anytype) ![op_refs.len]Temp { |
| 21722 | 21660 | var temps: [op_refs.len]Temp = undefined; |
| 21723 | 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 | 21666 | return temps; |
| 21727 | 21667 | } |
| ... | ... | @@ -21776,6 +21716,8 @@ const Pattern = struct { |
| 21776 | 21716 | implicit: u8, |
| 21777 | 21717 | /// repeat another operand |
| 21778 | 21718 | explicit: u8, |
| 21719 | /// a condition code |
| 21720 | cc, |
| 21779 | 21721 | /// any general purpose register |
| 21780 | 21722 | gpr, |
| 21781 | 21723 | /// any 64-bit mmx register |
| ... | ... | @@ -21808,6 +21750,8 @@ const Pattern = struct { |
| 21808 | 21750 | ymm_limb, |
| 21809 | 21751 | /// a limb stored in memory |
| 21810 | 21752 | mem_limb, |
| 21753 | /// a limb stored in a condition code |
| 21754 | cc_mask_limb, |
| 21811 | 21755 | /// a limb stored in a 64-bit mmx register mask |
| 21812 | 21756 | mm_mask_limb, |
| 21813 | 21757 | /// a limb stored in a 128-bit sse register masuk |
| ... | ... | @@ -21829,7 +21773,7 @@ const Pattern = struct { |
| 21829 | 21773 | |
| 21830 | 21774 | fn matches(op: Op, is_mut: bool, temp: Temp, cg: *CodeGen) bool { |
| 21831 | 21775 | switch (op) { |
| 21832 | | .implicit, .explicit => unreachable, |
| 21776 | .implicit, .explicit, .cc, .cc_mask_limb => unreachable, |
| 21833 | 21777 | else => {}, |
| 21834 | 21778 | // temp is undefined |
| 21835 | 21779 | .umax_gpr, .umax_mm, .umax_xmm, .umax_ymm => return true, |
| ... | ... | @@ -21837,7 +21781,7 @@ const Pattern = struct { |
| 21837 | 21781 | const temp_ty = temp.typeOf(cg); |
| 21838 | 21782 | const abi_size = temp_ty.abiSize(cg.pt.zcu); |
| 21839 | 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 | 21785 | .gpr => abi_size <= 8 and switch (temp.tracking(cg).short) { |
| 21842 | 21786 | .register => |reg| reg.class() == .general_purpose, |
| 21843 | 21787 | .register_offset => |reg_off| reg_off.reg.class() == .general_purpose and |
| ... | ... | @@ -21861,9 +21805,7 @@ const Pattern = struct { |
| 21861 | 21805 | }, |
| 21862 | 21806 | .mem, .mem_limb => (!is_mut or temp.isMut(cg)) and temp.tracking(cg).short.isMemory(), |
| 21863 | 21807 | .gpr_limb => abi_size > 8 and switch (temp.tracking(cg).short) { |
| 21864 | | inline .register_pair, .register_triple, .register_quadruple => |regs| for (regs) |reg| { |
| 21865 | | if (reg.class() != .general_purpose) break false; |
| 21866 | | } else true, |
| 21808 | .register, .register_pair, .register_triple, .register_quadruple => true, |
| 21867 | 21809 | else => |mcv| mcv.isMemory(), |
| 21868 | 21810 | }, |
| 21869 | 21811 | .mm_limb, .mm_mask_limb => abi_size > 8 and switch (temp.tracking(cg).short) { |
| ... | ... | @@ -21897,6 +21839,7 @@ const Pattern = struct { |
| 21897 | 21839 | }; |
| 21898 | 21840 | }; |
| 21899 | 21841 | const SelectOptions = struct { |
| 21842 | cc: ?Condition = null, |
| 21900 | 21843 | invert_result: bool = false, |
| 21901 | 21844 | }; |
| 21902 | 21845 | fn select( |
| ... | ... | @@ -21914,6 +21857,7 @@ fn select( |
| 21914 | 21857 | limb_reloc: Mir.Inst.Index, |
| 21915 | 21858 | limb_offset: Offset, |
| 21916 | 21859 | limb_size: ?u8, |
| 21860 | shuffle_temp: ?Temp, |
| 21917 | 21861 | mask_limb_temp: ?Temp, |
| 21918 | 21862 | mask_limb_offset: Offset, |
| 21919 | 21863 | mask_limb_offset_lock: ?RegisterLock, |
| ... | ... | @@ -21935,6 +21879,7 @@ fn select( |
| 21935 | 21879 | .limb_reloc = undefined, |
| 21936 | 21880 | .limb_offset = .unused, |
| 21937 | 21881 | .limb_size = null, |
| 21882 | .shuffle_temp = null, |
| 21938 | 21883 | .mask_limb_temp = null, |
| 21939 | 21884 | .mask_limb_offset = .unused, |
| 21940 | 21885 | .mask_limb_offset_lock = null, |
| ... | ... | @@ -21992,12 +21937,23 @@ fn select( |
| 21992 | 21937 | if (!ref_src_op.matches(is_mut, src_temp, cg)) continue :patterns; |
| 21993 | 21938 | } |
| 21994 | 21939 | |
| 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 | 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 | 21953 | .implicit, .explicit => |linked_index| pattern.ops[linked_index], |
| 21998 | 21954 | else => src_op, |
| 21999 | 21955 | }) { |
| 22000 | | .implicit, .explicit => unreachable, |
| 21956 | .implicit, .explicit, .cc, .cc_mask_limb => unreachable, |
| 22001 | 21957 | .gpr => try src_temp.toRegClass(.general_purpose, cg), |
| 22002 | 21958 | .mm, .mm_mask, .mm_sign_mask => try src_temp.toRegClass(.mmx, cg), |
| 22003 | 21959 | .xmm, |
| ... | ... | @@ -22015,23 +21971,22 @@ fn select( |
| 22015 | 21971 | .ymm_limb, |
| 22016 | 21972 | .mem_limb, |
| 22017 | 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 | 21975 | else => try src_temp.toBase(cg), |
| 22020 | 21976 | }, |
| 22021 | | .mm_mask_limb, |
| 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, |
| 21977 | .mm_mask_limb, .xmm_mask_limb, .ymm_mask_limb => false, |
| 22029 | 21978 | .umax_gpr, .umax_mm, .umax_xmm, .umax_ymm => false, |
| 22030 | 21979 | }) break; |
| 22031 | 21980 | } else break; |
| 22032 | 21981 | |
| 21982 | const invert_result = opts.invert_result != pattern_set.invert_result; |
| 22033 | 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 | 21990 | for (src_temps, pattern.ops[dst_temps.len..]) |src_temp, src_op| { |
| 22036 | 21991 | defer mir_ops_len += @intFromBool(src_op != .implicit); |
| 22037 | 21992 | const linked_src_op, const extra_temp = op: switch (src_op) { |
| ... | ... | @@ -22046,13 +22001,17 @@ fn select( |
| 22046 | 22001 | }; |
| 22047 | 22002 | const limb_size: u8, const rc = switch (linked_src_op) { |
| 22048 | 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 | 22009 | .mm_limb, .mm_mask_limb => .{ 8, @panic("TODO") }, |
| 22051 | 22010 | .xmm_limb, .xmm_mask_limb => .{ 16, abi.RegisterClass.sse }, |
| 22052 | 22011 | .ymm_limb, .ymm_mask_limb => .{ 32, abi.RegisterClass.sse }, |
| 22053 | 22012 | .umax_gpr, .umax_mm, .umax_xmm, .umax_ymm => { |
| 22054 | 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 | 22015 | else => unreachable, |
| 22057 | 22016 | .umax_gpr => abi.RegisterClass.gp, |
| 22058 | 22017 | .umax_mm => @panic("TODO"), |
| ... | ... | @@ -22064,10 +22023,18 @@ fn select( |
| 22064 | 22023 | assert(loop.limb_size == null or loop.limb_size == limb_size); |
| 22065 | 22024 | loop.limb_size = limb_size; |
| 22066 | 22025 | loop.remaining_size = loop.remaining_size orelse src_temp.typeOf(cg).abiSize(cg.pt.zcu); |
| 22067 | | switch (src_temp.tracking(cg).short) { |
| 22068 | | .register_pair, .register_triple, .register_quadruple => switch (loop.limb_offset) { |
| 22069 | | .unused, .temp => loop.limb_offset = .{ .known = 0 }, |
| 22070 | | .known => {}, |
| 22026 | const src_mcv = src_temp.tracking(cg).short; |
| 22027 | switch (src_mcv) { |
| 22028 | .register, .register_pair, .register_triple, .register_quadruple => { |
| 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 | 22039 | else => { |
| 22073 | 22040 | switch (loop.limb_offset) { |
| ... | ... | @@ -22075,7 +22042,7 @@ fn select( |
| 22075 | 22042 | .known, .temp => {}, |
| 22076 | 22043 | } |
| 22077 | 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 | 22057 | dst_temp.* = dst_temp: switch (dst_op) { |
| 22091 | 22058 | .implicit => unreachable, |
| 22092 | 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 | 22064 | .gpr => try cg.tempAllocReg(dst_ty, abi.RegisterClass.gp), |
| 22094 | 22065 | .mm, .mm_mask, .mm_sign_mask => @panic("TODO"), |
| 22095 | 22066 | .xmm, .xmm_mask, .xmm_sign_mask => try cg.tempAllocReg(dst_ty, abi.RegisterClass.sse), |
| 22096 | 22067 | .ymm, .ymm_mask, .ymm_sign_mask => try cg.tempAllocReg(dst_ty, abi.RegisterClass.sse), |
| 22097 | 22068 | .mem => @panic("TODO"), |
| 22098 | 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 | 22071 | else => unreachable, |
| 22101 | 22072 | .gpr_limb => abi.RegisterClass.gp, |
| 22102 | 22073 | .mm_limb => @panic("TODO"), |
| ... | ... | @@ -22105,11 +22076,11 @@ fn select( |
| 22105 | 22076 | break :dst_temp try cg.tempAlloc(dst_ty); |
| 22106 | 22077 | }, |
| 22107 | 22078 | .mem_limb => try cg.tempAlloc(dst_ty), |
| 22108 | | .mm_mask_limb, .xmm_mask_limb, .ymm_mask_limb => unreachable, // already checked |
| 22079 | .cc_mask_limb, .mm_mask_limb, .xmm_mask_limb, .ymm_mask_limb => unreachable, // already checked |
| 22109 | 22080 | .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 | 22084 | const scalar_size = @divExact(switch (pattern_set.scalar) { |
| 22114 | 22085 | .any, .bool => unreachable, |
| 22115 | 22086 | .float, .any_int, .signed_int, .unsigned_int, .any_float_or_int => |size| size, |
| ... | ... | @@ -22131,14 +22102,17 @@ fn select( |
| 22131 | 22102 | assert(loop.mask_store_bit_size == null or loop.mask_store_bit_size == mask_store_bit_size); |
| 22132 | 22103 | loop.mask_store_bit_size = mask_store_bit_size; |
| 22133 | 22104 | loop.mask_limb_offset = loop.limb_offset; |
| 22134 | | if (extra_temp.* == null) extra_temp.* = try cg.tempAllocReg(Type.usize, switch (dst_op) { |
| 22135 | | else => unreachable, |
| 22136 | | .mm_mask_limb => @panic("TODO"), |
| 22137 | | .xmm_mask_limb, .ymm_mask_limb => abi.RegisterClass.sse, |
| 22138 | | }); |
| 22139 | | if (loop.mask_limb_temp == null) loop.mask_limb_temp = try cg.tempAllocReg(Type.usize, abi.RegisterClass.gp); |
| 22105 | if (loop.mask_limb_temp == null) { |
| 22106 | loop.mask_limb_temp = try cg.tempAllocReg(.usize, abi.RegisterClass.gp); |
| 22107 | if (dst_op == .cc_mask_limb and mask_store_bit_size > 8) { |
| 22108 | // setcc only clears 8 bits |
| 22109 | const mask_limb_alias = loop.mask_limb_temp.?.tracking(cg).short.register.to32(); |
| 22110 | try cg.spillEflagsIfOccupied(); |
| 22111 | try cg.asmRegisterRegister(.{ ._, .xor }, mask_limb_alias, mask_limb_alias); |
| 22112 | } |
| 22113 | } |
| 22140 | 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 | 22116 | loop.mask_store_reg = loop.mask_store_temp.?.tracking(cg).short.register; |
| 22143 | 22117 | } |
| 22144 | 22118 | dst_temp.* = if (mask_store_bit_size < mask_bit_size) |
| ... | ... | @@ -22152,28 +22126,26 @@ fn select( |
| 22152 | 22126 | switch (loop.mask_limb_offset) { |
| 22153 | 22127 | .unused, .known => {}, |
| 22154 | 22128 | .temp => |*mask_limb_offset| { |
| 22155 | | if (cg.hasFeature(.bmi2)) { |
| 22156 | | assert(loop.mask_limb_offset_lock == null); |
| 22157 | | mask_limb_offset.* = try cg.tempAllocReg(Type.usize, abi.RegisterClass.gp); |
| 22158 | | } else { |
| 22159 | | if (loop.mask_limb_offset_lock) |lock| cg.register_manager.unlockReg(lock); |
| 22160 | | loop.mask_limb_offset_lock = null; |
| 22161 | | mask_limb_offset.* = try cg.tempFromValue(Type.usize, .{ .register = .rcx }); |
| 22162 | | } |
| 22129 | mask_limb_offset.* = if (cg.hasFeature(.bmi2)) |
| 22130 | try cg.tempAllocReg(.usize, abi.RegisterClass.gp) |
| 22131 | else if (loop.mask_limb_offset_lock != null) |
| 22132 | try cg.tempFromValue(.usize, .{ .register = .rcx }) |
| 22133 | else |
| 22134 | unreachable; |
| 22163 | 22135 | if (loop.mask_store_reg) |mask_store_reg| { |
| 22164 | | const mask_store_alias = registerAlias( |
| 22165 | | mask_store_reg, |
| 22166 | | @min(std.math.divCeil(u7, loop.mask_store_bit_size.?, 8) catch unreachable, 4), |
| 22167 | | ); |
| 22136 | const mask_store_alias = |
| 22137 | if (loop.mask_store_bit_size.? > 8) mask_store_reg.to32() else mask_store_reg.to8(); |
| 22168 | 22138 | try cg.spillEflagsIfOccupied(); |
| 22169 | 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 | 22145 | switch (loop.element_offset) { |
| 22174 | 22146 | .unused, .known => {}, |
| 22175 | 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 | 22149 | const element_offset_reg = element_offset.tracking(cg).short.register; |
| 22178 | 22150 | try cg.spillEflagsIfOccupied(); |
| 22179 | 22151 | try cg.asmRegisterRegister(.{ ._, .xor }, element_offset_reg.to32(), element_offset_reg.to32()); |
| ... | ... | @@ -22182,7 +22154,7 @@ fn select( |
| 22182 | 22154 | } |
| 22183 | 22155 | switch (loop.limb_offset) { |
| 22184 | 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 | 22159 | while (true) { |
| 22188 | 22160 | switch (loop.mask_limb_offset) { |
| ... | ... | @@ -22204,7 +22176,7 @@ fn select( |
| 22204 | 22176 | } |
| 22205 | 22177 | while (true) { |
| 22206 | 22178 | var mir_ops: [4]Operand = @splat(.none); |
| 22207 | | mir_ops_len = dst_temps.len; |
| 22179 | mir_ops_len = dst_mir_ops_len; |
| 22208 | 22180 | for (src_temps, pattern.ops[dst_temps.len..]) |src_temp, src_op| { |
| 22209 | 22181 | defer mir_ops_len += @intFromBool(src_op != .implicit); |
| 22210 | 22182 | const mir_op, const linked_src_op, const extra_temp = switch (src_op) { |
| ... | ... | @@ -22217,35 +22189,146 @@ fn select( |
| 22217 | 22189 | // src_temp is undefined |
| 22218 | 22190 | .umax_gpr, .umax_mm, .umax_xmm, .umax_ymm => extra_temp.?, |
| 22219 | 22191 | }.tracking(cg).short; |
| 22220 | | copy_limb: switch (src_mcv) { |
| 22221 | | .register_pair, .register_triple, .register_quadruple => {}, |
| 22222 | | else => try cg.asmRegisterMemory( |
| 22223 | | switch (linked_src_op) { |
| 22224 | | else => break :copy_limb, |
| 22225 | | .gpr_limb => .{ ._, .mov }, |
| 22226 | | .mm_limb, .mm_mask_limb => .{ ._q, .mov }, |
| 22227 | | .xmm_limb, |
| 22228 | | .ymm_limb, |
| 22229 | | .xmm_mask_limb, |
| 22230 | | .ymm_mask_limb, |
| 22231 | | => .{ if (cg.hasFeature(.avx)) .v_ else ._, .movdqu }, |
| 22192 | switch (linked_src_op) { |
| 22193 | else => {}, |
| 22194 | .gpr_limb, |
| 22195 | .mm_limb, |
| 22196 | .xmm_limb, |
| 22197 | .ymm_limb, |
| 22198 | .mm_mask_limb, |
| 22199 | .xmm_mask_limb, |
| 22200 | .ymm_mask_limb, |
| 22201 | => if (extra_temp) |limb_temp| switch (src_mcv) { |
| 22202 | .register, .register_pair, .register_triple, .register_quadruple => { |
| 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.?), |
| 22234 | | try src_mcv.mem(cg, switch (loop.limb_offset) { |
| 22235 | | .unused => unreachable, |
| 22236 | | .known => |limb_offset| .{ |
| 22237 | | .size = .fromSize(loop.limb_size.?), |
| 22238 | | .disp = limb_offset, |
| 22239 | | }, |
| 22240 | | .temp => |limb_offset| .{ |
| 22241 | | .size = .fromSize(loop.limb_size.?), |
| 22242 | | .index = limb_offset.tracking(cg).short.register.to64(), |
| 22304 | else => try cg.asmRegisterMemory( |
| 22305 | switch (linked_src_op) { |
| 22306 | else => unreachable, |
| 22307 | .gpr_limb => .{ ._, .mov }, |
| 22308 | .mm_limb, .mm_mask_limb => .{ ._q, .mov }, |
| 22309 | .xmm_limb, |
| 22310 | .ymm_limb, |
| 22311 | .xmm_mask_limb, |
| 22312 | .ymm_mask_limb, |
| 22313 | => .{ if (cg.hasFeature(.avx)) .v_ else ._, .movdqu }, |
| 22243 | 22314 | }, |
| 22244 | | }), |
| 22245 | | ), |
| 22315 | registerAlias(limb_temp.tracking(cg).short.register, loop.limb_size.?), |
| 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 | 22330 | mir_op.* = switch (linked_src_op) { |
| 22248 | | .implicit, .explicit => unreachable, |
| 22331 | .implicit, .explicit, .cc, .cc_mask_limb => unreachable, |
| 22249 | 22332 | .gpr => .{ .reg = registerAlias( |
| 22250 | 22333 | src_mcv.register, |
| 22251 | 22334 | @intCast(src_temp.typeOf(cg).abiSize(cg.pt.zcu)), |
| ... | ... | @@ -22262,25 +22345,12 @@ fn select( |
| 22262 | 22345 | .mm_mask_limb, |
| 22263 | 22346 | .xmm_mask_limb, |
| 22264 | 22347 | .ymm_mask_limb, |
| 22265 | | => switch (src_mcv) { |
| 22266 | | inline .register_pair, |
| 22267 | | .register_triple, |
| 22268 | | .register_quadruple, |
| 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 | | }, |
| 22348 | => .{ .reg = registerAlias(if (extra_temp) |limb_temp| |
| 22349 | limb_temp.tracking(cg).short.register |
| 22350 | else |
| 22351 | src_mcv.getRegs()[@divExact(loop.limb_offset.known, loop.limb_size.?)], loop.limb_size.?) }, |
| 22282 | 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 | 22354 | else => switch (loop.limb_offset) { |
| 22285 | 22355 | .unused => unreachable, |
| 22286 | 22356 | .known => |limb_offset| try src_mcv.mem(cg, .{ |
| ... | ... | @@ -22316,15 +22386,15 @@ fn select( |
| 22316 | 22386 | } |
| 22317 | 22387 | } |
| 22318 | 22388 | for ( |
| 22319 | | mir_ops[0..dst_temps.len], |
| 22320 | | pattern.ops[0..dst_temps.len], |
| 22321 | | dst_temps, |
| 22322 | | dst_tys, |
| 22323 | | extra_temps[0..dst_temps.len], |
| 22389 | mir_ops[0..dst_mir_ops_len], |
| 22390 | pattern.ops[0..dst_mir_ops_len], |
| 22391 | dst_temps[0..dst_mir_ops_len], |
| 22392 | dst_tys[0..dst_mir_ops_len], |
| 22393 | extra_temps[0..dst_mir_ops_len], |
| 22324 | 22394 | ) |*mir_op, dst_op, dst_temp, dst_ty, extra_temp| { |
| 22325 | 22395 | if (mir_op.* != .none) continue; |
| 22326 | 22396 | mir_op.* = switch (dst_op) { |
| 22327 | | .implicit => unreachable, |
| 22397 | .implicit, .cc, .cc_mask_limb => unreachable, |
| 22328 | 22398 | .explicit => |linked_index| mir_ops[linked_index], |
| 22329 | 22399 | .gpr => .{ .reg = registerAlias( |
| 22330 | 22400 | dst_temp.tracking(cg).short.register, |
| ... | ... | @@ -22334,7 +22404,14 @@ fn select( |
| 22334 | 22404 | .xmm, .xmm_mask, .xmm_sign_mask => .{ .reg = dst_temp.tracking(cg).short.register.to128() }, |
| 22335 | 22405 | .ymm, .ymm_mask, .ymm_sign_mask => .{ .reg = dst_temp.tracking(cg).short.register.to256() }, |
| 22336 | 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 | 22415 | .mm_limb => .{ .reg = extra_temp.?.tracking(cg).short.register }, |
| 22339 | 22416 | .xmm_limb => .{ .reg = extra_temp.?.tracking(cg).short.register.to128() }, |
| 22340 | 22417 | .ymm_limb => .{ .reg = extra_temp.?.tracking(cg).short.register.to256() }, |
| ... | ... | @@ -22376,7 +22453,6 @@ fn select( |
| 22376 | 22453 | }, |
| 22377 | 22454 | else => |e| return e, |
| 22378 | 22455 | }; |
| 22379 | | const invert_result = opts.invert_result != pattern_set.invert_result; |
| 22380 | 22456 | for ( |
| 22381 | 22457 | extra_temps[0..dst_temps.len], |
| 22382 | 22458 | pattern.ops[0..dst_temps.len], |
| ... | ... | @@ -22410,21 +22486,15 @@ fn select( |
| 22410 | 22486 | .any, .bool => unreachable, |
| 22411 | 22487 | .float, .any_int, .signed_int, .unsigned_int, .any_float_or_int => |size| size, |
| 22412 | 22488 | }, cg), |
| 22413 | | .gpr_limb, .mm_limb, .xmm_limb, .ymm_limb => if (extra_temp) |limb_temp| |
| 22414 | | switch (dst_temp.tracking(cg).short) { |
| 22415 | | inline .register_pair, |
| 22416 | | .register_triple, |
| 22417 | | .register_quadruple, |
| 22418 | | => |dst_regs| switch (loop.limb_offset) { |
| 22419 | | .unused => unreachable, |
| 22420 | | .known => |limb_offset| try cg.asmRegisterRegister( |
| 22421 | | .{ ._, .mov }, |
| 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( |
| 22489 | .gpr_limb, .mm_limb, .xmm_limb, .ymm_limb => if (extra_temp) |limb_temp| { |
| 22490 | const dst_mcv = dst_temp.tracking(cg).short; |
| 22491 | switch (dst_mcv) { |
| 22492 | .register_pair, .register_triple, .register_quadruple => try cg.asmRegisterRegister( |
| 22493 | .{ ._, .mov }, |
| 22494 | dst_mcv.getRegs()[@divExact(loop.limb_offset.known, loop.limb_size.?)].to64(), |
| 22495 | limb_temp.tracking(cg).short.register.to64(), |
| 22496 | ), |
| 22497 | else => try cg.asmMemoryRegister( |
| 22428 | 22498 | switch (dst_op) { |
| 22429 | 22499 | else => unreachable, |
| 22430 | 22500 | .gpr_limb => .{ ._, .mov }, |
| ... | ... | @@ -22444,57 +22514,66 @@ fn select( |
| 22444 | 22514 | }), |
| 22445 | 22515 | registerAlias(limb_temp.tracking(cg).short.register, loop.limb_size.?), |
| 22446 | 22516 | ), |
| 22447 | | }, |
| 22448 | | .mm_mask_limb, .xmm_mask_limb, .ymm_mask_limb => { |
| 22517 | } |
| 22518 | }, |
| 22519 | .cc_mask_limb, .mm_mask_limb, .xmm_mask_limb, .ymm_mask_limb => { |
| 22449 | 22520 | const scalar_size = switch (pattern_set.scalar) { |
| 22450 | 22521 | .any, .bool => unreachable, |
| 22451 | 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 | 22524 | const mask_store_size: u4 = |
| 22467 | 22525 | @intCast(std.math.divCeil(u7, loop.mask_store_bit_size.?, 8) catch unreachable); |
| 22468 | | const mask_limb_reg = registerAlias( |
| 22469 | | loop.mask_limb_temp.?.tracking(cg).short.register, |
| 22470 | | mask_store_size, |
| 22471 | | ); |
| 22472 | | try cg.asmRegisterRegister(switch (scalar_size) { |
| 22526 | const known_shl_count = if (loop.mask_store_reg) |_| switch (loop.mask_limb_offset) { |
| 22527 | .unused => unreachable, |
| 22528 | .known => |mask_limb_offset| mask_limb_offset & (loop.mask_store_bit_size.? - 1), |
| 22529 | .temp => null, |
| 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 | 22536 | else => unreachable, |
| 22474 | | .byte, .word => .{ if (cg.hasFeature(.avx)) .vp_b else .p_b, .movmsk }, |
| 22475 | | .dword => .{ if (cg.hasFeature(.avx)) .v_ps else ._ps, .movmsk }, |
| 22476 | | .qword => .{ if (cg.hasFeature(.avx)) .v_pd else ._pd, .movmsk }, |
| 22477 | | }, mask_limb_reg.to32(), mir_op.reg); |
| 22478 | | if (invert_result) if (loop.mask_store_reg) |_| { |
| 22479 | | try cg.spillEflagsIfOccupied(); |
| 22480 | | try cg.asmRegisterImmediate( |
| 22481 | | .{ ._, .xor }, |
| 22482 | | registerAlias(mask_limb_reg, @min(mask_store_size, 4)), |
| 22483 | | .u((@as(u32, 1) << @intCast(loop.mask_limb_bit_size.?)) - 1), |
| 22484 | | ); |
| 22485 | | } else try cg.asmRegister(.{ ._, .not }, mask_limb_reg); |
| 22537 | .cc_mask_limb => try cg.asmSetccRegister(switch (invert_result) { |
| 22538 | false => opts.cc.?, |
| 22539 | true => opts.cc.?.negate(), |
| 22540 | }, mask_limb_reg.to8()), |
| 22541 | .mm_mask_limb, .xmm_mask_limb, .ymm_mask_limb => { |
| 22542 | if (scalar_size == .word) if (cg.hasFeature(.avx)) try cg.asmRegisterRegisterRegister( |
| 22543 | .{ .vp_b, .ackssw }, |
| 22544 | mir_op.reg, |
| 22545 | mir_op.reg, |
| 22546 | mir_op.reg, |
| 22547 | ) else try cg.asmRegisterRegister( |
| 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 | 22568 | if (loop.mask_store_reg) |mask_store_reg| { |
| 22487 | 22569 | const mask_store_alias = registerAlias(mask_store_reg, mask_store_size); |
| 22488 | 22570 | switch (loop.mask_limb_offset) { |
| 22489 | 22571 | .unused => unreachable, |
| 22490 | | .known => |mask_limb_offset| switch (mask_limb_offset & (loop.mask_store_bit_size.? - 1)) { |
| 22491 | | 0 => try cg.asmRegisterRegister(.{ ._, .mov }, mask_store_alias, mask_limb_reg), |
| 22492 | | else => |shl_count| { |
| 22493 | | try cg.spillEflagsIfOccupied(); |
| 22494 | | try cg.asmRegisterImmediate(.{ ._l, .sh }, mask_limb_reg, .u(shl_count)); |
| 22495 | | try cg.spillEflagsIfOccupied(); |
| 22496 | | try cg.asmRegisterRegister(.{ ._, .@"or" }, mask_store_alias, mask_limb_reg); |
| 22497 | | }, |
| 22572 | .known => if (known_shl_count.? != 0) { |
| 22573 | try cg.spillEflagsIfOccupied(); |
| 22574 | try cg.asmRegisterImmediate(.{ ._l, .sh }, mask_limb_reg, .u(known_shl_count.?)); |
| 22575 | try cg.spillEflagsIfOccupied(); |
| 22576 | try cg.asmRegisterRegister(.{ ._, .@"or" }, mask_store_alias, mask_limb_reg); |
| 22498 | 22577 | }, |
| 22499 | 22578 | .temp => |mask_limb_offset| { |
| 22500 | 22579 | if (cg.hasFeature(.bmi2)) { |
| ... | ... | @@ -22524,23 +22603,23 @@ fn select( |
| 22524 | 22603 | .unused => unreachable, |
| 22525 | 22604 | .known => |*mask_limb_offset| { |
| 22526 | 22605 | mask_limb_offset.* += loop.mask_limb_bit_size.?; |
| 22527 | | if (mask_limb_offset.* & (loop.mask_store_bit_size.? - 1) == 0) { |
| 22528 | | switch (dst_mcv) { |
| 22529 | | .register => {}, |
| 22530 | | else => try cg.asmMemoryRegister( |
| 22606 | if (mask_limb_offset.* & (loop.mask_store_bit_size.? - 1) == 0) switch (dst_mcv) { |
| 22607 | .register => {}, |
| 22608 | else => { |
| 22609 | try cg.asmMemoryRegister( |
| 22531 | 22610 | .{ ._, .mov }, |
| 22532 | 22611 | try dst_mcv.mem(cg, .{ |
| 22533 | 22612 | .size = .fromSize(mask_store_size), |
| 22534 | 22613 | .disp = @divExact(mask_limb_offset.*, 8) - mask_store_size, |
| 22535 | 22614 | }), |
| 22536 | 22615 | registerAlias(loop.mask_store_reg orelse mask_limb_reg, mask_store_size), |
| 22537 | | ), |
| 22538 | | } |
| 22539 | | if (loop.mask_store_reg) |mask_store_reg| { |
| 22540 | | const mask_store_alias = registerAlias(mask_store_reg, @min(mask_store_size, 4)); |
| 22541 | | try cg.asmRegisterRegister(.{ ._, .xor }, mask_store_alias, mask_store_alias); |
| 22542 | | } |
| 22543 | | } |
| 22616 | ); |
| 22617 | if (loop.mask_store_reg) |mask_store_reg| { |
| 22618 | const mask_store_alias = registerAlias(mask_store_reg, @min(mask_store_size, 4)); |
| 22619 | try cg.asmRegisterRegister(.{ ._, .xor }, mask_store_alias, mask_store_alias); |
| 22620 | } |
| 22621 | }, |
| 22622 | }; |
| 22544 | 22623 | }, |
| 22545 | 22624 | .temp => |mask_limb_offset| { |
| 22546 | 22625 | const mask_limb_offset_reg = mask_limb_offset.tracking(cg).short.register.to32(); |
| ... | ... | @@ -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 | 22724 | if (loop.mask_limb_temp) |mask_limb_temp| try mask_limb_temp.die(cg); |
| 22645 | 22725 | if (loop.mask_store_temp) |mask_store_temp| try mask_store_temp.die(cg); |
| 22646 | 22726 | switch (loop.mask_limb_offset) { |