Merge pull request #416 from joshtriplett/outline-atomics

This commit is contained in:
Amanieu d'Antras 2021-04-30 20:40:17 +01:00 committed by GitHub
commit 8c8e485957
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 67 additions and 3 deletions

View file

@ -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

View file

@ -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
}
}