]>
Commit | Line | Data |
---|---|---|
923072b8 | 1 | use rustc_ast::{NestedMetaItem, CRATE_NODE_ID}; |
74b04a01 | 2 | use rustc_attr as attr; |
dfeec247 | 3 | use rustc_data_structures::fx::FxHashSet; |
dfeec247 | 4 | use rustc_hir as hir; |
04454e1e | 5 | use rustc_hir::def::DefKind; |
136023e0 | 6 | use rustc_middle::ty::{List, ParamEnv, ParamEnvAnd, Ty, TyCtxt}; |
f2b60f7d FG |
7 | use rustc_session::config::CrateType; |
8 | use rustc_session::cstore::{DllCallingConvention, DllImport, NativeLib, PeImportNameType}; | |
ba9703b0 | 9 | use rustc_session::parse::feature_err; |
f2b60f7d | 10 | use rustc_session::search_paths::PathKind; |
f9f354fc | 11 | use rustc_session::utils::NativeLibKind; |
ba9703b0 | 12 | use rustc_session::Session; |
923072b8 | 13 | use rustc_span::symbol::{sym, Symbol}; |
83c7162d | 14 | use rustc_target::spec::abi::Abi; |
60c5eb7d | 15 | |
f2b60f7d FG |
16 | use crate::errors::{ |
17 | AsNeededCompatibility, BundleNeedsStatic, EmptyLinkName, EmptyRenamingTarget, | |
18 | FrameworkOnlyWindows, ImportNameTypeForm, ImportNameTypeRaw, ImportNameTypeX86, | |
19 | IncompatibleWasmLink, InvalidLinkModifier, LibFrameworkApple, LinkCfgForm, | |
20 | LinkCfgSinglePredicate, LinkFrameworkApple, LinkKindForm, LinkModifiersForm, LinkNameForm, | |
21 | LinkOrdinalRawDylib, LinkRequiresName, MissingNativeLibrary, MultipleCfgs, | |
22 | MultipleImportNameType, MultipleKindsInLink, MultipleLinkModifiers, MultipleModifiers, | |
23 | MultipleNamesInLink, MultipleRenamings, MultipleWasmImport, NoLinkModOverride, RawDylibNoNul, | |
24 | RenamingNoLink, UnexpectedLinkArg, UnknownImportNameType, UnknownLinkKind, UnknownLinkModifier, | |
25 | UnsupportedAbi, UnsupportedAbiI686, WasmImportForm, WholeArchiveNeedsStatic, | |
26 | }; | |
27 | ||
28 | use std::path::PathBuf; | |
29 | ||
30 | pub fn find_native_static_library( | |
31 | name: &str, | |
487cf647 | 32 | verbatim: bool, |
f2b60f7d FG |
33 | search_paths: &[PathBuf], |
34 | sess: &Session, | |
35 | ) -> PathBuf { | |
487cf647 | 36 | let formats = if verbatim { |
2b03887a | 37 | vec![("".into(), "".into())] |
f2b60f7d | 38 | } else { |
2b03887a FG |
39 | let os = (sess.target.staticlib_prefix.clone(), sess.target.staticlib_suffix.clone()); |
40 | // On Windows, static libraries sometimes show up as libfoo.a and other | |
41 | // times show up as foo.lib | |
42 | let unix = ("lib".into(), ".a".into()); | |
43 | if os == unix { vec![os] } else { vec![os, unix] } | |
f2b60f7d | 44 | }; |
f2b60f7d FG |
45 | |
46 | for path in search_paths { | |
2b03887a | 47 | for (prefix, suffix) in &formats { |
9c376795 | 48 | let test = path.join(format!("{prefix}{name}{suffix}")); |
f2b60f7d FG |
49 | if test.exists() { |
50 | return test; | |
51 | } | |
52 | } | |
53 | } | |
2b03887a | 54 | |
487cf647 | 55 | sess.emit_fatal(MissingNativeLibrary::new(name, verbatim)); |
f2b60f7d FG |
56 | } |
57 | ||
58 | fn find_bundled_library( | |
59 | name: Option<Symbol>, | |
60 | verbatim: Option<bool>, | |
61 | kind: NativeLibKind, | |
62 | sess: &Session, | |
63 | ) -> Option<Symbol> { | |
64 | if sess.opts.unstable_opts.packed_bundled_libs && | |
65 | sess.crate_types().iter().any(|ct| ct == &CrateType::Rlib || ct == &CrateType::Staticlib) && | |
66 | let NativeLibKind::Static { bundle: Some(true) | None, .. } = kind { | |
67 | find_native_static_library( | |
68 | name.unwrap().as_str(), | |
487cf647 | 69 | verbatim.unwrap_or(false), |
f2b60f7d FG |
70 | &sess.target_filesearch(PathKind::Native).search_path_dirs(), |
71 | sess, | |
72 | ).file_name().and_then(|s| s.to_str()).map(Symbol::intern) | |
73 | } else { | |
74 | None | |
75 | } | |
76 | } | |
77 | ||
923072b8 | 78 | pub(crate) fn collect(tcx: TyCtxt<'_>) -> Vec<NativeLib> { |
dfeec247 | 79 | let mut collector = Collector { tcx, libs: Vec::new() }; |
04454e1e FG |
80 | for id in tcx.hir().items() { |
81 | collector.process_item(id); | |
82 | } | |
ea8adc8c | 83 | collector.process_command_line(); |
ba9703b0 | 84 | collector.libs |
ea8adc8c XL |
85 | } |
86 | ||
923072b8 | 87 | pub(crate) fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool { |
ea8adc8c | 88 | match lib.cfg { |
5e7ed085 | 89 | Some(ref cfg) => attr::cfg_matches(cfg, &sess.parse_sess, CRATE_NODE_ID, None), |
ea8adc8c XL |
90 | None => true, |
91 | } | |
92 | } | |
93 | ||
dc9dc135 XL |
94 | struct Collector<'tcx> { |
95 | tcx: TyCtxt<'tcx>, | |
f9f354fc | 96 | libs: Vec<NativeLib>, |
ea8adc8c XL |
97 | } |
98 | ||
04454e1e FG |
99 | impl<'tcx> Collector<'tcx> { |
100 | fn process_item(&mut self, id: rustc_hir::ItemId) { | |
2b03887a | 101 | if !matches!(self.tcx.def_kind(id.owner_id), DefKind::ForeignMod) { |
04454e1e FG |
102 | return; |
103 | } | |
104 | ||
105 | let it = self.tcx.hir().item(id); | |
5e7ed085 FG |
106 | let hir::ItemKind::ForeignMod { abi, items: foreign_mod_items } = it.kind else { |
107 | return; | |
ea8adc8c XL |
108 | }; |
109 | ||
fc512014 | 110 | if abi == Abi::Rust || abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic { |
dfeec247 | 111 | return; |
ea8adc8c XL |
112 | } |
113 | ||
114 | // Process all of the #[link(..)]-style arguments | |
3dfed10e | 115 | let sess = &self.tcx.sess; |
923072b8 | 116 | let features = self.tcx.features(); |
94222f64 | 117 | for m in self.tcx.hir().attrs(it.hir_id()).iter().filter(|a| a.has_name(sym::link)) { |
5e7ed085 FG |
118 | let Some(items) = m.meta_item_list() else { |
119 | continue; | |
ea8adc8c | 120 | }; |
8faf50e0 | 121 | |
923072b8 FG |
122 | let mut name = None; |
123 | let mut kind = None; | |
124 | let mut modifiers = None; | |
125 | let mut cfg = None; | |
126 | let mut wasm_import_module = None; | |
f2b60f7d | 127 | let mut import_name_type = None; |
8faf50e0 | 128 | for item in items.iter() { |
923072b8 FG |
129 | match item.name_or_empty() { |
130 | sym::name => { | |
131 | if name.is_some() { | |
f2b60f7d | 132 | sess.emit_err(MultipleNamesInLink { span: item.span() }); |
923072b8 | 133 | continue; |
17df50a5 | 134 | } |
923072b8 | 135 | let Some(link_name) = item.value_str() else { |
f2b60f7d | 136 | sess.emit_err(LinkNameForm { span: item.span() }); |
923072b8 FG |
137 | continue; |
138 | }; | |
139 | let span = item.name_value_literal_span().unwrap(); | |
140 | if link_name.is_empty() { | |
f2b60f7d | 141 | sess.emit_err(EmptyLinkName { span }); |
8faf50e0 | 142 | } |
923072b8 | 143 | name = Some((link_name, span)); |
8faf50e0 | 144 | } |
923072b8 FG |
145 | sym::kind => { |
146 | if kind.is_some() { | |
f2b60f7d | 147 | sess.emit_err(MultipleKindsInLink { span: item.span() }); |
923072b8 | 148 | continue; |
8faf50e0 | 149 | } |
923072b8 | 150 | let Some(link_kind) = item.value_str() else { |
f2b60f7d | 151 | sess.emit_err(LinkKindForm { span: item.span() }); |
923072b8 | 152 | continue; |
17df50a5 XL |
153 | }; |
154 | ||
923072b8 FG |
155 | let span = item.name_value_literal_span().unwrap(); |
156 | let link_kind = match link_kind.as_str() { | |
157 | "static" => NativeLibKind::Static { bundle: None, whole_archive: None }, | |
158 | "dylib" => NativeLibKind::Dylib { as_needed: None }, | |
159 | "framework" => { | |
160 | if !sess.target.is_like_osx { | |
f2b60f7d | 161 | sess.emit_err(LinkFrameworkApple { span }); |
5e7ed085 | 162 | } |
923072b8 | 163 | NativeLibKind::Framework { as_needed: None } |
5e7ed085 | 164 | } |
923072b8 FG |
165 | "raw-dylib" => { |
166 | if !sess.target.is_like_windows { | |
f2b60f7d FG |
167 | sess.emit_err(FrameworkOnlyWindows { span }); |
168 | } else if !features.raw_dylib && sess.target.arch == "x86" { | |
923072b8 FG |
169 | feature_err( |
170 | &sess.parse_sess, | |
171 | sym::raw_dylib, | |
172 | span, | |
f2b60f7d | 173 | "link kind `raw-dylib` is unstable on x86", |
923072b8 FG |
174 | ) |
175 | .emit(); | |
5e7ed085 | 176 | } |
923072b8 | 177 | NativeLibKind::RawDylib |
17df50a5 | 178 | } |
923072b8 | 179 | kind => { |
f2b60f7d | 180 | sess.emit_err(UnknownLinkKind { span, kind }); |
923072b8 | 181 | continue; |
5e7ed085 | 182 | } |
923072b8 FG |
183 | }; |
184 | kind = Some(link_kind); | |
185 | } | |
186 | sym::modifiers => { | |
187 | if modifiers.is_some() { | |
f2b60f7d | 188 | sess.emit_err(MultipleLinkModifiers { span: item.span() }); |
923072b8 | 189 | continue; |
17df50a5 | 190 | } |
923072b8 | 191 | let Some(link_modifiers) = item.value_str() else { |
f2b60f7d | 192 | sess.emit_err(LinkModifiersForm { span: item.span() }); |
923072b8 FG |
193 | continue; |
194 | }; | |
195 | modifiers = Some((link_modifiers, item.name_value_literal_span().unwrap())); | |
17df50a5 | 196 | } |
923072b8 FG |
197 | sym::cfg => { |
198 | if cfg.is_some() { | |
f2b60f7d | 199 | sess.emit_err(MultipleCfgs { span: item.span() }); |
923072b8 FG |
200 | continue; |
201 | } | |
202 | let Some(link_cfg) = item.meta_item_list() else { | |
f2b60f7d | 203 | sess.emit_err(LinkCfgForm { span: item.span() }); |
923072b8 FG |
204 | continue; |
205 | }; | |
206 | let [NestedMetaItem::MetaItem(link_cfg)] = link_cfg else { | |
f2b60f7d | 207 | sess.emit_err(LinkCfgSinglePredicate { span: item.span() }); |
923072b8 FG |
208 | continue; |
209 | }; | |
210 | if !features.link_cfg { | |
211 | feature_err( | |
212 | &sess.parse_sess, | |
213 | sym::link_cfg, | |
214 | item.span(), | |
215 | "link cfg is unstable", | |
216 | ) | |
217 | .emit(); | |
218 | } | |
219 | cfg = Some(link_cfg.clone()); | |
220 | } | |
221 | sym::wasm_import_module => { | |
222 | if wasm_import_module.is_some() { | |
f2b60f7d | 223 | sess.emit_err(MultipleWasmImport { span: item.span() }); |
923072b8 FG |
224 | continue; |
225 | } | |
226 | let Some(link_wasm_import_module) = item.value_str() else { | |
f2b60f7d | 227 | sess.emit_err(WasmImportForm { span: item.span() }); |
923072b8 FG |
228 | continue; |
229 | }; | |
230 | wasm_import_module = Some((link_wasm_import_module, item.span())); | |
231 | } | |
f2b60f7d FG |
232 | sym::import_name_type => { |
233 | if import_name_type.is_some() { | |
234 | sess.emit_err(MultipleImportNameType { span: item.span() }); | |
235 | continue; | |
236 | } | |
237 | let Some(link_import_name_type) = item.value_str() else { | |
238 | sess.emit_err(ImportNameTypeForm { span: item.span() }); | |
239 | continue; | |
240 | }; | |
241 | if self.tcx.sess.target.arch != "x86" { | |
242 | sess.emit_err(ImportNameTypeX86 { span: item.span() }); | |
243 | continue; | |
244 | } | |
245 | ||
246 | let link_import_name_type = match link_import_name_type.as_str() { | |
247 | "decorated" => PeImportNameType::Decorated, | |
248 | "noprefix" => PeImportNameType::NoPrefix, | |
249 | "undecorated" => PeImportNameType::Undecorated, | |
250 | import_name_type => { | |
251 | sess.emit_err(UnknownImportNameType { | |
252 | span: item.span(), | |
253 | import_name_type, | |
254 | }); | |
255 | continue; | |
256 | } | |
257 | }; | |
258 | if !features.raw_dylib { | |
259 | let span = item.name_value_literal_span().unwrap(); | |
260 | feature_err( | |
261 | &sess.parse_sess, | |
262 | sym::raw_dylib, | |
263 | span, | |
264 | "import name type is unstable", | |
265 | ) | |
266 | .emit(); | |
267 | } | |
268 | import_name_type = Some((link_import_name_type, item.span())); | |
269 | } | |
923072b8 | 270 | _ => { |
f2b60f7d | 271 | sess.emit_err(UnexpectedLinkArg { span: item.span() }); |
5e7ed085 | 272 | } |
17df50a5 XL |
273 | } |
274 | } | |
275 | ||
923072b8 FG |
276 | // Do this outside the above loop so we don't depend on modifiers coming after kinds |
277 | let mut verbatim = None; | |
278 | if let Some((modifiers, span)) = modifiers { | |
279 | for modifier in modifiers.as_str().split(',') { | |
280 | let (modifier, value) = match modifier.strip_prefix(&['+', '-']) { | |
281 | Some(m) => (m, modifier.starts_with('+')), | |
282 | None => { | |
f2b60f7d | 283 | sess.emit_err(InvalidLinkModifier { span }); |
923072b8 FG |
284 | continue; |
285 | } | |
286 | }; | |
287 | ||
288 | macro report_unstable_modifier($feature: ident) { | |
289 | if !features.$feature { | |
290 | feature_err( | |
291 | &sess.parse_sess, | |
292 | sym::$feature, | |
293 | span, | |
294 | &format!("linking modifier `{modifier}` is unstable"), | |
295 | ) | |
296 | .emit(); | |
297 | } | |
298 | } | |
299 | let assign_modifier = |dst: &mut Option<bool>| { | |
300 | if dst.is_some() { | |
f2b60f7d | 301 | sess.emit_err(MultipleModifiers { span, modifier }); |
923072b8 FG |
302 | } else { |
303 | *dst = Some(value); | |
304 | } | |
305 | }; | |
306 | match (modifier, &mut kind) { | |
307 | ("bundle", Some(NativeLibKind::Static { bundle, .. })) => { | |
308 | assign_modifier(bundle) | |
309 | } | |
310 | ("bundle", _) => { | |
f2b60f7d | 311 | sess.emit_err(BundleNeedsStatic { span }); |
923072b8 FG |
312 | } |
313 | ||
487cf647 | 314 | ("verbatim", _) => assign_modifier(&mut verbatim), |
923072b8 FG |
315 | |
316 | ("whole-archive", Some(NativeLibKind::Static { whole_archive, .. })) => { | |
317 | assign_modifier(whole_archive) | |
318 | } | |
319 | ("whole-archive", _) => { | |
f2b60f7d | 320 | sess.emit_err(WholeArchiveNeedsStatic { span }); |
923072b8 FG |
321 | } |
322 | ||
323 | ("as-needed", Some(NativeLibKind::Dylib { as_needed })) | |
324 | | ("as-needed", Some(NativeLibKind::Framework { as_needed })) => { | |
325 | report_unstable_modifier!(native_link_modifiers_as_needed); | |
326 | assign_modifier(as_needed) | |
327 | } | |
328 | ("as-needed", _) => { | |
f2b60f7d | 329 | sess.emit_err(AsNeededCompatibility { span }); |
923072b8 FG |
330 | } |
331 | ||
332 | _ => { | |
f2b60f7d | 333 | sess.emit_err(UnknownLinkModifier { span, modifier }); |
923072b8 FG |
334 | } |
335 | } | |
336 | } | |
5e7ed085 FG |
337 | } |
338 | ||
923072b8 FG |
339 | if let Some((_, span)) = wasm_import_module { |
340 | if name.is_some() || kind.is_some() || modifiers.is_some() || cfg.is_some() { | |
f2b60f7d | 341 | sess.emit_err(IncompatibleWasmLink { span }); |
923072b8 FG |
342 | } |
343 | } else if name.is_none() { | |
f2b60f7d FG |
344 | sess.emit_err(LinkRequiresName { span: m.span }); |
345 | } | |
346 | ||
347 | // Do this outside of the loop so that `import_name_type` can be specified before `kind`. | |
348 | if let Some((_, span)) = import_name_type { | |
349 | if kind != Some(NativeLibKind::RawDylib) { | |
350 | sess.emit_err(ImportNameTypeRaw { span }); | |
351 | } | |
8faf50e0 | 352 | } |
17df50a5 | 353 | |
923072b8 FG |
354 | let dll_imports = match kind { |
355 | Some(NativeLibKind::RawDylib) => { | |
356 | if let Some((name, span)) = name && name.as_str().contains('\0') { | |
f2b60f7d | 357 | sess.emit_err(RawDylibNoNul { span }); |
923072b8 | 358 | } |
17df50a5 XL |
359 | foreign_mod_items |
360 | .iter() | |
f2b60f7d FG |
361 | .map(|child_item| { |
362 | self.build_dll_import( | |
363 | abi, | |
364 | import_name_type.map(|(import_name_type, _)| import_name_type), | |
365 | child_item, | |
366 | ) | |
367 | }) | |
923072b8 | 368 | .collect() |
ea8adc8c | 369 | } |
f2b60f7d FG |
370 | _ => { |
371 | for child_item in foreign_mod_items { | |
2b03887a | 372 | if self.tcx.def_kind(child_item.id.owner_id).has_codegen_attrs() |
f2b60f7d FG |
373 | && self |
374 | .tcx | |
2b03887a | 375 | .codegen_fn_attrs(child_item.id.owner_id) |
f2b60f7d FG |
376 | .link_ordinal |
377 | .is_some() | |
378 | { | |
379 | let link_ordinal_attr = self | |
380 | .tcx | |
381 | .hir() | |
2b03887a | 382 | .attrs(child_item.id.owner_id.into()) |
f2b60f7d FG |
383 | .iter() |
384 | .find(|a| a.has_name(sym::link_ordinal)) | |
385 | .unwrap(); | |
386 | sess.emit_err(LinkOrdinalRawDylib { span: link_ordinal_attr.span }); | |
387 | } | |
388 | } | |
389 | ||
390 | Vec::new() | |
391 | } | |
17df50a5 | 392 | }; |
f2b60f7d FG |
393 | |
394 | let name = name.map(|(name, _)| name); | |
395 | let kind = kind.unwrap_or(NativeLibKind::Unspecified); | |
396 | let filename = find_bundled_library(name, verbatim, kind, sess); | |
923072b8 | 397 | self.libs.push(NativeLib { |
f2b60f7d FG |
398 | name, |
399 | filename, | |
400 | kind, | |
923072b8 | 401 | cfg, |
2b03887a | 402 | foreign_module: Some(it.owner_id.to_def_id()), |
923072b8 FG |
403 | wasm_import_module: wasm_import_module.map(|(name, _)| name), |
404 | verbatim, | |
405 | dll_imports, | |
406 | }); | |
e74abb32 | 407 | } |
ea8adc8c XL |
408 | } |
409 | ||
410 | // Process libs passed on the command line | |
411 | fn process_command_line(&mut self) { | |
412 | // First, check for errors | |
0bf4aa26 | 413 | let mut renames = FxHashSet::default(); |
17df50a5 | 414 | for lib in &self.tcx.sess.opts.libs { |
923072b8 FG |
415 | if let NativeLibKind::Framework { .. } = lib.kind && !self.tcx.sess.target.is_like_osx { |
416 | // Cannot check this when parsing options because the target is not yet available. | |
f2b60f7d | 417 | self.tcx.sess.emit_err(LibFrameworkApple); |
923072b8 | 418 | } |
17df50a5 | 419 | if let Some(ref new_name) = lib.new_name { |
dfeec247 XL |
420 | let any_duplicate = self |
421 | .libs | |
8faf50e0 XL |
422 | .iter() |
423 | .filter_map(|lib| lib.name.as_ref()) | |
3c0e092e | 424 | .any(|n| n.as_str() == lib.name); |
ea8adc8c | 425 | if new_name.is_empty() { |
f2b60f7d | 426 | self.tcx.sess.emit_err(EmptyRenamingTarget { lib_name: &lib.name }); |
8faf50e0 | 427 | } else if !any_duplicate { |
f2b60f7d | 428 | self.tcx.sess.emit_err(RenamingNoLink { lib_name: &lib.name }); |
17df50a5 | 429 | } else if !renames.insert(&lib.name) { |
f2b60f7d | 430 | self.tcx.sess.emit_err(MultipleRenamings { lib_name: &lib.name }); |
ea8adc8c XL |
431 | } |
432 | } | |
433 | } | |
434 | ||
b7449926 | 435 | // Update kind and, optionally, the name of all native libraries |
9c376795 | 436 | // (there may be more than one) with the specified name. If any |
532ac7d7 XL |
437 | // library is mentioned more than once, keep the latest mention |
438 | // of it, so that any possible dependent libraries appear before | |
9c376795 | 439 | // it. (This ensures that the linker is able to see symbols from |
532ac7d7 XL |
440 | // all possible dependent libraries before linking in the library |
441 | // in question.) | |
17df50a5 | 442 | for passed_lib in &self.tcx.sess.opts.libs { |
532ac7d7 XL |
443 | // If we've already added any native libraries with the same |
444 | // name, they will be pulled out into `existing`, so that we | |
445 | // can move them to the end of the list below. | |
dfeec247 XL |
446 | let mut existing = self |
447 | .libs | |
448 | .drain_filter(|lib| { | |
449 | if let Some(lib_name) = lib.name { | |
17df50a5 | 450 | if lib_name.as_str() == passed_lib.name { |
5e7ed085 FG |
451 | // FIXME: This whole logic is questionable, whether modifiers are |
452 | // involved or not, library reordering and kind overriding without | |
453 | // explicit `:rename` in particular. | |
454 | if lib.has_modifiers() || passed_lib.has_modifiers() { | |
04454e1e | 455 | match lib.foreign_module { |
f2b60f7d FG |
456 | Some(def_id) => self.tcx.sess.emit_err(NoLinkModOverride { |
457 | span: Some(self.tcx.def_span(def_id)), | |
458 | }), | |
459 | None => { | |
460 | self.tcx.sess.emit_err(NoLinkModOverride { span: None }) | |
461 | } | |
04454e1e | 462 | }; |
5e7ed085 | 463 | } |
17df50a5 XL |
464 | if passed_lib.kind != NativeLibKind::Unspecified { |
465 | lib.kind = passed_lib.kind; | |
dfeec247 | 466 | } |
17df50a5 | 467 | if let Some(new_name) = &passed_lib.new_name { |
dfeec247 XL |
468 | lib.name = Some(Symbol::intern(new_name)); |
469 | } | |
17df50a5 | 470 | lib.verbatim = passed_lib.verbatim; |
dfeec247 | 471 | return true; |
532ac7d7 | 472 | } |
ea8adc8c | 473 | } |
dfeec247 XL |
474 | false |
475 | }) | |
476 | .collect::<Vec<_>>(); | |
532ac7d7 | 477 | if existing.is_empty() { |
ea8adc8c | 478 | // Add if not found |
c295e0f8 | 479 | let new_name: Option<&str> = passed_lib.new_name.as_deref(); |
f2b60f7d FG |
480 | let name = Some(Symbol::intern(new_name.unwrap_or(&passed_lib.name))); |
481 | let sess = self.tcx.sess; | |
482 | let filename = | |
483 | find_bundled_library(name, passed_lib.verbatim, passed_lib.kind, sess); | |
923072b8 | 484 | self.libs.push(NativeLib { |
f2b60f7d FG |
485 | name, |
486 | filename, | |
17df50a5 | 487 | kind: passed_lib.kind, |
ea8adc8c | 488 | cfg: None, |
0531ce1d | 489 | foreign_module: None, |
8faf50e0 | 490 | wasm_import_module: None, |
17df50a5 XL |
491 | verbatim: passed_lib.verbatim, |
492 | dll_imports: Vec::new(), | |
923072b8 | 493 | }); |
532ac7d7 XL |
494 | } else { |
495 | // Move all existing libraries with the same name to the | |
496 | // end of the command line. | |
497 | self.libs.append(&mut existing); | |
ea8adc8c XL |
498 | } |
499 | } | |
500 | } | |
136023e0 | 501 | |
c295e0f8 | 502 | fn i686_arg_list_size(&self, item: &hir::ForeignItemRef) -> usize { |
136023e0 XL |
503 | let argument_types: &List<Ty<'_>> = self.tcx.erase_late_bound_regions( |
504 | self.tcx | |
2b03887a | 505 | .type_of(item.id.owner_id) |
136023e0 XL |
506 | .fn_sig(self.tcx) |
507 | .inputs() | |
508 | .map_bound(|slice| self.tcx.mk_type_list(slice.iter())), | |
509 | ); | |
510 | ||
511 | argument_types | |
512 | .iter() | |
513 | .map(|ty| { | |
514 | let layout = self | |
515 | .tcx | |
516 | .layout_of(ParamEnvAnd { param_env: ParamEnv::empty(), value: ty }) | |
517 | .expect("layout") | |
518 | .layout; | |
519 | // In both stdcall and fastcall, we always round up the argument size to the | |
520 | // nearest multiple of 4 bytes. | |
5e7ed085 | 521 | (layout.size().bytes_usize() + 3) & !3 |
136023e0 XL |
522 | }) |
523 | .sum() | |
524 | } | |
525 | ||
f2b60f7d FG |
526 | fn build_dll_import( |
527 | &self, | |
528 | abi: Abi, | |
529 | import_name_type: Option<PeImportNameType>, | |
530 | item: &hir::ForeignItemRef, | |
531 | ) -> DllImport { | |
136023e0 XL |
532 | let calling_convention = if self.tcx.sess.target.arch == "x86" { |
533 | match abi { | |
5099ac24 | 534 | Abi::C { .. } | Abi::Cdecl { .. } => DllCallingConvention::C, |
136023e0 XL |
535 | Abi::Stdcall { .. } | Abi::System { .. } => { |
536 | DllCallingConvention::Stdcall(self.i686_arg_list_size(item)) | |
537 | } | |
5099ac24 FG |
538 | Abi::Fastcall { .. } => { |
539 | DllCallingConvention::Fastcall(self.i686_arg_list_size(item)) | |
540 | } | |
064997fb FG |
541 | Abi::Vectorcall { .. } => { |
542 | DllCallingConvention::Vectorcall(self.i686_arg_list_size(item)) | |
543 | } | |
136023e0 | 544 | _ => { |
f2b60f7d | 545 | self.tcx.sess.emit_fatal(UnsupportedAbiI686 { span: item.span }); |
136023e0 XL |
546 | } |
547 | } | |
548 | } else { | |
549 | match abi { | |
5099ac24 | 550 | Abi::C { .. } | Abi::Win64 { .. } | Abi::System { .. } => DllCallingConvention::C, |
136023e0 | 551 | _ => { |
f2b60f7d | 552 | self.tcx.sess.emit_fatal(UnsupportedAbi { span: item.span }); |
136023e0 XL |
553 | } |
554 | } | |
555 | }; | |
c295e0f8 | 556 | |
2b03887a | 557 | let codegen_fn_attrs = self.tcx.codegen_fn_attrs(item.id.owner_id); |
f2b60f7d FG |
558 | let import_name_type = codegen_fn_attrs |
559 | .link_ordinal | |
560 | .map_or(import_name_type, |ord| Some(PeImportNameType::Ordinal(ord))); | |
561 | ||
c295e0f8 | 562 | DllImport { |
f2b60f7d FG |
563 | name: codegen_fn_attrs.link_name.unwrap_or(item.ident.name), |
564 | import_name_type, | |
c295e0f8 XL |
565 | calling_convention, |
566 | span: item.span, | |
2b03887a | 567 | is_fn: self.tcx.def_kind(item.id.owner_id).is_fn_like(), |
c295e0f8 | 568 | } |
136023e0 | 569 | } |
ea8adc8c | 570 | } |