authorbors <bors@rust-lang.org> 2024-10-11 16:27:23 UTC
committerbors <bors@rust-lang.org> 2024-10-11 16:27:23 UTC
log01e2fff90c7ed19e1d9fb828ebc012e7b9732297
tree49b5869e859d2415e6f0a6b02f5bb1dbf1581d8d
parentf4966590d8edd5f493a1aab04016b94a75494329
parentb18e1aa612d75114ee67091f3af82ea04a08ef36

Auto merge of #131547 - matthiaskrgr:rollup-ui4p744, r=matthiaskrgr

Rollup of 6 pull requests Successful merges: - #129079 (Create `_imp__` symbols also when doing ThinLTO) - #131208 (ABI: Pass aggregates by value on AIX) - #131394 (fix(rustdoc): add space between struct fields and their descriptions) - #131519 (Use Default visibility for rustc-generated C symbol declarations) - #131541 (compiletest: Extract auxiliary-crate properties to their own module/struct) - #131542 (next-solver: remove outdated FIXMEs) r? `@ghost` `@rustbot` modify labels: rollup

20 files changed, 225 insertions(+), 95 deletions(-)

compiler/rustc_codegen_llvm/src/declare.rs+3-4
......@@ -84,10 +84,9 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
8484 unnamed: llvm::UnnamedAddr,
8585 fn_type: &'ll Type,
8686 ) -> &'ll Value {
87 // Declare C ABI functions with the visibility used by C by default.
88 let visibility = Visibility::from_generic(self.tcx.sess.default_visibility());
89
90 declare_raw_fn(self, name, llvm::CCallConv, unnamed, visibility, fn_type)
87 // Visibility should always be default for declarations, otherwise the linker may report an
88 // error.
89 declare_raw_fn(self, name, llvm::CCallConv, unnamed, Visibility::Default, fn_type)
9190 }
9291
9392 /// Declare an entry Function
compiler/rustc_codegen_ssa/src/back/write.rs+7-1
......@@ -2164,8 +2164,14 @@ fn msvc_imps_needed(tcx: TyCtxt<'_>) -> bool {
21642164 && tcx.sess.opts.cg.prefer_dynamic)
21652165 );
21662166
2167 // We need to generate _imp__ symbol if we are generating an rlib or we include one
2168 // indirectly from ThinLTO. In theory these are not needed as ThinLTO could resolve
2169 // these, but it currently does not do so.
2170 let can_have_static_objects =
2171 tcx.sess.lto() == Lto::Thin || tcx.crate_types().iter().any(|ct| *ct == CrateType::Rlib);
2172
21672173 tcx.sess.target.is_like_windows &&
2168 tcx.crate_types().iter().any(|ct| *ct == CrateType::Rlib) &&
2174 can_have_static_objects &&
21692175 // ThinLTO can't handle this workaround in all cases, so we don't
21702176 // emit the `__imp_` symbols. Instead we make them unnecessary by disallowing
21712177 // dynamic linking when linker plugin LTO is enabled.
compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs-1
......@@ -444,7 +444,6 @@ where
444444 for &arg in &state.value.var_values.var_values.as_slice()
445445 [orig_values.len()..state.value.var_values.len()]
446446 {
447 // FIXME: This is so ugly.
448447 let unconstrained = delegate.fresh_var_for_kind_with_span(arg, span);
449448 orig_values.push(unconstrained);
450449 }
compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs+1-1
......@@ -92,7 +92,6 @@ where
9292#[derive_where(Clone, Debug, Default; I: Interner)]
9393#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
9494#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
95// FIXME: This can be made crate-private once `EvalCtxt` also lives in this crate.
9695struct NestedGoals<I: Interner> {
9796 /// These normalizes-to goals are treated specially during the evaluation
9897 /// loop. In each iteration we take the RHS of the projection, replace it with
......@@ -421,6 +420,7 @@ where
421420 let (normalization_nested_goals, certainty) =
422421 self.instantiate_and_apply_query_response(goal.param_env, orig_values, response);
423422 self.inspect.goal_evaluation(goal_evaluation);
423
424424 // FIXME: We previously had an assert here that checked that recomputing
425425 // a goal after applying its constraints did not change its response.
426426 //
compiler/rustc_next_trait_solver/src/solve/mod.rs-3
......@@ -10,9 +10,6 @@
1010//!
1111//! For a high-level overview of how this solver works, check out the relevant
1212//! section of the rustc-dev-guide.
13//!
14//! FIXME(@lcnr): Write that section. If you read this before then ask me
15//! about it on zulip.
1613
1714mod alias_relate;
1815mod assembly;
compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs+1-1
......@@ -899,7 +899,7 @@ where
899899 for ty in types.iter() {
900900 // We can't find the intersection if the types used are generic.
901901 //
902 // FIXME(effects) do we want to look at where clauses to get some
902 // FIXME(effects): do we want to look at where clauses to get some
903903 // clue for the case where generic types are being used?
904904 let Some(kind) = ty::EffectKind::try_from_ty(cx, ty) else {
905905 return Err(NoSolution);
compiler/rustc_next_trait_solver/src/solve/trait_goals.rs+2-9
......@@ -108,7 +108,6 @@ where
108108 ecx: &mut EvalCtxt<'_, D>,
109109 _guar: I::ErrorGuaranteed,
110110 ) -> Result<Candidate<I>, NoSolution> {
111 // FIXME: don't need to enter a probe here.
112111 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
113112 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
114113 }
......@@ -463,7 +462,6 @@ where
463462 // Async coroutine unconditionally implement `Future`
464463 // Technically, we need to check that the future output type is Sized,
465464 // but that's already proven by the coroutine being WF.
466 // FIXME: use `consider_implied`
467465 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
468466 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
469467 }
......@@ -489,7 +487,6 @@ where
489487 // Gen coroutines unconditionally implement `Iterator`
490488 // Technically, we need to check that the iterator output type is Sized,
491489 // but that's already proven by the coroutines being WF.
492 // FIXME: use `consider_implied`
493490 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
494491 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
495492 }
......@@ -512,8 +509,7 @@ where
512509 return Err(NoSolution);
513510 }
514511
515 // Gen coroutines unconditionally implement `FusedIterator`
516 // FIXME: use `consider_implied`
512 // Gen coroutines unconditionally implement `FusedIterator`.
517513 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
518514 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
519515 }
......@@ -539,7 +535,6 @@ where
539535 // Gen coroutines unconditionally implement `Iterator`
540536 // Technically, we need to check that the iterator output type is Sized,
541537 // but that's already proven by the coroutines being WF.
542 // FIXME: use `consider_implied`
543538 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
544539 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
545540 }
......@@ -610,7 +605,7 @@ where
610605 return Err(NoSolution);
611606 }
612607
613 // FIXME(-Znext-solver): Implement this when we get const working in the new solver
608 // FIXME(effects): Implement this when we get const working in the new solver
614609
615610 // `Destruct` is automatically implemented for every type in
616611 // non-const environments.
......@@ -631,8 +626,6 @@ where
631626 return Err(NoSolution);
632627 }
633628
634 // FIXME: This actually should destructure the `Result` we get from transmutability and
635 // register candidates. We probably need to register >1 since we may have an OR of ANDs.
636629 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
637630 let certainty = ecx.is_transmutable(
638631 goal.param_env,
compiler/rustc_target/src/abi/call/powerpc64.rs+13-3
......@@ -10,6 +10,7 @@ use crate::spec::HasTargetSpec;
1010enum ABI {
1111 ELFv1, // original ABI used for powerpc64 (big-endian)
1212 ELFv2, // newer ABI used for powerpc64le and musl (both endians)
13 AIX, // used by AIX OS, big-endian only
1314}
1415use ABI::*;
1516
......@@ -23,9 +24,9 @@ where
2324 C: HasDataLayout,
2425{
2526 arg.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()).and_then(|unit| {
26 // ELFv1 only passes one-member aggregates transparently.
27 // ELFv1 and AIX only passes one-member aggregates transparently.
2728 // ELFv2 passes up to eight uniquely addressable members.
28 if (abi == ELFv1 && arg.layout.size > unit.size)
29 if ((abi == ELFv1 || abi == AIX) && arg.layout.size > unit.size)
2930 || arg.layout.size > unit.size.checked_mul(8, cx).unwrap()
3031 {
3132 return None;
......@@ -55,8 +56,15 @@ where
5556 return;
5657 }
5758
59 // The AIX ABI expect byval for aggregates
60 // See https://github.com/llvm/llvm-project/blob/main/clang/lib/CodeGen/Targets/PPC.cpp.
61 if !is_ret && abi == AIX {
62 arg.pass_by_stack_offset(None);
63 return;
64 }
65
5866 // The ELFv1 ABI doesn't return aggregates in registers
59 if is_ret && abi == ELFv1 {
67 if is_ret && (abi == ELFv1 || abi == AIX) {
6068 arg.make_indirect();
6169 return;
6270 }
......@@ -93,6 +101,8 @@ where
93101{
94102 let abi = if cx.target_spec().env == "musl" {
95103 ELFv2
104 } else if cx.target_spec().os == "aix" {
105 AIX
96106 } else {
97107 match cx.data_layout().endian {
98108 Endian::Big => ELFv1,
compiler/rustc_trait_selection/src/solve/delegate.rs+2
......@@ -223,6 +223,8 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
223223 if eligible { Ok(Some(node_item.item.def_id)) } else { Ok(None) }
224224 }
225225
226 // FIXME: This actually should destructure the `Result` we get from transmutability and
227 // register candidates. We probably need to register >1 since we may have an OR of ANDs.
226228 fn is_transmutable(
227229 &self,
228230 param_env: ty::ParamEnv<'tcx>,
src/librustdoc/html/static/css/rustdoc.css+3
......@@ -230,6 +230,9 @@ h4.code-header {
230230 padding: 0;
231231 white-space: pre-wrap;
232232}
233.structfield {
234 margin: 0.6em 0;
235}
233236
234237#crate-search,
235238h1, h2, h3, h4, h5, h6,
src/tools/compiletest/src/header.rs+14-57
......@@ -9,11 +9,13 @@ use std::process::Command;
99use tracing::*;
1010
1111use crate::common::{Config, Debugger, FailMode, Mode, PassMode};
12use crate::header::auxiliary::{AuxProps, parse_and_update_aux};
1213use crate::header::cfg::{MatchOutcome, parse_cfg_name_directive};
1314use crate::header::needs::CachedNeedsConditions;
1415use crate::util::static_regex;
1516use crate::{extract_cdb_version, extract_gdb_version};
1617
18pub(crate) mod auxiliary;
1719mod cfg;
1820mod needs;
1921#[cfg(test)]
......@@ -33,9 +35,10 @@ impl HeadersCache {
3335/// the test.
3436#[derive(Default)]
3537pub struct EarlyProps {
36 pub aux: Vec<String>,
37 pub aux_bin: Vec<String>,
38 pub aux_crate: Vec<(String, String)>,
38 /// Auxiliary crates that should be built and made available to this test.
39 /// Included in [`EarlyProps`] so that the indicated files can participate
40 /// in up-to-date checking. Building happens via [`TestProps::aux`] instead.
41 pub(crate) aux: AuxProps,
3942 pub revisions: Vec<String>,
4043}
4144
......@@ -55,21 +58,7 @@ impl EarlyProps {
5558 testfile,
5659 rdr,
5760 &mut |HeaderLine { directive: ln, .. }| {
58 config.push_name_value_directive(ln, directives::AUX_BUILD, &mut props.aux, |r| {
59 r.trim().to_string()
60 });
61 config.push_name_value_directive(
62 ln,
63 directives::AUX_BIN,
64 &mut props.aux_bin,
65 |r| r.trim().to_string(),
66 );
67 config.push_name_value_directive(
68 ln,
69 directives::AUX_CRATE,
70 &mut props.aux_crate,
71 Config::parse_aux_crate,
72 );
61 parse_and_update_aux(config, ln, &mut props.aux);
7362 config.parse_and_update_revisions(ln, &mut props.revisions);
7463 },
7564 );
......@@ -98,18 +87,8 @@ pub struct TestProps {
9887 // If present, the name of a file that this test should match when
9988 // pretty-printed
10089 pub pp_exact: Option<PathBuf>,
101 // Other crates that should be compiled (typically from the same
102 // directory as the test, but for backwards compatibility reasons
103 // we also check the auxiliary directory)
104 pub aux_builds: Vec<String>,
105 // Auxiliary crates that should be compiled as `#![crate_type = "bin"]`.
106 pub aux_bins: Vec<String>,
107 // Similar to `aux_builds`, but a list of NAME=somelib.rs of dependencies
108 // to build and pass with the `--extern` flag.
109 pub aux_crates: Vec<(String, String)>,
110 /// Similar to `aux_builds`, but also passes the resulting dylib path to
111 /// `-Zcodegen-backend`.
112 pub aux_codegen_backend: Option<String>,
90 /// Auxiliary crates that should be built and made available to this test.
91 pub(crate) aux: AuxProps,
11392 // Environment settings to use for compiling
11493 pub rustc_env: Vec<(String, String)>,
11594 // Environment variables to unset prior to compiling.
......@@ -276,10 +255,7 @@ impl TestProps {
276255 run_flags: vec![],
277256 doc_flags: vec![],
278257 pp_exact: None,
279 aux_builds: vec![],
280 aux_bins: vec![],
281 aux_crates: vec![],
282 aux_codegen_backend: None,
258 aux: Default::default(),
283259 revisions: vec![],
284260 rustc_env: vec![
285261 ("RUSTC_ICE".to_string(), "0".to_string()),
......@@ -454,21 +430,10 @@ impl TestProps {
454430 PRETTY_COMPARE_ONLY,
455431 &mut self.pretty_compare_only,
456432 );
457 config.push_name_value_directive(ln, AUX_BUILD, &mut self.aux_builds, |r| {
458 r.trim().to_string()
459 });
460 config.push_name_value_directive(ln, AUX_BIN, &mut self.aux_bins, |r| {
461 r.trim().to_string()
462 });
463 config.push_name_value_directive(
464 ln,
465 AUX_CRATE,
466 &mut self.aux_crates,
467 Config::parse_aux_crate,
468 );
469 if let Some(r) = config.parse_name_value_directive(ln, AUX_CODEGEN_BACKEND) {
470 self.aux_codegen_backend = Some(r.trim().to_owned());
471 }
433
434 // Call a helper method to deal with aux-related directives.
435 parse_and_update_aux(config, ln, &mut self.aux);
436
472437 config.push_name_value_directive(
473438 ln,
474439 EXEC_ENV,
......@@ -942,14 +907,6 @@ fn iter_header(
942907}
943908
944909impl Config {
945 fn parse_aux_crate(r: String) -> (String, String) {
946 let mut parts = r.trim().splitn(2, '=');
947 (
948 parts.next().expect("missing aux-crate name (e.g. log=log.rs)").to_string(),
949 parts.next().expect("missing aux-crate value (e.g. log=log.rs)").to_string(),
950 )
951 }
952
953910 fn parse_and_update_revisions(&self, line: &str, existing: &mut Vec<String>) {
954911 if let Some(raw) = self.parse_name_value_directive(line, "revisions") {
955912 let mut duplicates: HashSet<_> = existing.iter().cloned().collect();
src/tools/compiletest/src/header/auxiliary.rs created+60
......@@ -0,0 +1,60 @@
1//! Code for dealing with test directives that request an "auxiliary" crate to
2//! be built and made available to the test in some way.
3
4use std::iter;
5
6use crate::common::Config;
7use crate::header::directives::{AUX_BIN, AUX_BUILD, AUX_CODEGEN_BACKEND, AUX_CRATE};
8
9/// Properties parsed from `aux-*` test directives.
10#[derive(Clone, Debug, Default)]
11pub(crate) struct AuxProps {
12 /// Other crates that should be built and made available to this test.
13 /// These are filenames relative to `./auxiliary/` in the test's directory.
14 pub(crate) builds: Vec<String>,
15 /// Auxiliary crates that should be compiled as `#![crate_type = "bin"]`.
16 pub(crate) bins: Vec<String>,
17 /// Similar to `builds`, but a list of NAME=somelib.rs of dependencies
18 /// to build and pass with the `--extern` flag.
19 pub(crate) crates: Vec<(String, String)>,
20 /// Similar to `builds`, but also uses the resulting dylib as a
21 /// `-Zcodegen-backend` when compiling the test file.
22 pub(crate) codegen_backend: Option<String>,
23}
24
25impl AuxProps {
26 /// Yields all of the paths (relative to `./auxiliary/`) that have been
27 /// specified in `aux-*` directives for this test.
28 pub(crate) fn all_aux_path_strings(&self) -> impl Iterator<Item = &str> {
29 let Self { builds, bins, crates, codegen_backend } = self;
30
31 iter::empty()
32 .chain(builds.iter().map(String::as_str))
33 .chain(bins.iter().map(String::as_str))
34 .chain(crates.iter().map(|(_, path)| path.as_str()))
35 .chain(codegen_backend.iter().map(String::as_str))
36 }
37}
38
39/// If the given test directive line contains an `aux-*` directive, parse it
40/// and update [`AuxProps`] accordingly.
41pub(super) fn parse_and_update_aux(config: &Config, ln: &str, aux: &mut AuxProps) {
42 if !ln.starts_with("aux-") {
43 return;
44 }
45
46 config.push_name_value_directive(ln, AUX_BUILD, &mut aux.builds, |r| r.trim().to_string());
47 config.push_name_value_directive(ln, AUX_BIN, &mut aux.bins, |r| r.trim().to_string());
48 config.push_name_value_directive(ln, AUX_CRATE, &mut aux.crates, parse_aux_crate);
49 if let Some(r) = config.parse_name_value_directive(ln, AUX_CODEGEN_BACKEND) {
50 aux.codegen_backend = Some(r.trim().to_owned());
51 }
52}
53
54fn parse_aux_crate(r: String) -> (String, String) {
55 let mut parts = r.trim().splitn(2, '=');
56 (
57 parts.next().expect("missing aux-crate name (e.g. log=log.rs)").to_string(),
58 parts.next().expect("missing aux-crate value (e.g. log=log.rs)").to_string(),
59 )
60}
src/tools/compiletest/src/header/tests.rs+2-1
......@@ -242,7 +242,8 @@ fn aux_build() {
242242 //@ aux-build: b.rs
243243 "
244244 )
245 .aux,
245 .aux
246 .builds,
246247 vec!["a.rs", "b.rs"],
247248 );
248249}
src/tools/compiletest/src/lib.rs+2-1
......@@ -862,7 +862,8 @@ fn files_related_to_test(
862862 related.push(testpaths.file.clone());
863863 }
864864
865 for aux in &props.aux {
865 for aux in props.aux.all_aux_path_strings() {
866 // FIXME(Zalathar): Perform all `auxiliary` path resolution in one place.
866867 let path = testpaths.file.parent().unwrap().join("auxiliary").join(aux);
867868 related.push(path);
868869 }
src/tools/compiletest/src/runtest.rs+9-9
......@@ -841,13 +841,13 @@ impl<'test> TestCx<'test> {
841841 /// Auxiliaries, no matter how deep, have the same root_out_dir and root_testpaths.
842842 fn document(&self, root_out_dir: &Path, root_testpaths: &TestPaths) -> ProcRes {
843843 if self.props.build_aux_docs {
844 for rel_ab in &self.props.aux_builds {
844 for rel_ab in &self.props.aux.builds {
845845 let aux_testpaths = self.compute_aux_test_paths(root_testpaths, rel_ab);
846 let aux_props =
846 let props_for_aux =
847847 self.props.from_aux_file(&aux_testpaths.file, self.revision, self.config);
848848 let aux_cx = TestCx {
849849 config: self.config,
850 props: &aux_props,
850 props: &props_for_aux,
851851 testpaths: &aux_testpaths,
852852 revision: self.revision,
853853 };
......@@ -1059,11 +1059,11 @@ impl<'test> TestCx<'test> {
10591059 fn aux_output_dir(&self) -> PathBuf {
10601060 let aux_dir = self.aux_output_dir_name();
10611061
1062 if !self.props.aux_builds.is_empty() {
1062 if !self.props.aux.builds.is_empty() {
10631063 remove_and_create_dir_all(&aux_dir);
10641064 }
10651065
1066 if !self.props.aux_bins.is_empty() {
1066 if !self.props.aux.bins.is_empty() {
10671067 let aux_bin_dir = self.aux_bin_output_dir_name();
10681068 remove_and_create_dir_all(&aux_dir);
10691069 remove_and_create_dir_all(&aux_bin_dir);
......@@ -1073,15 +1073,15 @@ impl<'test> TestCx<'test> {
10731073 }
10741074
10751075 fn build_all_auxiliary(&self, of: &TestPaths, aux_dir: &Path, rustc: &mut Command) {
1076 for rel_ab in &self.props.aux_builds {
1076 for rel_ab in &self.props.aux.builds {
10771077 self.build_auxiliary(of, rel_ab, &aux_dir, false /* is_bin */);
10781078 }
10791079
1080 for rel_ab in &self.props.aux_bins {
1080 for rel_ab in &self.props.aux.bins {
10811081 self.build_auxiliary(of, rel_ab, &aux_dir, true /* is_bin */);
10821082 }
10831083
1084 for (aux_name, aux_path) in &self.props.aux_crates {
1084 for (aux_name, aux_path) in &self.props.aux.crates {
10851085 let aux_type = self.build_auxiliary(of, &aux_path, &aux_dir, false /* is_bin */);
10861086 let lib_name =
10871087 get_lib_name(&aux_path.trim_end_matches(".rs").replace('-', "_"), aux_type);
......@@ -1097,7 +1097,7 @@ impl<'test> TestCx<'test> {
10971097
10981098 // Build any `//@ aux-codegen-backend`, and pass the resulting library
10991099 // to `-Zcodegen-backend` when compiling the test file.
1100 if let Some(aux_file) = &self.props.aux_codegen_backend {
1100 if let Some(aux_file) = &self.props.aux.codegen_backend {
11011101 let aux_type = self.build_auxiliary(of, aux_file, aux_dir, false);
11021102 if let Some(lib_name) = get_lib_name(aux_file.trim_end_matches(".rs"), aux_type) {
11031103 let lib_path = aux_dir.join(&lib_name);
tests/assembly/powerpc64-struct-abi.rs+39-4
......@@ -1,4 +1,4 @@
1//@ revisions: elfv1-be elfv2-be elfv2-le
1//@ revisions: elfv1-be elfv2-be elfv2-le aix
22//@ assembly-output: emit-asm
33//@ compile-flags: -O
44//@[elfv1-be] compile-flags: --target powerpc64-unknown-linux-gnu
......@@ -7,8 +7,13 @@
77//@[elfv2-be] needs-llvm-components: powerpc
88//@[elfv2-le] compile-flags: --target powerpc64le-unknown-linux-gnu
99//@[elfv2-le] needs-llvm-components: powerpc
10//@[aix] compile-flags: --target powerpc64-ibm-aix
11//@[aix] needs-llvm-components: powerpc
1012//@[elfv1-be] filecheck-flags: --check-prefix be
1113//@[elfv2-be] filecheck-flags: --check-prefix be
14//@[elfv1-be] filecheck-flags: --check-prefix elf
15//@[elfv2-be] filecheck-flags: --check-prefix elf
16//@[elfv2-le] filecheck-flags: --check-prefix elf
1217
1318#![feature(no_core, lang_items)]
1419#![no_std]
......@@ -44,6 +49,10 @@ struct FiveU16s(u16, u16, u16, u16, u16);
4449struct ThreeU8s(u8, u8, u8);
4550
4651// CHECK-LABEL: read_large
52// aix: lwz [[REG1:.*]], 16(4)
53// aix-NEXT: lxvd2x 0, 0, 4
54// aix-NEXT: stw [[REG1]], 16(3)
55// aix-NEXT: stxvd2x 0, 0, 3
4756// be: lwz [[REG1:.*]], 16(4)
4857// be-NEXT: stw [[REG1]], 16(3)
4958// be-NEXT: ld [[REG2:.*]], 8(4)
......@@ -61,6 +70,10 @@ extern "C" fn read_large(x: &FiveU32s) -> FiveU32s {
6170}
6271
6372// CHECK-LABEL: read_medium
73// aix: lhz [[REG1:.*]], 8(4)
74// aix-NEXT: ld [[REG2:.*]], 0(4)
75// aix-NEXT: sth [[REG1]], 8(3)
76// aix-NEXT: std [[REG2]], 0(3)
6477// elfv1-be: lhz [[REG1:.*]], 8(4)
6578// elfv1-be-NEXT: ld [[REG2:.*]], 0(4)
6679// elfv1-be-NEXT: sth [[REG1]], 8(3)
......@@ -78,6 +91,10 @@ extern "C" fn read_medium(x: &FiveU16s) -> FiveU16s {
7891}
7992
8093// CHECK-LABEL: read_small
94// aix: lbz [[REG1:.*]], 2(4)
95// aix-NEXT: lhz [[REG2:.*]], 0(4)
96// aix-NEXT: stb [[REG1]], 2(3)
97// aix-NEXT: sth [[REG2]], 0(3)
8198// elfv1-be: lbz [[REG1:.*]], 2(4)
8299// elfv1-be-NEXT: lhz [[REG2:.*]], 0(4)
83100// elfv1-be-NEXT: stb [[REG1]], 2(3)
......@@ -95,9 +112,17 @@ extern "C" fn read_small(x: &ThreeU8s) -> ThreeU8s {
95112}
96113
97114// CHECK-LABEL: write_large
98// CHECK: std 3, 0(6)
115// aix: std 3, 48(1)
116// aix-NEXT: rldicl [[REG1:.*]], 5, 32, 32
117// aix-NEXT: std 5, 64(1)
118// aix-NEXT: std 4, 56(1)
119// aix-NEXT: stw [[REG1]], 16(6)
120// aix-NEXT: addi [[REG2:.*]], 1, 48
121// aix-NEXT: lxvd2x 0, 0, [[REG2]]
122// aix-NEXT: stxvd2x 0, 0, 6
123// elf: std 3, 0(6)
99124// be-NEXT: rldicl [[REG1:.*]], 5, 32, 32
100// CHECK-NEXT: std 4, 8(6)
125// elf-NEXT: std 4, 8(6)
101126// be-NEXT: stw [[REG1]], 16(6)
102127// elfv2-le-NEXT: stw 5, 16(6)
103128// CHECK-NEXT: blr
......@@ -107,7 +132,12 @@ extern "C" fn write_large(x: FiveU32s, dest: &mut FiveU32s) {
107132}
108133
109134// CHECK-LABEL: write_medium
110// CHECK: std 3, 0(5)
135// aix: std 4, 56(1)
136// aix-NEXT: rldicl [[REG1:.*]], 4, 16, 48
137// aix-NEXT: std 3, 48(1)
138// aix-NEXT: std 3, 0(5)
139// aix-NEXT: sth [[REG1]], 8(5)
140// elf: std 3, 0(5)
111141// be-NEXT: rldicl [[REG1:.*]], 4, 16, 48
112142// be-NEXT: sth [[REG1]], 8(5)
113143// elfv2-le-NEXT: sth 4, 8(5)
......@@ -118,6 +148,11 @@ extern "C" fn write_medium(x: FiveU16s, dest: &mut FiveU16s) {
118148}
119149
120150// CHECK-LABEL: write_small
151// aix: std 3, 48(1)
152// aix-NEXT: rldicl [[REG1:.*]], 3, 16, 48
153// aix-NEXT: sth 3, 0(4)
154// aix-NEXT: lbz 3, 50(1)
155// aix-NEXT: stb [[REG1]], 2(4)
121156// be: stb 3, 2(4)
122157// be-NEXT: srwi [[REG1:.*]], 3, 8
123158// be-NEXT: sth [[REG1]], 0(4)
tests/codegen/default-visibility.rs+16
......@@ -31,3 +31,19 @@ pub static tested_symbol: [u8; 6] = *b"foobar";
3131// PROTECTED: @{{.*}}default_visibility{{.*}}tested_symbol{{.*}} = protected constant
3232// INTERPOSABLE: @{{.*}}default_visibility{{.*}}tested_symbol{{.*}} = constant
3333// DEFAULT: @{{.*}}default_visibility{{.*}}tested_symbol{{.*}} = constant
34
35pub fn do_memcmp(left: &[u8], right: &[u8]) -> i32 {
36 left.cmp(right) as i32
37}
38
39// CHECK: define {{.*}} @{{.*}}do_memcmp{{.*}} {
40// CHECK: }
41
42// `do_memcmp` should invoke core::intrinsic::compare_bytes which emits a call
43// to the C symbol `memcmp` (at least on x86_64-unknown-linux-gnu). This symbol
44// should *not* be declared hidden or protected.
45
46// HIDDEN: declare i32 @memcmp
47// PROTECTED: declare i32 @memcmp
48// INTERPOSABLE: declare i32 @memcmp
49// DEFAULT: declare i32 @memcmp
tests/run-make/msvc-lld-thinlto-imp-symbols/issue_81408.rs created+13
......@@ -0,0 +1,13 @@
1use std::sync::atomic::{AtomicPtr, Ordering};
2
3#[inline(always)]
4pub fn memrchr() {
5 fn detect() {}
6
7 static CROSS_CRATE_STATIC_ITEM: AtomicPtr<()> = AtomicPtr::new(detect as *mut ());
8
9 unsafe {
10 let fun = CROSS_CRATE_STATIC_ITEM.load(Ordering::SeqCst);
11 std::mem::transmute::<*mut (), fn()>(fun)()
12 }
13}
tests/run-make/msvc-lld-thinlto-imp-symbols/main.rs created+5
......@@ -0,0 +1,5 @@
1extern crate issue_81408;
2
3fn main() {
4 issue_81408::memrchr();
5}
tests/run-make/msvc-lld-thinlto-imp-symbols/rmake.rs created+33
......@@ -0,0 +1,33 @@
1// This is a non-regression test for issue #81408 involving an lld bug and ThinLTO, on windows.
2// MSVC's link.exe doesn't need any workarounds in rustc, but lld does, so we'll check that the
3// binary runs successfully instead of using a codegen test.
4
5//@ only-x86_64-pc-windows-msvc
6//@ needs-rust-lld
7//@ ignore-cross-compile: the built binary is executed
8
9use run_make_support::{run, rustc};
10
11fn test_with_linker(linker: &str) {
12 rustc().input("issue_81408.rs").crate_name("issue_81408").crate_type("lib").opt().run();
13 rustc()
14 .input("main.rs")
15 .crate_type("bin")
16 .arg("-Clto=thin")
17 .opt()
18 .arg(&format!("-Clinker={linker}"))
19 .extern_("issue_81408", "libissue_81408.rlib")
20 .run();
21
22 // To make possible failures clearer, print an intro that will only be shown if the test does
23 // fail when running the binary.
24 eprint!("Running binary linked with {linker}... ");
25 run("main");
26 eprintln!("ok");
27}
28
29fn main() {
30 // We want the reproducer to work when linked with both linkers.
31 test_with_linker("link");
32 test_with_linker("rust-lld");
33}