Auto merge of #132756 - workingjubilee:rollup-bed2akn, r=workingjubilee
Rollup of 10 pull requests Successful merges: - #130586 (Set "symbol name" in raw-dylib import libraries to the decorated name) - #131913 (Add `{ignore,needs}-{rustc,std}-debug-assertions` directive support) - #132095 (Fix #131977 parens mangled in shared mut static lint suggestion) - #132131 ([StableMIR] API to retrieve definitions from crates) - #132639 (core: move intrinsics.rs into intrinsics folder) - #132696 (Compile `test_num_f128` conditionally on `reliable_f128_math` config) - #132737 (bootstrap: Print better message if lock pid isn't available) - #132739 (Fix `librustdoc/scrape_examples.rs` formatting) - #132740 (Update test for LLVM 20's new vector splat syntax) - #132741 (Update mips64 data layout to match LLVM 20 change) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
78bb5ee79e
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
use rustc_codegen_ssa::back::archive::{
|
use rustc_codegen_ssa::back::archive::{
|
||||||
ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder, DEFAULT_OBJECT_READER,
|
ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder, DEFAULT_OBJECT_READER,
|
||||||
|
ImportLibraryItem,
|
||||||
};
|
};
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
|
|
||||||
@ -16,7 +17,7 @@ fn create_dll_import_lib(
|
|||||||
&self,
|
&self,
|
||||||
_sess: &Session,
|
_sess: &Session,
|
||||||
_lib_name: &str,
|
_lib_name: &str,
|
||||||
_import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
|
_items: Vec<ImportLibraryItem>,
|
||||||
_output_path: &Path,
|
_output_path: &Path,
|
||||||
) {
|
) {
|
||||||
unimplemented!("creating dll imports is not yet supported");
|
unimplemented!("creating dll imports is not yet supported");
|
||||||
|
@ -44,6 +44,22 @@ pub(crate) fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'t
|
|||||||
let llfn = if tcx.sess.target.arch == "x86"
|
let llfn = if tcx.sess.target.arch == "x86"
|
||||||
&& let Some(dllimport) = crate::common::get_dllimport(tcx, instance_def_id, sym)
|
&& let Some(dllimport) = crate::common::get_dllimport(tcx, instance_def_id, sym)
|
||||||
{
|
{
|
||||||
|
// When calling functions in generated import libraries, MSVC needs
|
||||||
|
// the fully decorated name (as would have been in the declaring
|
||||||
|
// object file), but MinGW wants the name as exported (as would be
|
||||||
|
// in the def file) which may be missing decorations.
|
||||||
|
let mingw_gnu_toolchain = common::is_mingw_gnu_toolchain(&tcx.sess.target);
|
||||||
|
let llfn = cx.declare_fn(
|
||||||
|
&common::i686_decorated_name(
|
||||||
|
dllimport,
|
||||||
|
mingw_gnu_toolchain,
|
||||||
|
true,
|
||||||
|
!mingw_gnu_toolchain,
|
||||||
|
),
|
||||||
|
fn_abi,
|
||||||
|
Some(instance),
|
||||||
|
);
|
||||||
|
|
||||||
// Fix for https://github.com/rust-lang/rust/issues/104453
|
// Fix for https://github.com/rust-lang/rust/issues/104453
|
||||||
// On x86 Windows, LLVM uses 'L' as the prefix for any private
|
// On x86 Windows, LLVM uses 'L' as the prefix for any private
|
||||||
// global symbols, so when we create an undecorated function symbol
|
// global symbols, so when we create an undecorated function symbol
|
||||||
@ -55,15 +71,6 @@ pub(crate) fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'t
|
|||||||
// LLVM will prefix the name with `__imp_`. Ideally, we'd like the
|
// LLVM will prefix the name with `__imp_`. Ideally, we'd like the
|
||||||
// existing logic below to set the Storage Class, but it has an
|
// existing logic below to set the Storage Class, but it has an
|
||||||
// exemption for MinGW for backwards compatibility.
|
// exemption for MinGW for backwards compatibility.
|
||||||
let llfn = cx.declare_fn(
|
|
||||||
&common::i686_decorated_name(
|
|
||||||
dllimport,
|
|
||||||
common::is_mingw_gnu_toolchain(&tcx.sess.target),
|
|
||||||
true,
|
|
||||||
),
|
|
||||||
fn_abi,
|
|
||||||
Some(instance),
|
|
||||||
);
|
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm::LLVMSetDLLStorageClass(llfn, llvm::DLLStorageClass::DllImport);
|
llvm::LLVMSetDLLStorageClass(llfn, llvm::DLLStorageClass::DllImport);
|
||||||
}
|
}
|
||||||
|
@ -194,16 +194,10 @@ fn check_and_apply_linkage<'ll, 'tcx>(
|
|||||||
unsafe { llvm::LLVMSetInitializer(g2, g1) };
|
unsafe { llvm::LLVMSetInitializer(g2, g1) };
|
||||||
g2
|
g2
|
||||||
} else if cx.tcx.sess.target.arch == "x86"
|
} else if cx.tcx.sess.target.arch == "x86"
|
||||||
|
&& common::is_mingw_gnu_toolchain(&cx.tcx.sess.target)
|
||||||
&& let Some(dllimport) = crate::common::get_dllimport(cx.tcx, def_id, sym)
|
&& let Some(dllimport) = crate::common::get_dllimport(cx.tcx, def_id, sym)
|
||||||
{
|
{
|
||||||
cx.declare_global(
|
cx.declare_global(&common::i686_decorated_name(dllimport, true, true, false), llty)
|
||||||
&common::i686_decorated_name(
|
|
||||||
dllimport,
|
|
||||||
common::is_mingw_gnu_toolchain(&cx.tcx.sess.target),
|
|
||||||
true,
|
|
||||||
),
|
|
||||||
llty,
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
// Generate an external declaration.
|
// Generate an external declaration.
|
||||||
// FIXME(nagisa): investigate whether it can be changed into define_global
|
// FIXME(nagisa): investigate whether it can be changed into define_global
|
||||||
|
@ -154,6 +154,11 @@ pub(crate) unsafe fn create_module<'ll>(
|
|||||||
// See https://github.com/llvm/llvm-project/pull/106951
|
// See https://github.com/llvm/llvm-project/pull/106951
|
||||||
target_data_layout = target_data_layout.replace("-i128:128", "");
|
target_data_layout = target_data_layout.replace("-i128:128", "");
|
||||||
}
|
}
|
||||||
|
if sess.target.arch.starts_with("mips64") {
|
||||||
|
// LLVM 20 updates the mips64 layout to correctly align 128 bit integers to 128 bit.
|
||||||
|
// See https://github.com/llvm/llvm-project/pull/112084
|
||||||
|
target_data_layout = target_data_layout.replace("-i128:128", "");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the data-layout values hardcoded remain the defaults.
|
// Ensure the data-layout values hardcoded remain the defaults.
|
||||||
|
@ -26,6 +26,35 @@
|
|||||||
DlltoolFailImportLibrary, ErrorCallingDllTool, ErrorCreatingImportLibrary, ErrorWritingDEFFile,
|
DlltoolFailImportLibrary, ErrorCallingDllTool, ErrorCreatingImportLibrary, ErrorWritingDEFFile,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// An item to be included in an import library.
|
||||||
|
/// This is a slimmed down version of `COFFShortExport` from `ar-archive-writer`.
|
||||||
|
pub struct ImportLibraryItem {
|
||||||
|
/// The name to be exported.
|
||||||
|
pub name: String,
|
||||||
|
/// The ordinal to be exported, if any.
|
||||||
|
pub ordinal: Option<u16>,
|
||||||
|
/// The original, decorated name if `name` is not decorated.
|
||||||
|
pub symbol_name: Option<String>,
|
||||||
|
/// True if this is a data export, false if it is a function export.
|
||||||
|
pub is_data: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ImportLibraryItem> for COFFShortExport {
|
||||||
|
fn from(item: ImportLibraryItem) -> Self {
|
||||||
|
COFFShortExport {
|
||||||
|
name: item.name,
|
||||||
|
ext_name: None,
|
||||||
|
symbol_name: item.symbol_name,
|
||||||
|
alias_target: None,
|
||||||
|
ordinal: item.ordinal.unwrap_or(0),
|
||||||
|
noname: item.ordinal.is_some(),
|
||||||
|
data: item.is_data,
|
||||||
|
private: false,
|
||||||
|
constant: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait ArchiveBuilderBuilder {
|
pub trait ArchiveBuilderBuilder {
|
||||||
fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder + 'a>;
|
fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder + 'a>;
|
||||||
|
|
||||||
@ -38,7 +67,7 @@ fn create_dll_import_lib(
|
|||||||
&self,
|
&self,
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
lib_name: &str,
|
lib_name: &str,
|
||||||
import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
|
items: Vec<ImportLibraryItem>,
|
||||||
output_path: &Path,
|
output_path: &Path,
|
||||||
) {
|
) {
|
||||||
if common::is_mingw_gnu_toolchain(&sess.target) {
|
if common::is_mingw_gnu_toolchain(&sess.target) {
|
||||||
@ -47,21 +76,16 @@ fn create_dll_import_lib(
|
|||||||
// that loaded but crashed with an AV upon calling one of the imported
|
// that loaded but crashed with an AV upon calling one of the imported
|
||||||
// functions. Therefore, use binutils to create the import library instead,
|
// functions. Therefore, use binutils to create the import library instead,
|
||||||
// by writing a .DEF file to the temp dir and calling binutils's dlltool.
|
// by writing a .DEF file to the temp dir and calling binutils's dlltool.
|
||||||
create_mingw_dll_import_lib(
|
create_mingw_dll_import_lib(sess, lib_name, items, output_path);
|
||||||
sess,
|
|
||||||
lib_name,
|
|
||||||
import_name_and_ordinal_vector,
|
|
||||||
output_path,
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
trace!("creating import library");
|
trace!("creating import library");
|
||||||
trace!(" dll_name {:#?}", lib_name);
|
trace!(" dll_name {:#?}", lib_name);
|
||||||
trace!(" output_path {}", output_path.display());
|
trace!(" output_path {}", output_path.display());
|
||||||
trace!(
|
trace!(
|
||||||
" import names: {}",
|
" import names: {}",
|
||||||
import_name_and_ordinal_vector
|
items
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(name, _ordinal)| name.clone())
|
.map(|ImportLibraryItem { name, .. }| name.clone())
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join(", "),
|
.join(", "),
|
||||||
);
|
);
|
||||||
@ -79,20 +103,7 @@ fn create_dll_import_lib(
|
|||||||
.emit_fatal(ErrorCreatingImportLibrary { lib_name, error: error.to_string() }),
|
.emit_fatal(ErrorCreatingImportLibrary { lib_name, error: error.to_string() }),
|
||||||
};
|
};
|
||||||
|
|
||||||
let exports = import_name_and_ordinal_vector
|
let exports = items.into_iter().map(Into::into).collect::<Vec<_>>();
|
||||||
.iter()
|
|
||||||
.map(|(name, ordinal)| COFFShortExport {
|
|
||||||
name: name.to_string(),
|
|
||||||
ext_name: None,
|
|
||||||
symbol_name: None,
|
|
||||||
alias_target: None,
|
|
||||||
ordinal: ordinal.unwrap_or(0),
|
|
||||||
noname: ordinal.is_some(),
|
|
||||||
data: false,
|
|
||||||
private: false,
|
|
||||||
constant: false,
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
let machine = match &*sess.target.arch {
|
let machine = match &*sess.target.arch {
|
||||||
"x86_64" => MachineTypes::AMD64,
|
"x86_64" => MachineTypes::AMD64,
|
||||||
"x86" => MachineTypes::I386,
|
"x86" => MachineTypes::I386,
|
||||||
@ -160,16 +171,16 @@ fn extract_bundled_libs<'a>(
|
|||||||
fn create_mingw_dll_import_lib(
|
fn create_mingw_dll_import_lib(
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
lib_name: &str,
|
lib_name: &str,
|
||||||
import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
|
items: Vec<ImportLibraryItem>,
|
||||||
output_path: &Path,
|
output_path: &Path,
|
||||||
) {
|
) {
|
||||||
let def_file_path = output_path.with_extension("def");
|
let def_file_path = output_path.with_extension("def");
|
||||||
|
|
||||||
let def_file_content = format!(
|
let def_file_content = format!(
|
||||||
"EXPORTS\n{}",
|
"EXPORTS\n{}",
|
||||||
import_name_and_ordinal_vector
|
items
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(name, ordinal)| {
|
.map(|ImportLibraryItem { name, ordinal, .. }| {
|
||||||
match ordinal {
|
match ordinal {
|
||||||
Some(n) => format!("{name} @{n} NONAME"),
|
Some(n) => format!("{name} @{n} NONAME"),
|
||||||
None => name,
|
None => name,
|
||||||
|
@ -45,7 +45,7 @@
|
|||||||
use tempfile::Builder as TempFileBuilder;
|
use tempfile::Builder as TempFileBuilder;
|
||||||
use tracing::{debug, info, warn};
|
use tracing::{debug, info, warn};
|
||||||
|
|
||||||
use super::archive::{ArchiveBuilder, ArchiveBuilderBuilder};
|
use super::archive::{ArchiveBuilder, ArchiveBuilderBuilder, ImportLibraryItem};
|
||||||
use super::command::Command;
|
use super::command::Command;
|
||||||
use super::linker::{self, Linker};
|
use super::linker::{self, Linker};
|
||||||
use super::metadata::{MetadataPosition, create_wrapper_file};
|
use super::metadata::{MetadataPosition, create_wrapper_file};
|
||||||
@ -495,16 +495,35 @@ fn create_dll_import_libs<'a>(
|
|||||||
|
|
||||||
let mingw_gnu_toolchain = common::is_mingw_gnu_toolchain(&sess.target);
|
let mingw_gnu_toolchain = common::is_mingw_gnu_toolchain(&sess.target);
|
||||||
|
|
||||||
let import_name_and_ordinal_vector: Vec<(String, Option<u16>)> = raw_dylib_imports
|
let items: Vec<ImportLibraryItem> = raw_dylib_imports
|
||||||
.iter()
|
.iter()
|
||||||
.map(|import: &DllImport| {
|
.map(|import: &DllImport| {
|
||||||
if sess.target.arch == "x86" {
|
if sess.target.arch == "x86" {
|
||||||
(
|
ImportLibraryItem {
|
||||||
common::i686_decorated_name(import, mingw_gnu_toolchain, false),
|
name: common::i686_decorated_name(
|
||||||
import.ordinal(),
|
import,
|
||||||
|
mingw_gnu_toolchain,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
ordinal: import.ordinal(),
|
||||||
|
symbol_name: import.is_missing_decorations().then(|| {
|
||||||
|
common::i686_decorated_name(
|
||||||
|
import,
|
||||||
|
mingw_gnu_toolchain,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
)
|
)
|
||||||
|
}),
|
||||||
|
is_data: !import.is_fn,
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
(import.name.to_string(), import.ordinal())
|
ImportLibraryItem {
|
||||||
|
name: import.name.to_string(),
|
||||||
|
ordinal: import.ordinal(),
|
||||||
|
symbol_name: None,
|
||||||
|
is_data: !import.is_fn,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
@ -512,7 +531,7 @@ fn create_dll_import_libs<'a>(
|
|||||||
archive_builder_builder.create_dll_import_lib(
|
archive_builder_builder.create_dll_import_lib(
|
||||||
sess,
|
sess,
|
||||||
&raw_dylib_name,
|
&raw_dylib_name,
|
||||||
import_name_and_ordinal_vector,
|
items,
|
||||||
&output_path,
|
&output_path,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -187,12 +187,15 @@ pub fn i686_decorated_name(
|
|||||||
dll_import: &DllImport,
|
dll_import: &DllImport,
|
||||||
mingw: bool,
|
mingw: bool,
|
||||||
disable_name_mangling: bool,
|
disable_name_mangling: bool,
|
||||||
|
force_fully_decorated: bool,
|
||||||
) -> String {
|
) -> String {
|
||||||
let name = dll_import.name.as_str();
|
let name = dll_import.name.as_str();
|
||||||
|
|
||||||
let (add_prefix, add_suffix) = match dll_import.import_name_type {
|
let (add_prefix, add_suffix) = match (force_fully_decorated, dll_import.import_name_type) {
|
||||||
Some(PeImportNameType::NoPrefix) => (false, true),
|
// No prefix is a bit weird, in that LLVM/ar_archive_writer won't emit it, so we will
|
||||||
Some(PeImportNameType::Undecorated) => (false, false),
|
// ignore `force_fully_decorated` and always partially decorate it.
|
||||||
|
(_, Some(PeImportNameType::NoPrefix)) => (false, true),
|
||||||
|
(false, Some(PeImportNameType::Undecorated)) => (false, false),
|
||||||
_ => (true, true),
|
_ => (true, true),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
use rustc_middle::ty::{Mutability, TyKind};
|
use rustc_middle::ty::{Mutability, TyKind};
|
||||||
use rustc_session::lint::FutureIncompatibilityReason;
|
use rustc_session::lint::FutureIncompatibilityReason;
|
||||||
use rustc_session::{declare_lint, declare_lint_pass};
|
use rustc_session::{declare_lint, declare_lint_pass};
|
||||||
use rustc_span::Span;
|
|
||||||
use rustc_span::edition::Edition;
|
use rustc_span::edition::Edition;
|
||||||
|
use rustc_span::{BytePos, Span};
|
||||||
|
|
||||||
use crate::lints::{MutRefSugg, RefOfMutStatic};
|
use crate::lints::{MutRefSugg, RefOfMutStatic};
|
||||||
use crate::{LateContext, LateLintPass, LintContext};
|
use crate::{LateContext, LateLintPass, LintContext};
|
||||||
@ -71,13 +71,24 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) {
|
|||||||
if matches!(borrow_kind, hir::BorrowKind::Ref)
|
if matches!(borrow_kind, hir::BorrowKind::Ref)
|
||||||
&& let Some(err_span) = path_is_static_mut(ex, err_span) =>
|
&& let Some(err_span) = path_is_static_mut(ex, err_span) =>
|
||||||
{
|
{
|
||||||
emit_static_mut_refs(
|
let source_map = cx.sess().source_map();
|
||||||
cx,
|
let snippet = source_map.span_to_snippet(err_span);
|
||||||
err_span,
|
|
||||||
err_span.with_hi(ex.span.lo()),
|
let sugg_span = if let Ok(snippet) = snippet {
|
||||||
m,
|
// ( ( &IDENT ) )
|
||||||
!expr.span.from_expansion(),
|
// ~~~~ exclude these from the suggestion span to avoid unmatching parens
|
||||||
);
|
let exclude_n_bytes: u32 = snippet
|
||||||
|
.chars()
|
||||||
|
.take_while(|ch| ch.is_whitespace() || *ch == '(')
|
||||||
|
.map(|ch| ch.len_utf8() as u32)
|
||||||
|
.sum();
|
||||||
|
|
||||||
|
err_span.with_lo(err_span.lo() + BytePos(exclude_n_bytes)).with_hi(ex.span.lo())
|
||||||
|
} else {
|
||||||
|
err_span.with_hi(ex.span.lo())
|
||||||
|
};
|
||||||
|
|
||||||
|
emit_static_mut_refs(cx, err_span, sugg_span, m, !expr.span.from_expansion());
|
||||||
}
|
}
|
||||||
hir::ExprKind::MethodCall(_, e, _, _)
|
hir::ExprKind::MethodCall(_, e, _, _)
|
||||||
if let Some(err_span) = path_is_static_mut(e, expr.span)
|
if let Some(err_span) = path_is_static_mut(e, expr.span)
|
||||||
|
@ -384,6 +384,7 @@ fn into_args(self) -> (DefId, SimplifiedType) {
|
|||||||
crate_hash => { cdata.root.header.hash }
|
crate_hash => { cdata.root.header.hash }
|
||||||
crate_host_hash => { cdata.host_hash }
|
crate_host_hash => { cdata.host_hash }
|
||||||
crate_name => { cdata.root.header.name }
|
crate_name => { cdata.root.header.name }
|
||||||
|
num_extern_def_ids => { cdata.num_def_ids() }
|
||||||
|
|
||||||
extra_filename => { cdata.root.extra_filename.clone() }
|
extra_filename => { cdata.root.extra_filename.clone() }
|
||||||
|
|
||||||
|
@ -1844,6 +1844,16 @@
|
|||||||
desc { |tcx| "computing crate imported by `{}`", tcx.def_path_str(def_id) }
|
desc { |tcx| "computing crate imported by `{}`", tcx.def_path_str(def_id) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets the number of definitions in a foreign crate.
|
||||||
|
///
|
||||||
|
/// This allows external tools to iterate over all definitions in a foreign crate.
|
||||||
|
///
|
||||||
|
/// This should never be used for the local crate, instead use `iter_local_def_id`.
|
||||||
|
query num_extern_def_ids(_: CrateNum) -> usize {
|
||||||
|
desc { "fetching the number of definitions in a crate" }
|
||||||
|
separate_provide_extern
|
||||||
|
}
|
||||||
|
|
||||||
query lib_features(_: CrateNum) -> &'tcx LibFeatures {
|
query lib_features(_: CrateNum) -> &'tcx LibFeatures {
|
||||||
desc { "calculating the lib features defined in a crate" }
|
desc { "calculating the lib features defined in a crate" }
|
||||||
separate_provide_extern
|
separate_provide_extern
|
||||||
|
@ -130,6 +130,11 @@ pub fn ordinal(&self) -> Option<u16> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_missing_decorations(&self) -> bool {
|
||||||
|
self.import_name_type == Some(PeImportNameType::Undecorated)
|
||||||
|
|| self.import_name_type == Some(PeImportNameType::NoPrefix)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calling convention for a function defined in an external library.
|
/// Calling convention for a function defined in an external library.
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
|
|
||||||
use crate::rustc_internal::RustcInternal;
|
use crate::rustc_internal::RustcInternal;
|
||||||
use crate::rustc_smir::builder::BodyBuilder;
|
use crate::rustc_smir::builder::BodyBuilder;
|
||||||
use crate::rustc_smir::{Stable, Tables, alloc, new_item_kind, smir_crate};
|
use crate::rustc_smir::{Stable, Tables, alloc, filter_def_ids, new_item_kind, smir_crate};
|
||||||
|
|
||||||
impl<'tcx> Context for TablesWrapper<'tcx> {
|
impl<'tcx> Context for TablesWrapper<'tcx> {
|
||||||
fn target_info(&self) -> MachineInfo {
|
fn target_info(&self) -> MachineInfo {
|
||||||
@ -80,6 +80,20 @@ fn foreign_modules(&self, crate_num: CrateNum) -> Vec<stable_mir::ty::ForeignMod
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn crate_functions(&self, crate_num: CrateNum) -> Vec<FnDef> {
|
||||||
|
let mut tables = self.0.borrow_mut();
|
||||||
|
let tcx = tables.tcx;
|
||||||
|
let krate = crate_num.internal(&mut *tables, tcx);
|
||||||
|
filter_def_ids(tcx, krate, |def_id| tables.to_fn_def(def_id))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn crate_statics(&self, crate_num: CrateNum) -> Vec<StaticDef> {
|
||||||
|
let mut tables = self.0.borrow_mut();
|
||||||
|
let tcx = tables.tcx;
|
||||||
|
let krate = crate_num.internal(&mut *tables, tcx);
|
||||||
|
filter_def_ids(tcx, krate, |def_id| tables.to_static(def_id))
|
||||||
|
}
|
||||||
|
|
||||||
fn foreign_module(
|
fn foreign_module(
|
||||||
&self,
|
&self,
|
||||||
mod_def: stable_mir::ty::ForeignModuleDef,
|
mod_def: stable_mir::ty::ForeignModuleDef,
|
||||||
|
@ -15,8 +15,8 @@
|
|||||||
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
|
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
|
||||||
use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE};
|
use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE};
|
||||||
use stable_mir::abi::Layout;
|
use stable_mir::abi::Layout;
|
||||||
use stable_mir::mir::mono::InstanceDef;
|
use stable_mir::mir::mono::{InstanceDef, StaticDef};
|
||||||
use stable_mir::ty::{MirConstId, Span, TyConstId};
|
use stable_mir::ty::{FnDef, MirConstId, Span, TyConstId};
|
||||||
use stable_mir::{CtorKind, ItemKind};
|
use stable_mir::{CtorKind, ItemKind};
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
@ -79,6 +79,36 @@ pub(crate) fn item_has_body(&self, def_id: DefId) -> bool {
|
|||||||
};
|
};
|
||||||
!must_override && self.tcx.is_mir_available(def_id)
|
!must_override && self.tcx.is_mir_available(def_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn to_fn_def(&mut self, def_id: DefId) -> Option<FnDef> {
|
||||||
|
if matches!(self.tcx.def_kind(def_id), DefKind::Fn | DefKind::AssocFn) {
|
||||||
|
Some(self.fn_def(def_id))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_static(&mut self, def_id: DefId) -> Option<StaticDef> {
|
||||||
|
matches!(self.tcx.def_kind(def_id), DefKind::Static { .. }).then(|| self.static_def(def_id))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Iterate over the definitions of the given crate.
|
||||||
|
pub(crate) fn filter_def_ids<F, T>(tcx: TyCtxt<'_>, krate: CrateNum, mut func: F) -> Vec<T>
|
||||||
|
where
|
||||||
|
F: FnMut(DefId) -> Option<T>,
|
||||||
|
{
|
||||||
|
if krate == LOCAL_CRATE {
|
||||||
|
tcx.iter_local_def_id().filter_map(|did| func(did.to_def_id())).collect()
|
||||||
|
} else {
|
||||||
|
let num_definitions = tcx.num_extern_def_ids(krate);
|
||||||
|
(0..num_definitions)
|
||||||
|
.filter_map(move |i| {
|
||||||
|
let def_id = DefId { krate, index: rustc_span::def_id::DefIndex::from_usize(i) };
|
||||||
|
func(def_id)
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Build a stable mir crate from a given crate number.
|
/// Build a stable mir crate from a given crate number.
|
||||||
|
@ -20,7 +20,7 @@ pub(crate) fn target() -> Target {
|
|||||||
std: None, // ?
|
std: None, // ?
|
||||||
},
|
},
|
||||||
pointer_width: 64,
|
pointer_width: 64,
|
||||||
data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
|
data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
|
||||||
arch: "mips64".into(),
|
arch: "mips64".into(),
|
||||||
options: TargetOptions {
|
options: TargetOptions {
|
||||||
abi: "abi64".into(),
|
abi: "abi64".into(),
|
||||||
|
@ -11,7 +11,7 @@ pub(crate) fn target() -> Target {
|
|||||||
std: Some(true),
|
std: Some(true),
|
||||||
},
|
},
|
||||||
pointer_width: 64,
|
pointer_width: 64,
|
||||||
data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
|
data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
|
||||||
arch: "mips64".into(),
|
arch: "mips64".into(),
|
||||||
options: TargetOptions {
|
options: TargetOptions {
|
||||||
abi: "abi64".into(),
|
abi: "abi64".into(),
|
||||||
|
@ -16,7 +16,7 @@ pub(crate) fn target() -> Target {
|
|||||||
std: Some(true),
|
std: Some(true),
|
||||||
},
|
},
|
||||||
pointer_width: 64,
|
pointer_width: 64,
|
||||||
data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
|
data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
|
||||||
arch: "mips64".into(),
|
arch: "mips64".into(),
|
||||||
options: TargetOptions {
|
options: TargetOptions {
|
||||||
abi: "abi64".into(),
|
abi: "abi64".into(),
|
||||||
|
@ -10,7 +10,7 @@ pub(crate) fn target() -> Target {
|
|||||||
std: Some(true),
|
std: Some(true),
|
||||||
},
|
},
|
||||||
pointer_width: 64,
|
pointer_width: 64,
|
||||||
data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
|
data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
|
||||||
arch: "mips64".into(),
|
arch: "mips64".into(),
|
||||||
options: TargetOptions {
|
options: TargetOptions {
|
||||||
abi: "abi64".into(),
|
abi: "abi64".into(),
|
||||||
|
@ -15,7 +15,7 @@ pub(crate) fn target() -> Target {
|
|||||||
std: Some(true),
|
std: Some(true),
|
||||||
},
|
},
|
||||||
pointer_width: 64,
|
pointer_width: 64,
|
||||||
data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
|
data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
|
||||||
arch: "mips64".into(),
|
arch: "mips64".into(),
|
||||||
options: TargetOptions { abi: "abi64".into(), mcount: "_mcount".into(), ..base },
|
options: TargetOptions { abi: "abi64".into(), mcount: "_mcount".into(), ..base },
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ pub(crate) fn target() -> Target {
|
|||||||
std: None, // ?
|
std: None, // ?
|
||||||
},
|
},
|
||||||
pointer_width: 64,
|
pointer_width: 64,
|
||||||
data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
|
data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
|
||||||
arch: "mips64r6".into(),
|
arch: "mips64r6".into(),
|
||||||
options: TargetOptions {
|
options: TargetOptions {
|
||||||
abi: "abi64".into(),
|
abi: "abi64".into(),
|
||||||
|
@ -10,7 +10,7 @@ pub(crate) fn target() -> Target {
|
|||||||
std: Some(true),
|
std: Some(true),
|
||||||
},
|
},
|
||||||
pointer_width: 64,
|
pointer_width: 64,
|
||||||
data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
|
data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
|
||||||
arch: "mips64r6".into(),
|
arch: "mips64r6".into(),
|
||||||
options: TargetOptions {
|
options: TargetOptions {
|
||||||
abi: "abi64".into(),
|
abi: "abi64".into(),
|
||||||
|
@ -34,6 +34,12 @@ pub trait Context {
|
|||||||
/// Check whether the body of a function is available.
|
/// Check whether the body of a function is available.
|
||||||
fn has_body(&self, item: DefId) -> bool;
|
fn has_body(&self, item: DefId) -> bool;
|
||||||
fn foreign_modules(&self, crate_num: CrateNum) -> Vec<ForeignModuleDef>;
|
fn foreign_modules(&self, crate_num: CrateNum) -> Vec<ForeignModuleDef>;
|
||||||
|
|
||||||
|
/// Retrieve all functions defined in this crate.
|
||||||
|
fn crate_functions(&self, crate_num: CrateNum) -> Vec<FnDef>;
|
||||||
|
|
||||||
|
/// Retrieve all static items defined in this crate.
|
||||||
|
fn crate_statics(&self, crate_num: CrateNum) -> Vec<StaticDef>;
|
||||||
fn foreign_module(&self, mod_def: ForeignModuleDef) -> ForeignModule;
|
fn foreign_module(&self, mod_def: ForeignModuleDef) -> ForeignModule;
|
||||||
fn foreign_items(&self, mod_def: ForeignModuleDef) -> Vec<ForeignDef>;
|
fn foreign_items(&self, mod_def: ForeignModuleDef) -> Vec<ForeignDef>;
|
||||||
fn all_trait_decls(&self) -> TraitDecls;
|
fn all_trait_decls(&self) -> TraitDecls;
|
||||||
|
@ -25,8 +25,9 @@
|
|||||||
use crate::compiler_interface::with;
|
use crate::compiler_interface::with;
|
||||||
pub use crate::crate_def::{CrateDef, CrateDefType, DefId};
|
pub use crate::crate_def::{CrateDef, CrateDefType, DefId};
|
||||||
pub use crate::error::*;
|
pub use crate::error::*;
|
||||||
|
use crate::mir::mono::StaticDef;
|
||||||
use crate::mir::{Body, Mutability};
|
use crate::mir::{Body, Mutability};
|
||||||
use crate::ty::{ForeignModuleDef, ImplDef, IndexedVal, Span, TraitDef, Ty};
|
use crate::ty::{FnDef, ForeignModuleDef, ImplDef, IndexedVal, Span, TraitDef, Ty};
|
||||||
|
|
||||||
pub mod abi;
|
pub mod abi;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
@ -96,6 +97,16 @@ pub fn trait_decls(&self) -> TraitDecls {
|
|||||||
pub fn trait_impls(&self) -> ImplTraitDecls {
|
pub fn trait_impls(&self) -> ImplTraitDecls {
|
||||||
with(|cx| cx.trait_impls(self.id))
|
with(|cx| cx.trait_impls(self.id))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return a list of function definitions from this crate independent on their visibility.
|
||||||
|
pub fn fn_defs(&self) -> Vec<FnDef> {
|
||||||
|
with(|cx| cx.crate_functions(self.id))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return a list of static items defined in this crate independent on their visibility.
|
||||||
|
pub fn statics(&self) -> Vec<StaticDef> {
|
||||||
|
with(|cx| cx.crate_statics(self.id))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, Serialize)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, Serialize)]
|
||||||
|
@ -2,7 +2,10 @@
|
|||||||
#![cfg(reliable_f128)]
|
#![cfg(reliable_f128)]
|
||||||
|
|
||||||
use crate::f128::consts;
|
use crate::f128::consts;
|
||||||
use crate::num::{FpCategory as Fp, *};
|
use crate::num::FpCategory as Fp;
|
||||||
|
#[cfg(reliable_f128_math)]
|
||||||
|
use crate::ops::Rem;
|
||||||
|
use crate::ops::{Add, Div, Mul, Sub};
|
||||||
|
|
||||||
// Note these tolerances make sense around zero, but not for more extreme exponents.
|
// Note these tolerances make sense around zero, but not for more extreme exponents.
|
||||||
|
|
||||||
@ -53,7 +56,22 @@ macro_rules! assert_f128_biteq {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_num_f128() {
|
fn test_num_f128() {
|
||||||
test_num(10f128, 2f128);
|
// FIXME(f16_f128): replace with a `test_num` call once the required `fmodl`/`fmodf128`
|
||||||
|
// function is available on all platforms.
|
||||||
|
let ten = 10f128;
|
||||||
|
let two = 2f128;
|
||||||
|
assert_eq!(ten.add(two), ten + two);
|
||||||
|
assert_eq!(ten.sub(two), ten - two);
|
||||||
|
assert_eq!(ten.mul(two), ten * two);
|
||||||
|
assert_eq!(ten.div(two), ten / two);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(reliable_f128_math)]
|
||||||
|
fn test_num_f128_rem() {
|
||||||
|
let ten = 10f128;
|
||||||
|
let two = 2f128;
|
||||||
|
assert_eq!(ten.rem(two), ten % two);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -33,7 +33,7 @@ fn main() {
|
|||||||
// Display PID of process holding the lock
|
// Display PID of process holding the lock
|
||||||
// PID will be stored in a lock file
|
// PID will be stored in a lock file
|
||||||
let lock_path = config.out.join("lock");
|
let lock_path = config.out.join("lock");
|
||||||
let pid = fs::read_to_string(&lock_path).unwrap_or_default();
|
let pid = fs::read_to_string(&lock_path);
|
||||||
|
|
||||||
build_lock = fd_lock::RwLock::new(t!(fs::OpenOptions::new()
|
build_lock = fd_lock::RwLock::new(t!(fs::OpenOptions::new()
|
||||||
.write(true)
|
.write(true)
|
||||||
@ -47,7 +47,11 @@ fn main() {
|
|||||||
}
|
}
|
||||||
err => {
|
err => {
|
||||||
drop(err);
|
drop(err);
|
||||||
|
if let Ok(pid) = pid {
|
||||||
println!("WARNING: build directory locked by process {pid}, waiting for lock");
|
println!("WARNING: build directory locked by process {pid}, waiting for lock");
|
||||||
|
} else {
|
||||||
|
println!("WARNING: build directory locked, waiting for lock");
|
||||||
|
}
|
||||||
let mut lock = t!(build_lock.write());
|
let mut lock = t!(build_lock.write());
|
||||||
t!(lock.write(process::id().to_string().as_ref()));
|
t!(lock.write(process::id().to_string().as_ref()));
|
||||||
lock
|
lock
|
||||||
|
@ -1938,9 +1938,13 @@ fn run(self, builder: &Builder<'_>) {
|
|||||||
|
|
||||||
cmd.arg("--json");
|
cmd.arg("--json");
|
||||||
|
|
||||||
if builder.config.rust_debug_assertions_std {
|
if builder.config.rustc_debug_assertions {
|
||||||
cmd.arg("--with-debug-assertions");
|
cmd.arg("--with-rustc-debug-assertions");
|
||||||
};
|
}
|
||||||
|
|
||||||
|
if builder.config.std_debug_assertions {
|
||||||
|
cmd.arg("--with-std-debug-assertions");
|
||||||
|
}
|
||||||
|
|
||||||
let mut llvm_components_passed = false;
|
let mut llvm_components_passed = false;
|
||||||
let mut copts_passed = false;
|
let mut copts_passed = false;
|
||||||
|
@ -833,9 +833,9 @@ fn cargo(
|
|||||||
cargo.env(
|
cargo.env(
|
||||||
profile_var("DEBUG_ASSERTIONS"),
|
profile_var("DEBUG_ASSERTIONS"),
|
||||||
if mode == Mode::Std {
|
if mode == Mode::Std {
|
||||||
self.config.rust_debug_assertions_std.to_string()
|
self.config.std_debug_assertions.to_string()
|
||||||
} else {
|
} else {
|
||||||
self.config.rust_debug_assertions.to_string()
|
self.config.rustc_debug_assertions.to_string()
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
cargo.env(
|
cargo.env(
|
||||||
|
@ -263,8 +263,10 @@ pub struct Config {
|
|||||||
pub rust_optimize: RustOptimize,
|
pub rust_optimize: RustOptimize,
|
||||||
pub rust_codegen_units: Option<u32>,
|
pub rust_codegen_units: Option<u32>,
|
||||||
pub rust_codegen_units_std: Option<u32>,
|
pub rust_codegen_units_std: Option<u32>,
|
||||||
pub rust_debug_assertions: bool,
|
|
||||||
pub rust_debug_assertions_std: bool,
|
pub rustc_debug_assertions: bool,
|
||||||
|
pub std_debug_assertions: bool,
|
||||||
|
|
||||||
pub rust_overflow_checks: bool,
|
pub rust_overflow_checks: bool,
|
||||||
pub rust_overflow_checks_std: bool,
|
pub rust_overflow_checks_std: bool,
|
||||||
pub rust_debug_logging: bool,
|
pub rust_debug_logging: bool,
|
||||||
@ -1115,9 +1117,9 @@ struct Rust {
|
|||||||
debug: Option<bool> = "debug",
|
debug: Option<bool> = "debug",
|
||||||
codegen_units: Option<u32> = "codegen-units",
|
codegen_units: Option<u32> = "codegen-units",
|
||||||
codegen_units_std: Option<u32> = "codegen-units-std",
|
codegen_units_std: Option<u32> = "codegen-units-std",
|
||||||
debug_assertions: Option<bool> = "debug-assertions",
|
rustc_debug_assertions: Option<bool> = "debug-assertions",
|
||||||
randomize_layout: Option<bool> = "randomize-layout",
|
randomize_layout: Option<bool> = "randomize-layout",
|
||||||
debug_assertions_std: Option<bool> = "debug-assertions-std",
|
std_debug_assertions: Option<bool> = "debug-assertions-std",
|
||||||
overflow_checks: Option<bool> = "overflow-checks",
|
overflow_checks: Option<bool> = "overflow-checks",
|
||||||
overflow_checks_std: Option<bool> = "overflow-checks-std",
|
overflow_checks_std: Option<bool> = "overflow-checks-std",
|
||||||
debug_logging: Option<bool> = "debug-logging",
|
debug_logging: Option<bool> = "debug-logging",
|
||||||
@ -1652,8 +1654,8 @@ fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
|
|||||||
let mut llvm_offload = None;
|
let mut llvm_offload = None;
|
||||||
let mut llvm_plugins = None;
|
let mut llvm_plugins = None;
|
||||||
let mut debug = None;
|
let mut debug = None;
|
||||||
let mut debug_assertions = None;
|
let mut rustc_debug_assertions = None;
|
||||||
let mut debug_assertions_std = None;
|
let mut std_debug_assertions = None;
|
||||||
let mut overflow_checks = None;
|
let mut overflow_checks = None;
|
||||||
let mut overflow_checks_std = None;
|
let mut overflow_checks_std = None;
|
||||||
let mut debug_logging = None;
|
let mut debug_logging = None;
|
||||||
@ -1675,8 +1677,8 @@ fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
|
|||||||
debug: debug_toml,
|
debug: debug_toml,
|
||||||
codegen_units,
|
codegen_units,
|
||||||
codegen_units_std,
|
codegen_units_std,
|
||||||
debug_assertions: debug_assertions_toml,
|
rustc_debug_assertions: rustc_debug_assertions_toml,
|
||||||
debug_assertions_std: debug_assertions_std_toml,
|
std_debug_assertions: std_debug_assertions_toml,
|
||||||
overflow_checks: overflow_checks_toml,
|
overflow_checks: overflow_checks_toml,
|
||||||
overflow_checks_std: overflow_checks_std_toml,
|
overflow_checks_std: overflow_checks_std_toml,
|
||||||
debug_logging: debug_logging_toml,
|
debug_logging: debug_logging_toml,
|
||||||
@ -1734,8 +1736,8 @@ fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
|
|||||||
config.download_ci_rustc_commit(download_rustc, config.llvm_assertions);
|
config.download_ci_rustc_commit(download_rustc, config.llvm_assertions);
|
||||||
|
|
||||||
debug = debug_toml;
|
debug = debug_toml;
|
||||||
debug_assertions = debug_assertions_toml;
|
rustc_debug_assertions = rustc_debug_assertions_toml;
|
||||||
debug_assertions_std = debug_assertions_std_toml;
|
std_debug_assertions = std_debug_assertions_toml;
|
||||||
overflow_checks = overflow_checks_toml;
|
overflow_checks = overflow_checks_toml;
|
||||||
overflow_checks_std = overflow_checks_std_toml;
|
overflow_checks_std = overflow_checks_std_toml;
|
||||||
debug_logging = debug_logging_toml;
|
debug_logging = debug_logging_toml;
|
||||||
@ -2148,14 +2150,13 @@ fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
|
|||||||
config.rust_std_features = std_features.unwrap_or(default_std_features);
|
config.rust_std_features = std_features.unwrap_or(default_std_features);
|
||||||
|
|
||||||
let default = debug == Some(true);
|
let default = debug == Some(true);
|
||||||
config.rust_debug_assertions = debug_assertions.unwrap_or(default);
|
config.rustc_debug_assertions = rustc_debug_assertions.unwrap_or(default);
|
||||||
config.rust_debug_assertions_std =
|
config.std_debug_assertions = std_debug_assertions.unwrap_or(config.rustc_debug_assertions);
|
||||||
debug_assertions_std.unwrap_or(config.rust_debug_assertions);
|
|
||||||
config.rust_overflow_checks = overflow_checks.unwrap_or(default);
|
config.rust_overflow_checks = overflow_checks.unwrap_or(default);
|
||||||
config.rust_overflow_checks_std =
|
config.rust_overflow_checks_std =
|
||||||
overflow_checks_std.unwrap_or(config.rust_overflow_checks);
|
overflow_checks_std.unwrap_or(config.rust_overflow_checks);
|
||||||
|
|
||||||
config.rust_debug_logging = debug_logging.unwrap_or(config.rust_debug_assertions);
|
config.rust_debug_logging = debug_logging.unwrap_or(config.rustc_debug_assertions);
|
||||||
|
|
||||||
let with_defaults = |debuginfo_level_specific: Option<_>| {
|
let with_defaults = |debuginfo_level_specific: Option<_>| {
|
||||||
debuginfo_level_specific.or(debuginfo_level).unwrap_or(if debug == Some(true) {
|
debuginfo_level_specific.or(debuginfo_level).unwrap_or(if debug == Some(true) {
|
||||||
@ -3075,8 +3076,8 @@ macro_rules! warn {
|
|||||||
debug: _,
|
debug: _,
|
||||||
codegen_units: _,
|
codegen_units: _,
|
||||||
codegen_units_std: _,
|
codegen_units_std: _,
|
||||||
debug_assertions: _,
|
rustc_debug_assertions: _,
|
||||||
debug_assertions_std: _,
|
std_debug_assertions: _,
|
||||||
overflow_checks: _,
|
overflow_checks: _,
|
||||||
overflow_checks_std: _,
|
overflow_checks_std: _,
|
||||||
debuginfo_level: _,
|
debuginfo_level: _,
|
||||||
|
@ -42,10 +42,16 @@ pub(crate) fn new(matches: &getopts::Matches, dcx: DiagCtxtHandle<'_>) -> Option
|
|||||||
scrape_tests,
|
scrape_tests,
|
||||||
}),
|
}),
|
||||||
(Some(_), false, _) | (None, true, _) => {
|
(Some(_), false, _) | (None, true, _) => {
|
||||||
dcx.fatal("must use --scrape-examples-output-path and --scrape-examples-target-crate together");
|
dcx.fatal(
|
||||||
|
"must use --scrape-examples-output-path and --scrape-examples-target-crate \
|
||||||
|
together",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
(None, false, true) => {
|
(None, false, true) => {
|
||||||
dcx.fatal("must use --scrape-examples-output-path and --scrape-examples-target-crate with --scrape-tests");
|
dcx.fatal(
|
||||||
|
"must use --scrape-examples-output-path and \
|
||||||
|
--scrape-examples-target-crate with --scrape-tests",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
(None, false, false) => None,
|
(None, false, false) => None,
|
||||||
}
|
}
|
||||||
@ -163,14 +169,15 @@ fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// If this span comes from a macro expansion, then the source code may not actually show
|
// If this span comes from a macro expansion, then the source code may not actually show
|
||||||
// a use of the given item, so it would be a poor example. Hence, we skip all uses in macros.
|
// a use of the given item, so it would be a poor example. Hence, we skip all uses in
|
||||||
|
// macros.
|
||||||
if call_span.from_expansion() {
|
if call_span.from_expansion() {
|
||||||
trace!("Rejecting expr from macro: {call_span:?}");
|
trace!("Rejecting expr from macro: {call_span:?}");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the enclosing item has a span coming from a proc macro, then we also don't want to include
|
// If the enclosing item has a span coming from a proc macro, then we also don't want to
|
||||||
// the example.
|
// include the example.
|
||||||
let enclosing_item_span =
|
let enclosing_item_span =
|
||||||
tcx.hir().span_with_body(tcx.hir().get_parent_item(ex.hir_id).into());
|
tcx.hir().span_with_body(tcx.hir().get_parent_item(ex.hir_id).into());
|
||||||
if enclosing_item_span.from_expansion() {
|
if enclosing_item_span.from_expansion() {
|
||||||
@ -178,11 +185,12 @@ fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the enclosing item doesn't actually enclose the call, this means we probably have a weird
|
// If the enclosing item doesn't actually enclose the call, this means we probably have a
|
||||||
// macro issue even though the spans aren't tagged as being from an expansion.
|
// weird macro issue even though the spans aren't tagged as being from an expansion.
|
||||||
if !enclosing_item_span.contains(call_span) {
|
if !enclosing_item_span.contains(call_span) {
|
||||||
warn!(
|
warn!(
|
||||||
"Attempted to scrape call at [{call_span:?}] whose enclosing item [{enclosing_item_span:?}] doesn't contain the span of the call."
|
"Attempted to scrape call at [{call_span:?}] whose enclosing item \
|
||||||
|
[{enclosing_item_span:?}] doesn't contain the span of the call."
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -190,7 +198,8 @@ fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
|
|||||||
// Similarly for the call w/ the function ident.
|
// Similarly for the call w/ the function ident.
|
||||||
if !call_span.contains(ident_span) {
|
if !call_span.contains(ident_span) {
|
||||||
warn!(
|
warn!(
|
||||||
"Attempted to scrape call at [{call_span:?}] whose identifier [{ident_span:?}] was not contained in the span of the call."
|
"Attempted to scrape call at [{call_span:?}] whose identifier [{ident_span:?}] was \
|
||||||
|
not contained in the span of the call."
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -224,7 +233,8 @@ fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
|
|||||||
Some(url) => url,
|
Some(url) => url,
|
||||||
None => {
|
None => {
|
||||||
trace!(
|
trace!(
|
||||||
"Rejecting expr ({call_span:?}) whose clean span ({clean_span:?}) cannot be turned into a link"
|
"Rejecting expr ({call_span:?}) whose clean span ({clean_span:?}) \
|
||||||
|
cannot be turned into a link"
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -272,7 +282,8 @@ pub(crate) fn run(
|
|||||||
let (cx, _) = Context::init(krate, renderopts, cache, tcx).map_err(|e| e.to_string())?;
|
let (cx, _) = Context::init(krate, renderopts, cache, tcx).map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
// Collect CrateIds corresponding to provided target crates
|
// Collect CrateIds corresponding to provided target crates
|
||||||
// If two different versions of the crate in the dependency tree, then examples will be collected from both.
|
// If two different versions of the crate in the dependency tree, then examples will be
|
||||||
|
// collected from both.
|
||||||
let all_crates = tcx
|
let all_crates = tcx
|
||||||
.crates(())
|
.crates(())
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -236,8 +236,11 @@ pub struct Config {
|
|||||||
/// Run ignored tests
|
/// Run ignored tests
|
||||||
pub run_ignored: bool,
|
pub run_ignored: bool,
|
||||||
|
|
||||||
/// Whether to run tests with `ignore-debug` header
|
/// Whether rustc was built with debug assertions.
|
||||||
pub with_debug_assertions: bool,
|
pub with_rustc_debug_assertions: bool,
|
||||||
|
|
||||||
|
/// Whether std was built with debug assertions.
|
||||||
|
pub with_std_debug_assertions: bool,
|
||||||
|
|
||||||
/// Only run tests that match these filters
|
/// Only run tests that match these filters
|
||||||
pub filters: Vec<String>,
|
pub filters: Vec<String>,
|
||||||
|
@ -46,7 +46,6 @@
|
|||||||
"ignore-coverage-map",
|
"ignore-coverage-map",
|
||||||
"ignore-coverage-run",
|
"ignore-coverage-run",
|
||||||
"ignore-cross-compile",
|
"ignore-cross-compile",
|
||||||
"ignore-debug",
|
|
||||||
"ignore-eabi",
|
"ignore-eabi",
|
||||||
"ignore-emscripten",
|
"ignore-emscripten",
|
||||||
"ignore-endian-big",
|
"ignore-endian-big",
|
||||||
@ -82,6 +81,7 @@
|
|||||||
"ignore-powerpc",
|
"ignore-powerpc",
|
||||||
"ignore-remote",
|
"ignore-remote",
|
||||||
"ignore-riscv64",
|
"ignore-riscv64",
|
||||||
|
"ignore-rustc-debug-assertions",
|
||||||
"ignore-s390x",
|
"ignore-s390x",
|
||||||
"ignore-sgx",
|
"ignore-sgx",
|
||||||
"ignore-sparc64",
|
"ignore-sparc64",
|
||||||
@ -89,6 +89,7 @@
|
|||||||
"ignore-stable",
|
"ignore-stable",
|
||||||
"ignore-stage1",
|
"ignore-stage1",
|
||||||
"ignore-stage2",
|
"ignore-stage2",
|
||||||
|
"ignore-std-debug-assertions",
|
||||||
"ignore-test",
|
"ignore-test",
|
||||||
"ignore-thumb",
|
"ignore-thumb",
|
||||||
"ignore-thumbv8m.base-none-eabi",
|
"ignore-thumbv8m.base-none-eabi",
|
||||||
@ -135,6 +136,7 @@
|
|||||||
"needs-relocation-model-pic",
|
"needs-relocation-model-pic",
|
||||||
"needs-run-enabled",
|
"needs-run-enabled",
|
||||||
"needs-rust-lld",
|
"needs-rust-lld",
|
||||||
|
"needs-rustc-debug-assertions",
|
||||||
"needs-sanitizer-address",
|
"needs-sanitizer-address",
|
||||||
"needs-sanitizer-cfi",
|
"needs-sanitizer-cfi",
|
||||||
"needs-sanitizer-dataflow",
|
"needs-sanitizer-dataflow",
|
||||||
@ -147,6 +149,7 @@
|
|||||||
"needs-sanitizer-shadow-call-stack",
|
"needs-sanitizer-shadow-call-stack",
|
||||||
"needs-sanitizer-support",
|
"needs-sanitizer-support",
|
||||||
"needs-sanitizer-thread",
|
"needs-sanitizer-thread",
|
||||||
|
"needs-std-debug-assertions",
|
||||||
"needs-symlink",
|
"needs-symlink",
|
||||||
"needs-threads",
|
"needs-threads",
|
||||||
"needs-unwind",
|
"needs-unwind",
|
||||||
|
@ -202,9 +202,14 @@ macro_rules! condition {
|
|||||||
message: "when running tests remotely",
|
message: "when running tests remotely",
|
||||||
}
|
}
|
||||||
condition! {
|
condition! {
|
||||||
name: "debug",
|
name: "rustc-debug-assertions",
|
||||||
condition: config.with_debug_assertions,
|
condition: config.with_rustc_debug_assertions,
|
||||||
message: "when running tests with `ignore-debug` header",
|
message: "when rustc is built with debug assertions",
|
||||||
|
}
|
||||||
|
condition! {
|
||||||
|
name: "std-debug-assertions",
|
||||||
|
condition: config.with_std_debug_assertions,
|
||||||
|
message: "when std is built with debug assertions",
|
||||||
}
|
}
|
||||||
condition! {
|
condition! {
|
||||||
name: config.debugger.as_ref().map(|d| d.to_str()),
|
name: config.debugger.as_ref().map(|d| d.to_str()),
|
||||||
|
@ -159,6 +159,16 @@ pub(super) fn handle_needs(
|
|||||||
condition: cache.llvm_zstd,
|
condition: cache.llvm_zstd,
|
||||||
ignore_reason: "ignored if LLVM wasn't build with zstd for ELF section compression",
|
ignore_reason: "ignored if LLVM wasn't build with zstd for ELF section compression",
|
||||||
},
|
},
|
||||||
|
Need {
|
||||||
|
name: "needs-rustc-debug-assertions",
|
||||||
|
condition: config.with_rustc_debug_assertions,
|
||||||
|
ignore_reason: "ignored if rustc wasn't built with debug assertions",
|
||||||
|
},
|
||||||
|
Need {
|
||||||
|
name: "needs-std-debug-assertions",
|
||||||
|
condition: config.with_std_debug_assertions,
|
||||||
|
ignore_reason: "ignored if std wasn't built with debug assertions",
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
let (name, comment) = match ln.split_once([':', ' ']) {
|
let (name, comment) = match ln.split_once([':', ' ']) {
|
||||||
|
@ -74,6 +74,8 @@ struct ConfigBuilder {
|
|||||||
git_hash: bool,
|
git_hash: bool,
|
||||||
system_llvm: bool,
|
system_llvm: bool,
|
||||||
profiler_runtime: bool,
|
profiler_runtime: bool,
|
||||||
|
rustc_debug_assertions: bool,
|
||||||
|
std_debug_assertions: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConfigBuilder {
|
impl ConfigBuilder {
|
||||||
@ -122,6 +124,16 @@ fn profiler_runtime(&mut self, is_available: bool) -> &mut Self {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn rustc_debug_assertions(&mut self, is_enabled: bool) -> &mut Self {
|
||||||
|
self.rustc_debug_assertions = is_enabled;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn std_debug_assertions(&mut self, is_enabled: bool) -> &mut Self {
|
||||||
|
self.std_debug_assertions = is_enabled;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
fn build(&mut self) -> Config {
|
fn build(&mut self) -> Config {
|
||||||
let args = &[
|
let args = &[
|
||||||
"compiletest",
|
"compiletest",
|
||||||
@ -170,6 +182,12 @@ fn build(&mut self) -> Config {
|
|||||||
if self.profiler_runtime {
|
if self.profiler_runtime {
|
||||||
args.push("--profiler-runtime".to_owned());
|
args.push("--profiler-runtime".to_owned());
|
||||||
}
|
}
|
||||||
|
if self.rustc_debug_assertions {
|
||||||
|
args.push("--with-rustc-debug-assertions".to_owned());
|
||||||
|
}
|
||||||
|
if self.std_debug_assertions {
|
||||||
|
args.push("--with-std-debug-assertions".to_owned());
|
||||||
|
}
|
||||||
|
|
||||||
args.push("--rustc-path".to_string());
|
args.push("--rustc-path".to_string());
|
||||||
// This is a subtle/fragile thing. On rust-lang CI, there is no global
|
// This is a subtle/fragile thing. On rust-lang CI, there is no global
|
||||||
@ -314,6 +332,32 @@ fn only_target() {
|
|||||||
assert!(!check_ignore(&config, "//@ only-64bit"));
|
assert!(!check_ignore(&config, "//@ only-64bit"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn rustc_debug_assertions() {
|
||||||
|
let config: Config = cfg().rustc_debug_assertions(false).build();
|
||||||
|
|
||||||
|
assert!(check_ignore(&config, "//@ needs-rustc-debug-assertions"));
|
||||||
|
assert!(!check_ignore(&config, "//@ ignore-rustc-debug-assertions"));
|
||||||
|
|
||||||
|
let config: Config = cfg().rustc_debug_assertions(true).build();
|
||||||
|
|
||||||
|
assert!(!check_ignore(&config, "//@ needs-rustc-debug-assertions"));
|
||||||
|
assert!(check_ignore(&config, "//@ ignore-rustc-debug-assertions"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn std_debug_assertions() {
|
||||||
|
let config: Config = cfg().std_debug_assertions(false).build();
|
||||||
|
|
||||||
|
assert!(check_ignore(&config, "//@ needs-std-debug-assertions"));
|
||||||
|
assert!(!check_ignore(&config, "//@ ignore-std-debug-assertions"));
|
||||||
|
|
||||||
|
let config: Config = cfg().std_debug_assertions(true).build();
|
||||||
|
|
||||||
|
assert!(!check_ignore(&config, "//@ needs-std-debug-assertions"));
|
||||||
|
assert!(check_ignore(&config, "//@ ignore-std-debug-assertions"));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn stage() {
|
fn stage() {
|
||||||
let config: Config = cfg().stage_id("stage1-x86_64-unknown-linux-gnu").build();
|
let config: Config = cfg().stage_id("stage1-x86_64-unknown-linux-gnu").build();
|
||||||
|
@ -88,7 +88,8 @@ pub fn parse_config(args: Vec<String>) -> Config {
|
|||||||
.optopt("", "run", "whether to execute run-* tests", "auto | always | never")
|
.optopt("", "run", "whether to execute run-* tests", "auto | always | never")
|
||||||
.optflag("", "ignored", "run tests marked as ignored")
|
.optflag("", "ignored", "run tests marked as ignored")
|
||||||
.optflag("", "has-enzyme", "run tests that require enzyme")
|
.optflag("", "has-enzyme", "run tests that require enzyme")
|
||||||
.optflag("", "with-debug-assertions", "whether to run tests with `ignore-debug` header")
|
.optflag("", "with-rustc-debug-assertions", "whether rustc was built with debug assertions")
|
||||||
|
.optflag("", "with-std-debug-assertions", "whether std was built with debug assertions")
|
||||||
.optmulti(
|
.optmulti(
|
||||||
"",
|
"",
|
||||||
"skip",
|
"skip",
|
||||||
@ -235,7 +236,8 @@ fn make_absolute(path: PathBuf) -> PathBuf {
|
|||||||
|
|
||||||
let src_base = opt_path(matches, "src-base");
|
let src_base = opt_path(matches, "src-base");
|
||||||
let run_ignored = matches.opt_present("ignored");
|
let run_ignored = matches.opt_present("ignored");
|
||||||
let with_debug_assertions = matches.opt_present("with-debug-assertions");
|
let with_rustc_debug_assertions = matches.opt_present("with-rustc-debug-assertions");
|
||||||
|
let with_std_debug_assertions = matches.opt_present("with-std-debug-assertions");
|
||||||
let mode = matches.opt_str("mode").unwrap().parse().expect("invalid mode");
|
let mode = matches.opt_str("mode").unwrap().parse().expect("invalid mode");
|
||||||
let has_html_tidy = if mode == Mode::Rustdoc {
|
let has_html_tidy = if mode == Mode::Rustdoc {
|
||||||
Command::new("tidy")
|
Command::new("tidy")
|
||||||
@ -293,7 +295,8 @@ fn make_absolute(path: PathBuf) -> PathBuf {
|
|||||||
suite: matches.opt_str("suite").unwrap(),
|
suite: matches.opt_str("suite").unwrap(),
|
||||||
debugger: None,
|
debugger: None,
|
||||||
run_ignored,
|
run_ignored,
|
||||||
with_debug_assertions,
|
with_rustc_debug_assertions,
|
||||||
|
with_std_debug_assertions,
|
||||||
filters,
|
filters,
|
||||||
skip: matches.opt_strs("skip"),
|
skip: matches.opt_strs("skip"),
|
||||||
filter_exact: matches.opt_present("exact"),
|
filter_exact: matches.opt_present("exact"),
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
//@ compile-flags: -O
|
//@ compile-flags: -O
|
||||||
//@ ignore-debug
|
//@ ignore-std-debug-assertions
|
||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
use std::collections::binary_heap::PeekMut;
|
use std::collections::binary_heap::PeekMut;
|
||||||
|
@ -4,7 +4,8 @@
|
|||||||
// known to be `1` after inlining).
|
// known to be `1` after inlining).
|
||||||
|
|
||||||
//@ compile-flags: -C no-prepopulate-passes -Zinline-mir=no
|
//@ compile-flags: -C no-prepopulate-passes -Zinline-mir=no
|
||||||
//@ ignore-debug: precondition checks in ptr::read make them a bad candidate for MIR inlining
|
//@ ignore-std-debug-assertions
|
||||||
|
// Reason: precondition checks in ptr::read make them a bad candidate for MIR inlining
|
||||||
//@ needs-deterministic-layouts
|
//@ needs-deterministic-layouts
|
||||||
|
|
||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
//@ compile-flags: -O -C no-prepopulate-passes
|
//@ compile-flags: -O -C no-prepopulate-passes
|
||||||
//@ only-x86_64 (to not worry about usize differing)
|
//@ only-x86_64 (to not worry about usize differing)
|
||||||
//@ ignore-debug: precondition checks make mem::replace not a candidate for MIR inlining
|
//@ ignore-std-debug-assertions
|
||||||
|
// Reason: precondition checks make mem::replace not a candidate for MIR inlining
|
||||||
|
|
||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
// CHECK-LABEL: @bitmask_int
|
// CHECK-LABEL: @bitmask_int
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe fn bitmask_int(x: i32x2) -> u8 {
|
pub unsafe fn bitmask_int(x: i32x2) -> u8 {
|
||||||
// CHECK: [[A:%[0-9]+]] = lshr <2 x i32> %{{x|1}}, <i32 31, i32 31>
|
// CHECK: [[A:%[0-9]+]] = lshr <2 x i32> %{{x|1}}, {{<i32 31, i32 31>|splat \(i32 31\)}}
|
||||||
// CHECK: [[B:%[0-9]+]] = trunc <2 x i32> [[A]] to <2 x i1>
|
// CHECK: [[B:%[0-9]+]] = trunc <2 x i32> [[A]] to <2 x i1>
|
||||||
// CHECK: [[C:%[0-9]+]] = bitcast <2 x i1> [[B]] to i2
|
// CHECK: [[C:%[0-9]+]] = bitcast <2 x i1> [[B]] to i2
|
||||||
// CHECK: %{{[0-9]+}} = zext i2 [[C]] to i8
|
// CHECK: %{{[0-9]+}} = zext i2 [[C]] to i8
|
||||||
@ -41,7 +41,7 @@ pub unsafe fn bitmask_int(x: i32x2) -> u8 {
|
|||||||
// CHECK-LABEL: @bitmask_uint
|
// CHECK-LABEL: @bitmask_uint
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe fn bitmask_uint(x: u32x2) -> u8 {
|
pub unsafe fn bitmask_uint(x: u32x2) -> u8 {
|
||||||
// CHECK: [[A:%[0-9]+]] = lshr <2 x i32> %{{x|1}}, <i32 31, i32 31>
|
// CHECK: [[A:%[0-9]+]] = lshr <2 x i32> %{{x|1}}, {{<i32 31, i32 31>|splat \(i32 31\)}}
|
||||||
// CHECK: [[B:%[0-9]+]] = trunc <2 x i32> [[A]] to <2 x i1>
|
// CHECK: [[B:%[0-9]+]] = trunc <2 x i32> [[A]] to <2 x i1>
|
||||||
// CHECK: [[C:%[0-9]+]] = bitcast <2 x i1> [[B]] to i2
|
// CHECK: [[C:%[0-9]+]] = bitcast <2 x i1> [[B]] to i2
|
||||||
// CHECK: %{{[0-9]+}} = zext i2 [[C]] to i8
|
// CHECK: %{{[0-9]+}} = zext i2 [[C]] to i8
|
||||||
@ -51,7 +51,7 @@ pub unsafe fn bitmask_uint(x: u32x2) -> u8 {
|
|||||||
// CHECK-LABEL: @bitmask_int16
|
// CHECK-LABEL: @bitmask_int16
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe fn bitmask_int16(x: i8x16) -> u16 {
|
pub unsafe fn bitmask_int16(x: i8x16) -> u16 {
|
||||||
// CHECK: [[A:%[0-9]+]] = lshr <16 x i8> %{{x|1|2}}, <i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7>
|
// CHECK: [[A:%[0-9]+]] = lshr <16 x i8> %{{x|1|2}}, {{<i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7>|splat \(i8 7\)}}
|
||||||
// CHECK: [[B:%[0-9]+]] = trunc <16 x i8> [[A]] to <16 x i1>
|
// CHECK: [[B:%[0-9]+]] = trunc <16 x i8> [[A]] to <16 x i1>
|
||||||
// CHECK: %{{[0-9]+}} = bitcast <16 x i1> [[B]] to i16
|
// CHECK: %{{[0-9]+}} = bitcast <16 x i1> [[B]] to i16
|
||||||
// CHECK-NOT: zext
|
// CHECK-NOT: zext
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
//@ compile-flags: -O
|
//@ compile-flags: -O
|
||||||
//@ only-x86_64
|
//@ only-x86_64
|
||||||
//@ ignore-debug: debug assertions prevent generating shufflevector
|
//@ ignore-std-debug-assertions (debug assertions prevent generating shufflevector)
|
||||||
|
|
||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
//@ ignore-debug: FIXME: checks for call detect scoped noalias metadata
|
//@ ignore-std-debug-assertions (FIXME: checks for call detect scoped noalias metadata)
|
||||||
//@ compile-flags: -O -Z merge-functions=disabled
|
//@ compile-flags: -O -Z merge-functions=disabled
|
||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// LLVM 17 realizes double panic is not possible and doesn't generate calls
|
// LLVM 17 realizes double panic is not possible and doesn't generate calls
|
||||||
// to panic_cannot_unwind.
|
// to panic_cannot_unwind.
|
||||||
//@ compile-flags: -O
|
//@ compile-flags: -O
|
||||||
//@ ignore-debug: plain old debug assertions
|
//@ ignore-std-debug-assertions (plain old debug assertions)
|
||||||
//@ needs-unwind
|
//@ needs-unwind
|
||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
#![feature(shrink_to)]
|
#![feature(shrink_to)]
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
//@ compile-flags: -O
|
//@ compile-flags: -O
|
||||||
//@ ignore-debug
|
//@ ignore-std-debug-assertions
|
||||||
// (with debug assertions turned on, `assert_unchecked` generates a real assertion)
|
// (with debug assertions turned on, `assert_unchecked` generates a real assertion)
|
||||||
|
|
||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
//@ compile-flags: -O
|
//@ compile-flags: -O
|
||||||
//@ needs-deterministic-layouts
|
//@ needs-deterministic-layouts
|
||||||
//@ ignore-debug: FIXME: checks for call detect scoped noalias metadata
|
//@ ignore-std-debug-assertions (FIXME: checks for call detect scoped noalias metadata)
|
||||||
|
|
||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// This test checks that `VecDeque::front[_mut]()` and `VecDeque::back[_mut]()` can't panic.
|
// This test checks that `VecDeque::front[_mut]()` and `VecDeque::back[_mut]()` can't panic.
|
||||||
|
|
||||||
//@ compile-flags: -O
|
//@ compile-flags: -O
|
||||||
//@ ignore-debug: plain old debug assertions
|
//@ ignore-std-debug-assertions (plain old debug assertions)
|
||||||
|
|
||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// skip-filecheck
|
// skip-filecheck
|
||||||
//@ compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2 -Zinline-mir
|
//@ compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2 -Zinline-mir
|
||||||
//@ ignore-debug: precondition checks on ptr::read/write are under cfg(debug_assertions)
|
//@ ignore-std-debug-assertions
|
||||||
|
// Reason: precondition checks on ptr::read/write are under cfg(debug_assertions)
|
||||||
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
|
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
|
||||||
|
|
||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// skip-filecheck
|
// skip-filecheck
|
||||||
//@ compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2 -Zinline-mir
|
//@ compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2 -Zinline-mir
|
||||||
//@ ignore-debug: precondition checks are under cfg(debug_assertions)
|
//@ ignore-std-debug-assertions (precondition checks are under cfg(debug_assertions))
|
||||||
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
|
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
|
||||||
|
|
||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// skip-filecheck
|
// skip-filecheck
|
||||||
//@ compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2
|
//@ compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2
|
||||||
//@ only-64bit (constants for `None::<&T>` show in the output)
|
//@ only-64bit (constants for `None::<&T>` show in the output)
|
||||||
//@ ignore-debug: precondition checks on ptr::add are under cfg(debug_assertions)
|
//@ ignore-std-debug-assertions (precondition checks on ptr::add are under cfg(debug_assertions))
|
||||||
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
|
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
|
||||||
|
|
||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
|
149
tests/ui-fulldeps/stable-mir/check_crate_defs.rs
Normal file
149
tests/ui-fulldeps/stable-mir/check_crate_defs.rs
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
//@ run-pass
|
||||||
|
//! Test information about crate definitions (local and external).
|
||||||
|
|
||||||
|
//@ ignore-stage1
|
||||||
|
//@ ignore-cross-compile
|
||||||
|
//@ ignore-remote
|
||||||
|
//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837
|
||||||
|
|
||||||
|
#![feature(rustc_private)]
|
||||||
|
#![feature(assert_matches)]
|
||||||
|
|
||||||
|
extern crate rustc_hir;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate rustc_smir;
|
||||||
|
extern crate rustc_driver;
|
||||||
|
extern crate rustc_interface;
|
||||||
|
extern crate stable_mir;
|
||||||
|
|
||||||
|
use rustc_smir::rustc_internal;
|
||||||
|
use stable_mir::CrateDef;
|
||||||
|
use std::collections::HashSet;
|
||||||
|
use std::io::Write;
|
||||||
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
|
const CRATE_NAME: &str = "crate_defs";
|
||||||
|
|
||||||
|
/// This function uses the Stable MIR APIs to get information about the test crate.
|
||||||
|
fn test_stable_mir() -> ControlFlow<()> {
|
||||||
|
// Find items in the local crate.
|
||||||
|
let local = stable_mir::local_crate();
|
||||||
|
check_items(&local.statics(), &["PRIVATE_STATIC", "dummy::PUBLIC_STATIC"]);
|
||||||
|
check_items(
|
||||||
|
&local.fn_defs(),
|
||||||
|
&[
|
||||||
|
"top_level",
|
||||||
|
"dummy::public_fn",
|
||||||
|
"dummy::private_fn",
|
||||||
|
"dummy::PrivateStruct::new",
|
||||||
|
"<dummy::PrivateStruct as std::ops::Drop>::drop",
|
||||||
|
"DummyTrait::method",
|
||||||
|
"<T as DummyTrait>::method",
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
// Find items inside core crate.
|
||||||
|
// FIXME: We are currently missing primitive type methods and trait implementations for external
|
||||||
|
// crates.
|
||||||
|
let core = stable_mir::find_crates("core").pop().expect("Cannot find `core` crate");
|
||||||
|
contains(
|
||||||
|
&core.fn_defs(),
|
||||||
|
&[
|
||||||
|
"std::fmt::Debug::fmt",
|
||||||
|
"std::option::Option::<T>::is_some",
|
||||||
|
"std::ptr::swap",
|
||||||
|
"<std::slice::Iter<'a, T> as std::iter::Iterator>::next",
|
||||||
|
"core::num::<impl u8>::abs_diff",
|
||||||
|
],
|
||||||
|
);
|
||||||
|
// Ensure nothing crashes. There is no public static in core that we can test here.
|
||||||
|
let _ = core.statics();
|
||||||
|
|
||||||
|
ControlFlow::Continue(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check if the list of definitions matches the expected list.
|
||||||
|
/// Note that order doesn't matter.
|
||||||
|
fn check_items<T: CrateDef>(items: &[T], expected: &[&str]) {
|
||||||
|
let expected: HashSet<_> = expected.iter().map(|s| s.to_string()).collect();
|
||||||
|
let item_names: HashSet<_> = items.iter().map(|item| item.name()).collect();
|
||||||
|
assert_eq!(item_names, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check that the list contains the expected items.
|
||||||
|
fn contains<T: CrateDef + std::fmt::Debug>(items: &[T], expected: &[&str]) {
|
||||||
|
let expected: HashSet<_> = expected.iter().map(|s| s.to_string()).collect();
|
||||||
|
let item_names = items.iter().map(|item| item.name()).collect();
|
||||||
|
let not_found: Vec<_> = expected.difference(&item_names).collect();
|
||||||
|
assert!(not_found.is_empty(), "Missing items: {:?}", not_found);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This test will generate and analyze a dummy crate using the stable mir.
|
||||||
|
/// For that, it will first write the dummy crate into a file.
|
||||||
|
/// Then it will create a `StableMir` using custom arguments and then
|
||||||
|
/// it will run the compiler.
|
||||||
|
fn main() {
|
||||||
|
let path = "crate_definitions.rs";
|
||||||
|
generate_input(&path).unwrap();
|
||||||
|
let args = vec![
|
||||||
|
"rustc".to_string(),
|
||||||
|
"--crate-type=lib".to_string(),
|
||||||
|
"--crate-name".to_string(),
|
||||||
|
CRATE_NAME.to_string(),
|
||||||
|
path.to_string(),
|
||||||
|
];
|
||||||
|
run!(args, test_stable_mir).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_input(path: &str) -> std::io::Result<()> {
|
||||||
|
let mut file = std::fs::File::create(path)?;
|
||||||
|
write!(
|
||||||
|
file,
|
||||||
|
r#"
|
||||||
|
#![allow(dead_code, unused_variables)]
|
||||||
|
static PRIVATE_STATIC: u8 = 0;
|
||||||
|
fn top_level() -> &'static str {{
|
||||||
|
"hello"
|
||||||
|
}}
|
||||||
|
|
||||||
|
pub trait DummyTrait {{
|
||||||
|
fn method(&self) -> Self;
|
||||||
|
}}
|
||||||
|
|
||||||
|
impl<T: Copy> DummyTrait for T {{
|
||||||
|
fn method(&self) -> T {{
|
||||||
|
*self
|
||||||
|
}}
|
||||||
|
}}
|
||||||
|
|
||||||
|
pub mod dummy {{
|
||||||
|
pub static mut PUBLIC_STATIC: Option<char> = None;
|
||||||
|
|
||||||
|
pub fn public_fn(input: bool) -> bool {{
|
||||||
|
private_fn(!input)
|
||||||
|
}}
|
||||||
|
|
||||||
|
fn private_fn(input: bool) -> bool {{
|
||||||
|
todo!()
|
||||||
|
}}
|
||||||
|
|
||||||
|
struct PrivateStruct {{
|
||||||
|
field: u32,
|
||||||
|
}}
|
||||||
|
|
||||||
|
impl PrivateStruct {{
|
||||||
|
fn new() -> Self {{
|
||||||
|
Self {{ field: 42 }}
|
||||||
|
}}
|
||||||
|
}}
|
||||||
|
|
||||||
|
impl Drop for PrivateStruct {{
|
||||||
|
fn drop(&mut self) {{
|
||||||
|
println!("Dropping PrivateStruct");
|
||||||
|
}}
|
||||||
|
}}
|
||||||
|
}}
|
||||||
|
"#
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
@ -11,12 +11,12 @@ LL | *ptr = 0;
|
|||||||
| ^^^^^^^^ accessing memory based on pointer with alignment 1, but alignment 4 is required
|
| ^^^^^^^^ accessing memory based on pointer with alignment 1, but alignment 4 is required
|
||||||
|
|
||||||
error[E0080]: evaluation of constant value failed
|
error[E0080]: evaluation of constant value failed
|
||||||
--> $SRC_DIR/core/src/intrinsics.rs:LL:COL
|
--> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL
|
||||||
|
|
|
|
||||||
= note: accessing memory with alignment 1, but alignment 4 is required
|
= note: accessing memory with alignment 1, but alignment 4 is required
|
||||||
|
|
|
|
||||||
note: inside `copy_nonoverlapping::<u32>`
|
note: inside `copy_nonoverlapping::<u32>`
|
||||||
--> $SRC_DIR/core/src/intrinsics.rs:LL:COL
|
--> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL
|
||||||
note: inside `std::ptr::const_ptr::<impl *const u32>::copy_to_nonoverlapping`
|
note: inside `std::ptr::const_ptr::<impl *const u32>::copy_to_nonoverlapping`
|
||||||
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
||||||
note: inside `MISALIGNED_COPY`
|
note: inside `MISALIGNED_COPY`
|
||||||
|
@ -27,7 +27,7 @@ LL | const_eval_select((), 42, 0xDEADBEEF);
|
|||||||
= help: the trait `FnOnce()` is not implemented for `{integer}`
|
= help: the trait `FnOnce()` is not implemented for `{integer}`
|
||||||
= note: wrap the `{integer}` in a closure with no arguments: `|| { /* code */ }`
|
= note: wrap the `{integer}` in a closure with no arguments: `|| { /* code */ }`
|
||||||
note: required by a bound in `const_eval_select`
|
note: required by a bound in `const_eval_select`
|
||||||
--> $SRC_DIR/core/src/intrinsics.rs:LL:COL
|
--> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL
|
||||||
|
|
||||||
error[E0277]: expected a `FnOnce()` closure, found `{integer}`
|
error[E0277]: expected a `FnOnce()` closure, found `{integer}`
|
||||||
--> $DIR/const-eval-select-bad.rs:10:31
|
--> $DIR/const-eval-select-bad.rs:10:31
|
||||||
@ -40,7 +40,7 @@ LL | const_eval_select((), 42, 0xDEADBEEF);
|
|||||||
= help: the trait `FnOnce()` is not implemented for `{integer}`
|
= help: the trait `FnOnce()` is not implemented for `{integer}`
|
||||||
= note: wrap the `{integer}` in a closure with no arguments: `|| { /* code */ }`
|
= note: wrap the `{integer}` in a closure with no arguments: `|| { /* code */ }`
|
||||||
note: required by a bound in `const_eval_select`
|
note: required by a bound in `const_eval_select`
|
||||||
--> $SRC_DIR/core/src/intrinsics.rs:LL:COL
|
--> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL
|
||||||
|
|
||||||
error: this argument must be a function item
|
error: this argument must be a function item
|
||||||
--> $DIR/const-eval-select-bad.rs:10:27
|
--> $DIR/const-eval-select-bad.rs:10:27
|
||||||
@ -69,7 +69,7 @@ LL | const_eval_select((1,), foo, bar);
|
|||||||
| required by a bound introduced by this call
|
| required by a bound introduced by this call
|
||||||
|
|
|
|
||||||
note: required by a bound in `const_eval_select`
|
note: required by a bound in `const_eval_select`
|
||||||
--> $SRC_DIR/core/src/intrinsics.rs:LL:COL
|
--> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL
|
||||||
|
|
||||||
error[E0631]: type mismatch in function arguments
|
error[E0631]: type mismatch in function arguments
|
||||||
--> $DIR/const-eval-select-bad.rs:37:32
|
--> $DIR/const-eval-select-bad.rs:37:32
|
||||||
@ -85,7 +85,7 @@ LL | const_eval_select((true,), foo, baz);
|
|||||||
= note: expected function signature `fn(bool) -> _`
|
= note: expected function signature `fn(bool) -> _`
|
||||||
found function signature `fn(i32) -> _`
|
found function signature `fn(i32) -> _`
|
||||||
note: required by a bound in `const_eval_select`
|
note: required by a bound in `const_eval_select`
|
||||||
--> $SRC_DIR/core/src/intrinsics.rs:LL:COL
|
--> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL
|
||||||
help: consider wrapping the function in a closure
|
help: consider wrapping the function in a closure
|
||||||
|
|
|
|
||||||
LL | const_eval_select((true,), |arg0: bool| foo(/* i32 */), baz);
|
LL | const_eval_select((true,), |arg0: bool| foo(/* i32 */), baz);
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
//! padding and overall computed sizes can be quite different.
|
//! padding and overall computed sizes can be quite different.
|
||||||
//!
|
//!
|
||||||
//@ compile-flags: -Z print-type-sizes --crate-type lib
|
//@ compile-flags: -Z print-type-sizes --crate-type lib
|
||||||
//@ ignore-debug: debug assertions will print more types
|
//@ ignore-std-debug-assertions (debug assertions will print more types)
|
||||||
//@ build-pass
|
//@ build-pass
|
||||||
//@ ignore-pass
|
//@ ignore-pass
|
||||||
// ^-- needed because `--pass check` does not emit the output needed.
|
// ^-- needed because `--pass check` does not emit the output needed.
|
||||||
|
13
tests/ui/statics/static-mut-shared-parens.rs
Normal file
13
tests/ui/statics/static-mut-shared-parens.rs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
//Missing paren in diagnostic msg: https://github.com/rust-lang/rust/issues/131977
|
||||||
|
//@check-pass
|
||||||
|
|
||||||
|
|
||||||
|
static mut TEST: usize = 0;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _ = unsafe { (&TEST) as *const usize };
|
||||||
|
//~^WARN creating a shared reference to mutable static is discouraged
|
||||||
|
|
||||||
|
let _ = unsafe { ((&mut TEST)) as *const usize };
|
||||||
|
//~^WARN creating a mutable reference to mutable static is discouraged
|
||||||
|
}
|
29
tests/ui/statics/static-mut-shared-parens.stderr
Normal file
29
tests/ui/statics/static-mut-shared-parens.stderr
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
warning: creating a shared reference to mutable static is discouraged
|
||||||
|
--> $DIR/static-mut-shared-parens.rs:8:22
|
||||||
|
|
|
||||||
|
LL | let _ = unsafe { (&TEST) as *const usize };
|
||||||
|
| ^^^^^^^ shared reference to mutable static
|
||||||
|
|
|
||||||
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
|
||||||
|
= note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
|
||||||
|
= note: `#[warn(static_mut_refs)]` on by default
|
||||||
|
help: use `&raw const` instead to create a raw pointer
|
||||||
|
|
|
||||||
|
LL | let _ = unsafe { (&raw const TEST) as *const usize };
|
||||||
|
| ~~~~~~~~~~
|
||||||
|
|
||||||
|
warning: creating a mutable reference to mutable static is discouraged
|
||||||
|
--> $DIR/static-mut-shared-parens.rs:11:22
|
||||||
|
|
|
||||||
|
LL | let _ = unsafe { ((&mut TEST)) as *const usize };
|
||||||
|
| ^^^^^^^^^^^^^ mutable reference to mutable static
|
||||||
|
|
|
||||||
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
|
||||||
|
= note: mutable references to mutable statics are dangerous; it's undefined behavior if any other pointer to the static is used or if any other reference is created for the static while the mutable reference lives
|
||||||
|
help: use `&raw mut` instead to create a raw pointer
|
||||||
|
|
|
||||||
|
LL | let _ = unsafe { ((&raw mut TEST)) as *const usize };
|
||||||
|
| ~~~~~~~~
|
||||||
|
|
||||||
|
warning: 2 warnings emitted
|
||||||
|
|
Loading…
Reference in New Issue
Block a user