@@ -1451,13 +1451,13 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
14511451 return OperandRef :: zero_sized ( place. layout ) ;
14521452 }
14531453
1454- let val = if let Some ( llextra ) = place. llextra {
1455- OperandValue :: Ref ( place. llval , Some ( llextra ) , place . align )
1454+ let val = if place. val . llextra . is_some ( ) {
1455+ OperandValue :: Ref ( place. val )
14561456 } else if self . cx . is_backend_immediate ( place. layout ) {
14571457 let llval = self . load (
14581458 place. layout . spirv_type ( self . span ( ) , self ) ,
1459- place. llval ,
1460- place. align ,
1459+ place. val . llval ,
1460+ place. val . align ,
14611461 ) ;
14621462 OperandValue :: Immediate ( self . to_immediate ( llval, place. layout ) )
14631463 } else if let Abi :: ScalarPair ( a, b) = place. layout . abi {
@@ -1468,9 +1468,9 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
14681468
14691469 let mut load = |i, scalar : Scalar , align| {
14701470 let llptr = if i == 0 {
1471- place. llval
1471+ place. val . llval
14721472 } else {
1473- self . inbounds_ptradd ( place. llval , self . const_usize ( b_offset. bytes ( ) ) )
1473+ self . inbounds_ptradd ( place. val . llval , self . const_usize ( b_offset. bytes ( ) ) )
14741474 } ;
14751475 let load = self . load (
14761476 self . scalar_pair_element_backend_type ( place. layout , i, false ) ,
@@ -1481,11 +1481,11 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
14811481 } ;
14821482
14831483 OperandValue :: Pair (
1484- load ( 0 , a, place. align ) ,
1485- load ( 1 , b, place. align . restrict_for_offset ( b_offset) ) ,
1484+ load ( 0 , a, place. val . align ) ,
1485+ load ( 1 , b, place. val . align . restrict_for_offset ( b_offset) ) ,
14861486 )
14871487 } else {
1488- OperandValue :: Ref ( place. llval , None , place . align )
1488+ OperandValue :: Ref ( place. val )
14891489 } ;
14901490 OperandRef {
14911491 val,
@@ -1501,11 +1501,11 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
15011501 dest : PlaceRef < ' tcx , Self :: Value > ,
15021502 ) {
15031503 let zero = self . const_usize ( 0 ) ;
1504- let start = dest. project_index ( self , zero) . llval ;
1504+ let start = dest. project_index ( self , zero) . val . llval ;
15051505
15061506 let elem_layout = dest. layout . field ( self . cx ( ) , 0 ) ;
15071507 let elem_ty = elem_layout. spirv_type ( self . span ( ) , self ) ;
1508- let align = dest. align . restrict_for_offset ( elem_layout. size ) ;
1508+ let align = dest. val . align . restrict_for_offset ( elem_layout. size ) ;
15091509
15101510 for i in 0 ..count {
15111511 let current = self . inbounds_gep ( elem_ty, start, & [ self . const_usize ( i) ] ) ;
@@ -2834,12 +2834,13 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
28342834 // are decoded to values of this `enum`. For instructions that
28352835 // produce results, the result ID is the first `ID` value.
28362836 #[ derive( Debug ) ]
2837- enum Inst < ' tcx , ID > {
2837+ enum Inst < ID > {
28382838 Bitcast ( ID , ID ) ,
28392839 CompositeExtract ( ID , ID , u32 ) ,
2840- InBoundsAccessChain ( ID , ID , SpirvConst < ' tcx , ' tcx > ) ,
2840+ InBoundsAccessChain ( ID , ID , u32 ) ,
28412841 Store ( ID , ID ) ,
28422842 Load ( ID , ID ) ,
2843+ CopyMemory ( ID , ID ) ,
28432844 Call ( ID , ID , SmallVec < [ ID ; 4 ] > ) ,
28442845
28452846 // HACK(eddyb) this only exists for better error reporting,
@@ -2882,14 +2883,17 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
28822883 match ( inst. class . opcode , inst. result_id , & id_operands[ ..] ) {
28832884 ( Op :: Bitcast , Some ( r) , & [ x] ) => Inst :: Bitcast ( r, x) ,
28842885 ( Op :: InBoundsAccessChain , Some ( r) , & [ p, i] ) => {
2885- Inst :: InBoundsAccessChain (
2886- r,
2887- p,
2888- self . builder . lookup_const_by_id ( i) ?,
2889- )
2886+ if let Some ( SpirvConst :: U32 ( i) ) =
2887+ self . builder . lookup_const_by_id ( i)
2888+ {
2889+ Inst :: InBoundsAccessChain ( r, p, i)
2890+ } else {
2891+ Inst :: Unsupported ( inst. class . opcode )
2892+ }
28902893 }
28912894 ( Op :: Store , None , & [ p, v] ) => Inst :: Store ( p, v) ,
28922895 ( Op :: Load , Some ( r) , & [ p] ) => Inst :: Load ( r, p) ,
2896+ ( Op :: CopyMemory , None , & [ a, b] ) => Inst :: CopyMemory ( a, b) ,
28932897 ( Op :: FunctionCall , Some ( r) , [ f, args @ ..] ) => {
28942898 Inst :: Call ( r, * f, args. iter ( ) . copied ( ) . collect ( ) )
28952899 }
@@ -2989,46 +2993,50 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
29892993 } ;
29902994 require_local_var ( rt_args_array_ptr_id, "[fmt::rt::Argument; N]" ) ?;
29912995
2992- // Each runtime argument has 3 instructions to call one of
2993- // the `fmt::rt::Argument::new_*` functions (and split its
2994- // scalar pair result), and 5 instructions to store it into
2995- // the appropriate slot in the array. The groups of 3 and 5
2996+ // Each runtime argument has 4 instructions to call one of
2997+ // the `fmt::rt::Argument::new_*` functions (and temporarily
2998+ // store its result), and 4 instructions to copy it into
2999+ // the appropriate slot in the array. The groups of 4 and 4
29963000 // instructions, for all runtime args, are each separate.
2997- let stores_to_rt_args_array =
2998- try_rev_take ( rt_args_count * 5 ) . ok_or_else ( || {
3001+ let copies_to_rt_args_array =
3002+ try_rev_take ( rt_args_count * 4 ) . ok_or_else ( || {
29993003 FormatArgsNotRecognized (
3000- "[fmt::rt::Argument; N] stores : ran out of instructions" . into ( ) ,
3004+ "[fmt::rt::Argument; N] copies : ran out of instructions" . into ( ) ,
30013005 )
30023006 } ) ?;
3003- let stores_to_rt_args_array = stores_to_rt_args_array . chunks ( 5 ) ;
3004- let rt_arg_new_calls = try_rev_take ( rt_args_count * 3 ) . ok_or_else ( || {
3007+ let copies_to_rt_args_array = copies_to_rt_args_array . chunks ( 4 ) ;
3008+ let rt_arg_new_calls = try_rev_take ( rt_args_count * 4 ) . ok_or_else ( || {
30053009 FormatArgsNotRecognized (
30063010 "fmt::rt::Argument::new calls: ran out of instructions" . into ( ) ,
30073011 )
30083012 } ) ?;
3009- let rt_arg_new_calls = rt_arg_new_calls. chunks ( 3 ) ;
3013+ let rt_arg_new_calls = rt_arg_new_calls. chunks ( 4 ) ;
30103014
3011- for ( rt_arg_idx, ( rt_arg_new_call_insts, store_to_rt_args_array_insts ) ) in
3012- rt_arg_new_calls. zip ( stores_to_rt_args_array ) . enumerate ( )
3015+ for ( rt_arg_idx, ( rt_arg_new_call_insts, copy_to_rt_args_array_insts ) ) in
3016+ rt_arg_new_calls. zip ( copies_to_rt_args_array ) . enumerate ( )
30133017 {
3014- let ( a , b ) = match rt_arg_new_call_insts[ ..] {
3018+ let call_ret_slot_ptr = match rt_arg_new_call_insts[ ..] {
30153019 [
30163020 Inst :: Call ( call_ret_id, callee_id, ref call_args) ,
3017- Inst :: CompositeExtract ( a, a_parent_pair, 0 ) ,
3018- Inst :: CompositeExtract ( b, b_parent_pair, 1 ) ,
3019- ] if [ a_parent_pair, b_parent_pair] == [ call_ret_id; 2 ] => self
3020- . fmt_rt_arg_new_fn_ids_to_ty_and_spec
3021- . borrow ( )
3022- . get ( & callee_id)
3023- . and_then ( |& ( ty, spec) | match call_args[ ..] {
3024- [ x] => {
3025- decoded_format_args
3026- . ref_arg_ids_with_ty_and_spec
3027- . push ( ( x, ty, spec) ) ;
3028- Some ( ( a, b) )
3029- }
3030- _ => None ,
3031- } ) ,
3021+ Inst :: InBoundsAccessChain ( tmp_slot_field_ptr, tmp_slot_ptr, 0 ) ,
3022+ Inst :: CompositeExtract ( field, wrapper_newtype, 0 ) ,
3023+ Inst :: Store ( st_dst_ptr, st_val) ,
3024+ ] if wrapper_newtype == call_ret_id
3025+ && ( st_dst_ptr, st_val) == ( tmp_slot_field_ptr, field) =>
3026+ {
3027+ self . fmt_rt_arg_new_fn_ids_to_ty_and_spec
3028+ . borrow ( )
3029+ . get ( & callee_id)
3030+ . and_then ( |& ( ty, spec) | match call_args[ ..] {
3031+ [ x] => {
3032+ decoded_format_args
3033+ . ref_arg_ids_with_ty_and_spec
3034+ . push ( ( x, ty, spec) ) ;
3035+ Some ( tmp_slot_ptr)
3036+ }
3037+ _ => None ,
3038+ } )
3039+ }
30323040 _ => None ,
30333041 }
30343042 . ok_or_else ( || {
@@ -3037,25 +3045,20 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
30373045 ) )
30383046 } ) ?;
30393047
3040- match store_to_rt_args_array_insts [ ..] {
3048+ match copy_to_rt_args_array_insts [ ..] {
30413049 [
3042- Inst :: InBoundsAccessChain (
3043- array_slot_ptr,
3044- array_base_ptr,
3045- SpirvConst :: U32 ( array_idx) ,
3046- ) ,
3047- Inst :: InBoundsAccessChain ( a_ptr, a_base_ptr, SpirvConst :: U32 ( 0 ) ) ,
3048- Inst :: Store ( a_st_dst, a_st_val) ,
3049- Inst :: InBoundsAccessChain ( b_ptr, b_base_ptr, SpirvConst :: U32 ( 1 ) ) ,
3050- Inst :: Store ( b_st_dst, b_st_val) ,
3051- ] if array_base_ptr == rt_args_array_ptr_id
3050+ Inst :: InBoundsAccessChain ( array_slot, array_base, array_idx) ,
3051+ Inst :: InBoundsAccessChain ( dst_field_ptr, dst_base_ptr, 0 ) ,
3052+ Inst :: InBoundsAccessChain ( src_field_ptr, src_base_ptr, 0 ) ,
3053+ Inst :: CopyMemory ( copy_dst, copy_src) ,
3054+ ] if array_base == rt_args_array_ptr_id
30523055 && array_idx as usize == rt_arg_idx
3053- && [ a_base_ptr , b_base_ptr ] == [ array_slot_ptr ; 2 ]
3054- && ( a , b ) == ( a_st_val , b_st_val )
3055- && ( a_ptr , b_ptr ) == ( a_st_dst , b_st_dst ) => { }
3056+ && dst_base_ptr == array_slot
3057+ && src_base_ptr == call_ret_slot_ptr
3058+ && ( copy_dst , copy_src ) == ( dst_field_ptr , src_field_ptr ) => { }
30563059 _ => {
30573060 return Err ( FormatArgsNotRecognized ( format ! (
3058- "[fmt::rt::Argument; N] stores sequence ({store_to_rt_args_array_insts :?})"
3061+ "[fmt::rt::Argument; N] copies sequence ({copy_to_rt_args_array_insts :?})"
30593062 ) ) ) ;
30603063 }
30613064 }
0 commit comments