From 18f8657415da5ebc480e63abe03f87d4b4ce4157 Mon Sep 17 00:00:00 2001 From: Kai Luo Date: Thu, 8 Aug 2024 22:08:57 -0400 Subject: [PATCH 1/6] Pass -bnoipath when adding rust upstream dynamic crates --- compiler/rustc_codegen_ssa/src/back/link.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index ad81ff272c62f..b3bb32bedf4b3 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -2753,6 +2753,13 @@ fn add_upstream_rust_crates( .find(|(ty, _)| *ty == crate_type) .expect("failed to find crate type in dependency format list"); + if sess.target.is_like_aix { + // Unlike GNU's ld, AIX linker doesn't feature `-soname=...` when output + // a shared library. Instead, AIX linker offers `(no)ipath`. See + // https://www.ibm.com/docs/en/aix/7.3?topic=l-ld-command. + cmd.link_or_cc_arg("-bnoipath"); + } + for &cnum in &codegen_results.crate_info.used_crates { // We may not pass all crates through to the linker. Some crates may appear statically in // an existing dylib, meaning we'll pick up all the symbols from the dylib. From 1ae1f8ce9cb327eaa22454bbf5a8e25123091ffb Mon Sep 17 00:00:00 2001 From: David Tenty Date: Fri, 6 Dec 2024 10:53:26 -0500 Subject: [PATCH 2/6] Clarify comment --- compiler/rustc_codegen_ssa/src/back/link.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index b3bb32bedf4b3..eb8f7cf6d407c 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -2754,8 +2754,10 @@ fn add_upstream_rust_crates( .expect("failed to find crate type in dependency format list"); if sess.target.is_like_aix { - // Unlike GNU's ld, AIX linker doesn't feature `-soname=...` when output - // a shared library. Instead, AIX linker offers `(no)ipath`. See + // Unlike ELF linkers, AIX doesn't feature `DT_SONAME` to override + // the dependency name when outputing a shared library. Thus, `ld` will + // use the full path to shared libraries as the dependency if passed it + // by default unless `noipath` is passed. // https://www.ibm.com/docs/en/aix/7.3?topic=l-ld-command. cmd.link_or_cc_arg("-bnoipath"); } From 61fd92e28411c2594c9f46cac9d96b96ef894d90 Mon Sep 17 00:00:00 2001 From: rohit141914 Date: Sat, 7 Dec 2024 01:01:03 +0530 Subject: [PATCH 3/6] Removed Unnecessary Spaces From RELEASES.md --- RELEASES.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index 8702bb021184a..99733bade32c4 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -503,7 +503,7 @@ Compatibility Notes * We have renamed `std::panic::PanicInfo` to `std::panic::PanicHookInfo`. The old name will continue to work as an alias, but will result in a deprecation warning starting in Rust 1.82.0. `core::panic::PanicInfo` will remain unchanged, however, as this is now a *different type*. - + The reason is that these types have different roles: `std::panic::PanicHookInfo` is the argument to the [panic hook](https://doc.rust-lang.org/stable/std/panic/fn.set_hook.html) in std context (where panics can have an arbitrary payload), while `core::panic::PanicInfo` is the argument to the [`#[panic_handler]`](https://doc.rust-lang.org/nomicon/panic-handler.html) in no_std context (where panics always carry a formatted *message*). Separating these types allows us to add more useful methods to these types, such as `std::panic::PanicHookInfo::payload_as_str()` and `core::panic::PanicInfo::message()`. * The new sort implementations may panic if a type's implementation of [`Ord`](https://doc.rust-lang.org/std/cmp/trait.Ord.html) (or the given comparison function) does not implement a [total order](https://en.wikipedia.org/wiki/Total_order) as the trait requires. `Ord`'s supertraits (`PartialOrd`, `Eq`, and `PartialEq`) must also be consistent. The previous implementations would not "notice" any problem, but the new implementations have a good chance of detecting inconsistencies, throwing a panic rather than returning knowingly unsorted data. @@ -584,7 +584,7 @@ Stabilized APIs - [`impl Default for Arc`](https://doc.rust-lang.org/beta/alloc/sync/struct.Arc.html#impl-Default-for-Arc%3CCStr%3E) - [`impl Default for Arc<[T]>`](https://doc.rust-lang.org/beta/alloc/sync/struct.Arc.html#impl-Default-for-Arc%3C%5BT%5D%3E) - [`impl IntoIterator for Box<[T]>`](https://doc.rust-lang.org/beta/alloc/boxed/struct.Box.html#impl-IntoIterator-for-Box%3C%5BI%5D,+A%3E) -- [`impl FromIterator for Box`](https://doc.rust-lang.org/beta/alloc/boxed/struct.Box.html#impl-FromIterator%3CString%3E-for-Box%3Cstr%3E) +- [`impl FromIterator for Box`](https://doc.rust-lang.org/beta/alloc/boxed/struct.Box.html#impl-FromIterator%3CString%3E-for-Box%3Cstr%3E) - [`impl FromIterator for Box`](https://doc.rust-lang.org/beta/alloc/boxed/struct.Box.html#impl-FromIterator%3Cchar%3E-for-Box%3Cstr%3E) - [`LazyCell`](https://doc.rust-lang.org/beta/core/cell/struct.LazyCell.html) - [`LazyLock`](https://doc.rust-lang.org/beta/std/sync/struct.LazyLock.html) @@ -1816,7 +1816,7 @@ Compiler - [Detect uninhabited types early in const eval](https://github.com/rust-lang/rust/pull/109435/) - [Switch to LLD as default linker for {arm,thumb}v4t-none-eabi](https://github.com/rust-lang/rust/pull/109721/) - [Add tier 3 target `loongarch64-unknown-linux-gnu`](https://github.com/rust-lang/rust/pull/96971) -- [Add tier 3 target for `i586-pc-nto-qnx700` (QNX Neutrino RTOS, version 7.0)](https://github.com/rust-lang/rust/pull/109173/), +- [Add tier 3 target for `i586-pc-nto-qnx700` (QNX Neutrino RTOS, version 7.0)](https://github.com/rust-lang/rust/pull/109173/), - [Insert alignment checks for pointer dereferences as debug assertions](https://github.com/rust-lang/rust/pull/98112) This catches undefined behavior at runtime, and may cause existing code to fail. @@ -2023,7 +2023,7 @@ Compatibility Notes If `tools = [...]` is set in config.toml, we will respect a missing rustdoc in that list. By default rustdoc remains included. To retain the prior behavior explicitly add `"rustdoc"` to the list. - + Internal Changes From ab2ee7aa2f0eb8906b5d04104c93050e703b3936 Mon Sep 17 00:00:00 2001 From: Xing Xue Date: Fri, 6 Dec 2024 15:22:46 -0500 Subject: [PATCH 4/6] Use option "-sf" for the AIX "ln" command. --- tests/run-make/libs-through-symlinks/Makefile | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tests/run-make/libs-through-symlinks/Makefile b/tests/run-make/libs-through-symlinks/Makefile index 592eae663a49a..c6ff566a0e86e 100644 --- a/tests/run-make/libs-through-symlinks/Makefile +++ b/tests/run-make/libs-through-symlinks/Makefile @@ -3,10 +3,20 @@ include ../tools.mk # ignore-windows +# The option -n for the AIX ln command has a different purpose than it does +# on Linux. On Linux, the -n option is used to treat the destination path as +# normal file if it is a symbolic link to a directory, which is the default +# behavior of the AIX ln command. +ifeq ($(UNAME),AIX) +LN_FLAGS := -sf +else +LN_FLAGS := -nsf +endif + NAME := $(shell $(RUSTC) --print file-names foo.rs) all: mkdir -p $(TMPDIR)/outdir $(RUSTC) foo.rs -o $(TMPDIR)/outdir/$(NAME) - ln -nsf outdir/$(NAME) $(TMPDIR) + ln $(LN_FLAGS) outdir/$(NAME) $(TMPDIR) RUSTC_LOG=rustc_metadata::loader $(RUSTC) bar.rs From 8aacd1c6a86ba4211b541aaf5b6d270ebb8727fa Mon Sep 17 00:00:00 2001 From: jyn Date: Sun, 1 Dec 2024 23:57:09 -0500 Subject: [PATCH 5/6] compiletest: show the difference between the normalized output and the actual output for lines which didn't match example output: ``` failures: ---- [ui] tests/ui/layout/enum.rs stdout ---- diff of stderr: - error: align: AbiAndPrefAlign { abi: Align(2 bytes), pref: $PREF_ALIGN } + error: align: AbiAndPrefAlign { abi: Align(2 bytes), pref: $PREF_ALIN } 2 --> $DIR/enum.rs:9:1 3 | 4 LL | enum UninhabitedVariantAlign { Note: some mismatched output was normalized before being compared - error: align: AbiAndPrefAlign { abi: Align(2 bytes), pref: Align(8 bytes) } - --> /home/jyn/src/rust2/tests/ui/layout/enum.rs:9:1 + error: align: AbiAndPrefAlign { abi: Align(2 bytes), pref: $PREF_ALIN } ``` --- src/tools/compiletest/src/runtest.rs | 136 ++++++++++++++---- src/tools/compiletest/src/runtest/coverage.rs | 16 ++- src/tools/compiletest/src/runtest/ui.rs | 2 +- 3 files changed, 119 insertions(+), 35 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 84269fd44a1e0..7b11bf3b1219c 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -22,7 +22,7 @@ use crate::common::{ UI_STDERR, UI_STDOUT, UI_SVG, UI_WINDOWS_SVG, Ui, expected_output_path, incremental_dir, output_base_dir, output_base_name, output_testname_unique, }; -use crate::compute_diff::{write_diff, write_filtered_diff}; +use crate::compute_diff::{DiffLine, make_diff, write_diff, write_filtered_diff}; use crate::errors::{self, Error, ErrorKind}; use crate::header::TestProps; use crate::read2::{Truncated, read2_abbreviated}; @@ -2295,17 +2295,31 @@ impl<'test> TestCx<'test> { match output_kind { TestOutput::Compile => { if !self.props.dont_check_compiler_stdout { - errors += - self.compare_output(stdout_kind, &normalized_stdout, &expected_stdout); + errors += self.compare_output( + stdout_kind, + &normalized_stdout, + &proc_res.stdout, + &expected_stdout, + ); } if !self.props.dont_check_compiler_stderr { - errors += - self.compare_output(stderr_kind, &normalized_stderr, &expected_stderr); + errors += self.compare_output( + stderr_kind, + &normalized_stderr, + &stderr, + &expected_stderr, + ); } } TestOutput::Run => { - errors += self.compare_output(stdout_kind, &normalized_stdout, &expected_stdout); - errors += self.compare_output(stderr_kind, &normalized_stderr, &expected_stderr); + errors += self.compare_output( + stdout_kind, + &normalized_stdout, + &proc_res.stdout, + &expected_stdout, + ); + errors += + self.compare_output(stderr_kind, &normalized_stderr, &stderr, &expected_stderr); } } errors @@ -2533,7 +2547,13 @@ impl<'test> TestCx<'test> { } } - fn compare_output(&self, stream: &str, actual: &str, expected: &str) -> usize { + fn compare_output( + &self, + stream: &str, + actual: &str, + actual_unnormalized: &str, + expected: &str, + ) -> usize { let are_different = match (self.force_color_svg(), expected.find('\n'), actual.find('\n')) { // FIXME: We ignore the first line of SVG files // because the width parameter is non-deterministic. @@ -2590,28 +2610,14 @@ impl<'test> TestCx<'test> { if expected.is_empty() { println!("normalized {}:\n{}\n", stream, actual); } else { - println!("diff of {stream}:\n"); - if let Some(diff_command) = self.config.diff_command.as_deref() { - let mut args = diff_command.split_whitespace(); - let name = args.next().unwrap(); - match Command::new(name) - .args(args) - .args([&expected_path, &actual_path]) - .output() - { - Err(err) => { - self.fatal(&format!( - "failed to call custom diff command `{diff_command}`: {err}" - )); - } - Ok(output) => { - let output = String::from_utf8_lossy(&output.stdout); - print!("{output}"); - } - } - } else { - print!("{}", write_diff(expected, actual, 3)); - } + self.show_diff( + stream, + &expected_path, + &actual_path, + expected, + actual, + actual_unnormalized, + ); } } else { // Delete non-revision .stderr/.stdout file if revisions are used. @@ -2633,6 +2639,76 @@ impl<'test> TestCx<'test> { if self.config.bless { 0 } else { 1 } } + /// Returns whether to show the full stderr/stdout. + fn show_diff( + &self, + stream: &str, + expected_path: &Path, + actual_path: &Path, + expected: &str, + actual: &str, + actual_unnormalized: &str, + ) { + eprintln!("diff of {stream}:\n"); + if let Some(diff_command) = self.config.diff_command.as_deref() { + let mut args = diff_command.split_whitespace(); + let name = args.next().unwrap(); + match Command::new(name).args(args).args([expected_path, actual_path]).output() { + Err(err) => { + self.fatal(&format!( + "failed to call custom diff command `{diff_command}`: {err}" + )); + } + Ok(output) => { + let output = String::from_utf8_lossy(&output.stdout); + eprint!("{output}"); + } + } + } else { + eprint!("{}", write_diff(expected, actual, 3)); + } + + // NOTE: argument order is important, we need `actual` to be on the left so the line number match up when we compare it to `actual_unnormalized` below. + let diff_results = make_diff(actual, expected, 0); + + let (mut mismatches_normalized, mut mismatch_line_nos) = (String::new(), vec![]); + for hunk in diff_results { + let mut line_no = hunk.line_number; + for line in hunk.lines { + // NOTE: `Expected` is actually correct here, the argument order is reversed so our line numbers match up + if let DiffLine::Expected(normalized) = line { + mismatches_normalized += &normalized; + mismatches_normalized += "\n"; + mismatch_line_nos.push(line_no); + line_no += 1; + } + } + } + let mut mismatches_unnormalized = String::new(); + let diff_normalized = make_diff(actual, actual_unnormalized, 0); + for hunk in diff_normalized { + if mismatch_line_nos.contains(&hunk.line_number) { + for line in hunk.lines { + if let DiffLine::Resulting(unnormalized) = line { + mismatches_unnormalized += &unnormalized; + mismatches_unnormalized += "\n"; + } + } + } + } + + let normalized_diff = make_diff(&mismatches_normalized, &mismatches_unnormalized, 0); + // HACK: instead of checking if each hunk is empty, this only checks if the whole input is empty. we should be smarter about this so we don't treat added or removed output as normalized. + if !normalized_diff.is_empty() + && !mismatches_unnormalized.is_empty() + && !mismatches_normalized.is_empty() + { + eprintln!("Note: some mismatched output was normalized before being compared"); + // FIXME: respect diff_command + eprint!("{}", write_diff(&mismatches_unnormalized, &mismatches_normalized, 0)); + } + } + fn check_and_prune_duplicate_outputs( &self, proc_res: &ProcRes, diff --git a/src/tools/compiletest/src/runtest/coverage.rs b/src/tools/compiletest/src/runtest/coverage.rs index 961a160298631..030ca5ebb2474 100644 --- a/src/tools/compiletest/src/runtest/coverage.rs +++ b/src/tools/compiletest/src/runtest/coverage.rs @@ -39,8 +39,12 @@ impl<'test> TestCx<'test> { let expected_coverage_dump = self.load_expected_output(kind); let actual_coverage_dump = self.normalize_output(&proc_res.stdout, &[]); - let coverage_dump_errors = - self.compare_output(kind, &actual_coverage_dump, &expected_coverage_dump); + let coverage_dump_errors = self.compare_output( + kind, + &actual_coverage_dump, + &proc_res.stdout, + &expected_coverage_dump, + ); if coverage_dump_errors > 0 { self.fatal_proc_rec( @@ -135,8 +139,12 @@ impl<'test> TestCx<'test> { self.fatal_proc_rec(&err, &proc_res); }); - let coverage_errors = - self.compare_output(kind, &normalized_actual_coverage, &expected_coverage); + let coverage_errors = self.compare_output( + kind, + &normalized_actual_coverage, + &proc_res.stdout, + &expected_coverage, + ); if coverage_errors > 0 { self.fatal_proc_rec( diff --git a/src/tools/compiletest/src/runtest/ui.rs b/src/tools/compiletest/src/runtest/ui.rs index bb747c6802926..172b1e32aad3b 100644 --- a/src/tools/compiletest/src/runtest/ui.rs +++ b/src/tools/compiletest/src/runtest/ui.rs @@ -100,7 +100,7 @@ impl TestCx<'_> { ) }); - errors += self.compare_output("fixed", &fixed_code, &expected_fixed); + errors += self.compare_output("fixed", &fixed_code, &fixed_code, &expected_fixed); } else if !expected_fixed.is_empty() { panic!( "the `//@ run-rustfix` directive wasn't found but a `*.fixed` \ From 9b07e750553fa9ad9b87e8e567bf05edf1001424 Mon Sep 17 00:00:00 2001 From: shamb0 Date: Wed, 4 Dec 2024 21:09:50 +0530 Subject: [PATCH 6/6] Add allocate_bytes and refactor allocate_str in InterpCx for raw byte allocation Signed-off-by: shamb0 --- .../rustc_const_eval/src/interpret/place.rs | 45 +++++++++++++------ 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 2beec544fad97..f54a932e1b6f5 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -1018,29 +1018,48 @@ where self.allocate_dyn(layout, kind, MemPlaceMeta::None) } - /// Returns a wide MPlace of type `str` to a new 1-aligned allocation. - /// Immutable strings are deduplicated and stored in global memory. - pub fn allocate_str( + /// Allocates a sequence of bytes in the interpreter's memory. + /// For immutable allocations, uses deduplication to reuse existing memory. + /// For mutable allocations, creates a new unique allocation. + pub fn allocate_bytes( &mut self, - str: &str, + bytes: &[u8], + align: Align, kind: MemoryKind, mutbl: Mutability, - ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> { - let tcx = self.tcx.tcx; - + ) -> InterpResult<'tcx, Pointer> { // Use cache for immutable strings. - let ptr = if mutbl.is_not() { + if mutbl.is_not() { // Use dedup'd allocation function. let salt = M::get_global_alloc_salt(self, None); - let id = tcx.allocate_bytes_dedup(str.as_bytes(), salt); + let id = self.tcx.allocate_bytes_dedup(bytes, salt); // Turn untagged "global" pointers (obtained via `tcx`) into the machine pointer to the allocation. - M::adjust_alloc_root_pointer(&self, Pointer::from(id), Some(kind))? + M::adjust_alloc_root_pointer(&self, Pointer::from(id), Some(kind)) } else { - self.allocate_bytes_ptr(str.as_bytes(), Align::ONE, kind, mutbl)? - }; - let meta = Scalar::from_target_usize(u64::try_from(str.len()).unwrap(), self); + // Allocate new memory for mutable data. + self.allocate_bytes_ptr(bytes, align, kind, mutbl) + } + } + + /// Allocates a string in the interpreter's memory with metadata for length. + /// Uses `allocate_bytes` internally but adds string-specific metadata handling. + pub fn allocate_str( + &mut self, + str: &str, + kind: MemoryKind, + mutbl: Mutability, + ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> { + let bytes = str.as_bytes(); + let ptr = self.allocate_bytes(bytes, Align::ONE, kind, mutbl)?; + + // Create length metadata for the string. + let meta = Scalar::from_target_usize(u64::try_from(bytes.len()).unwrap(), self); + + // Get layout for Rust's str type. let layout = self.layout_of(self.tcx.types.str_).unwrap(); + + // Combine pointer and metadata into a wide pointer. interp_ok(self.ptr_with_meta_to_mplace( ptr.into(), MemPlaceMeta::Meta(meta),