@@ -13,7 +13,7 @@ use rustc_codegen_ssa::traits::*;
13
13
use rustc_data_structures:: fx:: FxHashMap ;
14
14
use rustc_middle:: ty:: layout:: TyAndLayout ;
15
15
use rustc_middle:: { bug, span_bug, ty:: Instance } ;
16
- use rustc_span:: { Pos , Span } ;
16
+ use rustc_span:: { sym , Pos , Span , Symbol } ;
17
17
use rustc_target:: abi:: * ;
18
18
use rustc_target:: asm:: * ;
19
19
use tracing:: debug;
@@ -64,7 +64,7 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
64
64
let mut layout = None ;
65
65
let ty = if let Some ( ref place) = place {
66
66
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 )
68
68
} else if matches ! (
69
69
reg. reg_class( ) ,
70
70
InlineAsmRegClass :: X86 (
@@ -112,7 +112,7 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
112
112
// so we just use the type of the input.
113
113
& in_value. layout
114
114
} ;
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 ) ;
116
116
output_types. push ( ty) ;
117
117
op_idx. insert ( idx, constraints. len ( ) ) ;
118
118
let prefix = if late { "=" } else { "=&" } ;
@@ -127,8 +127,13 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
127
127
for ( idx, op) in operands. iter ( ) . enumerate ( ) {
128
128
match * op {
129
129
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
+ ) ;
132
137
inputs. push ( llval) ;
133
138
op_idx. insert ( idx, constraints. len ( ) ) ;
134
139
constraints. push ( reg_to_llvm ( reg, Some ( & value. layout ) ) ) ;
@@ -139,6 +144,7 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
139
144
in_value. immediate ( ) ,
140
145
reg. reg_class ( ) ,
141
146
& in_value. layout ,
147
+ instance,
142
148
) ;
143
149
inputs. push ( value) ;
144
150
@@ -341,7 +347,8 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
341
347
} else {
342
348
self . extract_value ( result, op_idx[ & idx] as u64 )
343
349
} ;
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) ;
345
352
OperandValue :: Immediate ( value) . store ( self , place) ;
346
353
}
347
354
}
@@ -913,12 +920,22 @@ fn llvm_asm_scalar_type<'ll>(cx: &CodegenCx<'ll, '_>, scalar: Scalar) -> &'ll Ty
913
920
}
914
921
}
915
922
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
+
916
932
/// Fix up an input value to work around LLVM bugs.
917
933
fn llvm_fixup_input < ' ll , ' tcx > (
918
934
bx : & mut Builder < ' _ , ' ll , ' tcx > ,
919
935
mut value : & ' ll Value ,
920
936
reg : InlineAsmRegClass ,
921
937
layout : & TyAndLayout < ' tcx > ,
938
+ instance : Instance < ' _ > ,
922
939
) -> & ' ll Value {
923
940
let dl = & bx. tcx . data_layout ;
924
941
match ( reg, layout. abi ) {
@@ -1029,6 +1046,16 @@ fn llvm_fixup_input<'ll, 'tcx>(
1029
1046
_ => value,
1030
1047
}
1031
1048
}
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
+ }
1032
1059
_ => value,
1033
1060
}
1034
1061
}
@@ -1039,6 +1066,7 @@ fn llvm_fixup_output<'ll, 'tcx>(
1039
1066
mut value : & ' ll Value ,
1040
1067
reg : InlineAsmRegClass ,
1041
1068
layout : & TyAndLayout < ' tcx > ,
1069
+ instance : Instance < ' _ > ,
1042
1070
) -> & ' ll Value {
1043
1071
match ( reg, layout. abi ) {
1044
1072
( InlineAsmRegClass :: AArch64 ( AArch64InlineAsmRegClass :: vreg) , Abi :: Scalar ( s) ) => {
@@ -1140,6 +1168,14 @@ fn llvm_fixup_output<'ll, 'tcx>(
1140
1168
_ => value,
1141
1169
}
1142
1170
}
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
+ }
1143
1179
_ => value,
1144
1180
}
1145
1181
}
@@ -1149,6 +1185,7 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
1149
1185
cx : & CodegenCx < ' ll , ' tcx > ,
1150
1186
reg : InlineAsmRegClass ,
1151
1187
layout : & TyAndLayout < ' tcx > ,
1188
+ instance : Instance < ' _ > ,
1152
1189
) -> & ' ll Type {
1153
1190
match ( reg, layout. abi ) {
1154
1191
( InlineAsmRegClass :: AArch64 ( AArch64InlineAsmRegClass :: vreg) , Abi :: Scalar ( s) ) => {
@@ -1242,6 +1279,12 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
1242
1279
_ => layout. llvm_type ( cx) ,
1243
1280
}
1244
1281
}
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
+ }
1245
1288
_ => layout. llvm_type ( cx) ,
1246
1289
}
1247
1290
}
0 commit comments