@@ -70,6 +70,13 @@ pub enum SpirvValueKind {
70
70
71
71
#[ derive( Copy , Clone , Debug , Ord , PartialOrd , Eq , PartialEq , Hash ) ]
72
72
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
+
73
80
pub kind : SpirvValueKind ,
74
81
pub ty : Word ,
75
82
}
@@ -103,7 +110,11 @@ impl SpirvValue {
103
110
} else {
104
111
SpirvValueKind :: IllegalConst ( pointee)
105
112
} ;
106
- Some ( SpirvValue { kind, ty } )
113
+ Some ( SpirvValue {
114
+ zombie_waiting_for_span : entry. legal . is_err ( ) ,
115
+ kind,
116
+ ty,
117
+ } )
107
118
}
108
119
_ => None ,
109
120
}
@@ -127,38 +138,7 @@ impl SpirvValue {
127
138
}
128
139
129
140
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 {
162
142
SpirvValueKind :: FnAddr { .. } => {
163
143
cx. builder
164
144
. const_to_id
@@ -171,26 +151,18 @@ impl SpirvValue {
171
151
. val
172
152
}
173
153
174
- SpirvValueKind :: LogicalPtrCast {
154
+ SpirvValueKind :: Def ( id)
155
+ | SpirvValueKind :: IllegalConst ( id)
156
+ | SpirvValueKind :: LogicalPtrCast {
175
157
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) ;
193
164
}
165
+ id
194
166
}
195
167
}
196
168
@@ -201,6 +173,7 @@ pub trait SpirvValueExt {
201
173
impl SpirvValueExt for Word {
202
174
fn with_type ( self , ty : Word ) -> SpirvValue {
203
175
SpirvValue {
176
+ zombie_waiting_for_span : false ,
204
177
kind : SpirvValueKind :: Def ( self ) ,
205
178
ty,
206
179
}
@@ -606,7 +579,11 @@ impl<'tcx> BuilderSpirv<'tcx> {
606
579
} else {
607
580
SpirvValueKind :: IllegalConst ( entry. val )
608
581
} ;
609
- return SpirvValue { kind, ty } ;
582
+ return SpirvValue {
583
+ zombie_waiting_for_span : entry. legal . is_err ( ) ,
584
+ kind,
585
+ ty,
586
+ } ;
610
587
}
611
588
let val = val_with_type. val ;
612
589
@@ -783,6 +760,17 @@ impl<'tcx> BuilderSpirv<'tcx> {
783
760
LeafIllegalConst :: UntypedConstDataFromAlloc ,
784
761
) ) ,
785
762
} ;
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
+
786
774
let val = val. tcx_arena_alloc_slices ( cx) ;
787
775
assert_matches ! (
788
776
self . const_to_id
@@ -802,7 +790,11 @@ impl<'tcx> BuilderSpirv<'tcx> {
802
790
} else {
803
791
SpirvValueKind :: IllegalConst ( id)
804
792
} ;
805
- SpirvValue { kind, ty }
793
+ SpirvValue {
794
+ zombie_waiting_for_span : legal. is_err ( ) ,
795
+ kind,
796
+ ty,
797
+ }
806
798
}
807
799
808
800
pub fn lookup_const_by_id ( & self , id : Word ) -> Option < SpirvConst < ' tcx , ' tcx > > {
0 commit comments