Skip to content

Commit b480b82

Browse files
committed
Allow #[link(kind = "dylib")] without a name
1 parent bfab34a commit b480b82

File tree

12 files changed

+128
-55
lines changed

12 files changed

+128
-55
lines changed

compiler/rustc_codegen_llvm/src/callee.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,7 @@ pub(crate) fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'t
142142
// MinGW: For backward compatibility we rely on the linker to decide whether it
143143
// should use dllimport for functions.
144144
if cx.use_dll_storage_attrs
145-
&& let Some(library) = tcx.native_library(instance_def_id)
146-
&& library.kind.is_dllimport()
145+
&& tcx.is_dllimport(instance_def_id)
147146
&& !matches!(tcx.sess.target.env.as_ref(), "gnu" | "uclibc")
148147
{
149148
llvm::LLVMSetDLLStorageClass(llfn, llvm::DLLStorageClass::DllImport);

compiler/rustc_codegen_llvm/src/consts.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -358,10 +358,7 @@ impl<'ll> CodegenCx<'ll, '_> {
358358
}
359359
}
360360

361-
if self.use_dll_storage_attrs
362-
&& let Some(library) = self.tcx.native_library(def_id)
363-
&& library.kind.is_dllimport()
364-
{
361+
if self.use_dll_storage_attrs && self.tcx.is_dllimport(def_id) {
365362
// For foreign (native) libs we know the exact storage type to use.
366363
unsafe {
367364
llvm::LLVMSetDLLStorageClass(g, llvm::DLLStorageClass::DllImport);

compiler/rustc_feature/src/unstable.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,8 @@ declare_features! (
377377
(unstable, async_fn_track_caller, "1.73.0", Some(110011)),
378378
/// Allows `for await` loops.
379379
(unstable, async_for_loop, "1.77.0", Some(118898)),
380+
/// Allows `#[link(kind = "dylib")]` without a library name.
381+
(unstable, bare_link_kind, "CURRENT_RUSTC_VERSION", None),
380382
/// Allows using C-variadics.
381383
(unstable, c_variadic, "1.34.0", Some(44930)),
382384
/// Allows the use of `#[cfg(<true/false>)]`.

compiler/rustc_metadata/src/native_libs.rs

Lines changed: 54 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ use rustc_middle::ty::{List, ParamEnv, ParamEnvAnd, Ty, TyCtxt};
99
use rustc_session::Session;
1010
use rustc_session::config::CrateType;
1111
use rustc_session::cstore::{
12-
DllCallingConvention, DllImport, ForeignModule, NativeLib, PeImportNameType,
12+
DllCallingConvention, DllImport, ForeignModule, NativeLib, NativeLibs, PeImportNameType,
1313
};
1414
use rustc_session::parse::feature_err;
1515
use rustc_session::search_paths::PathKind;
1616
use rustc_session::utils::NativeLibKind;
1717
use rustc_span::def_id::{DefId, LOCAL_CRATE};
18-
use rustc_span::symbol::{Symbol, sym};
18+
use rustc_span::symbol::{Symbol, kw, sym};
1919
use rustc_target::spec::LinkSelfContainedComponents;
2020
use rustc_target::spec::abi::Abi;
2121

@@ -173,15 +173,15 @@ fn find_bundled_library(
173173
None
174174
}
175175

176-
pub(crate) fn collect(tcx: TyCtxt<'_>, LocalCrate: LocalCrate) -> Vec<NativeLib> {
176+
pub(crate) fn collect(tcx: TyCtxt<'_>, LocalCrate: LocalCrate) -> NativeLibs {
177177
let mut collector = Collector { tcx, libs: Vec::new() };
178178
if tcx.sess.opts.unstable_opts.link_directives {
179179
for module in tcx.foreign_modules(LOCAL_CRATE).values() {
180180
collector.process_module(module);
181181
}
182182
}
183183
collector.process_command_line();
184-
collector.libs
184+
collector.libs.into()
185185
}
186186

187187
pub(crate) fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool {
@@ -191,6 +191,20 @@ pub(crate) fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool {
191191
}
192192
}
193193

194+
pub(crate) fn find_by_id<'a, I: Iterator<Item = &'a NativeLib>>(
195+
tcx: TyCtxt<'_>,
196+
id: DefId,
197+
iter: I,
198+
) -> Option<&'a NativeLib> {
199+
iter.filter(|lib| relevant_lib(tcx.sess, lib)).find(|lib| {
200+
let Some(fm_id) = lib.foreign_module else {
201+
return false;
202+
};
203+
let map = tcx.foreign_modules(id.krate);
204+
map.get(&fm_id).expect("failed to find foreign module").foreign_items.contains(&id)
205+
})
206+
}
207+
194208
struct Collector<'tcx> {
195209
tcx: TyCtxt<'tcx>,
196210
libs: Vec<NativeLib>,
@@ -445,10 +459,6 @@ impl<'tcx> Collector<'tcx> {
445459
if wasm_import_module.is_some() {
446460
(name, kind) = (wasm_import_module, Some(NativeLibKind::WasmImportModule));
447461
}
448-
let Some((name, name_span)) = name else {
449-
sess.dcx().emit_err(errors::LinkRequiresName { span: m.span });
450-
continue;
451-
};
452462

453463
// Do this outside of the loop so that `import_name_type` can be specified before `kind`.
454464
if let Some((_, span)) = import_name_type {
@@ -457,8 +467,25 @@ impl<'tcx> Collector<'tcx> {
457467
}
458468
}
459469

470+
if kind != Some(NativeLibKind::RawDylib) {
471+
for &child_item in foreign_items {
472+
if self.tcx.def_kind(child_item).has_codegen_attrs()
473+
&& self.tcx.codegen_fn_attrs(child_item).link_ordinal.is_some()
474+
{
475+
let link_ordinal_attr =
476+
self.tcx.get_attr(child_item, sym::link_ordinal).unwrap();
477+
sess.dcx()
478+
.emit_err(errors::LinkOrdinalRawDylib { span: link_ordinal_attr.span });
479+
}
480+
}
481+
}
482+
460483
let dll_imports = match kind {
461484
Some(NativeLibKind::RawDylib) => {
485+
let Some((name, name_span)) = name else {
486+
sess.dcx().emit_err(errors::LinkRequiresName { span: m.span });
487+
continue;
488+
};
462489
if name.as_str().contains('\0') {
463490
sess.dcx().emit_err(errors::RawDylibNoNul { span: name_span });
464491
}
@@ -473,25 +500,29 @@ impl<'tcx> Collector<'tcx> {
473500
})
474501
.collect()
475502
}
476-
_ => {
477-
for &child_item in foreign_items {
478-
if self.tcx.def_kind(child_item).has_codegen_attrs()
479-
&& self.tcx.codegen_fn_attrs(child_item).link_ordinal.is_some()
480-
{
481-
let link_ordinal_attr =
482-
self.tcx.get_attr(child_item, sym::link_ordinal).unwrap();
483-
sess.dcx().emit_err(errors::LinkOrdinalRawDylib {
484-
span: link_ordinal_attr.span,
485-
});
486-
}
487-
}
503+
_ => Vec::new(),
504+
};
488505

489-
Vec::new()
490-
}
506+
// Allow kind of "dylib" or "static" without adding a native lib.
507+
let name = if self.tcx.features().bare_link_kind
508+
&& matches!(kind, Some(NativeLibKind::Dylib { .. } | NativeLibKind::Static { .. }))
509+
&& items.len() == 1
510+
{
511+
kw::Empty
512+
} else {
513+
let Some((name, _)) = name else {
514+
sess.dcx().emit_err(errors::LinkRequiresName { span: m.span });
515+
continue;
516+
};
517+
name
491518
};
492519

493520
let kind = kind.unwrap_or(NativeLibKind::Unspecified);
494-
let filename = find_bundled_library(name, verbatim, kind, cfg.is_some(), self.tcx);
521+
let filename = if !name.is_empty() {
522+
find_bundled_library(name, verbatim, kind, cfg.is_some(), self.tcx)
523+
} else {
524+
None
525+
};
495526
self.libs.push(NativeLib {
496527
name,
497528
filename,

compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use rustc_middle::ty::fast_reject::SimplifiedType;
1717
use rustc_middle::ty::{self, TyCtxt};
1818
use rustc_middle::util::Providers;
1919
use rustc_session::cstore::{CrateStore, ExternCrate};
20+
use rustc_session::utils::NativeLibKind;
2021
use rustc_session::{Session, StableCrateId};
2122
use rustc_span::Span;
2223
use rustc_span::hygiene::ExpnId;
@@ -437,30 +438,27 @@ provide! { tcx, def_id, other, cdata,
437438

438439
pub(in crate::rmeta) fn provide(providers: &mut Providers) {
439440
provide_cstore_hooks(providers);
440-
// FIXME(#44234) - almost all of these queries have no sub-queries and
441-
// therefore no actual inputs, they're just reading tables calculated in
442-
// resolve! Does this work? Unsure! That's what the issue is about
443441
providers.queries = rustc_middle::query::Providers {
444442
allocator_kind: |tcx, ()| CStore::from_tcx(tcx).allocator_kind(),
445443
alloc_error_handler_kind: |tcx, ()| CStore::from_tcx(tcx).alloc_error_handler_kind(),
446444
is_private_dep: |_tcx, LocalCrate| false,
447445
native_library: |tcx, id| {
448-
tcx.native_libraries(id.krate)
449-
.iter()
450-
.filter(|lib| native_libs::relevant_lib(tcx.sess, lib))
451-
.find(|lib| {
452-
let Some(fm_id) = lib.foreign_module else {
453-
return false;
454-
};
455-
let map = tcx.foreign_modules(id.krate);
456-
map.get(&fm_id)
457-
.expect("failed to find foreign module")
458-
.foreign_items
459-
.contains(&id)
460-
})
446+
native_libs::find_by_id(tcx, id, tcx.native_libraries(id.krate).iter())
461447
},
462448
native_libraries: native_libs::collect,
463449
foreign_modules: foreign_modules::collect,
450+
is_dllimport: |tcx, id| {
451+
native_libs::find_by_id(tcx, id, tcx.native_libraries(id.krate).iter_all_items())
452+
.map(|l| {
453+
matches!(
454+
l.kind,
455+
NativeLibKind::Dylib { .. }
456+
| NativeLibKind::RawDylib
457+
| NativeLibKind::Unspecified
458+
)
459+
})
460+
.unwrap_or(false)
461+
},
464462

465463
// Returns a map from a sufficiently visible external item (i.e., an
466464
// external item that is visible from at least one local module) to a

compiler/rustc_metadata/src/rmeta/encoder.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1813,7 +1813,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
18131813
fn encode_native_libraries(&mut self) -> LazyArray<NativeLib> {
18141814
empty_proc_macro!(self);
18151815
let used_libraries = self.tcx.native_libraries(LOCAL_CRATE);
1816-
self.lazy_array(used_libraries.iter())
1816+
self.lazy_array(used_libraries.iter_all_items())
18171817
}
18181818

18191819
fn encode_foreign_modules(&mut self) -> LazyArray<ForeignModule> {

compiler/rustc_middle/src/query/mod.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ use rustc_query_system::query::{QueryCache, QueryMode, QueryState, try_get_cache
3535
use rustc_session::Limits;
3636
use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
3737
use rustc_session::cstore::{
38-
CrateDepKind, CrateSource, ExternCrate, ForeignModule, LinkagePreference, NativeLib,
38+
CrateDepKind, CrateSource, ExternCrate, ForeignModule, LinkagePreference, NativeLib, NativeLibs,
3939
};
4040
use rustc_session::lint::LintExpectationId;
4141
use rustc_span::def_id::LOCAL_CRATE;
@@ -406,7 +406,7 @@ rustc_queries! {
406406
/// These are assembled from the following places:
407407
/// - `extern` blocks (depending on their `link` attributes)
408408
/// - the `libs` (`-l`) option
409-
query native_libraries(_: CrateNum) -> &'tcx Vec<NativeLib> {
409+
query native_libraries(_: CrateNum) -> &'tcx NativeLibs {
410410
arena_cache
411411
desc { "looking up the native libraries of a linked crate" }
412412
separate_provide_extern
@@ -1734,6 +1734,10 @@ rustc_queries! {
17341734
desc { |tcx| "getting the native library for `{}`", tcx.def_path_str(def_id) }
17351735
}
17361736

1737+
query is_dllimport(def_id: DefId) -> bool {
1738+
desc { |tcx| "determining dllimport status of `{}`", tcx.def_path_str(def_id) }
1739+
}
1740+
17371741
query inherit_sig_for_delegation_item(def_id: LocalDefId) -> &'tcx [Ty<'tcx>] {
17381742
desc { "inheriting delegation signature" }
17391743
}

compiler/rustc_session/src/cstore.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,31 @@ impl NativeLib {
8888
}
8989
}
9090

91+
#[derive(Debug, HashStable_Generic)] // Encodable, Decodable,
92+
pub struct NativeLibs {
93+
libs: Vec<NativeLib>,
94+
}
95+
impl NativeLibs {
96+
pub fn iter(&self) -> impl Iterator<Item = &NativeLib> {
97+
// Hide entries without a library name.
98+
self.iter_all_items().filter(|l| !l.name.is_empty())
99+
}
100+
101+
pub fn iter_all_items(&self) -> impl Iterator<Item = &NativeLib> {
102+
self.libs.iter()
103+
}
104+
}
105+
impl From<Vec<NativeLib>> for NativeLibs {
106+
fn from(libs: Vec<NativeLib>) -> Self {
107+
Self { libs }
108+
}
109+
}
110+
impl FromIterator<NativeLib> for NativeLibs {
111+
fn from_iter<T: IntoIterator<Item = NativeLib>>(iter: T) -> Self {
112+
Self { libs: FromIterator::from_iter(iter) }
113+
}
114+
}
115+
91116
/// Different ways that the PE Format can decorate a symbol name.
92117
/// From <https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#import-name-type>
93118
#[derive(Copy, Clone, Debug, Encodable, Decodable, HashStable_Generic, PartialEq, Eq)]

compiler/rustc_session/src/utils.rs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -70,13 +70,6 @@ impl NativeLibKind {
7070
pub fn is_statically_included(&self) -> bool {
7171
matches!(self, NativeLibKind::Static { .. })
7272
}
73-
74-
pub fn is_dllimport(&self) -> bool {
75-
matches!(
76-
self,
77-
NativeLibKind::Dylib { .. } | NativeLibKind::RawDylib | NativeLibKind::Unspecified
78-
)
79-
}
8073
}
8174

8275
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)]

compiler/rustc_span/src/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,7 @@ symbols! {
490490
avx512f,
491491
await_macro,
492492
bang,
493+
bare_link_kind,
493494
begin_panic,
494495
bench,
495496
bin,

0 commit comments

Comments
 (0)