mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Auto merge of #155674 - JonathanBrouwer:rollup-NG1fnzG, r=JonathanBrouwer
Rollup of 10 pull requests Successful merges: - rust-lang/rust#146544 (mir-opt: Remove the workaround in UnreachableEnumBranching) - rust-lang/rust#154819 (Fix ICE for inherent associated type mismatches) - rust-lang/rust#155265 (Improved assumptions relating to isqrt) - rust-lang/rust#152576 (c-variadic: use `emit_ptr_va_arg` for mips) - rust-lang/rust#154481 (Mark a function only used in nightly as nightly only) - rust-lang/rust#155614 (c-variadic: rename `VaList::arg` to `VaList::next_arg`) - rust-lang/rust#155630 (Make `//@ skip-filecheck` a normal compiletest directive) - rust-lang/rust#155641 (Remove non-working code for "running" mir-opt tests) - rust-lang/rust#155652 (Expand `Path::is_empty` docs) - rust-lang/rust#155656 (rustc_llvm: update opt-level handling for LLVM 23)
This commit is contained in:
@@ -35,6 +35,7 @@ pub fn unit(self) -> Option<Reg> {
|
||||
/// Try to combine two `HomogeneousAggregate`s, e.g. from two fields in
|
||||
/// the same `struct`. Only succeeds if only one of them has any data,
|
||||
/// or both units are identical.
|
||||
#[cfg(feature = "nightly")]
|
||||
fn merge(self, other: HomogeneousAggregate) -> Result<HomogeneousAggregate, Heterogeneous> {
|
||||
match (self, other) {
|
||||
(x, HomogeneousAggregate::NoData) | (HomogeneousAggregate::NoData, x) => Ok(x),
|
||||
|
||||
@@ -1171,14 +1171,29 @@ pub(super) fn emit_va_arg<'ll, 'tcx>(
|
||||
AllowHigherAlign::Yes,
|
||||
ForceRightAdjust::No,
|
||||
),
|
||||
Arch::Mips | Arch::Mips32r6 | Arch::Mips64 | Arch::Mips64r6 => emit_ptr_va_arg(
|
||||
bx,
|
||||
addr,
|
||||
target_ty,
|
||||
PassMode::Direct,
|
||||
match &target.llvm_abiname {
|
||||
LlvmAbi::N32 | LlvmAbi::N64 => SlotSize::Bytes8,
|
||||
LlvmAbi::O32 => SlotSize::Bytes4,
|
||||
other => bug!("unexpected LLVM ABI {other}"),
|
||||
},
|
||||
AllowHigherAlign::Yes,
|
||||
// In big-endian mode the actual value is stored in the right side of the slot, meaning
|
||||
// that when the value is smaller than a slot, we need to adjust the pointer we read
|
||||
// to somewhere in the middle of the slot.
|
||||
match bx.tcx().sess.target.endian {
|
||||
Endian::Big => ForceRightAdjust::Yes,
|
||||
Endian::Little => ForceRightAdjust::No,
|
||||
},
|
||||
),
|
||||
|
||||
Arch::Bpf => bug!("bpf does not support c-variadic functions"),
|
||||
Arch::SpirV => bug!("spirv does not support c-variadic functions"),
|
||||
|
||||
Arch::Mips | Arch::Mips32r6 | Arch::Mips64 | Arch::Mips64r6 => {
|
||||
// FIXME: port MipsTargetLowering::lowerVAARG.
|
||||
bx.va_arg(addr.immediate(), bx.cx.layout_of(target_ty).llvm_type(bx.cx))
|
||||
}
|
||||
Arch::Sparc | Arch::Avr | Arch::M68k | Arch::Msp430 => {
|
||||
// Clang uses the LLVM implementation for these architectures.
|
||||
bx.va_arg(addr.immediate(), bx.cx.layout_of(target_ty).llvm_type(bx.cx))
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
use std::marker::PhantomData;
|
||||
#[cfg(not(feature = "nightly"))]
|
||||
use std::mem;
|
||||
use std::ops::{Bound, Range, RangeBounds};
|
||||
use std::rc::Rc;
|
||||
use std::{fmt, iter, slice};
|
||||
|
||||
@@ -165,10 +165,17 @@ static OptimizationLevel fromRust(LLVMRustPassBuilderOptLevel Level) {
|
||||
return OptimizationLevel::O2;
|
||||
case LLVMRustPassBuilderOptLevel::O3:
|
||||
return OptimizationLevel::O3;
|
||||
#if LLVM_VERSION_GE(23, 0)
|
||||
case LLVMRustPassBuilderOptLevel::Os:
|
||||
return OptimizationLevel::O2;
|
||||
case LLVMRustPassBuilderOptLevel::Oz:
|
||||
return OptimizationLevel::O2;
|
||||
#else
|
||||
case LLVMRustPassBuilderOptLevel::Os:
|
||||
return OptimizationLevel::Os;
|
||||
case LLVMRustPassBuilderOptLevel::Oz:
|
||||
return OptimizationLevel::Oz;
|
||||
#endif
|
||||
default:
|
||||
report_fatal_error("Bad PassBuilderOptLevel.");
|
||||
}
|
||||
|
||||
@@ -4,8 +4,7 @@
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::mir::{
|
||||
BasicBlock, BasicBlockData, BasicBlocks, Body, Local, Operand, Rvalue, StatementKind,
|
||||
TerminatorKind,
|
||||
BasicBlockData, Body, Local, Operand, Rvalue, StatementKind, TerminatorKind,
|
||||
};
|
||||
use rustc_middle::ty::layout::TyAndLayout;
|
||||
use rustc_middle::ty::{Ty, TyCtxt};
|
||||
@@ -125,43 +124,10 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||
unreachable_targets.push(index);
|
||||
}
|
||||
}
|
||||
let otherwise_is_empty_unreachable =
|
||||
body.basic_blocks[targets.otherwise()].is_empty_unreachable();
|
||||
fn check_successors(basic_blocks: &BasicBlocks<'_>, bb: BasicBlock) -> bool {
|
||||
// After resolving https://github.com/llvm/llvm-project/issues/78578,
|
||||
// We can remove this check.
|
||||
// The main issue here is that `early-tailduplication` causes compile time overhead
|
||||
// and potential performance problems.
|
||||
// Simply put, when encounter a switch (indirect branch) statement,
|
||||
// `early-tailduplication` tries to duplicate the switch branch statement with BB
|
||||
// into (each) predecessors. This makes CFG very complex.
|
||||
// We can understand it as it transforms the following code
|
||||
// ```rust
|
||||
// match a { ... many cases };
|
||||
// match b { ... many cases };
|
||||
// ```
|
||||
// into
|
||||
// ```rust
|
||||
// match a { ... many match b { goto BB cases } }
|
||||
// ... BB cases
|
||||
// ```
|
||||
// Abandon this transformation when it is possible (the best effort)
|
||||
// to encounter the problem.
|
||||
let mut successors = basic_blocks[bb].terminator().successors();
|
||||
let Some(first_successor) = successors.next() else { return true };
|
||||
if successors.next().is_some() {
|
||||
return true;
|
||||
}
|
||||
if let TerminatorKind::SwitchInt { .. } =
|
||||
&basic_blocks[first_successor].terminator().kind
|
||||
{
|
||||
return false;
|
||||
};
|
||||
true
|
||||
}
|
||||
|
||||
// If and only if there is a variant that does not have a branch set, change the
|
||||
// current of otherwise as the variant branch and set otherwise to unreachable. It
|
||||
// transforms following code
|
||||
// transforms the following code
|
||||
// ```rust
|
||||
// match c {
|
||||
// Ordering::Less => 1,
|
||||
@@ -177,15 +143,8 @@ fn check_successors(basic_blocks: &BasicBlocks<'_>, bb: BasicBlock) -> bool {
|
||||
// Ordering::Greater => 3,
|
||||
// }
|
||||
// ```
|
||||
let otherwise_is_last_variant = !otherwise_is_empty_unreachable
|
||||
&& allowed_variants.len() == 1
|
||||
// Despite the LLVM issue, we hope that small enum can still be transformed.
|
||||
// This is valuable for both `a <= b` and `if let Some/Ok(v)`.
|
||||
&& (targets.all_targets().len() <= 3
|
||||
|| check_successors(&body.basic_blocks, targets.otherwise()));
|
||||
let replace_otherwise_to_unreachable = otherwise_is_last_variant
|
||||
|| (!otherwise_is_empty_unreachable && allowed_variants.is_empty());
|
||||
|
||||
let replace_otherwise_to_unreachable = allowed_variants.len() <= 1
|
||||
&& !body.basic_blocks[targets.otherwise()].is_empty_unreachable();
|
||||
if unreachable_targets.is_empty() && !replace_otherwise_to_unreachable {
|
||||
continue;
|
||||
}
|
||||
@@ -193,6 +152,7 @@ fn check_successors(basic_blocks: &BasicBlocks<'_>, bb: BasicBlock) -> bool {
|
||||
let unreachable_block = patch.unreachable_no_cleanup_block();
|
||||
let mut targets = targets.clone();
|
||||
if replace_otherwise_to_unreachable {
|
||||
let otherwise_is_last_variant = allowed_variants.len() == 1;
|
||||
if otherwise_is_last_variant {
|
||||
// We have checked that `allowed_variants` has only one element.
|
||||
#[allow(rustc::potential_query_instability)]
|
||||
|
||||
@@ -606,6 +606,10 @@ fn suggest_constraint(
|
||||
ty: Ty<'tcx>,
|
||||
) -> bool {
|
||||
let tcx = self.tcx;
|
||||
// FIXME(inherent_associated_types): Extend this to support `ty::Inherent`, too.
|
||||
if !matches!(proj_ty.kind, ty::AliasTyKind::Projection { .. }) {
|
||||
return false;
|
||||
}
|
||||
let Some(body_owner_def_id) = body_owner_def_id else {
|
||||
return false;
|
||||
};
|
||||
|
||||
@@ -204,7 +204,7 @@ struct VaListInner {
|
||||
/// unsafe fn vmy_func(count: u32, mut ap: VaList<'_>) -> i32 {
|
||||
/// let mut sum = 0;
|
||||
/// for _ in 0..count {
|
||||
/// sum += unsafe { ap.arg::<i32>() };
|
||||
/// sum += unsafe { ap.next_arg::<i32>() };
|
||||
/// }
|
||||
/// sum
|
||||
/// }
|
||||
@@ -213,7 +213,7 @@ struct VaListInner {
|
||||
/// assert_eq!(unsafe { my_func(3, 42i32, -7i32, 20i32) }, 55);
|
||||
/// ```
|
||||
///
|
||||
/// The [`VaList::arg`] method reads the next argument from the variable argument list,
|
||||
/// The [`VaList::next_arg`] method reads the next argument from the variable argument list,
|
||||
/// and is equivalent to C `va_arg`.
|
||||
///
|
||||
/// Cloning a `VaList` performs the equivalent of C `va_copy`, producing an independent cursor
|
||||
@@ -284,7 +284,7 @@ impl<T> Sealed for *mut T {}
|
||||
impl<T> Sealed for *const T {}
|
||||
}
|
||||
|
||||
/// Types that are valid to read using [`VaList::arg`].
|
||||
/// Types that are valid to read using [`VaList::next_arg`].
|
||||
///
|
||||
/// This trait is implemented for primitive types that have a variable argument application-binary
|
||||
/// interface (ABI) on the current platform. It is always implemented for:
|
||||
@@ -391,7 +391,7 @@ impl<'f> VaList<'f> {
|
||||
/// are no more variable arguments, is unsound.
|
||||
#[inline] // Avoid codegen when not used to help backends that don't support VaList.
|
||||
#[rustc_const_unstable(feature = "const_c_variadic", issue = "151787")]
|
||||
pub const unsafe fn arg<T: VaArgSafe>(&mut self) -> T {
|
||||
pub const unsafe fn next_arg<T: VaArgSafe>(&mut self) -> T {
|
||||
// SAFETY: the caller must uphold the safety contract for `va_arg`.
|
||||
unsafe { va_arg(self) }
|
||||
}
|
||||
|
||||
@@ -41,36 +41,6 @@ pub(in crate::num) const fn u8(n: u8) -> u8 {
|
||||
U8_ISQRT_WITH_REMAINDER[n as usize].0
|
||||
}
|
||||
|
||||
/// Generates an `i*` function that returns the [integer square root](
|
||||
/// https://en.wikipedia.org/wiki/Integer_square_root) of any **nonnegative**
|
||||
/// input of a specific signed integer type.
|
||||
macro_rules! signed_fn {
|
||||
($SignedT:ident, $UnsignedT:ident) => {
|
||||
/// Returns the [integer square root](
|
||||
/// https://en.wikipedia.org/wiki/Integer_square_root) of any
|
||||
/// **nonnegative**
|
||||
#[doc = concat!("[`", stringify!($SignedT), "`](prim@", stringify!($SignedT), ")")]
|
||||
/// input.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This results in undefined behavior when the input is negative.
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub(in crate::num) const unsafe fn $SignedT(n: $SignedT) -> $SignedT {
|
||||
debug_assert!(n >= 0, "Negative input inside `isqrt`.");
|
||||
$UnsignedT(n as $UnsignedT) as $SignedT
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
signed_fn!(i8, u8);
|
||||
signed_fn!(i16, u16);
|
||||
signed_fn!(i32, u32);
|
||||
signed_fn!(i64, u64);
|
||||
signed_fn!(i128, u128);
|
||||
|
||||
/// Generates a `u*` function that returns the [integer square root](
|
||||
/// https://en.wikipedia.org/wiki/Integer_square_root) of any input of
|
||||
/// a specific unsigned integer type.
|
||||
|
||||
@@ -1933,10 +1933,9 @@ pub const fn checked_isqrt(self) -> Option<Self> {
|
||||
if self < 0 {
|
||||
None
|
||||
} else {
|
||||
// SAFETY: Input is nonnegative in this `else` branch.
|
||||
let result = unsafe {
|
||||
imp::int_sqrt::$ActualT(self as $ActualT) as $SelfT
|
||||
};
|
||||
// The upper bound of `$UnsignedT::MAX.isqrt()` told to the compiler
|
||||
// in the unsigned function also tells it that `result >= 0`
|
||||
let result = self.cast_unsigned().isqrt().cast_signed();
|
||||
|
||||
// Inform the optimizer what the range of outputs is. If
|
||||
// testing `core` crashes with no panic message and a
|
||||
@@ -1950,15 +1949,9 @@ pub const fn checked_isqrt(self) -> Option<Self> {
|
||||
// `[0, <$ActualT>::MAX]`, sqrt(n) will be bounded by
|
||||
// `[sqrt(0), sqrt(<$ActualT>::MAX)]`.
|
||||
unsafe {
|
||||
// SAFETY: `<$ActualT>::MAX` is nonnegative.
|
||||
const MAX_RESULT: $SelfT = unsafe {
|
||||
imp::int_sqrt::$ActualT(<$ActualT>::MAX) as $SelfT
|
||||
};
|
||||
|
||||
crate::hint::assert_unchecked(result >= 0);
|
||||
const MAX_RESULT: $SelfT = <$SelfT>::MAX.cast_unsigned().isqrt().cast_signed();
|
||||
crate::hint::assert_unchecked(result <= MAX_RESULT);
|
||||
}
|
||||
|
||||
Some(result)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3682,7 +3682,7 @@ pub const fn pow(self, mut exp: u32) -> Self {
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn isqrt(self) -> Self {
|
||||
let result = imp::int_sqrt::$ActualT(self as $ActualT) as $SelfT;
|
||||
let result = imp::int_sqrt::$ActualT(self as $ActualT) as Self;
|
||||
|
||||
// Inform the optimizer what the range of outputs is. If testing
|
||||
// `core` crashes with no panic message and a `num::int_sqrt::u*`
|
||||
@@ -3693,10 +3693,29 @@ pub const fn isqrt(self) -> Self {
|
||||
// function, which means that increasing the input will never
|
||||
// cause the output to decrease. Thus, since the input for unsigned
|
||||
// integers is bounded by `[0, <$ActualT>::MAX]`, sqrt(n) will be
|
||||
// bounded by `[sqrt(0), sqrt(<$ActualT>::MAX)]`.
|
||||
// bounded by `[sqrt(0), sqrt(<$ActualT>::MAX)]` and bounding the
|
||||
// input by `[1, <$ActualT>::MAX]` bounds sqrt(n) by
|
||||
// `[sqrt(1), sqrt(<$ActualT>::MAX)]`.
|
||||
unsafe {
|
||||
const MAX_RESULT: $SelfT = imp::int_sqrt::$ActualT(<$ActualT>::MAX) as $SelfT;
|
||||
crate::hint::assert_unchecked(result <= MAX_RESULT);
|
||||
crate::hint::assert_unchecked(result <= MAX_RESULT)
|
||||
}
|
||||
|
||||
if self >= 1 {
|
||||
// SAFETY: The above statements about monotonicity also apply here.
|
||||
// Since the input in this branch is bounded by `[1, <$ActualT>::MAX]`,
|
||||
// sqrt(n) is bounded by `[sqrt(1), sqrt(<$ActualT>::MAX)]`, and
|
||||
// `sqrt(1) == 1`.
|
||||
unsafe { crate::hint::assert_unchecked(result >= 1) }
|
||||
}
|
||||
|
||||
// SAFETY: the isqrt implementation returns the square root and rounds down,
|
||||
// meaning `result * result <= self`. This implies `result <= self`.
|
||||
// The compiler needs both to optimize for both.
|
||||
// `result * result <= self` implies the multiplication will not overflow.
|
||||
unsafe {
|
||||
crate::hint::assert_unchecked(result.unchecked_mul(result) <= self);
|
||||
crate::hint::assert_unchecked(result <= self);
|
||||
}
|
||||
|
||||
result
|
||||
|
||||
@@ -2828,6 +2828,10 @@ fn _ends_with(&self, child: &Path) -> bool {
|
||||
|
||||
/// Checks whether the `Path` is empty.
|
||||
///
|
||||
/// Passing an empty path to most OS filesystem APIs will always result in an error.
|
||||
///
|
||||
/// [Pushing][PathBuf::push] an empty path to an existing path will append a directory separator unless it already ends with a separator or the existing path is itself empty.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
|
||||
@@ -326,6 +326,8 @@ See [Pretty-printer](compiletest.md#pretty-printer-tests).
|
||||
The following directives affect how certain command-line tools are invoked, in
|
||||
test suites that use those tools:
|
||||
|
||||
- `skip-filecheck` avoids running LLVM's `FileCheck` tool in tests that would normally run it to check output.
|
||||
- Used by codegen tests, assembly tests, and mir-opt tests.
|
||||
- `filecheck-flags` adds extra flags when running LLVM's `FileCheck` tool.
|
||||
- Used by [codegen tests](compiletest.md#codegen-tests),
|
||||
[assembly tests](compiletest.md#assembly-tests), and
|
||||
|
||||
@@ -17,7 +17,7 @@ defined in Rust. They may be called both from within Rust and via FFI.
|
||||
pub unsafe extern "C" fn add(n: usize, mut args: ...) -> usize {
|
||||
let mut sum = 0;
|
||||
for _ in 0..n {
|
||||
sum += args.arg::<usize>();
|
||||
sum += args.next_arg::<usize>();
|
||||
}
|
||||
sum
|
||||
}
|
||||
|
||||
@@ -195,6 +195,9 @@ pub(crate) struct TestProps {
|
||||
/// Extra flags to pass to `llvm-cov` when producing coverage reports.
|
||||
/// Only used by the "coverage-run" test mode.
|
||||
pub(crate) llvm_cov_flags: Vec<String>,
|
||||
/// Don't run LLVM's `filecheck` tool to check compiler output,
|
||||
/// in tests that would normally run it.
|
||||
pub(crate) skip_filecheck: bool,
|
||||
/// Extra flags to pass to LLVM's `filecheck` tool, in tests that use it.
|
||||
pub(crate) filecheck_flags: Vec<String>,
|
||||
/// Don't automatically insert any `--check-cfg` args
|
||||
@@ -308,6 +311,7 @@ pub(crate) fn new() -> Self {
|
||||
mir_unit_test: None,
|
||||
remap_src_base: false,
|
||||
llvm_cov_flags: vec![],
|
||||
skip_filecheck: false,
|
||||
filecheck_flags: vec![],
|
||||
no_auto_check_cfg: false,
|
||||
add_minicore: false,
|
||||
@@ -438,7 +442,6 @@ fn update_pass_mode(&mut self, ln: &DirectiveLine<'_>, config: &Config) {
|
||||
let check_no_run = |s| match (config.mode, s) {
|
||||
(TestMode::Ui, _) => (),
|
||||
(TestMode::Crashes, _) => (),
|
||||
(TestMode::Codegen, "build-pass") => (),
|
||||
(mode, _) => panic!("`{s}` directive is not supported in `{mode}` tests"),
|
||||
};
|
||||
let pass_mode = if config.parse_name_directive(ln, "check-pass") {
|
||||
|
||||
@@ -286,6 +286,7 @@
|
||||
"rustc-env",
|
||||
"rustfix-only-machine-applicable",
|
||||
"should-fail",
|
||||
"skip-filecheck",
|
||||
"stderr-per-bitwidth",
|
||||
"test-mir-pass",
|
||||
"unique-doc-out-dir",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::collections::HashMap;
|
||||
use std::sync::{Arc, LazyLock};
|
||||
|
||||
use crate::common::Config;
|
||||
use crate::common::{Config, TestMode};
|
||||
use crate::directives::{
|
||||
DirectiveLine, NormalizeKind, NormalizeRule, TestProps, parse_and_update_aux,
|
||||
parse_edition_range, split_flags,
|
||||
@@ -312,6 +312,18 @@ fn make_directive_handlers_map() -> HashMap<&'static str, Handler> {
|
||||
props.llvm_cov_flags.extend(split_flags(&flags));
|
||||
}
|
||||
}),
|
||||
handler("skip-filecheck", |config, ln, props| {
|
||||
let directive_name = ln.name;
|
||||
// FIXME(Zalathar): Someday we should add unified support for declaring
|
||||
// and checking which modes are supported by each directive.
|
||||
if !matches!(config.mode, TestMode::Assembly | TestMode::Codegen | TestMode::MirOpt) {
|
||||
panic!(
|
||||
"directive `//@ {directive_name}` is not supported by this test suite (mode: {mode:?})",
|
||||
mode = config.mode
|
||||
);
|
||||
}
|
||||
config.set_name_directive(ln, directive_name, &mut props.skip_filecheck);
|
||||
}),
|
||||
handler(FILECHECK_FLAGS, |config, ln, props| {
|
||||
if let Some(flags) = config.parse_name_value_directive(ln, FILECHECK_FLAGS) {
|
||||
props.filecheck_flags.extend(split_flags(&flags));
|
||||
|
||||
@@ -295,14 +295,9 @@ fn pass_mode(&self) -> Option<PassMode> {
|
||||
|
||||
fn should_run(&self, pm: Option<PassMode>) -> WillExecute {
|
||||
let test_should_run = match self.config.mode {
|
||||
TestMode::Ui
|
||||
if pm == Some(PassMode::Run)
|
||||
|| matches!(self.props.fail_mode, Some(FailMode::Run(_))) =>
|
||||
{
|
||||
true
|
||||
TestMode::Ui => {
|
||||
pm == Some(PassMode::Run) || matches!(self.props.fail_mode, Some(FailMode::Run(_)))
|
||||
}
|
||||
TestMode::MirOpt if pm == Some(PassMode::Run) => true,
|
||||
TestMode::Ui | TestMode::MirOpt => false,
|
||||
mode => panic!("unimplemented for mode {:?}", mode),
|
||||
};
|
||||
if test_should_run { self.run_if_enabled() } else { WillExecute::No }
|
||||
@@ -314,7 +309,7 @@ fn run_if_enabled(&self) -> WillExecute {
|
||||
|
||||
fn should_run_successfully(&self, pm: Option<PassMode>) -> bool {
|
||||
match self.config.mode {
|
||||
TestMode::Ui | TestMode::MirOpt => pm == Some(PassMode::Run),
|
||||
TestMode::Ui => pm == Some(PassMode::Run),
|
||||
mode => panic!("unimplemented for mode {:?}", mode),
|
||||
}
|
||||
}
|
||||
@@ -935,23 +930,13 @@ fn should_emit_metadata(&self, pm: Option<PassMode>) -> Emit {
|
||||
}
|
||||
|
||||
fn compile_test(&self, will_execute: WillExecute, emit: Emit) -> ProcRes {
|
||||
self.compile_test_general(will_execute, emit, self.props.local_pass_mode(), Vec::new())
|
||||
}
|
||||
|
||||
fn compile_test_with_passes(
|
||||
&self,
|
||||
will_execute: WillExecute,
|
||||
emit: Emit,
|
||||
passes: Vec<String>,
|
||||
) -> ProcRes {
|
||||
self.compile_test_general(will_execute, emit, self.props.local_pass_mode(), passes)
|
||||
self.compile_test_general(will_execute, emit, Vec::new())
|
||||
}
|
||||
|
||||
fn compile_test_general(
|
||||
&self,
|
||||
will_execute: WillExecute,
|
||||
emit: Emit,
|
||||
local_pm: Option<PassMode>,
|
||||
passes: Vec<String>,
|
||||
) -> ProcRes {
|
||||
let compiler_kind = self.compiler_kind_for_non_aux();
|
||||
@@ -975,7 +960,7 @@ fn compile_test_general(
|
||||
// Note that we use the local pass mode here as we don't want
|
||||
// to set unused to allow if we've overridden the pass mode
|
||||
// via command line flags.
|
||||
&& local_pm != Some(PassMode::Run)
|
||||
&& self.props.local_pass_mode() != Some(PassMode::Run)
|
||||
{
|
||||
AllowUnused::Yes
|
||||
} else {
|
||||
|
||||
@@ -13,9 +13,11 @@ pub(super) fn run_assembly_test(&self) {
|
||||
self.fatal_proc_rec("compilation failed!", &proc_res);
|
||||
}
|
||||
|
||||
let proc_res = self.verify_with_filecheck(&output_path);
|
||||
if !proc_res.status.success() {
|
||||
self.fatal_proc_rec("verification with 'FileCheck' failed", &proc_res);
|
||||
if !self.props.skip_filecheck {
|
||||
let proc_res = self.verify_with_filecheck(&output_path);
|
||||
if !proc_res.status.success() {
|
||||
self.fatal_proc_rec("verification with 'FileCheck' failed", &proc_res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use super::{PassMode, TestCx};
|
||||
use super::TestCx;
|
||||
|
||||
impl TestCx<'_> {
|
||||
pub(super) fn run_codegen_test(&self) {
|
||||
@@ -11,12 +11,11 @@ pub(super) fn run_codegen_test(&self) {
|
||||
self.fatal_proc_rec("compilation failed!", &proc_res);
|
||||
}
|
||||
|
||||
if let Some(PassMode::Build) = self.pass_mode() {
|
||||
return;
|
||||
}
|
||||
let proc_res = self.verify_with_filecheck(&output_path);
|
||||
if !proc_res.status.success() {
|
||||
self.fatal_proc_rec("verification with 'FileCheck' failed", &proc_res);
|
||||
if !self.props.skip_filecheck {
|
||||
let proc_res = self.verify_with_filecheck(&output_path);
|
||||
if !proc_res.status.success() {
|
||||
self.fatal_proc_rec("verification with 'FileCheck' failed", &proc_res);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,9 +10,6 @@
|
||||
|
||||
impl TestCx<'_> {
|
||||
pub(super) fn run_mir_opt_test(&self) {
|
||||
let pm = self.pass_mode();
|
||||
let should_run = self.should_run(pm);
|
||||
|
||||
let mut test_info = files_for_miropt_test(
|
||||
&self.testpaths.file.as_std_path(),
|
||||
self.config.get_pointer_width(),
|
||||
@@ -21,26 +18,18 @@ pub(super) fn run_mir_opt_test(&self) {
|
||||
|
||||
let passes = std::mem::take(&mut test_info.passes);
|
||||
|
||||
let proc_res = self.compile_test_with_passes(should_run, Emit::Mir, passes);
|
||||
let proc_res = self.compile_test_general(WillExecute::No, Emit::Mir, passes);
|
||||
if !proc_res.status.success() {
|
||||
self.fatal_proc_rec("compilation failed!", &proc_res);
|
||||
}
|
||||
self.check_mir_dump(test_info);
|
||||
|
||||
if let WillExecute::Yes = should_run {
|
||||
let proc_res = self.exec_compiled_test();
|
||||
|
||||
if !proc_res.status.success() {
|
||||
self.fatal_proc_rec("test run failed!", &proc_res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_mir_dump(&self, test_info: MiroptTest) {
|
||||
let test_dir = self.testpaths.file.parent().unwrap();
|
||||
let test_crate = self.testpaths.file.file_stem().unwrap().replace('-', "_");
|
||||
|
||||
let MiroptTest { run_filecheck, suffix, files, passes: _ } = test_info;
|
||||
let MiroptTest { suffix, files, passes: _ } = test_info;
|
||||
|
||||
if self.config.bless {
|
||||
for e in glob(&format!("{}/{}.*{}.mir", test_dir, test_crate, suffix)).unwrap() {
|
||||
@@ -89,7 +78,7 @@ fn check_mir_dump(&self, test_info: MiroptTest) {
|
||||
}
|
||||
}
|
||||
|
||||
if run_filecheck {
|
||||
if !self.props.skip_filecheck {
|
||||
let output_path = self.output_base_name().with_extension("mir");
|
||||
let proc_res = self.verify_with_filecheck(&output_path);
|
||||
if !proc_res.status.success() {
|
||||
|
||||
@@ -15,10 +15,12 @@ impl TestCx<'_> {
|
||||
pub(super) fn run_ui_test(&self) {
|
||||
if let Some(FailMode::Build) = self.props.fail_mode {
|
||||
// Make sure a build-fail test cannot fail due to failing analysis (e.g. typeck).
|
||||
let pm = Some(PassMode::Check);
|
||||
let proc_res =
|
||||
self.compile_test_general(WillExecute::No, Emit::Metadata, pm, Vec::new());
|
||||
self.check_if_test_should_compile(self.props.fail_mode, pm, &proc_res);
|
||||
let proc_res = self.compile_test(WillExecute::No, Emit::Metadata);
|
||||
self.check_if_test_should_compile(
|
||||
self.props.fail_mode,
|
||||
Some(PassMode::Check),
|
||||
&proc_res,
|
||||
);
|
||||
}
|
||||
|
||||
let pm = self.pass_mode();
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
fn read_too_many() {
|
||||
unsafe extern "C" fn variadic(mut ap: ...) {
|
||||
ap.arg::<i32>();
|
||||
ap.next_arg::<i32>();
|
||||
}
|
||||
|
||||
unsafe { variadic() };
|
||||
|
||||
@@ -7,7 +7,7 @@ LL | unsafe { va_arg(self) }
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
= note: stack backtrace:
|
||||
0: std::ffi::VaList::<'_>::arg
|
||||
0: std::ffi::VaList::<'_>::next_arg
|
||||
at RUSTLIB/core/src/ffi/va_list.rs:LL:CC
|
||||
1: read_too_many::variadic
|
||||
at tests/fail/c-variadic.rs:LL:CC
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
|
||||
fn main() {
|
||||
unsafe extern "C" fn variadic(mut ap: ...) {
|
||||
ap.arg::<i32>();
|
||||
ap.arg::<i32>();
|
||||
ap.next_arg::<i32>();
|
||||
ap.next_arg::<i32>();
|
||||
}
|
||||
|
||||
unsafe { variadic(0i32, (), 1i32) }
|
||||
|
||||
@@ -11,7 +11,7 @@ fn ignores_arguments() {
|
||||
|
||||
fn echo() {
|
||||
unsafe extern "C" fn variadic(mut ap: ...) -> i32 {
|
||||
ap.arg()
|
||||
ap.next_arg()
|
||||
}
|
||||
|
||||
assert_eq!(unsafe { variadic(1) }, 1);
|
||||
@@ -20,7 +20,7 @@ fn echo() {
|
||||
|
||||
fn forward_by_val() {
|
||||
unsafe fn helper(mut ap: VaList) -> i32 {
|
||||
ap.arg()
|
||||
ap.next_arg()
|
||||
}
|
||||
|
||||
unsafe extern "C" fn variadic(ap: ...) -> i32 {
|
||||
@@ -33,7 +33,7 @@ unsafe fn helper(mut ap: VaList) -> i32 {
|
||||
|
||||
fn forward_by_ref() {
|
||||
unsafe fn helper(ap: &mut VaList) -> i32 {
|
||||
ap.arg()
|
||||
ap.next_arg()
|
||||
}
|
||||
|
||||
unsafe extern "C" fn variadic(mut ap: ...) -> i32 {
|
||||
@@ -47,7 +47,7 @@ unsafe fn helper(ap: &mut VaList) -> i32 {
|
||||
#[allow(improper_ctypes_definitions)]
|
||||
fn nested() {
|
||||
unsafe fn helper(mut ap1: VaList, mut ap2: VaList) -> (i32, i32) {
|
||||
(ap1.arg(), ap2.arg())
|
||||
(ap1.next_arg(), ap2.next_arg())
|
||||
}
|
||||
|
||||
unsafe extern "C" fn variadic2(ap1: VaList, ap2: ...) -> (i32, i32) {
|
||||
@@ -83,13 +83,13 @@ unsafe fn compare_c_str(ptr: *const c_char, val: &str) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
continue_if!(ap.arg::<c_double>().floor() == 3.14f64.floor());
|
||||
continue_if!(ap.arg::<c_long>() == 12);
|
||||
continue_if!(ap.arg::<c_int>() == 'a' as c_int);
|
||||
continue_if!(ap.arg::<c_double>().floor() == 6.18f64.floor());
|
||||
continue_if!(compare_c_str(ap.arg::<*const c_char>(), "Hello"));
|
||||
continue_if!(ap.arg::<c_int>() == 42);
|
||||
continue_if!(compare_c_str(ap.arg::<*const c_char>(), "World"));
|
||||
continue_if!(ap.next_arg::<c_double>().floor() == 3.14f64.floor());
|
||||
continue_if!(ap.next_arg::<c_long>() == 12);
|
||||
continue_if!(ap.next_arg::<c_int>() == 'a' as c_int);
|
||||
continue_if!(ap.next_arg::<c_double>().floor() == 6.18f64.floor());
|
||||
continue_if!(compare_c_str(ap.next_arg::<*const c_char>(), "Hello"));
|
||||
continue_if!(ap.next_arg::<c_int>() == 42);
|
||||
continue_if!(compare_c_str(ap.next_arg::<*const c_char>(), "World"));
|
||||
}
|
||||
|
||||
unsafe {
|
||||
|
||||
@@ -8,7 +8,6 @@ pub struct MiroptTestFile {
|
||||
}
|
||||
|
||||
pub struct MiroptTest {
|
||||
pub run_filecheck: bool,
|
||||
pub suffix: String,
|
||||
pub files: Vec<MiroptTestFile>,
|
||||
/// Vec of passes under test to be dumped
|
||||
@@ -57,13 +56,15 @@ pub fn files_for_miropt_test(
|
||||
let test_crate = testfile.file_stem().unwrap().to_str().unwrap().replace('-', "_");
|
||||
|
||||
let suffix = output_file_suffix(testfile, bit_width, panic_strategy);
|
||||
let mut run_filecheck = true;
|
||||
let mut passes = Vec::new();
|
||||
|
||||
for l in test_file_contents.lines() {
|
||||
// FIXME(Zalathar): Remove this `skip-filecheck` migration error in 2027,
|
||||
// or perhaps earlier if it seems no longer useful.
|
||||
if l.starts_with("// skip-filecheck") {
|
||||
run_filecheck = false;
|
||||
continue;
|
||||
panic!(
|
||||
"error: `// skip-filecheck` is no longer supported, use `//@ skip-filecheck` instead."
|
||||
);
|
||||
}
|
||||
if l.starts_with("// EMIT_MIR ") {
|
||||
let test_name = l.trim_start_matches("// EMIT_MIR ").trim();
|
||||
@@ -128,10 +129,7 @@ pub fn files_for_miropt_test(
|
||||
|
||||
out.push(MiroptTestFile { expected_file, from_file, to_file });
|
||||
}
|
||||
if !run_filecheck && l.trim_start().starts_with("// CHECK") {
|
||||
panic!("error: test contains filecheck directive but is marked `skip-filecheck`");
|
||||
}
|
||||
}
|
||||
|
||||
MiroptTest { run_filecheck, suffix, files: out, passes }
|
||||
MiroptTest { suffix, files: out, passes }
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
// CHECK: vadd.f64
|
||||
// CHECK: vldr
|
||||
// CHECK: vadd.f64
|
||||
let b = args.arg::<f64>();
|
||||
let c = args.arg::<f64>();
|
||||
let b = args.next_arg::<f64>();
|
||||
let c = args.next_arg::<f64>();
|
||||
a + b + c
|
||||
|
||||
// CHECK: add sp, sp
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
//@ add-minicore
|
||||
//@ assembly-output: emit-asm
|
||||
//
|
||||
//@ revisions: MIPS MIPS64 MIPS64EL
|
||||
//@ [MIPS] compile-flags: -Copt-level=3 --target mips-unknown-linux-gnu
|
||||
//@ [MIPS] needs-llvm-components: mips
|
||||
//@ [MIPS64] compile-flags: -Copt-level=3 --target mipsisa64r6-unknown-linux-gnuabi64
|
||||
//@ [MIPS64] needs-llvm-components: mips
|
||||
//@ [MIPS64EL] compile-flags: -Copt-level=3 --target mips64el-unknown-linux-gnuabi64
|
||||
//@ [MIPS64EL] needs-llvm-components: mips
|
||||
#![feature(c_variadic, no_core, lang_items, intrinsics, rustc_attrs, asm_experimental_arch)]
|
||||
#![no_core]
|
||||
#![crate_type = "lib"]
|
||||
|
||||
// Check that the assembly that rustc generates matches what clang emits.
|
||||
|
||||
extern crate minicore;
|
||||
use minicore::*;
|
||||
|
||||
#[lang = "va_arg_safe"]
|
||||
pub unsafe trait VaArgSafe {}
|
||||
|
||||
unsafe impl VaArgSafe for i32 {}
|
||||
unsafe impl VaArgSafe for i64 {}
|
||||
unsafe impl VaArgSafe for f64 {}
|
||||
unsafe impl<T> VaArgSafe for *const T {}
|
||||
|
||||
#[repr(transparent)]
|
||||
struct VaListInner {
|
||||
ptr: *const c_void,
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
#[lang = "va_list"]
|
||||
pub struct VaList<'a> {
|
||||
inner: VaListInner,
|
||||
_marker: PhantomData<&'a mut ()>,
|
||||
}
|
||||
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub const unsafe fn va_arg<T: VaArgSafe>(ap: &mut VaList<'_>) -> T;
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
unsafe extern "C" fn read_f64(ap: &mut VaList<'_>) -> f64 {
|
||||
// CHECK-LABEL: read_f64
|
||||
//
|
||||
// MIPS: lw $1, 0($4)
|
||||
// MIPS-NEXT: addiu $2, $zero, -8
|
||||
// MIPS-NEXT: addiu $1, $1, 7
|
||||
// MIPS-NEXT: and $1, $1, $2
|
||||
// MIPS-NEXT: addiu $2, $1, 8
|
||||
// MIPS-NEXT: sw $2, 0($4)
|
||||
// MIPS-NEXT: ldc1 $f0, 0($1)
|
||||
// MIPS-NEXT: jr $ra
|
||||
// MIPS-NEXT: nop
|
||||
//
|
||||
// MIPS64: ld $1, 0($4)
|
||||
// MIPS64-NEXT: daddiu $2, $1, 8
|
||||
// MIPS64-NEXT: sd $2, 0($4)
|
||||
// MIPS64-NEXT: ldc1 $f0, 0($1)
|
||||
// MIPS64-NEXT: jrc $ra
|
||||
//
|
||||
// MIPS64EL: ld $1, 0($4)
|
||||
// MIPS64EL-NEXT: daddiu $2, $1, 8
|
||||
// MIPS64EL-NEXT: sd $2, 0($4)
|
||||
// MIPS64EL-NEXT: ldc1 $f0, 0($1)
|
||||
// MIPS64EL-NEXT: jr $ra
|
||||
// MIPS64EL-NEXT: nop
|
||||
va_arg(ap)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
unsafe extern "C" fn read_i32(ap: &mut VaList<'_>) -> i32 {
|
||||
// CHECK-LABEL: read_i32
|
||||
//
|
||||
// MIPS: lw $1, 0($4)
|
||||
// MIPS-NEXT: addiu $2, $1, 4
|
||||
// MIPS-NEXT: sw $2, 0($4)
|
||||
// MIPS-NEXT: lw $2, 0($1)
|
||||
// MIPS-NEXT: jr $ra
|
||||
// MIPS-NEXT: nop
|
||||
//
|
||||
// MIPS64: ld $1, 0($4)
|
||||
// MIPS64-NEXT: daddiu $2, $1, 8
|
||||
// MIPS64-NEXT: sd $2, 0($4)
|
||||
// MIPS64-NEXT: lw $2, 4($1)
|
||||
// MIPS64-NEXT: jrc $ra
|
||||
//
|
||||
// MIPS64EL: ld $1, 0($4)
|
||||
// MIPS64EL-NEXT: daddiu $2, $1, 8
|
||||
// MIPS64EL-NEXT: sd $2, 0($4)
|
||||
// MIPS64EL-NEXT: lw $2, 0($1)
|
||||
// MIPS64EL-NEXT: jr $ra
|
||||
// MIPS64EL-NEXT: nop
|
||||
va_arg(ap)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
unsafe extern "C" fn read_i64(ap: &mut VaList<'_>) -> i64 {
|
||||
// CHECK-LABEL: read_i64
|
||||
//
|
||||
// MIPS: lw $1, 0($4)
|
||||
// MIPS-NEXT: addiu $2, $zero, -8
|
||||
// MIPS-NEXT: addiu $1, $1, 7
|
||||
// MIPS-NEXT: and $2, $1, $2
|
||||
// MIPS-NEXT: addiu $3, $2, 8
|
||||
// MIPS-NEXT: sw $3, 0($4)
|
||||
// MIPS-NEXT: addiu $3, $zero, 4
|
||||
// MIPS-NEXT: lw $2, 0($2)
|
||||
// MIPS-NEXT: ins $1, $3, 0, 3
|
||||
// MIPS-NEXT: lw $3, 0($1)
|
||||
// MIPS-NEXT: jr $ra
|
||||
// MIPS-NEXT: nop
|
||||
//
|
||||
// MIPS64: ld $1, 0($4)
|
||||
// MIPS64-NEXT: daddiu $2, $1, 8
|
||||
// MIPS64-NEXT: sd $2, 0($4)
|
||||
// MIPS64-NEXT: ld $2, 0($1)
|
||||
// MIPS64-NEXT: jrc $ra
|
||||
//
|
||||
// MIPS64EL: ld $1, 0($4)
|
||||
// MIPS64EL-NEXT: daddiu $2, $1, 8
|
||||
// MIPS64EL-NEXT: sd $2, 0($4)
|
||||
// MIPS64EL-NEXT: ld $2, 0($1)
|
||||
// MIPS64EL-NEXT: jr $ra
|
||||
// MIPS64EL-NEXT: nop
|
||||
va_arg(ap)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
unsafe extern "C" fn read_ptr(ap: &mut VaList<'_>) -> *const u8 {
|
||||
// MIPS: read_ptr = read_i32
|
||||
// MIPS64: read_ptr = read_i64
|
||||
// MIPS64EL: read_ptr = read_i64
|
||||
va_arg(ap)
|
||||
}
|
||||
@@ -11,8 +11,8 @@
|
||||
// CHECK: call void @llvm.lifetime.start.p0({{(i64 [0-9]+, )?}}ptr nonnull %args)
|
||||
// CHECK: call void @llvm.va_start.p0(ptr nonnull %args)
|
||||
|
||||
let b = args.arg::<f64>();
|
||||
let c = args.arg::<f64>();
|
||||
let b = args.next_arg::<f64>();
|
||||
let c = args.next_arg::<f64>();
|
||||
|
||||
a + b + c
|
||||
|
||||
|
||||
@@ -8,22 +8,22 @@
|
||||
|
||||
#[inline(always)]
|
||||
unsafe extern "C" fn inline_always(mut ap: ...) -> u32 {
|
||||
ap.arg::<u32>()
|
||||
ap.next_arg::<u32>()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe extern "C" fn inline(mut ap: ...) -> u32 {
|
||||
ap.arg::<u32>()
|
||||
ap.next_arg::<u32>()
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
unsafe extern "C" fn inline_never(mut ap: ...) -> u32 {
|
||||
ap.arg::<u32>()
|
||||
ap.next_arg::<u32>()
|
||||
}
|
||||
|
||||
#[cold]
|
||||
unsafe extern "C" fn cold(mut ap: ...) -> u32 {
|
||||
ap.arg::<u32>()
|
||||
ap.next_arg::<u32>()
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
// CHECK: call void @llvm.va_start
|
||||
let mut sum = 0;
|
||||
for _ in 0..n {
|
||||
sum += ap.arg::<i32>();
|
||||
sum += ap.next_arg::<i32>();
|
||||
}
|
||||
sum
|
||||
// CHECK: call void @llvm.va_end
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
//@ build-pass
|
||||
// FIXME: The FileCheck directives in this test are unchecked and probably broken.
|
||||
//@ skip-filecheck
|
||||
//@ only-aarch64
|
||||
#![crate_type = "lib"]
|
||||
#![allow(incomplete_features, internal_features)]
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//@ edition: 2021
|
||||
//@ only-x86_64
|
||||
//@ [mir-opt3]compile-flags: -Zmir-opt-level=3
|
||||
//@ [mir-opt3]build-pass
|
||||
//@ [mir-opt3] skip-filecheck
|
||||
|
||||
// mir-opt3 is a regression test for https://github.com/rust-lang/rust/issues/98016
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ The LLVM FileCheck tool is used to verify the contents of output MIR against `CH
|
||||
present in the test file. This works on the runtime MIR, generated by `--emit=mir`, and not
|
||||
on the output of a individual passes.
|
||||
|
||||
Use `// skip-filecheck` to prevent FileCheck from running.
|
||||
Use `//@ skip-filecheck` to prevent FileCheck from running.
|
||||
|
||||
To check MIR for function `foo`, start with a `// CHECK-LABEL fn foo(` directive.
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
// EMIT_MIR address_of.address_of_reborrow.SimplifyCfg-initial.after.mir
|
||||
|
||||
fn address_of_reborrow() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//@ edition:2021
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
|
||||
enum Foo {
|
||||
Bar,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//@ edition:2021
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
|
||||
#![allow(unused)]
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//@ edition:2024
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
|
||||
|
||||
#![feature(async_drop)]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//@edition: 2024
|
||||
//@ test-mir-pass: MentionedItems
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
#![feature(async_drop)]
|
||||
#![allow(incomplete_features)]
|
||||
use std::future::AsyncDrop;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
//@ test-mir-pass: ElaborateDrops
|
||||
//@ needs-unwind
|
||||
#![feature(allocator_api)]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
|
||||
// Validate that we record the target for the `as` coercion as `for<'a> fn(&'a (), &'a ())`,
|
||||
// and not `for<'a, 'b>(&'a (), &'b ())`. We previously did the latter due to a bug in
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
// This test makes sure that the coroutine MIR pass eliminates all calls to
|
||||
// `get_context`, and that the MIR argument type for an async fn and all locals
|
||||
// related to `yield` are `&mut Context`, and its return type is `Poll`.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
//@ edition:2024
|
||||
//@ compile-flags: -Zmir-opt-level=0 -C panic=abort
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
#![feature(custom_mir, core_intrinsics)]
|
||||
|
||||
extern crate core;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
#![feature(custom_mir, core_intrinsics)]
|
||||
|
||||
extern crate core;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
#![feature(custom_mir, core_intrinsics)]
|
||||
|
||||
extern crate core;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
#![feature(custom_mir, core_intrinsics)]
|
||||
|
||||
extern crate core;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
#![feature(custom_mir, core_intrinsics)]
|
||||
|
||||
extern crate core;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
#![feature(custom_mir, core_intrinsics)]
|
||||
|
||||
extern crate core;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
#![feature(custom_mir, core_intrinsics)]
|
||||
|
||||
extern crate core;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
#![feature(custom_mir, core_intrinsics)]
|
||||
|
||||
extern crate core;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
//@ compile-flags: --crate-type=lib
|
||||
#![feature(custom_mir, core_intrinsics)]
|
||||
use std::intrinsics::mir::*;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
#![feature(custom_mir, core_intrinsics)]
|
||||
|
||||
extern crate core;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
#![feature(custom_mir, core_intrinsics)]
|
||||
|
||||
extern crate core;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
#![feature(custom_mir, core_intrinsics)]
|
||||
|
||||
extern crate core;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
#![feature(custom_mir, core_intrinsics)]
|
||||
|
||||
extern crate core;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//@ compile-flags: -Zmir-opt-level=0
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
// EMIT_MIR enum_cast.foo.built.after.mir
|
||||
// EMIT_MIR enum_cast.bar.built.after.mir
|
||||
// EMIT_MIR enum_cast.boo.built.after.mir
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//@ compile-flags: -Zmir-opt-level=0
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
#![feature(never_type)]
|
||||
#![allow(unreachable_code)]
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//@ compile-flags: -Zmir-opt-level=0
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
// EMIT_MIR issue_101867.main.built.after.mir
|
||||
fn main() {
|
||||
let x: Option<u8> = Some(1);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//@ compile-flags: -Zmir-opt-level=0
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
// EMIT_MIR issue_110508.{impl#0}-BAR.built.after.mir
|
||||
// EMIT_MIR issue_110508.{impl#0}-SELF_BAR.built.after.mir
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//@ compile-flags: -Zmir-opt-level=0
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
// We must mark a variable whose initialization fails due to an
|
||||
// abort statement as StorageDead.
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
//@ compile-flags: -Zmir-opt-level=0 -Z validate-mir
|
||||
//@ edition: 2024
|
||||
struct Droppy(u8);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(loop_match)]
|
||||
#![crate_type = "lib"]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
//@ compile-flags: -Z mir-opt-level=0 -C panic=abort
|
||||
|
||||
#![feature(deref_patterns)]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
// Test that simple or-patterns don't get expanded to exponentially large CFGs
|
||||
|
||||
// EMIT_MIR exponential_or.match_tuple.SimplifyCfg-initial.after.mir
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
fn guard() -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
// Test that we don't generate unnecessarily large MIR for very simple matches
|
||||
|
||||
// EMIT_MIR simple_match.match_bool.built.after.mir
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//@ compile-flags: -Zmir-opt-level=0
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
// EMIT_MIR receiver_ptr_mutability.main.built.after.mir
|
||||
|
||||
#![feature(arbitrary_self_types_pointers)]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
//@ compile-flags: -Zmir-opt-level=0 -C debug-assertions=yes
|
||||
|
||||
// EMIT_MIR shifts.shift_signed.built.after.mir
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//@ compile-flags: -Zmir-opt-level=0
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
// Check that when we compile the static `XXX` into MIR, we do not
|
||||
// generate `StorageStart` or `StorageEnd` statements.
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//@ compile-flags: -Zmir-opt-level=0
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
|
||||
// Can't emit `built.after` here as that contains user type annotations which contain DefId that
|
||||
// change all the time.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//@ compile-flags: -Zmir-opt-level=0
|
||||
//@ edition: 2024
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
|
||||
// This test demonstrates how many user type annotations are recorded in MIR
|
||||
// for various binding constructs. In particular, this makes it possible to see
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
//@ compile-flags: -Z mir-opt-level=0
|
||||
|
||||
// EMIT_MIR byte_slice.main.SimplifyCfg-pre-optimizations.after.mir
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
//@ test-mir-pass: GVN
|
||||
//@ ignore-endian-big
|
||||
// EMIT_MIR_FOR_EACH_BIT_WIDTH
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
//@ test-mir-pass: GVN
|
||||
//@ ignore-endian-big
|
||||
// EMIT_MIR_FOR_EACH_BIT_WIDTH
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
//@ test-mir-pass: GVN
|
||||
//@ ignore-endian-big
|
||||
// EMIT_MIR_FOR_EACH_BIT_WIDTH
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
#![feature(min_const_generics)]
|
||||
#![crate_type = "lib"]
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
//@ ignore-endian-big
|
||||
extern "C" {
|
||||
static X: i32;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
//@ test-mir-pass: GVN
|
||||
//@ compile-flags: -Zmir-enable-passes=+RemoveZsts -Zdump-mir-exclude-alloc-bytes
|
||||
// Verify that we can pretty print invalid constants.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
//@ test-mir-pass: GVN
|
||||
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
|
||||
// EMIT_MIR_FOR_EACH_BIT_WIDTH
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
//@ test-mir-pass: GVN
|
||||
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
|
||||
|
||||
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
|
||||
|
||||
// Test that we generate StorageDead on unwind paths for coroutines.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
//! Tests that coroutines that cannot return or unwind don't have unnecessary
|
||||
//! panic branches.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#![feature(coverage_attribute)]
|
||||
//@ test-mir-pass: InstrumentCoverage
|
||||
//@ compile-flags: -Cinstrument-coverage -Zno-profiler-runtime -Zcoverage-options=branch
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
|
||||
enum Enum {
|
||||
A(u32),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
// Test graphviz dataflow output
|
||||
//@ compile-flags: -Z dump-mir=main -Z dump-mir-dataflow
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
//@ test-mir-pass: Derefer
|
||||
// EMIT_MIR derefer_complex_case.main.Derefer.diff
|
||||
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
//@ test-mir-pass: Derefer
|
||||
// EMIT_MIR derefer_inline_test.main.Derefer.diff
|
||||
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
//@ test-mir-pass: Derefer
|
||||
// EMIT_MIR derefer_terminator_test.main.Derefer.diff
|
||||
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
//@ test-mir-pass: Derefer
|
||||
// EMIT_MIR derefer_test.main.Derefer.diff
|
||||
fn main() {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
//@ test-mir-pass: Derefer
|
||||
// EMIT_MIR derefer_test_multiple.main.Derefer.diff
|
||||
fn main() {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
|
||||
//@ test-mir-pass: DestinationPropagation
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
//@ test-mir-pass: Inline
|
||||
//@ compile-flags: --crate-type=lib -C panic=abort
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
//@ test-mir-pass: ElaborateBoxDerefs
|
||||
|
||||
#![feature(custom_mir, core_intrinsics)]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
//@ test-mir-pass: EnumSizeOpt
|
||||
// EMIT_MIR_FOR_EACH_BIT_WIDTH
|
||||
//@ compile-flags: -Zunsound-mir-opts
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
//@ compile-flags: -Zmir-opt-level=0
|
||||
|
||||
// Tests that the `<fn() as Fn>` shim does not create a `Call` terminator with a `Self` callee
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
|
||||
// EMIT_MIR_FOR_EACH_BIT_WIDTH
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
//@ needs-asm-support
|
||||
|
||||
// `global_asm!` gets a fake body, make sure it is handled correctly
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
// Test graphviz output
|
||||
//@ compile-flags: -Z dump-mir-graphviz
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// skip-filecheck
|
||||
//@ skip-filecheck
|
||||
//@ test-mir-pass: GVN
|
||||
|
||||
// EMIT_MIR gvn_on_unsafe_binder.test.GVN.diff
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user