Merge from rustc

This commit is contained in:
The Miri Cronjob Bot 2024-08-17 05:02:50 +00:00
commit dc0faecfcf
196 changed files with 2754 additions and 1531 deletions

View file

@ -36,6 +36,14 @@ macro_rules! check_ci_llvm {
};
}
/// This file is embedded in the overlay directory of the tarball sources. It is
/// useful in scenarios where developers want to see how the tarball sources were
/// generated.
///
/// We also use this file to compare the host's config.toml against the CI rustc builder
/// configuration to detect any incompatible options.
pub(crate) const BUILDER_CONFIG_FILENAME: &str = "builder-config";
#[derive(Clone, Default)]
pub enum DryRun {
/// This isn't a dry run.
@ -47,7 +55,7 @@ pub enum DryRun {
UserSelected,
}
#[derive(Copy, Clone, Default, PartialEq, Eq)]
#[derive(Copy, Clone, Default, Debug, Eq, PartialEq)]
pub enum DebuginfoLevel {
#[default]
None,
@ -117,7 +125,7 @@ impl Display for DebuginfoLevel {
/// 2) MSVC
/// - Self-contained: `-Clinker=<path to rust-lld>`
/// - External: `-Clinker=lld`
#[derive(Default, Copy, Clone)]
#[derive(Copy, Clone, Default, Debug, PartialEq)]
pub enum LldMode {
/// Do not use LLD
#[default]
@ -1203,40 +1211,42 @@ impl Config {
}
}
pub fn parse(flags: Flags) -> Config {
#[cfg(test)]
fn get_toml(_: &Path) -> TomlConfig {
TomlConfig::default()
}
#[cfg(not(test))]
fn get_toml(file: &Path) -> TomlConfig {
let contents =
t!(fs::read_to_string(file), format!("config file {} not found", file.display()));
// Deserialize to Value and then TomlConfig to prevent the Deserialize impl of
// TomlConfig and sub types to be monomorphized 5x by toml.
toml::from_str(&contents)
.and_then(|table: toml::Value| TomlConfig::deserialize(table))
.unwrap_or_else(|err| {
if let Ok(Some(changes)) = toml::from_str(&contents)
.and_then(|table: toml::Value| ChangeIdWrapper::deserialize(table)).map(|change_id| change_id.inner.map(crate::find_recent_config_change_ids))
{
if !changes.is_empty() {
println!(
"WARNING: There have been changes to x.py since you last updated:\n{}",
crate::human_readable_changes(&changes)
);
}
}
eprintln!("failed to parse TOML configuration '{}': {err}", file.display());
exit!(2);
})
}
Self::parse_inner(flags, get_toml)
#[cfg(test)]
fn get_toml(_: &Path) -> Result<TomlConfig, toml::de::Error> {
Ok(TomlConfig::default())
}
pub(crate) fn parse_inner(mut flags: Flags, get_toml: impl Fn(&Path) -> TomlConfig) -> Config {
#[cfg(not(test))]
fn get_toml(file: &Path) -> Result<TomlConfig, toml::de::Error> {
let contents =
t!(fs::read_to_string(file), format!("config file {} not found", file.display()));
// Deserialize to Value and then TomlConfig to prevent the Deserialize impl of
// TomlConfig and sub types to be monomorphized 5x by toml.
toml::from_str(&contents)
.and_then(|table: toml::Value| TomlConfig::deserialize(table))
.inspect_err(|_| {
if let Ok(Some(changes)) = toml::from_str(&contents)
.and_then(|table: toml::Value| ChangeIdWrapper::deserialize(table))
.map(|change_id| change_id.inner.map(crate::find_recent_config_change_ids))
{
if !changes.is_empty() {
println!(
"WARNING: There have been changes to x.py since you last updated:\n{}",
crate::human_readable_changes(&changes)
);
}
}
})
}
pub fn parse(flags: Flags) -> Config {
Self::parse_inner(flags, Self::get_toml)
}
pub(crate) fn parse_inner(
mut flags: Flags,
get_toml: impl Fn(&Path) -> Result<TomlConfig, toml::de::Error>,
) -> Config {
let mut config = Config::default_opts();
// Set flags.
@ -1344,7 +1354,10 @@ impl Config {
} else {
toml_path.clone()
});
get_toml(&toml_path)
get_toml(&toml_path).unwrap_or_else(|e| {
eprintln!("ERROR: Failed to parse '{}': {e}", toml_path.display());
exit!(2);
})
} else {
config.config = None;
TomlConfig::default()
@ -1375,7 +1388,13 @@ impl Config {
include_path.push("bootstrap");
include_path.push("defaults");
include_path.push(format!("config.{include}.toml"));
let included_toml = get_toml(&include_path);
let included_toml = get_toml(&include_path).unwrap_or_else(|e| {
eprintln!(
"ERROR: Failed to parse default config profile at '{}': {e}",
include_path.display()
);
exit!(2);
});
toml.merge(included_toml, ReplaceOpt::IgnoreDuplicate);
}
@ -1591,24 +1610,6 @@ impl Config {
let mut is_user_configured_rust_channel = false;
if let Some(rust) = toml.rust {
if let Some(commit) = config.download_ci_rustc_commit(rust.download_rustc.clone()) {
// Primarily used by CI runners to avoid handling download-rustc incompatible
// options one by one on shell scripts.
let disable_ci_rustc_if_incompatible =
env::var_os("DISABLE_CI_RUSTC_IF_INCOMPATIBLE")
.is_some_and(|s| s == "1" || s == "true");
if let Err(e) = check_incompatible_options_for_ci_rustc(&rust) {
if disable_ci_rustc_if_incompatible {
config.download_rustc_commit = None;
} else {
panic!("{}", e);
}
} else {
config.download_rustc_commit = Some(commit);
}
}
let Rust {
optimize: optimize_toml,
debug: debug_toml,
@ -1656,7 +1657,7 @@ impl Config {
new_symbol_mangling,
profile_generate,
profile_use,
download_rustc: _,
download_rustc,
lto,
validate_mir_opts,
frame_pointers,
@ -1668,6 +1669,8 @@ impl Config {
is_user_configured_rust_channel = channel.is_some();
set(&mut config.channel, channel.clone());
config.download_rustc_commit = config.download_ci_rustc_commit(download_rustc);
debug = debug_toml;
debug_assertions = debug_assertions_toml;
debug_assertions_std = debug_assertions_std_toml;
@ -2345,6 +2348,45 @@ impl Config {
None => None,
Some(commit) => {
self.download_ci_rustc(commit);
if let Some(config_path) = &self.config {
let builder_config_path =
self.out.join(self.build.triple).join("ci-rustc").join(BUILDER_CONFIG_FILENAME);
let ci_config_toml = match Self::get_toml(&builder_config_path) {
Ok(ci_config_toml) => ci_config_toml,
Err(e) if e.to_string().contains("unknown field") => {
println!("WARNING: CI rustc has some fields that are no longer supported in bootstrap; download-rustc will be disabled.");
println!("HELP: Consider rebasing to a newer commit if available.");
return None;
},
Err(e) => {
eprintln!("ERROR: Failed to parse CI rustc config at '{}': {e}", builder_config_path.display());
exit!(2);
},
};
let current_config_toml = Self::get_toml(config_path).unwrap();
// Check the config compatibility
// FIXME: this doesn't cover `--set` flags yet.
let res = check_incompatible_options_for_ci_rustc(
current_config_toml,
ci_config_toml,
);
let disable_ci_rustc_if_incompatible =
env::var_os("DISABLE_CI_RUSTC_IF_INCOMPATIBLE")
.is_some_and(|s| s == "1" || s == "true");
if disable_ci_rustc_if_incompatible && res.is_err() {
println!("WARNING: download-rustc is disabled with `DISABLE_CI_RUSTC_IF_INCOMPATIBLE` env.");
return None;
}
res.unwrap();
}
Some(commit.clone())
}
})
@ -2662,31 +2704,52 @@ impl Config {
}
}
/// Checks the CI rustc incompatible options by destructuring the `Rust` instance
/// and makes sure that no rust options from config.toml are missed.
fn check_incompatible_options_for_ci_rustc(rust: &Rust) -> Result<(), String> {
/// Compares the current Rust options against those in the CI rustc builder and detects any incompatible options.
/// It does this by destructuring the `Rust` instance to make sure every `Rust` field is covered and not missing.
fn check_incompatible_options_for_ci_rustc(
current_config_toml: TomlConfig,
ci_config_toml: TomlConfig,
) -> Result<(), String> {
macro_rules! err {
($name:expr) => {
if $name.is_some() {
return Err(format!(
"ERROR: Setting `rust.{}` is incompatible with `rust.download-rustc`.",
stringify!($name).replace("_", "-")
));
}
($current:expr, $expected:expr) => {
if let Some(current) = &$current {
if Some(current) != $expected.as_ref() {
return Err(format!(
"ERROR: Setting `rust.{}` is incompatible with `rust.download-rustc`. \
Current value: {:?}, Expected value(s): {}{:?}",
stringify!($expected).replace("_", "-"),
$current,
if $expected.is_some() { "None/" } else { "" },
$expected,
));
};
};
};
}
macro_rules! warn {
($name:expr) => {
if $name.is_some() {
println!(
"WARNING: `rust.{}` has no effect with `rust.download-rustc`.",
stringify!($name).replace("_", "-")
);
}
($current:expr, $expected:expr) => {
if let Some(current) = &$current {
if Some(current) != $expected.as_ref() {
println!(
"WARNING: `rust.{}` has no effect with `rust.download-rustc`. \
Current value: {:?}, Expected value(s): {}{:?}",
stringify!($expected).replace("_", "-"),
$current,
if $expected.is_some() { "None/" } else { "" },
$expected,
);
};
};
};
}
let (Some(current_rust_config), Some(ci_rust_config)) =
(current_config_toml.rust, ci_config_toml.rust)
else {
return Ok(());
};
let Rust {
// Following options are the CI rustc incompatible ones.
optimize,
@ -2744,7 +2807,7 @@ fn check_incompatible_options_for_ci_rustc(rust: &Rust) -> Result<(), String> {
download_rustc: _,
validate_mir_opts: _,
frame_pointers: _,
} = rust;
} = ci_rust_config;
// There are two kinds of checks for CI rustc incompatible options:
// 1. Checking an option that may change the compiler behaviour/output.
@ -2752,22 +2815,23 @@ fn check_incompatible_options_for_ci_rustc(rust: &Rust) -> Result<(), String> {
//
// If the option belongs to the first category, we call `err` macro for a hard error;
// otherwise, we just print a warning with `warn` macro.
err!(optimize);
err!(debug_logging);
err!(debuginfo_level_rustc);
err!(default_linker);
err!(rpath);
err!(strip);
err!(stack_protector);
err!(lld_mode);
err!(llvm_tools);
err!(llvm_bitcode_linker);
err!(jemalloc);
err!(lto);
warn!(channel);
warn!(description);
warn!(incremental);
err!(current_rust_config.optimize, optimize);
err!(current_rust_config.debug_logging, debug_logging);
err!(current_rust_config.debuginfo_level_rustc, debuginfo_level_rustc);
err!(current_rust_config.rpath, rpath);
err!(current_rust_config.strip, strip);
err!(current_rust_config.lld_mode, lld_mode);
err!(current_rust_config.llvm_tools, llvm_tools);
err!(current_rust_config.llvm_bitcode_linker, llvm_bitcode_linker);
err!(current_rust_config.jemalloc, jemalloc);
err!(current_rust_config.default_linker, default_linker);
err!(current_rust_config.stack_protector, stack_protector);
err!(current_rust_config.lto, lto);
warn!(current_rust_config.channel, channel);
warn!(current_rust_config.description, description);
warn!(current_rust_config.incremental, incremental);
Ok(())
}

View file

@ -14,7 +14,7 @@ use crate::core::config::{LldMode, Target, TargetSelection, TomlConfig};
fn parse(config: &str) -> Config {
Config::parse_inner(
Flags::parse(&["check".to_string(), "--config=/does/not/exist".to_string()]),
|&_| toml::from_str(&config).unwrap(),
|&_| toml::from_str(&config),
)
}
@ -151,7 +151,6 @@ runner = "x86_64-runner"
"#,
)
.unwrap()
},
);
assert_eq!(config.change_id, Some(1), "setting top-level value");
@ -208,13 +207,13 @@ fn override_toml_duplicate() {
"--set=change-id=1".to_owned(),
"--set=change-id=2".to_owned(),
]),
|&_| toml::from_str("change-id = 0").unwrap(),
|&_| toml::from_str("change-id = 0"),
);
}
#[test]
fn profile_user_dist() {
fn get_toml(file: &Path) -> TomlConfig {
fn get_toml(file: &Path) -> Result<TomlConfig, toml::de::Error> {
let contents =
if file.ends_with("config.toml") || env::var_os("RUST_BOOTSTRAP_CONFIG").is_some() {
"profile = \"user\"".to_owned()
@ -223,9 +222,7 @@ fn profile_user_dist() {
std::fs::read_to_string(file).unwrap()
};
toml::from_str(&contents)
.and_then(|table: toml::Value| TomlConfig::deserialize(table))
.unwrap()
toml::from_str(&contents).and_then(|table: toml::Value| TomlConfig::deserialize(table))
}
Config::parse_inner(Flags::parse(&["check".to_owned()]), get_toml);
}

View file

@ -9,6 +9,7 @@ use std::sync::OnceLock;
use build_helper::ci::CiEnv;
use xz2::bufread::XzDecoder;
use crate::core::config::BUILDER_CONFIG_FILENAME;
use crate::utils::exec::{command, BootstrapCommand};
use crate::utils::helpers::{check_run, exe, hex_encode, move_file, program_out_of_date};
use crate::{t, Config};
@ -273,11 +274,12 @@ impl Config {
let mut tar = tar::Archive::new(decompressor);
let is_ci_rustc = dst.ends_with("ci-rustc");
// `compile::Sysroot` needs to know the contents of the `rustc-dev` tarball to avoid adding
// it to the sysroot unless it was explicitly requested. But parsing the 100 MB tarball is slow.
// Cache the entries when we extract it so we only have to read it once.
let mut recorded_entries =
if dst.ends_with("ci-rustc") { recorded_entries(dst, pattern) } else { None };
let mut recorded_entries = if is_ci_rustc { recorded_entries(dst, pattern) } else { None };
for member in t!(tar.entries()) {
let mut member = t!(member);
@ -287,10 +289,12 @@ impl Config {
continue;
}
let mut short_path = t!(original_path.strip_prefix(directory_prefix));
if !short_path.starts_with(pattern) {
let is_builder_config = short_path.to_str() == Some(BUILDER_CONFIG_FILENAME);
if !(short_path.starts_with(pattern) || (is_ci_rustc && is_builder_config)) {
continue;
}
short_path = t!(short_path.strip_prefix(pattern));
short_path = short_path.strip_prefix(pattern).unwrap_or(short_path);
let dst_path = dst.join(short_path);
self.verbose(|| {
println!("extracting {} to {}", original_path.display(), dst.display())
@ -703,9 +707,7 @@ download-rustc = false
let file_times = fs::FileTimes::new().set_accessed(now).set_modified(now);
let llvm_config = llvm_root.join("bin").join(exe("llvm-config", self.build));
let llvm_config_file = t!(File::options().write(true).open(llvm_config));
t!(llvm_config_file.set_times(file_times));
t!(crate::utils::helpers::set_file_times(llvm_config, file_times));
if self.should_fix_bins_and_dylibs() {
let llvm_lib = llvm_root.join("lib");

View file

@ -37,7 +37,9 @@ use crate::core::builder;
use crate::core::builder::{Builder, Kind};
use crate::core::config::{flags, DryRun, LldMode, LlvmLibunwind, Target, TargetSelection};
use crate::utils::exec::{command, BehaviorOnFailure, BootstrapCommand, CommandOutput, OutputMode};
use crate::utils::helpers::{self, dir_is_empty, exe, libdir, mtime, output, symlink_dir};
use crate::utils::helpers::{
self, dir_is_empty, exe, libdir, mtime, output, set_file_times, symlink_dir,
};
mod core;
mod utils;
@ -1056,11 +1058,29 @@ Executed at: {executed_at}"#,
}
};
let fail = |message: &str| {
let fail = |message: &str, output: CommandOutput| -> ! {
if self.is_verbose() {
println!("{message}");
} else {
println!("Command has failed. Rerun with -v to see more details.");
let (stdout, stderr) = (output.stdout_if_present(), output.stderr_if_present());
// If the command captures output, the user would not see any indication that
// it has failed. In this case, print a more verbose error, since to provide more
// context.
if stdout.is_some() || stderr.is_some() {
if let Some(stdout) =
output.stdout_if_present().take_if(|s| !s.trim().is_empty())
{
println!("STDOUT:\n{stdout}\n");
}
if let Some(stderr) =
output.stderr_if_present().take_if(|s| !s.trim().is_empty())
{
println!("STDERR:\n{stderr}\n");
}
println!("Command {command:?} has failed. Rerun with -v to see more details.");
} else {
println!("Command has failed. Rerun with -v to see more details.");
}
}
exit!(1);
};
@ -1069,14 +1089,14 @@ Executed at: {executed_at}"#,
match command.failure_behavior {
BehaviorOnFailure::DelayFail => {
if self.fail_fast {
fail(&message);
fail(&message, output);
}
let mut failures = self.delayed_failures.borrow_mut();
failures.push(message);
}
BehaviorOnFailure::Exit => {
fail(&message);
fail(&message, output);
}
BehaviorOnFailure::Ignore => {
// If failures are allowed, either the error has been printed already
@ -1774,21 +1794,20 @@ Executed at: {executed_at}"#,
}
}
if let Ok(()) = fs::hard_link(&src, dst) {
// Attempt to "easy copy" by creating a hard link
// (symlinks don't work on windows), but if that fails
// just fall back to a slow `copy` operation.
// Attempt to "easy copy" by creating a hard link (symlinks are priviledged on windows),
// but if that fails just fall back to a slow `copy` operation.
} else {
if let Err(e) = fs::copy(&src, dst) {
panic!("failed to copy `{}` to `{}`: {}", src.display(), dst.display(), e)
}
t!(fs::set_permissions(dst, metadata.permissions()));
// Restore file times because changing permissions on e.g. Linux using `chmod` can cause
// file access time to change.
let file_times = fs::FileTimes::new()
.set_accessed(t!(metadata.accessed()))
.set_modified(t!(metadata.modified()));
let dst_file = t!(fs::File::open(dst));
t!(dst_file.set_times(file_times));
t!(set_file_times(dst, file_times));
}
}

View file

@ -291,6 +291,11 @@ impl CommandOutput {
.expect("Cannot parse process stdout as UTF-8")
}
#[must_use]
pub fn stdout_if_present(&self) -> Option<String> {
self.stdout.as_ref().and_then(|s| String::from_utf8(s.clone()).ok())
}
#[must_use]
pub fn stdout_if_ok(&self) -> Option<String> {
if self.is_success() { Some(self.stdout()) } else { None }
@ -303,6 +308,11 @@ impl CommandOutput {
)
.expect("Cannot parse process stderr as UTF-8")
}
#[must_use]
pub fn stderr_if_present(&self) -> Option<String> {
self.stderr.as_ref().and_then(|s| String::from_utf8(s.clone()).ok())
}
}
impl Default for CommandOutput {

View file

@ -544,3 +544,15 @@ pub fn get_closest_merge_base_commit(
Ok(output_result(git.as_command_mut())?.trim().to_owned())
}
/// Sets the file times for a given file at `path`.
pub fn set_file_times<P: AsRef<Path>>(path: P, times: fs::FileTimes) -> io::Result<()> {
// Windows requires file to be writable to modify file times. But on Linux CI the file does not
// need to be writable to modify file times and might be read-only.
let f = if cfg!(windows) {
fs::File::options().write(true).open(path)?
} else {
fs::File::open(path)?
};
f.set_times(times)
}

View file

@ -3,7 +3,8 @@ use std::io::Write;
use std::path::PathBuf;
use crate::utils::helpers::{
check_cfg_arg, extract_beta_rev, hex_encode, make, program_out_of_date, symlink_dir,
check_cfg_arg, extract_beta_rev, hex_encode, make, program_out_of_date, set_file_times,
symlink_dir,
};
use crate::{Config, Flags};
@ -92,3 +93,25 @@ fn test_symlink_dir() {
#[cfg(not(windows))]
fs::remove_file(link_path).unwrap();
}
#[test]
fn test_set_file_times_sanity_check() {
let config =
Config::parse(Flags::parse(&["check".to_owned(), "--config=/does/not/exist".to_owned()]));
let tempfile = config.tempdir().join(".tmp-file");
{
File::create(&tempfile).unwrap().write_all(b"dummy value").unwrap();
assert!(tempfile.exists());
}
// This might only fail on Windows (if file is default read-only then we try to modify file
// times).
let unix_epoch = std::time::SystemTime::UNIX_EPOCH;
let target_time = fs::FileTimes::new().set_accessed(unix_epoch).set_modified(unix_epoch);
set_file_times(&tempfile, target_time).unwrap();
let found_metadata = fs::metadata(tempfile).unwrap();
assert_eq!(found_metadata.accessed().unwrap(), unix_epoch);
assert_eq!(found_metadata.modified().unwrap(), unix_epoch)
}

View file

@ -9,6 +9,7 @@ use std::path::{Path, PathBuf};
use crate::core::build_steps::dist::distdir;
use crate::core::builder::{Builder, Kind};
use crate::core::config::BUILDER_CONFIG_FILENAME;
use crate::utils::exec::BootstrapCommand;
use crate::utils::helpers::{move_file, t};
use crate::utils::{channel, helpers};
@ -320,7 +321,7 @@ impl<'a> Tarball<'a> {
// Add config file if present.
if let Some(config) = &self.builder.config.config {
self.add_renamed_file(config, &self.overlay_dir, "builder-config");
self.add_renamed_file(config, &self.overlay_dir, BUILDER_CONFIG_FILENAME);
}
for file in self.overlay.legal_and_readme() {

@ -1 +1 @@
Subproject commit 67fa536768013d9d5a13f3a06790521d511ef711
Subproject commit 04bc1396bb857f35b5dda1d773c9571e1f253304

@ -1 +1 @@
Subproject commit 5454de3d12b9ccc6375b629cf7ccda8264640aac
Subproject commit aeeb287d41a0332c210da122bea8e0e91844ab3e

@ -1 +1 @@
Subproject commit 0ebdacadbda8ce2cd8fbf93985e15af61a7ab895
Subproject commit 6ecf95c5f2bfa0e6314dfe282bf775fd1405f7e9

@ -1 +1 @@
Subproject commit 2e191814f163ee1e77e2d6094eee4dd78a289c5b
Subproject commit 62cd0df95061ba0ac886333f5cd7f3012f149da1

@ -1 +1 @@
Subproject commit 89aecb6951b77bc746da73df8c9f2b2ceaad494a
Subproject commit 8f94061936e492159f4f6c09c0f917a7521893ff

@ -1 +1 @@
Subproject commit 0c4d55cb59fe440d1a630e4e5774d043968edb3f
Subproject commit 43d83780db545a1ed6d45773312fc578987e3968

View file

@ -61,6 +61,7 @@
- [mipsisa\*r6\*-unknown-linux-gnu\*](platform-support/mips-release-6.md)
- [nvptx64-nvidia-cuda](platform-support/nvptx64-nvidia-cuda.md)
- [powerpc-unknown-openbsd](platform-support/powerpc-unknown-openbsd.md)
- [powerpc-unknown-linux-muslspe](platform-support/powerpc-unknown-linux-muslspe.md)
- [powerpc64-ibm-aix](platform-support/aix.md)
- [riscv32im-risc0-zkvm-elf](platform-support/riscv32im-risc0-zkvm-elf.md)
- [riscv32imac-unknown-xous-elf](platform-support/riscv32imac-unknown-xous-elf.md)

View file

@ -332,6 +332,7 @@ target | std | host | notes
`msp430-none-elf` | * | | 16-bit MSP430 microcontrollers
`powerpc-unknown-linux-gnuspe` | ✓ | | PowerPC SPE Linux
`powerpc-unknown-linux-musl` | ? | | PowerPC Linux with musl 1.2.3
[`powerpc-unknown-linux-muslspe`](platform-support/powerpc-unknown-linux-muslspe.md) | ? | | PowerPC SPE Linux
[`powerpc-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD 32-bit powerpc systems
[`powerpc-unknown-openbsd`](platform-support/powerpc-unknown-openbsd.md) | * | |
[`powerpc-wrs-vxworks-spe`](platform-support/vxworks.md) | ✓ | |

View file

@ -61,3 +61,8 @@ Currently the `riscv64-linux-android` target requires the following architecture
* `Zba` (address calculation instructions)
* `Zbb` (base instructions)
* `Zbs` (single-bit instructions)
### aarch64-linux-android on Nightly compilers
As soon as `-Zfixed-x18` compiler flag is supplied, the [`ShadowCallStack` sanitizer](https://releases.llvm.org/7.0.1/tools/clang/docs/ShadowCallStack.html)
instrumentation is also made avaiable by supplying the second compiler flag `-Zsanitizer=shadow-call-stack`.

View file

@ -0,0 +1,32 @@
# powerpc-unknown-linux-muslspe
**Tier: 3**
This target is very similar to already existing ones like `powerpc_unknown_linux_musl` and `powerpc_unknown_linux_gnuspe`.
This one has PowerPC SPE support for musl. Unfortunately, the last supported gcc version with PowerPC SPE is 8.4.0.
## Target maintainers
- [@BKPepe](https://github.com/BKPepe)
## Requirements
This target is cross-compiled. There is no support for `std`. There is no
default allocator, but it's possible to use `alloc` by supplying an allocator.
This target generated binaries in the ELF format.
## Building the target
This target was tested and used within the `OpenWrt` build system for CZ.NIC Turris 1.x routers using Freescale P2020.
## Building Rust programs
Rust does not yet ship pre-compiled artifacts for this target. To compile for
this target, you will either need to build Rust with the target enabled (see
"Building the target" above), or build your own copy of `core` by using
`build-std` or similar.
## Testing
This is a cross-compiled target and there is no support to run rustc test suite.

View file

@ -515,6 +515,9 @@ pub fn no_documentation() {}
Note that the third item is the crate root, which in this case is undocumented.
If you want the JSON output to be displayed on `stdout` instead of having a file generated, you can
use `-o -`.
### `-w`/`--output-format`: output format
`--output-format json` emits documentation in the experimental

View file

@ -1,7 +1,7 @@
# `fixed-x18`
This option prevents the compiler from using the x18 register. It is only
supported on aarch64.
supported on `aarch64`.
From the [ABI spec][arm-abi]:
@ -23,6 +23,11 @@ Currently, the `-Zsanitizer=shadow-call-stack` flag is only supported on
platforms that always treat x18 as a reserved register, and the `-Zfixed-x18`
flag is not required to use the sanitizer on such platforms. However, the
sanitizer may be supported on targets where this is not the case in the future.
One way to do so now on Nightly compilers is to explicitly supply this `-Zfixed-x18`
flag with `aarch64` targets, so that the sanitizer is available for instrumentation
on targets like `aarch64-unknown-none`, for instance. However, discretion is still
required to make sure that the runtime support is in place for this sanitizer
to be effective.
It is undefined behavior for `-Zsanitizer=shadow-call-stack` code to call into
code where x18 is a temporary register. On the other hand, when you are *not*

View file

@ -787,6 +787,10 @@ A runtime must be provided by the application or operating system.
See the [Clang ShadowCallStack documentation][clang-scs] for more details.
* `aarch64-unknown-none`
In addition to support from a runtime by the application or operating system, the `-Zfixed-x18` flag is also mandatory.
# ThreadSanitizer
ThreadSanitizer is a data race detection tool. It is supported on the following

View file

@ -286,6 +286,9 @@ pub(crate) struct RenderOptions {
pub(crate) no_emit_shared: bool,
/// If `true`, HTML source code pages won't be generated.
pub(crate) html_no_source: bool,
/// This field is only used for the JSON output. If it's set to true, no file will be created
/// and content will be displayed in stdout directly.
pub(crate) output_to_stdout: bool,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
@ -548,16 +551,17 @@ impl Options {
dcx.fatal("the `--test` flag must be passed to enable `--no-run`");
}
let mut output_to_stdout = false;
let test_builder_wrappers =
matches.opt_strs("test-builder-wrapper").iter().map(PathBuf::from).collect();
let out_dir = matches.opt_str("out-dir").map(|s| PathBuf::from(&s));
let output = matches.opt_str("output").map(|s| PathBuf::from(&s));
let output = match (out_dir, output) {
let output = match (matches.opt_str("out-dir"), matches.opt_str("output")) {
(Some(_), Some(_)) => {
dcx.fatal("cannot use both 'out-dir' and 'output' at once");
}
(Some(out_dir), None) => out_dir,
(None, Some(output)) => output,
(Some(out_dir), None) | (None, Some(out_dir)) => {
output_to_stdout = out_dir == "-";
PathBuf::from(out_dir)
}
(None, None) => PathBuf::from("doc"),
};
@ -818,6 +822,7 @@ impl Options {
call_locations,
no_emit_shared: false,
html_no_source,
output_to_stdout,
};
Some((options, render_options))
}

View file

@ -9,16 +9,19 @@ mod import_finder;
use std::cell::RefCell;
use std::fs::{create_dir_all, File};
use std::io::{BufWriter, Write};
use std::io::{stdout, BufWriter, Write};
use std::path::PathBuf;
use std::rc::Rc;
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def_id::{DefId, DefIdSet};
use rustc_middle::ty::TyCtxt;
use rustc_session::Session;
use rustc_span::def_id::LOCAL_CRATE;
use rustdoc_json_types as types;
// It's important to use the FxHashMap from rustdoc_json_types here, instead of
// the one from rustc_data_structures, as they're different types due to sysroots.
// See #110051 and #127456 for details
use rustdoc_json_types::FxHashMap;
use crate::clean::types::{ExternalCrate, ExternalLocation};
use crate::clean::ItemKind;
@ -37,7 +40,7 @@ pub(crate) struct JsonRenderer<'tcx> {
/// level field of the JSON blob.
index: Rc<RefCell<FxHashMap<types::Id, types::Item>>>,
/// The directory where the blob will be written to.
out_path: PathBuf,
out_path: Option<PathBuf>,
cache: Rc<Cache>,
imported_items: DefIdSet,
}
@ -97,6 +100,20 @@ impl<'tcx> JsonRenderer<'tcx> {
})
.unwrap_or_default()
}
fn write<T: Write>(
&self,
output: types::Crate,
mut writer: BufWriter<T>,
path: &str,
) -> Result<(), Error> {
self.tcx
.sess
.time("rustdoc_json_serialization", || serde_json::ser::to_writer(&mut writer, &output))
.unwrap();
try_err!(writer.flush(), path);
Ok(())
}
}
impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
@ -120,7 +137,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
JsonRenderer {
tcx,
index: Rc::new(RefCell::new(FxHashMap::default())),
out_path: options.output,
out_path: if options.output_to_stdout { None } else { Some(options.output) },
cache: Rc::new(cache),
imported_items,
},
@ -220,14 +237,11 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
let index = (*self.index).clone().into_inner();
debug!("Constructing Output");
// This needs to be the default HashMap for compatibility with the public interface for
// rustdoc-json-types
#[allow(rustc::default_hash_types)]
let output = types::Crate {
root: types::Id(format!("0:0:{}", e.name(self.tcx).as_u32())),
crate_version: self.cache.crate_version.clone(),
includes_private: self.cache.document_private,
index: index.into_iter().collect(),
index,
paths: self
.cache
.paths
@ -264,20 +278,21 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
.collect(),
format_version: types::FORMAT_VERSION,
};
let out_dir = self.out_path.clone();
try_err!(create_dir_all(&out_dir), out_dir);
if let Some(ref out_path) = self.out_path {
let out_dir = out_path.clone();
try_err!(create_dir_all(&out_dir), out_dir);
let mut p = out_dir;
p.push(output.index.get(&output.root).unwrap().name.clone().unwrap());
p.set_extension("json");
let mut file = BufWriter::new(try_err!(File::create(&p), p));
self.tcx
.sess
.time("rustdoc_json_serialization", || serde_json::ser::to_writer(&mut file, &output))
.unwrap();
try_err!(file.flush(), p);
Ok(())
let mut p = out_dir;
p.push(output.index.get(&output.root).unwrap().name.clone().unwrap());
p.set_extension("json");
self.write(
output,
BufWriter::new(try_err!(File::create(&p), p)),
&p.display().to_string(),
)
} else {
self.write(output, BufWriter::new(stdout()), "<stdout>")
}
}
fn cache(&self) -> &Cache {

@ -1 +1 @@
Subproject commit 57ae1a3474057fead2c438928ed368b3740bf0ec
Subproject commit ccf4c38bdd73f1a37ec266c73bdaef80e39f8cf6

View file

@ -5,7 +5,7 @@
use std::path::PathBuf;
use rustc_hash::FxHashMap;
pub use rustc_hash::FxHashMap;
use serde::{Deserialize, Serialize};
/// The version of JSON output that this crate represents.

@ -1 +1 @@
Subproject commit 0d8d22f83b066503f6b2b755925197e959e58b4f
Subproject commit 2f738d617c6ead388f899802dd1a7fd66858a691

View file

@ -470,7 +470,7 @@ fn setup_mod_file(path: &Path, lint: &LintData<'_>) -> io::Result<&'static str>
});
// Find both the last lint declaration (declare_clippy_lint!) and the lint pass impl
while let Some(LintDeclSearchResult { content, .. }) = iter.find(|result| result.token_kind == TokenKind::Ident) {
while let Some(LintDeclSearchResult { content, .. }) = iter.find(|result| result.token == TokenKind::Ident) {
let mut iter = iter
.by_ref()
.filter(|t| !matches!(t.token_kind, TokenKind::Whitespace | TokenKind::LineComment { .. }));
@ -480,7 +480,7 @@ fn setup_mod_file(path: &Path, lint: &LintData<'_>) -> io::Result<&'static str>
// matches `!{`
match_tokens!(iter, Bang OpenBrace);
if let Some(LintDeclSearchResult { range, .. }) =
iter.find(|result| result.token_kind == TokenKind::CloseBrace)
iter.find(|result| result.token == TokenKind::CloseBrace)
{
last_decl_curly_offset = Some(range.end);
}

View file

@ -12,7 +12,6 @@
#![feature(let_chains)]
#![feature(trait_upcasting)]
#![feature(strict_overflow_ops)]
#![feature(is_none_or)]
// Configure clippy and other lints
#![allow(
clippy::collapsible_else_if,

View file

@ -11,3 +11,4 @@ wasmparser = { version = "0.214", default-features = false, features = ["std"] }
regex = "1.8" # 1.8 to avoid memchr 2.6.0, as 2.5.0 is pinned in the workspace
gimli = "0.31.0"
build_helper = { path = "../build_helper" }
serde_json = "1.0"

View file

@ -285,12 +285,24 @@ impl LlvmAr {
self
}
/// Like `obj_to_ar` except creating a thin archive.
pub fn obj_to_thin_ar(&mut self) -> &mut Self {
self.cmd.arg("rcus").arg("--thin");
self
}
/// Extract archive members back to files.
pub fn extract(&mut self) -> &mut Self {
self.cmd.arg("x");
self
}
/// Print the table of contents.
pub fn table_of_contents(&mut self) -> &mut Self {
self.cmd.arg("t");
self
}
/// Provide an output, then an input file. Bundled in one function, as llvm-ar has
/// no "--output"-style flag.
pub fn output_input(&mut self, out: impl AsRef<Path>, input: impl AsRef<Path>) -> &mut Self {

View file

@ -71,14 +71,8 @@ impl Rustdoc {
self
}
/// Specify path to the output folder.
pub fn output<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
self.cmd.arg("-o");
self.cmd.arg(path.as_ref());
self
}
/// Specify output directory.
#[doc(alias = "output")]
pub fn out_dir<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
self.cmd.arg("--out-dir").arg(path.as_ref());
self

View file

@ -38,6 +38,7 @@ pub use bstr;
pub use gimli;
pub use object;
pub use regex;
pub use serde_json;
pub use wasmparser;
// Re-exports of external dependencies.

View file

@ -84,3 +84,18 @@ pub fn has_suffix<P: AsRef<Path>>(path: P, suffix: &str) -> bool {
pub fn filename_contains<P: AsRef<Path>>(path: P, needle: &str) -> bool {
path.as_ref().file_name().is_some_and(|name| name.to_str().unwrap().contains(needle))
}
/// Helper for reading entries in a given directory and its children.
pub fn read_dir_entries_recursive<P: AsRef<Path>, F: FnMut(&Path)>(dir: P, mut callback: F) {
fn read_dir_entries_recursive_inner<P: AsRef<Path>, F: FnMut(&Path)>(dir: P, callback: &mut F) {
for entry in rfs::read_dir(dir) {
let path = entry.unwrap().path();
callback(&path);
if path.is_dir() {
read_dir_entries_recursive_inner(path, callback);
}
}
}
read_dir_entries_recursive_inner(dir, &mut callback);
}

View file

@ -1462,7 +1462,7 @@ fn generic_args_sans_defaults<'ga>(
// otherwise, if the arg is equal to the param default, hide it (unless the
// default is an error which can happen for the trait Self type)
#[allow(unstable_name_collisions)]
default_parameters.get(i).is_none_or(|default_parameter| {
IsNoneOr::is_none_or(default_parameters.get(i), |default_parameter| {
// !is_err(default_parameter.skip_binders())
// &&
arg != &default_parameter.clone().substitute(Interner, &parameters)

View file

@ -15,8 +15,10 @@ extern crate rustc_abi;
#[cfg(not(feature = "in-rust-tree"))]
extern crate ra_ap_rustc_abi as rustc_abi;
// Use the crates.io version unconditionally until the API settles enough that we can switch to
// using the in-tree one.
#[cfg(feature = "in-rust-tree")]
extern crate rustc_pattern_analysis;
#[cfg(not(feature = "in-rust-tree"))]
extern crate ra_ap_rustc_pattern_analysis as rustc_pattern_analysis;
mod builder;

View file

@ -303,6 +303,12 @@ dependencies = [
"crypto-common",
]
[[package]]
name = "doc-comment"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
[[package]]
name = "elasticlunr-rs"
version = "3.0.2"
@ -465,6 +471,21 @@ dependencies = [
"syn",
]
[[package]]
name = "html_parser"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6f56db07b6612644f6f7719f8ef944f75fff9d6378fdf3d316fd32194184abd"
dependencies = [
"doc-comment",
"pest",
"pest_derive",
"serde",
"serde_derive",
"serde_json",
"thiserror",
]
[[package]]
name = "humantime"
version = "2.1.0"
@ -680,13 +701,13 @@ name = "mdbook-trpl-listing"
version = "0.1.0"
dependencies = [
"clap",
"html_parser",
"mdbook",
"pulldown-cmark",
"pulldown-cmark-to-cmark",
"serde_json",
"thiserror",
"toml 0.8.14",
"xmlparser",
]
[[package]]
@ -1767,12 +1788,6 @@ dependencies = [
"memchr",
]
[[package]]
name = "xmlparser"
version = "0.13.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4"
[[package]]
name = "yaml-rust"
version = "0.4.5"

View file

@ -84,9 +84,7 @@ pub(crate) struct ParsedMacroArgs {
fn check_keyword<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option<MacroArg> {
for &keyword in RUST_KW.iter() {
if parser.token.is_keyword(keyword)
&& parser.look_ahead(1, |t| {
t.kind == TokenKind::Eof || t.kind == TokenKind::Comma
})
&& parser.look_ahead(1, |t| *t == TokenKind::Eof || *t == TokenKind::Comma)
{
parser.bump();
return Some(MacroArg::Keyword(
@ -131,7 +129,7 @@ pub(crate) fn parse_macro_args(
Some(arg) => {
args.push(arg);
parser.bump();
if parser.token.kind == TokenKind::Eof && args.len() == 2 {
if parser.token == TokenKind::Eof && args.len() == 2 {
vec_with_semi = true;
break;
}
@ -150,7 +148,7 @@ pub(crate) fn parse_macro_args(
parser.bump();
if parser.token.kind == TokenKind::Eof {
if parser.token == TokenKind::Eof {
trailing_comma = true;
break;
}

View file

@ -1,21 +1,13 @@
run-make/branch-protection-check-IBT/Makefile
run-make/cat-and-grep-sanity-check/Makefile
run-make/dep-info-doesnt-run-much/Makefile
run-make/dep-info-spaces/Makefile
run-make/dep-info/Makefile
run-make/emit-to-stdout/Makefile
run-make/extern-fn-reachable/Makefile
run-make/incr-add-rust-src-component/Makefile
run-make/issue-84395-lto-embed-bitcode/Makefile
run-make/jobserver-error/Makefile
run-make/libs-through-symlinks/Makefile
run-make/libtest-json/Makefile
run-make/libtest-junit/Makefile
run-make/libtest-thread-limit/Makefile
run-make/macos-deployment-target/Makefile
run-make/native-link-modifier-bundle/Makefile
run-make/reproducible-build/Makefile
run-make/rlib-format-packed-bundled-libs/Makefile
run-make/split-debuginfo/Makefile
run-make/symbol-mangling-hashed/Makefile
run-make/translation/Makefile