Skip to content

Commit 2f6fb23

Browse files
committed
Add a test
1 parent 82717ab commit 2f6fb23

File tree

7 files changed

+189
-21
lines changed

7 files changed

+189
-21
lines changed

Diff for: Cargo.lock

+31-8
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ version = "0.1.5"
214214
source = "registry+https://github.com/rust-lang/crates.io-index"
215215
checksum = "9792d37ca5173d7e7f4fe453739a0671d0557915a030a383d6b866476bbc3e71"
216216
dependencies = [
217-
"object",
217+
"object 0.32.2",
218218
]
219219

220220
[[package]]
@@ -281,7 +281,7 @@ dependencies = [
281281
"cfg-if",
282282
"libc",
283283
"miniz_oxide",
284-
"object",
284+
"object 0.32.2",
285285
"rustc-demangle",
286286
]
287287

@@ -2623,10 +2623,21 @@ dependencies = [
26232623
"memchr",
26242624
"rustc-std-workspace-alloc",
26252625
"rustc-std-workspace-core",
2626-
"ruzstd",
2626+
"ruzstd 0.5.0",
26272627
"wasmparser",
26282628
]
26292629

2630+
[[package]]
2631+
name = "object"
2632+
version = "0.34.0"
2633+
source = "registry+https://github.com/rust-lang/crates.io-index"
2634+
checksum = "d7090bae93f8585aad99e595b7073c5de9ba89fbd6b4e9f0cdd7a10177273ac8"
2635+
dependencies = [
2636+
"flate2",
2637+
"memchr",
2638+
"ruzstd 0.6.0",
2639+
]
2640+
26302641
[[package]]
26312642
name = "odht"
26322643
version = "0.3.1"
@@ -3310,6 +3321,7 @@ dependencies = [
33103321
name = "run_make_support"
33113322
version = "0.0.0"
33123323
dependencies = [
3324+
"object 0.34.0",
33133325
"wasmparser",
33143326
]
33153327

@@ -3621,7 +3633,7 @@ dependencies = [
36213633
"itertools 0.12.1",
36223634
"libc",
36233635
"measureme",
3624-
"object",
3636+
"object 0.32.2",
36253637
"rustc-demangle",
36263638
"rustc_ast",
36273639
"rustc_attr",
@@ -3657,7 +3669,7 @@ dependencies = [
36573669
"itertools 0.12.1",
36583670
"jobserver",
36593671
"libc",
3660-
"object",
3672+
"object 0.32.2",
36613673
"pathdiff",
36623674
"regex",
36633675
"rustc_arena",
@@ -4614,7 +4626,7 @@ name = "rustc_target"
46144626
version = "0.0.0"
46154627
dependencies = [
46164628
"bitflags 2.4.2",
4617-
"object",
4629+
"object 0.32.2",
46184630
"rustc_abi",
46194631
"rustc_data_structures",
46204632
"rustc_feature",
@@ -4881,6 +4893,17 @@ dependencies = [
48814893
"twox-hash",
48824894
]
48834895

4896+
[[package]]
4897+
name = "ruzstd"
4898+
version = "0.6.0"
4899+
source = "registry+https://github.com/rust-lang/crates.io-index"
4900+
checksum = "5174a470eeb535a721ae9fdd6e291c2411a906b96592182d05217591d5c5cf7b"
4901+
dependencies = [
4902+
"byteorder",
4903+
"derive_more",
4904+
"twox-hash",
4905+
]
4906+
48844907
[[package]]
48854908
name = "ryu"
48864909
version = "1.0.17"
@@ -5184,7 +5207,7 @@ dependencies = [
51845207
"hermit-abi",
51855208
"libc",
51865209
"miniz_oxide",
5187-
"object",
5210+
"object 0.32.2",
51885211
"panic_abort",
51895212
"panic_unwind",
51905213
"profiler_builtins",
@@ -5501,7 +5524,7 @@ checksum = "4db52ee8fec06e119b692ef3dd2c4cf621a99204c1b8c47407870ed050305b9b"
55015524
dependencies = [
55025525
"gimli",
55035526
"hashbrown",
5504-
"object",
5527+
"object 0.32.2",
55055528
"tracing",
55065529
]
55075530

Diff for: Cargo.toml

-9
Original file line numberDiff line numberDiff line change
@@ -66,15 +66,6 @@ exclude = [
6666
]
6767

6868
[profile.release.package.compiler_builtins]
69-
# The compiler-builtins crate cannot reference libcore, and its own CI will
70-
# verify that this is the case. This requires, however, that the crate is built
71-
# without overflow checks and debug assertions. Forcefully disable debug
72-
# assertions and overflow checks here which should ensure that even if these
73-
# assertions are enabled for libstd we won't enable them for compiler_builtins
74-
# which should ensure we still link everything correctly.
75-
debug-assertions = false
76-
overflow-checks = false
77-
7869
# For compiler-builtins we always use a high number of codegen units.
7970
# The goal here is to place every single intrinsic into its own object
8071
# file to avoid symbol clashes with the system libgcc if possible. Note

Diff for: compiler/rustc_codegen_ssa/src/mir/block.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -1693,11 +1693,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
16931693

16941694
self.set_debug_loc(&mut bx, mir::SourceInfo::outermost(self.mir.span));
16951695

1696-
let (fn_abi, fn_ptr, _instance) = common::build_langcall(&bx, None, reason.lang_item());
1697-
let fn_ty = bx.fn_decl_backend_type(fn_abi);
1696+
let (fn_abi, fn_ptr, instance) = common::build_langcall(&bx, None, reason.lang_item());
1697+
if is_call_from_compiler_builtins_to_upstream_monomorphization(bx.tcx(), instance) {
1698+
bx.abort();
1699+
} else {
1700+
let fn_ty = bx.fn_decl_backend_type(fn_abi);
16981701

1699-
let llret = bx.call(fn_ty, None, Some(fn_abi), fn_ptr, &[], funclet.as_ref());
1700-
bx.apply_attrs_to_cleanup_callsite(llret);
1702+
let llret = bx.call(fn_ty, None, Some(fn_abi), fn_ptr, &[], funclet.as_ref());
1703+
bx.apply_attrs_to_cleanup_callsite(llret);
1704+
}
17011705

17021706
bx.unreachable();
17031707

Diff for: compiler/rustc_middle/src/ty/instance.rs

+6
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use rustc_hir::lang_items::LangItem;
1010
use rustc_index::bit_set::FiniteBitSet;
1111
use rustc_macros::HashStable;
1212
use rustc_middle::ty::normalize_erasing_regions::NormalizationError;
13+
use rustc_span::def_id::LOCAL_CRATE;
1314
use rustc_span::Symbol;
1415

1516
use std::assert_matches::assert_matches;
@@ -168,6 +169,11 @@ impl<'tcx> Instance<'tcx> {
168169
// If this a non-generic instance, it cannot be a shared monomorphization.
169170
self.args.non_erasable_generics(tcx, self.def_id()).next()?;
170171

172+
// compiler_builtins cannot use upstream monomorphizations.
173+
if tcx.is_compiler_builtins(LOCAL_CRATE) {
174+
return None;
175+
}
176+
171177
match self.def {
172178
InstanceDef::Item(def) => tcx
173179
.upstream_monomorphizations_for(def)

Diff for: src/tools/run-make-support/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ version = "0.0.0"
44
edition = "2021"
55

66
[dependencies]
7+
object = "0.34.0"
78
wasmparser = "0.118.2"

Diff for: src/tools/run-make-support/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use std::env;
22
use std::path::{Path, PathBuf};
33
use std::process::{Command, Output};
44

5+
pub use object;
56
pub use wasmparser;
67

78
pub fn out_dir() -> PathBuf {

Diff for: tests/run-make/compiler-builtins/rmake.rs

+142
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
//! The compiler_builtins library is special. It can call functions in core, but it must not
2+
//! require linkage against a build of core. If it ever does, building the standard library *may*
3+
//! result in linker errors, depending on whether the linker in use applies optimizations first or
4+
//! resolves symbols first. So the portable and safe approach is to forbid such a linkage
5+
//! requirement entirely.
6+
//!
7+
//! In addition, whether compiler_builtins requires linkage against core can depend on optimization
8+
//! settings. Turning off optimizations and enabling debug assertions tends to produce the most
9+
//! dependence on core that is possible, so that is the configuration we test here.
10+
11+
#![deny(warnings)]
12+
13+
extern crate run_make_support;
14+
15+
use run_make_support::object;
16+
use run_make_support::object::read::archive::ArchiveFile;
17+
use run_make_support::object::read::Object;
18+
use run_make_support::object::ObjectSection;
19+
use run_make_support::object::ObjectSymbol;
20+
use run_make_support::object::RelocationTarget;
21+
use run_make_support::out_dir;
22+
use std::collections::HashSet;
23+
24+
const MANIFEST: &str = r#"
25+
[package]
26+
name = "scratch"
27+
version = "0.1.0"
28+
edition = "2021"
29+
30+
[lib]
31+
path = "lib.rs""#;
32+
33+
fn main() {
34+
let target_dir = out_dir().join("target");
35+
let target = std::env::var("TARGET").unwrap();
36+
if target.starts_with("wasm") || target.starts_with("nvptx") {
37+
// wasm and nvptx targets don't produce rlib files that object can parse.
38+
return;
39+
}
40+
41+
println!("Testing compiler_builtins for {}", target);
42+
43+
// Set up the tiniest Cargo project: An empty no_std library. Just enough to run -Zbuild-std.
44+
let manifest_path = out_dir().join("Cargo.toml");
45+
std::fs::write(&manifest_path, MANIFEST.as_bytes()).unwrap();
46+
std::fs::write(out_dir().join("lib.rs"), b"#![no_std]").unwrap();
47+
48+
let path = std::env::var("PATH").unwrap();
49+
let rustc = std::env::var("RUSTC").unwrap();
50+
let bootstrap_cargo = std::env::var("BOOTSTRAP_CARGO").unwrap();
51+
let status = std::process::Command::new(bootstrap_cargo)
52+
.args([
53+
"build",
54+
"--manifest-path",
55+
manifest_path.to_str().unwrap(),
56+
"-Zbuild-std=core",
57+
"--target",
58+
&target,
59+
])
60+
.env_clear()
61+
.env("PATH", path)
62+
.env("RUSTC", rustc)
63+
.env("RUSTFLAGS", "-Copt-level=0 -Cdebug-assertions=yes")
64+
.env("CARGO_TARGET_DIR", &target_dir)
65+
.env("RUSTC_BOOTSTRAP", "1")
66+
.status()
67+
.unwrap();
68+
69+
assert!(status.success());
70+
71+
let rlibs_path = target_dir.join(target).join("debug").join("deps");
72+
let compiler_builtins_rlib = std::fs::read_dir(rlibs_path)
73+
.unwrap()
74+
.find_map(|e| {
75+
let path = e.unwrap().path();
76+
let file_name = path.file_name().unwrap().to_str().unwrap();
77+
if file_name.starts_with("libcompiler_builtins") && file_name.ends_with(".rlib") {
78+
Some(path)
79+
} else {
80+
None
81+
}
82+
})
83+
.unwrap();
84+
85+
// rlib files are archives, where the archive members each a CGU, and we also have one called
86+
// lib.rmeta which is the encoded metadata. Each of the CGUs is an object file.
87+
let data = std::fs::read(compiler_builtins_rlib).unwrap();
88+
89+
let mut defined_symbols = HashSet::new();
90+
let mut undefined_relocations = HashSet::new();
91+
92+
let archive = ArchiveFile::parse(&*data).unwrap();
93+
for member in archive.members() {
94+
let member = member.unwrap();
95+
if member.name() == b"lib.rmeta" {
96+
continue;
97+
}
98+
let data = member.data(&*data).unwrap();
99+
let object = object::File::parse(&*data).unwrap();
100+
101+
// Record all defined symbols in this CGU.
102+
for symbol in object.symbols() {
103+
if !symbol.is_undefined() {
104+
let name = symbol.name().unwrap();
105+
defined_symbols.insert(name);
106+
}
107+
}
108+
109+
// Find any relocations against undefined symbols. Calls within this CGU are relocations
110+
// against a defined symbol.
111+
for (_offset, relocation) in object.sections().flat_map(|section| section.relocations()) {
112+
let RelocationTarget::Symbol(symbol_index) = relocation.target() else {
113+
continue;
114+
};
115+
let symbol = object.symbol_by_index(symbol_index).unwrap();
116+
if symbol.is_undefined() {
117+
let name = symbol.name().unwrap();
118+
undefined_relocations.insert(name);
119+
}
120+
}
121+
}
122+
123+
// We can have symbols in the compiler_builtins rlib that are actually from core, if they were
124+
// monomorphized in the compiler_builtins crate. This is totally fine, because though the call
125+
// is to a function in core, it's resolved internally.
126+
//
127+
// It is normal to have relocations against symbols not defined in the rlib for things like
128+
// unwinding, or math functions provided the target's platform libraries. Finding these is not
129+
// a problem, we want to specifically ban relocations against core which are not resolved
130+
// internally.
131+
undefined_relocations
132+
.retain(|symbol| !defined_symbols.contains(symbol) && symbol.contains("core"));
133+
134+
if !undefined_relocations.is_empty() {
135+
panic!(
136+
"compiler_builtins must not link against core, but it does. \n\
137+
These symbols may be undefined in a debug build of compiler_builtins:\n\
138+
{:?}",
139+
undefined_relocations
140+
);
141+
}
142+
}

0 commit comments

Comments
 (0)