(&mut self, val: Self::Value, dest_ty: Self::Type, is_signed: bool)
| 1553 | } |
| 1554 | |
| 1555 | fn intcast(&mut self, val: Self::Value, dest_ty: Self::Type, is_signed: bool) -> Self::Value { |
| 1556 | if val.ty == dest_ty { |
| 1557 | // I guess? |
| 1558 | return val; |
| 1559 | } |
| 1560 | match (self.lookup_type(val.ty), self.lookup_type(dest_ty)) { |
| 1561 | // sign change |
| 1562 | ( |
| 1563 | SpirvType::Integer(val_width, val_signedness), |
| 1564 | SpirvType::Integer(dest_width, dest_signedness), |
| 1565 | ) if val_width == dest_width && val_signedness != dest_signedness => self |
| 1566 | .emit() |
| 1567 | .bitcast(dest_ty, None, val.def(self)) |
| 1568 | .unwrap() |
| 1569 | .with_type(dest_ty), |
| 1570 | // width change, and optional sign change |
| 1571 | (SpirvType::Integer(_, _), SpirvType::Integer(_, dest_signedness)) => { |
| 1572 | // spir-v spec doesn't seem to say that signedness needs to match the operands, only that the signedness |
| 1573 | // of the destination type must match the instruction's signedness. |
| 1574 | if dest_signedness { |
| 1575 | self.emit().s_convert(dest_ty, None, val.def(self)) |
| 1576 | } else { |
| 1577 | self.emit().u_convert(dest_ty, None, val.def(self)) |
| 1578 | } |
| 1579 | .unwrap() |
| 1580 | .with_type(dest_ty) |
| 1581 | } |
| 1582 | // bools are ints in llvm, so we have to implement this here |
| 1583 | (SpirvType::Bool, SpirvType::Integer(_, _)) => { |
| 1584 | // spir-v doesn't have a direct conversion instruction |
| 1585 | let if_true = self.constant_int(dest_ty, 1); |
| 1586 | let if_false = self.constant_int(dest_ty, 0); |
| 1587 | self.emit() |
| 1588 | .select( |
| 1589 | dest_ty, |
| 1590 | None, |
| 1591 | val.def(self), |
| 1592 | if_true.def(self), |
| 1593 | if_false.def(self), |
| 1594 | ) |
| 1595 | .unwrap() |
| 1596 | .with_type(dest_ty) |
| 1597 | } |
| 1598 | (SpirvType::Integer(_, _), SpirvType::Bool) => { |
| 1599 | // spir-v doesn't have a direct conversion instruction, glslang emits OpINotEqual |
| 1600 | let zero = self.constant_int(val.ty, 0); |
| 1601 | self.emit() |
| 1602 | .i_not_equal(dest_ty, None, val.def(self), zero.def(self)) |
| 1603 | .unwrap() |
| 1604 | .with_type(dest_ty) |
| 1605 | } |
| 1606 | (val_ty, dest_ty_spv) => self.fatal(&format!( |
| 1607 | "TODO: intcast not implemented yet: val={val:?} val.ty={val_ty:?} dest_ty={dest_ty_spv:?} is_signed={is_signed}" |
| 1608 | )), |
| 1609 | } |
| 1610 | } |
| 1611 | |
| 1612 | fn pointercast(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value { |
no test coverage detected