mir_build: check annotated functions w/out callers · rust-lang/rust@cc9a9ec (original) (raw)

`@@ -10,13 +10,12 @@ use rustc_hir::def_id::DefId;

`

10

10

`use rustc_index::Idx;

`

11

11

`use rustc_index::bit_set::BitSet;

`

12

12

`use rustc_middle::bug;

`

13

``

`-

use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};

`

``

13

`+

use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;

`

14

14

`use rustc_middle::mir::visit::*;

`

15

15

`use rustc_middle::mir::*;

`

16

16

`use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt, TypeFlags, TypeVisitableExt};

`

17

17

`use rustc_session::config::{DebugInfo, OptLevel};

`

18

18

`use rustc_span::source_map::Spanned;

`

19

``

`-

use rustc_span::sym;

`

20

19

`use tracing::{debug, instrument, trace, trace_span};

`

21

20

``

22

21

`use crate::cost_checker::CostChecker;

`

`@@ -120,7 +119,6 @@ trait Inliner<'tcx> {

`

120

119

`callsite: &CallSite<'tcx>,

`

121

120

`callee_body: &Body<'tcx>,

`

122

121

`callee_attrs: &CodegenFnAttrs,

`

123

``

`-

cross_crate_inlinable: bool,

`

124

122

`) -> Result<(), &'static str>;

`

125

123

``

126

124

`// 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> {

`

196

194

` _: &CallSite<'tcx>,

`

197

195

`callee_body: &Body<'tcx>,

`

198

196

`callee_attrs: &CodegenFnAttrs,

`

199

``

`-

_: bool,

`

200

197

`) -> Result<(), &'static str> {

`

201

198

`if callee_body.tainted_by_errors.is_some() {

`

202

199

`return Err("body has errors");

`

`@@ -215,14 +212,6 @@ impl<'tcx> Inliner<'tcx> for ForceInliner<'tcx> {

`

215

212

`// inline-asm is detected. LLVM will still possibly do an inline later on

`

216

213

`// if the no-attribute function ends up with the same instruction set anyway.

`

217

214

`Err("cannot move inline-asm across instruction sets")

`

218

``

`-

} else if callee_body

`

219

``

`-

.basic_blocks

`

220

``

`-

.iter()

`

221

``

`-

.any(|bb| matches!(bb.terminator().kind, TerminatorKind::TailCall { .. }))

`

222

``

`-

{

`

223

``

`-

// FIXME(explicit_tail_calls): figure out how exactly functions containing tail

`

224

``

`-

// calls can be inlined (and if they even should)

`

225

``

`-

Err("can't inline functions with tail calls")

`

226

215

`} else {

`

227

216

`Ok(())

`

228

217

`}

`

`@@ -348,7 +337,6 @@ impl<'tcx> Inliner<'tcx> for NormalInliner<'tcx> {

`

348

337

`callsite: &CallSite<'tcx>,

`

349

338

`callee_body: &Body<'tcx>,

`

350

339

`callee_attrs: &CodegenFnAttrs,

`

351

``

`-

cross_crate_inlinable: bool,

`

352

340

`) -> Result<(), &'static str> {

`

353

341

`let tcx = self.tcx();

`

354

342

``

`@@ -358,7 +346,7 @@ impl<'tcx> Inliner<'tcx> for NormalInliner<'tcx> {

`

358

346

``

359

347

`let mut threshold = if self.caller_is_inline_forwarder {

`

360

348

` tcx.sess.opts.unstable_opts.inline_mir_forwarder_threshold.unwrap_or(30)

`

361

``

`-

} else if cross_crate_inlinable {

`

``

349

`+

} else if tcx.cross_crate_inlinable(callsite.callee.def_id()) {

`

362

350

` tcx.sess.opts.unstable_opts.inline_mir_hint_threshold.unwrap_or(100)

`

363

351

`} else {

`

364

352

` tcx.sess.opts.unstable_opts.inline_mir_threshold.unwrap_or(50)

`

`@@ -587,16 +575,8 @@ fn try_inlining<'tcx, I: Inliner<'tcx>>(

`

587

575

`check_mir_is_available(inliner, caller_body, callsite.callee)?;

`

588

576

``

589

577

`let callee_attrs = tcx.codegen_fn_attrs(callsite.callee.def_id());

`

590

``

`-

let cross_crate_inlinable = tcx.cross_crate_inlinable(callsite.callee.def_id());

`

591

``

`-

check_codegen_attributes(inliner, callsite, callee_attrs, cross_crate_inlinable)?;

`

592

``

-

593

``

`-

// Intrinsic fallback bodies are automatically made cross-crate inlineable,

`

594

``

`-

// but at this stage we don't know whether codegen knows the intrinsic,

`

595

``

`-

// so just conservatively don't inline it. This also ensures that we do not

`

596

``

`-

// accidentally inline the body of an intrinsic that must be overridden.

`

597

``

`-

if tcx.has_attr(callsite.callee.def_id(), sym::rustc_intrinsic) {

`

598

``

`-

return Err("callee is an intrinsic");

`

599

``

`-

}

`

``

578

`+

rustc_mir_build::check_inline::is_inline_valid_on_fn(tcx, callsite.callee.def_id())?;

`

``

579

`+

check_codegen_attributes(inliner, callsite, callee_attrs)?;

`

600

580

``

601

581

`let terminator = caller_body[callsite.block].terminator.as_ref().unwrap();

`

602

582

`let TerminatorKind::Call { args, destination, .. } = &terminator.kind else { bug!() };

`

`@@ -610,7 +590,8 @@ fn try_inlining<'tcx, I: Inliner<'tcx>>(

`

610

590

`}

`

611

591

``

612

592

`let callee_body = try_instance_mir(tcx, callsite.callee.def)?;

`

613

``

`-

inliner.check_callee_mir_body(callsite, callee_body, callee_attrs, cross_crate_inlinable)?;

`

``

593

`+

rustc_mir_build::check_inline::is_inline_valid_on_body(tcx, callee_body)?;

`

``

594

`+

inliner.check_callee_mir_body(callsite, callee_body, callee_attrs)?;

`

614

595

``

615

596

`let Ok(callee_body) = callsite.callee.try_instantiate_mir_and_normalize_erasing_regions(

`

616

597

` tcx,

`

`@@ -775,38 +756,19 @@ fn check_codegen_attributes<'tcx, I: Inliner<'tcx>>(

`

775

756

`inliner: &I,

`

776

757

`callsite: &CallSite<'tcx>,

`

777

758

`callee_attrs: &CodegenFnAttrs,

`

778

``

`-

cross_crate_inlinable: bool,

`

779

759

`) -> Result<(), &'static str> {

`

780

760

`let tcx = inliner.tcx();

`

781

``

`-

if tcx.has_attr(callsite.callee.def_id(), sym::rustc_no_mir_inline) {

`

782

``

`-

return Err("#[rustc_no_mir_inline]");

`

783

``

`-

}

`

784

``

-

785

761

`if let InlineAttr::Never = callee_attrs.inline {

`

786

762

`return Err("never inline attribute");

`

787

763

`}

`

788

764

``

789

``

`-

// FIXME(#127234): Coverage instrumentation currently doesn't handle inlined

`

790

``

`-

// MIR correctly when Modified Condition/Decision Coverage is enabled.

`

791

``

`-

if tcx.sess.instrument_coverage_mcdc() {

`

792

``

`-

return Err("incompatible with MC/DC coverage");

`

793

``

`-

}

`

794

``

-

795

765

`// Reachability pass defines which functions are eligible for inlining. Generally inlining

`

796

766

`// other functions is incorrect because they could reference symbols that aren't exported.

`

797

767

`let is_generic = callsite.callee.args.non_erasable_generics().next().is_some();

`

798

``

`-

if !is_generic && !cross_crate_inlinable {

`

``

768

`+

if !is_generic && !tcx.cross_crate_inlinable(callsite.callee.def_id()) {

`

799

769

`return Err("not exported");

`

800

770

`}

`

801

771

``

802

``

`-

if callsite.fn_sig.c_variadic() {

`

803

``

`-

return Err("C variadic");

`

804

``

`-

}

`

805

``

-

806

``

`-

if callee_attrs.flags.contains(CodegenFnAttrFlags::COLD) {

`

807

``

`-

return Err("cold");

`

808

``

`-

}

`

809

``

-

810

772

`let codegen_fn_attrs = tcx.codegen_fn_attrs(inliner.caller_def_id());

`

811

773

`if callee_attrs.no_sanitize != codegen_fn_attrs.no_sanitize {

`

812

774

`return Err("incompatible sanitizer set");

`