mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
Auto merge of #116505 - saethlin:infer-inline, r=cjgillot
Automatically enable cross-crate inlining for small functions This is basically reviving https://github.com/rust-lang/rust/pull/70550 The `#[inline]` attribute can have a significant impact on code generation or runtime performance (because it enables inlining between CGUs where it would normally not happen) and also on compile-time performance (because it enables MIR inlining). But it has to be added manually, which is awkward. This PR factors whether a DefId is cross-crate inlinable into a query, and replaces all uses of `CodegenFnAttrs::requests_inline` with this new query. The new query incorporates all the other logic that is used to determine whether a Def should be treated as cross-crate-inlinable, and as a last step inspects the function's optimized_mir to determine if it should be treated as cross-crate-inlinable. The heuristic implemented here is deliberately conservative; we only infer inlinability for functions whose optimized_mir does not contain any calls or asserts. I plan to study adjusting the cost model later, but for now the compile time implications of this change are so significant that I think this very crude heuristic is well worth landing.
This commit is contained in:
commit
5d5edf0248
@ -770,6 +770,7 @@ fn test_unstable_options_tracking_hash() {
|
||||
);
|
||||
tracked!(codegen_backend, Some("abc".to_string()));
|
||||
tracked!(crate_attr, vec!["abc".to_string()]);
|
||||
tracked!(cross_crate_inline_threshold, Some(200));
|
||||
tracked!(debug_info_for_profiling, true);
|
||||
tracked!(debug_macros, true);
|
||||
tracked!(dep_info_omit_d_target, true);
|
||||
|
@ -1273,6 +1273,10 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
||||
self.root.tables.optimized_mir.get(self, id).is_some()
|
||||
}
|
||||
|
||||
fn cross_crate_inlinable(self, id: DefIndex) -> bool {
|
||||
self.root.tables.cross_crate_inlinable.get(self, id).unwrap_or(false)
|
||||
}
|
||||
|
||||
fn get_fn_has_self_parameter(self, id: DefIndex, sess: &'a Session) -> bool {
|
||||
self.root
|
||||
.tables
|
||||
|
@ -287,6 +287,7 @@ provide! { tcx, def_id, other, cdata,
|
||||
item_attrs => { tcx.arena.alloc_from_iter(cdata.get_item_attrs(def_id.index, tcx.sess)) }
|
||||
is_mir_available => { cdata.is_item_mir_available(def_id.index) }
|
||||
is_ctfe_mir_available => { cdata.is_ctfe_mir_available(def_id.index) }
|
||||
cross_crate_inlinable => { cdata.cross_crate_inlinable(def_id.index) }
|
||||
|
||||
dylib_dependency_formats => { cdata.get_dylib_dependency_formats(tcx) }
|
||||
is_private_dep => {
|
||||
|
@ -1046,7 +1046,7 @@ fn should_encode_mir(
|
||||
|| (tcx.sess.opts.output_types.should_codegen()
|
||||
&& reachable_set.contains(&def_id)
|
||||
&& (generics.requires_monomorphization(tcx)
|
||||
|| tcx.codegen_fn_attrs(def_id).requests_inline()));
|
||||
|| tcx.cross_crate_inlinable(def_id)));
|
||||
// The function has a `const` modifier or is in a `#[const_trait]`.
|
||||
let is_const_fn = tcx.is_const_fn_raw(def_id.to_def_id())
|
||||
|| tcx.is_const_default_method(def_id.to_def_id());
|
||||
@ -1615,6 +1615,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
debug!("EntryBuilder::encode_mir({:?})", def_id);
|
||||
if encode_opt {
|
||||
record!(self.tables.optimized_mir[def_id.to_def_id()] <- tcx.optimized_mir(def_id));
|
||||
self.tables
|
||||
.cross_crate_inlinable
|
||||
.set(def_id.to_def_id().index, Some(self.tcx.cross_crate_inlinable(def_id)));
|
||||
record!(self.tables.closure_saved_names_of_captured_variables[def_id.to_def_id()]
|
||||
<- tcx.closure_saved_names_of_captured_variables(def_id));
|
||||
|
||||
|
@ -427,6 +427,7 @@ define_tables! {
|
||||
object_lifetime_default: Table<DefIndex, LazyValue<ObjectLifetimeDefault>>,
|
||||
optimized_mir: Table<DefIndex, LazyValue<mir::Body<'static>>>,
|
||||
mir_for_ctfe: Table<DefIndex, LazyValue<mir::Body<'static>>>,
|
||||
cross_crate_inlinable: Table<DefIndex, bool>,
|
||||
closure_saved_names_of_captured_variables: Table<DefIndex, LazyValue<IndexVec<FieldIdx, Symbol>>>,
|
||||
mir_generator_witnesses: Table<DefIndex, LazyValue<mir::GeneratorLayout<'static>>>,
|
||||
promoted_mir: Table<DefIndex, LazyValue<IndexVec<mir::Promoted, mir::Body<'static>>>>,
|
||||
|
@ -299,6 +299,30 @@ impl FixedSizeEncoding for bool {
|
||||
}
|
||||
}
|
||||
|
||||
impl FixedSizeEncoding for Option<bool> {
|
||||
type ByteArray = [u8; 1];
|
||||
|
||||
#[inline]
|
||||
fn from_bytes(b: &[u8; 1]) -> Self {
|
||||
match b[0] {
|
||||
0 => Some(false),
|
||||
1 => Some(true),
|
||||
2 => None,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_to_bytes(self, b: &mut [u8; 1]) {
|
||||
debug_assert!(!self.is_default());
|
||||
b[0] = match self {
|
||||
Some(false) => 0,
|
||||
Some(true) => 1,
|
||||
None => 2,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
impl FixedSizeEncoding for UnusedGenericParams {
|
||||
type ByteArray = [u8; 4];
|
||||
|
||||
|
@ -126,14 +126,6 @@ impl CodegenFnAttrs {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if `#[inline]` or `#[inline(always)]` is present.
|
||||
pub fn requests_inline(&self) -> bool {
|
||||
match self.inline {
|
||||
InlineAttr::Hint | InlineAttr::Always => true,
|
||||
InlineAttr::None | InlineAttr::Never => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if it looks like this symbol needs to be exported, for example:
|
||||
///
|
||||
/// * `#[no_mangle]` is present
|
||||
|
@ -2202,6 +2202,11 @@ rustc_queries! {
|
||||
query generics_require_sized_self(def_id: DefId) -> bool {
|
||||
desc { "check whether the item has a `where Self: Sized` bound" }
|
||||
}
|
||||
|
||||
query cross_crate_inlinable(def_id: DefId) -> bool {
|
||||
desc { "whether the item should be made inlinable across crates" }
|
||||
separate_provide_extern
|
||||
}
|
||||
}
|
||||
|
||||
rustc_query_append! { define_callbacks! }
|
||||
|
@ -245,16 +245,15 @@ impl<'tcx> InstanceDef<'tcx> {
|
||||
// drops of `Option::None` before LTO. We also respect the intent of
|
||||
// `#[inline]` on `Drop::drop` implementations.
|
||||
return ty.ty_adt_def().map_or(true, |adt_def| {
|
||||
adt_def.destructor(tcx).map_or_else(
|
||||
|| adt_def.is_enum(),
|
||||
|dtor| tcx.codegen_fn_attrs(dtor.did).requests_inline(),
|
||||
)
|
||||
adt_def
|
||||
.destructor(tcx)
|
||||
.map_or_else(|| adt_def.is_enum(), |dtor| tcx.cross_crate_inlinable(dtor.did))
|
||||
});
|
||||
}
|
||||
if let ty::InstanceDef::ThreadLocalShim(..) = *self {
|
||||
return false;
|
||||
}
|
||||
tcx.codegen_fn_attrs(self.def_id()).requests_inline()
|
||||
tcx.cross_crate_inlinable(self.def_id())
|
||||
}
|
||||
|
||||
pub fn requires_caller_location(&self, tcx: TyCtxt<'_>) -> bool {
|
||||
|
119
compiler/rustc_mir_transform/src/cross_crate_inline.rs
Normal file
119
compiler/rustc_mir_transform/src/cross_crate_inline.rs
Normal file
@ -0,0 +1,119 @@
|
||||
use rustc_attr::InlineAttr;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_middle::mir::visit::Visitor;
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::config::OptLevel;
|
||||
|
||||
pub fn provide(providers: &mut Providers) {
|
||||
providers.cross_crate_inlinable = cross_crate_inlinable;
|
||||
}
|
||||
|
||||
fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
|
||||
let codegen_fn_attrs = tcx.codegen_fn_attrs(def_id);
|
||||
// If this has an extern indicator, then this function is globally shared and thus will not
|
||||
// generate cgu-internal copies which would make it cross-crate inlinable.
|
||||
if codegen_fn_attrs.contains_extern_indicator() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Obey source annotations first; this is important because it means we can use
|
||||
// #[inline(never)] to force code generation.
|
||||
match codegen_fn_attrs.inline {
|
||||
InlineAttr::Never => return false,
|
||||
InlineAttr::Hint | InlineAttr::Always => return true,
|
||||
_ => {}
|
||||
}
|
||||
|
||||
// This just reproduces the logic from Instance::requires_inline.
|
||||
match tcx.def_kind(def_id) {
|
||||
DefKind::Ctor(..) | DefKind::Closure => return true,
|
||||
DefKind::Fn | DefKind::AssocFn => {}
|
||||
_ => return false,
|
||||
}
|
||||
|
||||
// Don't do any inference when incremental compilation is enabled; the additional inlining that
|
||||
// inference permits also creates more work for small edits.
|
||||
if tcx.sess.opts.incremental.is_some() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't do any inference unless optimizations are enabled.
|
||||
if matches!(tcx.sess.opts.optimize, OptLevel::No) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if !tcx.is_mir_available(def_id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let mir = tcx.optimized_mir(def_id);
|
||||
let mut checker =
|
||||
CostChecker { tcx, callee_body: mir, calls: 0, statements: 0, landing_pads: 0, resumes: 0 };
|
||||
checker.visit_body(mir);
|
||||
checker.calls == 0
|
||||
&& checker.resumes == 0
|
||||
&& checker.landing_pads == 0
|
||||
&& checker.statements
|
||||
<= tcx.sess.opts.unstable_opts.cross_crate_inline_threshold.unwrap_or(100)
|
||||
}
|
||||
|
||||
struct CostChecker<'b, 'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
callee_body: &'b Body<'tcx>,
|
||||
calls: usize,
|
||||
statements: usize,
|
||||
landing_pads: usize,
|
||||
resumes: usize,
|
||||
}
|
||||
|
||||
impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
|
||||
fn visit_statement(&mut self, statement: &Statement<'tcx>, _: Location) {
|
||||
// Don't count StorageLive/StorageDead in the inlining cost.
|
||||
match statement.kind {
|
||||
StatementKind::StorageLive(_)
|
||||
| StatementKind::StorageDead(_)
|
||||
| StatementKind::Deinit(_)
|
||||
| StatementKind::Nop => {}
|
||||
_ => self.statements += 1,
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, _: Location) {
|
||||
let tcx = self.tcx;
|
||||
match terminator.kind {
|
||||
TerminatorKind::Drop { ref place, unwind, .. } => {
|
||||
let ty = place.ty(self.callee_body, tcx).ty;
|
||||
if !ty.is_trivially_pure_clone_copy() {
|
||||
self.calls += 1;
|
||||
if let UnwindAction::Cleanup(_) = unwind {
|
||||
self.landing_pads += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
TerminatorKind::Call { unwind, .. } => {
|
||||
self.calls += 1;
|
||||
if let UnwindAction::Cleanup(_) = unwind {
|
||||
self.landing_pads += 1;
|
||||
}
|
||||
}
|
||||
TerminatorKind::Assert { unwind, .. } => {
|
||||
self.calls += 1;
|
||||
if let UnwindAction::Cleanup(_) = unwind {
|
||||
self.landing_pads += 1;
|
||||
}
|
||||
}
|
||||
TerminatorKind::UnwindResume => self.resumes += 1,
|
||||
TerminatorKind::InlineAsm { unwind, .. } => {
|
||||
self.statements += 1;
|
||||
if let UnwindAction::Cleanup(_) = unwind {
|
||||
self.landing_pads += 1;
|
||||
}
|
||||
}
|
||||
TerminatorKind::Return => {}
|
||||
_ => self.statements += 1,
|
||||
}
|
||||
}
|
||||
}
|
@ -169,8 +169,11 @@ impl<'tcx> Inliner<'tcx> {
|
||||
caller_body: &mut Body<'tcx>,
|
||||
callsite: &CallSite<'tcx>,
|
||||
) -> Result<std::ops::Range<BasicBlock>, &'static str> {
|
||||
self.check_mir_is_available(caller_body, &callsite.callee)?;
|
||||
|
||||
let callee_attrs = self.tcx.codegen_fn_attrs(callsite.callee.def_id());
|
||||
self.check_codegen_attributes(callsite, callee_attrs)?;
|
||||
let cross_crate_inlinable = self.tcx.cross_crate_inlinable(callsite.callee.def_id());
|
||||
self.check_codegen_attributes(callsite, callee_attrs, cross_crate_inlinable)?;
|
||||
|
||||
let terminator = caller_body[callsite.block].terminator.as_ref().unwrap();
|
||||
let TerminatorKind::Call { args, destination, .. } = &terminator.kind else { bug!() };
|
||||
@ -183,9 +186,8 @@ impl<'tcx> Inliner<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
self.check_mir_is_available(caller_body, &callsite.callee)?;
|
||||
let callee_body = try_instance_mir(self.tcx, callsite.callee.def)?;
|
||||
self.check_mir_body(callsite, callee_body, callee_attrs)?;
|
||||
self.check_mir_body(callsite, callee_body, callee_attrs, cross_crate_inlinable)?;
|
||||
|
||||
if !self.tcx.consider_optimizing(|| {
|
||||
format!("Inline {:?} into {:?}", callsite.callee, caller_body.source)
|
||||
@ -401,6 +403,7 @@ impl<'tcx> Inliner<'tcx> {
|
||||
&self,
|
||||
callsite: &CallSite<'tcx>,
|
||||
callee_attrs: &CodegenFnAttrs,
|
||||
cross_crate_inlinable: bool,
|
||||
) -> Result<(), &'static str> {
|
||||
if let InlineAttr::Never = callee_attrs.inline {
|
||||
return Err("never inline hint");
|
||||
@ -414,7 +417,7 @@ impl<'tcx> Inliner<'tcx> {
|
||||
.non_erasable_generics(self.tcx, callsite.callee.def_id())
|
||||
.next()
|
||||
.is_some();
|
||||
if !is_generic && !callee_attrs.requests_inline() {
|
||||
if !is_generic && !cross_crate_inlinable {
|
||||
return Err("not exported");
|
||||
}
|
||||
|
||||
@ -456,10 +459,11 @@ impl<'tcx> Inliner<'tcx> {
|
||||
callsite: &CallSite<'tcx>,
|
||||
callee_body: &Body<'tcx>,
|
||||
callee_attrs: &CodegenFnAttrs,
|
||||
cross_crate_inlinable: bool,
|
||||
) -> Result<(), &'static str> {
|
||||
let tcx = self.tcx;
|
||||
|
||||
let mut threshold = if callee_attrs.requests_inline() {
|
||||
let mut threshold = if cross_crate_inlinable {
|
||||
self.tcx.sess.opts.unstable_opts.inline_mir_hint_threshold.unwrap_or(100)
|
||||
} else {
|
||||
self.tcx.sess.opts.unstable_opts.inline_mir_threshold.unwrap_or(50)
|
||||
|
@ -62,6 +62,7 @@ mod const_prop;
|
||||
mod const_prop_lint;
|
||||
mod copy_prop;
|
||||
mod coverage;
|
||||
mod cross_crate_inline;
|
||||
mod ctfe_limit;
|
||||
mod dataflow_const_prop;
|
||||
mod dead_store_elimination;
|
||||
@ -123,6 +124,7 @@ pub fn provide(providers: &mut Providers) {
|
||||
coverage::query::provide(providers);
|
||||
ffi_unwind_calls::provide(providers);
|
||||
shim::provide(providers);
|
||||
cross_crate_inline::provide(providers);
|
||||
*providers = Providers {
|
||||
mir_keys,
|
||||
mir_const,
|
||||
|
@ -18,43 +18,10 @@ use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_session::config::CrateType;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
|
||||
// Returns true if the given item must be inlined because it may be
|
||||
// monomorphized or it was marked with `#[inline]`. This will only return
|
||||
// true for functions.
|
||||
fn item_might_be_inlined(tcx: TyCtxt<'_>, item: &hir::Item<'_>, attrs: &CodegenFnAttrs) -> bool {
|
||||
if attrs.requests_inline() {
|
||||
return true;
|
||||
}
|
||||
|
||||
match item.kind {
|
||||
hir::ItemKind::Fn(ref sig, ..) if sig.header.is_const() => true,
|
||||
hir::ItemKind::Impl { .. } | hir::ItemKind::Fn(..) => {
|
||||
let generics = tcx.generics_of(item.owner_id);
|
||||
generics.requires_monomorphization(tcx)
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn method_might_be_inlined(
|
||||
tcx: TyCtxt<'_>,
|
||||
impl_item: &hir::ImplItem<'_>,
|
||||
impl_src: LocalDefId,
|
||||
) -> bool {
|
||||
let codegen_fn_attrs = tcx.codegen_fn_attrs(impl_item.hir_id().owner.to_def_id());
|
||||
let generics = tcx.generics_of(impl_item.owner_id);
|
||||
if codegen_fn_attrs.requests_inline() || generics.requires_monomorphization(tcx) {
|
||||
return true;
|
||||
}
|
||||
if let hir::ImplItemKind::Fn(method_sig, _) = &impl_item.kind {
|
||||
if method_sig.header.is_const() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
match tcx.hir().find_by_def_id(impl_src) {
|
||||
Some(Node::Item(item)) => item_might_be_inlined(tcx, &item, codegen_fn_attrs),
|
||||
Some(..) | None => span_bug!(impl_item.span, "impl did is not an item"),
|
||||
}
|
||||
fn item_might_be_inlined(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
|
||||
tcx.generics_of(def_id).requires_monomorphization(tcx)
|
||||
|| tcx.cross_crate_inlinable(def_id)
|
||||
|| tcx.is_const_fn(def_id)
|
||||
}
|
||||
|
||||
// Information needed while computing reachability.
|
||||
@ -150,9 +117,7 @@ impl<'tcx> ReachableContext<'tcx> {
|
||||
|
||||
match self.tcx.hir().find_by_def_id(def_id) {
|
||||
Some(Node::Item(item)) => match item.kind {
|
||||
hir::ItemKind::Fn(..) => {
|
||||
item_might_be_inlined(self.tcx, &item, self.tcx.codegen_fn_attrs(def_id))
|
||||
}
|
||||
hir::ItemKind::Fn(..) => item_might_be_inlined(self.tcx, def_id.into()),
|
||||
_ => false,
|
||||
},
|
||||
Some(Node::TraitItem(trait_method)) => match trait_method.kind {
|
||||
@ -164,9 +129,7 @@ impl<'tcx> ReachableContext<'tcx> {
|
||||
Some(Node::ImplItem(impl_item)) => match impl_item.kind {
|
||||
hir::ImplItemKind::Const(..) => true,
|
||||
hir::ImplItemKind::Fn(..) => {
|
||||
let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
|
||||
let impl_did = self.tcx.hir().get_parent_item(hir_id);
|
||||
method_might_be_inlined(self.tcx, impl_item, impl_did.def_id)
|
||||
item_might_be_inlined(self.tcx, impl_item.hir_id().owner.to_def_id())
|
||||
}
|
||||
hir::ImplItemKind::Type(_) => false,
|
||||
},
|
||||
@ -226,11 +189,7 @@ impl<'tcx> ReachableContext<'tcx> {
|
||||
Node::Item(item) => {
|
||||
match item.kind {
|
||||
hir::ItemKind::Fn(.., body) => {
|
||||
if item_might_be_inlined(
|
||||
self.tcx,
|
||||
&item,
|
||||
self.tcx.codegen_fn_attrs(item.owner_id),
|
||||
) {
|
||||
if item_might_be_inlined(self.tcx, item.owner_id.into()) {
|
||||
self.visit_nested_body(body);
|
||||
}
|
||||
}
|
||||
@ -279,8 +238,7 @@ impl<'tcx> ReachableContext<'tcx> {
|
||||
self.visit_nested_body(body);
|
||||
}
|
||||
hir::ImplItemKind::Fn(_, body) => {
|
||||
let impl_def_id = self.tcx.local_parent(search_item);
|
||||
if method_might_be_inlined(self.tcx, impl_item, impl_def_id) {
|
||||
if item_might_be_inlined(self.tcx, impl_item.hir_id().owner.to_def_id()) {
|
||||
self.visit_nested_body(body)
|
||||
}
|
||||
}
|
||||
|
@ -1452,6 +1452,8 @@ options! {
|
||||
"combine CGUs into a single one"),
|
||||
crate_attr: Vec<String> = (Vec::new(), parse_string_push, [TRACKED],
|
||||
"inject the given attribute in the crate"),
|
||||
cross_crate_inline_threshold: Option<usize> = (None, parse_opt_number, [TRACKED],
|
||||
"threshold to allow cross crate inlining of functions"),
|
||||
debug_info_for_profiling: bool = (false, parse_bool, [TRACKED],
|
||||
"emit discriminators and other data necessary for AutoFDO"),
|
||||
debug_macros: bool = (false, parse_bool, [TRACKED],
|
||||
|
@ -530,6 +530,7 @@ fn alloc_guard(alloc_size: usize) -> Result<(), TryReserveError> {
|
||||
// ensure that the code generation related to these panics is minimal as there's
|
||||
// only one location which panics rather than a bunch throughout the module.
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
#[inline(never)]
|
||||
fn capacity_overflow() -> ! {
|
||||
panic!("capacity overflow");
|
||||
}
|
||||
|
@ -155,6 +155,7 @@ fn lang_start_internal(
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
#[inline(never)]
|
||||
#[lang = "start"]
|
||||
fn lang_start<T: crate::process::Termination + 'static>(
|
||||
main: fn() -> T,
|
||||
|
@ -1,6 +1,7 @@
|
||||
// assembly-output: emit-asm
|
||||
// compile-flags: --target armv7-unknown-linux-gnueabihf
|
||||
// compile-flags: -C target-feature=+neon
|
||||
// compile-flags: -C opt-level=0
|
||||
// needs-llvm-components: arm
|
||||
|
||||
#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
|
||||
|
@ -22,6 +22,7 @@ pub unsafe fn sse41_blend_nofeature(x: __m128, y: __m128) -> __m128 {
|
||||
f(x, y)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[target_feature(enable = "sse4.1")]
|
||||
pub fn sse41_blend_noinline(x: __m128, y: __m128) -> __m128 {
|
||||
let f = {
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Makes sure that `-Z dwarf-version=5` causes `rustc` to emit DWARF version 5.
|
||||
// assembly-output: emit-asm
|
||||
// compile-flags: -g --target x86_64-unknown-linux-gnu -Z dwarf-version=5
|
||||
// compile-flags: -g --target x86_64-unknown-linux-gnu -Z dwarf-version=5 -Copt-level=0
|
||||
// needs-llvm-components: x86
|
||||
|
||||
#![feature(no_core, lang_items)]
|
||||
|
@ -6,15 +6,18 @@ pub unsafe fn f() {
|
||||
//~ MONO_ITEM static f::S @@ asm_sym-cgu.0[External]
|
||||
static S: usize = 1;
|
||||
//~ MONO_ITEM fn f::fun @@ asm_sym-cgu.0[External]
|
||||
#[inline(never)]
|
||||
fn fun() {}
|
||||
core::arch::asm!("/* {0} {1} */", sym S, sym fun);
|
||||
}
|
||||
|
||||
//~ MONO_ITEM fn g @@ asm_sym-cgu.0[External]
|
||||
#[inline(never)]
|
||||
pub unsafe fn g() {
|
||||
//~ MONO_ITEM static g::S @@ asm_sym-cgu.0[Internal]
|
||||
static S: usize = 2;
|
||||
//~ MONO_ITEM fn g::fun @@ asm_sym-cgu.0[Internal]
|
||||
#[inline(never)]
|
||||
fn fun() {}
|
||||
core::arch::asm!("/* {0} {1} */", sym S, sym fun);
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
// compile-flags: -Copt-level=0
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
pub trait Trait : Sized {
|
||||
|
@ -1,4 +1,4 @@
|
||||
// compile-flags:-Zprint-mono-items=eager -Zinline-mir=no
|
||||
// compile-flags:-Zprint-mono-items=eager -Zinline-mir=no -Copt-level=0
|
||||
|
||||
#![deny(dead_code)]
|
||||
#![feature(start)]
|
||||
|
@ -1,4 +1,4 @@
|
||||
// compile-flags:-Zprint-mono-items=eager
|
||||
// compile-flags:-Zprint-mono-items=eager -Copt-level=0
|
||||
|
||||
#![deny(dead_code)]
|
||||
#![feature(start)]
|
||||
|
@ -4,6 +4,7 @@
|
||||
#![crate_type = "rlib"]
|
||||
|
||||
//~ MONO_ITEM fn foo @@ unreferenced_const_fn-cgu.0[External]
|
||||
#[inline(never)]
|
||||
pub const fn foo(x: u32) -> u32 {
|
||||
x + 0xf00
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// FIXME(nagisa): remove the flags below once all targets support `asm!`.
|
||||
// compile-flags: --target x86_64-unknown-linux-gnu
|
||||
// compile-flags: --target x86_64-unknown-linux-gnu -Copt-level=0
|
||||
// needs-llvm-components: x86
|
||||
|
||||
// Verify we sanitize the special tokens for the LLVM inline-assembly, ensuring people won't
|
||||
|
@ -3,7 +3,7 @@
|
||||
// extensions rely on the field having this name.
|
||||
|
||||
// ignore-tidy-linelength
|
||||
// compile-flags: -C debuginfo=2 --edition=2018
|
||||
// compile-flags: -C debuginfo=2 --edition=2018 -Copt-level=0
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
// Verifies that linkage name is omitted when it is
|
||||
// the same as variable / function name.
|
||||
//
|
||||
// compile-flags: -C no-prepopulate-passes
|
||||
// compile-flags: -C debuginfo=2
|
||||
// compile-flags: -C no-prepopulate-passes -Copt-level=0
|
||||
// compile-flags: -C debuginfo=2 -Copt-level=0
|
||||
#![crate_type = "lib"]
|
||||
|
||||
pub mod xyz {
|
||||
|
@ -1,5 +1,5 @@
|
||||
// revisions: WINDOWS ANDROID
|
||||
// compile-flags: -C panic=abort
|
||||
// compile-flags: -C panic=abort -Copt-level=0
|
||||
// [WINDOWS] compile-flags: --target=x86_64-pc-windows-msvc
|
||||
// [WINDOWS] needs-llvm-components: x86
|
||||
// [ANDROID] compile-flags: --target=armv7-linux-androideabi
|
||||
|
@ -7,10 +7,12 @@
|
||||
struct SomeUniqueName;
|
||||
|
||||
impl Drop for SomeUniqueName {
|
||||
#[inline(never)]
|
||||
fn drop(&mut self) {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
pub fn possibly_unwinding() {
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// compile-flags: -C no-prepopulate-passes -C force-frame-pointers=y
|
||||
// compile-flags: -C no-prepopulate-passes -C force-frame-pointers=y -Copt-level=0
|
||||
|
||||
#![crate_type="lib"]
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// compile-flags: -C no-prepopulate-passes -C force-unwind-tables=y
|
||||
// compile-flags: -C no-prepopulate-passes -C force-unwind-tables=y -Copt-level=0
|
||||
|
||||
#![crate_type="lib"]
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
#[inline(never)]
|
||||
pub fn outer_function(x: usize, y: usize) -> usize {
|
||||
inner_function(x, y) + 1
|
||||
}
|
||||
@ -13,8 +14,8 @@ pub fn outer_function(x: usize, y: usize) -> usize {
|
||||
#[inline]
|
||||
fn inner_function(aaaa: usize, bbbb: usize) -> usize {
|
||||
// CHECK: !DILocalVariable(name: "aaaa", arg: 1
|
||||
// CHECK-SAME: line: 14
|
||||
// CHECK-SAME: line: 15
|
||||
// CHECK: !DILocalVariable(name: "bbbb", arg: 2
|
||||
// CHECK-SAME: line: 14
|
||||
// CHECK-SAME: line: 15
|
||||
aaaa + bbbb
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// compile-flags: -Z instrument-mcount
|
||||
// compile-flags: -Z instrument-mcount -Copt-level=0
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Checks that `-Z instrument-xray` produces expected instrumentation.
|
||||
//
|
||||
// needs-xray
|
||||
// compile-flags: -Z instrument-xray=always
|
||||
// compile-flags: -Z instrument-xray=always -Copt-level=0
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
// Checks that `-Z instrument-xray` options can be specified multiple times.
|
||||
//
|
||||
// needs-xray
|
||||
// compile-flags: -Z instrument-xray=skip-exit
|
||||
// compile-flags: -Z instrument-xray=instruction-threshold=123
|
||||
// compile-flags: -Z instrument-xray=instruction-threshold=456
|
||||
// compile-flags: -Z instrument-xray=skip-exit -Copt-level=0
|
||||
// compile-flags: -Z instrument-xray=instruction-threshold=123 -Copt-level=0
|
||||
// compile-flags: -Z instrument-xray=instruction-threshold=456 -Copt-level=0
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
// Checks that the last `-Z instrument-xray` option wins.
|
||||
//
|
||||
// needs-xray
|
||||
// compile-flags: -Z instrument-xray=always
|
||||
// compile-flags: -Z instrument-xray=never
|
||||
// compile-flags: -Z instrument-xray=always -Copt-level=0
|
||||
// compile-flags: -Z instrument-xray=never -Copt-level=0
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// compile-flags: -C panic=unwind -C no-prepopulate-passes
|
||||
// compile-flags: -C panic=unwind -C no-prepopulate-passes -Copt-level=0
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
|
@ -9,10 +9,12 @@
|
||||
struct S;
|
||||
|
||||
impl Drop for S {
|
||||
#[inline(never)]
|
||||
fn drop(&mut self) {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
fn might_unwind() {
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Verifies that user-defined CFI encoding for types are emitted.
|
||||
//
|
||||
// needs-sanitizer-cfi
|
||||
// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi
|
||||
// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Copt-level=0
|
||||
|
||||
#![crate_type="lib"]
|
||||
#![feature(cfi_encoding, extern_types)]
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Verifies that type metadata identifiers for functions are emitted correctly.
|
||||
//
|
||||
// needs-sanitizer-cfi
|
||||
// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi
|
||||
// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Copt-level=0
|
||||
|
||||
#![crate_type="lib"]
|
||||
#![allow(dead_code)]
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Verifies that pointer types are generalized.
|
||||
//
|
||||
// needs-sanitizer-cfi
|
||||
// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-generalize-pointers
|
||||
// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-generalize-pointers -Copt-level=0
|
||||
|
||||
#![crate_type="lib"]
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Verifies that integer types are normalized.
|
||||
//
|
||||
// needs-sanitizer-cfi
|
||||
// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-normalize-integers
|
||||
// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-normalize-integers -Copt-level=0
|
||||
|
||||
#![crate_type="lib"]
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Verifies that `-Zsanitizer=kernel-address` emits sanitizer instrumentation.
|
||||
|
||||
// compile-flags: -Zsanitizer=kernel-address
|
||||
// compile-flags: -Zsanitizer=kernel-address -Copt-level=0
|
||||
// revisions: aarch64 riscv64imac riscv64gc x86_64
|
||||
//[aarch64] compile-flags: --target aarch64-unknown-none
|
||||
//[aarch64] needs-llvm-components: aarch64
|
||||
|
@ -2,7 +2,7 @@
|
||||
// applied when enabling the memtag sanitizer.
|
||||
//
|
||||
// needs-sanitizer-memtag
|
||||
// compile-flags: -Zsanitizer=memtag -Ctarget-feature=+mte
|
||||
// compile-flags: -Zsanitizer=memtag -Ctarget-feature=+mte -Copt-level=0
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
// selectively disable sanitizer instrumentation.
|
||||
//
|
||||
// needs-sanitizer-address
|
||||
// compile-flags: -Zsanitizer=address -Ctarget-feature=-crt-static
|
||||
// compile-flags: -Zsanitizer=address -Ctarget-feature=-crt-static -Copt-level=0
|
||||
|
||||
#![crate_type="lib"]
|
||||
#![feature(no_sanitize)]
|
||||
|
@ -1,7 +1,7 @@
|
||||
// This tests that the safestack attribute is applied when enabling the safe-stack sanitizer.
|
||||
//
|
||||
// needs-sanitizer-safestack
|
||||
// compile-flags: -Zsanitizer=safestack
|
||||
// compile-flags: -Zsanitizer=safestack -Copt-level=0
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// compile-flags: -g -Z src-hash-algorithm=md5
|
||||
// compile-flags: -g -Z src-hash-algorithm=md5 -Copt-level=0
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// compile-flags: -g -Z src-hash-algorithm=sha1
|
||||
// compile-flags: -g -Z src-hash-algorithm=sha1 -Copt-level=0
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// compile-flags: -g -Z src-hash-algorithm=sha256
|
||||
// compile-flags: -g -Z src-hash-algorithm=sha256 -Copt-level=0
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
|
@ -15,7 +15,8 @@ pub extern "C" fn exported() {
|
||||
|
||||
// CHECK-LABEL: ; target_cpu_on_functions::not_exported
|
||||
// CHECK-NEXT: ; Function Attrs:
|
||||
// CHECK-NEXT: define {{.*}}() {{.*}} #0
|
||||
// CHECK-NEXT: define {{.*}}() {{.*}} #1
|
||||
#[inline(never)]
|
||||
fn not_exported() {}
|
||||
|
||||
// CHECK: attributes #0 = {{.*}} "target-cpu"="{{.*}}"
|
||||
|
@ -7,16 +7,16 @@
|
||||
// are targeting older LLVM versions. Once the min supported version
|
||||
// is LLVM-14 we can remove the optional regex matching for this feature.
|
||||
|
||||
// [ENABLE_SVE] compile-flags: -C target-feature=+sve
|
||||
// [ENABLE_SVE] compile-flags: -C target-feature=+sve -Copt-level=0
|
||||
// ENABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(\+sve,?)|(\+neon,?))*}}" }
|
||||
|
||||
// [DISABLE_SVE] compile-flags: -C target-feature=-sve
|
||||
// [DISABLE_SVE] compile-flags: -C target-feature=-sve -Copt-level=0
|
||||
// DISABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(-sve,?)|(\+neon,?))*}}" }
|
||||
|
||||
// [DISABLE_NEON] compile-flags: -C target-feature=-neon
|
||||
// [DISABLE_NEON] compile-flags: -C target-feature=-neon -Copt-level=0
|
||||
// DISABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(-fp-armv8,?)|(-neon,?))*}}" }
|
||||
|
||||
// [ENABLE_NEON] compile-flags: -C target-feature=+neon
|
||||
// [ENABLE_NEON] compile-flags: -C target-feature=+neon -Copt-level=0
|
||||
// ENABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(\+fp-armv8,?)|(\+neon,?))*}}" }
|
||||
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
// no-prefer-dynamic
|
||||
//
|
||||
// compile-flags: -C no-prepopulate-passes -C panic=abort -C linker-plugin-lto -Cpasses=name-anon-globals -Z tune-cpu=generic
|
||||
// compile-flags: -C no-prepopulate-passes -C panic=abort -C linker-plugin-lto -Cpasses=name-anon-globals -Z tune-cpu=generic -Copt-level=0
|
||||
|
||||
#![crate_type = "staticlib"]
|
||||
|
||||
|
@ -1,45 +1,62 @@
|
||||
Function name: <try_error_result::Thing1>::get_thing_2
|
||||
Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 28, 05, 01, 18, 05, 02, 0d, 00, 14, 02, 02, 0d, 00, 1a, 07, 02, 05, 00, 06]
|
||||
Raw bytes (63): 0x[01, 01, 02, 01, 05, 05, 02, 0b, 01, 28, 05, 01, 18, 05, 02, 0d, 00, 14, 00, 00, 0d, 00, 14, 00, 00, 0d, 00, 14, 00, 00, 0d, 00, 14, 00, 00, 0d, 00, 14, 00, 00, 0d, 00, 14, 02, 02, 0d, 00, 1a, 00, 00, 0d, 00, 1a, 00, 00, 0d, 00, 1a, 07, 02, 05, 00, 06]
|
||||
Number of files: 1
|
||||
- file 0 => global file 1
|
||||
Number of expressions: 2
|
||||
- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
|
||||
- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub)
|
||||
Number of file 0 mappings: 4
|
||||
Number of file 0 mappings: 11
|
||||
- Code(Counter(0)) at (prev + 40, 5) to (start + 1, 24)
|
||||
- Code(Counter(1)) at (prev + 2, 13) to (start + 0, 20)
|
||||
- Code(Zero) at (prev + 0, 13) to (start + 0, 20)
|
||||
- Code(Zero) at (prev + 0, 13) to (start + 0, 20)
|
||||
- Code(Zero) at (prev + 0, 13) to (start + 0, 20)
|
||||
- Code(Zero) at (prev + 0, 13) to (start + 0, 20)
|
||||
- Code(Zero) at (prev + 0, 13) to (start + 0, 20)
|
||||
- Code(Expression(0, Sub)) at (prev + 2, 13) to (start + 0, 26)
|
||||
= (c0 - c1)
|
||||
- Code(Zero) at (prev + 0, 13) to (start + 0, 26)
|
||||
- Code(Zero) at (prev + 0, 13) to (start + 0, 26)
|
||||
- Code(Expression(1, Add)) at (prev + 2, 5) to (start + 0, 6)
|
||||
= (c1 + (c0 - c1))
|
||||
|
||||
Function name: <try_error_result::Thing2>::call
|
||||
Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 33, 05, 01, 18, 05, 02, 0d, 00, 14, 02, 02, 0d, 00, 13, 07, 02, 05, 00, 06]
|
||||
Raw bytes (63): 0x[01, 01, 02, 01, 05, 05, 02, 0b, 01, 33, 05, 01, 18, 05, 02, 0d, 00, 14, 00, 00, 0d, 00, 14, 00, 00, 0d, 00, 14, 00, 00, 0d, 00, 14, 00, 00, 0d, 00, 14, 02, 02, 0d, 00, 13, 00, 00, 0d, 00, 13, 00, 00, 0d, 00, 13, 00, 00, 0d, 00, 13, 07, 02, 05, 00, 06]
|
||||
Number of files: 1
|
||||
- file 0 => global file 1
|
||||
Number of expressions: 2
|
||||
- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
|
||||
- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub)
|
||||
Number of file 0 mappings: 4
|
||||
Number of file 0 mappings: 11
|
||||
- Code(Counter(0)) at (prev + 51, 5) to (start + 1, 24)
|
||||
- Code(Counter(1)) at (prev + 2, 13) to (start + 0, 20)
|
||||
- Code(Zero) at (prev + 0, 13) to (start + 0, 20)
|
||||
- Code(Zero) at (prev + 0, 13) to (start + 0, 20)
|
||||
- Code(Zero) at (prev + 0, 13) to (start + 0, 20)
|
||||
- Code(Zero) at (prev + 0, 13) to (start + 0, 20)
|
||||
- Code(Expression(0, Sub)) at (prev + 2, 13) to (start + 0, 19)
|
||||
= (c0 - c1)
|
||||
- Code(Zero) at (prev + 0, 13) to (start + 0, 19)
|
||||
- Code(Zero) at (prev + 0, 13) to (start + 0, 19)
|
||||
- Code(Zero) at (prev + 0, 13) to (start + 0, 19)
|
||||
- Code(Expression(1, Add)) at (prev + 2, 5) to (start + 0, 6)
|
||||
= (c1 + (c0 - c1))
|
||||
|
||||
Function name: try_error_result::call
|
||||
Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 04, 01, 01, 14, 05, 02, 09, 00, 10, 02, 02, 09, 00, 0f, 07, 02, 01, 00, 02]
|
||||
Raw bytes (43): 0x[01, 01, 02, 01, 05, 05, 02, 07, 01, 04, 01, 01, 14, 05, 02, 09, 00, 10, 00, 00, 09, 00, 10, 00, 00, 09, 00, 10, 02, 02, 09, 00, 0f, 00, 00, 09, 00, 0f, 07, 02, 01, 00, 02]
|
||||
Number of files: 1
|
||||
- file 0 => global file 1
|
||||
Number of expressions: 2
|
||||
- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
|
||||
- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub)
|
||||
Number of file 0 mappings: 4
|
||||
Number of file 0 mappings: 7
|
||||
- Code(Counter(0)) at (prev + 4, 1) to (start + 1, 20)
|
||||
- Code(Counter(1)) at (prev + 2, 9) to (start + 0, 16)
|
||||
- Code(Zero) at (prev + 0, 9) to (start + 0, 16)
|
||||
- Code(Zero) at (prev + 0, 9) to (start + 0, 16)
|
||||
- Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 15)
|
||||
= (c0 - c1)
|
||||
- Code(Zero) at (prev + 0, 9) to (start + 0, 15)
|
||||
- Code(Expression(1, Add)) at (prev + 2, 1) to (start + 0, 2)
|
||||
= (c1 + (c0 - c1))
|
||||
|
||||
|
@ -4,29 +4,20 @@
|
||||
fn main() -> () {
|
||||
let mut _0: ();
|
||||
let _1: main::Un;
|
||||
let mut _2: u32;
|
||||
let mut _3: u32;
|
||||
scope 1 {
|
||||
debug un => _1;
|
||||
scope 2 {
|
||||
}
|
||||
scope 3 (inlined std::mem::drop::<u32>) {
|
||||
debug _x => _3;
|
||||
scope 4 (inlined std::mem::drop::<u32>) {
|
||||
debug _x => const 1_u32;
|
||||
}
|
||||
}
|
||||
scope 3 (inlined val) {
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1);
|
||||
StorageLive(_2);
|
||||
_2 = val() -> [return: bb1, unwind unreachable];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
_1 = Un { us: move _2 };
|
||||
StorageDead(_2);
|
||||
StorageLive(_3);
|
||||
_3 = (_1.0: u32);
|
||||
StorageDead(_3);
|
||||
_1 = Un { us: const 1_u32 };
|
||||
StorageDead(_1);
|
||||
return;
|
||||
}
|
||||
|
@ -4,29 +4,20 @@
|
||||
fn main() -> () {
|
||||
let mut _0: ();
|
||||
let _1: main::Un;
|
||||
let mut _2: u32;
|
||||
let mut _3: u32;
|
||||
scope 1 {
|
||||
debug un => _1;
|
||||
scope 2 {
|
||||
}
|
||||
scope 3 (inlined std::mem::drop::<u32>) {
|
||||
debug _x => _3;
|
||||
scope 4 (inlined std::mem::drop::<u32>) {
|
||||
debug _x => const 1_u32;
|
||||
}
|
||||
}
|
||||
scope 3 (inlined val) {
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1);
|
||||
StorageLive(_2);
|
||||
_2 = val() -> [return: bb1, unwind continue];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
_1 = Un { us: move _2 };
|
||||
StorageDead(_2);
|
||||
StorageLive(_3);
|
||||
_3 = (_1.0: u32);
|
||||
StorageDead(_3);
|
||||
_1 = Un { us: const 1_u32 };
|
||||
StorageDead(_1);
|
||||
return;
|
||||
}
|
||||
|
@ -7,104 +7,104 @@
|
||||
debug upper => _3;
|
||||
let mut _0: std::result::Result<(), std::fmt::Error>;
|
||||
let _4: bool;
|
||||
let mut _5: &std::fmt::Formatter<'_>;
|
||||
let mut _7: std::option::Option<usize>;
|
||||
let mut _8: &std::fmt::Formatter<'_>;
|
||||
let mut _9: isize;
|
||||
let mut _11: &mut std::fmt::Formatter<'_>;
|
||||
let mut _12: &T;
|
||||
let mut _13: core::num::flt2dec::Sign;
|
||||
let mut _14: u32;
|
||||
let mut _15: u32;
|
||||
let mut _16: usize;
|
||||
let mut _17: bool;
|
||||
let mut _18: &mut std::fmt::Formatter<'_>;
|
||||
let mut _19: &T;
|
||||
let mut _20: core::num::flt2dec::Sign;
|
||||
let mut _21: bool;
|
||||
let mut _6: std::option::Option<usize>;
|
||||
let mut _7: isize;
|
||||
let mut _9: &mut std::fmt::Formatter<'_>;
|
||||
let mut _10: &T;
|
||||
let mut _11: core::num::flt2dec::Sign;
|
||||
let mut _12: u32;
|
||||
let mut _13: u32;
|
||||
let mut _14: usize;
|
||||
let mut _15: bool;
|
||||
let mut _16: &mut std::fmt::Formatter<'_>;
|
||||
let mut _17: &T;
|
||||
let mut _18: core::num::flt2dec::Sign;
|
||||
let mut _19: bool;
|
||||
scope 1 {
|
||||
debug force_sign => _4;
|
||||
let _6: core::num::flt2dec::Sign;
|
||||
let _5: core::num::flt2dec::Sign;
|
||||
scope 2 {
|
||||
debug sign => _6;
|
||||
debug sign => _5;
|
||||
scope 3 {
|
||||
debug precision => _10;
|
||||
let _10: usize;
|
||||
debug precision => _8;
|
||||
let _8: usize;
|
||||
scope 5 (inlined Formatter::<'_>::precision) {
|
||||
debug self => _1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
scope 4 (inlined Formatter::<'_>::sign_plus) {
|
||||
debug self => _1;
|
||||
let mut _20: u32;
|
||||
let mut _21: u32;
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_4);
|
||||
StorageLive(_20);
|
||||
StorageLive(_21);
|
||||
_21 = ((*_1).0: u32);
|
||||
_20 = BitAnd(move _21, const 1_u32);
|
||||
StorageDead(_21);
|
||||
_4 = Ne(move _20, const 0_u32);
|
||||
StorageDead(_20);
|
||||
StorageLive(_5);
|
||||
_5 = &(*_1);
|
||||
_4 = Formatter::<'_>::sign_plus(move _5) -> [return: bb1, unwind unreachable];
|
||||
switchInt(_4) -> [0: bb2, otherwise: bb1];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
StorageDead(_5);
|
||||
StorageLive(_6);
|
||||
switchInt(_4) -> [0: bb3, otherwise: bb2];
|
||||
- _5 = MinusPlus;
|
||||
+ _5 = const MinusPlus;
|
||||
goto -> bb3;
|
||||
}
|
||||
|
||||
bb2: {
|
||||
- _6 = MinusPlus;
|
||||
+ _6 = const MinusPlus;
|
||||
goto -> bb4;
|
||||
- _5 = Minus;
|
||||
+ _5 = const Minus;
|
||||
goto -> bb3;
|
||||
}
|
||||
|
||||
bb3: {
|
||||
- _6 = Minus;
|
||||
+ _6 = const Minus;
|
||||
goto -> bb4;
|
||||
StorageLive(_6);
|
||||
_6 = ((*_1).4: std::option::Option<usize>);
|
||||
_7 = discriminant(_6);
|
||||
switchInt(move _7) -> [1: bb4, otherwise: bb6];
|
||||
}
|
||||
|
||||
bb4: {
|
||||
StorageLive(_7);
|
||||
StorageLive(_8);
|
||||
_8 = &(*_1);
|
||||
_7 = Formatter::<'_>::precision(move _8) -> [return: bb5, unwind unreachable];
|
||||
_8 = ((_6 as Some).0: usize);
|
||||
StorageLive(_11);
|
||||
_11 = _5;
|
||||
StorageLive(_12);
|
||||
StorageLive(_13);
|
||||
_13 = _8 as u32 (IntToInt);
|
||||
_12 = Add(move _13, const 1_u32);
|
||||
StorageDead(_13);
|
||||
_0 = float_to_exponential_common_exact::<T>(_1, _2, move _11, move _12, _3) -> [return: bb5, unwind unreachable];
|
||||
}
|
||||
|
||||
bb5: {
|
||||
StorageDead(_8);
|
||||
_9 = discriminant(_7);
|
||||
switchInt(move _9) -> [1: bb6, otherwise: bb8];
|
||||
StorageDead(_12);
|
||||
StorageDead(_11);
|
||||
goto -> bb8;
|
||||
}
|
||||
|
||||
bb6: {
|
||||
_10 = ((_7 as Some).0: usize);
|
||||
StorageLive(_13);
|
||||
_13 = _6;
|
||||
StorageLive(_14);
|
||||
StorageLive(_15);
|
||||
_15 = _10 as u32 (IntToInt);
|
||||
_14 = Add(move _15, const 1_u32);
|
||||
StorageDead(_15);
|
||||
_0 = float_to_exponential_common_exact::<T>(_1, _2, move _13, move _14, _3) -> [return: bb7, unwind unreachable];
|
||||
StorageLive(_18);
|
||||
_18 = _5;
|
||||
_0 = float_to_exponential_common_shortest::<T>(_1, _2, move _18, _3) -> [return: bb7, unwind unreachable];
|
||||
}
|
||||
|
||||
bb7: {
|
||||
StorageDead(_14);
|
||||
StorageDead(_13);
|
||||
goto -> bb10;
|
||||
StorageDead(_18);
|
||||
goto -> bb8;
|
||||
}
|
||||
|
||||
bb8: {
|
||||
StorageLive(_20);
|
||||
_20 = _6;
|
||||
_0 = float_to_exponential_common_shortest::<T>(_1, _2, move _20, _3) -> [return: bb9, unwind unreachable];
|
||||
}
|
||||
|
||||
bb9: {
|
||||
StorageDead(_20);
|
||||
goto -> bb10;
|
||||
}
|
||||
|
||||
bb10: {
|
||||
StorageDead(_6);
|
||||
StorageDead(_5);
|
||||
StorageDead(_4);
|
||||
StorageDead(_7);
|
||||
StorageDead(_6);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -7,104 +7,104 @@
|
||||
debug upper => _3;
|
||||
let mut _0: std::result::Result<(), std::fmt::Error>;
|
||||
let _4: bool;
|
||||
let mut _5: &std::fmt::Formatter<'_>;
|
||||
let mut _7: std::option::Option<usize>;
|
||||
let mut _8: &std::fmt::Formatter<'_>;
|
||||
let mut _9: isize;
|
||||
let mut _11: &mut std::fmt::Formatter<'_>;
|
||||
let mut _12: &T;
|
||||
let mut _13: core::num::flt2dec::Sign;
|
||||
let mut _14: u32;
|
||||
let mut _15: u32;
|
||||
let mut _16: usize;
|
||||
let mut _17: bool;
|
||||
let mut _18: &mut std::fmt::Formatter<'_>;
|
||||
let mut _19: &T;
|
||||
let mut _20: core::num::flt2dec::Sign;
|
||||
let mut _21: bool;
|
||||
let mut _6: std::option::Option<usize>;
|
||||
let mut _7: isize;
|
||||
let mut _9: &mut std::fmt::Formatter<'_>;
|
||||
let mut _10: &T;
|
||||
let mut _11: core::num::flt2dec::Sign;
|
||||
let mut _12: u32;
|
||||
let mut _13: u32;
|
||||
let mut _14: usize;
|
||||
let mut _15: bool;
|
||||
let mut _16: &mut std::fmt::Formatter<'_>;
|
||||
let mut _17: &T;
|
||||
let mut _18: core::num::flt2dec::Sign;
|
||||
let mut _19: bool;
|
||||
scope 1 {
|
||||
debug force_sign => _4;
|
||||
let _6: core::num::flt2dec::Sign;
|
||||
let _5: core::num::flt2dec::Sign;
|
||||
scope 2 {
|
||||
debug sign => _6;
|
||||
debug sign => _5;
|
||||
scope 3 {
|
||||
debug precision => _10;
|
||||
let _10: usize;
|
||||
debug precision => _8;
|
||||
let _8: usize;
|
||||
scope 5 (inlined Formatter::<'_>::precision) {
|
||||
debug self => _1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
scope 4 (inlined Formatter::<'_>::sign_plus) {
|
||||
debug self => _1;
|
||||
let mut _20: u32;
|
||||
let mut _21: u32;
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_4);
|
||||
StorageLive(_20);
|
||||
StorageLive(_21);
|
||||
_21 = ((*_1).0: u32);
|
||||
_20 = BitAnd(move _21, const 1_u32);
|
||||
StorageDead(_21);
|
||||
_4 = Ne(move _20, const 0_u32);
|
||||
StorageDead(_20);
|
||||
StorageLive(_5);
|
||||
_5 = &(*_1);
|
||||
_4 = Formatter::<'_>::sign_plus(move _5) -> [return: bb1, unwind continue];
|
||||
switchInt(_4) -> [0: bb2, otherwise: bb1];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
StorageDead(_5);
|
||||
StorageLive(_6);
|
||||
switchInt(_4) -> [0: bb3, otherwise: bb2];
|
||||
- _5 = MinusPlus;
|
||||
+ _5 = const MinusPlus;
|
||||
goto -> bb3;
|
||||
}
|
||||
|
||||
bb2: {
|
||||
- _6 = MinusPlus;
|
||||
+ _6 = const MinusPlus;
|
||||
goto -> bb4;
|
||||
- _5 = Minus;
|
||||
+ _5 = const Minus;
|
||||
goto -> bb3;
|
||||
}
|
||||
|
||||
bb3: {
|
||||
- _6 = Minus;
|
||||
+ _6 = const Minus;
|
||||
goto -> bb4;
|
||||
StorageLive(_6);
|
||||
_6 = ((*_1).4: std::option::Option<usize>);
|
||||
_7 = discriminant(_6);
|
||||
switchInt(move _7) -> [1: bb4, otherwise: bb6];
|
||||
}
|
||||
|
||||
bb4: {
|
||||
StorageLive(_7);
|
||||
StorageLive(_8);
|
||||
_8 = &(*_1);
|
||||
_7 = Formatter::<'_>::precision(move _8) -> [return: bb5, unwind continue];
|
||||
_8 = ((_6 as Some).0: usize);
|
||||
StorageLive(_11);
|
||||
_11 = _5;
|
||||
StorageLive(_12);
|
||||
StorageLive(_13);
|
||||
_13 = _8 as u32 (IntToInt);
|
||||
_12 = Add(move _13, const 1_u32);
|
||||
StorageDead(_13);
|
||||
_0 = float_to_exponential_common_exact::<T>(_1, _2, move _11, move _12, _3) -> [return: bb5, unwind continue];
|
||||
}
|
||||
|
||||
bb5: {
|
||||
StorageDead(_8);
|
||||
_9 = discriminant(_7);
|
||||
switchInt(move _9) -> [1: bb6, otherwise: bb8];
|
||||
StorageDead(_12);
|
||||
StorageDead(_11);
|
||||
goto -> bb8;
|
||||
}
|
||||
|
||||
bb6: {
|
||||
_10 = ((_7 as Some).0: usize);
|
||||
StorageLive(_13);
|
||||
_13 = _6;
|
||||
StorageLive(_14);
|
||||
StorageLive(_15);
|
||||
_15 = _10 as u32 (IntToInt);
|
||||
_14 = Add(move _15, const 1_u32);
|
||||
StorageDead(_15);
|
||||
_0 = float_to_exponential_common_exact::<T>(_1, _2, move _13, move _14, _3) -> [return: bb7, unwind continue];
|
||||
StorageLive(_18);
|
||||
_18 = _5;
|
||||
_0 = float_to_exponential_common_shortest::<T>(_1, _2, move _18, _3) -> [return: bb7, unwind continue];
|
||||
}
|
||||
|
||||
bb7: {
|
||||
StorageDead(_14);
|
||||
StorageDead(_13);
|
||||
goto -> bb10;
|
||||
StorageDead(_18);
|
||||
goto -> bb8;
|
||||
}
|
||||
|
||||
bb8: {
|
||||
StorageLive(_20);
|
||||
_20 = _6;
|
||||
_0 = float_to_exponential_common_shortest::<T>(_1, _2, move _20, _3) -> [return: bb9, unwind continue];
|
||||
}
|
||||
|
||||
bb9: {
|
||||
StorageDead(_20);
|
||||
goto -> bb10;
|
||||
}
|
||||
|
||||
bb10: {
|
||||
StorageDead(_6);
|
||||
StorageDead(_5);
|
||||
StorageDead(_4);
|
||||
StorageDead(_7);
|
||||
StorageDead(_6);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ pub fn outer() -> usize {
|
||||
inner()
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
fn index() -> usize {
|
||||
loop {}
|
||||
}
|
||||
|
@ -8,31 +8,37 @@
|
||||
let mut _3: &fn() {foo};
|
||||
let _4: fn() {foo};
|
||||
let mut _5: ();
|
||||
+ scope 1 (inlined hide_foo) {
|
||||
+ }
|
||||
|
||||
bb0: {
|
||||
StorageLive(_2);
|
||||
StorageLive(_3);
|
||||
StorageLive(_4);
|
||||
_4 = hide_foo() -> [return: bb1, unwind unreachable];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
- _4 = hide_foo() -> [return: bb1, unwind unreachable];
|
||||
- }
|
||||
-
|
||||
- bb1: {
|
||||
_3 = &_4;
|
||||
StorageLive(_5);
|
||||
_5 = ();
|
||||
_2 = <fn() {foo} as Fn<()>>::call(move _3, move _5) -> [return: bb2, unwind unreachable];
|
||||
- _2 = <fn() {foo} as Fn<()>>::call(move _3, move _5) -> [return: bb2, unwind unreachable];
|
||||
+ _2 = <fn() {foo} as Fn<()>>::call(move _3, move _5) -> [return: bb1, unwind unreachable];
|
||||
}
|
||||
|
||||
bb2: {
|
||||
- bb2: {
|
||||
+ bb1: {
|
||||
StorageDead(_5);
|
||||
StorageDead(_3);
|
||||
StorageDead(_4);
|
||||
StorageDead(_2);
|
||||
_0 = const ();
|
||||
drop(_1) -> [return: bb3, unwind unreachable];
|
||||
- drop(_1) -> [return: bb3, unwind unreachable];
|
||||
+ drop(_1) -> [return: bb2, unwind unreachable];
|
||||
}
|
||||
|
||||
bb3: {
|
||||
- bb3: {
|
||||
+ bb2: {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -8,39 +8,48 @@
|
||||
let mut _3: &fn() {foo};
|
||||
let _4: fn() {foo};
|
||||
let mut _5: ();
|
||||
+ scope 1 (inlined hide_foo) {
|
||||
+ }
|
||||
|
||||
bb0: {
|
||||
StorageLive(_2);
|
||||
StorageLive(_3);
|
||||
StorageLive(_4);
|
||||
_4 = hide_foo() -> [return: bb1, unwind: bb4];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
- _4 = hide_foo() -> [return: bb1, unwind: bb4];
|
||||
- }
|
||||
-
|
||||
- bb1: {
|
||||
_3 = &_4;
|
||||
StorageLive(_5);
|
||||
_5 = ();
|
||||
_2 = <fn() {foo} as Fn<()>>::call(move _3, move _5) -> [return: bb2, unwind: bb4];
|
||||
- _2 = <fn() {foo} as Fn<()>>::call(move _3, move _5) -> [return: bb2, unwind: bb4];
|
||||
+ _2 = <fn() {foo} as Fn<()>>::call(move _3, move _5) -> [return: bb1, unwind: bb3];
|
||||
}
|
||||
|
||||
bb2: {
|
||||
- bb2: {
|
||||
+ bb1: {
|
||||
StorageDead(_5);
|
||||
StorageDead(_3);
|
||||
StorageDead(_4);
|
||||
StorageDead(_2);
|
||||
_0 = const ();
|
||||
drop(_1) -> [return: bb3, unwind: bb5];
|
||||
- drop(_1) -> [return: bb3, unwind: bb5];
|
||||
+ drop(_1) -> [return: bb2, unwind: bb4];
|
||||
}
|
||||
|
||||
bb3: {
|
||||
- bb3: {
|
||||
+ bb2: {
|
||||
return;
|
||||
}
|
||||
|
||||
bb4 (cleanup): {
|
||||
drop(_1) -> [return: bb5, unwind terminate(cleanup)];
|
||||
- bb4 (cleanup): {
|
||||
- drop(_1) -> [return: bb5, unwind terminate(cleanup)];
|
||||
+ bb3 (cleanup): {
|
||||
+ drop(_1) -> [return: bb4, unwind terminate(cleanup)];
|
||||
}
|
||||
|
||||
bb5 (cleanup): {
|
||||
- bb5 (cleanup): {
|
||||
+ bb4 (cleanup): {
|
||||
resume;
|
||||
}
|
||||
}
|
||||
|
@ -4,17 +4,14 @@ fn outer(_1: u8) -> u8 {
|
||||
debug v => _1; // in scope 0 at $DIR/spans.rs:9:14: 9:15
|
||||
let mut _0: u8; // return place in scope 0 at $DIR/spans.rs:9:24: 9:26
|
||||
let mut _2: &u8; // in scope 0 at $DIR/spans.rs:10:11: 10:13
|
||||
scope 1 (inlined inner) { // at $DIR/spans.rs:10:5: 10:14
|
||||
debug x => _2; // in scope 1 at $DIR/spans.rs:13:14: 13:15
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_2); // scope 0 at $DIR/spans.rs:10:11: 10:13
|
||||
_2 = &_1; // scope 0 at $DIR/spans.rs:10:11: 10:13
|
||||
_0 = inner(move _2) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/spans.rs:10:5: 10:14
|
||||
// mir::ConstOperand
|
||||
// + span: $DIR/spans.rs:10:5: 10:10
|
||||
// + const_: Const { ty: for<'a> fn(&'a u8) -> u8 {inner}, val: Value(inner) }
|
||||
}
|
||||
|
||||
bb1: {
|
||||
_0 = _1; // scope 1 at $DIR/spans.rs:14:5: 14:7
|
||||
StorageDead(_2); // scope 0 at $DIR/spans.rs:10:13: 10:14
|
||||
return; // scope 0 at $DIR/spans.rs:11:2: 11:2
|
||||
}
|
||||
|
@ -4,17 +4,14 @@ fn outer(_1: u8) -> u8 {
|
||||
debug v => _1; // in scope 0 at $DIR/spans.rs:9:14: 9:15
|
||||
let mut _0: u8; // return place in scope 0 at $DIR/spans.rs:9:24: 9:26
|
||||
let mut _2: &u8; // in scope 0 at $DIR/spans.rs:10:11: 10:13
|
||||
scope 1 (inlined inner) { // at $DIR/spans.rs:10:5: 10:14
|
||||
debug x => _2; // in scope 1 at $DIR/spans.rs:13:14: 13:15
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_2); // scope 0 at $DIR/spans.rs:10:11: 10:13
|
||||
_2 = &_1; // scope 0 at $DIR/spans.rs:10:11: 10:13
|
||||
_0 = inner(move _2) -> [return: bb1, unwind continue]; // scope 0 at $DIR/spans.rs:10:5: 10:14
|
||||
// mir::ConstOperand
|
||||
// + span: $DIR/spans.rs:10:5: 10:10
|
||||
// + const_: Const { ty: for<'a> fn(&'a u8) -> u8 {inner}, val: Value(inner) }
|
||||
}
|
||||
|
||||
bb1: {
|
||||
_0 = _1; // scope 1 at $DIR/spans.rs:14:5: 14:7
|
||||
StorageDead(_2); // scope 0 at $DIR/spans.rs:10:13: 10:14
|
||||
return; // scope 0 at $DIR/spans.rs:11:2: 11:2
|
||||
}
|
||||
|
@ -3,44 +3,26 @@
|
||||
fn while_loop(_1: bool) -> () {
|
||||
debug c => _1;
|
||||
let mut _0: ();
|
||||
let mut _2: bool;
|
||||
let mut _3: bool;
|
||||
scope 1 (inlined get_bool) {
|
||||
debug c => _1;
|
||||
}
|
||||
scope 2 (inlined get_bool) {
|
||||
debug c => _1;
|
||||
}
|
||||
|
||||
bb0: {
|
||||
goto -> bb1;
|
||||
}
|
||||
|
||||
bb1: {
|
||||
StorageLive(_2);
|
||||
_2 = get_bool(_1) -> [return: bb2, unwind unreachable];
|
||||
switchInt(_1) -> [0: bb3, otherwise: bb2];
|
||||
}
|
||||
|
||||
bb2: {
|
||||
switchInt(move _2) -> [0: bb7, otherwise: bb3];
|
||||
switchInt(_1) -> [0: bb1, otherwise: bb3];
|
||||
}
|
||||
|
||||
bb3: {
|
||||
StorageLive(_3);
|
||||
_3 = get_bool(_1) -> [return: bb4, unwind unreachable];
|
||||
}
|
||||
|
||||
bb4: {
|
||||
switchInt(move _3) -> [0: bb5, otherwise: bb6];
|
||||
}
|
||||
|
||||
bb5: {
|
||||
StorageDead(_3);
|
||||
StorageDead(_2);
|
||||
goto -> bb1;
|
||||
}
|
||||
|
||||
bb6: {
|
||||
StorageDead(_3);
|
||||
goto -> bb7;
|
||||
}
|
||||
|
||||
bb7: {
|
||||
StorageDead(_2);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -3,44 +3,26 @@
|
||||
fn while_loop(_1: bool) -> () {
|
||||
debug c => _1;
|
||||
let mut _0: ();
|
||||
let mut _2: bool;
|
||||
let mut _3: bool;
|
||||
scope 1 (inlined get_bool) {
|
||||
debug c => _1;
|
||||
}
|
||||
scope 2 (inlined get_bool) {
|
||||
debug c => _1;
|
||||
}
|
||||
|
||||
bb0: {
|
||||
goto -> bb1;
|
||||
}
|
||||
|
||||
bb1: {
|
||||
StorageLive(_2);
|
||||
_2 = get_bool(_1) -> [return: bb2, unwind continue];
|
||||
switchInt(_1) -> [0: bb3, otherwise: bb2];
|
||||
}
|
||||
|
||||
bb2: {
|
||||
switchInt(move _2) -> [0: bb7, otherwise: bb3];
|
||||
switchInt(_1) -> [0: bb1, otherwise: bb3];
|
||||
}
|
||||
|
||||
bb3: {
|
||||
StorageLive(_3);
|
||||
_3 = get_bool(_1) -> [return: bb4, unwind continue];
|
||||
}
|
||||
|
||||
bb4: {
|
||||
switchInt(move _3) -> [0: bb5, otherwise: bb6];
|
||||
}
|
||||
|
||||
bb5: {
|
||||
StorageDead(_3);
|
||||
StorageDead(_2);
|
||||
goto -> bb1;
|
||||
}
|
||||
|
||||
bb6: {
|
||||
StorageDead(_3);
|
||||
goto -> bb7;
|
||||
}
|
||||
|
||||
bb7: {
|
||||
StorageDead(_2);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
#![crate_type = "lib"]
|
||||
|
||||
#[inline(never)]
|
||||
pub fn foo() {}
|
||||
|
@ -2,6 +2,7 @@
|
||||
use std::arch::asm;
|
||||
|
||||
#[deny(unreachable_code)]
|
||||
#[inline(never)]
|
||||
pub fn exit(n: usize) -> i32 {
|
||||
unsafe {
|
||||
// Pretend this asm is an exit() syscall.
|
||||
|
@ -5,6 +5,7 @@ use std::arch::asm;
|
||||
use std::intrinsics;
|
||||
|
||||
#[allow(unreachable_code)]
|
||||
#[inline(never)]
|
||||
pub fn exit(n: usize) -> i32 {
|
||||
unsafe {
|
||||
// Pretend this asm is an exit() syscall.
|
||||
|
@ -1,3 +1,3 @@
|
||||
thread 'main' panicked at library/alloc/src/raw_vec.rs:534:5:
|
||||
thread 'main' panicked at library/alloc/src/raw_vec.rs:535:5:
|
||||
capacity overflow
|
||||
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
|
||||
|
Loading…
Reference in New Issue
Block a user