@@ -81,7 +81,7 @@ mod c {
81
81
82
82
use std:: collections:: BTreeMap ;
83
83
use std:: env;
84
- use std:: path:: PathBuf ;
84
+ use std:: path:: { Path , PathBuf } ;
85
85
86
86
struct Sources {
87
87
// SYMBOL -> PATH TO SOURCE
@@ -489,7 +489,20 @@ mod c {
489
489
// use of that macro in lib/builtins/int_util.h in compiler-rt.
490
490
cfg. flag_if_supported ( & format ! ( "-ffile-prefix-map={}=." , root. display( ) ) ) ;
491
491
492
+ // Include out-of-line atomics for aarch64, which are all generated by supplying different
493
+ // sets of flags to the same source file.
492
494
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
+
493
506
for ( sym, src) in sources. map . iter ( ) {
494
507
let src = src_dir. join ( src) ;
495
508
cfg. file ( & src) ;
@@ -499,4 +512,60 @@ mod c {
499
512
500
513
cfg. compile ( "libcompiler-rt.a" ) ;
501
514
}
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
+
530
+ // A stable release hasn't been made with lse.S yet. Until we pick that up, do nothing.
531
+ if !outlined_atomics_file. exists ( ) {
532
+ return vec ! [ ] ;
533
+ }
534
+
535
+ println ! ( "cargo:rerun-if-changed={}" , outlined_atomics_file. display( ) ) ;
536
+ let out_dir: PathBuf = env:: var ( "OUT_DIR" ) . unwrap ( ) . into ( ) ;
537
+
538
+ // Ideally, this would be a Vec of object files, but cc doesn't make it *entirely*
539
+ // trivial to build an individual object.
540
+ let mut atomics_libraries = Vec :: new ( ) ;
541
+ for instruction_type in & [ "cas" , "cwp" , "ldadd" , "ldclr" , "ldeor" , "ldset" ] {
542
+ for size in & [ 1 , 2 , 4 , 8 , 16 ] {
543
+ if * size == 16 && * instruction_type != "cas" {
544
+ continue ;
545
+ }
546
+
547
+ for ( model_number, model_name) in
548
+ & [ ( 1 , "relax" ) , ( 2 , "acq" ) , ( 3 , "rel" ) , ( 4 , "acq_rel" ) ]
549
+ {
550
+ let library_name = format ! (
551
+ "liboutline_atomic_helper_{}_{}_{}.a" ,
552
+ instruction_type, size, model_name
553
+ ) ;
554
+ let sym = format ! ( "__aarch64_{}{}_{}" , instruction_type, size, model_name) ;
555
+ let mut cfg = cfg. clone ( ) ;
556
+
557
+ cfg. include ( & builtins_dir)
558
+ . define ( & format ! ( "L_{}" , instruction_type) , None )
559
+ . define ( "SIZE" , size. to_string ( ) . as_str ( ) )
560
+ . define ( "MODEL" , model_number. to_string ( ) . as_str ( ) )
561
+ . file ( & outlined_atomics_file) ;
562
+ cfg. compile ( & library_name) ;
563
+
564
+ atomics_libraries. push ( out_dir. join ( library_name) ) ;
565
+ println ! ( "cargo:rustc-cfg={}=\" optimized-c\" " , sym) ;
566
+ }
567
+ }
568
+ }
569
+ atomics_libraries
570
+ }
502
571
}
0 commit comments