@@ -70,6 +70,13 @@ pub enum SpirvValueKind {
7070
7171#[ derive( Copy , Clone , Debug , Ord , PartialOrd , Eq , PartialEq , Hash ) ]
7272pub 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- \n from `{}`\
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 {
201173impl 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 > > {
0 commit comments