@@ -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