@@ -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 } ;
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
}
@@ -919,6 +926,7 @@ fn llvm_fixup_input<'ll, 'tcx>(
919
926
mut value : & ' ll Value ,
920
927
reg : InlineAsmRegClass ,
921
928
layout : & TyAndLayout < ' tcx > ,
929
+ instance : Instance < ' _ > ,
922
930
) -> & ' ll Value {
923
931
let dl = & bx. tcx . data_layout ;
924
932
match ( reg, layout. abi ) {
@@ -1029,6 +1037,16 @@ fn llvm_fixup_input<'ll, 'tcx>(
1029
1037
_ => value,
1030
1038
}
1031
1039
}
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
+ }
1032
1050
_ => value,
1033
1051
}
1034
1052
}
@@ -1039,6 +1057,7 @@ fn llvm_fixup_output<'ll, 'tcx>(
1039
1057
mut value : & ' ll Value ,
1040
1058
reg : InlineAsmRegClass ,
1041
1059
layout : & TyAndLayout < ' tcx > ,
1060
+ instance : Instance < ' _ > ,
1042
1061
) -> & ' ll Value {
1043
1062
match ( reg, layout. abi ) {
1044
1063
( InlineAsmRegClass :: AArch64 ( AArch64InlineAsmRegClass :: vreg) , Abi :: Scalar ( s) ) => {
@@ -1140,6 +1159,14 @@ fn llvm_fixup_output<'ll, 'tcx>(
1140
1159
_ => value,
1141
1160
}
1142
1161
}
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
+ }
1143
1170
_ => value,
1144
1171
}
1145
1172
}
@@ -1149,6 +1176,7 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
1149
1176
cx : & CodegenCx < ' ll , ' tcx > ,
1150
1177
reg : InlineAsmRegClass ,
1151
1178
layout : & TyAndLayout < ' tcx > ,
1179
+ instance : Instance < ' _ > ,
1152
1180
) -> & ' ll Type {
1153
1181
match ( reg, layout. abi ) {
1154
1182
( InlineAsmRegClass :: AArch64 ( AArch64InlineAsmRegClass :: vreg) , Abi :: Scalar ( s) ) => {
@@ -1242,6 +1270,12 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
1242
1270
_ => layout. llvm_type ( cx) ,
1243
1271
}
1244
1272
}
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
+ }
1245
1279
_ => layout. llvm_type ( cx) ,
1246
1280
}
1247
1281
}
0 commit comments