1 // Copyright 2012-2014 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
::middle
::region
::CodeExtent
;
13 use rustc
::middle
::ty
::Ty
;
14 use rustc_data_structures
::fnv
::FnvHashMap
;
18 use syntax
::codemap
::Span
;
19 use tcx
::{Cx, PatNode}
;
21 struct Builder
<'a
, 'tcx
: 'a
> {
23 extents
: FnvHashMap
<CodeExtent
, Vec
<GraphExtent
>>,
25 scopes
: Vec
<scope
::Scope
<'tcx
>>,
26 loop_scopes
: Vec
<scope
::LoopScope
>,
27 unit_temp
: Lvalue
<'tcx
>,
28 var_decls
: Vec
<VarDecl
<'tcx
>>,
29 var_indices
: FnvHashMap
<ast
::NodeId
, u32>,
30 temp_decls
: Vec
<TempDecl
<'tcx
>>,
34 basic_blocks
: Vec
<BasicBlockData
<'tcx
>>,
37 ///////////////////////////////////////////////////////////////////////////
38 // The `BlockAnd` "monad" packages up the new basic block along with a
39 // produced value (sometimes just unit, of course). The `unpack!`
40 // macro (and methods below) makes working with `BlockAnd` much more
43 #[must_use] // if you don't use one of these results, you're leaving a dangling edge
44 struct BlockAnd
<T
>(BasicBlock
, T
);
47 fn and
<T
>(self, v
: T
) -> BlockAnd
<T
> {
51 fn unit(self) -> BlockAnd
<()> {
56 /// Update a block pointer and return the value.
57 /// Use it like `let x = unpack!(block = self.foo(block, foo))`.
59 ($x
:ident
= $c
:expr
) => {
61 let BlockAnd(b
, v
) = $c
;
69 let BlockAnd(b
, ()) = $c
;
75 ///////////////////////////////////////////////////////////////////////////
76 // construct() -- the main entry point for building MIR for a function
78 pub fn construct
<'a
, 'tcx
>(mut hir
: Cx
<'a
, 'tcx
>,
80 implicit_arguments
: Vec
<Ty
<'tcx
>>,
81 explicit_arguments
: Vec
<(Ty
<'tcx
>, PatNode
<'tcx
>)>,
82 argument_extent
: CodeExtent
,
83 ast_block
: &'tcx hir
::Block
)
85 let cfg
= CFG { basic_blocks: vec![] }
;
87 // it's handy to have a temporary of type `()` sometimes, so make
88 // one from the start and keep it available
89 let temp_decls
= vec
![TempDecl
::<'tcx
> { ty: hir.unit_ty() }
];
90 let unit_temp
= Lvalue
::Temp(0);
92 let mut builder
= Builder
{
95 extents
: FnvHashMap(),
98 temp_decls
: temp_decls
,
100 var_indices
: FnvHashMap(),
101 unit_temp
: unit_temp
,
104 assert_eq
!(builder
.cfg
.start_new_block(), START_BLOCK
);
105 assert_eq
!(builder
.cfg
.start_new_block(), END_BLOCK
);
106 assert_eq
!(builder
.cfg
.start_new_block(), DIVERGE_BLOCK
);
108 let mut block
= START_BLOCK
;
109 let arg_decls
= unpack
!(block
= builder
.args_and_body(block
,
115 builder
.cfg
.terminate(block
, Terminator
::Goto { target: END_BLOCK }
);
116 builder
.cfg
.terminate(END_BLOCK
, Terminator
::Return
);
119 basic_blocks
: builder
.cfg
.basic_blocks
,
120 extents
: builder
.extents
,
121 var_decls
: builder
.var_decls
,
122 arg_decls
: arg_decls
,
123 temp_decls
: builder
.temp_decls
,
127 impl<'a
,'tcx
> Builder
<'a
,'tcx
> {
128 fn args_and_body(&mut self,
129 mut block
: BasicBlock
,
130 implicit_arguments
: Vec
<Ty
<'tcx
>>,
131 explicit_arguments
: Vec
<(Ty
<'tcx
>, PatNode
<'tcx
>)>,
132 argument_extent
: CodeExtent
,
133 ast_block
: &'tcx hir
::Block
)
134 -> BlockAnd
<Vec
<ArgDecl
<'tcx
>>>
136 self.in_scope(argument_extent
, block
, |this
| {
138 let implicit_arg_decls
= implicit_arguments
.into_iter()
139 .map(|ty
| ArgDecl { ty: ty }
);
141 // to start, translate the argument patterns and collect the
143 let explicit_arg_decls
=
147 .map(|(index
, (ty
, pattern
))| {
148 let lvalue
= Lvalue
::Arg(index
as u32);
149 unpack
!(block
= this
.lvalue_into_pattern(block
,
151 hair
::PatternRef
::Hair(pattern
),
156 implicit_arg_decls
.chain(explicit_arg_decls
).collect()
159 // start the first basic block and translate the body
160 unpack
!(block
= this
.ast_block(&Lvalue
::ReturnPointer
, block
, ast_block
));
167 ///////////////////////////////////////////////////////////////////////////
168 // Builder methods are broken up into modules, depending on what kind
169 // of thing is being translated. Note that they use the `unpack` macro
170 // above extensively.