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