Skip to content

Commit 13924a5

Browse files
committed
Always register zombie messages, only at most defer their Spans.
1 parent 377411f commit 13924a5

File tree

4 files changed

+103
-59
lines changed

4 files changed

+103
-59
lines changed

crates/rustc_codegen_spirv/src/builder/builder_methods.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2218,11 +2218,25 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
22182218
);
22192219
// Defer the cast so that it has a chance to be avoided.
22202220
let original_ptr = ptr.def(self);
2221+
let bitcast_result_id = self.emit().bitcast(dest_ty, None, original_ptr).unwrap();
2222+
2223+
self.zombie(
2224+
bitcast_result_id,
2225+
&format!(
2226+
"cannot cast between pointer types\
2227+
\nfrom `{}`\
2228+
\n to `{}`",
2229+
self.debug_type(ptr.ty),
2230+
self.debug_type(dest_ty)
2231+
),
2232+
);
2233+
22212234
SpirvValue {
2235+
zombie_waiting_for_span: false,
22222236
kind: SpirvValueKind::LogicalPtrCast {
22232237
original_ptr,
22242238
original_ptr_ty: ptr.ty,
2225-
bitcast_result_id: self.emit().bitcast(dest_ty, None, original_ptr).unwrap(),
2239+
bitcast_result_id,
22262240
},
22272241
ty: dest_ty,
22282242
}

crates/rustc_codegen_spirv/src/builder_spirv.rs

Lines changed: 45 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,13 @@ pub enum SpirvValueKind {
7070

7171
#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)]
7272
pub struct SpirvValue {
73+
// HACK(eddyb) used to cheaply check whether this is a SPIR-V value ID
74+
// with a "zombie" (deferred error) attached to it, that may need a `Span`
75+
// still (e.g. such as constants, which can't easily take a `Span`).
76+
// FIXME(eddyb) a whole `bool` field is sadly inefficient, but anything
77+
// which may make `SpirvValue` smaller requires far too much impl effort.
78+
pub zombie_waiting_for_span: bool,
79+
7380
pub kind: SpirvValueKind,
7481
pub ty: Word,
7582
}
@@ -103,7 +110,11 @@ impl SpirvValue {
103110
} else {
104111
SpirvValueKind::IllegalConst(pointee)
105112
};
106-
Some(SpirvValue { kind, ty })
113+
Some(SpirvValue {
114+
zombie_waiting_for_span: entry.legal.is_err(),
115+
kind,
116+
ty,
117+
})
107118
}
108119
_ => None,
109120
}
@@ -127,38 +138,7 @@ impl SpirvValue {
127138
}
128139

129140
pub fn def_with_span(self, cx: &CodegenCx<'_>, span: Span) -> Word {
130-
match self.kind {
131-
SpirvValueKind::Def(id) => id,
132-
133-
SpirvValueKind::IllegalConst(id) => {
134-
let entry = &cx.builder.id_to_const.borrow()[&id];
135-
let msg = match entry.legal.unwrap_err() {
136-
IllegalConst::Shallow(cause) => {
137-
if let (
138-
LeafIllegalConst::CompositeContainsPtrTo,
139-
SpirvConst::Composite(_fields),
140-
) = (cause, &entry.val)
141-
{
142-
// FIXME(eddyb) materialize this at runtime, using
143-
// `OpCompositeConstruct` (transitively, i.e. after
144-
// putting every field through `SpirvValue::def`),
145-
// if we have a `Builder` to do that in.
146-
// FIXME(eddyb) this isn't possible right now, as
147-
// the builder would be dynamically "locked" anyway
148-
// (i.e. attempting to do `bx.emit()` would panic).
149-
}
150-
151-
cause.message()
152-
}
153-
154-
IllegalConst::Indirect(cause) => cause.message(),
155-
};
156-
157-
cx.zombie_with_span(id, span, msg);
158-
159-
id
160-
}
161-
141+
let id = match self.kind {
162142
SpirvValueKind::FnAddr { .. } => {
163143
cx.builder
164144
.const_to_id
@@ -171,26 +151,18 @@ impl SpirvValue {
171151
.val
172152
}
173153

174-
SpirvValueKind::LogicalPtrCast {
154+
SpirvValueKind::Def(id)
155+
| SpirvValueKind::IllegalConst(id)
156+
| SpirvValueKind::LogicalPtrCast {
175157
original_ptr: _,
176-
original_ptr_ty,
177-
bitcast_result_id,
178-
} => {
179-
cx.zombie_with_span(
180-
bitcast_result_id,
181-
span,
182-
&format!(
183-
"cannot cast between pointer types\
184-
\nfrom `{}`\
185-
\n to `{}`",
186-
cx.debug_type(original_ptr_ty),
187-
cx.debug_type(self.ty)
188-
),
189-
);
190-
191-
bitcast_result_id
192-
}
158+
original_ptr_ty: _,
159+
bitcast_result_id: id,
160+
} => id,
161+
};
162+
if self.zombie_waiting_for_span {
163+
cx.add_span_to_zombie_if_missing(id, span);
193164
}
165+
id
194166
}
195167
}
196168

@@ -201,6 +173,7 @@ pub trait SpirvValueExt {
201173
impl SpirvValueExt for Word {
202174
fn with_type(self, ty: Word) -> SpirvValue {
203175
SpirvValue {
176+
zombie_waiting_for_span: false,
204177
kind: SpirvValueKind::Def(self),
205178
ty,
206179
}
@@ -606,7 +579,11 @@ impl<'tcx> BuilderSpirv<'tcx> {
606579
} else {
607580
SpirvValueKind::IllegalConst(entry.val)
608581
};
609-
return SpirvValue { kind, ty };
582+
return SpirvValue {
583+
zombie_waiting_for_span: entry.legal.is_err(),
584+
kind,
585+
ty,
586+
};
610587
}
611588
let val = val_with_type.val;
612589

@@ -783,6 +760,17 @@ impl<'tcx> BuilderSpirv<'tcx> {
783760
LeafIllegalConst::UntypedConstDataFromAlloc,
784761
)),
785762
};
763+
764+
// FIXME(eddyb) avoid dragging "const (il)legality" around, as well
765+
// (sadly that does require that `SpirvConst` -> SPIR-V be injective,
766+
// e.g. `OpUndef` can never be used for unrepresentable constants).
767+
if let Err(illegal) = legal {
768+
let msg = match illegal {
769+
IllegalConst::Shallow(cause) | IllegalConst::Indirect(cause) => cause.message(),
770+
};
771+
cx.zombie_no_span(id, msg);
772+
}
773+
786774
let val = val.tcx_arena_alloc_slices(cx);
787775
assert_matches!(
788776
self.const_to_id
@@ -802,7 +790,11 @@ impl<'tcx> BuilderSpirv<'tcx> {
802790
} else {
803791
SpirvValueKind::IllegalConst(id)
804792
};
805-
SpirvValue { kind, ty }
793+
SpirvValue {
794+
zombie_waiting_for_span: legal.is_err(),
795+
kind,
796+
ty,
797+
}
806798
}
807799

808800
pub fn lookup_const_by_id(&self, id: Word) -> Option<SpirvConst<'tcx, 'tcx>> {

crates/rustc_codegen_spirv/src/codegen_cx/mod.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -245,9 +245,9 @@ impl<'tcx> CodegenCx<'tcx> {
245245
/// is stripped from the binary.
246246
///
247247
/// Errors will only be emitted (by `linker::zombies`) for reachable zombies.
248-
pub fn zombie_with_span(&self, word: Word, span: Span, reason: &str) {
248+
pub fn zombie_with_span(&self, id: Word, span: Span, reason: &str) {
249249
self.zombie_decorations.borrow_mut().insert(
250-
word,
250+
id,
251251
(
252252
ZombieDecoration {
253253
// FIXME(eddyb) this could take advantage of `Cow` and use
@@ -258,8 +258,16 @@ impl<'tcx> CodegenCx<'tcx> {
258258
),
259259
);
260260
}
261-
pub fn zombie_no_span(&self, word: Word, reason: &str) {
262-
self.zombie_with_span(word, DUMMY_SP, reason);
261+
pub fn zombie_no_span(&self, id: Word, reason: &str) {
262+
self.zombie_with_span(id, DUMMY_SP, reason);
263+
}
264+
265+
pub fn add_span_to_zombie_if_missing(&self, id: Word, span: Span) {
266+
if span != DUMMY_SP
267+
&& let Some((_, src_loc @ None)) = self.zombie_decorations.borrow_mut().get_mut(&id)
268+
{
269+
*src_loc = SrcLocDecoration::from_rustc_span(span, &self.builder);
270+
}
263271
}
264272

265273
pub fn finalize_module(self) -> Module {
@@ -851,6 +859,7 @@ impl<'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'tcx> {
851859
self.def_constant(ty, SpirvConst::ZombieUndefForFnAddr);
852860

853861
SpirvValue {
862+
zombie_waiting_for_span: false,
854863
kind: SpirvValueKind::FnAddr {
855864
function: function.id,
856865
},

tests/compiletests/ui/dis/ptr_copy.normal.stderr

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ note: called by `main`
2828
error: cannot cast between pointer types
2929
from `*f32`
3030
to `*struct () { }`
31+
--> $CORE_SRC/ptr/mod.rs:625:34
32+
|
33+
625 | src: *const () = src as *const (),
34+
| ^^^^^^^^^^^^^^^^
35+
|
36+
note: used from within `core::ptr::copy::<f32>`
3137
--> $CORE_SRC/ptr/mod.rs:621:9
3238
|
3339
621 | / ub_checks::assert_unsafe_precondition!(
@@ -37,6 +43,29 @@ error: cannot cast between pointer types
3743
631 | | && ub_checks::maybe_is_aligned_and_not_null(dst, align, zero_size)
3844
632 | | );
3945
| |_________^
46+
note: called by `ptr_copy::copy_via_raw_ptr`
47+
--> $DIR/ptr_copy.rs:28:18
48+
|
49+
28 | unsafe { core::ptr::copy(src, dst, 1) }
50+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
51+
note: called by `ptr_copy::main`
52+
--> $DIR/ptr_copy.rs:33:5
53+
|
54+
33 | copy_via_raw_ptr(&i, o);
55+
| ^^^^^^^^^^^^^^^^^^^^^^^
56+
note: called by `main`
57+
--> $DIR/ptr_copy.rs:32:8
58+
|
59+
32 | pub fn main(i: f32, o: &mut f32) {
60+
| ^^^^
61+
62+
error: cannot cast between pointer types
63+
from `*f32`
64+
to `*struct () { }`
65+
--> $CORE_SRC/ptr/mod.rs:626:32
66+
|
67+
626 | dst: *mut () = dst as *mut (),
68+
| ^^^^^^^^^^^^^^
4069
|
4170
note: used from within `core::ptr::copy::<f32>`
4271
--> $CORE_SRC/ptr/mod.rs:621:9
@@ -64,5 +93,5 @@ note: called by `main`
6493
32 | pub fn main(i: f32, o: &mut f32) {
6594
| ^^^^
6695

67-
error: aborting due to 2 previous errors
96+
error: aborting due to 3 previous errors
6897

0 commit comments

Comments
 (0)