Add a test
This commit is contained in:
parent
82717ab877
commit
2f6fb234de
39
Cargo.lock
39
Cargo.lock
@ -214,7 +214,7 @@ version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9792d37ca5173d7e7f4fe453739a0671d0557915a030a383d6b866476bbc3e71"
|
||||
dependencies = [
|
||||
"object",
|
||||
"object 0.32.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -281,7 +281,7 @@ dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"miniz_oxide",
|
||||
"object",
|
||||
"object 0.32.2",
|
||||
"rustc-demangle",
|
||||
]
|
||||
|
||||
@ -2623,10 +2623,21 @@ dependencies = [
|
||||
"memchr",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
"ruzstd",
|
||||
"ruzstd 0.5.0",
|
||||
"wasmparser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.34.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7090bae93f8585aad99e595b7073c5de9ba89fbd6b4e9f0cdd7a10177273ac8"
|
||||
dependencies = [
|
||||
"flate2",
|
||||
"memchr",
|
||||
"ruzstd 0.6.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "odht"
|
||||
version = "0.3.1"
|
||||
@ -3310,6 +3321,7 @@ dependencies = [
|
||||
name = "run_make_support"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"object 0.34.0",
|
||||
"wasmparser",
|
||||
]
|
||||
|
||||
@ -3621,7 +3633,7 @@ dependencies = [
|
||||
"itertools 0.12.1",
|
||||
"libc",
|
||||
"measureme",
|
||||
"object",
|
||||
"object 0.32.2",
|
||||
"rustc-demangle",
|
||||
"rustc_ast",
|
||||
"rustc_attr",
|
||||
@ -3657,7 +3669,7 @@ dependencies = [
|
||||
"itertools 0.12.1",
|
||||
"jobserver",
|
||||
"libc",
|
||||
"object",
|
||||
"object 0.32.2",
|
||||
"pathdiff",
|
||||
"regex",
|
||||
"rustc_arena",
|
||||
@ -4614,7 +4626,7 @@ name = "rustc_target"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"object",
|
||||
"object 0.32.2",
|
||||
"rustc_abi",
|
||||
"rustc_data_structures",
|
||||
"rustc_feature",
|
||||
@ -4881,6 +4893,17 @@ dependencies = [
|
||||
"twox-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruzstd"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5174a470eeb535a721ae9fdd6e291c2411a906b96592182d05217591d5c5cf7b"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"derive_more",
|
||||
"twox-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.17"
|
||||
@ -5184,7 +5207,7 @@ dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"miniz_oxide",
|
||||
"object",
|
||||
"object 0.32.2",
|
||||
"panic_abort",
|
||||
"panic_unwind",
|
||||
"profiler_builtins",
|
||||
@ -5501,7 +5524,7 @@ checksum = "4db52ee8fec06e119b692ef3dd2c4cf621a99204c1b8c47407870ed050305b9b"
|
||||
dependencies = [
|
||||
"gimli",
|
||||
"hashbrown",
|
||||
"object",
|
||||
"object 0.32.2",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
|
@ -66,15 +66,6 @@ exclude = [
|
||||
]
|
||||
|
||||
[profile.release.package.compiler_builtins]
|
||||
# The compiler-builtins crate cannot reference libcore, and its own CI will
|
||||
# verify that this is the case. This requires, however, that the crate is built
|
||||
# without overflow checks and debug assertions. Forcefully disable debug
|
||||
# assertions and overflow checks here which should ensure that even if these
|
||||
# assertions are enabled for libstd we won't enable them for compiler_builtins
|
||||
# which should ensure we still link everything correctly.
|
||||
debug-assertions = false
|
||||
overflow-checks = false
|
||||
|
||||
# For compiler-builtins we always use a high number of codegen units.
|
||||
# The goal here is to place every single intrinsic into its own object
|
||||
# file to avoid symbol clashes with the system libgcc if possible. Note
|
||||
|
@ -1693,11 +1693,15 @@ fn terminate_block(&mut self, reason: UnwindTerminateReason) -> Bx::BasicBlock {
|
||||
|
||||
self.set_debug_loc(&mut bx, mir::SourceInfo::outermost(self.mir.span));
|
||||
|
||||
let (fn_abi, fn_ptr, _instance) = common::build_langcall(&bx, None, reason.lang_item());
|
||||
let fn_ty = bx.fn_decl_backend_type(fn_abi);
|
||||
let (fn_abi, fn_ptr, instance) = common::build_langcall(&bx, None, reason.lang_item());
|
||||
if is_call_from_compiler_builtins_to_upstream_monomorphization(bx.tcx(), instance) {
|
||||
bx.abort();
|
||||
} else {
|
||||
let fn_ty = bx.fn_decl_backend_type(fn_abi);
|
||||
|
||||
let llret = bx.call(fn_ty, None, Some(fn_abi), fn_ptr, &[], funclet.as_ref());
|
||||
bx.apply_attrs_to_cleanup_callsite(llret);
|
||||
let llret = bx.call(fn_ty, None, Some(fn_abi), fn_ptr, &[], funclet.as_ref());
|
||||
bx.apply_attrs_to_cleanup_callsite(llret);
|
||||
}
|
||||
|
||||
bx.unreachable();
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
use rustc_index::bit_set::FiniteBitSet;
|
||||
use rustc_macros::HashStable;
|
||||
use rustc_middle::ty::normalize_erasing_regions::NormalizationError;
|
||||
use rustc_span::def_id::LOCAL_CRATE;
|
||||
use rustc_span::Symbol;
|
||||
|
||||
use std::assert_matches::assert_matches;
|
||||
@ -168,6 +169,11 @@ pub fn upstream_monomorphization(&self, tcx: TyCtxt<'tcx>) -> Option<CrateNum> {
|
||||
// If this a non-generic instance, it cannot be a shared monomorphization.
|
||||
self.args.non_erasable_generics(tcx, self.def_id()).next()?;
|
||||
|
||||
// compiler_builtins cannot use upstream monomorphizations.
|
||||
if tcx.is_compiler_builtins(LOCAL_CRATE) {
|
||||
return None;
|
||||
}
|
||||
|
||||
match self.def {
|
||||
InstanceDef::Item(def) => tcx
|
||||
.upstream_monomorphizations_for(def)
|
||||
|
@ -4,4 +4,5 @@ version = "0.0.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
object = "0.34.0"
|
||||
wasmparser = "0.118.2"
|
||||
|
@ -2,6 +2,7 @@
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::{Command, Output};
|
||||
|
||||
pub use object;
|
||||
pub use wasmparser;
|
||||
|
||||
pub fn out_dir() -> PathBuf {
|
||||
|
142
tests/run-make/compiler-builtins/rmake.rs
Normal file
142
tests/run-make/compiler-builtins/rmake.rs
Normal file
@ -0,0 +1,142 @@
|
||||
//! The compiler_builtins library is special. It can call functions in core, but it must not
|
||||
//! require linkage against a build of core. If it ever does, building the standard library *may*
|
||||
//! result in linker errors, depending on whether the linker in use applies optimizations first or
|
||||
//! resolves symbols first. So the portable and safe approach is to forbid such a linkage
|
||||
//! requirement entirely.
|
||||
//!
|
||||
//! In addition, whether compiler_builtins requires linkage against core can depend on optimization
|
||||
//! settings. Turning off optimizations and enabling debug assertions tends to produce the most
|
||||
//! dependence on core that is possible, so that is the configuration we test here.
|
||||
|
||||
#![deny(warnings)]
|
||||
|
||||
extern crate run_make_support;
|
||||
|
||||
use run_make_support::object;
|
||||
use run_make_support::object::read::archive::ArchiveFile;
|
||||
use run_make_support::object::read::Object;
|
||||
use run_make_support::object::ObjectSection;
|
||||
use run_make_support::object::ObjectSymbol;
|
||||
use run_make_support::object::RelocationTarget;
|
||||
use run_make_support::out_dir;
|
||||
use std::collections::HashSet;
|
||||
|
||||
const MANIFEST: &str = r#"
|
||||
[package]
|
||||
name = "scratch"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
path = "lib.rs""#;
|
||||
|
||||
fn main() {
|
||||
let target_dir = out_dir().join("target");
|
||||
let target = std::env::var("TARGET").unwrap();
|
||||
if target.starts_with("wasm") || target.starts_with("nvptx") {
|
||||
// wasm and nvptx targets don't produce rlib files that object can parse.
|
||||
return;
|
||||
}
|
||||
|
||||
println!("Testing compiler_builtins for {}", target);
|
||||
|
||||
// Set up the tiniest Cargo project: An empty no_std library. Just enough to run -Zbuild-std.
|
||||
let manifest_path = out_dir().join("Cargo.toml");
|
||||
std::fs::write(&manifest_path, MANIFEST.as_bytes()).unwrap();
|
||||
std::fs::write(out_dir().join("lib.rs"), b"#![no_std]").unwrap();
|
||||
|
||||
let path = std::env::var("PATH").unwrap();
|
||||
let rustc = std::env::var("RUSTC").unwrap();
|
||||
let bootstrap_cargo = std::env::var("BOOTSTRAP_CARGO").unwrap();
|
||||
let status = std::process::Command::new(bootstrap_cargo)
|
||||
.args([
|
||||
"build",
|
||||
"--manifest-path",
|
||||
manifest_path.to_str().unwrap(),
|
||||
"-Zbuild-std=core",
|
||||
"--target",
|
||||
&target,
|
||||
])
|
||||
.env_clear()
|
||||
.env("PATH", path)
|
||||
.env("RUSTC", rustc)
|
||||
.env("RUSTFLAGS", "-Copt-level=0 -Cdebug-assertions=yes")
|
||||
.env("CARGO_TARGET_DIR", &target_dir)
|
||||
.env("RUSTC_BOOTSTRAP", "1")
|
||||
.status()
|
||||
.unwrap();
|
||||
|
||||
assert!(status.success());
|
||||
|
||||
let rlibs_path = target_dir.join(target).join("debug").join("deps");
|
||||
let compiler_builtins_rlib = std::fs::read_dir(rlibs_path)
|
||||
.unwrap()
|
||||
.find_map(|e| {
|
||||
let path = e.unwrap().path();
|
||||
let file_name = path.file_name().unwrap().to_str().unwrap();
|
||||
if file_name.starts_with("libcompiler_builtins") && file_name.ends_with(".rlib") {
|
||||
Some(path)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
// rlib files are archives, where the archive members each a CGU, and we also have one called
|
||||
// lib.rmeta which is the encoded metadata. Each of the CGUs is an object file.
|
||||
let data = std::fs::read(compiler_builtins_rlib).unwrap();
|
||||
|
||||
let mut defined_symbols = HashSet::new();
|
||||
let mut undefined_relocations = HashSet::new();
|
||||
|
||||
let archive = ArchiveFile::parse(&*data).unwrap();
|
||||
for member in archive.members() {
|
||||
let member = member.unwrap();
|
||||
if member.name() == b"lib.rmeta" {
|
||||
continue;
|
||||
}
|
||||
let data = member.data(&*data).unwrap();
|
||||
let object = object::File::parse(&*data).unwrap();
|
||||
|
||||
// Record all defined symbols in this CGU.
|
||||
for symbol in object.symbols() {
|
||||
if !symbol.is_undefined() {
|
||||
let name = symbol.name().unwrap();
|
||||
defined_symbols.insert(name);
|
||||
}
|
||||
}
|
||||
|
||||
// Find any relocations against undefined symbols. Calls within this CGU are relocations
|
||||
// against a defined symbol.
|
||||
for (_offset, relocation) in object.sections().flat_map(|section| section.relocations()) {
|
||||
let RelocationTarget::Symbol(symbol_index) = relocation.target() else {
|
||||
continue;
|
||||
};
|
||||
let symbol = object.symbol_by_index(symbol_index).unwrap();
|
||||
if symbol.is_undefined() {
|
||||
let name = symbol.name().unwrap();
|
||||
undefined_relocations.insert(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We can have symbols in the compiler_builtins rlib that are actually from core, if they were
|
||||
// monomorphized in the compiler_builtins crate. This is totally fine, because though the call
|
||||
// is to a function in core, it's resolved internally.
|
||||
//
|
||||
// It is normal to have relocations against symbols not defined in the rlib for things like
|
||||
// unwinding, or math functions provided the target's platform libraries. Finding these is not
|
||||
// a problem, we want to specifically ban relocations against core which are not resolved
|
||||
// internally.
|
||||
undefined_relocations
|
||||
.retain(|symbol| !defined_symbols.contains(symbol) && symbol.contains("core"));
|
||||
|
||||
if !undefined_relocations.is_empty() {
|
||||
panic!(
|
||||
"compiler_builtins must not link against core, but it does. \n\
|
||||
These symbols may be undefined in a debug build of compiler_builtins:\n\
|
||||
{:?}",
|
||||
undefined_relocations
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user