| ... | ... | @@ -2111,7 +2111,8 @@ const DeclGen = struct { |
| 2111 | 2111 | .bool_and => try self.airBinOpSimple(inst, .OpLogicalAnd), |
| 2112 | 2112 | .bool_or => try self.airBinOpSimple(inst, .OpLogicalOr), |
| 2113 | 2113 | |
| 2114 | | .shl => try self.airShift(inst, .OpShiftLeftLogical), |
| 2114 | .shl, .shl_exact => try self.airShift(inst, .OpShiftLeftLogical, .OpShiftLeftLogical), |
| 2115 | .shr, .shr_exact => try self.airShift(inst, .OpShiftRightLogical, .OpShiftRightArithmetic), |
| 2115 | 2116 | |
| 2116 | 2117 | .min => try self.airMinMax(inst, .lt), |
| 2117 | 2118 | .max => try self.airMinMax(inst, .gt), |
| ... | ... | @@ -2254,28 +2255,42 @@ const DeclGen = struct { |
| 2254 | 2255 | return try self.binOpSimple(ty, lhs_id, rhs_id, opcode); |
| 2255 | 2256 | } |
| 2256 | 2257 | |
| 2257 | | fn airShift(self: *DeclGen, inst: Air.Inst.Index, comptime opcode: Opcode) !?IdRef { |
| 2258 | fn airShift(self: *DeclGen, inst: Air.Inst.Index, comptime unsigned: Opcode, comptime signed: Opcode) !?IdRef { |
| 2258 | 2259 | if (self.liveness.isUnused(inst)) return null; |
| 2260 | const mod = self.module; |
| 2259 | 2261 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 2260 | 2262 | const lhs_id = try self.resolve(bin_op.lhs); |
| 2261 | 2263 | const rhs_id = try self.resolve(bin_op.rhs); |
| 2262 | | const result_type_id = try self.resolveTypeId(self.typeOfIndex(inst)); |
| 2263 | | |
| 2264 | | // the shift and the base must be the same type in SPIR-V, but in Zig the shift is a smaller int. |
| 2265 | | const shift_id = self.spv.allocId(); |
| 2266 | | try self.func.body.emit(self.spv.gpa, .OpUConvert, .{ |
| 2267 | | .id_result_type = result_type_id, |
| 2268 | | .id_result = shift_id, |
| 2269 | | .unsigned_value = rhs_id, |
| 2270 | | }); |
| 2264 | const result_ty = self.typeOfIndex(inst); |
| 2265 | const result_ty_ref = try self.resolveType(result_ty, .direct); |
| 2271 | 2266 | |
| 2272 | 2267 | const result_id = self.spv.allocId(); |
| 2273 | | try self.func.body.emit(self.spv.gpa, opcode, .{ |
| 2274 | | .id_result_type = result_type_id, |
| 2268 | |
| 2269 | // Sometimes Zig doesn't make both of the arguments the same types here. SPIR-V expects that, |
| 2270 | // so just manually upcast it if required. |
| 2271 | const shift_ty_ref = try self.resolveType(self.typeOf(bin_op.rhs), .direct); |
| 2272 | const shift_id = if (shift_ty_ref != result_ty_ref) blk: { |
| 2273 | const shift_id = self.spv.allocId(); |
| 2274 | try self.func.body.emit(self.spv.gpa, .OpUConvert, .{ |
| 2275 | .id_result_type = self.typeId(result_ty_ref), |
| 2276 | .id_result = shift_id, |
| 2277 | .unsigned_value = rhs_id, |
| 2278 | }); |
| 2279 | break :blk shift_id; |
| 2280 | } else rhs_id; |
| 2281 | |
| 2282 | const args = .{ |
| 2283 | .id_result_type = self.typeId(result_ty_ref), |
| 2275 | 2284 | .id_result = result_id, |
| 2276 | 2285 | .base = lhs_id, |
| 2277 | 2286 | .shift = shift_id, |
| 2278 | | }); |
| 2287 | }; |
| 2288 | |
| 2289 | if (result_ty.isSignedInt(mod)) { |
| 2290 | try self.func.body.emit(self.spv.gpa, signed, args); |
| 2291 | } else { |
| 2292 | try self.func.body.emit(self.spv.gpa, unsigned, args); |
| 2293 | } |
| 2279 | 2294 | return result_id; |
| 2280 | 2295 | } |
| 2281 | 2296 | |