@@ -4,72 +4,13 @@ use gccjit::Function;
44use rustc_attr:: InstructionSetAttr ;
55#[ cfg( feature="master" ) ]
66use rustc_attr:: InlineAttr ;
7- use rustc_codegen_ssa:: target_features:: tied_target_features;
8- use rustc_data_structures:: fx:: FxHashMap ;
97use rustc_middle:: ty;
108#[ cfg( feature="master" ) ]
119use rustc_middle:: middle:: codegen_fn_attrs:: CodegenFnAttrFlags ;
12- use rustc_session:: Session ;
1310use rustc_span:: symbol:: sym;
14- use smallvec:: { smallvec, SmallVec } ;
1511
1612use crate :: { context:: CodegenCx , errors:: TiedTargetFeatures } ;
17-
18- // Given a map from target_features to whether they are enabled or disabled,
19- // ensure only valid combinations are allowed.
20- pub fn check_tied_features ( sess : & Session , features : & FxHashMap < & str , bool > ) -> Option < & ' static [ & ' static str ] > {
21- for tied in tied_target_features ( sess) {
22- // Tied features must be set to the same value, or not set at all
23- let mut tied_iter = tied. iter ( ) ;
24- let enabled = features. get ( tied_iter. next ( ) . unwrap ( ) ) ;
25- if tied_iter. any ( |feature| enabled != features. get ( feature) ) {
26- return Some ( tied) ;
27- }
28- }
29- None
30- }
31-
32- // TODO(antoyo): maybe move to a new module gcc_util.
33- // To find a list of GCC's names, check https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
34- fn to_gcc_features < ' a > ( sess : & Session , s : & ' a str ) -> SmallVec < [ & ' a str ; 2 ] > {
35- let arch = if sess. target . arch == "x86_64" { "x86" } else { & * sess. target . arch } ;
36- match ( arch, s) {
37- ( "x86" , "sse4.2" ) => smallvec ! [ "sse4.2" , "crc32" ] ,
38- ( "x86" , "pclmulqdq" ) => smallvec ! [ "pclmul" ] ,
39- ( "x86" , "rdrand" ) => smallvec ! [ "rdrnd" ] ,
40- ( "x86" , "bmi1" ) => smallvec ! [ "bmi" ] ,
41- ( "x86" , "cmpxchg16b" ) => smallvec ! [ "cx16" ] ,
42- ( "x86" , "avx512vaes" ) => smallvec ! [ "vaes" ] ,
43- ( "x86" , "avx512gfni" ) => smallvec ! [ "gfni" ] ,
44- ( "x86" , "avx512vpclmulqdq" ) => smallvec ! [ "vpclmulqdq" ] ,
45- // NOTE: seems like GCC requires 'avx512bw' for 'avx512vbmi2'.
46- ( "x86" , "avx512vbmi2" ) => smallvec ! [ "avx512vbmi2" , "avx512bw" ] ,
47- // NOTE: seems like GCC requires 'avx512bw' for 'avx512bitalg'.
48- ( "x86" , "avx512bitalg" ) => smallvec ! [ "avx512bitalg" , "avx512bw" ] ,
49- ( "aarch64" , "rcpc2" ) => smallvec ! [ "rcpc-immo" ] ,
50- ( "aarch64" , "dpb" ) => smallvec ! [ "ccpp" ] ,
51- ( "aarch64" , "dpb2" ) => smallvec ! [ "ccdp" ] ,
52- ( "aarch64" , "frintts" ) => smallvec ! [ "fptoint" ] ,
53- ( "aarch64" , "fcma" ) => smallvec ! [ "complxnum" ] ,
54- ( "aarch64" , "pmuv3" ) => smallvec ! [ "perfmon" ] ,
55- ( "aarch64" , "paca" ) => smallvec ! [ "pauth" ] ,
56- ( "aarch64" , "pacg" ) => smallvec ! [ "pauth" ] ,
57- // Rust ties fp and neon together. In LLVM neon implicitly enables fp,
58- // but we manually enable neon when a feature only implicitly enables fp
59- ( "aarch64" , "f32mm" ) => smallvec ! [ "f32mm" , "neon" ] ,
60- ( "aarch64" , "f64mm" ) => smallvec ! [ "f64mm" , "neon" ] ,
61- ( "aarch64" , "fhm" ) => smallvec ! [ "fp16fml" , "neon" ] ,
62- ( "aarch64" , "fp16" ) => smallvec ! [ "fullfp16" , "neon" ] ,
63- ( "aarch64" , "jsconv" ) => smallvec ! [ "jsconv" , "neon" ] ,
64- ( "aarch64" , "sve" ) => smallvec ! [ "sve" , "neon" ] ,
65- ( "aarch64" , "sve2" ) => smallvec ! [ "sve2" , "neon" ] ,
66- ( "aarch64" , "sve2-aes" ) => smallvec ! [ "sve2-aes" , "neon" ] ,
67- ( "aarch64" , "sve2-sm4" ) => smallvec ! [ "sve2-sm4" , "neon" ] ,
68- ( "aarch64" , "sve2-sha3" ) => smallvec ! [ "sve2-sha3" , "neon" ] ,
69- ( "aarch64" , "sve2-bitperm" ) => smallvec ! [ "sve2-bitperm" , "neon" ] ,
70- ( _, s) => smallvec ! [ s] ,
71- }
72- }
13+ use crate :: gcc_util:: { check_tied_features, to_gcc_features} ;
7314
7415/// Get GCC attribute for the provided inline heuristic.
7516#[ cfg( feature="master" ) ]
@@ -153,11 +94,33 @@ pub fn from_fn_attrs<'gcc, 'tcx>(
15394 } ) )
15495 . collect :: < Vec < _ > > ( ) ;
15596
156- // TODO(antoyo): check if we really need global backend features. (Maybe they could be applied
157- // globally?)
97+ // TODO(antoyo): cg_llvm adds global features to each function so that LTO keep them.
98+ // Check if GCC requires the same.
15899 let mut global_features = cx. tcx . global_backend_features ( ( ) ) . iter ( ) . map ( |s| s. as_str ( ) ) ;
159100 function_features. extend ( & mut global_features) ;
160- let target_features = function_features. join ( "," ) ;
101+ let target_features = function_features
102+ . iter ( )
103+ . filter_map ( |feature| {
104+ // FIXME(antoyo): for some reasons, disabling SSE results in the following error when
105+ // compiling Rust for Linux:
106+ // SSE register return with SSE disabled
107+ // TODO(antoyo): support soft-float and retpoline-external-thunk.
108+ if feature. contains ( "soft-float" ) || feature. contains ( "retpoline-external-thunk" ) || * feature == "-sse" {
109+ return None ;
110+ }
111+
112+ if feature. starts_with ( '-' ) {
113+ Some ( format ! ( "no{}" , feature) )
114+ }
115+ else if feature. starts_with ( '+' ) {
116+ Some ( feature[ 1 ..] . to_string ( ) )
117+ }
118+ else {
119+ Some ( feature. to_string ( ) )
120+ }
121+ } )
122+ . collect :: < Vec < _ > > ( )
123+ . join ( "," ) ;
161124 if !target_features. is_empty ( ) {
162125 #[ cfg( feature="master" ) ]
163126 func. add_attribute ( FnAttribute :: Target ( & target_features) ) ;
0 commit comments