Rollup merge of #128206 - bjorn3:import_lib_writing_refactor, r=jieyouxu
Make create_dll_import_lib easier to implement This will make it easier to implement raw-dylib support in cg_clif and cg_gcc. This PR doesn't yet include an create_dll_import_lib implementation for cg_clif as I need to correctly implement dllimport in cg_clif first before raw-dylib can work at all with cg_clif. Required for https://github.com/rust-lang/rustc_codegen_cranelift/issues/1345
This commit is contained in:
commit
355eb9c79f
15
Cargo.lock
15
Cargo.lock
@ -205,11 +205,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ar_archive_writer"
|
name = "ar_archive_writer"
|
||||||
version = "0.3.0"
|
version = "0.3.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f8412a2d690663356cba5a2532f3ed55d1e8090743bc6695b88403b27df67733"
|
checksum = "3f2bcb7cf51decfbbfc7ef476e28b0775b13e5eb1190f8b7df145cd53d4f4374"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"object 0.35.0",
|
"object 0.36.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -2454,15 +2454,6 @@ dependencies = [
|
|||||||
"ruzstd 0.5.0",
|
"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]]
|
[[package]]
|
||||||
name = "object"
|
name = "object"
|
||||||
version = "0.36.2"
|
version = "0.36.2"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use std::path::{Path, PathBuf};
|
use std::path::Path;
|
||||||
|
|
||||||
use rustc_codegen_ssa::back::archive::{
|
use rustc_codegen_ssa::back::archive::{
|
||||||
ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder, DEFAULT_OBJECT_READER,
|
ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder, DEFAULT_OBJECT_READER,
|
||||||
@ -16,10 +16,9 @@ fn create_dll_import_lib(
|
|||||||
&self,
|
&self,
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
_lib_name: &str,
|
_lib_name: &str,
|
||||||
_dll_imports: &[rustc_session::cstore::DllImport],
|
_import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
|
||||||
_tmpdir: &Path,
|
_output_path: &Path,
|
||||||
_is_direct_dependency: bool,
|
) {
|
||||||
) -> PathBuf {
|
|
||||||
sess.dcx().fatal("raw-dylib is not yet supported by rustc_codegen_cranelift");
|
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::{
|
use rustc_codegen_ssa::back::archive::{
|
||||||
ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder, DEFAULT_OBJECT_READER,
|
ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder, DEFAULT_OBJECT_READER,
|
||||||
};
|
};
|
||||||
use rustc_session::cstore::DllImport;
|
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
|
|
||||||
pub(crate) struct ArArchiveBuilderBuilder;
|
pub(crate) struct ArArchiveBuilderBuilder;
|
||||||
@ -17,10 +16,9 @@ fn create_dll_import_lib(
|
|||||||
&self,
|
&self,
|
||||||
_sess: &Session,
|
_sess: &Session,
|
||||||
_lib_name: &str,
|
_lib_name: &str,
|
||||||
_dll_imports: &[DllImport],
|
_import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
|
||||||
_tmpdir: &Path,
|
_output_path: &Path,
|
||||||
_is_direct_dependency: bool,
|
) {
|
||||||
) -> PathBuf {
|
|
||||||
unimplemented!("creating dll imports is not yet supported");
|
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_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 =
|
codegen_llvm_dynamic_linking_with_lto =
|
||||||
cannot prefer dynamic linking when performing LTO
|
cannot prefer dynamic linking when performing LTO
|
||||||
.note = only 'staticlib', 'bin', and 'cdylib' outputs are supported with 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 =
|
codegen_llvm_error_creating_import_library =
|
||||||
Error creating import library for {$lib_name}: {$error}
|
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_fixed_x18_invalid_arch = the `-Zfixed-x18` flag is not supported on the `{$arch}` architecture
|
||||||
|
|
||||||
codegen_llvm_from_llvm_diag = {$message}
|
codegen_llvm_from_llvm_diag = {$message}
|
||||||
|
@ -1,21 +1,19 @@
|
|||||||
//! A helper class for dealing with static archives
|
//! 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::path::{Path, PathBuf};
|
||||||
use std::{env, io, mem, ptr, str};
|
use std::{io, mem, ptr, str};
|
||||||
|
|
||||||
use rustc_codegen_ssa::back::archive::{
|
use rustc_codegen_ssa::back::archive::{
|
||||||
try_extract_macho_fat_archive, ArArchiveBuilder, ArchiveBuildFailure, ArchiveBuilder,
|
create_mingw_dll_import_lib, try_extract_macho_fat_archive, ArArchiveBuilder,
|
||||||
ArchiveBuilderBuilder, ObjectReader, UnknownArchiveKind, DEFAULT_OBJECT_READER,
|
ArchiveBuildFailure, ArchiveBuilder, ArchiveBuilderBuilder, ObjectReader, UnknownArchiveKind,
|
||||||
|
DEFAULT_OBJECT_READER,
|
||||||
};
|
};
|
||||||
use rustc_session::cstore::DllImport;
|
use rustc_codegen_ssa::common;
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use tracing::trace;
|
use tracing::trace;
|
||||||
|
|
||||||
use crate::common;
|
use crate::errors::ErrorCreatingImportLibrary;
|
||||||
use crate::errors::{
|
|
||||||
DlltoolFailImportLibrary, ErrorCallingDllTool, ErrorCreatingImportLibrary, ErrorWritingDEFFile,
|
|
||||||
};
|
|
||||||
use crate::llvm::archive_ro::{ArchiveRO, Child};
|
use crate::llvm::archive_ro::{ArchiveRO, Child};
|
||||||
use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport};
|
use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport};
|
||||||
|
|
||||||
@ -121,116 +119,21 @@ fn create_dll_import_lib(
|
|||||||
&self,
|
&self,
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
lib_name: &str,
|
lib_name: &str,
|
||||||
dll_imports: &[DllImport],
|
import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
|
||||||
tmpdir: &Path,
|
output_path: &Path,
|
||||||
is_direct_dependency: bool,
|
) {
|
||||||
) -> PathBuf {
|
if common::is_mingw_gnu_toolchain(&sess.target) {
|
||||||
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 {
|
|
||||||
// The binutils linker used on -windows-gnu targets cannot read the import
|
// The binutils linker used on -windows-gnu targets cannot read the import
|
||||||
// libraries generated by LLVM: in our attempts, the linker produced an .EXE
|
// 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
|
// 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.
|
||||||
let def_file_path = tmpdir.join(format!("{lib_name}{name_suffix}.def"));
|
create_mingw_dll_import_lib(
|
||||||
|
sess,
|
||||||
let def_file_content = format!(
|
lib_name,
|
||||||
"EXPORTS\n{}",
|
import_name_and_ordinal_vector,
|
||||||
import_name_and_ordinal_vector
|
output_path,
|
||||||
.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),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// we've checked for \0 characters in the library name already
|
// we've checked for \0 characters in the library name already
|
||||||
let dll_name_z = CString::new(lib_name).unwrap();
|
let dll_name_z = CString::new(lib_name).unwrap();
|
||||||
@ -242,9 +145,9 @@ fn create_dll_import_lib(
|
|||||||
trace!(" output_path {}", output_path.display());
|
trace!(" output_path {}", output_path.display());
|
||||||
trace!(
|
trace!(
|
||||||
" import names: {}",
|
" import names: {}",
|
||||||
dll_imports
|
import_name_and_ordinal_vector
|
||||||
.iter()
|
.iter()
|
||||||
.map(|import| import.name.to_string())
|
.map(|(name, _ordinal)| name.clone())
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join(", "),
|
.join(", "),
|
||||||
);
|
);
|
||||||
@ -281,9 +184,7 @@ fn create_dll_import_lib(
|
|||||||
error: llvm::last_error().unwrap_or("unknown LLVM error".to_string()),
|
error: llvm::last_error().unwrap_or("unknown LLVM error".to_string()),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
output_path
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -457,39 +358,3 @@ fn build_with_llvm(&mut self, output: &Path) -> io::Result<bool> {
|
|||||||
fn string_to_io_error(s: String) -> io::Error {
|
fn string_to_io_error(s: String) -> io::Error {
|
||||||
io::Error::new(io::ErrorKind::Other, format!("bad archive: {s}"))
|
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
|
//! and methods are represented as just a fn ptr and not a full
|
||||||
//! closure.
|
//! closure.
|
||||||
|
|
||||||
|
use rustc_codegen_ssa::common;
|
||||||
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
|
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
|
||||||
use rustc_middle::ty::{self, Instance, TypeVisitableExt};
|
use rustc_middle::ty::{self, Instance, TypeVisitableExt};
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
use crate::context::CodegenCx;
|
use crate::context::CodegenCx;
|
||||||
use crate::value::Value;
|
use crate::value::Value;
|
||||||
use crate::{attributes, common, llvm};
|
use crate::{attributes, llvm};
|
||||||
|
|
||||||
/// Codegens a reference to a fn/method item, monomorphizing and
|
/// Codegens a reference to a fn/method item, monomorphizing and
|
||||||
/// inlining as it goes.
|
/// inlining as it goes.
|
||||||
@ -46,7 +47,7 @@ pub fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) ->
|
|||||||
} else {
|
} else {
|
||||||
let instance_def_id = instance.def_id();
|
let instance_def_id = instance.def_id();
|
||||||
let llfn = if tcx.sess.target.arch == "x86"
|
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
|
// 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
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
//! Code that is useful in various codegen modules.
|
//! Code that is useful in various codegen modules.
|
||||||
|
|
||||||
use std::fmt::Write;
|
|
||||||
|
|
||||||
use libc::{c_char, c_uint};
|
use libc::{c_char, c_uint};
|
||||||
use rustc_ast::Mutability;
|
use rustc_ast::Mutability;
|
||||||
use rustc_codegen_ssa::traits::*;
|
use rustc_codegen_ssa::traits::*;
|
||||||
@ -10,9 +8,8 @@
|
|||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc, Scalar};
|
use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc, Scalar};
|
||||||
use rustc_middle::ty::TyCtxt;
|
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::abi::{self, AddressSpace, HasDataLayout, Pointer};
|
||||||
use rustc_target::spec::Target;
|
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
use crate::consts::const_alloc_to_llvm;
|
use crate::consts::const_alloc_to_llvm;
|
||||||
@ -379,64 +376,3 @@ pub(crate) fn get_dllimport<'tcx>(
|
|||||||
tcx.native_library(id)
|
tcx.native_library(id)
|
||||||
.and_then(|lib| lib.dll_imports.iter().find(|di| di.name.as_str() == name))
|
.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 std::ops::Range;
|
||||||
|
|
||||||
|
use rustc_codegen_ssa::common;
|
||||||
use rustc_codegen_ssa::traits::*;
|
use rustc_codegen_ssa::traits::*;
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
@ -18,7 +19,7 @@
|
|||||||
};
|
};
|
||||||
use tracing::{debug, instrument, trace};
|
use tracing::{debug, instrument, trace};
|
||||||
|
|
||||||
use crate::common::{self, CodegenCx};
|
use crate::common::CodegenCx;
|
||||||
use crate::errors::{
|
use crate::errors::{
|
||||||
InvalidMinimumAlignmentNotPowerOfTwo, InvalidMinimumAlignmentTooLarge, SymbolAlreadyDefined,
|
InvalidMinimumAlignmentNotPowerOfTwo, InvalidMinimumAlignmentTooLarge, SymbolAlreadyDefined,
|
||||||
};
|
};
|
||||||
@ -195,7 +196,7 @@ fn check_and_apply_linkage<'ll, 'tcx>(
|
|||||||
g2
|
g2
|
||||||
}
|
}
|
||||||
} else if cx.tcx.sess.target.arch == "x86"
|
} 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(
|
cx.declare_global(
|
||||||
&common::i686_decorated_name(
|
&common::i686_decorated_name(
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
use std::borrow::Cow;
|
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
@ -71,28 +70,6 @@ pub(crate) struct InvalidMinimumAlignmentTooLarge {
|
|||||||
#[diag(codegen_llvm_sanitizer_memtag_requires_mte)]
|
#[diag(codegen_llvm_sanitizer_memtag_requires_mte)]
|
||||||
pub(crate) struct SanitizerMemtagRequiresMte;
|
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)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(codegen_llvm_dynamic_linking_with_lto)]
|
#[diag(codegen_llvm_dynamic_linking_with_lto)]
|
||||||
#[note]
|
#[note]
|
||||||
|
@ -5,7 +5,7 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# tidy-alphabetical-start
|
# tidy-alphabetical-start
|
||||||
ar_archive_writer = "0.3.0"
|
ar_archive_writer = "0.3.3"
|
||||||
arrayvec = { version = "0.7", default-features = false }
|
arrayvec = { version = "0.7", default-features = false }
|
||||||
bitflags = "2.4.1"
|
bitflags = "2.4.1"
|
||||||
cc = "1.0.90"
|
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_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_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_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
|
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::error::Error;
|
||||||
|
use std::ffi::OsString;
|
||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
@ -9,7 +11,6 @@
|
|||||||
use object::read::macho::FatArch;
|
use object::read::macho::FatArch;
|
||||||
use rustc_data_structures::fx::FxIndexSet;
|
use rustc_data_structures::fx::FxIndexSet;
|
||||||
use rustc_data_structures::memmap::Mmap;
|
use rustc_data_structures::memmap::Mmap;
|
||||||
use rustc_session::cstore::DllImport;
|
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use rustc_span::symbol::Symbol;
|
use rustc_span::symbol::Symbol;
|
||||||
use tempfile::Builder as TempFileBuilder;
|
use tempfile::Builder as TempFileBuilder;
|
||||||
@ -17,6 +18,7 @@
|
|||||||
use super::metadata::search_for_section;
|
use super::metadata::search_for_section;
|
||||||
// Re-exporting for rustc_codegen_llvm::back::archive
|
// Re-exporting for rustc_codegen_llvm::back::archive
|
||||||
pub use crate::errors::{ArchiveBuildFailure, ExtractBundledLibsError, UnknownArchiveKind};
|
pub use crate::errors::{ArchiveBuildFailure, ExtractBundledLibsError, UnknownArchiveKind};
|
||||||
|
use crate::errors::{DlltoolFailImportLibrary, ErrorCallingDllTool, ErrorWritingDEFFile};
|
||||||
|
|
||||||
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>;
|
||||||
@ -30,10 +32,9 @@ fn create_dll_import_lib(
|
|||||||
&self,
|
&self,
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
lib_name: &str,
|
lib_name: &str,
|
||||||
dll_imports: &[DllImport],
|
import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
|
||||||
tmpdir: &Path,
|
output_path: &Path,
|
||||||
is_direct_dependency: bool,
|
);
|
||||||
) -> PathBuf;
|
|
||||||
|
|
||||||
fn extract_bundled_libs<'a>(
|
fn extract_bundled_libs<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
@ -72,6 +73,130 @@ fn extract_bundled_libs<'a>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
pub trait ArchiveBuilder {
|
||||||
fn add_file(&mut self, path: &Path);
|
fn add_file(&mut self, path: &Path);
|
||||||
|
|
||||||
|
@ -51,7 +51,8 @@
|
|||||||
use super::metadata::{create_wrapper_file, MetadataPosition};
|
use super::metadata::{create_wrapper_file, MetadataPosition};
|
||||||
use super::rpath::{self, RPathConfig};
|
use super::rpath::{self, RPathConfig};
|
||||||
use crate::{
|
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) {
|
pub fn ensure_removed(dcx: DiagCtxtHandle<'_>, path: &Path) {
|
||||||
@ -390,17 +391,13 @@ fn link_rlib<'a>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (raw_dylib_name, raw_dylib_imports) in
|
for output_path in create_dll_import_libs(
|
||||||
collate_raw_dylibs(sess, codegen_results.crate_info.used_libraries.iter())?
|
sess,
|
||||||
{
|
archive_builder_builder,
|
||||||
let output_path = archive_builder_builder.create_dll_import_lib(
|
codegen_results.crate_info.used_libraries.iter(),
|
||||||
sess,
|
tmpdir.as_ref(),
|
||||||
&raw_dylib_name,
|
true,
|
||||||
&raw_dylib_imports,
|
)? {
|
||||||
tmpdir.as_ref(),
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
|
|
||||||
ab.add_archive(&output_path, Box::new(|_| false)).unwrap_or_else(|error| {
|
ab.add_archive(&output_path, Box::new(|_| false)).unwrap_or_else(|error| {
|
||||||
sess.dcx().emit_fatal(errors::AddNativeLibrary { library_path: output_path, error });
|
sess.dcx().emit_fatal(errors::AddNativeLibrary { library_path: output_path, error });
|
||||||
});
|
});
|
||||||
@ -488,6 +485,47 @@ fn collate_raw_dylibs<'a>(
|
|||||||
.collect())
|
.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.
|
/// Create a static archive.
|
||||||
///
|
///
|
||||||
/// This is essentially the same thing as an rlib, but it also involves adding all of the upstream
|
/// 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.
|
// Link with the import library generated for any raw-dylib functions.
|
||||||
for (raw_dylib_name, raw_dylib_imports) in
|
for output_path in create_dll_import_libs(
|
||||||
collate_raw_dylibs(sess, codegen_results.crate_info.used_libraries.iter())?
|
sess,
|
||||||
{
|
archive_builder_builder,
|
||||||
cmd.add_object(&archive_builder_builder.create_dll_import_lib(
|
codegen_results.crate_info.used_libraries.iter(),
|
||||||
sess,
|
tmpdir,
|
||||||
&raw_dylib_name,
|
true,
|
||||||
&raw_dylib_imports,
|
)? {
|
||||||
tmpdir,
|
cmd.add_object(&output_path);
|
||||||
true,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
// As with add_upstream_native_libraries, we need to add the upstream raw-dylib symbols in case
|
// 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*
|
// they are used within inlined functions or instantiated generic functions. We do this *after*
|
||||||
@ -2339,16 +2375,14 @@ fn linker_with_args(
|
|||||||
.flatten()
|
.flatten()
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
native_libraries_from_nonstatics.sort_unstable_by(|a, b| a.name.as_str().cmp(b.name.as_str()));
|
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
|
for output_path in create_dll_import_libs(
|
||||||
collate_raw_dylibs(sess, native_libraries_from_nonstatics)?
|
sess,
|
||||||
{
|
archive_builder_builder,
|
||||||
cmd.add_object(&archive_builder_builder.create_dll_import_lib(
|
native_libraries_from_nonstatics,
|
||||||
sess,
|
tmpdir,
|
||||||
&raw_dylib_name,
|
false,
|
||||||
&raw_dylib_imports,
|
)? {
|
||||||
tmpdir,
|
cmd.add_object(&output_path);
|
||||||
false,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Library linking above uses some global state for things like `-Bstatic`/`-Bdynamic` to make
|
// Library linking above uses some global state for things like `-Bstatic`/`-Bdynamic` to make
|
||||||
|
@ -4,7 +4,9 @@
|
|||||||
use rustc_middle::ty::layout::TyAndLayout;
|
use rustc_middle::ty::layout::TyAndLayout;
|
||||||
use rustc_middle::ty::{self, Instance, TyCtxt};
|
use rustc_middle::ty::{self, Instance, TyCtxt};
|
||||||
use rustc_middle::{bug, mir, span_bug};
|
use rustc_middle::{bug, mir, span_bug};
|
||||||
|
use rustc_session::cstore::{DllCallingConvention, DllImport, PeImportNameType};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
use rustc_target::spec::Target;
|
||||||
|
|
||||||
use crate::traits::*;
|
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),
|
_ => 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>,
|
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)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(codegen_ssa_error_creating_remark_dir)]
|
#[diag(codegen_ssa_error_creating_remark_dir)]
|
||||||
pub struct ErrorCreatingRemarkDir {
|
pub struct ErrorCreatingRemarkDir {
|
||||||
|
Loading…
Reference in New Issue
Block a user