Actually generate an OpBitcast for illegal pointercasts.

This commit is contained in:
Eduard-Mihai Burtescu 2023-04-21 19:56:05 +03:00 committed by Eduard-Mihai Burtescu
parent 51dec9f339
commit b5b651103d
4 changed files with 24 additions and 20 deletions

View File

@ -1267,7 +1267,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
if let SpirvValueKind::LogicalPtrCast {
original_ptr,
original_pointee_ty,
zombie_target_undef: _,
bitcast_result_id: _,
} = ptr.kind
{
let offset = match pointee_kind {
@ -1533,7 +1533,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
SpirvValueKind::LogicalPtrCast {
original_ptr,
original_pointee_ty,
zombie_target_undef: _,
bitcast_result_id: _,
} => (
original_ptr.with_type(
SpirvType::Pointer {
@ -1572,11 +1572,12 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
.with_type(dest_ty)
} else {
// Defer the cast so that it has a chance to be avoided.
let original_ptr = val.def(self);
SpirvValue {
kind: SpirvValueKind::LogicalPtrCast {
original_ptr: val.def(self),
original_ptr,
original_pointee_ty: val_pointee,
zombie_target_undef: self.undef(dest_ty).def(self),
bitcast_result_id: self.emit().bitcast(dest_ty, None, original_ptr).unwrap(),
},
ty: dest_ty,
}

View File

@ -59,10 +59,12 @@ pub enum SpirvValueKind {
/// Pointee type of `original_ptr`.
original_pointee_ty: Word,
/// `OpUndef` of the right target pointer type, to attach zombies to.
// FIXME(eddyb) we should be using a real `OpBitcast` here, but we can't
// emit that on the fly during `SpirvValue::def`, due to builder locking.
zombie_target_undef: Word,
/// Result ID for the `OpBitcast` instruction representing the cast,
/// to attach zombies to.
//
// HACK(eddyb) having an `OpBitcast` only works by being DCE'd away,
// or by being replaced with a noop in `qptr::lower`.
bitcast_result_id: Word,
},
}
@ -170,10 +172,10 @@ impl SpirvValue {
SpirvValueKind::LogicalPtrCast {
original_ptr: _,
original_pointee_ty,
zombie_target_undef,
bitcast_result_id,
} => {
cx.zombie_with_span(
zombie_target_undef,
bitcast_result_id,
span,
&format!(
"cannot cast between pointer types\
@ -184,7 +186,7 @@ impl SpirvValue {
),
);
zombie_target_undef
bitcast_result_id
}
}
}

View File

@ -102,8 +102,9 @@ impl Zombies {
// No need to zombie defs within a function: If any def within a function is zombied, then the
// whole function is zombied. But, we don't have to mark the defs within a function as zombie,
// because the defs can't escape the function.
// HACK(eddyb) one exception to this is function-local variables, which may
// be unused and as such cannot be allowed to always zombie the function.
// HACK(eddyb) one exception to this is function-local variables, or the
// `OpBitcast`s of pointer casts, either of which which may actually be
// unused and as such cannot be allowed to always zombie the function.
for func in &module.functions {
let func_id = func.def_id().unwrap();
if self.id_to_zombie_kind.contains_key(&func_id) {
@ -126,7 +127,7 @@ impl Zombies {
_ => {}
}
if inst.class.opcode == Op::Variable {
if [Op::Variable, Op::Bitcast].contains(&inst.class.opcode) {
let result_id = inst.result_id.unwrap();
if self.id_to_zombie_kind.contains_key(&result_id) {
continue;

View File

@ -18,11 +18,11 @@ note: called by `main_scalar_scalar_pair_nested`
| ^
error: cannot cast between pointer types
from `*struct (usize, usize) { u32, u32 }`
from `*u32`
to `*struct B { }`
--> $DIR/zst_member_ref_arg-broken.rs:33:5
--> $DIR/zst_member_ref_arg-broken.rs:23:5
|
33 | f(&s.y);
23 | f(&s.y);
| ^
|
note: used from within `zst_member_ref_arg_broken::main_scalar`
@ -37,11 +37,11 @@ note: called by `main_scalar`
| ^
error: cannot cast between pointer types
from `*struct (usize, usize) { u32, u32 }`
from `*struct S<usize, usize> { u32, u32 }`
to `*struct B { }`
--> $DIR/zst_member_ref_arg-broken.rs:33:5
--> $DIR/zst_member_ref_arg-broken.rs:28:5
|
33 | f(&s.y);
28 | f(&s.y);
| ^
|
note: used from within `zst_member_ref_arg_broken::main_scalar_pair`