Implementation of import_name_type
This commit is contained in:
parent
42fa8ac723
commit
cc49c3e582
31 changed files with 614 additions and 46 deletions
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue