Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/Caching.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ cases.

We also take into account in the hash:
* Hash of the compiler binary
* Hash of the assembler binary the compiler hands the compilation off to, and
the version it reports, when there is one: GCC always assembles that way,
clang only with `-fno-integrated-as`
* Programming language
* Flag required to compile for the given language
* File in which to generate dependencies.
Expand Down
47 changes: 47 additions & 0 deletions src/compiler/c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ pub struct ParsedArguments {
pub extra_dist_files: Vec<PathBuf>,
/// Extra files that need to have their contents hashed.
pub extra_hash_files: Vec<PathBuf>,
/// Whether the compiler runs a separate assembler to produce the object file.
pub uses_external_assembler: bool,
/// Whether or not the `-showIncludes` argument is passed on MSVC
pub msvc_show_includes: bool,
/// Whether the compilation is generating profiling or coverage data.
Expand Down Expand Up @@ -177,6 +179,11 @@ pub trait CCompilerImpl: Clone + fmt::Debug + Send + Sync + 'static {
fn plusplus(&self) -> bool;
/// Return the compiler version reported by the compiler executable.
fn version(&self) -> Option<String>;
/// Return the identity of the assembler the compiler would run, when it
/// runs one at all.
fn assembler_digest(&self) -> Option<String> {
None
}
/// Determine whether `arguments` are supported by this compiler.
fn parse_arguments(
&self,
Expand Down Expand Up @@ -379,6 +386,13 @@ where
let start_of_compilation = std::time::SystemTime::now();

let extra_hashes = hash_all(&self.parsed_args.extra_hash_files, &pool.clone()).await?;
// The assembler that turns the compiler's output into the object file is
// as much a part of the result as the compiler itself.
let assembler_digest = if self.parsed_args.uses_external_assembler {
self.compiler.assembler_digest()
} else {
None
};
// Create an argument vector containing both preprocessor and arch args, to
// use in creating a hash key
let mut preprocessor_and_arch_args = self.parsed_args.preprocessor_args.clone();
Expand Down Expand Up @@ -449,6 +463,7 @@ where
self.parsed_args.language,
&preprocessor_and_arch_args,
&extra_hashes,
assembler_digest.as_deref(),
&env_vars,
&absolute_input_path,
self.compiler.plusplus(),
Expand Down Expand Up @@ -627,6 +642,7 @@ where
.with_env_vars(&env_vars)
.with_plusplus(self.compiler.plusplus())
.with_basedirs(storage.basedirs())
.with_assembler_digest(assembler_digest.as_deref())
.compute();

// Cache the preprocessing step
Expand Down Expand Up @@ -1490,6 +1506,7 @@ pub struct HashKeyParams<'a> {
preprocessor_output: &'a [u8],
plusplus: bool,
basedirs: &'a [Vec<u8>],
assembler_digest: Option<&'a str>,
}

impl<'a> HashKeyParams<'a> {
Expand Down Expand Up @@ -1517,6 +1534,7 @@ impl<'a> HashKeyParams<'a> {
env_vars: &[],
plusplus: false,
basedirs: &[],
assembler_digest: None,
}
}

Expand Down Expand Up @@ -1544,6 +1562,12 @@ impl<'a> HashKeyParams<'a> {
self
}

/// Sets the identity of the assembler the compiler will run, if any.
pub fn with_assembler_digest(mut self, assembler_digest: Option<&'a str>) -> Self {
self.assembler_digest = assembler_digest;
self
}

/// Computes the hash key based on the configured parameters.
///
/// If `basedirs` are provided, paths in the preprocessor output will be normalized by
Expand All @@ -1566,6 +1590,9 @@ impl<'a> HashKeyParams<'a> {
for hash in self.extra_hashes {
m.update(hash.as_bytes());
}
if let Some(assembler_digest) = self.assembler_digest {
m.update(assembler_digest.as_bytes());
}

for (var, val) in self.env_vars.iter() {
if CACHED_ENV_VARS.contains(var.as_os_str()) {
Expand Down Expand Up @@ -1607,6 +1634,26 @@ mod test {
assert_neq!(h1, h2);
}

#[test]
fn test_assembler_digest_differs() {
let args = ovec!["a", "b", "c"];
let h1 = HashKeyParams::new("abcd", Language::C, &args, b"hello world").compute();
let h2 = HashKeyParams::new("abcd", Language::C, &args, b"hello world")
.with_assembler_digest(Some("abcd"))
.compute();
let h3 = HashKeyParams::new("abcd", Language::C, &args, b"hello world")
.with_assembler_digest(Some("efgh"))
.compute();
assert_neq!(h1, h2);
assert_neq!(h2, h3);
// Not knowing the assembler must keep the key the compiler alone would give,
// so that caches predating assembler tracking stay usable.
let h4 = HashKeyParams::new("abcd", Language::C, &args, b"hello world")
.with_assembler_digest(None)
.compute();
assert_eq!(h1, h4);
}

#[test]
fn test_header_differs() {
let args = ovec!["a", "b", "c"];
Expand Down
1 change: 1 addition & 0 deletions src/compiler/cicc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ where
unhashed_args,
extra_dist_files: extra_dist_files.clone(),
extra_hash_files: extra_dist_files,
uses_external_assembler: false,
msvc_show_includes: false,
profile_generate: false,
color_mode: ColorMode::Off,
Expand Down
43 changes: 43 additions & 0 deletions src/compiler/clang.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ pub struct Clang {
pub is_appleclang: bool,
/// String from __VERSION__ macro.
pub version: Option<String>,
/// Identity of the assembler used with -fno-integrated-as.
pub assembler_digest: Option<String>,
}

impl Clang {
Expand Down Expand Up @@ -90,6 +92,9 @@ impl CCompilerImpl for Clang {
fn version(&self) -> Option<String> {
self.version.clone()
}
fn assembler_digest(&self) -> Option<String> {
self.assembler_digest.clone()
}
fn parse_arguments(
&self,
arguments: &[OsString],
Expand Down Expand Up @@ -226,6 +231,7 @@ counted_array!(pub static ARGS: [ArgInfo<gcc::ArgData>; _] = [
take_arg!("-fembed-offload-object", PathBuf, Concatenated(b'='), ExtraHashFile),
take_arg!("-fexperimental-assignment-tracking", OsString, Concatenated(b'='), PassThrough),
flag!("-fimplicit-modules", TooHardFlag),
flag!("-fintegrated-as", IntegratedAs),
flag!("-fmemory-profile", TooHardFlag),
take_arg!("-fmemory-profile-use", PathBuf, Concatenated(b'='), ExtraHashFile),
take_arg!("-fmemory-profile=", OsString, Concatenated, TooHard),
Expand All @@ -238,6 +244,7 @@ counted_array!(pub static ARGS: [ArgInfo<gcc::ArgData>; _] = [
take_arg!("-fmodules-user-build-path", OsString, Separated, TooHard),
take_arg!("-fms-secure-hotpatch-functions-file", PathBuf, Concatenated(b'='), ExtraHashFile),
flag!("-fno-color-diagnostics", NoDiagnosticsColorFlag),
flag!("-fno-integrated-as", NoIntegratedAs),
flag!("-fno-pch-timestamp", PassThroughFlag),
flag!("-fno-profile-instr-generate", TooHardFlag),
flag!("-fno-profile-instr-use", TooHardFlag),
Expand Down Expand Up @@ -267,13 +274,15 @@ counted_array!(pub static ARGS: [ArgInfo<gcc::ArgData>; _] = [
take_arg!("-gcc-toolchain", OsString, Separated, PassThrough),
flag!("-gcodeview", PassThroughFlag),
take_arg!("-include-pch", PathBuf, CanBeSeparated, PreprocessorArgumentPath),
flag!("-integrated-as", IntegratedAs),
take_arg!("-ivfsoverlay", PathBuf, CanBeSeparated, PreprocessorArgumentPath),
take_arg!("-load", PathBuf, Separated, ExtraHashFile),
flag!("-mconstructor-aliases", PassThroughFlag),
take_arg!("-mllvm", OsString, Separated, PassThrough),
take_arg!("-mmlir", OsString, Separated, PassThrough),
take_arg!("-module-dependency-dir", OsString, Separated, TooHard),
flag!("-mrelax-all", PassThroughFlag),
flag!("-no-integrated-as", NoIntegratedAs),
flag!("-no-opaque-pointers", PreprocessorArgumentFlag),
// Note: this is ROCm clang specific. Parallelism level shouldn't affect output.
take_arg!("-parallel-jobs", OsString, Concatenated(b'='), Unhashed),
Expand Down Expand Up @@ -327,6 +336,7 @@ mod test {
clangplusplus: false,
is_appleclang: false,
version: None,
assembler_digest: None,
}
.parse_arguments(&arguments, &std::env::current_dir().unwrap(), &[])
}
Expand All @@ -347,6 +357,7 @@ mod test {
clangplusplus: false,
is_appleclang: false,
version: Some("\"Ubuntu Clang 14.0.0\"".to_string()),
assembler_digest: None,
}
.is_minversion(14)
);
Expand All @@ -355,24 +366,28 @@ mod test {
clangplusplus: false,
is_appleclang: false,
version: Some("\"Ubuntu Clang 13.0.0\"".to_string()),
assembler_digest: None,
}
.is_minversion(14)
);
assert!(Clang {
clangplusplus: false,
is_appleclang: false,
version: Some("\"FreeBSD Clang 14.0.5 (https://github.com/llvm/llvm-project.git llvmorg-14.0.5-0-gc12386ae247c)\"".to_string()),
assembler_digest: None,
}.is_minversion(14));
assert!(!Clang {
clangplusplus: false,
is_appleclang: false,
version: Some("\"FreeBSD Clang 13.0.0 (git@github.com:llvm/llvm-project.git llvmorg-13.0.0-0-gd7b669b3a303)\"".to_string()),
assembler_digest: None,
}.is_minversion(14));

assert!(!Clang {
clangplusplus: false,
is_appleclang: true,
version: Some("\"FreeBSD Clang 14.0.5 (https://github.com/llvm/llvm-project.git llvmorg-14.0.5-0-gc12386ae247c)\"".to_string()),
assembler_digest: None,
}.is_minversion(14)); // is_appleclang wins
}

Expand Down Expand Up @@ -775,6 +790,33 @@ mod test {
}
}

#[test]
fn test_parse_arguments_integrated_as() {
assert!(!parses!("-c", "foo.c", "-o", "foo.o").uses_external_assembler);
for flag in ["-fno-integrated-as", "-no-integrated-as"] {
let a = parses!("-c", "foo.c", "-o", "foo.o", flag);
assert!(a.uses_external_assembler);
assert_eq!(ovec![flag], a.common_args);
}
for flag in ["-fintegrated-as", "-integrated-as"] {
let a = parses!("-c", "foo.c", "-o", "foo.o", "-fno-integrated-as", flag);
assert!(!a.uses_external_assembler);
assert_eq!(ovec!["-fno-integrated-as", flag], a.common_args);
}
// We don't track what the flag does when it comes through -Xclang.
assert_eq!(
CompilerArguments::CannotCache("-no-integrated-as", None),
parse_arguments_(stringvec![
"-c",
"foo.c",
"-o",
"foo.o",
"-Xclang",
"-no-integrated-as"
])
);
}

#[test]
fn test_parse_arguments_clangmodules() {
assert_eq!(
Expand Down Expand Up @@ -1604,6 +1646,7 @@ mod test {
unhashed_args: vec![],
extra_dist_files: vec![],
extra_hash_files: vec![],
uses_external_assembler: false,
msvc_show_includes: false,
profile_generate: false,
color_mode: ColorMode::Auto,
Expand Down
Loading
Loading