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