@@ -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 } ;
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 }
@@ -919,6 +926,7 @@ fn llvm_fixup_input<'ll, 'tcx>(
919926 mut value : & ' ll Value ,
920927 reg : InlineAsmRegClass ,
921928 layout : & TyAndLayout < ' tcx > ,
929+ instance : Instance < ' _ > ,
922930) -> & ' ll Value {
923931 let dl = & bx. tcx . data_layout ;
924932 match ( reg, layout. abi ) {
@@ -1029,6 +1037,16 @@ fn llvm_fixup_input<'ll, 'tcx>(
10291037 _ => value,
10301038 }
10311039 }
1040+ ( InlineAsmRegClass :: RiscV ( RiscVInlineAsmRegClass :: freg) , Abi :: Scalar ( s) )
1041+ if s. primitive ( ) == Primitive :: Float ( Float :: F16 )
1042+ && !bx. tcx . asm_target_features ( instance. def_id ( ) ) . contains ( & sym:: zfhmin) =>
1043+ {
1044+ // Smaller floats are always "NaN-boxed" inside larger floats on RISC-V.
1045+ let value = bx. bitcast ( value, bx. type_i16 ( ) ) ;
1046+ let value = bx. zext ( value, bx. type_i32 ( ) ) ;
1047+ let value = bx. or ( value, bx. const_u32 ( 0xFFFF_0000 ) ) ;
1048+ bx. bitcast ( value, bx. type_f32 ( ) )
1049+ }
10321050 _ => value,
10331051 }
10341052}
@@ -1039,6 +1057,7 @@ fn llvm_fixup_output<'ll, 'tcx>(
10391057 mut value : & ' ll Value ,
10401058 reg : InlineAsmRegClass ,
10411059 layout : & TyAndLayout < ' tcx > ,
1060+ instance : Instance < ' _ > ,
10421061) -> & ' ll Value {
10431062 match ( reg, layout. abi ) {
10441063 ( InlineAsmRegClass :: AArch64 ( AArch64InlineAsmRegClass :: vreg) , Abi :: Scalar ( s) ) => {
@@ -1140,6 +1159,14 @@ fn llvm_fixup_output<'ll, 'tcx>(
11401159 _ => value,
11411160 }
11421161 }
1162+ ( InlineAsmRegClass :: RiscV ( RiscVInlineAsmRegClass :: freg) , Abi :: Scalar ( s) )
1163+ if s. primitive ( ) == Primitive :: Float ( Float :: F16 )
1164+ && !bx. tcx . asm_target_features ( instance. def_id ( ) ) . contains ( & sym:: zfhmin) =>
1165+ {
1166+ let value = bx. bitcast ( value, bx. type_i32 ( ) ) ;
1167+ let value = bx. trunc ( value, bx. type_i16 ( ) ) ;
1168+ bx. bitcast ( value, bx. type_f16 ( ) )
1169+ }
11431170 _ => value,
11441171 }
11451172}
@@ -1149,6 +1176,7 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
11491176 cx : & CodegenCx < ' ll , ' tcx > ,
11501177 reg : InlineAsmRegClass ,
11511178 layout : & TyAndLayout < ' tcx > ,
1179+ instance : Instance < ' _ > ,
11521180) -> & ' ll Type {
11531181 match ( reg, layout. abi ) {
11541182 ( InlineAsmRegClass :: AArch64 ( AArch64InlineAsmRegClass :: vreg) , Abi :: Scalar ( s) ) => {
@@ -1242,6 +1270,12 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
12421270 _ => layout. llvm_type ( cx) ,
12431271 }
12441272 }
1273+ ( InlineAsmRegClass :: RiscV ( RiscVInlineAsmRegClass :: freg) , Abi :: Scalar ( s) )
1274+ if s. primitive ( ) == Primitive :: Float ( Float :: F16 )
1275+ && !cx. tcx . asm_target_features ( instance. def_id ( ) ) . contains ( & sym:: zfhmin) =>
1276+ {
1277+ cx. type_f32 ( )
1278+ }
12451279 _ => layout. llvm_type ( cx) ,
12461280 }
12471281}
0 commit comments