]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/build/mod.rs
Auto merge of #30017 - nrc:fmt, r=brson
[rust.git] / src / librustc_mir / build / mod.rs
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.
4 //
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.
10
11 use hair::cx::Cx;
12 use rustc::middle::region::CodeExtent;
13 use rustc::middle::ty::{FnOutput, Ty};
14 use rustc_data_structures::fnv::FnvHashMap;
15 use rustc_front::hir;
16 use repr::*;
17 use syntax::ast;
18 use syntax::codemap::Span;
19
20 struct Builder<'a, 'tcx: 'a> {
21     hir: Cx<'a, 'tcx>,
22     cfg: CFG<'tcx>,
23     scopes: Vec<scope::Scope<'tcx>>,
24     loop_scopes: Vec<scope::LoopScope>,
25     unit_temp: Lvalue<'tcx>,
26     var_decls: Vec<VarDecl<'tcx>>,
27     var_indices: FnvHashMap<ast::NodeId, u32>,
28     temp_decls: Vec<TempDecl<'tcx>>,
29 }
30
31 struct CFG<'tcx> {
32     basic_blocks: Vec<BasicBlockData<'tcx>>,
33 }
34
35 ///////////////////////////////////////////////////////////////////////////
36 // The `BlockAnd` "monad" packages up the new basic block along with a
37 // produced value (sometimes just unit, of course). The `unpack!`
38 // macro (and methods below) makes working with `BlockAnd` much more
39 // convenient.
40
41 #[must_use] // if you don't use one of these results, you're leaving a dangling edge
42 struct BlockAnd<T>(BasicBlock, T);
43
44 impl BasicBlock {
45     fn and<T>(self, v: T) -> BlockAnd<T> {
46         BlockAnd(self, v)
47     }
48
49     fn unit(self) -> BlockAnd<()> {
50         BlockAnd(self, ())
51     }
52 }
53
54 /// Update a block pointer and return the value.
55 /// Use it like `let x = unpack!(block = self.foo(block, foo))`.
56 macro_rules! unpack {
57     ($x:ident = $c:expr) => {
58         {
59             let BlockAnd(b, v) = $c;
60             $x = b;
61             v
62         }
63     };
64
65     ($c:expr) => {
66         {
67             let BlockAnd(b, ()) = $c;
68             b
69         }
70     };
71 }
72
73 ///////////////////////////////////////////////////////////////////////////
74 // construct() -- the main entry point for building MIR for a function
75
76 pub fn construct<'a,'tcx>(mut hir: Cx<'a,'tcx>,
77                           _span: Span,
78                           implicit_arguments: Vec<Ty<'tcx>>,
79                           explicit_arguments: Vec<(Ty<'tcx>, &'tcx hir::Pat)>,
80                           argument_extent: CodeExtent,
81                           return_ty: FnOutput<'tcx>,
82                           ast_block: &'tcx hir::Block)
83                           -> Mir<'tcx> {
84     let cfg = CFG { basic_blocks: vec![] };
85
86     // it's handy to have a temporary of type `()` sometimes, so make
87     // one from the start and keep it available
88     let temp_decls = vec![TempDecl::<'tcx> { ty: hir.unit_ty() }];
89     let unit_temp = Lvalue::Temp(0);
90
91     let mut builder = Builder {
92         hir: hir,
93         cfg: cfg,
94         scopes: vec![],
95         loop_scopes: vec![],
96         temp_decls: temp_decls,
97         var_decls: vec![],
98         var_indices: FnvHashMap(),
99         unit_temp: unit_temp,
100     };
101
102     assert_eq!(builder.cfg.start_new_block(), START_BLOCK);
103     assert_eq!(builder.cfg.start_new_block(), END_BLOCK);
104     assert_eq!(builder.cfg.start_new_block(), DIVERGE_BLOCK);
105
106     let mut block = START_BLOCK;
107     let arg_decls = unpack!(block = builder.args_and_body(block,
108                                                           implicit_arguments,
109                                                           explicit_arguments,
110                                                           argument_extent,
111                                                           ast_block));
112
113     builder.cfg.terminate(block, Terminator::Goto { target: END_BLOCK });
114     builder.cfg.terminate(END_BLOCK, Terminator::Return);
115
116     Mir {
117         basic_blocks: builder.cfg.basic_blocks,
118         var_decls: builder.var_decls,
119         arg_decls: arg_decls,
120         temp_decls: builder.temp_decls,
121         return_ty: return_ty,
122     }
123 }
124
125 impl<'a,'tcx> Builder<'a,'tcx> {
126     fn args_and_body(&mut self,
127                      mut block: BasicBlock,
128                      implicit_arguments: Vec<Ty<'tcx>>,
129                      explicit_arguments: Vec<(Ty<'tcx>, &'tcx hir::Pat)>,
130                      argument_extent: CodeExtent,
131                      ast_block: &'tcx hir::Block)
132                      -> BlockAnd<Vec<ArgDecl<'tcx>>>
133     {
134         self.in_scope(argument_extent, block, |this| {
135             let arg_decls = {
136                 let implicit_arg_decls = implicit_arguments.into_iter()
137                                                            .map(|ty| ArgDecl { ty: ty });
138
139                 // to start, translate the argument patterns and collect the
140                 // argument types.
141                 let explicit_arg_decls =
142                     explicit_arguments
143                     .into_iter()
144                     .enumerate()
145                     .map(|(index, (ty, pattern))| {
146                         let lvalue = Lvalue::Arg(index as u32);
147                         let pattern = this.hir.irrefutable_pat(pattern);
148                         unpack!(block = this.lvalue_into_pattern(block,
149                                                                  argument_extent,
150                                                                  pattern,
151                                                                  &lvalue));
152                         ArgDecl { ty: ty }
153                     });
154
155                 implicit_arg_decls.chain(explicit_arg_decls).collect()
156             };
157
158             // start the first basic block and translate the body
159             unpack!(block = this.ast_block(&Lvalue::ReturnPointer, block, ast_block));
160
161             block.and(arg_decls)
162         })
163     }
164 }
165
166 ///////////////////////////////////////////////////////////////////////////
167 // Builder methods are broken up into modules, depending on what kind
168 // of thing is being translated. Note that they use the `unpack` macro
169 // above extensively.
170
171 mod block;
172 mod cfg;
173 mod expr;
174 mod into;
175 mod matches;
176 mod misc;
177 mod scope;
178 mod stmt;