about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs18
-rw-r--r--tests/run-make/allocator-shim-circular-deps/Makefile7
-rw-r--r--tests/run-make/allocator-shim-circular-deps/main.rs5
-rw-r--r--tests/run-make/allocator-shim-circular-deps/my_lib.rs10
4 files changed, 38 insertions, 2 deletions
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index dc4a28c866f..6abc56d5975 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -13,7 +13,7 @@ use crate::mir::place::PlaceRef;
 use crate::traits::*;
 use crate::{CachedModuleCodegen, CompiledModule, CrateInfo, MemFlags, ModuleCodegen, ModuleKind};
 
-use rustc_ast::expand::allocator::AllocatorKind;
+use rustc_ast::expand::allocator::{global_fn_name, AllocatorKind, ALLOCATOR_METHODS};
 use rustc_attr as attr;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry};
@@ -921,7 +921,21 @@ impl CrateInfo {
                         missing_weak_lang_items
                             .iter()
                             .map(|item| (format!("{prefix}{item}"), SymbolExportKind::Text)),
-                    )
+                    );
+                    if tcx.allocator_kind(()).is_some() {
+                        // At least one crate needs a global allocator. This crate may be placed
+                        // after the crate that defines it in the linker order, in which case some
+                        // linkers return an error. By adding the global allocator shim methods to
+                        // the linked_symbols list, linking the generated symbols.o will ensure that
+                        // circular dependencies involving the global allocator don't lead to linker
+                        // errors.
+                        linked_symbols.extend(ALLOCATOR_METHODS.iter().map(|method| {
+                            (
+                                format!("{prefix}{}", global_fn_name(method.name).as_str()),
+                                SymbolExportKind::Text,
+                            )
+                        }));
+                    }
                 });
         }
 
diff --git a/tests/run-make/allocator-shim-circular-deps/Makefile b/tests/run-make/allocator-shim-circular-deps/Makefile
new file mode 100644
index 00000000000..4624b846803
--- /dev/null
+++ b/tests/run-make/allocator-shim-circular-deps/Makefile
@@ -0,0 +1,7 @@
+# ignore-cross-compile
+include ../tools.mk
+
+all:
+	rm -rf $(TMPDIR) && mkdir $(TMPDIR)
+	$(RUSTC) my_lib.rs
+	$(RUSTC) main.rs --test --extern my_lib=$(TMPDIR)/libmy_lib.rlib
diff --git a/tests/run-make/allocator-shim-circular-deps/main.rs b/tests/run-make/allocator-shim-circular-deps/main.rs
new file mode 100644
index 00000000000..e317c657150
--- /dev/null
+++ b/tests/run-make/allocator-shim-circular-deps/main.rs
@@ -0,0 +1,5 @@
+#![crate_type = "bin"]
+
+fn main() {
+    my_lib::do_something();
+}
diff --git a/tests/run-make/allocator-shim-circular-deps/my_lib.rs b/tests/run-make/allocator-shim-circular-deps/my_lib.rs
new file mode 100644
index 00000000000..095b1036116
--- /dev/null
+++ b/tests/run-make/allocator-shim-circular-deps/my_lib.rs
@@ -0,0 +1,10 @@
+#![crate_type = "lib"]
+
+use std::alloc::System;
+
+#[global_allocator]
+static ALLOCATOR: System = System;
+
+pub fn do_something() {
+    format!("allocating a string!");
+}