| ... | @@ -8998,7 +8998,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -8998,7 +8998,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 8998 | }) else fallback: { | 8998 | }) else fallback: { |
| 8999 | const bin_op = air_datas[@intFromEnum(inst)].bin_op; | 8999 | const bin_op = air_datas[@intFromEnum(inst)].bin_op; |
| 9000 | const scalar_ty = cg.typeOf(bin_op.lhs).scalarType(zcu); | 9000 | const scalar_ty = cg.typeOf(bin_op.lhs).scalarType(zcu); |
| 9001 | if (scalar_ty.isRuntimeFloat() or ip.isOptionalType(scalar_ty.toIntern())) break :fallback try cg.airCmp(inst, switch (air_tag) { | 9001 | if (intInfo(scalar_ty, cg) == null) break :fallback try cg.airCmp(inst, switch (air_tag) { |
| 9002 | else => unreachable, | 9002 | else => unreachable, |
| 9003 | .cmp_eq, .cmp_eq_optimized => .eq, | 9003 | .cmp_eq, .cmp_eq_optimized => .eq, |
| 9004 | .cmp_neq, .cmp_neq_optimized => .neq, | 9004 | .cmp_neq, .cmp_neq_optimized => .neq, |
| ... | @@ -9012,38 +9012,81 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -9012,38 +9012,81 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 9012 | })) { | 9012 | })) { |
| 9013 | else => unreachable, | 9013 | else => unreachable, |
| 9014 | inline .e, .ne => |cc| comptime &.{ .{ | 9014 | inline .e, .ne => |cc| comptime &.{ .{ |
| 9015 | .required_features = .{ .avx2, null, null, null }, | 9015 | .src_constraints = .{ .{ .int = .byte }, .{ .int = .byte } }, |
| 9016 | .src_constraints = .{ .{ .int = .yword }, .{ .int = .yword } }, | | |
| 9017 | .patterns = &.{ | 9016 | .patterns = &.{ |
| 9018 | .{ .src = .{ .to_ymm, .mem } }, | 9017 | .{ .src = .{ .mem, .imm8 } }, |
| 9019 | .{ .src = .{ .mem, .to_ymm }, .commute = .{ 0, 1 } }, | 9018 | .{ .src = .{ .imm8, .mem }, .commute = .{ 0, 1 } }, |
| 9020 | .{ .src = .{ .to_ymm, .to_ymm } }, | 9019 | .{ .src = .{ .to_gpr, .imm8 } }, |
| | 9020 | .{ .src = .{ .imm8, .to_gpr }, .commute = .{ 0, 1 } }, |
| | 9021 | .{ .src = .{ .to_gpr, .mem } }, |
| | 9022 | .{ .src = .{ .mem, .to_gpr }, .commute = .{ 0, 1 } }, |
| | 9023 | .{ .src = .{ .to_gpr, .to_gpr } }, |
| 9021 | }, | 9024 | }, |
| 9022 | .extra_temps = .{ | 9025 | .dst_temps = .{.{ .cc = cc }}, |
| 9023 | .{ .kind = .{ .rc = .sse } }, | 9026 | .clobbers = .{ .eflags = true }, |
| 9024 | .unused, | 9027 | .each = .{ .once = &.{ |
| 9025 | .unused, | 9028 | .{ ._, ._, .cmp, .src0b, .src1b, ._, ._ }, |
| 9026 | .unused, | 9029 | } }, |
| 9027 | .unused, | 9030 | }, .{ |
| 9028 | .unused, | 9031 | .src_constraints = .{ .{ .int = .word }, .{ .int = .word } }, |
| | 9032 | .patterns = &.{ |
| | 9033 | .{ .src = .{ .mem, .imm16 } }, |
| | 9034 | .{ .src = .{ .imm16, .mem }, .commute = .{ 0, 1 } }, |
| | 9035 | .{ .src = .{ .to_gpr, .imm16 } }, |
| | 9036 | .{ .src = .{ .imm16, .to_gpr }, .commute = .{ 0, 1 } }, |
| | 9037 | .{ .src = .{ .to_gpr, .mem } }, |
| | 9038 | .{ .src = .{ .mem, .to_gpr }, .commute = .{ 0, 1 } }, |
| | 9039 | .{ .src = .{ .to_gpr, .to_gpr } }, |
| 9029 | }, | 9040 | }, |
| 9030 | .dst_temps = .{.{ .cc = cc }}, | 9041 | .dst_temps = .{.{ .cc = cc }}, |
| 9031 | .clobbers = .{ .eflags = true }, | 9042 | .clobbers = .{ .eflags = true }, |
| 9032 | .each = .{ .once = &.{ | 9043 | .each = .{ .once = &.{ |
| 9033 | .{ ._, .vp_, .xor, .tmp0y, .src0y, .src1y, ._ }, | 9044 | .{ ._, ._, .cmp, .src0w, .src1w, ._, ._ }, |
| 9034 | .{ ._, .vp_, .@"test", .tmp0y, .tmp0y, ._, ._ }, | | |
| 9035 | } }, | 9045 | } }, |
| 9036 | }, .{ | 9046 | }, .{ |
| 9037 | .required_features = .{ .avx, null, null, null }, | 9047 | .src_constraints = .{ .{ .int = .dword }, .{ .int = .dword } }, |
| 9038 | .src_constraints = .{ .{ .int = .yword }, .{ .int = .yword } }, | | |
| 9039 | .patterns = &.{ | 9048 | .patterns = &.{ |
| 9040 | .{ .src = .{ .to_ymm, .mem } }, | 9049 | .{ .src = .{ .mem, .imm32 } }, |
| 9041 | .{ .src = .{ .mem, .to_ymm }, .commute = .{ 0, 1 } }, | 9050 | .{ .src = .{ .imm32, .mem }, .commute = .{ 0, 1 } }, |
| 9042 | .{ .src = .{ .to_ymm, .to_ymm } }, | 9051 | .{ .src = .{ .to_gpr, .imm32 } }, |
| | 9052 | .{ .src = .{ .imm32, .to_gpr }, .commute = .{ 0, 1 } }, |
| | 9053 | .{ .src = .{ .to_gpr, .mem } }, |
| | 9054 | .{ .src = .{ .mem, .to_gpr }, .commute = .{ 0, 1 } }, |
| | 9055 | .{ .src = .{ .to_gpr, .to_gpr } }, |
| | 9056 | }, |
| | 9057 | .dst_temps = .{.{ .cc = cc }}, |
| | 9058 | .clobbers = .{ .eflags = true }, |
| | 9059 | .each = .{ .once = &.{ |
| | 9060 | .{ ._, ._, .cmp, .src0d, .src1d, ._, ._ }, |
| | 9061 | } }, |
| | 9062 | }, .{ |
| | 9063 | .required_features = .{ .@"64bit", null, null, null }, |
| | 9064 | .src_constraints = .{ .{ .int = .qword }, .{ .int = .qword } }, |
| | 9065 | .patterns = &.{ |
| | 9066 | .{ .src = .{ .mem, .simm32 } }, |
| | 9067 | .{ .src = .{ .simm32, .mem }, .commute = .{ 0, 1 } }, |
| | 9068 | .{ .src = .{ .to_gpr, .simm32 } }, |
| | 9069 | .{ .src = .{ .simm32, .to_gpr }, .commute = .{ 0, 1 } }, |
| | 9070 | .{ .src = .{ .to_gpr, .mem } }, |
| | 9071 | .{ .src = .{ .mem, .to_gpr }, .commute = .{ 0, 1 } }, |
| | 9072 | .{ .src = .{ .to_gpr, .to_gpr } }, |
| | 9073 | }, |
| | 9074 | .dst_temps = .{.{ .cc = cc }}, |
| | 9075 | .clobbers = .{ .eflags = true }, |
| | 9076 | .each = .{ .once = &.{ |
| | 9077 | .{ ._, ._, .cmp, .src0q, .src1q, ._, ._ }, |
| | 9078 | } }, |
| | 9079 | }, .{ |
| | 9080 | .required_features = .{ .sse, .mmx, null, null }, |
| | 9081 | .src_constraints = .{ .{ .int = .qword }, .{ .int = .qword } }, |
| | 9082 | .patterns = &.{ |
| | 9083 | .{ .src = .{ .to_mut_mm, .mem } }, |
| | 9084 | .{ .src = .{ .mem, .to_mut_mm }, .commute = .{ 0, 1 } }, |
| | 9085 | .{ .src = .{ .to_mut_mm, .to_mm } }, |
| 9043 | }, | 9086 | }, |
| 9044 | .extra_temps = .{ | 9087 | .extra_temps = .{ |
| 9045 | .{ .kind = .{ .rc = .sse } }, | 9088 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 9046 | .unused, | 9089 | .{ .kind = .{ .rc = .mmx } }, |
| 9047 | .unused, | 9090 | .unused, |
| 9048 | .unused, | 9091 | .unused, |
| 9049 | .unused, | 9092 | .unused, |
| ... | @@ -9052,8 +9095,11 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -9052,8 +9095,11 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 9052 | .dst_temps = .{.{ .cc = cc }}, | 9095 | .dst_temps = .{.{ .cc = cc }}, |
| 9053 | .clobbers = .{ .eflags = true }, | 9096 | .clobbers = .{ .eflags = true }, |
| 9054 | .each = .{ .once = &.{ | 9097 | .each = .{ .once = &.{ |
| 9055 | .{ ._, .v_pd, .xor, .tmp0y, .src0y, .src1y, ._ }, | 9098 | .{ ._, .p_, .xor, .tmp1q, .tmp1q, ._, ._ }, |
| 9056 | .{ ._, .vp_, .@"test", .tmp0y, .tmp0y, ._, ._ }, | 9099 | .{ ._, .p_, .xor, .src0q, .src1q, ._, ._ }, |
| | 9100 | .{ ._, .p_b, .cmpeq, .tmp1q, .src0q, ._, ._ }, |
| | 9101 | .{ ._, .p_b, .movmsk, .tmp0d, .tmp1q, ._, ._ }, |
| | 9102 | .{ ._, ._, .xor, .tmp0d, .si(0xff), ._, ._ }, |
| 9057 | } }, | 9103 | } }, |
| 9058 | }, .{ | 9104 | }, .{ |
| 9059 | .required_features = .{ .avx, null, null, null }, | 9105 | .required_features = .{ .avx, null, null, null }, |
| ... | @@ -9117,16 +9163,16 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -9117,16 +9163,16 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 9117 | .{ ._, ._, .xor, .tmp0d, .si(0xffff), ._, ._ }, | 9163 | .{ ._, ._, .xor, .tmp0d, .si(0xffff), ._, ._ }, |
| 9118 | } }, | 9164 | } }, |
| 9119 | }, .{ | 9165 | }, .{ |
| 9120 | .required_features = .{ .sse, .mmx, null, null }, | 9166 | .required_features = .{ .avx2, null, null, null }, |
| 9121 | .src_constraints = .{ .{ .int = .qword }, .{ .int = .qword } }, | 9167 | .src_constraints = .{ .{ .int = .yword }, .{ .int = .yword } }, |
| 9122 | .patterns = &.{ | 9168 | .patterns = &.{ |
| 9123 | .{ .src = .{ .to_mut_mm, .mem } }, | 9169 | .{ .src = .{ .to_ymm, .mem } }, |
| 9124 | .{ .src = .{ .mem, .to_mut_mm }, .commute = .{ 0, 1 } }, | 9170 | .{ .src = .{ .mem, .to_ymm }, .commute = .{ 0, 1 } }, |
| 9125 | .{ .src = .{ .to_mut_mm, .to_mm } }, | 9171 | .{ .src = .{ .to_ymm, .to_ymm } }, |
| 9126 | }, | 9172 | }, |
| 9127 | .extra_temps = .{ | 9173 | .extra_temps = .{ |
| 9128 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, | 9174 | .{ .kind = .{ .rc = .sse } }, |
| 9129 | .{ .kind = .{ .rc = .mmx } }, | 9175 | .unused, |
| 9130 | .unused, | 9176 | .unused, |
| 9131 | .unused, | 9177 | .unused, |
| 9132 | .unused, | 9178 | .unused, |
| ... | @@ -9135,76 +9181,30 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -9135,76 +9181,30 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 9135 | .dst_temps = .{.{ .cc = cc }}, | 9181 | .dst_temps = .{.{ .cc = cc }}, |
| 9136 | .clobbers = .{ .eflags = true }, | 9182 | .clobbers = .{ .eflags = true }, |
| 9137 | .each = .{ .once = &.{ | 9183 | .each = .{ .once = &.{ |
| 9138 | .{ ._, .p_, .xor, .tmp1q, .tmp1q, ._, ._ }, | 9184 | .{ ._, .vp_, .xor, .tmp0y, .src0y, .src1y, ._ }, |
| 9139 | .{ ._, .p_, .xor, .src0q, .src1q, ._, ._ }, | 9185 | .{ ._, .vp_, .@"test", .tmp0y, .tmp0y, ._, ._ }, |
| 9140 | .{ ._, .p_b, .cmpeq, .tmp1q, .src0q, ._, ._ }, | | |
| 9141 | .{ ._, .p_b, .movmsk, .tmp0d, .tmp1q, ._, ._ }, | | |
| 9142 | .{ ._, ._, .xor, .tmp0d, .si(0xff), ._, ._ }, | | |
| 9143 | } }, | | |
| 9144 | }, .{ | | |
| 9145 | .src_constraints = .{ .{ .int = .byte }, .{ .int = .byte } }, | | |
| 9146 | .patterns = &.{ | | |
| 9147 | .{ .src = .{ .mem, .imm8 } }, | | |
| 9148 | .{ .src = .{ .imm8, .mem }, .commute = .{ 0, 1 } }, | | |
| 9149 | .{ .src = .{ .to_gpr, .imm8 } }, | | |
| 9150 | .{ .src = .{ .imm8, .to_gpr }, .commute = .{ 0, 1 } }, | | |
| 9151 | .{ .src = .{ .to_gpr, .mem } }, | | |
| 9152 | .{ .src = .{ .mem, .to_gpr }, .commute = .{ 0, 1 } }, | | |
| 9153 | .{ .src = .{ .to_gpr, .to_gpr } }, | | |
| 9154 | }, | | |
| 9155 | .dst_temps = .{.{ .cc = cc }}, | | |
| 9156 | .clobbers = .{ .eflags = true }, | | |
| 9157 | .each = .{ .once = &.{ | | |
| 9158 | .{ ._, ._, .cmp, .src0b, .src1b, ._, ._ }, | | |
| 9159 | } }, | | |
| 9160 | }, .{ | | |
| 9161 | .src_constraints = .{ .{ .int = .word }, .{ .int = .word } }, | | |
| 9162 | .patterns = &.{ | | |
| 9163 | .{ .src = .{ .mem, .imm16 } }, | | |
| 9164 | .{ .src = .{ .imm16, .mem }, .commute = .{ 0, 1 } }, | | |
| 9165 | .{ .src = .{ .to_gpr, .imm16 } }, | | |
| 9166 | .{ .src = .{ .imm16, .to_gpr }, .commute = .{ 0, 1 } }, | | |
| 9167 | .{ .src = .{ .to_gpr, .mem } }, | | |
| 9168 | .{ .src = .{ .mem, .to_gpr }, .commute = .{ 0, 1 } }, | | |
| 9169 | .{ .src = .{ .to_gpr, .to_gpr } }, | | |
| 9170 | }, | | |
| 9171 | .dst_temps = .{.{ .cc = cc }}, | | |
| 9172 | .clobbers = .{ .eflags = true }, | | |
| 9173 | .each = .{ .once = &.{ | | |
| 9174 | .{ ._, ._, .cmp, .src0w, .src1w, ._, ._ }, | | |
| 9175 | } }, | 9186 | } }, |
| 9176 | }, .{ | 9187 | }, .{ |
| 9177 | .src_constraints = .{ .{ .int = .dword }, .{ .int = .dword } }, | 9188 | .required_features = .{ .avx, null, null, null }, |
| | 9189 | .src_constraints = .{ .{ .int = .yword }, .{ .int = .yword } }, |
| 9178 | .patterns = &.{ | 9190 | .patterns = &.{ |
| 9179 | .{ .src = .{ .mem, .imm32 } }, | 9191 | .{ .src = .{ .to_ymm, .mem } }, |
| 9180 | .{ .src = .{ .imm32, .mem }, .commute = .{ 0, 1 } }, | 9192 | .{ .src = .{ .mem, .to_ymm }, .commute = .{ 0, 1 } }, |
| 9181 | .{ .src = .{ .to_gpr, .imm32 } }, | 9193 | .{ .src = .{ .to_ymm, .to_ymm } }, |
| 9182 | .{ .src = .{ .imm32, .to_gpr }, .commute = .{ 0, 1 } }, | | |
| 9183 | .{ .src = .{ .to_gpr, .mem } }, | | |
| 9184 | .{ .src = .{ .mem, .to_gpr }, .commute = .{ 0, 1 } }, | | |
| 9185 | .{ .src = .{ .to_gpr, .to_gpr } }, | | |
| 9186 | }, | 9194 | }, |
| 9187 | .dst_temps = .{.{ .cc = cc }}, | 9195 | .extra_temps = .{ |
| 9188 | .clobbers = .{ .eflags = true }, | 9196 | .{ .kind = .{ .rc = .sse } }, |
| 9189 | .each = .{ .once = &.{ | 9197 | .unused, |
| 9190 | .{ ._, ._, .cmp, .src0d, .src1d, ._, ._ }, | 9198 | .unused, |
| 9191 | } }, | 9199 | .unused, |
| 9192 | }, .{ | 9200 | .unused, |
| 9193 | .required_features = .{ .@"64bit", null, null, null }, | 9201 | .unused, |
| 9194 | .src_constraints = .{ .{ .int = .qword }, .{ .int = .qword } }, | | |
| 9195 | .patterns = &.{ | | |
| 9196 | .{ .src = .{ .mem, .simm32 } }, | | |
| 9197 | .{ .src = .{ .simm32, .mem }, .commute = .{ 0, 1 } }, | | |
| 9198 | .{ .src = .{ .to_gpr, .simm32 } }, | | |
| 9199 | .{ .src = .{ .simm32, .to_gpr }, .commute = .{ 0, 1 } }, | | |
| 9200 | .{ .src = .{ .to_gpr, .mem } }, | | |
| 9201 | .{ .src = .{ .mem, .to_gpr }, .commute = .{ 0, 1 } }, | | |
| 9202 | .{ .src = .{ .to_gpr, .to_gpr } }, | | |
| 9203 | }, | 9202 | }, |
| 9204 | .dst_temps = .{.{ .cc = cc }}, | 9203 | .dst_temps = .{.{ .cc = cc }}, |
| 9205 | .clobbers = .{ .eflags = true }, | 9204 | .clobbers = .{ .eflags = true }, |
| 9206 | .each = .{ .once = &.{ | 9205 | .each = .{ .once = &.{ |
| 9207 | .{ ._, ._, .cmp, .src0q, .src1q, ._, ._ }, | 9206 | .{ ._, .v_pd, .xor, .tmp0y, .src0y, .src1y, ._ }, |
| | 9207 | .{ ._, .vp_, .@"test", .tmp0y, .tmp0y, ._, ._ }, |
| 9208 | } }, | 9208 | } }, |
| 9209 | }, .{ | 9209 | }, .{ |
| 9210 | .required_features = .{ .avx2, null, null, null }, | 9210 | .required_features = .{ .avx2, null, null, null }, |
| ... | @@ -19540,10 +19540,19 @@ fn genIntMulComplexOpMir(self: *CodeGen, dst_ty: Type, dst_mcv: MCValue, src_mcv | ... | @@ -19540,10 +19540,19 @@ fn genIntMulComplexOpMir(self: *CodeGen, dst_ty: Type, dst_mcv: MCValue, src_mcv |
| 19540 | .air_ref, | 19540 | .air_ref, |
| 19541 | => unreachable, // unmodifiable destination | 19541 | => unreachable, // unmodifiable destination |
| 19542 | .register => |dst_reg| { | 19542 | .register => |dst_reg| { |
| 19543 | const dst_alias = registerAlias(dst_reg, abi_size); | 19543 | const alias_size = switch (abi_size) { |
| | 19544 | 1 => 4, |
| | 19545 | else => abi_size, |
| | 19546 | }; |
| | 19547 | const dst_alias = registerAlias(dst_reg, alias_size); |
| 19544 | const dst_lock = self.register_manager.lockReg(dst_reg); | 19548 | const dst_lock = self.register_manager.lockReg(dst_reg); |
| 19545 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); | 19549 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); |
| 19546 | | 19550 | |
| | 19551 | switch (abi_size) { |
| | 19552 | 1 => try self.asmRegisterRegister(.{ ._, .movzx }, dst_reg.to32(), dst_reg.to8()), |
| | 19553 | else => {}, |
| | 19554 | } |
| | 19555 | |
| 19547 | const resolved_src_mcv = switch (src_mcv) { | 19556 | const resolved_src_mcv = switch (src_mcv) { |
| 19548 | else => src_mcv, | 19557 | else => src_mcv, |
| 19549 | .air_ref => |src_ref| try self.resolveInst(src_ref), | 19558 | .air_ref => |src_ref| try self.resolveInst(src_ref), |
| ... | @@ -19562,19 +19571,20 @@ fn genIntMulComplexOpMir(self: *CodeGen, dst_ty: Type, dst_mcv: MCValue, src_mcv | ... | @@ -19562,19 +19571,20 @@ fn genIntMulComplexOpMir(self: *CodeGen, dst_ty: Type, dst_mcv: MCValue, src_mcv |
| 19562 | .reserved_frame, | 19571 | .reserved_frame, |
| 19563 | .air_ref, | 19572 | .air_ref, |
| 19564 | => unreachable, | 19573 | => unreachable, |
| 19565 | .register => |src_reg| try self.asmRegisterRegister( | 19574 | .register => |src_reg| { |
| 19566 | .{ .i_, .mul }, | 19575 | switch (abi_size) { |
| 19567 | dst_alias, | 19576 | 1 => try self.asmRegisterRegister(.{ ._, .movzx }, src_reg.to32(), src_reg.to8()), |
| 19568 | registerAlias(src_reg, abi_size), | 19577 | else => {}, |
| 19569 | ), | 19578 | } |
| | 19579 | try self.asmRegisterRegister( |
| | 19580 | .{ .i_, .mul }, |
| | 19581 | dst_alias, |
| | 19582 | registerAlias(src_reg, alias_size), |
| | 19583 | ); |
| | 19584 | }, |
| 19570 | .immediate => |imm| { | 19585 | .immediate => |imm| { |
| 19571 | if (std.math.cast(i32, imm)) |small| { | 19586 | if (std.math.cast(i32, @as(i64, @bitCast(imm)))) |small| { |
| 19572 | try self.asmRegisterRegisterImmediate( | 19587 | try self.asmRegisterRegisterImmediate(.{ .i_, .mul }, dst_alias, dst_alias, .s(small)); |
| 19573 | .{ .i_, .mul }, | | |
| 19574 | dst_alias, | | |
| 19575 | dst_alias, | | |
| 19576 | .s(small), | | |
| 19577 | ); | | |
| 19578 | } else { | 19588 | } else { |
| 19579 | const src_reg = try self.copyToTmpRegister(dst_ty, resolved_src_mcv); | 19589 | const src_reg = try self.copyToTmpRegister(dst_ty, resolved_src_mcv); |
| 19580 | return self.genIntMulComplexOpMir(dst_ty, dst_mcv, MCValue{ .register = src_reg }); | 19590 | return self.genIntMulComplexOpMir(dst_ty, dst_mcv, MCValue{ .register = src_reg }); |
| ... | @@ -19591,47 +19601,57 @@ fn genIntMulComplexOpMir(self: *CodeGen, dst_ty: Type, dst_mcv: MCValue, src_mcv | ... | @@ -19591,47 +19601,57 @@ fn genIntMulComplexOpMir(self: *CodeGen, dst_ty: Type, dst_mcv: MCValue, src_mcv |
| 19591 | .load_tlv, | 19601 | .load_tlv, |
| 19592 | .lea_tlv, | 19602 | .lea_tlv, |
| 19593 | .lea_frame, | 19603 | .lea_frame, |
| 19594 | => try self.asmRegisterRegister( | 19604 | => { |
| 19595 | .{ .i_, .mul }, | 19605 | const src_reg = try self.copyToTmpRegister(dst_ty, resolved_src_mcv); |
| 19596 | dst_alias, | 19606 | switch (abi_size) { |
| 19597 | registerAlias(try self.copyToTmpRegister(dst_ty, resolved_src_mcv), abi_size), | 19607 | 1 => try self.asmRegisterRegister(.{ ._, .movzx }, src_reg.to32(), src_reg.to8()), |
| 19598 | ), | 19608 | else => {}, |
| 19599 | .memory, .indirect, .load_frame => try self.asmRegisterMemory( | 19609 | } |
| 19600 | .{ .i_, .mul }, | 19610 | try self.asmRegisterRegister(.{ .i_, .mul }, dst_alias, registerAlias(src_reg, alias_size)); |
| 19601 | dst_alias, | 19611 | }, |
| 19602 | switch (resolved_src_mcv) { | 19612 | .memory, .indirect, .load_frame => switch (abi_size) { |
| 19603 | .memory => |addr| .{ | 19613 | 1 => { |
| 19604 | .base = .{ .reg = .ds }, | 19614 | const src_reg = try self.copyToTmpRegister(dst_ty, resolved_src_mcv); |
| 19605 | .mod = .{ .rm = .{ | 19615 | try self.asmRegisterRegister(.{ ._, .movzx }, src_reg.to32(), src_reg.to8()); |
| 19606 | .size = .fromSize(abi_size), | 19616 | try self.asmRegisterRegister(.{ .i_, .mul }, dst_alias, registerAlias(src_reg, alias_size)); |
| 19607 | .disp = std.math.cast(i32, @as(i64, @bitCast(addr))) orelse | 19617 | }, |
| 19608 | return self.asmRegisterRegister( | 19618 | else => try self.asmRegisterMemory( |
| 19609 | .{ .i_, .mul }, | 19619 | .{ .i_, .mul }, |
| 19610 | dst_alias, | 19620 | dst_alias, |
| 19611 | registerAlias( | 19621 | switch (resolved_src_mcv) { |
| 19612 | try self.copyToTmpRegister(dst_ty, resolved_src_mcv), | 19622 | .memory => |addr| .{ |
| 19613 | abi_size, | 19623 | .base = .{ .reg = .ds }, |
| | 19624 | .mod = .{ .rm = .{ |
| | 19625 | .size = .fromSize(abi_size), |
| | 19626 | .disp = std.math.cast(i32, @as(i64, @bitCast(addr))) orelse |
| | 19627 | return self.asmRegisterRegister( |
| | 19628 | .{ .i_, .mul }, |
| | 19629 | dst_alias, |
| | 19630 | registerAlias( |
| | 19631 | try self.copyToTmpRegister(dst_ty, resolved_src_mcv), |
| | 19632 | abi_size, |
| | 19633 | ), |
| 19614 | ), | 19634 | ), |
| 19615 | ), | 19635 | } }, |
| 19616 | } }, | 19636 | }, |
| 19617 | }, | 19637 | .indirect => |reg_off| .{ |
| 19618 | .indirect => |reg_off| .{ | 19638 | .base = .{ .reg = reg_off.reg }, |
| 19619 | .base = .{ .reg = reg_off.reg }, | 19639 | .mod = .{ .rm = .{ |
| 19620 | .mod = .{ .rm = .{ | 19640 | .size = .fromSize(abi_size), |
| 19621 | .size = .fromSize(abi_size), | 19641 | .disp = reg_off.off, |
| 19622 | .disp = reg_off.off, | 19642 | } }, |
| 19623 | } }, | 19643 | }, |
| 19624 | }, | 19644 | .load_frame => |frame_addr| .{ |
| 19625 | .load_frame => |frame_addr| .{ | 19645 | .base = .{ .frame = frame_addr.index }, |
| 19626 | .base = .{ .frame = frame_addr.index }, | 19646 | .mod = .{ .rm = .{ |
| 19627 | .mod = .{ .rm = .{ | 19647 | .size = .fromSize(abi_size), |
| 19628 | .size = .fromSize(abi_size), | 19648 | .disp = frame_addr.off, |
| 19629 | .disp = frame_addr.off, | 19649 | } }, |
| 19630 | } }, | 19650 | }, |
| | 19651 | else => unreachable, |
| 19631 | }, | 19652 | }, |
| 19632 | else => unreachable, | 19653 | ), |
| 19633 | }, | 19654 | }, |
| 19634 | ), | | |
| 19635 | } | 19655 | } |
| 19636 | }, | 19656 | }, |
| 19637 | .register_pair, .register_triple, .register_quadruple => unreachable, // unimplemented | 19657 | .register_pair, .register_triple, .register_quadruple => unreachable, // unimplemented |
| ... | @@ -27952,6 +27972,75 @@ fn promoteVarArg(self: *CodeGen, ty: Type) Type { | ... | @@ -27952,6 +27972,75 @@ fn promoteVarArg(self: *CodeGen, ty: Type) Type { |
| 27952 | } | 27972 | } |
| 27953 | } | 27973 | } |
| 27954 | | 27974 | |
| | 27975 | fn intInfo(ty: Type, cg: *CodeGen) ?std.builtin.Type.Int { |
| | 27976 | const zcu = cg.pt.zcu; |
| | 27977 | const ip = &zcu.intern_pool; |
| | 27978 | var ty_index = ty.ip_index; |
| | 27979 | while (true) switch (ip.indexToKey(ty_index)) { |
| | 27980 | .int_type => |int_type| return int_type, |
| | 27981 | .ptr_type => |ptr_type| return switch (ptr_type.flags.size) { |
| | 27982 | .one, .many, .c => .{ .signedness = .unsigned, .bits = cg.target.ptrBitWidth() }, |
| | 27983 | .slice => null, |
| | 27984 | }, |
| | 27985 | .opt_type => |opt_child| return if (!Type.fromInterned(opt_child).hasRuntimeBitsIgnoreComptime(zcu)) |
| | 27986 | .{ .signedness = .unsigned, .bits = 1 } |
| | 27987 | else switch (ip.indexToKey(opt_child)) { |
| | 27988 | .ptr_type => |ptr_type| switch (ptr_type.flags.size) { |
| | 27989 | .one, .many => switch (ptr_type.flags.is_allowzero) { |
| | 27990 | false => .{ .signedness = .unsigned, .bits = cg.target.ptrBitWidth() }, |
| | 27991 | true => null, |
| | 27992 | }, |
| | 27993 | .slice, .c => null, |
| | 27994 | }, |
| | 27995 | else => null, |
| | 27996 | }, |
| | 27997 | .error_union_type => |error_union_type| return if (!Type.fromInterned(error_union_type.payload_type) |
| | 27998 | .hasRuntimeBitsIgnoreComptime(zcu)) .{ .signedness = .unsigned, .bits = zcu.errorSetBits() } else null, |
| | 27999 | .simple_type => |simple_type| return switch (simple_type) { |
| | 28000 | .bool => .{ .signedness = .unsigned, .bits = 1 }, |
| | 28001 | .anyerror => .{ .signedness = .unsigned, .bits = zcu.errorSetBits() }, |
| | 28002 | .isize => .{ .signedness = .signed, .bits = cg.target.ptrBitWidth() }, |
| | 28003 | .usize => .{ .signedness = .unsigned, .bits = cg.target.ptrBitWidth() }, |
| | 28004 | .c_char => .{ .signedness = cg.target.charSignedness(), .bits = cg.target.cTypeBitSize(.char) }, |
| | 28005 | .c_short => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.short) }, |
| | 28006 | .c_ushort => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.short) }, |
| | 28007 | .c_int => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.int) }, |
| | 28008 | .c_uint => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.int) }, |
| | 28009 | .c_long => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.long) }, |
| | 28010 | .c_ulong => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.long) }, |
| | 28011 | .c_longlong => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.longlong) }, |
| | 28012 | .c_ulonglong => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.longlong) }, |
| | 28013 | .f16, .f32, .f64, .f80, .f128, .c_longdouble => null, |
| | 28014 | .anyopaque, |
| | 28015 | .void, |
| | 28016 | .type, |
| | 28017 | .comptime_int, |
| | 28018 | .comptime_float, |
| | 28019 | .noreturn, |
| | 28020 | .null, |
| | 28021 | .undefined, |
| | 28022 | .enum_literal, |
| | 28023 | .adhoc_inferred_error_set, |
| | 28024 | .generic_poison, |
| | 28025 | => unreachable, |
| | 28026 | }, |
| | 28027 | .struct_type => { |
| | 28028 | const loaded_struct = ip.loadStructType(ty_index); |
| | 28029 | switch (loaded_struct.layout) { |
| | 28030 | .auto, .@"extern" => return null, |
| | 28031 | .@"packed" => ty_index = loaded_struct.backingIntTypeUnordered(ip), |
| | 28032 | } |
| | 28033 | }, |
| | 28034 | .union_type => return switch (ip.loadUnionType(ty_index).flagsUnordered(ip).layout) { |
| | 28035 | .auto, .@"extern" => null, |
| | 28036 | .@"packed" => .{ .signedness = .unsigned, .bits = @intCast(ty.bitSize(zcu)) }, |
| | 28037 | }, |
| | 28038 | .enum_type => ty_index = ip.loadEnumType(ty_index).tag_ty, |
| | 28039 | .error_set_type, .inferred_error_set_type => return .{ .signedness = .unsigned, .bits = zcu.errorSetBits() }, |
| | 28040 | else => return null, |
| | 28041 | }; |
| | 28042 | } |
| | 28043 | |
| 27955 | const Temp = struct { | 28044 | const Temp = struct { |
| 27956 | index: Air.Inst.Index, | 28045 | index: Air.Inst.Index, |
| 27957 | | 28046 | |
| ... | @@ -29061,197 +29150,112 @@ const Select = struct { | ... | @@ -29061,197 +29150,112 @@ const Select = struct { |
| 29061 | | 29150 | |
| 29062 | fn accepts(constraint: Constraint, ty: Type, cg: *CodeGen) bool { | 29151 | fn accepts(constraint: Constraint, ty: Type, cg: *CodeGen) bool { |
| 29063 | const zcu = cg.pt.zcu; | 29152 | const zcu = cg.pt.zcu; |
| 29064 | switch (constraint) { | 29153 | return switch (constraint) { |
| 29065 | .any => return true, | 29154 | .any => true, |
| 29066 | .any_bool_vec => return ty.isVector(zcu) and ty.childType(zcu).toIntern() == .bool_type, | 29155 | .any_bool_vec => ty.isVector(zcu) and ty.childType(zcu).toIntern() == .bool_type, |
| 29067 | .any_int => return ty.toIntern() == .bool_type or ty.isPtrAtRuntime(zcu) or ty.isAbiInt(zcu), | 29156 | .any_int => intInfo(ty, cg) != null, |
| 29068 | .any_signed_int => return ty.isAbiInt(zcu) and ty.intInfo(zcu).signedness == .signed, | 29157 | .any_signed_int => if (intInfo(ty, cg)) |int_info| int_info.signedness == .signed else false, |
| 29069 | .any_float => return ty.isRuntimeFloat(), | 29158 | .any_float => ty.isRuntimeFloat(), |
| 29070 | .po2_any => return std.math.isPowerOfTwo(ty.abiSize(zcu)), | 29159 | .po2_any => std.math.isPowerOfTwo(ty.abiSize(zcu)), |
| 29071 | .bool_vec => |size| return ty.isVector(zcu) and ty.scalarType(zcu).toIntern() == .bool_type and | 29160 | .bool_vec => |size| ty.isVector(zcu) and ty.scalarType(zcu).toIntern() == .bool_type and |
| 29072 | size.bitSize(cg.target) >= ty.vectorLen(zcu), | 29161 | size.bitSize(cg.target) >= ty.vectorLen(zcu), |
| 29073 | .vec => |size| return ty.isVector(zcu) and ty.scalarType(zcu).toIntern() != .bool_type and | 29162 | .vec => |size| ty.isVector(zcu) and ty.scalarType(zcu).toIntern() != .bool_type and |
| 29074 | size.bitSize(cg.target) >= ty.abiSize(zcu), | 29163 | size.bitSize(cg.target) >= ty.abiSize(zcu), |
| 29075 | .signed_int_vec => |size| { | 29164 | .signed_int_vec => |size| ty.isVector(zcu) and size.bitSize(cg.target) >= 8 * ty.abiSize(zcu) and |
| 29076 | if (!ty.isVector(zcu) or size.bitSize(cg.target) < 8 * ty.abiSize(zcu)) return false; | 29165 | if (intInfo(ty.childType(zcu), cg)) |int_info| int_info.signedness == .signed else false, |
| 29077 | const scalar_ty = ty.scalarType(zcu); | 29166 | .signed_int_or_full_vec => |size| ty.isVector(zcu) and size.bitSize(cg.target) >= 8 * ty.abiSize(zcu) and |
| 29078 | return scalar_ty.isAbiInt(zcu) and scalar_ty.intInfo(zcu).signedness == .signed; | 29167 | if (intInfo(ty.childType(zcu), cg)) |int_info| switch (int_info.signedness) { |
| 29079 | }, | 29168 | .signed => true, |
| 29080 | .signed_int_or_full_vec => |size| { | 29169 | .unsigned => int_info.bits >= 8 and std.math.isPowerOfTwo(int_info.bits), |
| 29081 | if (!ty.isVector(zcu) or size.bitSize(cg.target) < 8 * ty.abiSize(zcu)) return false; | 29170 | } else false, |
| 29082 | const scalar_ty = ty.scalarType(zcu); | 29171 | .unsigned_int_vec => |size| ty.isVector(zcu) and size.bitSize(cg.target) >= 8 * ty.abiSize(zcu) and |
| 29083 | if (scalar_ty.isPtrAtRuntime(zcu)) return true; | 29172 | if (intInfo(ty.childType(zcu), cg)) |int_info| int_info.signedness == .unsigned else false, |
| 29084 | if (!scalar_ty.isAbiInt(zcu)) return false; | 29173 | .int_or_vec => |size| if (intInfo(ty, cg)) |int_info| |
| 29085 | const scalar_int_info = scalar_ty.intInfo(zcu); | 29174 | size.bitSize(cg.target) >= int_info.bits |
| 29086 | return switch (scalar_int_info.signedness) { | 29175 | else |
| 29087 | .signed => true, | 29176 | ty.isVector(zcu) and size.bitSize(cg.target) >= 8 * ty.abiSize(zcu), |
| 29088 | .unsigned => scalar_int_info.bits >= 8 and std.math.isPowerOfTwo(scalar_int_info.bits), | 29177 | .exact_remainder_int_or_vec => |of_is| if (intInfo(ty, cg)) |int_info| |
| 29089 | }; | 29178 | of_is.is.bitSize(cg.target) == (int_info.bits - 1) % of_is.of.bitSize(cg.target) + 1 |
| 29090 | }, | 29179 | else |
| 29091 | .unsigned_int_vec => |size| { | 29180 | ty.isVector(zcu) and ty.childType(zcu).toIntern() != .bool_type and |
| 29092 | if (!ty.isVector(zcu) or size.bitSize(cg.target) < ty.bitSize(zcu)) return false; | 29181 | of_is.is.bitSize(cg.target) == (8 * ty.abiSize(zcu) - 1) % of_is.of.bitSize(cg.target) + 1, |
| 29093 | const scalar_ty = ty.scalarType(zcu); | 29182 | .int => |size| if (intInfo(ty, cg)) |int_info| size.bitSize(cg.target) >= int_info.bits else false, |
| 29094 | if (scalar_ty.isPtrAtRuntime(zcu)) return true; | 29183 | .scalar_int => |size| if (intInfo(ty.scalarType(zcu), cg)) |int_info| |
| 29095 | return scalar_ty.isAbiInt(zcu) and scalar_ty.intInfo(zcu).signedness == .unsigned; | 29184 | size.bitSize(cg.target) >= int_info.bits |
| 29096 | }, | 29185 | else |
| 29097 | .int_or_vec => |size| { | 29186 | false, |
| 29098 | if (ty.isVector(zcu)) return ty.scalarType(zcu).toIntern() != .bool_type and | 29187 | .scalar_signed_int => |size| if (intInfo(ty.scalarType(zcu), cg)) |int_info| switch (int_info.signedness) { |
| 29099 | size.bitSize(cg.target) >= 8 * ty.abiSize(zcu); | 29188 | .signed => size.bitSize(cg.target) >= int_info.bits, |
| 29100 | if (ty.toIntern() == .bool_type) return true; | 29189 | .unsigned => false, |
| 29101 | if (ty.isPtrAtRuntime(zcu)) return size.bitSize(cg.target) >= cg.target.ptrBitWidth(); | 29190 | } else false, |
| 29102 | return ty.isAbiInt(zcu) and size.bitSize(cg.target) >= ty.intInfo(zcu).bits; | 29191 | .scalar_unsigned_int => |size| if (intInfo(ty.scalarType(zcu), cg)) |int_info| switch (int_info.signedness) { |
| 29103 | }, | 29192 | .signed => false, |
| 29104 | .exact_remainder_int_or_vec => |of_is| { | 29193 | .unsigned => size.bitSize(cg.target) >= int_info.bits, |
| 29105 | if (ty.isVector(zcu)) return ty.scalarType(zcu).toIntern() != .bool_type and | 29194 | } else false, |
| 29106 | of_is.is.bitSize(cg.target) == (8 * ty.abiSize(zcu) - 1) % of_is.of.bitSize(cg.target) + 1; | 29195 | .scalar_remainder_int => |of_is| if (intInfo(ty.scalarType(zcu), cg)) |int_info| |
| 29107 | if (ty.isPtrAtRuntime(zcu)) | 29196 | of_is.is.bitSize(cg.target) >= (int_info.bits - 1) % of_is.of.bitSize(cg.target) + 1 |
| 29108 | return of_is.is.bitSize(cg.target) == (cg.target.ptrBitWidth() - 1) % of_is.of.bitSize(cg.target) + 1; | 29197 | else |
| 29109 | if (!ty.isAbiInt(zcu)) return false; | 29198 | false, |
| 29110 | return of_is.is.bitSize(cg.target) == (ty.intInfo(zcu).bits - 1) % of_is.of.bitSize(cg.target) + 1; | 29199 | .exact_int => |bit_size| if (intInfo(ty, cg)) |int_info| bit_size == int_info.bits else false, |
| 29111 | }, | 29200 | .exact_signed_int => |bit_size| if (intInfo(ty, cg)) |int_info| switch (int_info.signedness) { |
| 29112 | .int => |size| { | 29201 | .signed => bit_size == int_info.bits, |
| 29113 | if (ty.toIntern() == .bool_type) return true; | 29202 | .unsigned => false, |
| 29114 | if (ty.isPtrAtRuntime(zcu)) return size.bitSize(cg.target) >= cg.target.ptrBitWidth(); | 29203 | } else false, |
| 29115 | return ty.isAbiInt(zcu) and size.bitSize(cg.target) >= ty.intInfo(zcu).bits; | 29204 | .exact_unsigned_int => |bit_size| if (intInfo(ty, cg)) |int_info| switch (int_info.signedness) { |
| 29116 | }, | 29205 | .signed => false, |
| 29117 | .scalar_int => |size| { | 29206 | .unsigned => bit_size == int_info.bits, |
| 29118 | const scalar_ty = ty.scalarType(zcu); | 29207 | } else false, |
| 29119 | if (scalar_ty.isPtrAtRuntime(zcu)) return size.bitSize(cg.target) >= cg.target.ptrBitWidth(); | 29208 | .signed_or_exact_int => |size| if (intInfo(ty, cg)) |int_info| switch (int_info.signedness) { |
| 29120 | return scalar_ty.isAbiInt(zcu) and size.bitSize(cg.target) >= scalar_ty.intInfo(zcu).bits; | 29209 | .signed => size.bitSize(cg.target) >= int_info.bits, |
| 29121 | }, | 29210 | .unsigned => size.bitSize(cg.target) == int_info.bits, |
| 29122 | .scalar_signed_int => |size| { | 29211 | } else false, |
| 29123 | const scalar_ty = ty.scalarType(zcu); | 29212 | .unsigned_or_exact_int => |size| if (intInfo(ty, cg)) |int_info| switch (int_info.signedness) { |
| 29124 | if (!scalar_ty.isAbiInt(zcu)) return false; | 29213 | .signed => size.bitSize(cg.target) == int_info.bits, |
| 29125 | const scalar_int_info = scalar_ty.intInfo(zcu); | 29214 | .unsigned => size.bitSize(cg.target) >= int_info.bits, |
| 29126 | return scalar_int_info.signedness == .signed and size.bitSize(cg.target) >= scalar_int_info.bits; | 29215 | } else false, |
| 29127 | }, | 29216 | .po2_int => |size| if (intInfo(ty, cg)) |int_info| |
| 29128 | .scalar_unsigned_int => |size| { | 29217 | std.math.isPowerOfTwo(int_info.bits) and size.bitSize(cg.target) >= int_info.bits |
| 29129 | const scalar_ty = ty.scalarType(zcu); | 29218 | else |
| 29130 | if (scalar_ty.isPtrAtRuntime(zcu)) return size.bitSize(cg.target) >= cg.target.ptrBitWidth(); | 29219 | false, |
| 29131 | if (!scalar_ty.isAbiInt(zcu)) return false; | 29220 | .signed_po2_int => |size| if (intInfo(ty, cg)) |int_info| switch (int_info.signedness) { |
| 29132 | const scalar_int_info = scalar_ty.intInfo(zcu); | 29221 | .signed => std.math.isPowerOfTwo(int_info.bits) and size.bitSize(cg.target) >= int_info.bits, |
| 29133 | return scalar_int_info.signedness == .unsigned and size.bitSize(cg.target) >= scalar_int_info.bits; | 29222 | .unsigned => false, |
| 29134 | }, | 29223 | } else false, |
| 29135 | .scalar_remainder_int => |of_is| { | 29224 | .unsigned_po2_or_exact_int => |size| if (intInfo(ty, cg)) |int_info| switch (int_info.signedness) { |
| 29136 | const scalar_ty = ty.scalarType(zcu); | 29225 | .signed => size.bitSize(cg.target) == int_info.bits, |
| 29137 | if (scalar_ty.isPtrAtRuntime(zcu)) | 29226 | .unsigned => std.math.isPowerOfTwo(int_info.bits) and size.bitSize(cg.target) >= int_info.bits, |
| 29138 | return of_is.is.bitSize(cg.target) >= (cg.target.ptrBitWidth() - 1) % of_is.of.bitSize(cg.target) + 1; | 29227 | } else false, |
| 29139 | if (!scalar_ty.isAbiInt(zcu)) return false; | 29228 | .remainder_int => |of_is| if (intInfo(ty, cg)) |int_info| |
| 29140 | return of_is.is.bitSize(cg.target) >= (scalar_ty.intInfo(zcu).bits - 1) % of_is.of.bitSize(cg.target) + 1; | 29229 | of_is.is.bitSize(cg.target) >= (int_info.bits - 1) % of_is.of.bitSize(cg.target) + 1 |
| 29141 | }, | 29230 | else |
| 29142 | .exact_int => |bit_size| { | 29231 | false, |
| 29143 | if (ty.toIntern() == .bool_type) return bit_size == 1; | 29232 | .exact_remainder_int => |of_is| if (intInfo(ty, cg)) |int_info| |
| 29144 | if (ty.isPtrAtRuntime(zcu)) return bit_size == cg.target.ptrBitWidth(); | 29233 | of_is.is.bitSize(cg.target) == (int_info.bits - 1) % of_is.of.bitSize(cg.target) + 1 |
| 29145 | return ty.isAbiInt(zcu) and bit_size == ty.intInfo(zcu).bits; | 29234 | else |
| 29146 | }, | 29235 | false, |
| 29147 | .exact_signed_int => |bit_size| { | 29236 | .signed_or_exact_remainder_int => |of_is| if (intInfo(ty, cg)) |int_info| switch (int_info.signedness) { |
| 29148 | if (!ty.isAbiInt(zcu)) return false; | 29237 | .signed => of_is.is.bitSize(cg.target) >= (int_info.bits - 1) % of_is.of.bitSize(cg.target) + 1, |
| 29149 | const int_info = ty.intInfo(zcu); | 29238 | .unsigned => of_is.is.bitSize(cg.target) == (int_info.bits - 1) % of_is.of.bitSize(cg.target) + 1, |
| 29150 | return int_info.signedness == .signed and bit_size == int_info.bits; | 29239 | } else false, |
| 29151 | }, | 29240 | .unsigned_or_exact_remainder_int => |of_is| if (intInfo(ty, cg)) |int_info| switch (int_info.signedness) { |
| 29152 | .exact_unsigned_int => |bit_size| { | 29241 | .signed => of_is.is.bitSize(cg.target) == (int_info.bits - 1) % of_is.of.bitSize(cg.target) + 1, |
| 29153 | if (ty.toIntern() == .bool_type) return bit_size == 1; | 29242 | .unsigned => of_is.is.bitSize(cg.target) >= (int_info.bits - 1) % of_is.of.bitSize(cg.target) + 1, |
| 29154 | if (ty.isPtrAtRuntime(zcu)) return bit_size == cg.target.ptrBitWidth(); | 29243 | } else false, |
| 29155 | if (!ty.isAbiInt(zcu)) return false; | 29244 | .signed_int => |size| if (intInfo(ty, cg)) |int_info| switch (int_info.signedness) { |
| 29156 | const int_info = ty.intInfo(zcu); | 29245 | .signed => size.bitSize(cg.target) >= int_info.bits, |
| 29157 | return int_info.signedness == .unsigned and bit_size == int_info.bits; | 29246 | .unsigned => false, |
| 29158 | }, | 29247 | } else false, |
| 29159 | .signed_or_exact_int => |size| { | 29248 | .unsigned_int => |size| if (intInfo(ty, cg)) |int_info| switch (int_info.signedness) { |
| 29160 | if (ty.isPtrAtRuntime(zcu)) return size.bitSize(cg.target) == cg.target.ptrBitWidth(); | 29249 | .signed => false, |
| 29161 | if (!ty.isAbiInt(zcu)) return false; | 29250 | .unsigned => size.bitSize(cg.target) >= int_info.bits, |
| 29162 | const int_info = ty.intInfo(zcu); | 29251 | } else false, |
| 29163 | return switch (int_info.signedness) { | 29252 | .elem_size_is => |size| size == ty.elemType2(zcu).abiSize(zcu), |
| 29164 | .signed => size.bitSize(cg.target) >= int_info.bits, | 29253 | .po2_elem_size => std.math.isPowerOfTwo(ty.elemType2(zcu).abiSize(zcu)), |
| 29165 | .unsigned => size.bitSize(cg.target) == int_info.bits, | 29254 | .elem_int => |size| if (intInfo(ty.elemType2(zcu), cg)) |elem_int_info| |
| 29166 | }; | 29255 | size.bitSize(cg.target) >= elem_int_info.bits |
| 29167 | }, | 29256 | else |
| 29168 | .unsigned_or_exact_int => |size| { | 29257 | false, |
| 29169 | if (ty.toIntern() == .bool_type or ty.isPtrAtRuntime(zcu)) return true; | 29258 | }; |
| 29170 | if (!ty.isAbiInt(zcu)) return false; | | |
| 29171 | const int_info = ty.intInfo(zcu); | | |
| 29172 | return switch (int_info.signedness) { | | |
| 29173 | .signed => size.bitSize(cg.target) == int_info.bits, | | |
| 29174 | .unsigned => size.bitSize(cg.target) >= int_info.bits, | | |
| 29175 | }; | | |
| 29176 | }, | | |
| 29177 | .po2_int => |size| { | | |
| 29178 | if (ty.toIntern() == .bool_type) return true; | | |
| 29179 | if (ty.isPtrAtRuntime(zcu)) return size.bitSize(cg.target) >= cg.target.ptrBitWidth(); | | |
| 29180 | if (!ty.isAbiInt(zcu)) return false; | | |
| 29181 | const bit_size = ty.intInfo(zcu).bits; | | |
| 29182 | return std.math.isPowerOfTwo(bit_size) and size.bitSize(cg.target) >= bit_size; | | |
| 29183 | }, | | |
| 29184 | .signed_po2_int => |size| { | | |
| 29185 | if (!ty.isAbiInt(zcu)) return false; | | |
| 29186 | const int_info = ty.intInfo(zcu); | | |
| 29187 | return int_info.signedness == .signed and std.math.isPowerOfTwo(int_info.bits) and | | |
| 29188 | size.bitSize(cg.target) >= int_info.bits; | | |
| 29189 | }, | | |
| 29190 | .unsigned_po2_or_exact_int => |size| { | | |
| 29191 | if (ty.toIntern() == .bool_type) return true; | | |
| 29192 | if (ty.isPtrAtRuntime(zcu)) return size.bitSize(cg.target) >= cg.target.ptrBitWidth(); | | |
| 29193 | if (!ty.isAbiInt(zcu)) return false; | | |
| 29194 | const int_info = ty.intInfo(zcu); | | |
| 29195 | return switch (int_info.signedness) { | | |
| 29196 | .signed => size.bitSize(cg.target) == int_info.bits, | | |
| 29197 | .unsigned => std.math.isPowerOfTwo(int_info.bits) and size.bitSize(cg.target) >= int_info.bits, | | |
| 29198 | }; | | |
| 29199 | }, | | |
| 29200 | .remainder_int => |of_is| { | | |
| 29201 | if (ty.toIntern() == .bool_type) return true; | | |
| 29202 | if (ty.isPtrAtRuntime(zcu)) | | |
| 29203 | return of_is.is.bitSize(cg.target) >= (cg.target.ptrBitWidth() - 1) % of_is.of.bitSize(cg.target) + 1; | | |
| 29204 | if (!ty.isAbiInt(zcu)) return false; | | |
| 29205 | return of_is.is.bitSize(cg.target) >= (ty.intInfo(zcu).bits - 1) % of_is.of.bitSize(cg.target) + 1; | | |
| 29206 | }, | | |
| 29207 | .exact_remainder_int => |of_is| { | | |
| 29208 | if (ty.isPtrAtRuntime(zcu)) | | |
| 29209 | return of_is.is.bitSize(cg.target) == (cg.target.ptrBitWidth() - 1) % of_is.of.bitSize(cg.target) + 1; | | |
| 29210 | if (!ty.isAbiInt(zcu)) return false; | | |
| 29211 | return of_is.is.bitSize(cg.target) == (ty.intInfo(zcu).bits - 1) % of_is.of.bitSize(cg.target) + 1; | | |
| 29212 | }, | | |
| 29213 | .signed_or_exact_remainder_int => |of_is| { | | |
| 29214 | if (ty.isPtrAtRuntime(zcu)) | | |
| 29215 | return of_is.is.bitSize(cg.target) == (cg.target.ptrBitWidth() - 1) % of_is.of.bitSize(cg.target) + 1; | | |
| 29216 | if (!ty.isAbiInt(zcu)) return false; | | |
| 29217 | const int_info = ty.intInfo(zcu); | | |
| 29218 | return switch (int_info.signedness) { | | |
| 29219 | .signed => of_is.is.bitSize(cg.target) >= (int_info.bits - 1) % of_is.of.bitSize(cg.target) + 1, | | |
| 29220 | .unsigned => of_is.is.bitSize(cg.target) == (int_info.bits - 1) % of_is.of.bitSize(cg.target) + 1, | | |
| 29221 | }; | | |
| 29222 | }, | | |
| 29223 | .unsigned_or_exact_remainder_int => |of_is| { | | |
| 29224 | if (ty.toIntern() == .bool_type) return true; | | |
| 29225 | if (ty.isPtrAtRuntime(zcu)) | | |
| 29226 | return of_is.is.bitSize(cg.target) >= (cg.target.ptrBitWidth() - 1) % of_is.of.bitSize(cg.target) + 1; | | |
| 29227 | if (!ty.isAbiInt(zcu)) return false; | | |
| 29228 | const int_info = ty.intInfo(zcu); | | |
| 29229 | return switch (int_info.signedness) { | | |
| 29230 | .signed => of_is.is.bitSize(cg.target) == (int_info.bits - 1) % of_is.of.bitSize(cg.target) + 1, | | |
| 29231 | .unsigned => of_is.is.bitSize(cg.target) >= (int_info.bits - 1) % of_is.of.bitSize(cg.target) + 1, | | |
| 29232 | }; | | |
| 29233 | }, | | |
| 29234 | .signed_int => |size| { | | |
| 29235 | if (!ty.isAbiInt(zcu)) return false; | | |
| 29236 | const int_info = ty.intInfo(zcu); | | |
| 29237 | return int_info.signedness == .signed and size.bitSize(cg.target) >= int_info.bits; | | |
| 29238 | }, | | |
| 29239 | .unsigned_int => |size| { | | |
| 29240 | if (ty.toIntern() == .bool_type) return true; | | |
| 29241 | if (ty.isPtrAtRuntime(zcu)) return size.bitSize(cg.target) >= cg.target.ptrBitWidth(); | | |
| 29242 | if (!ty.isAbiInt(zcu)) return false; | | |
| 29243 | const int_info = ty.intInfo(zcu); | | |
| 29244 | return int_info.signedness == .unsigned and size.bitSize(cg.target) >= int_info.bits; | | |
| 29245 | }, | | |
| 29246 | .elem_size_is => |size| return size == ty.elemType2(zcu).abiSize(zcu), | | |
| 29247 | .po2_elem_size => return std.math.isPowerOfTwo(ty.elemType2(zcu).abiSize(zcu)), | | |
| 29248 | .elem_int => |size| { | | |
| 29249 | const elem_ty = ty.elemType2(zcu); | | |
| 29250 | if (elem_ty.toIntern() == .bool_type) return true; | | |
| 29251 | if (elem_ty.isPtrAtRuntime(zcu)) return size.bitSize(cg.target) >= cg.target.ptrBitWidth(); | | |
| 29252 | return elem_ty.isAbiInt(zcu) and size.bitSize(cg.target) >= elem_ty.intInfo(zcu).bits; | | |
| 29253 | }, | | |
| 29254 | } | | |
| 29255 | } | 29259 | } |
| 29256 | }; | 29260 | }; |
| 29257 | | 29261 | |
| ... | @@ -29431,10 +29435,7 @@ const Select = struct { | ... | @@ -29431,10 +29435,7 @@ const Select = struct { |
| 29431 | }), | 29435 | }), |
| 29432 | }, | 29436 | }, |
| 29433 | else => { | 29437 | else => { |
| 29434 | const scalar_info: InternPool.Key.IntType = if (scalar_ty.isAbiInt(zcu)) | 29438 | const scalar_info = intInfo(scalar_ty, cg).?; |
| 29435 | scalar_ty.intInfo(zcu) | | |
| 29436 | else | | |
| 29437 | .{ .signedness = .unsigned, .bits = @intCast(scalar_ty.bitSize(zcu)) }; | | |
| 29438 | const scalar_int_ty = try pt.intType(scalar_info.signedness, scalar_info.bits); | 29439 | const scalar_int_ty = try pt.intType(scalar_info.signedness, scalar_info.bits); |
| 29439 | if (scalar_info.bits <= 64) { | 29440 | if (scalar_info.bits <= 64) { |
| 29440 | const int_val: i64 = switch (spec.kind) { | 29441 | const int_val: i64 = switch (spec.kind) { |