Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit b3df0d7

Browse files
committed
Auto merge of rust-lang#122580 - saethlin:compiler-builtins-can-panic, r=pnkfelix
"Handle" calls to upstream monomorphizations in compiler_builtins This is pretty cooked, but I think it works. compiler-builtins has a long-standing problem that at link time, its rlib cannot contain any calls to `core`. And yet, in codegen we _love_ inserting calls to symbols in `core`, generally from various panic entrypoints. I intend this PR to attack that problem as completely as possible. When we generate a function call, we now check if we are generating a function call from `compiler_builtins` and whether the callee is a function which was not lowered in the current crate, meaning we will have to link to it. If those conditions are met, actually generating the call is asking for a linker error. So we don't. If the callee diverges, we lower to an abort with the same behavior as `core::intrinsics::abort`. If the callee does not diverge, we produce an error. This means that compiler-builtins can contain panics, but they'll SIGILL instead of panicking. I made non-diverging calls a compile error because I'm guessing that they'd mostly get into compiler-builtins by someone making a mistake while working on the crate, and compile errors are better than linker errors. We could turn such calls into aborts as well if that's preferred.
2 parents 1447f9d + 2f6fb23 commit b3df0d7

File tree

17 files changed

+284
-29
lines changed

17 files changed

+284
-29
lines changed

‎Cargo.lock‎

Lines changed: 32 additions & 8 deletions
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

@@ -2636,10 +2636,21 @@ dependencies = [
26362636
"memchr",
26372637
"rustc-std-workspace-alloc",
26382638
"rustc-std-workspace-core",
2639-
"ruzstd",
2639+
"ruzstd 0.5.0",
26402640
"wasmparser",
26412641
]
26422642

2643+
[[package]]
2644+
name = "object"
2645+
version = "0.34.0"
2646+
source = "registry+https://github.com/rust-lang/crates.io-index"
2647+
checksum = "d7090bae93f8585aad99e595b7073c5de9ba89fbd6b4e9f0cdd7a10177273ac8"
2648+
dependencies = [
2649+
"flate2",
2650+
"memchr",
2651+
"ruzstd 0.6.0",
2652+
]
2653+
26432654
[[package]]
26442655
name = "odht"
26452656
version = "0.3.1"
@@ -3323,6 +3334,7 @@ dependencies = [
33233334
name = "run_make_support"
33243335
version = "0.0.0"
33253336
dependencies = [
3337+
"object 0.34.0",
33263338
"wasmparser",
33273339
]
33283340

@@ -3634,7 +3646,7 @@ dependencies = [
36343646
"itertools 0.12.1",
36353647
"libc",
36363648
"measureme",
3637-
"object",
3649+
"object 0.32.2",
36383650
"rustc-demangle",
36393651
"rustc_ast",
36403652
"rustc_attr",
@@ -3670,7 +3682,7 @@ dependencies = [
36703682
"itertools 0.12.1",
36713683
"jobserver",
36723684
"libc",
3673-
"object",
3685+
"object 0.32.2",
36743686
"pathdiff",
36753687
"regex",
36763688
"rustc_arena",
@@ -3686,6 +3698,7 @@ dependencies = [
36863698
"rustc_macros",
36873699
"rustc_metadata",
36883700
"rustc_middle",
3701+
"rustc_monomorphize",
36893702
"rustc_query_system",
36903703
"rustc_serialize",
36913704
"rustc_session",
@@ -4630,7 +4643,7 @@ name = "rustc_target"
46304643
version = "0.0.0"
46314644
dependencies = [
46324645
"bitflags 2.4.2",
4633-
"object",
4646+
"object 0.32.2",
46344647
"rustc_abi",
46354648
"rustc_data_structures",
46364649
"rustc_feature",
@@ -4897,6 +4910,17 @@ dependencies = [
48974910
"twox-hash",
48984911
]
48994912

4913+
[[package]]
4914+
name = "ruzstd"
4915+
version = "0.6.0"
4916+
source = "registry+https://github.com/rust-lang/crates.io-index"
4917+
checksum = "5174a470eeb535a721ae9fdd6e291c2411a906b96592182d05217591d5c5cf7b"
4918+
dependencies = [
4919+
"byteorder",
4920+
"derive_more",
4921+
"twox-hash",
4922+
]
4923+
49004924
[[package]]
49014925
name = "ryu"
49024926
version = "1.0.17"
@@ -5200,7 +5224,7 @@ dependencies = [
52005224
"hermit-abi",
52015225
"libc",
52025226
"miniz_oxide",
5203-
"object",
5227+
"object 0.32.2",
52045228
"panic_abort",
52055229
"panic_unwind",
52065230
"profiler_builtins",
@@ -5517,7 +5541,7 @@ checksum = "4db52ee8fec06e119b692ef3dd2c4cf621a99204c1b8c47407870ed050305b9b"
55175541
dependencies = [
55185542
"gimli",
55195543
"hashbrown",
5520-
"object",
5544+
"object 0.32.2",
55215545
"tracing",
55225546
]
55235547

‎Cargo.toml‎

Lines changed: 0 additions & 9 deletions
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

‎compiler/rustc_codegen_cranelift/src/abi/mod.rs‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,11 @@ use std::borrow::Cow;
88

99
use cranelift_codegen::ir::SigRef;
1010
use cranelift_module::ModuleError;
11+
use rustc_codegen_ssa::errors::CompilerBuiltinsCannotCall;
1112
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
1213
use rustc_middle::ty::layout::FnAbiOf;
14+
use rustc_middle::ty::print::with_no_trimmed_paths;
15+
use rustc_monomorphize::is_call_from_compiler_builtins_to_upstream_monomorphization;
1316
use rustc_session::Session;
1417
use rustc_span::source_map::Spanned;
1518
use rustc_target::abi::call::{Conv, FnAbi};
@@ -372,6 +375,17 @@ pub(crate) fn codegen_terminator_call<'tcx>(
372375
ty::Instance::expect_resolve(fx.tcx, ty::ParamEnv::reveal_all(), def_id, fn_args)
373376
.polymorphize(fx.tcx);
374377

378+
if is_call_from_compiler_builtins_to_upstream_monomorphization(fx.tcx, instance) {
379+
if target.is_some() {
380+
let caller = with_no_trimmed_paths!(fx.tcx.def_path_str(fx.instance.def_id()));
381+
let callee = with_no_trimmed_paths!(fx.tcx.def_path_str(def_id));
382+
fx.tcx.dcx().emit_err(CompilerBuiltinsCannotCall { caller, callee });
383+
} else {
384+
fx.bcx.ins().trap(TrapCode::User(0));
385+
return;
386+
}
387+
}
388+
375389
if fx.tcx.symbol_name(instance).name.starts_with("llvm.") {
376390
crate::intrinsics::codegen_llvm_intrinsic_call(
377391
fx,

‎compiler/rustc_codegen_cranelift/src/base.rs‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use rustc_index::IndexVec;
88
use rustc_middle::ty::adjustment::PointerCoercion;
99
use rustc_middle::ty::layout::FnAbiOf;
1010
use rustc_middle::ty::print::with_no_trimmed_paths;
11+
use rustc_monomorphize::is_call_from_compiler_builtins_to_upstream_monomorphization;
1112

1213
use crate::constant::ConstantCx;
1314
use crate::debuginfo::FunctionDebugContext;
@@ -999,6 +1000,12 @@ fn codegen_panic_inner<'tcx>(
9991000
let def_id = fx.tcx.require_lang_item(lang_item, span);
10001001

10011002
let instance = Instance::mono(fx.tcx, def_id).polymorphize(fx.tcx);
1003+
1004+
if is_call_from_compiler_builtins_to_upstream_monomorphization(fx.tcx, instance) {
1005+
fx.bcx.ins().trap(TrapCode::User(0));
1006+
return;
1007+
}
1008+
10021009
let symbol_name = fx.tcx.symbol_name(instance).name;
10031010

10041011
fx.lib_call(

‎compiler/rustc_codegen_cranelift/src/lib.rs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ extern crate rustc_hir;
2121
extern crate rustc_incremental;
2222
extern crate rustc_index;
2323
extern crate rustc_metadata;
24+
extern crate rustc_monomorphize;
2425
extern crate rustc_session;
2526
extern crate rustc_span;
2627
extern crate rustc_target;

‎compiler/rustc_codegen_ssa/Cargo.toml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ rustc_index = { path = "../rustc_index" }
2525
rustc_macros = { path = "../rustc_macros" }
2626
rustc_metadata = { path = "../rustc_metadata" }
2727
rustc_middle = { path = "../rustc_middle" }
28+
rustc_monomorphize = { path = "../rustc_monomorphize" }
2829
rustc_query_system = { path = "../rustc_query_system" }
2930
rustc_serialize = { path = "../rustc_serialize" }
3031
rustc_session = { path = "../rustc_session" }

‎compiler/rustc_codegen_ssa/messages.ftl‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ codegen_ssa_cgu_not_recorded =
1616
1717
codegen_ssa_check_installed_visual_studio = please ensure that Visual Studio 2017 or later, or Build Tools for Visual Studio were installed with the Visual C++ option.
1818
19+
codegen_ssa_compiler_builtins_cannot_call =
20+
`compiler_builtins` cannot call functions through upstream monomorphizations; encountered invalid call from `{$caller}` to `{$callee}`
21+
1922
codegen_ssa_copy_path = could not copy {$from} to {$to}: {$error}
2023
2124
codegen_ssa_copy_path_buf = unable to copy {$source_file} to {$output_path}: {$error}

‎compiler/rustc_codegen_ssa/src/common.rs‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
use rustc_hir::LangItem;
44
use rustc_middle::mir;
5+
use rustc_middle::ty::Instance;
56
use rustc_middle::ty::{self, layout::TyAndLayout, Ty, TyCtxt};
67
use rustc_span::Span;
78

@@ -120,11 +121,11 @@ pub fn build_langcall<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
120121
bx: &Bx,
121122
span: Option<Span>,
122123
li: LangItem,
123-
) -> (Bx::FnAbiOfResult, Bx::Value) {
124+
) -> (Bx::FnAbiOfResult, Bx::Value,Instance<'tcx>) {
124125
let tcx = bx.tcx();
125126
let def_id = tcx.require_lang_item(li, span);
126127
let instance = ty::Instance::mono(tcx, def_id);
127-
(bx.fn_abi_of_instance(instance, ty::List::empty()), bx.get_fn_addr(instance))
128+
(bx.fn_abi_of_instance(instance, ty::List::empty()), bx.get_fn_addr(instance), instance)
128129
}
129130

130131
// To avoid UB from LLVM, these two functions mask RHS with an

‎compiler/rustc_codegen_ssa/src/errors.rs‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1030,3 +1030,10 @@ pub struct FailedToGetLayout<'tcx> {
10301030
pub struct ErrorCreatingRemarkDir {
10311031
pub error: std::io::Error,
10321032
}
1033+
1034+
#[derive(Diagnostic)]
1035+
#[diag(codegen_ssa_compiler_builtins_cannot_call)]
1036+
pub struct CompilerBuiltinsCannotCall {
1037+
pub caller: String,
1038+
pub callee: String,
1039+
}

‎compiler/rustc_codegen_ssa/src/mir/block.rs‎

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use super::{CachedLlbb, FunctionCx, LocalRef};
55

66
use crate::base;
77
use crate::common::{self, IntPredicate};
8+
use crate::errors::CompilerBuiltinsCannotCall;
89
use crate::meth;
910
use crate::traits::*;
1011
use crate::MemFlags;
@@ -16,6 +17,7 @@ use rustc_middle::mir::{self, AssertKind, BasicBlock, SwitchTargets, UnwindTermi
1617
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement};
1718
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
1819
use rustc_middle::ty::{self, Instance, Ty};
20+
use rustc_monomorphize::is_call_from_compiler_builtins_to_upstream_monomorphization;
1921
use rustc_session::config::OptLevel;
2022
use rustc_span::{source_map::Spanned, sym, Span};
2123
use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode, Reg};
@@ -157,8 +159,28 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
157159
destination: Option<(ReturnDest<'tcx, Bx::Value>, mir::BasicBlock)>,
158160
mut unwind: mir::UnwindAction,
159161
copied_constant_arguments: &[PlaceRef<'tcx, <Bx as BackendTypes>::Value>],
162+
instance: Option<Instance<'tcx>>,
160163
mergeable_succ: bool,
161164
) -> MergingSucc {
165+
let tcx = bx.tcx();
166+
if let Some(instance) = instance {
167+
if is_call_from_compiler_builtins_to_upstream_monomorphization(tcx, instance) {
168+
if destination.is_some() {
169+
let caller = with_no_trimmed_paths!(tcx.def_path_str(fx.instance.def_id()));
170+
let callee = with_no_trimmed_paths!(tcx.def_path_str(instance.def_id()));
171+
tcx.dcx().emit_err(CompilerBuiltinsCannotCall { caller, callee });
172+
} else {
173+
info!(
174+
"compiler_builtins call to diverging function {:?} replaced with abort",
175+
instance.def_id()
176+
);
177+
bx.abort();
178+
bx.unreachable();
179+
return MergingSucc::False;
180+
}
181+
}
182+
}
183+
162184
// If there is a cleanup block and the function we're calling can unwind, then
163185
// do an invoke, otherwise do a call.
164186
let fn_ty = bx.fn_decl_backend_type(fn_abi);
@@ -480,6 +502,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
480502
let ty = location.ty(self.mir, bx.tcx()).ty;
481503
let ty = self.monomorphize(ty);
482504
let drop_fn = Instance::resolve_drop_in_place(bx.tcx(), ty);
505+
let instance = drop_fn.clone();
483506

484507
if let ty::InstanceDef::DropGlue(_, None) = drop_fn.def {
485508
// we don't actually need to drop anything.
@@ -582,6 +605,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
582605
Some((ReturnDest::Nothing, target)),
583606
unwind,
584607
&[],
608+
Some(instance),
585609
mergeable_succ,
586610
)
587611
}
@@ -658,10 +682,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
658682
}
659683
};
660684

661-
let (fn_abi, llfn) = common::build_langcall(bx, Some(span), lang_item);
685+
let (fn_abi, llfn, instance) = common::build_langcall(bx, Some(span), lang_item);
662686

663687
// Codegen the actual panic invoke/call.
664-
let merging_succ = helper.do_call(self, bx, fn_abi, llfn, &args, None, unwind, &[], false);
688+
let merging_succ =
689+
helper.do_call(self, bx, fn_abi, llfn, &args, None, unwind, &[], Some(instance), false);
665690
assert_eq!(merging_succ, MergingSucc::False);
666691
MergingSucc::False
667692
}
@@ -677,7 +702,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
677702
self.set_debug_loc(bx, terminator.source_info);
678703

679704
// Obtain the panic entry point.
680-
let (fn_abi, llfn) = common::build_langcall(bx, Some(span), reason.lang_item());
705+
let (fn_abi, llfn, instance) = common::build_langcall(bx, Some(span), reason.lang_item());
681706

682707
// Codegen the actual panic invoke/call.
683708
let merging_succ = helper.do_call(
@@ -689,6 +714,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
689714
None,
690715
mir::UnwindAction::Unreachable,
691716
&[],
717+
Some(instance),
692718
false,
693719
);
694720
assert_eq!(merging_succ, MergingSucc::False);
@@ -738,7 +764,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
738764
let msg = bx.const_str(&msg_str);
739765

740766
// Obtain the panic entry point.
741-
let (fn_abi, llfn) =
767+
let (fn_abi, llfn, instance) =
742768
common::build_langcall(bx, Some(source_info.span), LangItem::PanicNounwind);
743769

744770
// Codegen the actual panic invoke/call.
@@ -751,6 +777,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
751777
target.as_ref().map(|bb| (ReturnDest::Nothing, *bb)),
752778
unwind,
753779
&[],
780+
Some(instance),
754781
mergeable_succ,
755782
)
756783
} else {
@@ -798,6 +825,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
798825
ty::FnPtr(_) => (None, Some(callee.immediate())),
799826
_ => bug!("{} is not callable", callee.layout.ty),
800827
};
828+
801829
let def = instance.map(|i| i.def);
802830

803831
if let Some(ty::InstanceDef::DropGlue(_, None)) = def {
@@ -1106,6 +1134,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
11061134
destination,
11071135
unwind,
11081136
&copied_constant_arguments,
1137+
instance,
11091138
mergeable_succ,
11101139
)
11111140
}
@@ -1664,11 +1693,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
16641693

16651694
self.set_debug_loc(&mut bx, mir::SourceInfo::outermost(self.mir.span));
16661695

1667-
let (fn_abi, fn_ptr) = common::build_langcall(&bx, None, reason.lang_item());
1668-
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);
16691701

1670-
let llret = bx.call(fn_ty, None, Some(fn_abi), fn_ptr, &[], funclet.as_ref());
1671-
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+
}
16721705

16731706
bx.unreachable();
16741707

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /