mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-13 04:26:48 +00:00
Implementation of import_name_type
This commit is contained in:
parent
42fa8ac723
commit
cc49c3e582
@ -8,10 +8,11 @@ use std::path::{Path, PathBuf};
|
||||
use std::ptr;
|
||||
use std::str;
|
||||
|
||||
use crate::common;
|
||||
use crate::llvm::archive_ro::{ArchiveRO, Child};
|
||||
use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport};
|
||||
use rustc_codegen_ssa::back::archive::{ArchiveBuilder, ArchiveBuilderBuilder};
|
||||
use rustc_session::cstore::{DllCallingConvention, DllImport};
|
||||
use rustc_session::cstore::DllImport;
|
||||
use rustc_session::Session;
|
||||
|
||||
/// Helper for adding many files to an archive.
|
||||
@ -111,21 +112,18 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
|
||||
};
|
||||
|
||||
let target = &sess.target;
|
||||
let mingw_gnu_toolchain = target.vendor == "pc"
|
||||
&& target.os == "windows"
|
||||
&& target.env == "gnu"
|
||||
&& target.abi.is_empty();
|
||||
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" {
|
||||
(
|
||||
LlvmArchiveBuilder::i686_decorated_name(import, mingw_gnu_toolchain),
|
||||
import.ordinal,
|
||||
common::i686_decorated_name(import, mingw_gnu_toolchain, false),
|
||||
import.ordinal(),
|
||||
)
|
||||
} else {
|
||||
(import.name.to_string(), import.ordinal)
|
||||
(import.name.to_string(), import.ordinal())
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
@ -159,6 +157,9 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
|
||||
}
|
||||
};
|
||||
|
||||
// --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 result = std::process::Command::new(dlltool)
|
||||
.args([
|
||||
@ -168,6 +169,7 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
|
||||
lib_name,
|
||||
"-l",
|
||||
output_path.to_str().unwrap(),
|
||||
"--no-leading-underscore",
|
||||
])
|
||||
.output();
|
||||
|
||||
@ -322,22 +324,6 @@ impl<'a> LlvmArchiveBuilder<'a> {
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
fn i686_decorated_name(import: &DllImport, mingw: bool) -> String {
|
||||
let name = import.name;
|
||||
let prefix = if mingw { "" } else { "_" };
|
||||
|
||||
match import.calling_convention {
|
||||
DllCallingConvention::C => format!("{}{}", prefix, name),
|
||||
DllCallingConvention::Stdcall(arg_list_size) => {
|
||||
format!("{}{}@{}", prefix, name, arg_list_size)
|
||||
}
|
||||
DllCallingConvention::Fastcall(arg_list_size) => format!("@{}@{}", name, arg_list_size),
|
||||
DllCallingConvention::Vectorcall(arg_list_size) => {
|
||||
format!("{}@@{}", name, arg_list_size)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn string_to_io_error(s: String) -> io::Error {
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
use crate::abi::FnAbiLlvmExt;
|
||||
use crate::attributes;
|
||||
use crate::common;
|
||||
use crate::context::CodegenCx;
|
||||
use crate::llvm;
|
||||
use crate::value::Value;
|
||||
@ -79,13 +80,18 @@ pub fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) ->
|
||||
llfn
|
||||
}
|
||||
} else {
|
||||
let llfn = cx.declare_fn(sym, fn_abi);
|
||||
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)
|
||||
{
|
||||
cx.declare_fn(&common::i686_decorated_name(&dllimport, common::is_mingw_gnu_toolchain(&tcx.sess.target), true), fn_abi)
|
||||
} else {
|
||||
cx.declare_fn(sym, fn_abi)
|
||||
};
|
||||
debug!("get_fn: not casting pointer!");
|
||||
|
||||
attributes::from_fn_attrs(cx, llfn, instance);
|
||||
|
||||
let instance_def_id = instance.def_id();
|
||||
|
||||
// Apply an appropriate linkage/visibility value to our item that we
|
||||
// just declared.
|
||||
//
|
||||
|
@ -10,12 +10,17 @@ use crate::value::Value;
|
||||
use rustc_ast::Mutability;
|
||||
use rustc_codegen_ssa::mir::place::PlaceRef;
|
||||
use rustc_codegen_ssa::traits::*;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc, Scalar};
|
||||
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::cstore::{DllCallingConvention, DllImport, PeImportNameType};
|
||||
use rustc_target::abi::{self, AddressSpace, HasDataLayout, Pointer, Size};
|
||||
use rustc_target::spec::Target;
|
||||
|
||||
use libc::{c_char, c_uint};
|
||||
use std::fmt::Write;
|
||||
use tracing::debug;
|
||||
|
||||
/*
|
||||
@ -357,3 +362,74 @@ fn hi_lo_to_u128(lo: u64, hi: u64) -> u128 {
|
||||
fn try_as_const_integral(v: &Value) -> Option<&ConstantInt> {
|
||||
unsafe { llvm::LLVMIsAConstantInt(v) }
|
||||
}
|
||||
|
||||
pub(crate) fn get_dllimport<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
id: DefId,
|
||||
name: &str,
|
||||
) -> Option<&'tcx DllImport> {
|
||||
tcx.native_library(id)
|
||||
.map(|lib| lib.dll_imports.iter().find(|di| di.name.as_str() == name))
|
||||
.flatten()
|
||||
}
|
||||
|
||||
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,5 @@
|
||||
use crate::base;
|
||||
use crate::common::CodegenCx;
|
||||
use crate::common::{self, CodegenCx};
|
||||
use crate::debuginfo;
|
||||
use crate::llvm::{self, True};
|
||||
use crate::llvm_util;
|
||||
@ -160,7 +160,7 @@ fn check_and_apply_linkage<'ll, 'tcx>(
|
||||
attrs: &CodegenFnAttrs,
|
||||
ty: Ty<'tcx>,
|
||||
sym: &str,
|
||||
span_def_id: DefId,
|
||||
def_id: DefId,
|
||||
) -> &'ll Value {
|
||||
let llty = cx.layout_of(ty).llvm_type(cx);
|
||||
if let Some(linkage) = attrs.linkage {
|
||||
@ -175,7 +175,7 @@ fn check_and_apply_linkage<'ll, 'tcx>(
|
||||
cx.layout_of(mt.ty).llvm_type(cx)
|
||||
} else {
|
||||
cx.sess().span_fatal(
|
||||
cx.tcx.def_span(span_def_id),
|
||||
cx.tcx.def_span(def_id),
|
||||
"must have type `*const T` or `*mut T` due to `#[linkage]` attribute",
|
||||
)
|
||||
};
|
||||
@ -194,7 +194,7 @@ fn check_and_apply_linkage<'ll, 'tcx>(
|
||||
real_name.push_str(sym);
|
||||
let g2 = cx.define_global(&real_name, llty).unwrap_or_else(|| {
|
||||
cx.sess().span_fatal(
|
||||
cx.tcx.def_span(span_def_id),
|
||||
cx.tcx.def_span(def_id),
|
||||
&format!("symbol `{}` is already defined", &sym),
|
||||
)
|
||||
});
|
||||
@ -202,6 +202,10 @@ fn check_and_apply_linkage<'ll, 'tcx>(
|
||||
llvm::LLVMSetInitializer(g2, g1);
|
||||
g2
|
||||
}
|
||||
} else if cx.tcx.sess.target.arch == "x86" &&
|
||||
let Some(dllimport) = common::get_dllimport(cx.tcx, def_id, sym)
|
||||
{
|
||||
cx.declare_global(&common::i686_decorated_name(&dllimport, common::is_mingw_gnu_toolchain(&cx.tcx.sess.target), true), llty)
|
||||
} else {
|
||||
// Generate an external declaration.
|
||||
// FIXME(nagisa): investigate whether it can be changed into define_global
|
||||
|
@ -335,7 +335,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||
// ABI, linking, symbols, and FFI
|
||||
ungated!(
|
||||
link, Normal,
|
||||
template!(List: r#"name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...""#),
|
||||
template!(List: r#"name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...", /*opt*/ import_name_type = "decorated|noprefix|undecorated""#),
|
||||
DuplicatesOk,
|
||||
),
|
||||
ungated!(link_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding),
|
||||
|
@ -5,7 +5,7 @@ use rustc_errors::struct_span_err;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_middle::ty::{List, ParamEnv, ParamEnvAnd, Ty, TyCtxt};
|
||||
use rustc_session::cstore::{DllCallingConvention, DllImport, NativeLib};
|
||||
use rustc_session::cstore::{DllCallingConvention, DllImport, NativeLib, PeImportNameType};
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_session::utils::NativeLibKind;
|
||||
use rustc_session::Session;
|
||||
@ -61,6 +61,7 @@ impl<'tcx> Collector<'tcx> {
|
||||
let mut modifiers = None;
|
||||
let mut cfg = None;
|
||||
let mut wasm_import_module = None;
|
||||
let mut import_name_type = None;
|
||||
for item in items.iter() {
|
||||
match item.name_or_empty() {
|
||||
sym::name => {
|
||||
@ -199,9 +200,51 @@ impl<'tcx> Collector<'tcx> {
|
||||
};
|
||||
wasm_import_module = Some((link_wasm_import_module, item.span()));
|
||||
}
|
||||
sym::import_name_type => {
|
||||
if import_name_type.is_some() {
|
||||
let msg = "multiple `import_name_type` arguments in a single `#[link]` attribute";
|
||||
sess.span_err(item.span(), msg);
|
||||
continue;
|
||||
}
|
||||
let Some(link_import_name_type) = item.value_str() else {
|
||||
let msg = "import name type must be of the form `import_name_type = \"string\"`";
|
||||
sess.span_err(item.span(), msg);
|
||||
continue;
|
||||
};
|
||||
if self.tcx.sess.target.arch != "x86" {
|
||||
let msg = "import name type is only supported on x86";
|
||||
sess.span_err(item.span(), msg);
|
||||
continue;
|
||||
}
|
||||
|
||||
let link_import_name_type = match link_import_name_type.as_str() {
|
||||
"decorated" => PeImportNameType::Decorated,
|
||||
"noprefix" => PeImportNameType::NoPrefix,
|
||||
"undecorated" => PeImportNameType::Undecorated,
|
||||
import_name_type => {
|
||||
let msg = format!(
|
||||
"unknown import name type `{import_name_type}`, expected one of: \
|
||||
decorated, noprefix, undecorated"
|
||||
);
|
||||
sess.span_err(item.span(), msg);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
if !features.raw_dylib {
|
||||
let span = item.name_value_literal_span().unwrap();
|
||||
feature_err(
|
||||
&sess.parse_sess,
|
||||
sym::raw_dylib,
|
||||
span,
|
||||
"import name type is unstable",
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
import_name_type = Some((link_import_name_type, item.span()));
|
||||
}
|
||||
_ => {
|
||||
let msg = "unexpected `#[link]` argument, expected one of: \
|
||||
name, kind, modifiers, cfg, wasm_import_module";
|
||||
name, kind, modifiers, cfg, wasm_import_module, import_name_type";
|
||||
sess.span_err(item.span(), msg);
|
||||
}
|
||||
}
|
||||
@ -315,6 +358,14 @@ impl<'tcx> Collector<'tcx> {
|
||||
.emit();
|
||||
}
|
||||
|
||||
// Do this outside of the loop so that `import_name_type` can be specified before `kind`.
|
||||
if let Some((_, span)) = import_name_type {
|
||||
if kind != Some(NativeLibKind::RawDylib) {
|
||||
let msg = "import name type can only be used with link kind `raw-dylib`";
|
||||
sess.span_err(span, msg);
|
||||
}
|
||||
}
|
||||
|
||||
let dll_imports = match kind {
|
||||
Some(NativeLibKind::RawDylib) => {
|
||||
if let Some((name, span)) = name && name.as_str().contains('\0') {
|
||||
@ -325,7 +376,13 @@ impl<'tcx> Collector<'tcx> {
|
||||
}
|
||||
foreign_mod_items
|
||||
.iter()
|
||||
.map(|child_item| self.build_dll_import(abi, child_item))
|
||||
.map(|child_item| {
|
||||
self.build_dll_import(
|
||||
abi,
|
||||
import_name_type.map(|(import_name_type, _)| import_name_type),
|
||||
child_item,
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
_ => {
|
||||
@ -486,7 +543,12 @@ impl<'tcx> Collector<'tcx> {
|
||||
.sum()
|
||||
}
|
||||
|
||||
fn build_dll_import(&self, abi: Abi, item: &hir::ForeignItemRef) -> DllImport {
|
||||
fn build_dll_import(
|
||||
&self,
|
||||
abi: Abi,
|
||||
import_name_type: Option<PeImportNameType>,
|
||||
item: &hir::ForeignItemRef,
|
||||
) -> DllImport {
|
||||
let calling_convention = if self.tcx.sess.target.arch == "x86" {
|
||||
match abi {
|
||||
Abi::C { .. } | Abi::Cdecl { .. } => DllCallingConvention::C,
|
||||
@ -518,11 +580,18 @@ impl<'tcx> Collector<'tcx> {
|
||||
}
|
||||
};
|
||||
|
||||
let import_name_type = self
|
||||
.tcx
|
||||
.codegen_fn_attrs(item.id.def_id)
|
||||
.link_ordinal
|
||||
.map_or(import_name_type, |ord| Some(PeImportNameType::Ordinal(ord)));
|
||||
|
||||
DllImport {
|
||||
name: item.ident.name,
|
||||
ordinal: self.tcx.codegen_fn_attrs(item.id.def_id).link_ordinal,
|
||||
import_name_type,
|
||||
calling_convention,
|
||||
span: item.span,
|
||||
is_fn: self.tcx.def_kind(item.id.def_id).is_fn_like(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -341,7 +341,8 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) {
|
||||
assert_eq!(cnum, LOCAL_CRATE);
|
||||
false
|
||||
},
|
||||
native_library_kind: |tcx, id| {
|
||||
native_library_kind: |tcx, id| tcx.native_library(id).map(|l| l.kind),
|
||||
native_library: |tcx, id| {
|
||||
tcx.native_libraries(id.krate)
|
||||
.iter()
|
||||
.filter(|lib| native_libs::relevant_lib(&tcx.sess, lib))
|
||||
@ -355,7 +356,6 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) {
|
||||
.foreign_items
|
||||
.contains(&id)
|
||||
})
|
||||
.map(|l| l.kind)
|
||||
},
|
||||
native_libraries: |tcx, cnum| {
|
||||
assert_eq!(cnum, LOCAL_CRATE);
|
||||
|
@ -1566,6 +1566,9 @@ rustc_queries! {
|
||||
-> Option<NativeLibKind> {
|
||||
desc { |tcx| "native_library_kind({})", tcx.def_path_str(def_id) }
|
||||
}
|
||||
query native_library(def_id: DefId) -> Option<&'tcx NativeLib> {
|
||||
desc { |tcx| "native_library({})", tcx.def_path_str(def_id) }
|
||||
}
|
||||
|
||||
/// Does lifetime resolution, but does not descend into trait items. This
|
||||
/// should only be used for resolving lifetimes of on trait definitions,
|
||||
|
@ -81,10 +81,29 @@ impl NativeLib {
|
||||
}
|
||||
}
|
||||
|
||||
/// Different ways that the PE Format can decorate a symbol name.
|
||||
/// From <https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#import-name-type>
|
||||
#[derive(Copy, Clone, Debug, Encodable, Decodable, HashStable_Generic, PartialEq, Eq)]
|
||||
pub enum PeImportNameType {
|
||||
/// IMPORT_ORDINAL
|
||||
/// Uses the ordinal (i.e., a number) rather than the name.
|
||||
Ordinal(u16),
|
||||
/// Same as IMPORT_NAME
|
||||
/// Name is decorated with all prefixes and suffixes.
|
||||
Decorated,
|
||||
/// Same as IMPORT_NAME_NOPREFIX
|
||||
/// Prefix (e.g., the leading `_` or `@`) is skipped, but suffix is kept.
|
||||
NoPrefix,
|
||||
/// Same as IMPORT_NAME_UNDECORATE
|
||||
/// Prefix (e.g., the leading `_` or `@`) and suffix (the first `@` and all
|
||||
/// trailing characters) are skipped.
|
||||
Undecorated,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Encodable, Decodable, HashStable_Generic)]
|
||||
pub struct DllImport {
|
||||
pub name: Symbol,
|
||||
pub ordinal: Option<u16>,
|
||||
pub import_name_type: Option<PeImportNameType>,
|
||||
/// Calling convention for the function.
|
||||
///
|
||||
/// On x86_64, this is always `DllCallingConvention::C`; on i686, it can be any
|
||||
@ -92,6 +111,18 @@ pub struct DllImport {
|
||||
pub calling_convention: DllCallingConvention,
|
||||
/// Span of import's "extern" declaration; used for diagnostics.
|
||||
pub span: Span,
|
||||
/// Is this for a function (rather than a static variable).
|
||||
pub is_fn: bool,
|
||||
}
|
||||
|
||||
impl DllImport {
|
||||
pub fn ordinal(&self) -> Option<u16> {
|
||||
if let Some(PeImportNameType::Ordinal(ordinal)) = self.import_name_type {
|
||||
Some(ordinal)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Calling convention for a function defined in an external library.
|
||||
|
@ -803,6 +803,7 @@ symbols! {
|
||||
impl_trait_in_bindings,
|
||||
implied_by,
|
||||
import,
|
||||
import_name_type,
|
||||
import_shadowing,
|
||||
imported_main,
|
||||
in_band_lifetimes,
|
||||
|
22
src/test/run-make/raw-dylib-import-name-type/Makefile
Normal file
22
src/test/run-make/raw-dylib-import-name-type/Makefile
Normal file
@ -0,0 +1,22 @@
|
||||
# Test the behavior of #[link(.., kind = "raw-dylib")] with alternative calling conventions.
|
||||
|
||||
# only-x86
|
||||
# only-windows
|
||||
|
||||
-include ../../run-make-fulldeps/tools.mk
|
||||
|
||||
all:
|
||||
$(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
|
||||
$(call COMPILE_OBJ,"$(TMPDIR)"/extern.obj,extern.c)
|
||||
ifdef IS_MSVC
|
||||
$(CC) "$(TMPDIR)"/extern.obj extern.msvc.def -link -dll -out:"$(TMPDIR)"/extern.dll -noimplib
|
||||
else
|
||||
$(CC) "$(TMPDIR)"/extern.obj extern.gnu.def --no-leading-underscore -shared -o "$(TMPDIR)"/extern.dll
|
||||
endif
|
||||
"$(TMPDIR)"/driver > "$(TMPDIR)"/output.txt
|
||||
|
||||
ifdef RUSTC_BLESS_TEST
|
||||
cp "$(TMPDIR)"/output.txt output.txt
|
||||
else
|
||||
$(DIFF) output.txt "$(TMPDIR)"/output.txt
|
||||
endif
|
79
src/test/run-make/raw-dylib-import-name-type/driver.rs
Normal file
79
src/test/run-make/raw-dylib-import-name-type/driver.rs
Normal file
@ -0,0 +1,79 @@
|
||||
#![feature(raw_dylib)]
|
||||
|
||||
#[link(name = "extern", kind = "raw-dylib", import_name_type = "undecorated")]
|
||||
extern "C" {
|
||||
fn cdecl_fn_undecorated(i: i32);
|
||||
static mut extern_variable_undecorated: i32;
|
||||
}
|
||||
|
||||
#[link(name = "extern", kind = "raw-dylib", import_name_type = "noprefix")]
|
||||
extern "C" {
|
||||
fn cdecl_fn_noprefix(i: i32);
|
||||
static mut extern_variable_noprefix: i32;
|
||||
}
|
||||
|
||||
#[link(name = "extern", kind = "raw-dylib", import_name_type = "decorated")]
|
||||
extern "C" {
|
||||
fn cdecl_fn_decorated(i: i32);
|
||||
static mut extern_variable_decorated: i32;
|
||||
}
|
||||
|
||||
#[link(name = "extern", kind = "raw-dylib", import_name_type = "undecorated")]
|
||||
extern "stdcall" {
|
||||
fn stdcall_fn_undecorated(i: i32);
|
||||
}
|
||||
|
||||
#[link(name = "extern", kind = "raw-dylib", import_name_type = "noprefix")]
|
||||
extern "stdcall" {
|
||||
fn stdcall_fn_noprefix(i: i32);
|
||||
}
|
||||
|
||||
#[link(name = "extern", kind = "raw-dylib", import_name_type = "decorated")]
|
||||
extern "stdcall" {
|
||||
fn stdcall_fn_decorated(i: i32);
|
||||
}
|
||||
|
||||
#[link(name = "extern", kind = "raw-dylib", import_name_type = "undecorated")]
|
||||
extern "fastcall" {
|
||||
fn fastcall_fn_undecorated(i: i32);
|
||||
}
|
||||
|
||||
#[link(name = "extern", kind = "raw-dylib", import_name_type = "noprefix")]
|
||||
extern "fastcall" {
|
||||
fn fastcall_fn_noprefix(i: i32);
|
||||
}
|
||||
|
||||
#[link(name = "extern", kind = "raw-dylib", import_name_type = "decorated")]
|
||||
extern "fastcall" {
|
||||
fn fastcall_fn_decorated(i: i32);
|
||||
}
|
||||
|
||||
#[link(name = "extern", kind = "raw-dylib")]
|
||||
extern {
|
||||
fn print_extern_variable_undecorated();
|
||||
fn print_extern_variable_noprefix();
|
||||
fn print_extern_variable_decorated();
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
unsafe {
|
||||
cdecl_fn_undecorated(1);
|
||||
cdecl_fn_noprefix(2);
|
||||
cdecl_fn_decorated(3);
|
||||
|
||||
stdcall_fn_undecorated(4);
|
||||
stdcall_fn_noprefix(5);
|
||||
stdcall_fn_decorated(6);
|
||||
|
||||
fastcall_fn_undecorated(7);
|
||||
fastcall_fn_noprefix(8);
|
||||
fastcall_fn_decorated(9);
|
||||
|
||||
extern_variable_undecorated = 42;
|
||||
print_extern_variable_undecorated();
|
||||
extern_variable_noprefix = 43;
|
||||
print_extern_variable_noprefix();
|
||||
extern_variable_decorated = 44;
|
||||
print_extern_variable_decorated();
|
||||
}
|
||||
}
|
65
src/test/run-make/raw-dylib-import-name-type/extern.c
Normal file
65
src/test/run-make/raw-dylib-import-name-type/extern.c
Normal file
@ -0,0 +1,65 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void _cdecl cdecl_fn_undecorated(int i) {
|
||||
printf("cdecl_fn_undecorated(%d)\n", i);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void _cdecl cdecl_fn_noprefix(int i) {
|
||||
printf("cdecl_fn_noprefix(%d)\n", i);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void _cdecl cdecl_fn_decorated(int i) {
|
||||
printf("cdecl_fn_decorated(%d)\n", i);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void __stdcall stdcall_fn_undecorated(int i) {
|
||||
printf("stdcall_fn_undecorated(%d)\n", i);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void __stdcall stdcall_fn_noprefix(int i) {
|
||||
printf("stdcall_fn_noprefix(%d)\n", i);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void __stdcall stdcall_fn_decorated(int i) {
|
||||
printf("stdcall_fn_decorated(%d)\n", i);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void __fastcall fastcall_fn_undecorated(int i) {
|
||||
printf("fastcall_fn_undecorated(%d)\n", i);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void __fastcall fastcall_fn_noprefix(int i) {
|
||||
printf("fastcall_fn_noprefix(%d)\n", i);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void __fastcall fastcall_fn_decorated(int i) {
|
||||
printf("fastcall_fn_decorated(%d)\n", i);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
int extern_variable_undecorated = 0;
|
||||
__declspec(dllexport) void print_extern_variable_undecorated() {
|
||||
printf("extern_variable_undecorated value: %d\n", extern_variable_undecorated);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
int extern_variable_noprefix = 0;
|
||||
__declspec(dllexport) void print_extern_variable_noprefix() {
|
||||
printf("extern_variable_noprefix value: %d\n", extern_variable_noprefix);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
int extern_variable_decorated = 0;
|
||||
__declspec(dllexport) void print_extern_variable_decorated() {
|
||||
printf("extern_variable_decorated value: %d\n", extern_variable_decorated);
|
||||
fflush(stdout);
|
||||
}
|
18
src/test/run-make/raw-dylib-import-name-type/extern.gnu.def
Normal file
18
src/test/run-make/raw-dylib-import-name-type/extern.gnu.def
Normal file
@ -0,0 +1,18 @@
|
||||
LIBRARY extern
|
||||
EXPORTS
|
||||
cdecl_fn_undecorated
|
||||
cdecl_fn_noprefix
|
||||
cdecl_fn_decorated
|
||||
stdcall_fn_undecorated
|
||||
stdcall_fn_noprefix@4
|
||||
fastcall_fn_undecorated
|
||||
@fastcall_fn_decorated@4
|
||||
|
||||
;ld doesn't handle fully-decorated stdcall, or no-prefix fastcall
|
||||
_stdcall_fn_decorated@4=stdcall_fn_decorated@4
|
||||
fastcall_fn_noprefix@4=@fastcall_fn_noprefix@4
|
||||
|
||||
;Variables are never decorated
|
||||
extern_variable_undecorated
|
||||
extern_variable_noprefix
|
||||
extern_variable_decorated
|
18
src/test/run-make/raw-dylib-import-name-type/extern.msvc.def
Normal file
18
src/test/run-make/raw-dylib-import-name-type/extern.msvc.def
Normal file
@ -0,0 +1,18 @@
|
||||
LIBRARY extern
|
||||
EXPORTS
|
||||
cdecl_fn_undecorated
|
||||
cdecl_fn_noprefix
|
||||
cdecl_fn_decorated
|
||||
stdcall_fn_undecorated
|
||||
_stdcall_fn_decorated@4
|
||||
fastcall_fn_undecorated
|
||||
@fastcall_fn_decorated@4
|
||||
|
||||
;MSVC doesn't seem to recognize the "no prefix" syntax.
|
||||
stdcall_fn_noprefix@4=_stdcall_fn_noprefix@4
|
||||
fastcall_fn_noprefix@4=@fastcall_fn_noprefix@4
|
||||
|
||||
;Variables are never decorated
|
||||
extern_variable_undecorated
|
||||
extern_variable_noprefix
|
||||
extern_variable_decorated
|
12
src/test/run-make/raw-dylib-import-name-type/output.txt
Normal file
12
src/test/run-make/raw-dylib-import-name-type/output.txt
Normal file
@ -0,0 +1,12 @@
|
||||
cdecl_fn_undecorated(1)
|
||||
cdecl_fn_noprefix(2)
|
||||
cdecl_fn_decorated(3)
|
||||
stdcall_fn_undecorated(4)
|
||||
stdcall_fn_noprefix(5)
|
||||
stdcall_fn_decorated(6)
|
||||
fastcall_fn_undecorated(7)
|
||||
fastcall_fn_noprefix(8)
|
||||
fastcall_fn_decorated(9)
|
||||
extern_variable_undecorated value: 42
|
||||
extern_variable_noprefix value: 43
|
||||
extern_variable_decorated value: 44
|
@ -0,0 +1,8 @@
|
||||
// only-windows
|
||||
// only-x86
|
||||
#[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated")]
|
||||
//~^ ERROR link kind `raw-dylib` is unstable
|
||||
//~| ERROR import name type is unstable
|
||||
extern "C" {}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,21 @@
|
||||
error[E0658]: link kind `raw-dylib` is unstable
|
||||
--> $DIR/feature-gate-raw-dylib-import-name-type.rs:3:29
|
||||
|
|
||||
LL | #[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated")]
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #58713 <https://github.com/rust-lang/rust/issues/58713> for more information
|
||||
= help: add `#![feature(raw_dylib)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: import name type is unstable
|
||||
--> $DIR/feature-gate-raw-dylib-import-name-type.rs:3:61
|
||||
|
|
||||
LL | #[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated")]
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #58713 <https://github.com/rust-lang/rust/issues/58713> for more information
|
||||
= help: add `#![feature(raw_dylib)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
@ -1,4 +1,4 @@
|
||||
error: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...")]`
|
||||
error: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...", /*opt*/ import_name_type = "decorated|noprefix|undecorated")]`
|
||||
--> $DIR/link-attr-validation-early.rs:2:1
|
||||
|
|
||||
LL | #[link]
|
||||
@ -8,7 +8,7 @@ LL | #[link]
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
|
||||
|
||||
error: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...")]`
|
||||
error: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...", /*opt*/ import_name_type = "decorated|noprefix|undecorated")]`
|
||||
--> $DIR/link-attr-validation-early.rs:4:1
|
||||
|
|
||||
LL | #[link = "foo"]
|
||||
|
@ -1,10 +1,10 @@
|
||||
error: unexpected `#[link]` argument, expected one of: name, kind, modifiers, cfg, wasm_import_module
|
||||
error: unexpected `#[link]` argument, expected one of: name, kind, modifiers, cfg, wasm_import_module, import_name_type
|
||||
--> $DIR/link-attr-validation-late.rs:5:22
|
||||
|
|
||||
LL | #[link(name = "...", "literal")]
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: unexpected `#[link]` argument, expected one of: name, kind, modifiers, cfg, wasm_import_module
|
||||
error: unexpected `#[link]` argument, expected one of: name, kind, modifiers, cfg, wasm_import_module, import_name_type
|
||||
--> $DIR/link-attr-validation-late.rs:6:22
|
||||
|
|
||||
LL | #[link(name = "...", unknown)]
|
||||
|
@ -26,7 +26,7 @@ LL | #[inline = ""]
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
|
||||
|
||||
error: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...")]`
|
||||
error: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...", /*opt*/ import_name_type = "decorated|noprefix|undecorated")]`
|
||||
--> $DIR/malformed-regressions.rs:7:1
|
||||
|
|
||||
LL | #[link]
|
||||
@ -35,7 +35,7 @@ LL | #[link]
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
|
||||
|
||||
error: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...")]`
|
||||
error: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...", /*opt*/ import_name_type = "decorated|noprefix|undecorated")]`
|
||||
--> $DIR/malformed-regressions.rs:9:1
|
||||
|
|
||||
LL | #[link = ""]
|
||||
|
@ -0,0 +1,10 @@
|
||||
// only-windows
|
||||
// only-x86
|
||||
#![feature(raw_dylib)]
|
||||
//~^ WARN the feature `raw_dylib` is incomplete
|
||||
|
||||
#[link(name = "foo", kind = "raw-dylib", import_name_type = 6)]
|
||||
//~^ ERROR import name type must be of the form `import_name_type = "string"`
|
||||
extern "C" { }
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,17 @@
|
||||
warning: the feature `raw_dylib` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/import-name-type-invalid-format.rs:3:12
|
||||
|
|
||||
LL | #![feature(raw_dylib)]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
= note: see issue #58713 <https://github.com/rust-lang/rust/issues/58713> for more information
|
||||
|
||||
error: import name type must be of the form `import_name_type = "string"`
|
||||
--> $DIR/import-name-type-invalid-format.rs:6:42
|
||||
|
|
||||
LL | #[link(name = "foo", kind = "raw-dylib", import_name_type = 6)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
11
src/test/ui/rfc-2627-raw-dylib/import-name-type-multiple.rs
Normal file
11
src/test/ui/rfc-2627-raw-dylib/import-name-type-multiple.rs
Normal file
@ -0,0 +1,11 @@
|
||||
// ignore-tidy-linelength
|
||||
// only-windows
|
||||
// only-x86
|
||||
#![feature(raw_dylib)]
|
||||
//~^ WARN the feature `raw_dylib` is incomplete
|
||||
|
||||
#[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated", import_name_type = "decorated")]
|
||||
//~^ ERROR multiple `import_name_type` arguments in a single `#[link]` attribute
|
||||
extern "C" { }
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,17 @@
|
||||
warning: the feature `raw_dylib` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/import-name-type-multiple.rs:4:12
|
||||
|
|
||||
LL | #![feature(raw_dylib)]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
= note: see issue #58713 <https://github.com/rust-lang/rust/issues/58713> for more information
|
||||
|
||||
error: multiple `import_name_type` arguments in a single `#[link]` attribute
|
||||
--> $DIR/import-name-type-multiple.rs:7:74
|
||||
|
|
||||
LL | #[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated", import_name_type = "decorated")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
@ -0,0 +1,10 @@
|
||||
// only-windows
|
||||
// only-x86
|
||||
#![feature(raw_dylib)]
|
||||
//~^ WARN the feature `raw_dylib` is incomplete
|
||||
|
||||
#[link(name = "foo", kind = "raw-dylib", import_name_type = "unknown")]
|
||||
//~^ ERROR unknown import name type `unknown`, expected one of: decorated, noprefix, undecorated
|
||||
extern "C" { }
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,17 @@
|
||||
warning: the feature `raw_dylib` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/import-name-type-unknown-value.rs:3:12
|
||||
|
|
||||
LL | #![feature(raw_dylib)]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
= note: see issue #58713 <https://github.com/rust-lang/rust/issues/58713> for more information
|
||||
|
||||
error: unknown import name type `unknown`, expected one of: decorated, noprefix, undecorated
|
||||
--> $DIR/import-name-type-unknown-value.rs:6:42
|
||||
|
|
||||
LL | #[link(name = "foo", kind = "raw-dylib", import_name_type = "unknown")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
@ -0,0 +1,18 @@
|
||||
// only-windows
|
||||
// only-x86
|
||||
#![feature(raw_dylib)]
|
||||
//~^ WARN the feature `raw_dylib` is incomplete
|
||||
|
||||
#[link(name = "foo", import_name_type = "decorated")]
|
||||
//~^ ERROR import name type can only be used with link kind `raw-dylib`
|
||||
extern "C" { }
|
||||
|
||||
#[link(name = "bar", kind = "static", import_name_type = "decorated")]
|
||||
//~^ ERROR import name type can only be used with link kind `raw-dylib`
|
||||
extern "C" { }
|
||||
|
||||
// Specifying `import_name_type` before `kind` shouldn't raise an error.
|
||||
#[link(name = "bar", import_name_type = "decorated", kind = "raw-dylib")]
|
||||
extern "C" { }
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,23 @@
|
||||
warning: the feature `raw_dylib` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/import-name-type-unsupported-link-kind.rs:3:12
|
||||
|
|
||||
LL | #![feature(raw_dylib)]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
= note: see issue #58713 <https://github.com/rust-lang/rust/issues/58713> for more information
|
||||
|
||||
error: import name type can only be used with link kind `raw-dylib`
|
||||
--> $DIR/import-name-type-unsupported-link-kind.rs:6:22
|
||||
|
|
||||
LL | #[link(name = "foo", import_name_type = "decorated")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: import name type can only be used with link kind `raw-dylib`
|
||||
--> $DIR/import-name-type-unsupported-link-kind.rs:10:39
|
||||
|
|
||||
LL | #[link(name = "bar", kind = "static", import_name_type = "decorated")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors; 1 warning emitted
|
||||
|
@ -0,0 +1,9 @@
|
||||
// only-windows
|
||||
// ignore-x86
|
||||
#![feature(raw_dylib)]
|
||||
//~^ WARN the feature `raw_dylib` is incomplete
|
||||
#[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated")]
|
||||
//~^ ERROR import name type is only supported on x86
|
||||
extern "C" { }
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,17 @@
|
||||
warning: the feature `raw_dylib` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/import-name-type-x86-only.rs:3:12
|
||||
|
|
||||
LL | #![feature(raw_dylib)]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
= note: see issue #58713 <https://github.com/rust-lang/rust/issues/58713> for more information
|
||||
|
||||
error: import name type is only supported on x86
|
||||
--> $DIR/import-name-type-x86-only.rs:5:42
|
||||
|
|
||||
LL | #[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
Loading…
Reference in New Issue
Block a user