Skip to content

Commit

Permalink
Actually generate an OpBitcast for illegal pointercasts.
Browse files Browse the repository at this point in the history
  • Loading branch information
eddyb committed Apr 21, 2023
1 parent 51dec9f commit b5b6511
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 20 deletions.
9 changes: 5 additions & 4 deletions crates/rustc_codegen_spirv/src/builder/builder_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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,
}
Expand Down
16 changes: 9 additions & 7 deletions crates/rustc_codegen_spirv/src/builder_spirv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
},
}

Expand Down Expand Up @@ -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\
Expand All @@ -184,7 +186,7 @@ impl SpirvValue {
),
);

zombie_target_undef
bitcast_result_id
}
}
}
Expand Down
7 changes: 4 additions & 3 deletions crates/rustc_codegen_spirv/src/linker/zombies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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;
Expand Down
12 changes: 6 additions & 6 deletions tests/ui/lang/core/ref/zst_member_ref_arg-broken.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand All @@ -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`
Expand Down

0 comments on commit b5b6511

Please sign in to comment.