瀏覽代碼

Merge pull request #416 from joshtriplett/outline-atomics

Amanieu d'Antras 4 年之前
父節點
當前提交
360dcef317
共有 2 個文件被更改,包括 67 次插入3 次删除
  1. 2 2
      .github/workflows/main.yml
  2. 65 1
      build.rs

+ 2 - 2
.github/workflows/main.yml

@@ -88,8 +88,8 @@ jobs:
     - run: rustup component add llvm-tools-preview
     - name: Download compiler-rt reference sources
       run: |
-        curl -L -o code.tar.gz https://github.com/rust-lang/llvm-project/archive/rustc/10.0-2020-05-05.tar.gz
-        tar xzf code.tar.gz --strip-components 1 llvm-project-rustc-10.0-2020-05-05/compiler-rt
+        curl -L -o code.tar.gz https://github.com/rust-lang/llvm-project/archive/rustc/12.0-2021-04-15.tar.gz
+        tar xzf code.tar.gz --strip-components 1 llvm-project-rustc-12.0-2021-04-15/compiler-rt
         echo RUST_COMPILER_RT_ROOT=./compiler-rt >> $GITHUB_ENV
       shell: bash
 

+ 65 - 1
build.rs

@@ -81,7 +81,7 @@ mod c {
 
     use std::collections::BTreeMap;
     use std::env;
-    use std::path::PathBuf;
+    use std::path::{Path, PathBuf};
 
     struct Sources {
         // SYMBOL -> PATH TO SOURCE
@@ -489,7 +489,20 @@ mod c {
         // use of that macro in lib/builtins/int_util.h in compiler-rt.
         cfg.flag_if_supported(&format!("-ffile-prefix-map={}=.", root.display()));
 
+        // Include out-of-line atomics for aarch64, which are all generated by supplying different
+        // sets of flags to the same source file.
         let src_dir = root.join("lib/builtins");
+        if target_arch == "aarch64" {
+            let atomics_libs = build_aarch64_out_of_line_atomics_libraries(&src_dir, cfg);
+            if !atomics_libs.is_empty() {
+                for library in atomics_libs {
+                    cfg.object(library);
+                }
+                // Some run-time CPU feature detection is necessary, as well.
+                sources.extend(&[("__aarch64_have_lse_atomics", "cpu_model.c")]);
+            }
+        }
+
         for (sym, src) in sources.map.iter() {
             let src = src_dir.join(src);
             cfg.file(&src);
@@ -499,4 +512,55 @@ mod c {
 
         cfg.compile("libcompiler-rt.a");
     }
+
+    fn build_aarch64_out_of_line_atomics_libraries(
+        builtins_dir: &Path,
+        cfg: &cc::Build,
+    ) -> Vec<PathBuf> {
+        // NOTE: because we're recompiling the same source file in N different ways, building
+        // serially is necessary. If we want to lift this restriction, we can either:
+        // - create symlinks to lse.S and build those_(though we'd still need to pass special
+        //   #define-like flags to each of these), or
+        // - synthesizing tiny .S files in out/ with the proper #defines, which ultimately #include
+        //   lse.S.
+        // That said, it's unclear how useful this added complexity will be, so just do the simple
+        // thing for now.
+        let outlined_atomics_file = builtins_dir.join("aarch64/lse.S");
+        println!("cargo:rerun-if-changed={}", outlined_atomics_file.display());
+
+        let out_dir: PathBuf = env::var("OUT_DIR").unwrap().into();
+
+        // Ideally, this would be a Vec of object files, but cc doesn't make it *entirely*
+        // trivial to build an individual object.
+        let mut atomics_libraries = Vec::new();
+        for instruction_type in &["cas", "swp", "ldadd", "ldclr", "ldeor", "ldset"] {
+            for size in &[1, 2, 4, 8, 16] {
+                if *size == 16 && *instruction_type != "cas" {
+                    continue;
+                }
+
+                for (model_number, model_name) in
+                    &[(1, "relax"), (2, "acq"), (3, "rel"), (4, "acq_rel")]
+                {
+                    let library_name = format!(
+                        "liboutline_atomic_helper_{}{}_{}.a",
+                        instruction_type, size, model_name
+                    );
+                    let sym = format!("__aarch64_{}{}_{}", instruction_type, size, model_name);
+                    let mut cfg = cfg.clone();
+
+                    cfg.include(&builtins_dir)
+                        .define(&format!("L_{}", instruction_type), None)
+                        .define("SIZE", size.to_string().as_str())
+                        .define("MODEL", model_number.to_string().as_str())
+                        .file(&outlined_atomics_file);
+                    cfg.compile(&library_name);
+
+                    atomics_libraries.push(out_dir.join(library_name));
+                    println!("cargo:rustc-cfg={}=\"optimized-c\"", sym);
+                }
+            }
+        }
+        atomics_libraries
+    }
 }