Auto merge of #122389 - workingjubilee:rollup-vbdniap, r=workingjubilee

Rollup of 12 pull requests

Successful merges:

 - #121754 ([bootstrap] Move the `split-debuginfo` setting to the per-target section)
 - #121953 (Add tests for the generated assembly of mask related simd instructions.)
 - #122081 (validate `builder::PATH_REMAP`)
 - #122245 (Detect truncated DepGraph files)
 - #122354 (bootstrap: Don't eagerly format verbose messages)
 - #122355 (rustdoc: fix up old test)
 - #122363 (tests: Add ui/attributes/unix_sigpipe/unix_sigpipe-str-list.rs)
 - #122366 (Fix stack overflow with recursive associated types)
 - #122377 (Fix discriminant_kind copy paste from the pointee trait case)
 - #122378 (Properly rebuild rustbooks)
 - #122380 (Fix typo in lib.rs of proc_macro)
 - #122381 (llvm-wrapper: adapt for LLVM API changes)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2024-03-12 16:31:43 +00:00
commit 6b1e5d9db3
34 changed files with 831 additions and 104 deletions

View file

@ -1112,11 +1112,16 @@ extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd(
LLVMRustDIBuilderRef Builder, LLVMValueRef V, LLVMMetadataRef VarInfo,
uint64_t *AddrOps, unsigned AddrOpsCount, LLVMMetadataRef DL,
LLVMBasicBlockRef InsertAtEnd) {
return wrap(Builder->insertDeclare(
auto Result = Builder->insertDeclare(
unwrap(V), unwrap<DILocalVariable>(VarInfo),
Builder->createExpression(llvm::ArrayRef<uint64_t>(AddrOps, AddrOpsCount)),
DebugLoc(cast<MDNode>(unwrap(DL))),
unwrap(InsertAtEnd)));
unwrap(InsertAtEnd));
#if LLVM_VERSION_GE(19, 0)
return wrap(Result.get<llvm::Instruction *>());
#else
return wrap(Result);
#endif
}
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerator(

View file

@ -179,13 +179,15 @@ impl SerializedDepGraph {
pub fn decode<D: Deps>(d: &mut MemDecoder<'_>) -> SerializedDepGraph {
// The last 16 bytes are the node count and edge count.
debug!("position: {:?}", d.position());
let (node_count, edge_count) =
d.with_position(d.len() - 2 * IntEncodedWithFixedSize::ENCODED_SIZE, |d| {
let (node_count, edge_count, graph_size) =
d.with_position(d.len() - 3 * IntEncodedWithFixedSize::ENCODED_SIZE, |d| {
debug!("position: {:?}", d.position());
let node_count = IntEncodedWithFixedSize::decode(d).0 as usize;
let edge_count = IntEncodedWithFixedSize::decode(d).0 as usize;
(node_count, edge_count)
let graph_size = IntEncodedWithFixedSize::decode(d).0 as usize;
(node_count, edge_count, graph_size)
});
assert_eq!(d.len(), graph_size);
debug!("position: {:?}", d.position());
debug!(?node_count, ?edge_count);
@ -491,6 +493,8 @@ fn finish(self, profiler: &SelfProfilerRef) -> FileEncodeResult {
debug!("position: {:?}", encoder.position());
IntEncodedWithFixedSize(node_count).encode(&mut encoder);
IntEncodedWithFixedSize(edge_count).encode(&mut encoder);
let graph_size = encoder.position() + IntEncodedWithFixedSize::ENCODED_SIZE;
IntEncodedWithFixedSize(graph_size as u64).encode(&mut encoder);
debug!("position: {:?}", encoder.position());
// Drop the encoder so that nothing is written after the counts.
let result = encoder.finish();

View file

@ -1061,8 +1061,9 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
// Integers and floats always have `u8` as their discriminant.
| ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(..)) => true,
// type parameters, opaques, and unnormalized projections have pointer
// metadata if they're known (e.g. by the param_env) to be sized
// type parameters, opaques, and unnormalized projections don't have
// a known discriminant and may need to be normalized further or rely
// on param env for discriminant projections
ty::Param(_)
| ty::Alias(..)
| ty::Bound(..)

View file

@ -240,6 +240,10 @@ fn visit_ty(&mut self, t: Ty<'tcx>) {
continue;
}
if !self.seen.insert(assoc.def_id.expect_local()) {
return;
}
let impl_args = alias_ty.args.rebase_onto(
self.tcx,
impl_trait_ref.def_id,

View file

@ -543,23 +543,15 @@
# FIXME(#61117): Some tests fail when this option is enabled.
#debuginfo-level-tests = 0
# Should rustc be build with split debuginfo? Default is platform dependent.
# Valid values are the same as those accepted by `-C split-debuginfo`
# (`off`/`unpacked`/`packed`).
# Should rustc and the standard library be built with split debuginfo? Default
# is platform dependent.
#
# On Linux, split debuginfo is disabled by default.
# This field is deprecated, use `target.<triple>.split-debuginfo` instead.
#
# On Apple platforms, unpacked split debuginfo is used by default. Unpacked
# debuginfo does not run `dsymutil`, which packages debuginfo from disparate
# object files into a single `.dSYM` file. `dsymutil` adds time to builds for
# no clear benefit, and also makes it more difficult for debuggers to find
# debug info. The compiler currently defaults to running `dsymutil` to preserve
# its historical default, but when compiling the compiler itself, we skip it by
# default since we know it's safe to do so in that case.
# The value specified here is only used when targeting the `build.build` triple,
# and is overridden by `target.<triple>.split-debuginfo` if specified.
#
# On Windows platforms, packed debuginfo is the only supported option,
# producing a `.pdb` file.
#split-debuginfo = if linux { off } else if windows { packed } else if apple { unpacked }
#split-debuginfo = see target.<triple>.split-debuginfo
# Whether or not `panic!`s generate backtraces (RUST_BACKTRACE)
#backtrace = true
@ -773,6 +765,26 @@
# Setting this will override the `use-lld` option for Rust code when targeting MSVC.
#linker = "cc" (path)
# Should rustc and the standard library be built with split debuginfo? Default
# is platform dependent.
#
# Valid values are the same as those accepted by `-C split-debuginfo`
# (`off`/`unpacked`/`packed`).
#
# On Linux, split debuginfo is disabled by default.
#
# On Apple platforms, unpacked split debuginfo is used by default. Unpacked
# debuginfo does not run `dsymutil`, which packages debuginfo from disparate
# object files into a single `.dSYM` file. `dsymutil` adds time to builds for
# no clear benefit, and also makes it more difficult for debuggers to find
# debug info. The compiler currently defaults to running `dsymutil` to preserve
# its historical default, but when compiling the compiler itself, we skip it by
# default since we know it's safe to do so in that case.
#
# On Windows platforms, packed debuginfo is the only supported option,
# producing a `.pdb` file.
#split-debuginfo = if linux { off } else if windows { packed } else if apple { unpacked }
# Path to the `llvm-config` binary of the installation of a custom LLVM to link
# against. Note that if this is specified we don't compile LLVM at all for this
# target.

View file

@ -73,7 +73,7 @@ pub fn is_available() -> bool {
/// The main type provided by this crate, representing an abstract stream of
/// tokens, or, more specifically, a sequence of token trees.
/// The type provide interfaces for iterating over those token trees and, conversely,
/// The type provides interfaces for iterating over those token trees and, conversely,
/// collecting a number of token trees into one stream.
///
/// This is both the input and output of `#[proc_macro]`, `#[proc_macro_attribute]`

View file

@ -1536,7 +1536,8 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
};
let sysroot = sysroot_dir(compiler.stage);
builder.verbose(&format!("Removing sysroot {} to avoid caching bugs", sysroot.display()));
builder
.verbose(|| println!("Removing sysroot {} to avoid caching bugs", sysroot.display()));
let _ = fs::remove_dir_all(&sysroot);
t!(fs::create_dir_all(&sysroot));
@ -1606,7 +1607,7 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
return true;
}
if !filtered_files.iter().all(|f| f != path.file_name().unwrap()) {
builder.verbose_than(1, &format!("ignoring {}", path.display()));
builder.verbose_than(1, || println!("ignoring {}", path.display()));
false
} else {
true
@ -2085,7 +2086,7 @@ pub fn stream_cargo(
cargo.arg(arg);
}
builder.verbose(&format!("running: {cargo:?}"));
builder.verbose(|| println!("running: {cargo:?}"));
if builder.config.dry_run() {
return true;

View file

@ -2107,7 +2107,7 @@ fn maybe_install_llvm(
{
let mut cmd = Command::new(llvm_config);
cmd.arg("--libfiles");
builder.verbose(&format!("running {cmd:?}"));
builder.verbose(|| println!("running {cmd:?}"));
let files = if builder.config.dry_run() { "".into() } else { output(&mut cmd) };
let build_llvm_out = &builder.llvm_out(builder.config.build);
let target_llvm_out = &builder.llvm_out(target);

View file

@ -145,7 +145,8 @@ fn run(self, builder: &Builder<'_>) {
let rustbook = builder.tool_exe(Tool::Rustbook);
let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
if !builder.config.dry_run() && !(up_to_date(&src, &index) || up_to_date(&rustbook, &index))
if !builder.config.dry_run()
&& (!up_to_date(&src, &index) || !up_to_date(&rustbook, &index))
{
builder.info(&format!("Rustbook ({target}) - {name}"));
let _ = fs::remove_dir_all(&out);

View file

@ -551,7 +551,7 @@ pub fn build_miri_sysroot(
if builder.config.dry_run() {
String::new()
} else {
builder.verbose(&format!("running: {cargo:?}"));
builder.verbose(|| println!("running: {cargo:?}"));
let out =
cargo.output().expect("We already ran `cargo miri setup` before and that worked");
assert!(out.status.success(), "`cargo miri setup` returned with non-0 exit code");
@ -559,7 +559,7 @@ pub fn build_miri_sysroot(
let stdout = String::from_utf8(out.stdout)
.expect("`cargo miri setup` stdout is not valid UTF-8");
let sysroot = stdout.trim_end();
builder.verbose(&format!("`cargo miri setup --print-sysroot` said: {sysroot:?}"));
builder.verbose(|| println!("`cargo miri setup --print-sysroot` said: {sysroot:?}"));
sysroot.to_owned()
}
}
@ -2326,7 +2326,7 @@ fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) ->
}
}
builder.verbose(&format!("doc tests for: {}", markdown.display()));
builder.verbose(|| println!("doc tests for: {}", markdown.display()));
let mut cmd = builder.rustdoc_cmd(compiler);
builder.add_rust_test_threads(&mut cmd);
// allow for unstable options such as new editions

View file

@ -291,7 +291,7 @@ pub fn assert_single_path(&self) -> &TaskPath {
const PATH_REMAP: &[(&str, &[&str])] = &[
// config.toml uses `rust-analyzer-proc-macro-srv`, but the
// actual path is `proc-macro-srv-cli`
("rust-analyzer-proc-macro-srv", &["proc-macro-srv-cli"]),
("rust-analyzer-proc-macro-srv", &["src/tools/rust-analyzer/crates/proc-macro-srv-cli"]),
// Make `x test tests` function the same as `x t tests/*`
(
"tests",
@ -382,10 +382,12 @@ fn is_excluded(&self, builder: &Builder<'_>, pathset: &PathSet) -> bool {
}
if !builder.config.skip.is_empty() && !matches!(builder.config.dry_run, DryRun::SelfCheck) {
builder.verbose(&format!(
"{:?} not skipped for {:?} -- not in {:?}",
pathset, self.name, builder.config.skip
));
builder.verbose(|| {
println!(
"{:?} not skipped for {:?} -- not in {:?}",
pathset, self.name, builder.config.skip
)
});
}
false
}
@ -1093,10 +1095,9 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
// Avoid deleting the rustlib/ directory we just copied
// (in `impl Step for Sysroot`).
if !builder.download_rustc() {
builder.verbose(&format!(
"Removing sysroot {} to avoid caching bugs",
sysroot.display()
));
builder.verbose(|| {
println!("Removing sysroot {} to avoid caching bugs", sysroot.display())
});
let _ = fs::remove_dir_all(&sysroot);
t!(fs::create_dir_all(&sysroot));
}
@ -1436,7 +1437,7 @@ fn cargo(
let sysroot_str = sysroot.as_os_str().to_str().expect("sysroot should be UTF-8");
if !matches!(self.config.dry_run, DryRun::SelfCheck) {
self.verbose_than(0, &format!("using sysroot {sysroot_str}"));
self.verbose_than(0, || println!("using sysroot {sysroot_str}"));
}
let mut rustflags = Rustflags::new(target);
@ -1731,15 +1732,16 @@ fn cargo(
},
);
let split_debuginfo = self.config.split_debuginfo(target);
let split_debuginfo_is_stable = target.contains("linux")
|| target.contains("apple")
|| (target.is_msvc() && self.config.rust_split_debuginfo == SplitDebuginfo::Packed)
|| (target.is_windows() && self.config.rust_split_debuginfo == SplitDebuginfo::Off);
|| (target.is_msvc() && split_debuginfo == SplitDebuginfo::Packed)
|| (target.is_windows() && split_debuginfo == SplitDebuginfo::Off);
if !split_debuginfo_is_stable {
rustflags.arg("-Zunstable-options");
}
match self.config.rust_split_debuginfo {
match split_debuginfo {
SplitDebuginfo::Packed => rustflags.arg("-Csplit-debuginfo=packed"),
SplitDebuginfo::Unpacked => rustflags.arg("-Csplit-debuginfo=unpacked"),
SplitDebuginfo::Off => rustflags.arg("-Csplit-debuginfo=off"),
@ -2102,11 +2104,11 @@ pub fn ensure<S: Step>(&'a self, step: S) -> S::Output {
panic!("{}", out);
}
if let Some(out) = self.cache.get(&step) {
self.verbose_than(1, &format!("{}c {:?}", " ".repeat(stack.len()), step));
self.verbose_than(1, || println!("{}c {:?}", " ".repeat(stack.len()), step));
return out;
}
self.verbose_than(1, &format!("{}> {:?}", " ".repeat(stack.len()), step));
self.verbose_than(1, || println!("{}> {:?}", " ".repeat(stack.len()), step));
stack.push(Box::new(step.clone()));
}
@ -2144,7 +2146,7 @@ pub fn ensure<S: Step>(&'a self, step: S) -> S::Output {
let cur_step = stack.pop().expect("step stack empty");
assert_eq!(cur_step.downcast_ref(), Some(&step));
}
self.verbose_than(1, &format!("{}< {:?}", " ".repeat(self.stack.borrow().len()), step));
self.verbose_than(1, || println!("{}< {:?}", " ".repeat(self.stack.borrow().len()), step));
self.cache.put(step, out.clone());
out
}

View file

@ -115,6 +115,19 @@ fn test_intersection() {
assert_eq!(command_paths, vec![Path::new("library/stdarch")]);
}
#[test]
fn validate_path_remap() {
let build = Build::new(configure("test", &["A"], &["A"]));
PATH_REMAP
.iter()
.flat_map(|(_, paths)| paths.iter())
.map(|path| build.src.join(path))
.for_each(|path| {
assert!(path.exists(), "{} should exist.", path.display());
});
}
#[test]
fn test_exclude() {
let mut config = configure("test", &["A"], &["A"]);

View file

@ -256,7 +256,7 @@ pub struct Config {
pub rust_debuginfo_level_std: DebuginfoLevel,
pub rust_debuginfo_level_tools: DebuginfoLevel,
pub rust_debuginfo_level_tests: DebuginfoLevel,
pub rust_split_debuginfo: SplitDebuginfo,
pub rust_split_debuginfo_for_build_triple: Option<SplitDebuginfo>, // FIXME: Deprecated field. Remove in Q3'24.
pub rust_rpath: bool,
pub rust_strip: bool,
pub rust_frame_pointers: bool,
@ -574,6 +574,7 @@ pub struct Target {
pub ranlib: Option<PathBuf>,
pub default_linker: Option<PathBuf>,
pub linker: Option<PathBuf>,
pub split_debuginfo: Option<SplitDebuginfo>,
pub sanitizers: Option<bool>,
pub profiler: Option<StringOrBool>,
pub rpath: Option<bool>,
@ -1133,6 +1134,7 @@ struct TomlTarget {
ranlib: Option<String> = "ranlib",
default_linker: Option<PathBuf> = "default-linker",
linker: Option<String> = "linker",
split_debuginfo: Option<String> = "split-debuginfo",
llvm_config: Option<String> = "llvm-config",
llvm_has_rust_patches: Option<bool> = "llvm-has-rust-patches",
llvm_filecheck: Option<String> = "llvm-filecheck",
@ -1627,11 +1629,18 @@ fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
debuginfo_level_tools = debuginfo_level_tools_toml;
debuginfo_level_tests = debuginfo_level_tests_toml;
config.rust_split_debuginfo = split_debuginfo
config.rust_split_debuginfo_for_build_triple = split_debuginfo
.as_deref()
.map(SplitDebuginfo::from_str)
.map(|v| v.expect("invalid value for rust.split_debuginfo"))
.unwrap_or(SplitDebuginfo::default_for_platform(config.build));
.map(|v| v.expect("invalid value for rust.split-debuginfo"));
if config.rust_split_debuginfo_for_build_triple.is_some() {
println!(
"WARNING: specifying `rust.split-debuginfo` is deprecated, use `target.{}.split-debuginfo` instead",
config.build
);
}
optimize = optimize_toml;
omit_git_hash = omit_git_hash_toml;
config.rust_new_symbol_mangling = new_symbol_mangling;
@ -1853,10 +1862,11 @@ fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
if let Some(ref s) = cfg.llvm_filecheck {
target.llvm_filecheck = Some(config.src.join(s));
}
target.llvm_libunwind = cfg
.llvm_libunwind
.as_ref()
.map(|v| v.parse().expect("failed to parse rust.llvm-libunwind"));
target.llvm_libunwind = cfg.llvm_libunwind.as_ref().map(|v| {
v.parse().unwrap_or_else(|_| {
panic!("failed to parse target.{triple}.llvm-libunwind")
})
});
if let Some(s) = cfg.no_std {
target.no_std = s;
}
@ -1893,6 +1903,12 @@ fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
}).collect());
}
target.split_debuginfo = cfg.split_debuginfo.as_ref().map(|v| {
v.parse().unwrap_or_else(|_| {
panic!("invalid value for target.{triple}.split-debuginfo")
})
});
config.target_config.insert(TargetSelection::from_user(&triple), target);
}
}
@ -2043,7 +2059,7 @@ pub(crate) fn try_run(&self, cmd: &mut Command) -> Result<(), ()> {
if self.dry_run() {
return Ok(());
}
self.verbose(&format!("running: {cmd:?}"));
self.verbose(|| println!("running: {cmd:?}"));
build_helper::util::try_run(cmd, self.is_verbose())
}
@ -2230,9 +2246,10 @@ pub(crate) fn initial_rustfmt(&self) -> Option<PathBuf> {
}
}
pub fn verbose(&self, msg: &str) {
/// Runs a function if verbosity is greater than 0
pub fn verbose(&self, f: impl Fn()) {
if self.verbose > 0 {
println!("{msg}");
f()
}
}
@ -2291,6 +2308,16 @@ pub fn llvm_libunwind(&self, target: TargetSelection) -> LlvmLibunwind {
})
}
pub fn split_debuginfo(&self, target: TargetSelection) -> SplitDebuginfo {
self.target_config
.get(&target)
.and_then(|t| t.split_debuginfo)
.or_else(|| {
if self.build == target { self.rust_split_debuginfo_for_build_triple } else { None }
})
.unwrap_or_else(|| SplitDebuginfo::default_for_platform(target))
}
pub fn submodules(&self, rust_info: &GitInfo) -> bool {
self.submodules.unwrap_or(rust_info.is_managed_git_subrepository())
}

View file

@ -61,7 +61,7 @@ pub(crate) fn check_run(&self, cmd: &mut Command) -> bool {
if self.dry_run() {
return true;
}
self.verbose(&format!("running: {cmd:?}"));
self.verbose(|| println!("running: {cmd:?}"));
check_run(cmd, self.is_verbose())
}
@ -195,7 +195,7 @@ fn fix_bin_or_dylib(&self, fname: &Path) {
}
fn download_file(&self, url: &str, dest_path: &Path, help_on_error: &str) {
self.verbose(&format!("download {url}"));
self.verbose(|| println!("download {url}"));
// Use a temporary file in case we crash while downloading, to avoid a corrupt download in cache/.
let tempfile = self.tempdir().join(dest_path.file_name().unwrap());
// While bootstrap itself only supports http and https downloads, downstream forks might
@ -300,7 +300,9 @@ fn unpack(&self, tarball: &Path, dst: &Path, pattern: &str) {
}
short_path = t!(short_path.strip_prefix(pattern));
let dst_path = dst.join(short_path);
self.verbose(&format!("extracting {} to {}", original_path.display(), dst.display()));
self.verbose(|| {
println!("extracting {} to {}", original_path.display(), dst.display())
});
if !t!(member.unpack_in(dst)) {
panic!("path traversal attack ??");
}
@ -323,7 +325,7 @@ fn unpack(&self, tarball: &Path, dst: &Path, pattern: &str) {
pub(crate) fn verify(&self, path: &Path, expected: &str) -> bool {
use sha2::Digest;
self.verbose(&format!("verifying {}", path.display()));
self.verbose(|| println!("verifying {}", path.display()));
if self.dry_run() {
return false;
@ -379,7 +381,7 @@ enum DownloadSource {
/// Functions that are only ever called once, but named for clarify and to avoid thousand-line functions.
impl Config {
pub(crate) fn download_clippy(&self) -> PathBuf {
self.verbose("downloading stage0 clippy artifacts");
self.verbose(|| println!("downloading stage0 clippy artifacts"));
let date = &self.stage0_metadata.compiler.date;
let version = &self.stage0_metadata.compiler.version;
@ -469,7 +471,7 @@ fn ci_component_contents(&self, stamp_file: &str) -> Vec<String> {
}
pub(crate) fn download_ci_rustc(&self, commit: &str) {
self.verbose(&format!("using downloaded stage2 artifacts from CI (commit {commit})"));
self.verbose(|| println!("using downloaded stage2 artifacts from CI (commit {commit})"));
let version = self.artifact_version_part(commit);
// download-rustc doesn't need its own cargo, it can just use beta's. But it does need the
@ -486,7 +488,7 @@ pub(crate) fn download_ci_rustc(&self, commit: &str) {
}
pub(crate) fn download_beta_toolchain(&self) {
self.verbose("downloading stage0 beta artifacts");
self.verbose(|| println!("downloading stage0 beta artifacts"));
let date = &self.stage0_metadata.compiler.date;
let version = &self.stage0_metadata.compiler.version;
@ -625,10 +627,12 @@ fn download_component(
self.unpack(&tarball, &bin_root, prefix);
return;
} else {
self.verbose(&format!(
"ignoring cached file {} due to failed verification",
tarball.display()
));
self.verbose(|| {
println!(
"ignoring cached file {} due to failed verification",
tarball.display()
)
});
self.remove(&tarball);
}
}

View file

@ -288,7 +288,7 @@ impl Build {
}
forward! {
verbose(msg: &str),
verbose(f: impl Fn()),
is_verbose() -> bool,
create(path: &Path, s: &str),
remove(f: &Path),
@ -440,11 +440,11 @@ pub fn new(mut config: Config) -> Build {
.unwrap()
.trim();
if local_release.split('.').take(2).eq(version.split('.').take(2)) {
build.verbose(&format!("auto-detected local-rebuild {local_release}"));
build.verbose(|| println!("auto-detected local-rebuild {local_release}"));
build.local_rebuild = true;
}
build.verbose("finding compilers");
build.verbose(|| println!("finding compilers"));
utils::cc_detect::find(&build);
// When running `setup`, the profile is about to change, so any requirements we have now may
// be different on the next invocation. Don't check for them until the next time x.py is
@ -452,7 +452,7 @@ pub fn new(mut config: Config) -> Build {
//
// Similarly, for `setup` we don't actually need submodules or cargo metadata.
if !matches!(build.config.cmd, Subcommand::Setup { .. }) {
build.verbose("running sanity check");
build.verbose(|| println!("running sanity check"));
crate::core::sanity::check(&mut build);
// Make sure we update these before gathering metadata so we don't get an error about missing
@ -464,7 +464,7 @@ pub fn new(mut config: Config) -> Build {
// Now, update all existing submodules.
build.update_existing_submodules();
build.verbose("learning about cargo");
build.verbose(|| println!("learning about cargo"));
crate::core::metadata::build(&mut build);
}
@ -693,7 +693,7 @@ fn clear_if_dirty(&self, dir: &Path, input: &Path) -> bool {
let stamp = dir.join(".stamp");
let mut cleared = false;
if mtime(&stamp) < mtime(input) {
self.verbose(&format!("Dirty - {}", dir.display()));
self.verbose(|| println!("Dirty - {}", dir.display()));
let _ = fs::remove_dir_all(dir);
cleared = true;
} else if stamp.exists() {
@ -986,7 +986,7 @@ pub(crate) fn run_cmd<'a, C: Into<BootstrapCommand<'a>>>(&self, cmd: C) -> bool
}
let command = cmd.into();
self.verbose(&format!("running: {command:?}"));
self.verbose(|| println!("running: {command:?}"));
let (output, print_error) = match command.output_mode {
mode @ (OutputMode::PrintAll | OutputMode::PrintOutput) => (
@ -1044,14 +1044,15 @@ pub(crate) fn run_cmd<'a, C: Into<BootstrapCommand<'a>>>(&self, cmd: C) -> bool
}
}
/// Check if verbosity is greater than the `level`
pub fn is_verbose_than(&self, level: usize) -> bool {
self.verbosity > level
}
/// Prints a message if this build is configured in more verbose mode than `level`.
fn verbose_than(&self, level: usize, msg: &str) {
/// Runs a function if verbosity is greater than `level`.
fn verbose_than(&self, level: usize, f: impl Fn()) {
if self.is_verbose_than(level) {
println!("{msg}");
f()
}
}
@ -1654,7 +1655,7 @@ fn copy_internal(&self, src: &Path, dst: &Path, dereference_symlinks: bool) {
if self.config.dry_run() {
return;
}
self.verbose_than(1, &format!("Copy {src:?} to {dst:?}"));
self.verbose_than(1, || println!("Copy {src:?} to {dst:?}"));
if src == dst {
return;
}
@ -1745,7 +1746,7 @@ fn install(&self, src: &Path, dstdir: &Path, perms: u32) {
return;
}
let dst = dstdir.join(src.file_name().unwrap());
self.verbose_than(1, &format!("Install {src:?} to {dst:?}"));
self.verbose_than(1, || println!("Install {src:?} to {dst:?}"));
t!(fs::create_dir_all(dstdir));
if !src.exists() {
panic!("ERROR: File \"{}\" not found!", src.display());

View file

@ -145,15 +145,15 @@ pub fn find_target(build: &Build, target: TargetSelection) {
build.cxx.borrow_mut().insert(target, compiler);
}
build.verbose(&format!("CC_{} = {:?}", &target.triple, build.cc(target)));
build.verbose(&format!("CFLAGS_{} = {:?}", &target.triple, cflags));
build.verbose(|| println!("CC_{} = {:?}", &target.triple, build.cc(target)));
build.verbose(|| println!("CFLAGS_{} = {:?}", &target.triple, cflags));
if let Ok(cxx) = build.cxx(target) {
let cxxflags = build.cflags(target, GitRepo::Rustc, CLang::Cxx);
build.verbose(&format!("CXX_{} = {:?}", &target.triple, cxx));
build.verbose(&format!("CXXFLAGS_{} = {:?}", &target.triple, cxxflags));
build.verbose(|| println!("CXX_{} = {:?}", &target.triple, cxx));
build.verbose(|| println!("CXXFLAGS_{} = {:?}", &target.triple, cxxflags));
}
if let Some(ar) = ar {
build.verbose(&format!("AR_{} = {:?}", &target.triple, ar));
build.verbose(|| println!("AR_{} = {:?}", &target.triple, ar));
build.ar.borrow_mut().insert(target, ar);
}

View file

@ -151,4 +151,9 @@ pub fn find_recent_config_change_ids(current_id: usize) -> Vec<ChangeInfo> {
severity: ChangeSeverity::Info,
summary: "New option `rust.llvm-bitcode-linker` that will build the llvm-bitcode-linker.",
},
ChangeInfo {
change_id: 121754,
severity: ChangeSeverity::Warning,
summary: "`rust.split-debuginfo` has been moved to `target.<triple>.split-debuginfo` and its default value is determined for each target individually.",
},
];

View file

@ -44,7 +44,7 @@ pub(crate) fn try_run_tests(builder: &Builder<'_>, cmd: &mut Command, stream: bo
fn run_tests(builder: &Builder<'_>, cmd: &mut Command, stream: bool) -> bool {
cmd.stdout(Stdio::piped());
builder.verbose(&format!("running: {cmd:?}"));
builder.verbose(|| println!("running: {cmd:?}"));
let mut process = cmd.spawn().unwrap();

View file

@ -328,7 +328,9 @@ fn run(self, build_cli: impl FnOnce(&Tarball<'a>, &mut Command)) -> GeneratedTar
// For `x install` tarball files aren't needed, so we can speed up the process by not producing them.
let compression_profile = if self.builder.kind == Kind::Install {
self.builder.verbose("Forcing dist.compression-profile = 'no-op' for `x install`.");
self.builder.verbose(|| {
println!("Forcing dist.compression-profile = 'no-op' for `x install`.")
});
// "no-op" indicates that the rust-installer won't produce compressed tarball sources.
"no-op"
} else {

View file

@ -694,7 +694,6 @@ pub fn line_directive<'line>(
"check-stdout",
"check-test-line-numbers-match",
"compile-flags",
"count",
"dont-check-compiler-stderr",
"dont-check-compiler-stdout",
"dont-check-failure-status",

View file

@ -0,0 +1,149 @@
//@ revisions: x86 x86-avx2 x86-avx512 aarch64
//@ [x86] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel
//@ [x86] needs-llvm-components: x86
//@ [x86-avx2] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel
//@ [x86-avx2] compile-flags: -C target-feature=+avx2
//@ [x86-avx2] needs-llvm-components: x86
//@ [x86-avx512] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel
//@ [x86-avx512] compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bw,+avx512dq
//@ [x86-avx512] needs-llvm-components: x86
//@ [aarch64] compile-flags: --target=aarch64-unknown-linux-gnu
//@ [aarch64] needs-llvm-components: aarch64
//@ [aarch64] min-llvm-version: 18.0
//@ assembly-output: emit-asm
//@ compile-flags: --crate-type=lib -O
#![feature(no_core, lang_items, repr_simd, intrinsics)]
#![no_core]
#![allow(non_camel_case_types)]
// Because we don't have core yet.
#[lang = "sized"]
pub trait Sized {}
#[lang = "copy"]
trait Copy {}
#[repr(simd)]
pub struct m8x16([i8; 16]);
#[repr(simd)]
pub struct m8x64([i8; 64]);
#[repr(simd)]
pub struct m32x4([i32; 4]);
#[repr(simd)]
pub struct m64x2([i64; 2]);
#[repr(simd)]
pub struct m64x4([i64; 4]);
extern "rust-intrinsic" {
fn simd_bitmask<V, B>(mask: V) -> B;
}
// CHECK-LABEL: bitmask_m8x16
#[no_mangle]
pub unsafe extern "C" fn bitmask_m8x16(mask: m8x16) -> u16 {
// The simd_bitmask intrinsic already uses the most significant bit, so no shift is necessary.
// Note that x86 has no byte shift, llvm uses a word shift to move the least significant bit
// of each byte into the right position.
//
// x86-NOT: psllw
// x86: movmskb eax, xmm0
//
// x86-avx2-NOT: vpsllw
// x86-avx2: vpmovmskb eax, xmm0
//
// x86-avx512-NOT: vpsllw xmm0
// x86-avx512: vpmovmskb eax, xmm0
//
// aarch64: adrp
// aarch64-NEXT: cmlt
// aarch64-NEXT: ldr
// aarch64-NEXT: and
// aarch64-NEXT: ext
// aarch64-NEXT: zip1
// aarch64-NEXT: addv
// aarch64-NEXT: fmov
simd_bitmask(mask)
}
// CHECK-LABEL: bitmask_m8x64
#[no_mangle]
pub unsafe extern "C" fn bitmask_m8x64(mask: m8x64) -> u64 {
// The simd_bitmask intrinsic already uses the most significant bit, so no shift is necessary.
// Note that x86 has no byte shift, llvm uses a word shift to move the least significant bit
// of each byte into the right position.
//
// The parameter is a 512 bit vector which in the C abi is only valid for avx512 targets.
//
// x86-avx512-NOT: vpsllw
// x86-avx512: vpmovb2m k0, zmm0
// x86-avx512: kmovq rax, k0
simd_bitmask(mask)
}
// CHECK-LABEL: bitmask_m32x4
#[no_mangle]
pub unsafe extern "C" fn bitmask_m32x4(mask: m32x4) -> u8 {
// The simd_bitmask intrinsic already uses the most significant bit, so no shift is necessary.
//
// x86-NOT: psllq
// x86: movmskps eax, xmm0
//
// x86-avx2-NOT: vpsllq
// x86-avx2: vmovmskps eax, xmm0
//
// x86-avx512-NOT: vpsllq
// x86-avx512: vmovmskps eax, xmm0
//
// aarch64: adrp
// aarch64-NEXT: cmlt
// aarch64-NEXT: ldr
// aarch64-NEXT: and
// aarch64-NEXT: addv
// aarch64-NEXT: fmov
// aarch64-NEXT: and
simd_bitmask(mask)
}
// CHECK-LABEL: bitmask_m64x2
#[no_mangle]
pub unsafe extern "C" fn bitmask_m64x2(mask: m64x2) -> u8 {
// The simd_bitmask intrinsic already uses the most significant bit, so no shift is necessary.
//
// x86-NOT: psllq
// x86: movmskpd eax, xmm0
//
// x86-avx2-NOT: vpsllq
// x86-avx2: vmovmskpd eax, xmm0
//
// x86-avx512-NOT: vpsllq
// x86-avx512: vmovmskpd eax, xmm0
//
// aarch64: adrp
// aarch64-NEXT: cmlt
// aarch64-NEXT: ldr
// aarch64-NEXT: and
// aarch64-NEXT: addp
// aarch64-NEXT: fmov
// aarch64-NEXT: and
simd_bitmask(mask)
}
// CHECK-LABEL: bitmask_m64x4
#[no_mangle]
pub unsafe extern "C" fn bitmask_m64x4(mask: m64x4) -> u8 {
// The simd_bitmask intrinsic already uses the most significant bit, so no shift is necessary.
//
// The parameter is a 256 bit vector which in the C abi is only valid for avx/avx512 targets.
//
// x86-avx2-NOT: vpsllq
// x86-avx2: vmovmskpd eax, ymm0
//
// x86-avx512-NOT: vpsllq
// x86-avx512: vmovmskpd eax, ymm0
simd_bitmask(mask)
}

View file

@ -0,0 +1,44 @@
//@ revisions: x86-avx512
//@ [x86-avx512] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel
//@ [x86-avx512] compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bw,+avx512dq
//@ [x86-avx512] needs-llvm-components: x86
//@ [x86-avx512] min-llvm-version: 18.0
//@ assembly-output: emit-asm
//@ compile-flags: --crate-type=lib -O
#![feature(no_core, lang_items, repr_simd, intrinsics)]
#![no_core]
#![allow(non_camel_case_types)]
// Because we don't have core yet.
#[lang = "sized"]
pub trait Sized {}
#[lang = "copy"]
trait Copy {}
#[repr(simd)]
pub struct f64x4([f64; 4]);
#[repr(simd)]
pub struct m64x4([i64; 4]);
#[repr(simd)]
pub struct pf64x4([*const f64; 4]);
extern "rust-intrinsic" {
fn simd_gather<V, M, P>(values: V, mask: M, pointer: P) -> V;
}
// CHECK-LABEL: gather_f64x4
#[no_mangle]
pub unsafe extern "C" fn gather_f64x4(mask: m64x4, ptrs: pf64x4) -> f64x4 {
// FIXME: This should also get checked to generate a gather instruction for avx2.
// Currently llvm scalarizes this code, see https://github.com/llvm/llvm-project/issues/59789
//
// x86-avx512: vpsllq ymm0, ymm0, 63
// x86-avx512-NEXT: vpmovq2m k1, ymm0
// x86-avx512-NEXT: vpxor xmm0, xmm0, xmm0
// x86-avx512-NEXT: vgatherqpd ymm0 {k1}, ymmword ptr [1*ymm1]
simd_gather(f64x4([0_f64, 0_f64, 0_f64, 0_f64]), ptrs, mask)
}

View file

@ -0,0 +1,88 @@
//@ revisions: x86-avx2 x86-avx512
//@ [x86-avx2] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel
//@ [x86-avx2] compile-flags: -C target-feature=+avx2
//@ [x86-avx2] needs-llvm-components: x86
//@ [x86-avx512] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel
//@ [x86-avx512] compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bw,+avx512dq
//@ [x86-avx512] needs-llvm-components: x86
//@ assembly-output: emit-asm
//@ compile-flags: --crate-type=lib -O
#![feature(no_core, lang_items, repr_simd, intrinsics)]
#![no_core]
#![allow(non_camel_case_types)]
// Because we don't have core yet.
#[lang = "sized"]
pub trait Sized {}
#[lang = "copy"]
trait Copy {}
#[repr(simd)]
pub struct i8x16([i8; 16]);
#[repr(simd)]
pub struct m8x16([i8; 16]);
#[repr(simd)]
pub struct f32x8([f32; 8]);
#[repr(simd)]
pub struct m32x8([i32; 8]);
#[repr(simd)]
pub struct f64x4([f64; 4]);
#[repr(simd)]
pub struct m64x4([i64; 4]);
extern "rust-intrinsic" {
fn simd_masked_load<M, P, T>(mask: M, pointer: P, values: T) -> T;
}
// CHECK-LABEL: load_i8x16
#[no_mangle]
pub unsafe extern "C" fn load_i8x16(mask: m8x16, pointer: *const i8) -> i8x16 {
// Since avx2 supports no masked loads for bytes, the code tests each individual bit
// and jumps to code that inserts individual bytes.
// x86-avx2: vpsllw xmm0, xmm0, 7
// x86-avx2-NEXT: vpmovmskb eax, xmm0
// x86-avx2-NEXT: vpxor xmm0, xmm0
// x86-avx2-NEXT: test al, 1
// x86-avx2-NEXT: jne
// x86-avx2-NEXT: test al, 2
// x86-avx2-NEXT: jne
// x86-avx2-DAG: movzx [[REG:[a-z]+]], byte ptr [rdi]
// x86-avx2-NEXT: vmovd xmm0, [[REG]]
// x86-avx2-DAG: vpinsrb xmm0, xmm0, byte ptr [rdi + 1], 1
//
// x86-avx512: vpsllw xmm0, xmm0, 7
// x86-avx512-NEXT: vpmovb2m k1, xmm0
// x86-avx512-NEXT: vmovdqu8 xmm0 {k1} {z}, xmmword ptr [rdi]
simd_masked_load(mask, pointer, i8x16([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]))
}
// CHECK-LABEL: load_f32x8
#[no_mangle]
pub unsafe extern "C" fn load_f32x8(mask: m32x8, pointer: *const f32) -> f32x8 {
// x86-avx2: vpslld ymm0, ymm0, 31
// x86-avx2-NEXT: vmaskmovps ymm0, ymm0, ymmword ptr [rdi]
//
// x86-avx512: vpslld ymm0, ymm0, 31
// x86-avx512-NEXT: vpmovd2m k1, ymm0
// x86-avx512-NEXT: vmovups ymm0 {k1} {z}, ymmword ptr [rdi]
simd_masked_load(mask, pointer, f32x8([0_f32, 0_f32, 0_f32, 0_f32, 0_f32, 0_f32, 0_f32, 0_f32]))
}
// CHECK-LABEL: load_f64x4
#[no_mangle]
pub unsafe extern "C" fn load_f64x4(mask: m64x4, pointer: *const f64) -> f64x4 {
// x86-avx2: vpsllq ymm0, ymm0, 63
// x86-avx2-NEXT: vmaskmovpd ymm0, ymm0, ymmword ptr [rdi]
//
// x86-avx512: vpsllq ymm0, ymm0, 63
// x86-avx512-NEXT: vpmovq2m k1, ymm0
// x86-avx512-NEXT: vmovupd ymm0 {k1} {z}, ymmword ptr [rdi]
simd_masked_load(mask, pointer, f64x4([0_f64, 0_f64, 0_f64, 0_f64]))
}

View file

@ -0,0 +1,60 @@
// verify that simd mask reductions do not introduce additional bit shift operations
//@ revisions: x86 aarch64
//@ [x86] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel
//@ [x86] needs-llvm-components: x86
//@ [aarch64] compile-flags: --target=aarch64-unknown-linux-gnu
//@ [aarch64] needs-llvm-components: aarch64
//@ [aarch64] min-llvm-version: 18.0
//@ assembly-output: emit-asm
//@ compile-flags: --crate-type=lib -O
#![feature(no_core, lang_items, repr_simd, intrinsics)]
#![no_core]
#![allow(non_camel_case_types)]
// Because we don't have core yet.
#[lang = "sized"]
pub trait Sized {}
#[lang = "copy"]
trait Copy {}
#[repr(simd)]
pub struct mask8x16([i8; 16]);
extern "rust-intrinsic" {
fn simd_reduce_all<T>(x: T) -> bool;
fn simd_reduce_any<T>(x: T) -> bool;
}
// CHECK-LABEL: mask_reduce_all:
#[no_mangle]
pub unsafe extern "C" fn mask_reduce_all(m: mask8x16) -> bool {
// x86: psllw xmm0, 7
// x86-NEXT: pmovmskb eax, xmm0
// x86-NEXT: {{cmp ax, -1|xor eax, 65535}}
// x86-NEXT: sete al
//
// aarch64: shl v0.16b, v0.16b, #7
// aarch64-NEXT: cmlt v0.16b, v0.16b, #0
// aarch64-NEXT: uminv b0, v0.16b
// aarch64-NEXT: fmov [[REG:[a-z0-9]+]], s0
// aarch64-NEXT: and w0, [[REG]], #0x1
simd_reduce_all(m)
}
// CHECK-LABEL: mask_reduce_any:
#[no_mangle]
pub unsafe extern "C" fn mask_reduce_any(m: mask8x16) -> bool {
// x86: psllw xmm0, 7
// x86-NEXT: pmovmskb
// x86-NEXT: test eax, eax
// x86-NEXT: setne al
//
// aarch64: shl v0.16b, v0.16b, #7
// aarch64-NEXT: cmlt v0.16b, v0.16b, #0
// aarch64-NEXT: umaxv b0, v0.16b
// aarch64-NEXT: fmov [[REG:[a-z0-9]+]], s0
// aarch64-NEXT: and w0, [[REG]], #0x1
simd_reduce_any(m)
}

View file

@ -0,0 +1,86 @@
//@ revisions: x86-avx2 x86-avx512
//@ [x86-avx2] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel
//@ [x86-avx2] compile-flags: -C target-feature=+avx2
//@ [x86-avx2] needs-llvm-components: x86
//@ [x86-avx512] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel
//@ [x86-avx512] compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bw,+avx512dq
//@ [x86-avx512] needs-llvm-components: x86
//@ assembly-output: emit-asm
//@ compile-flags: --crate-type=lib -O
#![feature(no_core, lang_items, repr_simd, intrinsics)]
#![no_core]
#![allow(non_camel_case_types)]
// Because we don't have core yet.
#[lang = "sized"]
pub trait Sized {}
#[lang = "copy"]
trait Copy {}
#[repr(simd)]
pub struct i8x16([i8; 16]);
#[repr(simd)]
pub struct m8x16([i8; 16]);
#[repr(simd)]
pub struct f32x8([f32; 8]);
#[repr(simd)]
pub struct m32x8([i32; 8]);
#[repr(simd)]
pub struct f64x4([f64; 4]);
#[repr(simd)]
pub struct m64x4([i64; 4]);
extern "rust-intrinsic" {
fn simd_masked_store<M, P, T>(mask: M, pointer: P, values: T);
}
// CHECK-LABEL: store_i8x16
#[no_mangle]
pub unsafe extern "C" fn store_i8x16(mask: m8x16, pointer: *mut i8, value: i8x16) {
// Since avx2 supports no masked stores for bytes, the code tests each individual bit
// and jumps to code that extracts individual bytes to memory.
// x86-avx2: vpsllw xmm0, xmm0, 7
// x86-avx2-NEXT: vpmovmskb eax, xmm0
// x86-avx2-NEXT: test al, 1
// x86-avx2-NEXT: jne
// x86-avx2-NEXT: test al, 2
// x86-avx2-NEXT: jne
// x86-avx2-DAG: vpextrb byte ptr [rdi + 1], xmm1, 1
// x86-avx2-DAG: vpextrb byte ptr [rdi], xmm1, 0
//
// x86-avx512: vpsllw xmm0, xmm0, 7
// x86-avx512-NEXT: vpmovb2m k1, xmm0
// x86-avx512-NEXT: vmovdqu8 xmmword ptr [rdi] {k1}, xmm1
simd_masked_store(mask, pointer, value)
}
// CHECK-LABEL: store_f32x8
#[no_mangle]
pub unsafe extern "C" fn store_f32x8(mask: m32x8, pointer: *mut f32, value: f32x8) {
// x86-avx2: vpslld ymm0, ymm0, 31
// x86-avx2-NEXT: vmaskmovps ymmword ptr [rdi], ymm0, ymm1
//
// x86-avx512: vpslld ymm0, ymm0, 31
// x86-avx512-NEXT: vpmovd2m k1, ymm0
// x86-avx512-NEXT: vmovups ymmword ptr [rdi] {k1}, ymm1
simd_masked_store(mask, pointer, value)
}
// CHECK-LABEL: store_f64x4
#[no_mangle]
pub unsafe extern "C" fn store_f64x4(mask: m64x4, pointer: *mut f64, value: f64x4) {
// x86-avx2: vpsllq ymm0, ymm0, 63
// x86-avx2-NEXT: vmaskmovpd ymmword ptr [rdi], ymm0, ymm1
//
// x86-avx512: vpsllq ymm0, ymm0, 63
// x86-avx512-NEXT: vpmovq2m k1, ymm0
// x86-avx512-NEXT: vmovupd ymmword ptr [rdi] {k1}, ymm1
simd_masked_store(mask, pointer, value)
}

View file

@ -0,0 +1,40 @@
//@ revisions: x86-avx512
//@ [x86-avx512] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel
//@ [x86-avx512] compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bw,+avx512dq
//@ [x86-avx512] needs-llvm-components: x86
//@ [x86-avx512] min-llvm-version: 18.0
//@ assembly-output: emit-asm
//@ compile-flags: --crate-type=lib -O
#![feature(no_core, lang_items, repr_simd, intrinsics)]
#![no_core]
#![allow(non_camel_case_types)]
// Because we don't have core yet.
#[lang = "sized"]
pub trait Sized {}
#[lang = "copy"]
trait Copy {}
#[repr(simd)]
pub struct f64x4([f64; 4]);
#[repr(simd)]
pub struct m64x4([i64; 4]);
#[repr(simd)]
pub struct pf64x4([*mut f64; 4]);
extern "rust-intrinsic" {
fn simd_scatter<V, P, M>(values: V, pointer: P, mask: M);
}
// CHECK-LABEL: scatter_f64x4
#[no_mangle]
pub unsafe extern "C" fn scatter_f64x4(values: f64x4, ptrs: pf64x4, mask: m64x4) {
// x86-avx512: vpsllq ymm2, ymm2, 63
// x86-avx512-NEXT: vpmovq2m k1, ymm2
// x86-avx512-NEXT: vscatterqpd ymmword ptr [1*ymm1] {k1}, ymm0
simd_scatter(values, ptrs, mask)
}

View file

@ -0,0 +1,130 @@
//@ revisions: x86-avx2 x86-avx512 aarch64
//@ [x86-avx2] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel
//@ [x86-avx2] compile-flags: -C target-feature=+avx2
//@ [x86-avx2] needs-llvm-components: x86
//@ [x86-avx512] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel
//@ [x86-avx512] compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bw,+avx512dq
//@ [x86-avx512] needs-llvm-components: x86
//@ [aarch64] compile-flags: --target=aarch64-unknown-linux-gnu
//@ [aarch64] needs-llvm-components: aarch64
//@ [aarch64] min-llvm-version: 18.0
//@ assembly-output: emit-asm
//@ compile-flags: --crate-type=lib -O
#![feature(no_core, lang_items, repr_simd, intrinsics)]
#![no_core]
#![allow(non_camel_case_types)]
// Because we don't have core yet.
#[lang = "sized"]
pub trait Sized {}
#[lang = "copy"]
trait Copy {}
#[repr(simd)]
pub struct i8x16([i8; 16]);
#[repr(simd)]
pub struct m8x16([i8; 16]);
#[repr(simd)]
pub struct f32x4([f32; 4]);
#[repr(simd)]
pub struct m32x4([i32; 4]);
#[repr(simd)]
pub struct f64x2([f64; 2]);
#[repr(simd)]
pub struct m64x2([i64; 2]);
#[repr(simd)]
pub struct f64x4([f64; 4]);
#[repr(simd)]
pub struct m64x4([i64; 4]);
#[repr(simd)]
pub struct f64x8([f64; 8]);
#[repr(simd)]
pub struct m64x8([i64; 8]);
extern "rust-intrinsic" {
fn simd_select<M, V>(mask: M, a: V, b: V) -> V;
}
// CHECK-LABEL: select_i8x16
#[no_mangle]
pub unsafe extern "C" fn select_i8x16(mask: m8x16, a: i8x16, b: i8x16) -> i8x16 {
// x86-avx2: vpsllw xmm0, xmm0, 7
// x86-avx2-NEXT: vpblendvb xmm0, xmm2, xmm1, xmm0
//
// x86-avx512: vpsllw xmm0, xmm0, 7
// x86-avx512-NEXT: vpmovb2m k1, xmm0
// x86-avx512-NEXT: vpblendmb xmm0 {k1}, xmm2, xmm1
//
// aarch64: shl v0.16b, v0.16b, #7
// aarch64-NEXT: cmlt v0.16b, v0.16b, #0
// aarch64-NEXT: bsl v0.16b, v1.16b, v2.16b
simd_select(mask, a, b)
}
// CHECK-LABEL: select_f32x4
#[no_mangle]
pub unsafe extern "C" fn select_f32x4(mask: m32x4, a: f32x4, b: f32x4) -> f32x4 {
// x86-avx2: vpslld xmm0, xmm0, 31
// x86-avx2-NEXT: vblendvps xmm0, xmm2, xmm1, xmm0
//
// x86-avx512: vpslld xmm0, xmm0, 31
// x86-avx512-NEXT: vpmovd2m k1, xmm0
// x86-avx512-NEXT: vblendmps xmm0 {k1}, xmm2, xmm1
//
// aarch64: shl v0.4s, v0.4s, #31
// aarch64-NEXT: cmlt v0.4s, v0.4s, #0
// aarch64-NEXT: bsl v0.16b, v1.16b, v2.16b
simd_select(mask, a, b)
}
// CHECK-LABEL: select_f64x2
#[no_mangle]
pub unsafe extern "C" fn select_f64x2(mask: m64x2, a: f64x2, b: f64x2) -> f64x2 {
// x86-avx2: vpsllq xmm0, xmm0, 63
// x86-avx2-NEXT: vblendvpd xmm0, xmm2, xmm1, xmm0
//
// x86-avx512: vpsllq xmm0, xmm0, 63
// x86-avx512-NEXT: vpmovq2m k1, xmm0
// x86-avx512-NEXT: vblendmpd xmm0 {k1}, xmm2, xmm1
//
// aarch64: shl v0.2d, v0.2d, #63
// aarch64-NEXT: cmlt v0.2d, v0.2d, #0
// aarch64-NEXT: bsl v0.16b, v1.16b, v2.16b
simd_select(mask, a, b)
}
// CHECK-LABEL: select_f64x4
#[no_mangle]
pub unsafe extern "C" fn select_f64x4(mask: m64x4, a: f64x4, b: f64x4) -> f64x4 {
// The parameter is a 256 bit vector which in the C abi is only valid for avx targets.
//
// x86-avx2: vpsllq ymm0, ymm0, 63
// x86-avx2-NEXT: vblendvpd ymm0, ymm2, ymm1, ymm0
//
// x86-avx512: vpsllq ymm0, ymm0, 63
// x86-avx512-NEXT: vpmovq2m k1, ymm0
// x86-avx512-NEXT: vblendmpd ymm0 {k1}, ymm2, ymm1
simd_select(mask, a, b)
}
// CHECK-LABEL: select_f64x8
#[no_mangle]
pub unsafe extern "C" fn select_f64x8(mask: m64x8, a: f64x8, b: f64x8) -> f64x8 {
// The parameter is a 256 bit vector which in the C abi is only valid for avx512 targets.
//
// x86-avx512: vpsllq zmm0, zmm0, 63
// x86-avx512-NEXT: vpmovq2m k1, zmm0
// x86-avx512-NEXT: vblendmpd zmm0 {k1}, zmm2, zmm1
simd_select(mask, a, b)
}

View file

@ -1,26 +1,37 @@
#![crate_name = "foo"]
use std::ops::Add;
use std::fmt::Display;
use std::ops::Add;
//@count foo/fn.function_with_a_really_long_name.html //pre/br 2
pub fn function_with_a_really_long_name(parameter_one: i32,
parameter_two: i32)
-> Option<i32> {
// @matches foo/fn.function_with_a_really_long_name.html '//*[@class="rust item-decl"]//code' "\
// function_with_a_really_long_name\(\n\
// \ parameter_one: i32,\n\
// \ parameter_two: i32\n\
// \) -> Option<i32>$"
pub fn function_with_a_really_long_name(parameter_one: i32, parameter_two: i32) -> Option<i32> {
Some(parameter_one + parameter_two)
}
//@count foo/fn.short_name.html //pre/br 0
pub fn short_name(param: i32) -> i32 { param + 1 }
// @matches foo/fn.short_name.html '//*[@class="rust item-decl"]//code' \
// "short_name\(param: i32\) -> i32$"
pub fn short_name(param: i32) -> i32 {
param + 1
}
//@count foo/fn.where_clause.html //pre/br 4
pub fn where_clause<T, U>(param_one: T,
param_two: U)
where T: Add<U> + Display + Copy,
U: Add<T> + Display + Copy,
T::Output: Display + Add<U::Output> + Copy,
<T::Output as Add<U::Output>>::Output: Display,
U::Output: Display + Copy
// @matches foo/fn.where_clause.html '//*[@class="rust item-decl"]//code' "\
// where_clause<T, U>\(param_one: T, param_two: U\)where\n\
// \ T: Add<U> \+ Display \+ Copy,\n\
// \ U: Add<T> \+ Display \+ Copy,\n\
// \ T::Output: Display \+ Add<U::Output> \+ Copy,\n\
// \ <T::Output as Add<U::Output>>::Output: Display,\n\
// \ U::Output: Display \+ Copy,$"
pub fn where_clause<T, U>(param_one: T, param_two: U)
where
T: Add<U> + Display + Copy,
U: Add<T> + Display + Copy,
T::Output: Display + Add<U::Output> + Copy,
<T::Output as Add<U::Output>>::Output: Display,
U::Output: Display + Copy,
{
let x = param_one + param_two;
println!("{} + {} = {}", param_one, param_two, x);

View file

@ -1,5 +1,5 @@
error: malformed `unix_sigpipe` attribute input
--> $DIR/unix_sigpipe-list.rs:3:1
--> $DIR/unix_sigpipe-ident-list.rs:3:1
|
LL | #[unix_sigpipe(sig_dfl)]
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[unix_sigpipe = "inherit|sig_ign|sig_dfl"]`

View file

@ -0,0 +1,4 @@
#![feature(unix_sigpipe)]
#[unix_sigpipe("sig_dfl")] //~ error: malformed `unix_sigpipe` attribute input
fn main() {}

View file

@ -0,0 +1,8 @@
error: malformed `unix_sigpipe` attribute input
--> $DIR/unix_sigpipe-str-list.rs:3:1
|
LL | #[unix_sigpipe("sig_dfl")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[unix_sigpipe = "inherit|sig_ign|sig_dfl"]`
error: aborting due to 1 previous error

View file

@ -0,0 +1,14 @@
trait Foo {
type Bar;
fn foo(self) -> Self::Bar;
}
impl Foo for Box<dyn Foo> {
//~^ ERROR: the value of the associated type `Bar` in `Foo` must be specified
type Bar = <Self as Foo>::Bar;
fn foo(self) -> <Self as Foo>::Bar {
(*self).foo()
}
}
fn main() {}

View file

@ -0,0 +1,12 @@
error[E0191]: the value of the associated type `Bar` in `Foo` must be specified
--> $DIR/associated-type-cycle.rs:6:22
|
LL | type Bar;
| -------- `Bar` defined here
...
LL | impl Foo for Box<dyn Foo> {
| ^^^ help: specify the associated type: `Foo<Bar = Type>`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0191`.