diff options
| author | David Wood <david.wood2@arm.com> | 2025-01-07 11:27:04 +0000 |
|---|---|---|
| committer | David Wood <david.wood2@arm.com> | 2025-01-10 18:37:57 +0000 |
| commit | cc9a9ecccb2fbbb7687ed076e06411c2f4ac5fbb (patch) | |
| tree | c2ac8174b0be897938a5a801c58a97a87eee2b1d /compiler/rustc_mir_transform/src/inline.rs | |
| parent | ce602acfc22724c30b6154f650225d2e1d1550ed (diff) | |
| download | rust-cc9a9ecccb2fbbb7687ed076e06411c2f4ac5fbb.tar.gz rust-cc9a9ecccb2fbbb7687ed076e06411c2f4ac5fbb.zip | |
mir_build: check annotated functions w/out callers
Diffstat (limited to 'compiler/rustc_mir_transform/src/inline.rs')
| -rw-r--r-- | compiler/rustc_mir_transform/src/inline.rs | 52 |
1 files changed, 7 insertions, 45 deletions
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 44c6d8190f1..e4daa2b9757 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -10,13 +10,12 @@ use rustc_hir::def_id::DefId; use rustc_index::Idx; use rustc_index::bit_set::BitSet; use rustc_middle::bug; -use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; +use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::mir::visit::*; use rustc_middle::mir::*; use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt, TypeFlags, TypeVisitableExt}; use rustc_session::config::{DebugInfo, OptLevel}; use rustc_span::source_map::Spanned; -use rustc_span::sym; use tracing::{debug, instrument, trace, trace_span}; use crate::cost_checker::CostChecker; @@ -120,7 +119,6 @@ trait Inliner<'tcx> { callsite: &CallSite<'tcx>, callee_body: &Body<'tcx>, callee_attrs: &CodegenFnAttrs, - cross_crate_inlinable: bool, ) -> Result<(), &'static str>; // How many callsites in a body are we allowed to inline? We need to limit this in order @@ -196,7 +194,6 @@ impl<'tcx> Inliner<'tcx> for ForceInliner<'tcx> { _: &CallSite<'tcx>, callee_body: &Body<'tcx>, callee_attrs: &CodegenFnAttrs, - _: bool, ) -> Result<(), &'static str> { if callee_body.tainted_by_errors.is_some() { return Err("body has errors"); @@ -215,14 +212,6 @@ impl<'tcx> Inliner<'tcx> for ForceInliner<'tcx> { // inline-asm is detected. LLVM will still possibly do an inline later on // if the no-attribute function ends up with the same instruction set anyway. Err("cannot move inline-asm across instruction sets") - } else if callee_body - .basic_blocks - .iter() - .any(|bb| matches!(bb.terminator().kind, TerminatorKind::TailCall { .. })) - { - // FIXME(explicit_tail_calls): figure out how exactly functions containing tail - // calls can be inlined (and if they even should) - Err("can't inline functions with tail calls") } else { Ok(()) } @@ -348,7 +337,6 @@ impl<'tcx> Inliner<'tcx> for NormalInliner<'tcx> { callsite: &CallSite<'tcx>, callee_body: &Body<'tcx>, callee_attrs: &CodegenFnAttrs, - cross_crate_inlinable: bool, ) -> Result<(), &'static str> { let tcx = self.tcx(); @@ -358,7 +346,7 @@ impl<'tcx> Inliner<'tcx> for NormalInliner<'tcx> { let mut threshold = if self.caller_is_inline_forwarder { tcx.sess.opts.unstable_opts.inline_mir_forwarder_threshold.unwrap_or(30) - } else if cross_crate_inlinable { + } else if tcx.cross_crate_inlinable(callsite.callee.def_id()) { tcx.sess.opts.unstable_opts.inline_mir_hint_threshold.unwrap_or(100) } else { tcx.sess.opts.unstable_opts.inline_mir_threshold.unwrap_or(50) @@ -587,16 +575,8 @@ fn try_inlining<'tcx, I: Inliner<'tcx>>( check_mir_is_available(inliner, caller_body, callsite.callee)?; let callee_attrs = tcx.codegen_fn_attrs(callsite.callee.def_id()); - let cross_crate_inlinable = tcx.cross_crate_inlinable(callsite.callee.def_id()); - check_codegen_attributes(inliner, callsite, callee_attrs, cross_crate_inlinable)?; - - // Intrinsic fallback bodies are automatically made cross-crate inlineable, - // but at this stage we don't know whether codegen knows the intrinsic, - // so just conservatively don't inline it. This also ensures that we do not - // accidentally inline the body of an intrinsic that *must* be overridden. - if tcx.has_attr(callsite.callee.def_id(), sym::rustc_intrinsic) { - return Err("callee is an intrinsic"); - } + rustc_mir_build::check_inline::is_inline_valid_on_fn(tcx, callsite.callee.def_id())?; + check_codegen_attributes(inliner, callsite, callee_attrs)?; let terminator = caller_body[callsite.block].terminator.as_ref().unwrap(); let TerminatorKind::Call { args, destination, .. } = &terminator.kind else { bug!() }; @@ -610,7 +590,8 @@ fn try_inlining<'tcx, I: Inliner<'tcx>>( } let callee_body = try_instance_mir(tcx, callsite.callee.def)?; - inliner.check_callee_mir_body(callsite, callee_body, callee_attrs, cross_crate_inlinable)?; + rustc_mir_build::check_inline::is_inline_valid_on_body(tcx, callee_body)?; + inliner.check_callee_mir_body(callsite, callee_body, callee_attrs)?; let Ok(callee_body) = callsite.callee.try_instantiate_mir_and_normalize_erasing_regions( tcx, @@ -775,38 +756,19 @@ fn check_codegen_attributes<'tcx, I: Inliner<'tcx>>( inliner: &I, callsite: &CallSite<'tcx>, callee_attrs: &CodegenFnAttrs, - cross_crate_inlinable: bool, ) -> Result<(), &'static str> { let tcx = inliner.tcx(); - if tcx.has_attr(callsite.callee.def_id(), sym::rustc_no_mir_inline) { - return Err("#[rustc_no_mir_inline]"); - } - if let InlineAttr::Never = callee_attrs.inline { return Err("never inline attribute"); } - // FIXME(#127234): Coverage instrumentation currently doesn't handle inlined - // MIR correctly when Modified Condition/Decision Coverage is enabled. - if tcx.sess.instrument_coverage_mcdc() { - return Err("incompatible with MC/DC coverage"); - } - // Reachability pass defines which functions are eligible for inlining. Generally inlining // other functions is incorrect because they could reference symbols that aren't exported. let is_generic = callsite.callee.args.non_erasable_generics().next().is_some(); - if !is_generic && !cross_crate_inlinable { + if !is_generic && !tcx.cross_crate_inlinable(callsite.callee.def_id()) { return Err("not exported"); } - if callsite.fn_sig.c_variadic() { - return Err("C variadic"); - } - - if callee_attrs.flags.contains(CodegenFnAttrFlags::COLD) { - return Err("cold"); - } - let codegen_fn_attrs = tcx.codegen_fn_attrs(inliner.caller_def_id()); if callee_attrs.no_sanitize != codegen_fn_attrs.no_sanitize { return Err("incompatible sanitizer set"); |
