]> git.proxmox.com Git - rustc.git/blame - src/librustc_mir/build/mod.rs
New upstream version 1.15.0+dfsg1
[rustc.git] / src / librustc_mir / build / mod.rs
CommitLineData
e9174d1e
SL
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
92a42be0 11use hair::cx::Cx;
c30ab7b3
SL
12use hair::Pattern;
13
a7813a04
XL
14use rustc::middle::region::{CodeExtent, CodeExtentData, ROOT_CODE_EXTENT};
15use rustc::ty::{self, Ty};
c30ab7b3 16use rustc::mir::*;
3157f602 17use rustc::util::nodemap::NodeMap;
54a0048b 18use rustc::hir;
a7813a04 19use syntax::abi::Abi;
b039eaaf 20use syntax::ast;
476ff2be 21use syntax::symbol::keywords;
3157f602
XL
22use syntax_pos::Span;
23
24use rustc_data_structures::indexed_vec::{IndexVec, Idx};
25
26use std::u32;
b039eaaf 27
a7813a04
XL
28pub struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
29 hir: Cx<'a, 'gcx, 'tcx>,
b039eaaf 30 cfg: CFG<'tcx>,
54a0048b
SL
31
32 fn_span: Span,
c30ab7b3 33 arg_count: usize,
54a0048b 34
a7813a04
XL
35 /// the current set of scopes, updated as we traverse;
36 /// see the `scope` module for more details
b039eaaf 37 scopes: Vec<scope::Scope<'tcx>>,
54a0048b 38
a7813a04
XL
39 /// the current set of loops; see the `scope` module for more
40 /// details
476ff2be 41 loop_scopes: Vec<scope::LoopScope<'tcx>>,
54a0048b 42
a7813a04
XL
43 /// the vector of all scopes that we have created thus far;
44 /// we track this for debuginfo later
3157f602
XL
45 visibility_scopes: IndexVec<VisibilityScope, VisibilityScopeData>,
46 visibility_scope: VisibilityScope,
54a0048b 47
c30ab7b3
SL
48 /// Maps node ids of variable bindings to the `Local`s created for them.
49 var_indices: NodeMap<Local>,
50 local_decls: IndexVec<Local, LocalDecl<'tcx>>,
7453a54e 51 unit_temp: Option<Lvalue<'tcx>>,
54a0048b 52
a7813a04
XL
53 /// cached block with the RESUME terminator; this is created
54 /// when first set of cleanups are built.
54a0048b 55 cached_resume_block: Option<BasicBlock>,
a7813a04
XL
56 /// cached block with the RETURN terminator
57 cached_return_block: Option<BasicBlock>,
e9174d1e
SL
58}
59
b039eaaf 60struct CFG<'tcx> {
3157f602
XL
61 basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
62}
63
64#[derive(Copy, Clone, Debug, PartialEq, Eq)]
65pub struct ScopeId(u32);
66
67impl Idx for ScopeId {
68 fn new(index: usize) -> ScopeId {
69 assert!(index < (u32::MAX as usize));
70 ScopeId(index as u32)
71 }
72
73 fn index(self) -> usize {
74 self.0 as usize
75 }
e9174d1e
SL
76}
77
78///////////////////////////////////////////////////////////////////////////
7453a54e
SL
79/// The `BlockAnd` "monad" packages up the new basic block along with a
80/// produced value (sometimes just unit, of course). The `unpack!`
81/// macro (and methods below) makes working with `BlockAnd` much more
82/// convenient.
e9174d1e
SL
83
84#[must_use] // if you don't use one of these results, you're leaving a dangling edge
9cc50fc6 85pub struct BlockAnd<T>(BasicBlock, T);
e9174d1e 86
92a42be0
SL
87trait BlockAndExtension {
88 fn and<T>(self, v: T) -> BlockAnd<T>;
89 fn unit(self) -> BlockAnd<()>;
90}
91
92impl BlockAndExtension for BasicBlock {
e9174d1e
SL
93 fn and<T>(self, v: T) -> BlockAnd<T> {
94 BlockAnd(self, v)
95 }
96
97 fn unit(self) -> BlockAnd<()> {
98 BlockAnd(self, ())
99 }
100}
101
102/// Update a block pointer and return the value.
103/// Use it like `let x = unpack!(block = self.foo(block, foo))`.
104macro_rules! unpack {
105 ($x:ident = $c:expr) => {
106 {
107 let BlockAnd(b, v) = $c;
108 $x = b;
109 v
110 }
111 };
112
113 ($c:expr) => {
114 {
115 let BlockAnd(b, ()) = $c;
116 b
117 }
118 };
119}
120
121///////////////////////////////////////////////////////////////////////////
7453a54e 122/// the main entry point for building MIR for a function
e9174d1e 123
a7813a04
XL
124pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
125 fn_id: ast::NodeId,
126 arguments: A,
476ff2be 127 abi: Abi,
5bcae85e 128 return_ty: Ty<'gcx>,
476ff2be
SL
129 ast_body: &'gcx hir::Expr)
130 -> Mir<'tcx>
a7813a04
XL
131 where A: Iterator<Item=(Ty<'gcx>, Option<&'gcx hir::Pat>)>
132{
c30ab7b3
SL
133 let arguments: Vec<_> = arguments.collect();
134
54a0048b 135 let tcx = hir.tcx();
a7813a04 136 let span = tcx.map.span(fn_id);
c30ab7b3 137 let mut builder = Builder::new(hir, span, arguments.len(), return_ty);
54a0048b 138
476ff2be 139 let body_id = ast_body.id;
54a0048b
SL
140 let call_site_extent =
141 tcx.region_maps.lookup_code_extent(
142 CodeExtentData::CallSiteScope { fn_id: fn_id, body_id: body_id });
a7813a04
XL
143 let arg_extent =
144 tcx.region_maps.lookup_code_extent(
145 CodeExtentData::ParameterScope { fn_id: fn_id, body_id: body_id });
146 let mut block = START_BLOCK;
c30ab7b3
SL
147 unpack!(block = builder.in_scope(call_site_extent, block, |builder| {
148 unpack!(block = builder.in_scope(arg_extent, block, |builder| {
476ff2be 149 builder.args_and_body(block, &arguments, arg_extent, ast_body)
54a0048b 150 }));
c30ab7b3
SL
151 // Attribute epilogue to function's closing brace
152 let fn_end = Span { lo: span.hi, ..span };
153 let source_info = builder.source_info(fn_end);
a7813a04 154 let return_block = builder.return_block();
3157f602 155 builder.cfg.terminate(block, source_info,
a7813a04 156 TerminatorKind::Goto { target: return_block });
3157f602 157 builder.cfg.terminate(return_block, source_info,
54a0048b 158 TerminatorKind::Return);
c30ab7b3 159 return_block.unit()
a7813a04
XL
160 }));
161 assert_eq!(block, builder.return_block());
162
c30ab7b3 163 let mut spread_arg = None;
476ff2be
SL
164 if abi == Abi::RustCall {
165 // RustCall pseudo-ABI untuples the last argument.
166 spread_arg = Some(Local::new(arguments.len()));
a7813a04 167 }
54a0048b 168
a7813a04
XL
169 // Gather the upvars of a closure, if any.
170 let upvar_decls: Vec<_> = tcx.with_freevars(fn_id, |freevars| {
171 freevars.iter().map(|fv| {
9e0c209e 172 let var_id = tcx.map.as_local_node_id(fv.def.def_id()).unwrap();
c30ab7b3 173 let by_ref = tcx.tables().upvar_capture(ty::UpvarId {
9e0c209e 174 var_id: var_id,
a7813a04
XL
175 closure_expr_id: fn_id
176 }).map_or(false, |capture| match capture {
177 ty::UpvarCapture::ByValue => false,
178 ty::UpvarCapture::ByRef(..) => true
179 });
180 let mut decl = UpvarDecl {
181 debug_name: keywords::Invalid.name(),
182 by_ref: by_ref
183 };
9e0c209e 184 if let Some(hir::map::NodeLocal(pat)) = tcx.map.find(var_id) {
476ff2be 185 if let hir::PatKind::Binding(_, _, ref ident, _) = pat.node {
a7813a04
XL
186 decl.debug_name = ident.node;
187 }
188 }
189 decl
190 }).collect()
54a0048b
SL
191 });
192
476ff2be 193 let mut mir = builder.finish(upvar_decls, return_ty);
c30ab7b3 194 mir.spread_arg = spread_arg;
476ff2be 195 mir
a7813a04
XL
196}
197
198pub fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
199 item_id: ast::NodeId,
200 ast_expr: &'tcx hir::Expr)
476ff2be 201 -> Mir<'tcx> {
a7813a04 202 let tcx = hir.tcx();
c30ab7b3 203 let ty = tcx.tables().expr_ty_adjusted(ast_expr);
a7813a04 204 let span = tcx.map.span(item_id);
c30ab7b3 205 let mut builder = Builder::new(hir, span, 0, ty);
a7813a04 206
5bcae85e
SL
207 let extent = tcx.region_maps.temporary_scope(ast_expr.id)
208 .unwrap_or(ROOT_CODE_EXTENT);
a7813a04 209 let mut block = START_BLOCK;
3157f602 210 let _ = builder.in_scope(extent, block, |builder| {
a7813a04 211 let expr = builder.hir.mirror(ast_expr);
c30ab7b3 212 unpack!(block = builder.into(&Lvalue::Local(RETURN_POINTER), block, expr));
a7813a04 213
3157f602 214 let source_info = builder.source_info(span);
a7813a04 215 let return_block = builder.return_block();
3157f602 216 builder.cfg.terminate(block, source_info,
a7813a04 217 TerminatorKind::Goto { target: return_block });
3157f602 218 builder.cfg.terminate(return_block, source_info,
a7813a04
XL
219 TerminatorKind::Return);
220
221 return_block.unit()
222 });
223
c30ab7b3 224 builder.finish(vec![], ty)
e9174d1e
SL
225}
226
a7813a04 227impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
c30ab7b3
SL
228 fn new(hir: Cx<'a, 'gcx, 'tcx>,
229 span: Span,
230 arg_count: usize,
231 return_ty: Ty<'tcx>)
232 -> Builder<'a, 'gcx, 'tcx> {
a7813a04
XL
233 let mut builder = Builder {
234 hir: hir,
3157f602 235 cfg: CFG { basic_blocks: IndexVec::new() },
a7813a04 236 fn_span: span,
c30ab7b3 237 arg_count: arg_count,
a7813a04 238 scopes: vec![],
3157f602
XL
239 visibility_scopes: IndexVec::new(),
240 visibility_scope: ARGUMENT_VISIBILITY_SCOPE,
a7813a04 241 loop_scopes: vec![],
c30ab7b3 242 local_decls: IndexVec::from_elem_n(LocalDecl::new_return_pointer(return_ty), 1),
3157f602 243 var_indices: NodeMap(),
a7813a04
XL
244 unit_temp: None,
245 cached_resume_block: None,
246 cached_return_block: None
247 };
248
249 assert_eq!(builder.cfg.start_new_block(), START_BLOCK);
3157f602
XL
250 assert_eq!(builder.new_visibility_scope(span), ARGUMENT_VISIBILITY_SCOPE);
251 builder.visibility_scopes[ARGUMENT_VISIBILITY_SCOPE].parent_scope = None;
a7813a04
XL
252
253 builder
254 }
255
256 fn finish(self,
257 upvar_decls: Vec<UpvarDecl>,
5bcae85e 258 return_ty: Ty<'tcx>)
476ff2be 259 -> Mir<'tcx> {
a7813a04
XL
260 for (index, block) in self.cfg.basic_blocks.iter().enumerate() {
261 if block.terminator.is_none() {
262 span_bug!(self.fn_span, "no terminator on block {:?}", index);
263 }
264 }
265
476ff2be
SL
266 Mir::new(self.cfg.basic_blocks,
267 self.visibility_scopes,
268 IndexVec::new(),
269 return_ty,
270 self.local_decls,
271 self.arg_count,
272 upvar_decls,
273 self.fn_span
274 )
a7813a04
XL
275 }
276
c30ab7b3
SL
277 fn args_and_body(&mut self,
278 mut block: BasicBlock,
c30ab7b3
SL
279 arguments: &[(Ty<'gcx>, Option<&'gcx hir::Pat>)],
280 argument_extent: CodeExtent,
476ff2be 281 ast_body: &'gcx hir::Expr)
c30ab7b3 282 -> BlockAnd<()>
e9174d1e 283 {
c30ab7b3
SL
284 // Allocate locals for the function arguments
285 for &(ty, pattern) in arguments.iter() {
286 // If this is a simple binding pattern, give the local a nice name for debuginfo.
287 let mut name = None;
288 if let Some(pat) = pattern {
476ff2be 289 if let hir::PatKind::Binding(_, _, ref ident, _) = pat.node {
c30ab7b3
SL
290 name = Some(ident.node);
291 }
292 }
293
294 self.local_decls.push(LocalDecl {
295 mutability: Mutability::Not,
296 ty: ty,
297 source_info: None,
298 name: name,
299 });
300 }
301
3157f602 302 let mut scope = None;
c30ab7b3
SL
303 // Bind the argument patterns
304 for (index, &(ty, pattern)) in arguments.iter().enumerate() {
305 // Function arguments always get the first Local indices after the return pointer
306 let lvalue = Lvalue::Local(Local::new(index + 1));
307
a7813a04 308 if let Some(pattern) = pattern {
c30ab7b3 309 let pattern = Pattern::from_hir(self.hir.tcx(), pattern);
476ff2be 310 scope = self.declare_bindings(scope, ast_body.span, &pattern);
3157f602 311 unpack!(block = self.lvalue_into_pattern(block, pattern, &lvalue));
a7813a04 312 }
54a0048b 313
a7813a04 314 // Make sure we drop (parts of) the argument even when not matched on.
476ff2be 315 self.schedule_drop(pattern.as_ref().map_or(ast_body.span, |pat| pat.span),
a7813a04
XL
316 argument_extent, &lvalue, ty);
317
c30ab7b3 318 }
a7813a04 319
3157f602
XL
320 // Enter the argument pattern bindings visibility scope, if it exists.
321 if let Some(visibility_scope) = scope {
322 self.visibility_scope = visibility_scope;
323 }
324
476ff2be
SL
325 let body = self.hir.mirror(ast_body);
326 self.into(&Lvalue::Local(RETURN_POINTER), block, body)
e9174d1e 327 }
7453a54e
SL
328
329 fn get_unit_temp(&mut self) -> Lvalue<'tcx> {
330 match self.unit_temp {
331 Some(ref tmp) => tmp.clone(),
332 None => {
333 let ty = self.hir.unit_ty();
334 let tmp = self.temp(ty);
335 self.unit_temp = Some(tmp.clone());
336 tmp
337 }
338 }
339 }
a7813a04
XL
340
341 fn return_block(&mut self) -> BasicBlock {
342 match self.cached_return_block {
343 Some(rb) => rb,
344 None => {
345 let rb = self.cfg.start_new_block();
346 self.cached_return_block = Some(rb);
347 rb
348 }
349 }
350 }
e9174d1e
SL
351}
352
353///////////////////////////////////////////////////////////////////////////
354// Builder methods are broken up into modules, depending on what kind
355// of thing is being translated. Note that they use the `unpack` macro
356// above extensively.
357
358mod block;
359mod cfg;
360mod expr;
361mod into;
362mod matches;
363mod misc;
364mod scope;