Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 39 additions & 13 deletions compiler/rustc_codegen_ssa/src/back/link/raw_dylib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use rustc_data_structures::stable_hasher::StableHasher;
use rustc_hashes::Hash128;
use rustc_hir::attrs::NativeLibKind;
use rustc_session::Session;
use rustc_session::cstore::DllImport;
use rustc_session::cstore::{DllImport, DllImportSymbolType};
use rustc_span::Symbol;
use rustc_target::spec::Arch;

Expand Down Expand Up @@ -95,14 +95,14 @@ pub(super) fn create_raw_dylib_dll_import_libs<'a>(
true,
)
}),
is_data: !import.is_fn,
is_data: import.symbol_type != DllImportSymbolType::Function,
}
} else {
ImportLibraryItem {
name: import.name.to_string(),
ordinal: import.ordinal(),
symbol_name: None,
is_data: !import.is_fn,
is_data: import.symbol_type != DllImportSymbolType::Function,
}
}
})
Expand Down Expand Up @@ -271,10 +271,10 @@ fn create_elf_raw_dylib_stub(sess: &Session, soname: &str, symbols: &[DllImport]
vers.push((version_name, dynstr));
id
};
syms.push((name, dynstr, Some(ver), symbol.is_fn));
syms.push((name, dynstr, Some(ver), symbol.symbol_type, symbol.size));
} else {
let dynstr = stub.add_dynamic_string(symbol_name.as_bytes());
syms.push((symbol_name, dynstr, None, symbol.is_fn));
syms.push((symbol_name, dynstr, None, symbol.symbol_type, symbol.size));
}
}

Expand All @@ -296,6 +296,8 @@ fn create_elf_raw_dylib_stub(sess: &Session, soname: &str, symbols: &[DllImport]
stub.reserve_shstrtab_section_index();
let text_section_name = stub.add_section_name(".text".as_bytes());
let text_section = stub.reserve_section_index();
let data_section_name = stub.add_section_name(".data".as_bytes());
let data_section = stub.reserve_section_index();
stub.reserve_dynsym_section_index();
stub.reserve_dynstr_section_index();
if !vers.is_empty() {
Expand Down Expand Up @@ -375,7 +377,7 @@ fn create_elf_raw_dylib_stub(sess: &Session, soname: &str, symbols: &[DllImport]
// Section headers
stub.write_null_section_header();
stub.write_shstrtab_section_header();
// Create a dummy .text section for our dummy symbols.
// Create a dummy .text section for our dummy non-data symbols.
stub.write_section_header(&write::SectionHeader {
name: Some(text_section_name),
sh_type: elf::SHT_PROGBITS,
Expand All @@ -385,7 +387,20 @@ fn create_elf_raw_dylib_stub(sess: &Session, soname: &str, symbols: &[DllImport]
sh_size: 0,
sh_link: 0,
sh_info: 0,
sh_addralign: 1,
sh_addralign: 16,
sh_entsize: 0,
});
// And also a dummy .data section for our dummy data symbols.
stub.write_section_header(&write::SectionHeader {
name: Some(data_section_name),
sh_type: elf::SHT_PROGBITS,
sh_flags: (elf::SHF_WRITE | elf::SHF_ALLOC) as u64,
sh_addr: 0,
sh_offset: 0,
sh_size: 0,
sh_link: 0,
sh_info: 0,
sh_addralign: 16,
sh_entsize: 0,
});
stub.write_dynsym_section_header(0, 1);
Expand All @@ -398,17 +413,28 @@ fn create_elf_raw_dylib_stub(sess: &Session, soname: &str, symbols: &[DllImport]

// .dynsym
stub.write_null_dynamic_symbol();
for (_name, dynstr, _ver, is_fn) in syms.iter().copied() {
let sym_type = if is_fn { elf::STT_FUNC } else { elf::STT_NOTYPE };
// Linkers like LLD require at least somewhat reasonable symbol values rather than zero,
// otherwise all the symbols might get put at the same address. Thus we increment the value
// every time we write a symbol.
let mut st_value = 0;
for (_name, dynstr, _ver, symbol_type, size) in syms.iter().copied() {
let sym_type = match symbol_type {
DllImportSymbolType::Function => elf::STT_FUNC,
DllImportSymbolType::Static => elf::STT_OBJECT,
DllImportSymbolType::ThreadLocal => elf::STT_TLS,
};
let section =
if symbol_type == DllImportSymbolType::Static { data_section } else { text_section };
stub.write_dynamic_symbol(&write::Sym {
name: Some(dynstr),
st_info: (elf::STB_GLOBAL << 4) | sym_type,
st_other: elf::STV_DEFAULT,
section: Some(text_section),
section: Some(section),
st_shndx: 0, // ignored by object in favor of the `section` field
st_value: 0,
st_size: 0,
st_value,
st_size: size.bytes(),
});
st_value += 8;
}

// .dynstr
Expand All @@ -418,7 +444,7 @@ fn create_elf_raw_dylib_stub(sess: &Session, soname: &str, symbols: &[DllImport]
if !vers.is_empty() {
// .gnu_version
stub.write_null_gnu_versym();
for (_name, _dynstr, ver, _is_fn) in syms.iter().copied() {
for (_name, _dynstr, ver, _symbol_type, _size) in syms.iter().copied() {
stub.write_gnu_versym(if let Some(ver) = ver {
assert!((2 + ver as u16) < elf::VERSYM_HIDDEN);
elf::VERSYM_HIDDEN | (2 + ver as u16)
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_codegen_ssa/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use rustc_hir::attrs::PeImportNameType;
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};
use rustc_session::cstore::{DllCallingConvention, DllImport, DllImportSymbolType};
use rustc_span::Span;
use rustc_target::spec::{Abi, Env, Os, Target};

Expand Down Expand Up @@ -199,15 +199,15 @@ pub fn i686_decorated_name(
decorated_name.push('\x01');
}

let prefix = if add_prefix && dll_import.is_fn {
let prefix = if add_prefix && dll_import.symbol_type == DllImportSymbolType::Function {
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 {
} else if dll_import.symbol_type != DllImportSymbolType::Function && !mingw {
// For static variables, prefix with '_' on MSVC.
Some('_')
} else {
Expand All @@ -219,7 +219,7 @@ pub fn i686_decorated_name(

decorated_name.push_str(name);

if add_suffix && dll_import.is_fn {
if add_suffix && dll_import.symbol_type == DllImportSymbolType::Function {
use std::fmt::Write;

match dll_import.calling_convention {
Expand Down
41 changes: 33 additions & 8 deletions compiler/rustc_metadata/src/native_libs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,17 @@ use rustc_abi::ExternAbi;
use rustc_attr_parsing::eval_config_entry;
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::attrs::{NativeLibKind, PeImportNameType};
use rustc_hir::def::DefKind;
use rustc_hir::find_attr;
use rustc_middle::bug;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::query::LocalCrate;
use rustc_middle::ty::{self, List, Ty, TyCtxt};
use rustc_session::Session;
use rustc_session::config::CrateType;
use rustc_session::cstore::{DllCallingConvention, DllImport, ForeignModule, NativeLib};
use rustc_session::cstore::{
DllCallingConvention, DllImport, DllImportSymbolType, ForeignModule, NativeLib,
};
use rustc_session::search_paths::PathKind;
use rustc_span::Symbol;
use rustc_span::def_id::{DefId, LOCAL_CRATE};
Expand Down Expand Up @@ -451,12 +456,32 @@ impl<'tcx> Collector<'tcx> {
}
}

DllImport {
name,
import_name_type,
calling_convention,
span,
is_fn: self.tcx.def_kind(item).is_fn_like(),
}
let def_kind = self.tcx.def_kind(item);
let symbol_type = if def_kind.is_fn_like() {
DllImportSymbolType::Function
} else if matches!(def_kind, DefKind::Static { .. }) {
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL) {
DllImportSymbolType::ThreadLocal
} else {
DllImportSymbolType::Static
}
} else {
bug!("Unexpected type for raw-dylib: {}", def_kind.descr(item));
};

let size = match symbol_type {
// We cannot determine the size of a function at compile time, but it shouldn't matter anyway.
DllImportSymbolType::Function => rustc_abi::Size::ZERO,
DllImportSymbolType::Static | DllImportSymbolType::ThreadLocal => {
let ty = self.tcx.type_of(item).instantiate_identity();
self.tcx
.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty))
.ok()
.map(|layout| layout.size)
.unwrap_or_else(|| bug!("Non-function symbols must have a size"))
}
};

DllImport { name, import_name_type, calling_convention, span, symbol_type, size }
}
}
70 changes: 70 additions & 0 deletions compiler/rustc_middle/src/query/into_query_key.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
use rustc_hir::OwnerId;
use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId, ModDefId};

/// Argument-conversion trait used by some queries and other `TyCtxt` methods.
///
/// A function that accepts an `impl IntoQueryKey<DefId>` argument can be thought
/// of as taking a [`DefId`], except that callers can also pass a [`LocalDefId`]
/// or values of other narrower ID types, as long as they have a trivial conversion
/// to `DefId`.
///
/// Using a dedicated trait instead of [`Into`] makes the purpose of the conversion
/// more explicit, and makes occurrences easier to search for.
pub trait IntoQueryKey<K> {
/// Argument conversion from `Self` to `K`.
/// This should always be a very cheap conversion, e.g. [`LocalDefId::to_def_id`].
fn into_query_key(self) -> K;
}

/// Any type can be converted to itself.
///
/// This is useful in generic or macro-generated code where we don't know whether
/// conversion is actually needed, so that we can do a conversion unconditionally.
impl<K> IntoQueryKey<K> for K {
#[inline(always)]
fn into_query_key(self) -> K {
self
}
}

impl IntoQueryKey<LocalDefId> for OwnerId {
#[inline(always)]
fn into_query_key(self) -> LocalDefId {
self.def_id
}
}

impl IntoQueryKey<DefId> for LocalDefId {
#[inline(always)]
fn into_query_key(self) -> DefId {
self.to_def_id()
}
}

impl IntoQueryKey<DefId> for OwnerId {
#[inline(always)]
fn into_query_key(self) -> DefId {
self.to_def_id()
}
}

impl IntoQueryKey<DefId> for ModDefId {
#[inline(always)]
fn into_query_key(self) -> DefId {
self.to_def_id()
}
}

impl IntoQueryKey<DefId> for LocalModDefId {
#[inline(always)]
fn into_query_key(self) -> DefId {
self.to_def_id()
}
}

impl IntoQueryKey<LocalDefId> for LocalModDefId {
#[inline(always)]
fn into_query_key(self) -> LocalDefId {
self.into()
}
}
6 changes: 4 additions & 2 deletions compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use rustc_hir::def_id::LocalDefId;

pub use self::caches::{DefIdCache, DefaultCache, QueryCache, SingleCache, VecCache};
pub use self::into_query_key::IntoQueryKey;
pub use self::job::{QueryJob, QueryJobId, QueryLatch, QueryWaiter};
pub use self::keys::{AsLocalQueryKey, LocalCrate, QueryKey};
pub use self::plumbing::{
ActiveKeyStatus, CycleError, EnsureMode, IntoQueryParam, QueryMode, QueryState, QuerySystem,
QueryVTable, TyCtxtAt, TyCtxtEnsureDone, TyCtxtEnsureOk, TyCtxtEnsureResult,
ActiveKeyStatus, CycleError, EnsureMode, QueryMode, QueryState, QuerySystem, QueryVTable,
TyCtxtAt, TyCtxtEnsureDone, TyCtxtEnsureOk, TyCtxtEnsureResult,
};
pub use self::stack::QueryStackFrame;
pub use crate::queries::Providers;
Expand All @@ -15,6 +16,7 @@ pub(crate) mod arena_cached;
mod caches;
pub mod erase;
pub(crate) mod inner;
mod into_query_key;
mod job;
mod keys;
pub(crate) mod modifiers;
Expand Down
Loading
Loading