@@ -81,7 +81,7 @@ mod c {
8181
8282 use std:: collections:: BTreeMap ;
8383 use std:: env;
84- use std:: path:: PathBuf ;
84+ use std:: path:: { Path , PathBuf } ;
8585
8686 struct Sources {
8787 // SYMBOL -> PATH TO SOURCE
@@ -489,7 +489,20 @@ mod c {
489489 // use of that macro in lib/builtins/int_util.h in compiler-rt.
490490 cfg. flag_if_supported ( & format ! ( "-ffile-prefix-map={}=." , root. display( ) ) ) ;
491491
492+ // Include out-of-line atomics for aarch64, which are all generated by supplying different
493+ // sets of flags to the same source file.
492494 let src_dir = root. join ( "lib/builtins" ) ;
495+ if target_arch == "aarch64" {
496+ let atomics_libs = build_aarch64_out_of_line_atomics_libraries ( & src_dir, cfg) ;
497+ if !atomics_libs. is_empty ( ) {
498+ for library in atomics_libs {
499+ cfg. object ( library) ;
500+ }
501+ // Some run-time CPU feature detection is necessary, as well.
502+ sources. extend ( & [ ( "__aarch64_have_lse_atomics" , "cpu_model.c" ) ] ) ;
503+ }
504+ }
505+
493506 for ( sym, src) in sources. map . iter ( ) {
494507 let src = src_dir. join ( src) ;
495508 cfg. file ( & src) ;
@@ -499,4 +512,55 @@ mod c {
499512
500513 cfg. compile ( "libcompiler-rt.a" ) ;
501514 }
515+
516+ fn build_aarch64_out_of_line_atomics_libraries (
517+ builtins_dir : & Path ,
518+ cfg : & cc:: Build ,
519+ ) -> Vec < PathBuf > {
520+ // NOTE: because we're recompiling the same source file in N different ways, building
521+ // serially is necessary. If we want to lift this restriction, we can either:
522+ // - create symlinks to lse.S and build those_(though we'd still need to pass special
523+ // #define-like flags to each of these), or
524+ // - synthesizing tiny .S files in out/ with the proper #defines, which ultimately #include
525+ // lse.S.
526+ // That said, it's unclear how useful this added complexity will be, so just do the simple
527+ // thing for now.
528+ let outlined_atomics_file = builtins_dir. join ( "aarch64/lse.S" ) ;
529+ println ! ( "cargo:rerun-if-changed={}" , outlined_atomics_file. display( ) ) ;
530+
531+ let out_dir: PathBuf = env:: var ( "OUT_DIR" ) . unwrap ( ) . into ( ) ;
532+
533+ // Ideally, this would be a Vec of object files, but cc doesn't make it *entirely*
534+ // trivial to build an individual object.
535+ let mut atomics_libraries = Vec :: new ( ) ;
536+ for instruction_type in & [ "cas" , "swp" , "ldadd" , "ldclr" , "ldeor" , "ldset" ] {
537+ for size in & [ 1 , 2 , 4 , 8 , 16 ] {
538+ if * size == 16 && * instruction_type != "cas" {
539+ continue ;
540+ }
541+
542+ for ( model_number, model_name) in
543+ & [ ( 1 , "relax" ) , ( 2 , "acq" ) , ( 3 , "rel" ) , ( 4 , "acq_rel" ) ]
544+ {
545+ let library_name = format ! (
546+ "liboutline_atomic_helper_{}{}_{}.a" ,
547+ instruction_type, size, model_name
548+ ) ;
549+ let sym = format ! ( "__aarch64_{}{}_{}" , instruction_type, size, model_name) ;
550+ let mut cfg = cfg. clone ( ) ;
551+
552+ cfg. include ( & builtins_dir)
553+ . define ( & format ! ( "L_{}" , instruction_type) , None )
554+ . define ( "SIZE" , size. to_string ( ) . as_str ( ) )
555+ . define ( "MODEL" , model_number. to_string ( ) . as_str ( ) )
556+ . file ( & outlined_atomics_file) ;
557+ cfg. compile ( & library_name) ;
558+
559+ atomics_libraries. push ( out_dir. join ( library_name) ) ;
560+ println ! ( "cargo:rustc-cfg={}=\" optimized-c\" " , sym) ;
561+ }
562+ }
563+ }
564+ atomics_libraries
565+ }
502566}
0 commit comments