Skip to content

Commit 34feef3

Browse files
committed
Handle calls to upstream monomorphizations in compiler_builtins
1 parent 1ca424c commit 34feef3

File tree

9 files changed

+57
-9
lines changed

9 files changed

+57
-9
lines changed

Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -3673,6 +3673,7 @@ dependencies = [
36733673
"rustc_macros",
36743674
"rustc_metadata",
36753675
"rustc_middle",
3676+
"rustc_monomorphize",
36763677
"rustc_query_system",
36773678
"rustc_serialize",
36783679
"rustc_session",

compiler/rustc_codegen_ssa/Cargo.toml

+1
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

+3
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 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

+3-2
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

+6
Original file line numberDiff line numberDiff line change
@@ -1030,3 +1030,9 @@ 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 callee: String,
1038+
}

compiler/rustc_codegen_ssa/src/mir/block.rs

+38-5
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,7 +17,9 @@ 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::should_codegen_locally;
1921
use rustc_session::config::OptLevel;
22+
use rustc_span::def_id::LOCAL_CRATE;
2023
use rustc_span::{source_map::Spanned, sym, Span};
2124
use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode, Reg};
2225
use rustc_target::abi::{self, HasDataLayout, WrappingRange};
@@ -157,8 +160,31 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
157160
destination: Option<(ReturnDest<'tcx, Bx::Value>, mir::BasicBlock)>,
158161
mut unwind: mir::UnwindAction,
159162
copied_constant_arguments: &[PlaceRef<'tcx, <Bx as BackendTypes>::Value>],
163+
instance: Option<Instance<'tcx>>,
160164
mergeable_succ: bool,
161165
) -> MergingSucc {
166+
let tcx = bx.tcx();
167+
if let Some(instance) = instance {
168+
let def_id = instance.def_id();
169+
if !def_id.is_local()
170+
&& tcx.is_compiler_builtins(LOCAL_CRATE)
171+
&& !should_codegen_locally(tcx, &instance)
172+
{
173+
if destination.is_some() {
174+
let callee = with_no_trimmed_paths!(tcx.def_path_str(def_id));
175+
tcx.dcx().emit_err(CompilerBuiltinsCannotCall { callee });
176+
} else {
177+
info!(
178+
"compiler_builtins call to diverging function {:?} replaced with abort",
179+
instance.def_id()
180+
);
181+
bx.abort();
182+
bx.unreachable();
183+
return MergingSucc::False;
184+
}
185+
}
186+
}
187+
162188
// If there is a cleanup block and the function we're calling can unwind, then
163189
// do an invoke, otherwise do a call.
164190
let fn_ty = bx.fn_decl_backend_type(fn_abi);
@@ -480,6 +506,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
480506
let ty = location.ty(self.mir, bx.tcx()).ty;
481507
let ty = self.monomorphize(ty);
482508
let drop_fn = Instance::resolve_drop_in_place(bx.tcx(), ty);
509+
let instance = drop_fn.clone();
483510

484511
if let ty::InstanceDef::DropGlue(_, None) = drop_fn.def {
485512
// we don't actually need to drop anything.
@@ -582,6 +609,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
582609
Some((ReturnDest::Nothing, target)),
583610
unwind,
584611
&[],
612+
Some(instance),
585613
mergeable_succ,
586614
)
587615
}
@@ -658,10 +686,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
658686
}
659687
};
660688

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

663691
// Codegen the actual panic invoke/call.
664-
let merging_succ = helper.do_call(self, bx, fn_abi, llfn, &args, None, unwind, &[], false);
692+
let merging_succ =
693+
helper.do_call(self, bx, fn_abi, llfn, &args, None, unwind, &[], Some(instance), false);
665694
assert_eq!(merging_succ, MergingSucc::False);
666695
MergingSucc::False
667696
}
@@ -677,7 +706,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
677706
self.set_debug_loc(bx, terminator.source_info);
678707

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

682711
// Codegen the actual panic invoke/call.
683712
let merging_succ = helper.do_call(
@@ -689,6 +718,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
689718
None,
690719
mir::UnwindAction::Unreachable,
691720
&[],
721+
Some(instance),
692722
false,
693723
);
694724
assert_eq!(merging_succ, MergingSucc::False);
@@ -738,7 +768,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
738768
let msg = bx.const_str(&msg_str);
739769

740770
// Obtain the panic entry point.
741-
let (fn_abi, llfn) =
771+
let (fn_abi, llfn, instance) =
742772
common::build_langcall(bx, Some(source_info.span), LangItem::PanicNounwind);
743773

744774
// Codegen the actual panic invoke/call.
@@ -751,6 +781,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
751781
target.as_ref().map(|bb| (ReturnDest::Nothing, *bb)),
752782
unwind,
753783
&[],
784+
Some(instance),
754785
mergeable_succ,
755786
)
756787
} else {
@@ -798,6 +829,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
798829
ty::FnPtr(_) => (None, Some(callee.immediate())),
799830
_ => bug!("{} is not callable", callee.layout.ty),
800831
};
832+
801833
let def = instance.map(|i| i.def);
802834

803835
if let Some(ty::InstanceDef::DropGlue(_, None)) = def {
@@ -1106,6 +1138,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
11061138
destination,
11071139
unwind,
11081140
&copied_constant_arguments,
1141+
instance,
11091142
mergeable_succ,
11101143
)
11111144
}
@@ -1664,7 +1697,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
16641697

16651698
self.set_debug_loc(&mut bx, mir::SourceInfo::outermost(self.mir.span));
16661699

1667-
let (fn_abi, fn_ptr) = common::build_langcall(&bx, None, reason.lang_item());
1700+
let (fn_abi, fn_ptr, _instance) = common::build_langcall(&bx, None, reason.lang_item());
16681701
let fn_ty = bx.fn_decl_backend_type(fn_abi);
16691702

16701703
let llret = bx.call(fn_ty, None, Some(fn_abi), fn_ptr, &[], funclet.as_ref());

compiler/rustc_codegen_ssa/src/size_of_val.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
6262
let msg = bx.const_str(&msg_str);
6363

6464
// Obtain the panic entry point.
65-
let (fn_abi, llfn) = common::build_langcall(bx, None, LangItem::PanicNounwind);
65+
let (fn_abi, llfn, _instance) =
66+
common::build_langcall(bx, None, LangItem::PanicNounwind);
6667

6768
// Generate the call.
6869
// Cannot use `do_call` since we don't have a MIR terminator so we can't create a `TerminationCodegenHelper`.

compiler/rustc_monomorphize/src/collector.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1020,7 +1020,7 @@ fn visit_instance_use<'tcx>(
10201020

10211021
/// Returns `true` if we should codegen an instance in the local crate, or returns `false` if we
10221022
/// can just link to the upstream crate and therefore don't need a mono item.
1023-
fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) -> bool {
1023+
pub fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) -> bool {
10241024
let Some(def_id) = instance.def.def_id_if_not_guaranteed_local_codegen() else {
10251025
return true;
10261026
};

compiler/rustc_monomorphize/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ mod partitioning;
2020
mod polymorphize;
2121
mod util;
2222

23+
pub use collector::should_codegen_locally;
24+
2325
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
2426

2527
fn custom_coerce_unsize_info<'tcx>(

0 commit comments

Comments
 (0)