1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
12 use rustc
::hir
::def_id
::{CrateNum, DefId, LOCAL_CRATE}
;
14 use rustc
::mir
::transform
::{MirPassIndex
, MirSuite
, MirSource
,
15 MIR_CONST
, MIR_VALIDATED
, MIR_OPTIMIZED
};
16 use rustc
::ty
::{self, TyCtxt}
;
17 use rustc
::ty
::maps
::Providers
;
18 use rustc
::ty
::steal
::Steal
;
20 use rustc
::hir
::intravisit
::{self, Visitor, NestedVisitorMap}
;
21 use rustc
::util
::nodemap
::DefIdSet
;
24 use syntax_pos
::{DUMMY_SP, Span}
;
27 pub mod clean_end_regions
;
28 pub mod simplify_branches
;
30 pub mod erase_regions
;
31 pub mod no_landing_pads
;
34 pub mod elaborate_drops
;
35 pub mod add_call_guards
;
36 pub mod promote_consts
;
37 pub mod qualify_consts
;
44 pub(crate) fn provide(providers
: &mut Providers
) {
45 self::qualify_consts
::provide(providers
);
46 *providers
= Providers
{
56 fn is_mir_available
<'a
, 'tcx
>(tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>, def_id
: DefId
) -> bool
{
57 tcx
.mir_keys(def_id
.krate
).contains(&def_id
)
60 /// Finds the full set of def-ids within the current crate that have
61 /// MIR associated with them.
62 fn mir_keys
<'a
, 'tcx
>(tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>, krate
: CrateNum
)
64 assert_eq
!(krate
, LOCAL_CRATE
);
66 let mut set
= DefIdSet();
68 // All body-owners have MIR associated with them.
69 set
.extend(tcx
.body_owners());
71 // Additionally, tuple struct/variant constructors have MIR, but
72 // they don't have a BodyId, so we need to build them separately.
73 struct GatherCtors
<'a
, 'tcx
: 'a
> {
74 tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>,
75 set
: &'a
mut DefIdSet
,
77 impl<'a
, 'tcx
> Visitor
<'tcx
> for GatherCtors
<'a
, 'tcx
> {
78 fn visit_variant_data(&mut self,
79 v
: &'tcx hir
::VariantData
,
81 _
: &'tcx hir
::Generics
,
84 if let hir
::VariantData
::Tuple(_
, node_id
) = *v
{
85 self.set
.insert(self.tcx
.hir
.local_def_id(node_id
));
87 intravisit
::walk_struct_def(self, v
)
89 fn nested_visit_map
<'b
>(&'b
mut self) -> NestedVisitorMap
<'b
, 'tcx
> {
90 NestedVisitorMap
::None
93 tcx
.hir
.krate().visit_all_item_likes(&mut GatherCtors
{
101 fn mir_const
<'a
, 'tcx
>(tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>, def_id
: DefId
) -> &'tcx Steal
<Mir
<'tcx
>> {
102 let mut mir
= build
::mir_build(tcx
, def_id
);
103 let source
= MirSource
::from_local_def_id(tcx
, def_id
);
104 transform
::run_suite(tcx
, source
, MIR_CONST
, &mut mir
);
105 tcx
.alloc_steal_mir(mir
)
108 fn mir_validated
<'a
, 'tcx
>(tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>, def_id
: DefId
) -> &'tcx Steal
<Mir
<'tcx
>> {
109 let source
= MirSource
::from_local_def_id(tcx
, def_id
);
110 if let MirSource
::Const(_
) = source
{
111 // Ensure that we compute the `mir_const_qualif` for constants at
112 // this point, before we steal the mir-const result. We don't
113 // directly need the result or `mir_const_qualif`, so we can just force it.
114 ty
::queries
::mir_const_qualif
::force(tcx
, DUMMY_SP
, def_id
);
117 let mut mir
= tcx
.mir_const(def_id
).steal();
118 transform
::run_suite(tcx
, source
, MIR_VALIDATED
, &mut mir
);
119 tcx
.alloc_steal_mir(mir
)
122 fn optimized_mir
<'a
, 'tcx
>(tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>, def_id
: DefId
) -> &'tcx Mir
<'tcx
> {
123 // Borrowck uses `mir_validated`, so we have to force it to
124 // execute before we can steal.
125 ty
::queries
::borrowck
::force(tcx
, DUMMY_SP
, def_id
);
127 let mut mir
= tcx
.mir_validated(def_id
).steal();
128 let source
= MirSource
::from_local_def_id(tcx
, def_id
);
129 transform
::run_suite(tcx
, source
, MIR_OPTIMIZED
, &mut mir
);
133 fn run_suite
<'a
, 'tcx
>(tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>,
138 let passes
= tcx
.mir_passes
.passes(suite
);
140 for (pass
, index
) in passes
.iter().zip(0..) {
141 let pass_num
= MirPassIndex(index
);
143 for hook
in tcx
.mir_passes
.hooks() {
144 hook
.on_mir_pass(tcx
, suite
, pass_num
, &pass
.name(), source
, &mir
, false);
147 pass
.run_pass(tcx
, source
, mir
);
149 for hook
in tcx
.mir_passes
.hooks() {
150 hook
.on_mir_pass(tcx
, suite
, pass_num
, &pass
.name(), source
, &mir
, true);