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