Auto merge of #128783 - GuillaumeGomez:rollup-2kvpg7s, r=GuillaumeGomez
Rollup of 9 pull requests Successful merges: - #128206 (Make create_dll_import_lib easier to implement) - #128424 (minor `effects` cleanups) - #128527 (More information for fully-qualified suggestion when there are multiple impls) - #128656 (Enable msvc for run-make/rust-lld) - #128683 (bootstrap: clear miri's ui test deps when rustc changes) - #128700 (Migrate `simd-ffi` `run-make` test to rmake) - #128753 (Don't arbitrarily choose one upper bound for hidden captured region error message) - #128757 (Migrate `pgo-gen-lto` `run-make` test to rmake) - #128758 (Specify a minimum supported version for VxWorks) Failed merges: - #128679 (codegen: better centralize function declaration attribute computation) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
8d0066922b
34 changed files with 566 additions and 473 deletions
15
Cargo.lock
15
Cargo.lock
|
|
@ -205,11 +205,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ar_archive_writer"
|
||||
version = "0.3.0"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8412a2d690663356cba5a2532f3ed55d1e8090743bc6695b88403b27df67733"
|
||||
checksum = "3f2bcb7cf51decfbbfc7ef476e28b0775b13e5eb1190f8b7df145cd53d4f4374"
|
||||
dependencies = [
|
||||
"object 0.35.0",
|
||||
"object 0.36.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2454,15 +2454,6 @@ dependencies = [
|
|||
"ruzstd 0.5.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.35.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8ec7ab813848ba4522158d5517a6093db1ded27575b070f4177b8d12b41db5e"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.36.2"
|
||||
|
|
|
|||
|
|
@ -1668,7 +1668,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
}),
|
||||
)),
|
||||
)),
|
||||
// FIXME(effects) we might not need a default.
|
||||
default: Some(default_ct),
|
||||
is_host_effect: true,
|
||||
synthetic: true,
|
||||
|
|
|
|||
|
|
@ -225,21 +225,26 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
|
||||
// Find something that we can name
|
||||
let upper_bound = self.approx_universal_upper_bound(vid);
|
||||
let upper_bound = &self.definitions[upper_bound];
|
||||
match upper_bound.external_name {
|
||||
Some(reg) => reg,
|
||||
None => {
|
||||
// Nothing exact found, so we pick the first one that we find.
|
||||
let scc = self.constraint_sccs.scc(vid);
|
||||
for vid in self.rev_scc_graph.as_ref().unwrap().upper_bounds(scc) {
|
||||
match self.definitions[vid].external_name {
|
||||
None => {}
|
||||
Some(region) if region.is_static() => {}
|
||||
Some(region) => return region,
|
||||
}
|
||||
}
|
||||
region
|
||||
}
|
||||
if let Some(universal_region) = self.definitions[upper_bound].external_name {
|
||||
return universal_region;
|
||||
}
|
||||
|
||||
// Nothing exact found, so we pick a named upper bound, if there's only one.
|
||||
// If there's >1 universal region, then we probably are dealing w/ an intersection
|
||||
// region which cannot be mapped back to a universal.
|
||||
// FIXME: We could probably compute the LUB if there is one.
|
||||
let scc = self.constraint_sccs.scc(vid);
|
||||
let upper_bounds: Vec<_> = self
|
||||
.rev_scc_graph
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.upper_bounds(scc)
|
||||
.filter_map(|vid| self.definitions[vid].external_name)
|
||||
.filter(|r| !r.is_static())
|
||||
.collect();
|
||||
match &upper_bounds[..] {
|
||||
[universal_region] => *universal_region,
|
||||
_ => region,
|
||||
}
|
||||
}
|
||||
_ => region,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use std::path::{Path, PathBuf};
|
||||
use std::path::Path;
|
||||
|
||||
use rustc_codegen_ssa::back::archive::{
|
||||
ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder, DEFAULT_OBJECT_READER,
|
||||
|
|
@ -16,10 +16,9 @@ impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
|
|||
&self,
|
||||
sess: &Session,
|
||||
_lib_name: &str,
|
||||
_dll_imports: &[rustc_session::cstore::DllImport],
|
||||
_tmpdir: &Path,
|
||||
_is_direct_dependency: bool,
|
||||
) -> PathBuf {
|
||||
_import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
|
||||
_output_path: &Path,
|
||||
) {
|
||||
sess.dcx().fatal("raw-dylib is not yet supported by rustc_codegen_cranelift");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
use std::path::{Path, PathBuf};
|
||||
use std::path::Path;
|
||||
|
||||
use rustc_codegen_ssa::back::archive::{
|
||||
ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder, DEFAULT_OBJECT_READER,
|
||||
};
|
||||
use rustc_session::cstore::DllImport;
|
||||
use rustc_session::Session;
|
||||
|
||||
pub(crate) struct ArArchiveBuilderBuilder;
|
||||
|
|
@ -17,10 +16,9 @@ impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
|
|||
&self,
|
||||
_sess: &Session,
|
||||
_lib_name: &str,
|
||||
_dll_imports: &[DllImport],
|
||||
_tmpdir: &Path,
|
||||
_is_direct_dependency: bool,
|
||||
) -> PathBuf {
|
||||
_import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
|
||||
_output_path: &Path,
|
||||
) {
|
||||
unimplemented!("creating dll imports is not yet supported");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,23 +1,13 @@
|
|||
codegen_llvm_copy_bitcode = failed to copy bitcode to object file: {$err}
|
||||
|
||||
codegen_llvm_dlltool_fail_import_library =
|
||||
Dlltool could not create import library with {$dlltool_path} {$dlltool_args}:
|
||||
{$stdout}
|
||||
{$stderr}
|
||||
|
||||
codegen_llvm_dynamic_linking_with_lto =
|
||||
cannot prefer dynamic linking when performing LTO
|
||||
.note = only 'staticlib', 'bin', and 'cdylib' outputs are supported with LTO
|
||||
|
||||
codegen_llvm_error_calling_dlltool =
|
||||
Error calling dlltool '{$dlltool_path}': {$error}
|
||||
|
||||
codegen_llvm_error_creating_import_library =
|
||||
Error creating import library for {$lib_name}: {$error}
|
||||
|
||||
codegen_llvm_error_writing_def_file =
|
||||
Error writing .DEF file: {$error}
|
||||
|
||||
codegen_llvm_fixed_x18_invalid_arch = the `-Zfixed-x18` flag is not supported on the `{$arch}` architecture
|
||||
|
||||
codegen_llvm_from_llvm_diag = {$message}
|
||||
|
|
|
|||
|
|
@ -1,21 +1,19 @@
|
|||
//! A helper class for dealing with static archives
|
||||
|
||||
use std::ffi::{c_char, c_void, CStr, CString, OsString};
|
||||
use std::ffi::{c_char, c_void, CStr, CString};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::{env, io, mem, ptr, str};
|
||||
use std::{io, mem, ptr, str};
|
||||
|
||||
use rustc_codegen_ssa::back::archive::{
|
||||
try_extract_macho_fat_archive, ArArchiveBuilder, ArchiveBuildFailure, ArchiveBuilder,
|
||||
ArchiveBuilderBuilder, ObjectReader, UnknownArchiveKind, DEFAULT_OBJECT_READER,
|
||||
create_mingw_dll_import_lib, try_extract_macho_fat_archive, ArArchiveBuilder,
|
||||
ArchiveBuildFailure, ArchiveBuilder, ArchiveBuilderBuilder, ObjectReader, UnknownArchiveKind,
|
||||
DEFAULT_OBJECT_READER,
|
||||
};
|
||||
use rustc_session::cstore::DllImport;
|
||||
use rustc_codegen_ssa::common;
|
||||
use rustc_session::Session;
|
||||
use tracing::trace;
|
||||
|
||||
use crate::common;
|
||||
use crate::errors::{
|
||||
DlltoolFailImportLibrary, ErrorCallingDllTool, ErrorCreatingImportLibrary, ErrorWritingDEFFile,
|
||||
};
|
||||
use crate::errors::ErrorCreatingImportLibrary;
|
||||
use crate::llvm::archive_ro::{ArchiveRO, Child};
|
||||
use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport};
|
||||
|
||||
|
|
@ -121,116 +119,21 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
|
|||
&self,
|
||||
sess: &Session,
|
||||
lib_name: &str,
|
||||
dll_imports: &[DllImport],
|
||||
tmpdir: &Path,
|
||||
is_direct_dependency: bool,
|
||||
) -> PathBuf {
|
||||
let name_suffix = if is_direct_dependency { "_imports" } else { "_imports_indirect" };
|
||||
let output_path = tmpdir.join(format!("{lib_name}{name_suffix}.lib"));
|
||||
|
||||
let target = &sess.target;
|
||||
let mingw_gnu_toolchain = common::is_mingw_gnu_toolchain(target);
|
||||
|
||||
let import_name_and_ordinal_vector: Vec<(String, Option<u16>)> = dll_imports
|
||||
.iter()
|
||||
.map(|import: &DllImport| {
|
||||
if sess.target.arch == "x86" {
|
||||
(
|
||||
common::i686_decorated_name(import, mingw_gnu_toolchain, false),
|
||||
import.ordinal(),
|
||||
)
|
||||
} else {
|
||||
(import.name.to_string(), import.ordinal())
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
if mingw_gnu_toolchain {
|
||||
import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
|
||||
output_path: &Path,
|
||||
) {
|
||||
if common::is_mingw_gnu_toolchain(&sess.target) {
|
||||
// The binutils linker used on -windows-gnu targets cannot read the import
|
||||
// libraries generated by LLVM: in our attempts, the linker produced an .EXE
|
||||
// that loaded but crashed with an AV upon calling one of the imported
|
||||
// functions. Therefore, use binutils to create the import library instead,
|
||||
// by writing a .DEF file to the temp dir and calling binutils's dlltool.
|
||||
let def_file_path = tmpdir.join(format!("{lib_name}{name_suffix}.def"));
|
||||
|
||||
let def_file_content = format!(
|
||||
"EXPORTS\n{}",
|
||||
import_name_and_ordinal_vector
|
||||
.into_iter()
|
||||
.map(|(name, ordinal)| {
|
||||
match ordinal {
|
||||
Some(n) => format!("{name} @{n} NONAME"),
|
||||
None => name,
|
||||
}
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
.join("\n")
|
||||
create_mingw_dll_import_lib(
|
||||
sess,
|
||||
lib_name,
|
||||
import_name_and_ordinal_vector,
|
||||
output_path,
|
||||
);
|
||||
|
||||
match std::fs::write(&def_file_path, def_file_content) {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
sess.dcx().emit_fatal(ErrorWritingDEFFile { error: e });
|
||||
}
|
||||
};
|
||||
|
||||
// --no-leading-underscore: For the `import_name_type` feature to work, we need to be
|
||||
// able to control the *exact* spelling of each of the symbols that are being imported:
|
||||
// hence we don't want `dlltool` adding leading underscores automatically.
|
||||
let dlltool = find_binutils_dlltool(sess);
|
||||
let temp_prefix = {
|
||||
let mut path = PathBuf::from(&output_path);
|
||||
path.pop();
|
||||
path.push(lib_name);
|
||||
path
|
||||
};
|
||||
// dlltool target architecture args from:
|
||||
// https://github.com/llvm/llvm-project-release-prs/blob/llvmorg-15.0.6/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp#L69
|
||||
let (dlltool_target_arch, dlltool_target_bitness) = match sess.target.arch.as_ref() {
|
||||
"x86_64" => ("i386:x86-64", "--64"),
|
||||
"x86" => ("i386", "--32"),
|
||||
"aarch64" => ("arm64", "--64"),
|
||||
"arm" => ("arm", "--32"),
|
||||
_ => panic!("unsupported arch {}", sess.target.arch),
|
||||
};
|
||||
let mut dlltool_cmd = std::process::Command::new(&dlltool);
|
||||
dlltool_cmd
|
||||
.arg("-d")
|
||||
.arg(def_file_path)
|
||||
.arg("-D")
|
||||
.arg(lib_name)
|
||||
.arg("-l")
|
||||
.arg(&output_path)
|
||||
.arg("-m")
|
||||
.arg(dlltool_target_arch)
|
||||
.arg("-f")
|
||||
.arg(dlltool_target_bitness)
|
||||
.arg("--no-leading-underscore")
|
||||
.arg("--temp-prefix")
|
||||
.arg(temp_prefix);
|
||||
|
||||
match dlltool_cmd.output() {
|
||||
Err(e) => {
|
||||
sess.dcx().emit_fatal(ErrorCallingDllTool {
|
||||
dlltool_path: dlltool.to_string_lossy(),
|
||||
error: e,
|
||||
});
|
||||
}
|
||||
// dlltool returns '0' on failure, so check for error output instead.
|
||||
Ok(output) if !output.stderr.is_empty() => {
|
||||
sess.dcx().emit_fatal(DlltoolFailImportLibrary {
|
||||
dlltool_path: dlltool.to_string_lossy(),
|
||||
dlltool_args: dlltool_cmd
|
||||
.get_args()
|
||||
.map(|arg| arg.to_string_lossy())
|
||||
.collect::<Vec<_>>()
|
||||
.join(" "),
|
||||
stdout: String::from_utf8_lossy(&output.stdout),
|
||||
stderr: String::from_utf8_lossy(&output.stderr),
|
||||
})
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
} else {
|
||||
// we've checked for \0 characters in the library name already
|
||||
let dll_name_z = CString::new(lib_name).unwrap();
|
||||
|
|
@ -242,9 +145,9 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
|
|||
trace!(" output_path {}", output_path.display());
|
||||
trace!(
|
||||
" import names: {}",
|
||||
dll_imports
|
||||
import_name_and_ordinal_vector
|
||||
.iter()
|
||||
.map(|import| import.name.to_string())
|
||||
.map(|(name, _ordinal)| name.clone())
|
||||
.collect::<Vec<_>>()
|
||||
.join(", "),
|
||||
);
|
||||
|
|
@ -281,9 +184,7 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
|
|||
error: llvm::last_error().unwrap_or("unknown LLVM error".to_string()),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
output_path
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -457,39 +358,3 @@ impl<'a> LlvmArchiveBuilder<'a> {
|
|||
fn string_to_io_error(s: String) -> io::Error {
|
||||
io::Error::new(io::ErrorKind::Other, format!("bad archive: {s}"))
|
||||
}
|
||||
|
||||
fn find_binutils_dlltool(sess: &Session) -> OsString {
|
||||
assert!(sess.target.options.is_like_windows && !sess.target.options.is_like_msvc);
|
||||
if let Some(dlltool_path) = &sess.opts.cg.dlltool {
|
||||
return dlltool_path.clone().into_os_string();
|
||||
}
|
||||
|
||||
let tool_name: OsString = if sess.host.options.is_like_windows {
|
||||
// If we're compiling on Windows, always use "dlltool.exe".
|
||||
"dlltool.exe"
|
||||
} else {
|
||||
// On other platforms, use the architecture-specific name.
|
||||
match sess.target.arch.as_ref() {
|
||||
"x86_64" => "x86_64-w64-mingw32-dlltool",
|
||||
"x86" => "i686-w64-mingw32-dlltool",
|
||||
"aarch64" => "aarch64-w64-mingw32-dlltool",
|
||||
|
||||
// For non-standard architectures (e.g., aarch32) fallback to "dlltool".
|
||||
_ => "dlltool",
|
||||
}
|
||||
}
|
||||
.into();
|
||||
|
||||
// NOTE: it's not clear how useful it is to explicitly search PATH.
|
||||
for dir in env::split_paths(&env::var_os("PATH").unwrap_or_default()) {
|
||||
let full_path = dir.join(&tool_name);
|
||||
if full_path.is_file() {
|
||||
return full_path.into_os_string();
|
||||
}
|
||||
}
|
||||
|
||||
// The user didn't specify the location of the dlltool binary, and we weren't able
|
||||
// to find the appropriate one on the PATH. Just return the name of the tool
|
||||
// and let the invocation fail with a hopefully useful error message.
|
||||
tool_name
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,13 +4,14 @@
|
|||
//! and methods are represented as just a fn ptr and not a full
|
||||
//! closure.
|
||||
|
||||
use rustc_codegen_ssa::common;
|
||||
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
|
||||
use rustc_middle::ty::{self, Instance, TypeVisitableExt};
|
||||
use tracing::debug;
|
||||
|
||||
use crate::context::CodegenCx;
|
||||
use crate::value::Value;
|
||||
use crate::{attributes, common, llvm};
|
||||
use crate::{attributes, llvm};
|
||||
|
||||
/// Codegens a reference to a fn/method item, monomorphizing and
|
||||
/// inlining as it goes.
|
||||
|
|
@ -46,7 +47,7 @@ pub fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) ->
|
|||
} else {
|
||||
let instance_def_id = instance.def_id();
|
||||
let llfn = if tcx.sess.target.arch == "x86"
|
||||
&& let Some(dllimport) = common::get_dllimport(tcx, instance_def_id, sym)
|
||||
&& let Some(dllimport) = crate::common::get_dllimport(tcx, instance_def_id, sym)
|
||||
{
|
||||
// Fix for https://github.com/rust-lang/rust/issues/104453
|
||||
// On x86 Windows, LLVM uses 'L' as the prefix for any private
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
//! Code that is useful in various codegen modules.
|
||||
|
||||
use std::fmt::Write;
|
||||
|
||||
use libc::{c_char, c_uint};
|
||||
use rustc_ast::Mutability;
|
||||
use rustc_codegen_ssa::traits::*;
|
||||
|
|
@ -10,9 +8,8 @@ use rustc_hir::def_id::DefId;
|
|||
use rustc_middle::bug;
|
||||
use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc, Scalar};
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::cstore::{DllCallingConvention, DllImport, PeImportNameType};
|
||||
use rustc_session::cstore::DllImport;
|
||||
use rustc_target::abi::{self, AddressSpace, HasDataLayout, Pointer};
|
||||
use rustc_target::spec::Target;
|
||||
use tracing::debug;
|
||||
|
||||
use crate::consts::const_alloc_to_llvm;
|
||||
|
|
@ -379,64 +376,3 @@ pub(crate) fn get_dllimport<'tcx>(
|
|||
tcx.native_library(id)
|
||||
.and_then(|lib| lib.dll_imports.iter().find(|di| di.name.as_str() == name))
|
||||
}
|
||||
|
||||
pub(crate) fn is_mingw_gnu_toolchain(target: &Target) -> bool {
|
||||
target.vendor == "pc" && target.os == "windows" && target.env == "gnu" && target.abi.is_empty()
|
||||
}
|
||||
|
||||
pub(crate) fn i686_decorated_name(
|
||||
dll_import: &DllImport,
|
||||
mingw: bool,
|
||||
disable_name_mangling: bool,
|
||||
) -> String {
|
||||
let name = dll_import.name.as_str();
|
||||
|
||||
let (add_prefix, add_suffix) = match dll_import.import_name_type {
|
||||
Some(PeImportNameType::NoPrefix) => (false, true),
|
||||
Some(PeImportNameType::Undecorated) => (false, false),
|
||||
_ => (true, true),
|
||||
};
|
||||
|
||||
// Worst case: +1 for disable name mangling, +1 for prefix, +4 for suffix (@@__).
|
||||
let mut decorated_name = String::with_capacity(name.len() + 6);
|
||||
|
||||
if disable_name_mangling {
|
||||
// LLVM uses a binary 1 ('\x01') prefix to a name to indicate that mangling needs to be disabled.
|
||||
decorated_name.push('\x01');
|
||||
}
|
||||
|
||||
let prefix = if add_prefix && dll_import.is_fn {
|
||||
match dll_import.calling_convention {
|
||||
DllCallingConvention::C | DllCallingConvention::Vectorcall(_) => None,
|
||||
DllCallingConvention::Stdcall(_) => (!mingw
|
||||
|| dll_import.import_name_type == Some(PeImportNameType::Decorated))
|
||||
.then_some('_'),
|
||||
DllCallingConvention::Fastcall(_) => Some('@'),
|
||||
}
|
||||
} else if !dll_import.is_fn && !mingw {
|
||||
// For static variables, prefix with '_' on MSVC.
|
||||
Some('_')
|
||||
} else {
|
||||
None
|
||||
};
|
||||
if let Some(prefix) = prefix {
|
||||
decorated_name.push(prefix);
|
||||
}
|
||||
|
||||
decorated_name.push_str(name);
|
||||
|
||||
if add_suffix && dll_import.is_fn {
|
||||
match dll_import.calling_convention {
|
||||
DllCallingConvention::C => {}
|
||||
DllCallingConvention::Stdcall(arg_list_size)
|
||||
| DllCallingConvention::Fastcall(arg_list_size) => {
|
||||
write!(&mut decorated_name, "@{arg_list_size}").unwrap();
|
||||
}
|
||||
DllCallingConvention::Vectorcall(arg_list_size) => {
|
||||
write!(&mut decorated_name, "@@{arg_list_size}").unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
decorated_name
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use std::ops::Range;
|
||||
|
||||
use rustc_codegen_ssa::common;
|
||||
use rustc_codegen_ssa::traits::*;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::DefId;
|
||||
|
|
@ -18,7 +19,7 @@ use rustc_target::abi::{
|
|||
};
|
||||
use tracing::{debug, instrument, trace};
|
||||
|
||||
use crate::common::{self, CodegenCx};
|
||||
use crate::common::CodegenCx;
|
||||
use crate::errors::{
|
||||
InvalidMinimumAlignmentNotPowerOfTwo, InvalidMinimumAlignmentTooLarge, SymbolAlreadyDefined,
|
||||
};
|
||||
|
|
@ -195,7 +196,7 @@ fn check_and_apply_linkage<'ll, 'tcx>(
|
|||
g2
|
||||
}
|
||||
} else if cx.tcx.sess.target.arch == "x86"
|
||||
&& let Some(dllimport) = common::get_dllimport(cx.tcx, def_id, sym)
|
||||
&& let Some(dllimport) = crate::common::get_dllimport(cx.tcx, def_id, sym)
|
||||
{
|
||||
cx.declare_global(
|
||||
&common::i686_decorated_name(
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
use std::borrow::Cow;
|
||||
use std::ffi::CString;
|
||||
use std::path::Path;
|
||||
|
||||
|
|
@ -71,28 +70,6 @@ pub(crate) struct InvalidMinimumAlignmentTooLarge {
|
|||
#[diag(codegen_llvm_sanitizer_memtag_requires_mte)]
|
||||
pub(crate) struct SanitizerMemtagRequiresMte;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_error_writing_def_file)]
|
||||
pub(crate) struct ErrorWritingDEFFile {
|
||||
pub error: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_error_calling_dlltool)]
|
||||
pub(crate) struct ErrorCallingDllTool<'a> {
|
||||
pub dlltool_path: Cow<'a, str>,
|
||||
pub error: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_dlltool_fail_import_library)]
|
||||
pub(crate) struct DlltoolFailImportLibrary<'a> {
|
||||
pub dlltool_path: Cow<'a, str>,
|
||||
pub dlltool_args: String,
|
||||
pub stdout: Cow<'a, str>,
|
||||
pub stderr: Cow<'a, str>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_dynamic_linking_with_lto)]
|
||||
#[note]
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ edition = "2021"
|
|||
|
||||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
ar_archive_writer = "0.3.0"
|
||||
ar_archive_writer = "0.3.3"
|
||||
arrayvec = { version = "0.7", default-features = false }
|
||||
bitflags = "2.4.1"
|
||||
cc = "1.0.90"
|
||||
|
|
|
|||
|
|
@ -24,8 +24,19 @@ codegen_ssa_copy_path_buf = unable to copy {$source_file} to {$output_path}: {$e
|
|||
|
||||
codegen_ssa_create_temp_dir = couldn't create a temp dir: {$error}
|
||||
|
||||
codegen_ssa_dlltool_fail_import_library =
|
||||
Dlltool could not create import library with {$dlltool_path} {$dlltool_args}:
|
||||
{$stdout}
|
||||
{$stderr}
|
||||
|
||||
codegen_ssa_error_calling_dlltool =
|
||||
Error calling dlltool '{$dlltool_path}': {$error}
|
||||
|
||||
codegen_ssa_error_creating_remark_dir = failed to create remark directory: {$error}
|
||||
|
||||
codegen_ssa_error_writing_def_file =
|
||||
Error writing .DEF file: {$error}
|
||||
|
||||
codegen_ssa_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`
|
||||
|
||||
codegen_ssa_extern_funcs_not_found = some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
use std::env;
|
||||
use std::error::Error;
|
||||
use std::ffi::OsString;
|
||||
use std::fs::{self, File};
|
||||
use std::io::{self, Write};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
|
@ -9,7 +11,6 @@ use object::read::archive::ArchiveFile;
|
|||
use object::read::macho::FatArch;
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_data_structures::memmap::Mmap;
|
||||
use rustc_session::cstore::DllImport;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::symbol::Symbol;
|
||||
use tempfile::Builder as TempFileBuilder;
|
||||
|
|
@ -17,6 +18,7 @@ use tempfile::Builder as TempFileBuilder;
|
|||
use super::metadata::search_for_section;
|
||||
// Re-exporting for rustc_codegen_llvm::back::archive
|
||||
pub use crate::errors::{ArchiveBuildFailure, ExtractBundledLibsError, UnknownArchiveKind};
|
||||
use crate::errors::{DlltoolFailImportLibrary, ErrorCallingDllTool, ErrorWritingDEFFile};
|
||||
|
||||
pub trait ArchiveBuilderBuilder {
|
||||
fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder + 'a>;
|
||||
|
|
@ -30,10 +32,9 @@ pub trait ArchiveBuilderBuilder {
|
|||
&self,
|
||||
sess: &Session,
|
||||
lib_name: &str,
|
||||
dll_imports: &[DllImport],
|
||||
tmpdir: &Path,
|
||||
is_direct_dependency: bool,
|
||||
) -> PathBuf;
|
||||
import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
|
||||
output_path: &Path,
|
||||
);
|
||||
|
||||
fn extract_bundled_libs<'a>(
|
||||
&'a self,
|
||||
|
|
@ -72,6 +73,130 @@ pub trait ArchiveBuilderBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn create_mingw_dll_import_lib(
|
||||
sess: &Session,
|
||||
lib_name: &str,
|
||||
import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
|
||||
output_path: &Path,
|
||||
) {
|
||||
let def_file_path = output_path.with_extension("def");
|
||||
|
||||
let def_file_content = format!(
|
||||
"EXPORTS\n{}",
|
||||
import_name_and_ordinal_vector
|
||||
.into_iter()
|
||||
.map(|(name, ordinal)| {
|
||||
match ordinal {
|
||||
Some(n) => format!("{name} @{n} NONAME"),
|
||||
None => name,
|
||||
}
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
.join("\n")
|
||||
);
|
||||
|
||||
match std::fs::write(&def_file_path, def_file_content) {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
sess.dcx().emit_fatal(ErrorWritingDEFFile { error: e });
|
||||
}
|
||||
};
|
||||
|
||||
// --no-leading-underscore: For the `import_name_type` feature to work, we need to be
|
||||
// able to control the *exact* spelling of each of the symbols that are being imported:
|
||||
// hence we don't want `dlltool` adding leading underscores automatically.
|
||||
let dlltool = find_binutils_dlltool(sess);
|
||||
let temp_prefix = {
|
||||
let mut path = PathBuf::from(&output_path);
|
||||
path.pop();
|
||||
path.push(lib_name);
|
||||
path
|
||||
};
|
||||
// dlltool target architecture args from:
|
||||
// https://github.com/llvm/llvm-project-release-prs/blob/llvmorg-15.0.6/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp#L69
|
||||
let (dlltool_target_arch, dlltool_target_bitness) = match sess.target.arch.as_ref() {
|
||||
"x86_64" => ("i386:x86-64", "--64"),
|
||||
"x86" => ("i386", "--32"),
|
||||
"aarch64" => ("arm64", "--64"),
|
||||
"arm" => ("arm", "--32"),
|
||||
_ => panic!("unsupported arch {}", sess.target.arch),
|
||||
};
|
||||
let mut dlltool_cmd = std::process::Command::new(&dlltool);
|
||||
dlltool_cmd
|
||||
.arg("-d")
|
||||
.arg(def_file_path)
|
||||
.arg("-D")
|
||||
.arg(lib_name)
|
||||
.arg("-l")
|
||||
.arg(&output_path)
|
||||
.arg("-m")
|
||||
.arg(dlltool_target_arch)
|
||||
.arg("-f")
|
||||
.arg(dlltool_target_bitness)
|
||||
.arg("--no-leading-underscore")
|
||||
.arg("--temp-prefix")
|
||||
.arg(temp_prefix);
|
||||
|
||||
match dlltool_cmd.output() {
|
||||
Err(e) => {
|
||||
sess.dcx().emit_fatal(ErrorCallingDllTool {
|
||||
dlltool_path: dlltool.to_string_lossy(),
|
||||
error: e,
|
||||
});
|
||||
}
|
||||
// dlltool returns '0' on failure, so check for error output instead.
|
||||
Ok(output) if !output.stderr.is_empty() => {
|
||||
sess.dcx().emit_fatal(DlltoolFailImportLibrary {
|
||||
dlltool_path: dlltool.to_string_lossy(),
|
||||
dlltool_args: dlltool_cmd
|
||||
.get_args()
|
||||
.map(|arg| arg.to_string_lossy())
|
||||
.collect::<Vec<_>>()
|
||||
.join(" "),
|
||||
stdout: String::from_utf8_lossy(&output.stdout),
|
||||
stderr: String::from_utf8_lossy(&output.stderr),
|
||||
})
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn find_binutils_dlltool(sess: &Session) -> OsString {
|
||||
assert!(sess.target.options.is_like_windows && !sess.target.options.is_like_msvc);
|
||||
if let Some(dlltool_path) = &sess.opts.cg.dlltool {
|
||||
return dlltool_path.clone().into_os_string();
|
||||
}
|
||||
|
||||
let tool_name: OsString = if sess.host.options.is_like_windows {
|
||||
// If we're compiling on Windows, always use "dlltool.exe".
|
||||
"dlltool.exe"
|
||||
} else {
|
||||
// On other platforms, use the architecture-specific name.
|
||||
match sess.target.arch.as_ref() {
|
||||
"x86_64" => "x86_64-w64-mingw32-dlltool",
|
||||
"x86" => "i686-w64-mingw32-dlltool",
|
||||
"aarch64" => "aarch64-w64-mingw32-dlltool",
|
||||
|
||||
// For non-standard architectures (e.g., aarch32) fallback to "dlltool".
|
||||
_ => "dlltool",
|
||||
}
|
||||
}
|
||||
.into();
|
||||
|
||||
// NOTE: it's not clear how useful it is to explicitly search PATH.
|
||||
for dir in env::split_paths(&env::var_os("PATH").unwrap_or_default()) {
|
||||
let full_path = dir.join(&tool_name);
|
||||
if full_path.is_file() {
|
||||
return full_path.into_os_string();
|
||||
}
|
||||
}
|
||||
|
||||
// The user didn't specify the location of the dlltool binary, and we weren't able
|
||||
// to find the appropriate one on the PATH. Just return the name of the tool
|
||||
// and let the invocation fail with a hopefully useful error message.
|
||||
tool_name
|
||||
}
|
||||
|
||||
pub trait ArchiveBuilder {
|
||||
fn add_file(&mut self, path: &Path);
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,8 @@ use super::linker::{self, Linker};
|
|||
use super::metadata::{create_wrapper_file, MetadataPosition};
|
||||
use super::rpath::{self, RPathConfig};
|
||||
use crate::{
|
||||
errors, looks_like_rust_object_file, CodegenResults, CompiledModule, CrateInfo, NativeLib,
|
||||
common, errors, looks_like_rust_object_file, CodegenResults, CompiledModule, CrateInfo,
|
||||
NativeLib,
|
||||
};
|
||||
|
||||
pub fn ensure_removed(dcx: DiagCtxtHandle<'_>, path: &Path) {
|
||||
|
|
@ -390,17 +391,13 @@ fn link_rlib<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
for (raw_dylib_name, raw_dylib_imports) in
|
||||
collate_raw_dylibs(sess, codegen_results.crate_info.used_libraries.iter())?
|
||||
{
|
||||
let output_path = archive_builder_builder.create_dll_import_lib(
|
||||
sess,
|
||||
&raw_dylib_name,
|
||||
&raw_dylib_imports,
|
||||
tmpdir.as_ref(),
|
||||
true,
|
||||
);
|
||||
|
||||
for output_path in create_dll_import_libs(
|
||||
sess,
|
||||
archive_builder_builder,
|
||||
codegen_results.crate_info.used_libraries.iter(),
|
||||
tmpdir.as_ref(),
|
||||
true,
|
||||
)? {
|
||||
ab.add_archive(&output_path, Box::new(|_| false)).unwrap_or_else(|error| {
|
||||
sess.dcx().emit_fatal(errors::AddNativeLibrary { library_path: output_path, error });
|
||||
});
|
||||
|
|
@ -488,6 +485,47 @@ fn collate_raw_dylibs<'a>(
|
|||
.collect())
|
||||
}
|
||||
|
||||
fn create_dll_import_libs<'a>(
|
||||
sess: &Session,
|
||||
archive_builder_builder: &dyn ArchiveBuilderBuilder,
|
||||
used_libraries: impl IntoIterator<Item = &'a NativeLib>,
|
||||
tmpdir: &Path,
|
||||
is_direct_dependency: bool,
|
||||
) -> Result<Vec<PathBuf>, ErrorGuaranteed> {
|
||||
Ok(collate_raw_dylibs(sess, used_libraries)?
|
||||
.into_iter()
|
||||
.map(|(raw_dylib_name, raw_dylib_imports)| {
|
||||
let name_suffix = if is_direct_dependency { "_imports" } else { "_imports_indirect" };
|
||||
let output_path = tmpdir.join(format!("{raw_dylib_name}{name_suffix}.lib"));
|
||||
|
||||
let mingw_gnu_toolchain = common::is_mingw_gnu_toolchain(&sess.target);
|
||||
|
||||
let import_name_and_ordinal_vector: Vec<(String, Option<u16>)> = raw_dylib_imports
|
||||
.iter()
|
||||
.map(|import: &DllImport| {
|
||||
if sess.target.arch == "x86" {
|
||||
(
|
||||
common::i686_decorated_name(import, mingw_gnu_toolchain, false),
|
||||
import.ordinal(),
|
||||
)
|
||||
} else {
|
||||
(import.name.to_string(), import.ordinal())
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
archive_builder_builder.create_dll_import_lib(
|
||||
sess,
|
||||
&raw_dylib_name,
|
||||
import_name_and_ordinal_vector,
|
||||
&output_path,
|
||||
);
|
||||
|
||||
output_path
|
||||
})
|
||||
.collect())
|
||||
}
|
||||
|
||||
/// Create a static archive.
|
||||
///
|
||||
/// This is essentially the same thing as an rlib, but it also involves adding all of the upstream
|
||||
|
|
@ -2305,16 +2343,14 @@ fn linker_with_args(
|
|||
);
|
||||
|
||||
// Link with the import library generated for any raw-dylib functions.
|
||||
for (raw_dylib_name, raw_dylib_imports) in
|
||||
collate_raw_dylibs(sess, codegen_results.crate_info.used_libraries.iter())?
|
||||
{
|
||||
cmd.add_object(&archive_builder_builder.create_dll_import_lib(
|
||||
sess,
|
||||
&raw_dylib_name,
|
||||
&raw_dylib_imports,
|
||||
tmpdir,
|
||||
true,
|
||||
));
|
||||
for output_path in create_dll_import_libs(
|
||||
sess,
|
||||
archive_builder_builder,
|
||||
codegen_results.crate_info.used_libraries.iter(),
|
||||
tmpdir,
|
||||
true,
|
||||
)? {
|
||||
cmd.add_object(&output_path);
|
||||
}
|
||||
// As with add_upstream_native_libraries, we need to add the upstream raw-dylib symbols in case
|
||||
// they are used within inlined functions or instantiated generic functions. We do this *after*
|
||||
|
|
@ -2339,16 +2375,14 @@ fn linker_with_args(
|
|||
.flatten()
|
||||
.collect::<Vec<_>>();
|
||||
native_libraries_from_nonstatics.sort_unstable_by(|a, b| a.name.as_str().cmp(b.name.as_str()));
|
||||
for (raw_dylib_name, raw_dylib_imports) in
|
||||
collate_raw_dylibs(sess, native_libraries_from_nonstatics)?
|
||||
{
|
||||
cmd.add_object(&archive_builder_builder.create_dll_import_lib(
|
||||
sess,
|
||||
&raw_dylib_name,
|
||||
&raw_dylib_imports,
|
||||
tmpdir,
|
||||
false,
|
||||
));
|
||||
for output_path in create_dll_import_libs(
|
||||
sess,
|
||||
archive_builder_builder,
|
||||
native_libraries_from_nonstatics,
|
||||
tmpdir,
|
||||
false,
|
||||
)? {
|
||||
cmd.add_object(&output_path);
|
||||
}
|
||||
|
||||
// Library linking above uses some global state for things like `-Bstatic`/`-Bdynamic` to make
|
||||
|
|
|
|||
|
|
@ -4,7 +4,9 @@ use rustc_hir::LangItem;
|
|||
use rustc_middle::ty::layout::TyAndLayout;
|
||||
use rustc_middle::ty::{self, Instance, TyCtxt};
|
||||
use rustc_middle::{bug, mir, span_bug};
|
||||
use rustc_session::cstore::{DllCallingConvention, DllImport, PeImportNameType};
|
||||
use rustc_span::Span;
|
||||
use rustc_target::spec::Target;
|
||||
|
||||
use crate::traits::*;
|
||||
|
||||
|
|
@ -176,3 +178,66 @@ pub fn asm_const_to_str<'tcx>(
|
|||
_ => span_bug!(sp, "asm const has bad type {}", ty_and_layout.ty),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_mingw_gnu_toolchain(target: &Target) -> bool {
|
||||
target.vendor == "pc" && target.os == "windows" && target.env == "gnu" && target.abi.is_empty()
|
||||
}
|
||||
|
||||
pub fn i686_decorated_name(
|
||||
dll_import: &DllImport,
|
||||
mingw: bool,
|
||||
disable_name_mangling: bool,
|
||||
) -> String {
|
||||
let name = dll_import.name.as_str();
|
||||
|
||||
let (add_prefix, add_suffix) = match dll_import.import_name_type {
|
||||
Some(PeImportNameType::NoPrefix) => (false, true),
|
||||
Some(PeImportNameType::Undecorated) => (false, false),
|
||||
_ => (true, true),
|
||||
};
|
||||
|
||||
// Worst case: +1 for disable name mangling, +1 for prefix, +4 for suffix (@@__).
|
||||
let mut decorated_name = String::with_capacity(name.len() + 6);
|
||||
|
||||
if disable_name_mangling {
|
||||
// LLVM uses a binary 1 ('\x01') prefix to a name to indicate that mangling needs to be disabled.
|
||||
decorated_name.push('\x01');
|
||||
}
|
||||
|
||||
let prefix = if add_prefix && dll_import.is_fn {
|
||||
match dll_import.calling_convention {
|
||||
DllCallingConvention::C | DllCallingConvention::Vectorcall(_) => None,
|
||||
DllCallingConvention::Stdcall(_) => (!mingw
|
||||
|| dll_import.import_name_type == Some(PeImportNameType::Decorated))
|
||||
.then_some('_'),
|
||||
DllCallingConvention::Fastcall(_) => Some('@'),
|
||||
}
|
||||
} else if !dll_import.is_fn && !mingw {
|
||||
// For static variables, prefix with '_' on MSVC.
|
||||
Some('_')
|
||||
} else {
|
||||
None
|
||||
};
|
||||
if let Some(prefix) = prefix {
|
||||
decorated_name.push(prefix);
|
||||
}
|
||||
|
||||
decorated_name.push_str(name);
|
||||
|
||||
if add_suffix && dll_import.is_fn {
|
||||
use std::fmt::Write;
|
||||
|
||||
match dll_import.calling_convention {
|
||||
DllCallingConvention::C => {}
|
||||
DllCallingConvention::Stdcall(arg_list_size)
|
||||
| DllCallingConvention::Fastcall(arg_list_size) => {
|
||||
write!(&mut decorated_name, "@{arg_list_size}").unwrap();
|
||||
}
|
||||
DllCallingConvention::Vectorcall(arg_list_size) => {
|
||||
write!(&mut decorated_name, "@@{arg_list_size}").unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
decorated_name
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1026,6 +1026,28 @@ pub struct FailedToGetLayout<'tcx> {
|
|||
pub err: LayoutError<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa_dlltool_fail_import_library)]
|
||||
pub(crate) struct DlltoolFailImportLibrary<'a> {
|
||||
pub dlltool_path: Cow<'a, str>,
|
||||
pub dlltool_args: String,
|
||||
pub stdout: Cow<'a, str>,
|
||||
pub stderr: Cow<'a, str>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa_error_writing_def_file)]
|
||||
pub(crate) struct ErrorWritingDEFFile {
|
||||
pub error: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa_error_calling_dlltool)]
|
||||
pub(crate) struct ErrorCallingDllTool<'a> {
|
||||
pub dlltool_path: Cow<'a, str>,
|
||||
pub error: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa_error_creating_remark_dir)]
|
||||
pub struct ErrorCreatingRemarkDir {
|
||||
|
|
|
|||
|
|
@ -253,32 +253,6 @@ pub fn lower_generic_args<'tcx: 'a, 'a>(
|
|||
match (args_iter.peek(), params.peek()) {
|
||||
(Some(&arg), Some(¶m)) => {
|
||||
match (arg, ¶m.kind, arg_count.explicit_late_bound) {
|
||||
(
|
||||
GenericArg::Const(hir::ConstArg {
|
||||
is_desugared_from_effects: true,
|
||||
..
|
||||
}),
|
||||
GenericParamDefKind::Const { is_host_effect: false, .. }
|
||||
| GenericParamDefKind::Type { .. }
|
||||
| GenericParamDefKind::Lifetime,
|
||||
_,
|
||||
) => {
|
||||
// FIXME(effects): this should be removed
|
||||
// SPECIAL CASE FOR DESUGARED EFFECT PARAMS
|
||||
// This comes from the following example:
|
||||
//
|
||||
// ```
|
||||
// #[const_trait]
|
||||
// pub trait PartialEq<Rhs: ?Sized = Self> {}
|
||||
// impl const PartialEq for () {}
|
||||
// ```
|
||||
//
|
||||
// Since this is a const impl, we need to insert a host arg at the end of
|
||||
// `PartialEq`'s generics, but this errors since `Rhs` isn't specified.
|
||||
// To work around this, we infer all arguments until we reach the host param.
|
||||
args.push(ctx.inferred_kind(&args, param, infer_args));
|
||||
params.next();
|
||||
}
|
||||
(GenericArg::Lifetime(_), GenericParamDefKind::Lifetime, _)
|
||||
| (
|
||||
GenericArg::Type(_) | GenericArg::Infer(_),
|
||||
|
|
|
|||
|
|
@ -388,39 +388,67 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
trait_impls.non_blanket_impls().values().flatten().count();
|
||||
// If there is only one implementation of the trait, suggest using it.
|
||||
// Otherwise, use a placeholder comment for the implementation.
|
||||
let (message, self_type) = if non_blanket_impl_count == 1 {
|
||||
let (message, self_types) = if non_blanket_impl_count == 1 {
|
||||
(
|
||||
"use the fully-qualified path to the only available \
|
||||
implementation",
|
||||
format!(
|
||||
vec![format!(
|
||||
"{}",
|
||||
self.tcx.type_of(impl_def_id).instantiate_identity()
|
||||
),
|
||||
)],
|
||||
)
|
||||
} else if non_blanket_impl_count < 20 {
|
||||
(
|
||||
"use a fully-qualified path to one of the available \
|
||||
implementations",
|
||||
trait_impls
|
||||
.non_blanket_impls()
|
||||
.values()
|
||||
.flatten()
|
||||
.map(|id| {
|
||||
format!(
|
||||
"{}",
|
||||
self.tcx.type_of(id).instantiate_identity()
|
||||
)
|
||||
})
|
||||
.collect::<Vec<String>>(),
|
||||
)
|
||||
} else {
|
||||
(
|
||||
"use a fully-qualified path to a specific available \
|
||||
implementation",
|
||||
"/* self type */".to_string(),
|
||||
vec!["/* self type */".to_string()],
|
||||
)
|
||||
};
|
||||
let mut suggestions =
|
||||
vec![(path.span.shrink_to_lo(), format!("<{self_type} as "))];
|
||||
if let Some(generic_arg) = trait_path_segment.args {
|
||||
let between_span =
|
||||
trait_path_segment.ident.span.between(generic_arg.span_ext);
|
||||
// get rid of :: between Trait and <type>
|
||||
// must be '::' between them, otherwise the parser won't accept the code
|
||||
suggestions.push((between_span, "".to_string()));
|
||||
suggestions
|
||||
.push((generic_arg.span_ext.shrink_to_hi(), ">".to_string()));
|
||||
} else {
|
||||
suggestions.push((
|
||||
trait_path_segment.ident.span.shrink_to_hi(),
|
||||
">".to_string(),
|
||||
));
|
||||
}
|
||||
err.multipart_suggestion(
|
||||
let suggestions: Vec<_> = self_types
|
||||
.into_iter()
|
||||
.map(|self_type| {
|
||||
let mut suggestions = vec![(
|
||||
path.span.shrink_to_lo(),
|
||||
format!("<{self_type} as "),
|
||||
)];
|
||||
if let Some(generic_arg) = trait_path_segment.args {
|
||||
let between_span = trait_path_segment
|
||||
.ident
|
||||
.span
|
||||
.between(generic_arg.span_ext);
|
||||
// get rid of :: between Trait and <type>
|
||||
// must be '::' between them, otherwise the parser won't accept the code
|
||||
suggestions.push((between_span, "".to_string()));
|
||||
suggestions.push((
|
||||
generic_arg.span_ext.shrink_to_hi(),
|
||||
">".to_string(),
|
||||
));
|
||||
} else {
|
||||
suggestions.push((
|
||||
trait_path_segment.ident.span.shrink_to_hi(),
|
||||
">".to_string(),
|
||||
));
|
||||
}
|
||||
suggestions
|
||||
})
|
||||
.collect();
|
||||
err.multipart_suggestions(
|
||||
message,
|
||||
suggestions,
|
||||
Applicability::MaybeIncorrect,
|
||||
|
|
|
|||
|
|
@ -520,6 +520,14 @@ impl Step for Miri {
|
|||
builder.ensure(compile::Std::new(target_compiler, host));
|
||||
let host_sysroot = builder.sysroot(target_compiler);
|
||||
|
||||
// Miri has its own "target dir" for ui test dependencies. Make sure it gets cleared
|
||||
// properly when rustc changes. Similar to `Builder::cargo`, we skip this in dry runs to
|
||||
// make sure the relevant compiler has been set up properly.
|
||||
if !builder.config.dry_run() {
|
||||
let ui_test_dep_dir = builder.stage_out(host_compiler, Mode::ToolStd).join("miri_ui");
|
||||
builder.clear_if_dirty(&ui_test_dep_dir, &builder.rustc(host_compiler));
|
||||
}
|
||||
|
||||
// Run `cargo test`.
|
||||
// This is with the Miri crate, so it uses the host compiler.
|
||||
let mut cargo = tool::prepare_tool_cargo(
|
||||
|
|
|
|||
|
|
@ -20,6 +20,12 @@ Target triplets available:
|
|||
|
||||
## Requirements
|
||||
|
||||
### OS version
|
||||
|
||||
The minimum supported version is VxWorks 7.
|
||||
|
||||
## Building
|
||||
|
||||
Rust for each target can be cross-compiled with its specific target vsb configuration. Std support is added but not yet fully tested.
|
||||
|
||||
## Building the target
|
||||
|
|
|
|||
|
|
@ -17,12 +17,10 @@ run-make/min-global-align/Makefile
|
|||
run-make/native-link-modifier-bundle/Makefile
|
||||
run-make/no-alloc-shim/Makefile
|
||||
run-make/pdb-buildinfo-cl-cmd/Makefile
|
||||
run-make/pgo-gen-lto/Makefile
|
||||
run-make/pgo-indirect-call-promotion/Makefile
|
||||
run-make/remap-path-prefix-dwarf/Makefile
|
||||
run-make/reproducible-build/Makefile
|
||||
run-make/rlib-format-packed-bundled-libs/Makefile
|
||||
run-make/simd-ffi/Makefile
|
||||
run-make/split-debuginfo/Makefile
|
||||
run-make/staticlib-dylib-linkage/Makefile
|
||||
run-make/symbol-mangling-hashed/Makefile
|
||||
|
|
|
|||
|
|
@ -1,11 +0,0 @@
|
|||
# needs-profiler-support
|
||||
# ignore-cross-compile
|
||||
|
||||
include ../tools.mk
|
||||
|
||||
COMPILE_FLAGS=-Copt-level=3 -Clto=fat -Cprofile-generate="$(TMPDIR)"
|
||||
|
||||
all:
|
||||
$(RUSTC) $(COMPILE_FLAGS) test.rs
|
||||
$(call RUN,test) || exit 1
|
||||
[ -e "$(TMPDIR)"/default_*.profraw ] || (echo "No .profraw file"; exit 1)
|
||||
22
tests/run-make/pgo-gen-lto/rmake.rs
Normal file
22
tests/run-make/pgo-gen-lto/rmake.rs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
// A simple smoke test: when rustc compiles with profiling enabled, a profraw file
|
||||
// should be generated.
|
||||
// See https://github.com/rust-lang/rust/pull/48346
|
||||
|
||||
//@ needs-profiler-support
|
||||
// Reason: this exercises LTO profiling
|
||||
//@ ignore-cross-compile
|
||||
// Reason: the compiled binary is executed
|
||||
|
||||
use run_make_support::{cwd, has_extension, has_prefix, run, rustc, shallow_find_files};
|
||||
|
||||
fn main() {
|
||||
rustc().opt_level("3").arg("-Clto=fat").profile_generate(cwd()).input("test.rs").run();
|
||||
run("test");
|
||||
assert_eq!(
|
||||
shallow_find_files(cwd(), |path| {
|
||||
has_prefix(path, "default_") && has_extension(path, "profraw")
|
||||
})
|
||||
.len(),
|
||||
1
|
||||
);
|
||||
}
|
||||
|
|
@ -2,15 +2,17 @@
|
|||
// see https://github.com/rust-lang/compiler-team/issues/510 for more info
|
||||
|
||||
//@ needs-rust-lld
|
||||
//@ ignore-msvc
|
||||
//@ ignore-s390x lld does not yet support s390x as target
|
||||
|
||||
use std::process::Output;
|
||||
|
||||
use run_make_support::regex::Regex;
|
||||
use run_make_support::rustc;
|
||||
use run_make_support::{is_msvc, rustc};
|
||||
|
||||
fn main() {
|
||||
// lld-link is used if msvc, otherwise a gnu-compatible lld is used.
|
||||
let linker_version_flag = if is_msvc() { "--version" } else { "-Wl,-v" };
|
||||
|
||||
// Opt-in to lld and the self-contained linker, to link with rust-lld. We'll check that by
|
||||
// asking the linker to display its version number with a link-arg.
|
||||
let output = rustc()
|
||||
|
|
@ -18,7 +20,7 @@ fn main() {
|
|||
.arg("-Zlinker-features=+lld")
|
||||
.arg("-Clink-self-contained=+linker")
|
||||
.arg("-Zunstable-options")
|
||||
.link_arg("-Wl,-v")
|
||||
.link_arg(linker_version_flag)
|
||||
.input("main.rs")
|
||||
.run();
|
||||
assert!(
|
||||
|
|
@ -27,10 +29,10 @@ fn main() {
|
|||
output.stderr_utf8()
|
||||
);
|
||||
|
||||
// It should not be used when we explictly opt-out of lld.
|
||||
// It should not be used when we explicitly opt-out of lld.
|
||||
let output = rustc()
|
||||
.env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info")
|
||||
.link_arg("-Wl,-v")
|
||||
.link_arg(linker_version_flag)
|
||||
.arg("-Zlinker-features=-lld")
|
||||
.input("main.rs")
|
||||
.run();
|
||||
|
|
@ -44,7 +46,7 @@ fn main() {
|
|||
// times to rustc.
|
||||
let output = rustc()
|
||||
.env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info")
|
||||
.link_arg("-Wl,-v")
|
||||
.link_arg(linker_version_flag)
|
||||
.arg("-Clink-self-contained=+linker")
|
||||
.arg("-Zunstable-options")
|
||||
.arg("-Zlinker-features=-lld")
|
||||
|
|
|
|||
|
|
@ -1,47 +0,0 @@
|
|||
include ../tools.mk
|
||||
|
||||
TARGETS =
|
||||
ifeq ($(filter arm,$(LLVM_COMPONENTS)),arm)
|
||||
# construct a fairly exhaustive list of platforms that we
|
||||
# support. These ones don't follow a pattern
|
||||
TARGETS += arm-linux-androideabi arm-unknown-linux-gnueabihf arm-unknown-linux-gnueabi
|
||||
endif
|
||||
|
||||
ifeq ($(filter x86,$(LLVM_COMPONENTS)),x86)
|
||||
X86_ARCHS = i686 x86_64
|
||||
else
|
||||
X86_ARCHS =
|
||||
endif
|
||||
|
||||
# these ones do, each OS lists the architectures it supports
|
||||
LINUX=$(filter aarch64 mips,$(LLVM_COMPONENTS)) $(X86_ARCHS)
|
||||
ifeq ($(filter mips,$(LLVM_COMPONENTS)),mips)
|
||||
LINUX += mipsel
|
||||
endif
|
||||
|
||||
WINDOWS=$(X86_ARCHS)
|
||||
# fails with: failed to get iphonesimulator SDK path: no such file or directory
|
||||
#IOS=i386 aarch64 armv7
|
||||
DARWIN=$(X86_ARCHS)
|
||||
|
||||
$(foreach arch,$(LINUX),$(eval TARGETS += $(arch)-unknown-linux-gnu))
|
||||
$(foreach arch,$(WINDOWS),$(eval TARGETS += $(arch)-pc-windows-gnu))
|
||||
#$(foreach arch,$(IOS),$(eval TARGETS += $(arch)-apple-ios))
|
||||
$(foreach arch,$(DARWIN),$(eval TARGETS += $(arch)-apple-darwin))
|
||||
|
||||
all: $(TARGETS)
|
||||
|
||||
define MK_TARGETS
|
||||
# compile the rust file to the given target, but only to asm and IR
|
||||
# form, to avoid having to have an appropriate linker.
|
||||
#
|
||||
# we need some features because the integer SIMD instructions are not
|
||||
# enabled by-default for i686 and ARM; these features will be invalid
|
||||
# on some platforms, but LLVM just prints a warning so that's fine for
|
||||
# now.
|
||||
$(1): simd.rs
|
||||
$$(RUSTC) --target=$(1) --emit=llvm-ir,asm simd.rs \
|
||||
-C target-feature='+neon,+sse2' -C extra-filename=-$(1)
|
||||
endef
|
||||
|
||||
$(foreach targetxxx,$(TARGETS),$(eval $(call MK_TARGETS,$(targetxxx))))
|
||||
63
tests/run-make/simd-ffi/rmake.rs
Normal file
63
tests/run-make/simd-ffi/rmake.rs
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
// Using SIMD types in a program with foreign-function interfaces used to result in an ICE
|
||||
// (internal compiler error). Since this was fixed in #21233, it should be checked that
|
||||
// compilation of SIMD and FFI together should be successful on all the most common
|
||||
// architectures.
|
||||
// Note that this test does not check linking or binary execution.
|
||||
// See https://github.com/rust-lang/rust/pull/21233
|
||||
|
||||
use run_make_support::{llvm_components_contain, rustc};
|
||||
|
||||
fn main() {
|
||||
let mut targets = Vec::new();
|
||||
// arm-specific targets.
|
||||
if llvm_components_contain("arm") {
|
||||
targets.append(&mut vec![
|
||||
"arm-linux-androideabi".to_owned(),
|
||||
"arm-unknown-linux-gnueabihf".to_owned(),
|
||||
"arm-unknown-linux-gnueabi".to_owned(),
|
||||
]);
|
||||
}
|
||||
let mut x86_archs = Vec::new();
|
||||
if llvm_components_contain("x86") {
|
||||
x86_archs.append(&mut vec!["i686", "x86_64"]);
|
||||
}
|
||||
// Linux has all x86 targets, plus aarch64 and mips.
|
||||
let mut extra_targets = x86_archs.clone();
|
||||
if llvm_components_contain("aarch64") {
|
||||
extra_targets.push("aarch64");
|
||||
}
|
||||
if llvm_components_contain("mips") {
|
||||
extra_targets.append(&mut vec!["mips", "mipsel"]);
|
||||
}
|
||||
|
||||
for target in extra_targets {
|
||||
let linux = format!("{target}-unknown-linux-gnu");
|
||||
targets.push(linux);
|
||||
}
|
||||
|
||||
// Windows and Darwin (OSX) only receive x86 targets.
|
||||
let extra_targets = x86_archs.clone();
|
||||
for target in extra_targets {
|
||||
let windows = format!("{target}-pc-windows-gnu");
|
||||
let darwin = format!("{target}-apple-darwin");
|
||||
targets.push(windows);
|
||||
targets.push(darwin);
|
||||
}
|
||||
|
||||
for target in targets {
|
||||
// compile the rust file to the given target, but only to asm and IR
|
||||
// form, to avoid having to have an appropriate linker.
|
||||
//
|
||||
// we need some features because the integer SIMD instructions are not
|
||||
// enabled by-default for i686 and ARM; these features will be invalid
|
||||
// on some platforms, but LLVM just prints a warning so that's fine for
|
||||
// now.
|
||||
rustc()
|
||||
.target(&target)
|
||||
.emit("llvm-ir,asm")
|
||||
.input("simd.rs")
|
||||
.arg("-Ctarget-feature=+neon,+sse")
|
||||
.arg(&format!("-Cextra-filename=-{target}"))
|
||||
.run();
|
||||
}
|
||||
}
|
||||
|
|
@ -7,10 +7,12 @@ LL | fn create() -> u32;
|
|||
LL | let cont: u32 = Coroutine::create();
|
||||
| ^^^^^^^^^^^^^^^^^^^ cannot call associated function of trait
|
||||
|
|
||||
help: use a fully-qualified path to a specific available implementation
|
||||
help: use a fully-qualified path to one of the available implementations
|
||||
|
|
||||
LL | let cont: u32 = </* self type */ as Coroutine>::create();
|
||||
| +++++++++++++++++++ +
|
||||
LL | let cont: u32 = <Impl as Coroutine>::create();
|
||||
| ++++++++ +
|
||||
LL | let cont: u32 = <AnotherImpl as Coroutine>::create();
|
||||
| +++++++++++++++ +
|
||||
|
||||
error[E0283]: type annotations needed
|
||||
--> $DIR/E0283.rs:35:24
|
||||
|
|
|
|||
|
|
@ -63,10 +63,12 @@ LL | fn my_fn();
|
|||
LL | MyTrait2::my_fn();
|
||||
| ^^^^^^^^^^^^^^^^^ cannot call associated function of trait
|
||||
|
|
||||
help: use a fully-qualified path to a specific available implementation
|
||||
help: use a fully-qualified path to one of the available implementations
|
||||
|
|
||||
LL | </* self type */ as MyTrait2>::my_fn();
|
||||
| +++++++++++++++++++ +
|
||||
LL | <Impl1 as MyTrait2>::my_fn();
|
||||
| +++++++++ +
|
||||
LL | <Impl2 as MyTrait2>::my_fn();
|
||||
| +++++++++ +
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
|
|
|
|||
29
tests/ui/impl-trait/in-trait/cannot-capture-intersection.rs
Normal file
29
tests/ui/impl-trait/in-trait/cannot-capture-intersection.rs
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#![feature(precise_capturing)]
|
||||
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
|
||||
trait MyTrait {
|
||||
fn foo<'a, 'b>(&'a self, x: &'b i32) -> impl Future<Output = i32>;
|
||||
}
|
||||
|
||||
trait ErasedMyTrait {
|
||||
fn foo<'life0, 'life1, 'dynosaur>(&'life0 self, x: &'life1 i32)
|
||||
-> Pin<Box<dyn Future<Output = i32> + 'dynosaur>>
|
||||
where
|
||||
'life0: 'dynosaur,
|
||||
'life1: 'dynosaur;
|
||||
}
|
||||
|
||||
struct DynMyTrait<T: ErasedMyTrait> {
|
||||
ptr: T,
|
||||
}
|
||||
|
||||
impl<T: ErasedMyTrait> MyTrait for DynMyTrait<T> {
|
||||
fn foo<'a, 'b>(&'a self, x: &'b i32) -> impl Future<Output = i32> {
|
||||
self.ptr.foo(x)
|
||||
//~^ ERROR hidden type for `impl Future<Output = i32>` captures lifetime that does not appear in bounds
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
error[E0700]: hidden type for `impl Future<Output = i32>` captures lifetime that does not appear in bounds
|
||||
--> $DIR/cannot-capture-intersection.rs:24:9
|
||||
|
|
||||
LL | fn foo<'a, 'b>(&'a self, x: &'b i32) -> impl Future<Output = i32> {
|
||||
| ------------------------- opaque type defined here
|
||||
LL | self.ptr.foo(x)
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: hidden type `Pin<Box<dyn Future<Output = i32>>>` captures lifetime `'_`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0700`.
|
||||
|
|
@ -2,17 +2,12 @@ error[E0700]: hidden type for `impl Trait<'d, 'e>` captures lifetime that does n
|
|||
--> $DIR/ordinary-bounds-unrelated.rs:28:33
|
||||
|
|
||||
LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e>
|
||||
| -- ------------------ opaque type defined here
|
||||
| |
|
||||
| hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here
|
||||
| ------------------ opaque type defined here
|
||||
...
|
||||
LL | if condition() { a } else { b }
|
||||
| ^
|
||||
|
|
||||
help: to declare that `impl Trait<'d, 'e>` captures `'b`, you can add an explicit `'b` lifetime bound
|
||||
|
|
||||
LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e> + 'b
|
||||
| ++++
|
||||
= note: hidden type `Ordinary<'_>` captures lifetime `'_`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -2,17 +2,12 @@ error[E0700]: hidden type for `impl Trait<'a, 'b>` captures lifetime that does n
|
|||
--> $DIR/ordinary-bounds-unsuited.rs:31:33
|
||||
|
|
||||
LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b>
|
||||
| -- ------------------ opaque type defined here
|
||||
| |
|
||||
| hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here
|
||||
| ------------------ opaque type defined here
|
||||
...
|
||||
LL | if condition() { a } else { b }
|
||||
| ^
|
||||
|
|
||||
help: to declare that `impl Trait<'a, 'b>` captures `'b`, you can add an explicit `'b` lifetime bound
|
||||
|
|
||||
LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> + 'b
|
||||
| ++++
|
||||
= note: hidden type `Ordinary<'_>` captures lifetime `'_`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -2,18 +2,13 @@ error[E0700]: hidden type for `impl Iterator<Item = i32>` captures lifetime that
|
|||
--> $DIR/explicit-lifetime-suggestion-in-proper-span-issue-121267.rs:7:5
|
||||
|
|
||||
LL | fn bar(src: &crate::Foo) -> impl Iterator<Item = i32> {
|
||||
| ---------- ------------------------- opaque type defined here
|
||||
| |
|
||||
| hidden type `FilterMap<std::slice::Iter<'static, i32>, {closure@$DIR/explicit-lifetime-suggestion-in-proper-span-issue-121267.rs:9:21: 9:24}>` captures the anonymous lifetime defined here
|
||||
| ------------------------- opaque type defined here
|
||||
LL | / [0].into_iter()
|
||||
LL | |
|
||||
LL | | .filter_map(|_| foo(src))
|
||||
| |_________________________________^
|
||||
|
|
||||
help: to declare that `impl Iterator<Item = i32>` captures `'_`, you can introduce a named lifetime parameter `'a`
|
||||
|
|
||||
LL | fn bar<'a>(src: &'a crate::Foo<'a>) -> impl Iterator<Item = i32> + 'a {
|
||||
| ++++ ++ ++++ ++++
|
||||
= note: hidden type `FilterMap<std::slice::Iter<'static, i32>, {closure@$DIR/explicit-lifetime-suggestion-in-proper-span-issue-121267.rs:9:21: 9:24}>` captures lifetime `'_`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue