@@ -6,8 +6,8 @@ use crate::custom_insts::CustomOp;
66use crate :: spirv_type:: SpirvType ;
77use either:: Either ;
88use itertools:: Itertools ;
9- use rspirv:: dr:: Operand ;
10- use rspirv:: spirv:: { Op , Word } ;
9+ use rspirv:: dr:: { InsertPoint , Instruction , Operand } ;
10+ use rspirv:: spirv:: { Op , StorageClass , Word } ;
1111use rustc_abi:: { Align , BackendRepr } ;
1212use rustc_data_structures:: fx:: FxHashSet ;
1313use rustc_middle:: ty:: Ty ;
@@ -236,11 +236,37 @@ impl<'tcx> DecodedFormatArgs<'tcx> {
236236 }
237237 } ;
238238 let mut spill_value_to_local = |value : SpirvValue | {
239- let size = builder
240- . lookup_type ( value. ty )
241- . sizeof ( builder)
242- . expect ( "panic argument should have a sized type" ) ;
243- let ptr = builder. alloca ( size, Align :: ONE ) ;
239+ let ptr_ty = builder. type_ptr_to ( value. ty ) ;
240+
241+ let ptr = {
242+ // `OpVariable`s in functions must be inserted at the start of the
243+ // first block, before any non-`OpVariable` instruction.
244+ let mut emit = builder. emit ( ) ;
245+ emit. select_block ( Some ( 0 ) ) . unwrap ( ) ;
246+ let index = {
247+ let block = & emit. module_ref ( ) . functions [ emit. selected_function ( ) . unwrap ( ) ]
248+ . blocks [ emit. selected_block ( ) . unwrap ( ) ] ;
249+ block
250+ . instructions
251+ . iter ( )
252+ . enumerate ( )
253+ . find_map ( |( index, inst) | {
254+ ( inst. class . opcode != Op :: Variable )
255+ . then_some ( InsertPoint :: FromBegin ( index) )
256+ } )
257+ . unwrap_or ( InsertPoint :: End )
258+ } ;
259+ let result_id = emit. id ( ) ;
260+ let inst = Instruction :: new (
261+ Op :: Variable ,
262+ Some ( ptr_ty) ,
263+ Some ( result_id) ,
264+ vec ! [ Operand :: StorageClass ( StorageClass :: Function ) ] ,
265+ ) ;
266+ emit. insert_into_block ( index, inst) . unwrap ( ) ;
267+ result_id. with_type ( ptr_ty)
268+ } ;
269+
244270 builder. store ( value, ptr, Align :: ONE ) ;
245271 match ptr. kind {
246272 SpirvValueKind :: Def ( id) => Some ( id) ,
0 commit comments