@@ -13,7 +13,7 @@ use rustc_codegen_ssa::traits::*;
1313use  rustc_data_structures:: fx:: FxHashMap ; 
1414use  rustc_middle:: ty:: layout:: TyAndLayout ; 
1515use  rustc_middle:: { bug,  span_bug,  ty:: Instance } ; 
16- use  rustc_span:: { Pos ,  Span } ; 
16+ use  rustc_span:: { sym ,   Pos ,  Span ,   Symbol } ; 
1717use  rustc_target:: abi:: * ; 
1818use  rustc_target:: asm:: * ; 
1919use  tracing:: debug; 
@@ -64,7 +64,7 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
6464                    let  mut  layout = None ; 
6565                    let  ty = if  let  Some ( ref  place)  = place { 
6666                        layout = Some ( & place. layout ) ; 
67-                         llvm_fixup_output_type ( self . cx ,  reg. reg_class ( ) ,  & place. layout ) 
67+                         llvm_fixup_output_type ( self . cx ,  reg. reg_class ( ) ,  & place. layout ,  instance ) 
6868                    }  else  if  matches ! ( 
6969                        reg. reg_class( ) , 
7070                        InlineAsmRegClass :: X86 ( 
@@ -112,7 +112,7 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
112112                        // so we just use the type of the input. 
113113                        & in_value. layout 
114114                    } ; 
115-                     let  ty = llvm_fixup_output_type ( self . cx ,  reg. reg_class ( ) ,  layout) ; 
115+                     let  ty = llvm_fixup_output_type ( self . cx ,  reg. reg_class ( ) ,  layout,  instance ) ; 
116116                    output_types. push ( ty) ; 
117117                    op_idx. insert ( idx,  constraints. len ( ) ) ; 
118118                    let  prefix = if  late {  "="  }  else  {  "=&"  } ; 
@@ -127,8 +127,13 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
127127        for  ( idx,  op)  in  operands. iter ( ) . enumerate ( )  { 
128128            match  * op { 
129129                InlineAsmOperandRef :: In  {  reg,  value }  => { 
130-                     let  llval =
131-                         llvm_fixup_input ( self ,  value. immediate ( ) ,  reg. reg_class ( ) ,  & value. layout ) ; 
130+                     let  llval = llvm_fixup_input ( 
131+                         self , 
132+                         value. immediate ( ) , 
133+                         reg. reg_class ( ) , 
134+                         & value. layout , 
135+                         instance, 
136+                     ) ; 
132137                    inputs. push ( llval) ; 
133138                    op_idx. insert ( idx,  constraints. len ( ) ) ; 
134139                    constraints. push ( reg_to_llvm ( reg,  Some ( & value. layout ) ) ) ; 
@@ -139,6 +144,7 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
139144                        in_value. immediate ( ) , 
140145                        reg. reg_class ( ) , 
141146                        & in_value. layout , 
147+                         instance, 
142148                    ) ; 
143149                    inputs. push ( value) ; 
144150
@@ -341,7 +347,8 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
341347                }  else  { 
342348                    self . extract_value ( result,  op_idx[ & idx]  as  u64 ) 
343349                } ; 
344-                 let  value = llvm_fixup_output ( self ,  value,  reg. reg_class ( ) ,  & place. layout ) ; 
350+                 let  value =
351+                     llvm_fixup_output ( self ,  value,  reg. reg_class ( ) ,  & place. layout ,  instance) ; 
345352                OperandValue :: Immediate ( value) . store ( self ,  place) ; 
346353            } 
347354        } 
@@ -913,12 +920,22 @@ fn llvm_asm_scalar_type<'ll>(cx: &CodegenCx<'ll, '_>, scalar: Scalar) -> &'ll Ty
913920    } 
914921} 
915922
923+ fn  any_target_feature_enabled ( 
924+     cx :  & CodegenCx < ' _ ,  ' _ > , 
925+     instance :  Instance < ' _ > , 
926+     features :  & [ Symbol ] , 
927+ )  -> bool  { 
928+     let  enabled = cx. tcx . asm_target_features ( instance. def_id ( ) ) ; 
929+     features. iter ( ) . any ( |feat| enabled. contains ( feat) ) 
930+ } 
931+ 
916932/// Fix up an input value to work around LLVM bugs. 
917933fn  llvm_fixup_input < ' ll ,  ' tcx > ( 
918934    bx :  & mut  Builder < ' _ ,  ' ll ,  ' tcx > , 
919935    mut  value :  & ' ll  Value , 
920936    reg :  InlineAsmRegClass , 
921937    layout :  & TyAndLayout < ' tcx > , 
938+     instance :  Instance < ' _ > , 
922939)  -> & ' ll  Value  { 
923940    let  dl = & bx. tcx . data_layout ; 
924941    match  ( reg,  layout. abi )  { 
@@ -1029,6 +1046,16 @@ fn llvm_fixup_input<'ll, 'tcx>(
10291046                _ => value, 
10301047            } 
10311048        } 
1049+         ( InlineAsmRegClass :: RiscV ( RiscVInlineAsmRegClass :: freg) ,  Abi :: Scalar ( s) ) 
1050+             if  s. primitive ( )  == Primitive :: Float ( Float :: F16 ) 
1051+                 && !any_target_feature_enabled ( bx,  instance,  & [ sym:: zfhmin,  sym:: zfh] )  =>
1052+         { 
1053+             // Smaller floats are always "NaN-boxed" inside larger floats on RISC-V. 
1054+             let  value = bx. bitcast ( value,  bx. type_i16 ( ) ) ; 
1055+             let  value = bx. zext ( value,  bx. type_i32 ( ) ) ; 
1056+             let  value = bx. or ( value,  bx. const_u32 ( 0xFFFF_0000 ) ) ; 
1057+             bx. bitcast ( value,  bx. type_f32 ( ) ) 
1058+         } 
10321059        _ => value, 
10331060    } 
10341061} 
@@ -1039,6 +1066,7 @@ fn llvm_fixup_output<'ll, 'tcx>(
10391066    mut  value :  & ' ll  Value , 
10401067    reg :  InlineAsmRegClass , 
10411068    layout :  & TyAndLayout < ' tcx > , 
1069+     instance :  Instance < ' _ > , 
10421070)  -> & ' ll  Value  { 
10431071    match  ( reg,  layout. abi )  { 
10441072        ( InlineAsmRegClass :: AArch64 ( AArch64InlineAsmRegClass :: vreg) ,  Abi :: Scalar ( s) )  => { 
@@ -1140,6 +1168,14 @@ fn llvm_fixup_output<'ll, 'tcx>(
11401168                _ => value, 
11411169            } 
11421170        } 
1171+         ( InlineAsmRegClass :: RiscV ( RiscVInlineAsmRegClass :: freg) ,  Abi :: Scalar ( s) ) 
1172+             if  s. primitive ( )  == Primitive :: Float ( Float :: F16 ) 
1173+                 && !any_target_feature_enabled ( bx,  instance,  & [ sym:: zfhmin,  sym:: zfh] )  =>
1174+         { 
1175+             let  value = bx. bitcast ( value,  bx. type_i32 ( ) ) ; 
1176+             let  value = bx. trunc ( value,  bx. type_i16 ( ) ) ; 
1177+             bx. bitcast ( value,  bx. type_f16 ( ) ) 
1178+         } 
11431179        _ => value, 
11441180    } 
11451181} 
@@ -1149,6 +1185,7 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
11491185    cx :  & CodegenCx < ' ll ,  ' tcx > , 
11501186    reg :  InlineAsmRegClass , 
11511187    layout :  & TyAndLayout < ' tcx > , 
1188+     instance :  Instance < ' _ > , 
11521189)  -> & ' ll  Type  { 
11531190    match  ( reg,  layout. abi )  { 
11541191        ( InlineAsmRegClass :: AArch64 ( AArch64InlineAsmRegClass :: vreg) ,  Abi :: Scalar ( s) )  => { 
@@ -1242,6 +1279,12 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
12421279                _ => layout. llvm_type ( cx) , 
12431280            } 
12441281        } 
1282+         ( InlineAsmRegClass :: RiscV ( RiscVInlineAsmRegClass :: freg) ,  Abi :: Scalar ( s) ) 
1283+             if  s. primitive ( )  == Primitive :: Float ( Float :: F16 ) 
1284+                 && !any_target_feature_enabled ( cx,  instance,  & [ sym:: zfhmin,  sym:: zfh] )  =>
1285+         { 
1286+             cx. type_f32 ( ) 
1287+         } 
12451288        _ => layout. llvm_type ( cx) , 
12461289    } 
12471290} 
0 commit comments