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