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::{FnOutput, Ty};
14 use rustc::mir::repr::*;
15 use rustc_data_structures::fnv::FnvHashMap;
19 use syntax::codemap::Span;
21 struct Builder<'a, 'tcx: 'a> {
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>>,
33 basic_blocks: Vec<BasicBlockData<'tcx>>,
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
42 #[must_use] // if you don't use one of these results, you're leaving a dangling edge
43 struct BlockAnd<T>(BasicBlock, T);
45 trait BlockAndExtension {
46 fn and<T>(self, v: T) -> BlockAnd<T>;
47 fn unit(self) -> BlockAnd<()>;
50 impl BlockAndExtension for BasicBlock {
51 fn and<T>(self, v: T) -> BlockAnd<T> {
55 fn unit(self) -> BlockAnd<()> {
60 /// Update a block pointer and return the value.
61 /// Use it like `let x = unpack!(block = self.foo(block, foo))`.
63 ($x:ident = $c:expr) => {
65 let BlockAnd(b, v) = $c;
73 let BlockAnd(b, ()) = $c;
79 ///////////////////////////////////////////////////////////////////////////
80 // construct() -- the main entry point for building MIR for a function
82 pub fn construct<'a,'tcx>(mut hir: Cx<'a,'tcx>,
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)
90 let cfg = CFG { basic_blocks: vec![] };
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);
97 let mut builder = Builder {
102 temp_decls: temp_decls,
104 var_indices: FnvHashMap(),
105 unit_temp: unit_temp,
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);
112 let mut block = START_BLOCK;
113 let arg_decls = unpack!(block = builder.args_and_body(block,
119 builder.cfg.terminate(block, Terminator::Goto { target: END_BLOCK });
120 builder.cfg.terminate(END_BLOCK, Terminator::Return);
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,
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>>>
140 self.in_scope(argument_extent, block, |this| {
142 let implicit_arg_decls = implicit_arguments.into_iter()
143 .map(|ty| ArgDecl { ty: ty });
145 // to start, translate the argument patterns and collect the
147 let explicit_arg_decls =
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,
161 implicit_arg_decls.chain(explicit_arg_decls).collect()
164 // start the first basic block and translate the body
165 unpack!(block = this.ast_block(&Lvalue::ReturnPointer, block, ast_block));
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.