]> git.proxmox.com Git - rustc.git/blame - src/librustc_trans/mir/mod.rs
New upstream version 1.17.0+dfsg1
[rustc.git] / src / librustc_trans / mir / mod.rs
CommitLineData
92a42be0
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
11use libc::c_uint;
32a655c1
SL
12use llvm::{self, ValueRef, BasicBlockRef};
13use llvm::debuginfo::DIScope;
476ff2be 14use rustc::ty::{self, layout};
32a655c1 15use rustc::mir::{self, Mir};
92a42be0 16use rustc::mir::tcx::LvalueTy;
32a655c1
SL
17use rustc::ty::subst::Substs;
18use rustc::infer::TransNormalize;
19use rustc::ty::TypeFoldable;
a7813a04 20use session::config::FullDebugInfo;
54a0048b 21use base;
32a655c1
SL
22use builder::Builder;
23use common::{self, CrateContext, C_null, Funclet};
24use debuginfo::{self, declare_local, VariableAccess, VariableKind, FunctionDebugContext};
25use monomorphize::{self, Instance};
26use abi::FnType;
a7813a04
XL
27use type_of;
28
32a655c1 29use syntax_pos::{DUMMY_SP, NO_EXPANSION, COMMAND_LINE_EXPN, BytePos, Span};
476ff2be 30use syntax::symbol::keywords;
54a0048b 31
5bcae85e 32use std::iter;
54a0048b 33
54a0048b 34use rustc_data_structures::bitvec::BitVector;
3157f602 35use rustc_data_structures::indexed_vec::{IndexVec, Idx};
54a0048b 36
a7813a04
XL
37pub use self::constant::trans_static_initializer;
38
32a655c1
SL
39use self::analyze::CleanupKind;
40use self::lvalue::{Alignment, LvalueRef};
3157f602 41use rustc::mir::traversal;
92a42be0 42
a7813a04 43use self::operand::{OperandRef, OperandValue};
92a42be0 44
92a42be0 45/// Master context for translating MIR.
32a655c1
SL
46pub struct MirContext<'a, 'tcx:'a> {
47 mir: &'a mir::Mir<'tcx>,
48
49 debug_context: debuginfo::FunctionDebugContext,
50
51 llfn: ValueRef,
92a42be0 52
32a655c1
SL
53 ccx: &'a CrateContext<'a, 'tcx>,
54
55 fn_ty: FnType,
9cc50fc6 56
92a42be0
SL
57 /// When unwinding is initiated, we have to store this personality
58 /// value somewhere so that we can load it and re-use it in the
59 /// resume instruction. The personality is (afaik) some kind of
60 /// value used for C++ unwinding, which must filter by type: we
61 /// don't really care about it very much. Anyway, this value
62 /// contains an alloca into which the personality is stored and
63 /// then later loaded when generating the DIVERGE_BLOCK.
64 llpersonalityslot: Option<ValueRef>,
65
66 /// A `Block` for each MIR `BasicBlock`
32a655c1 67 blocks: IndexVec<mir::BasicBlock, BasicBlockRef>,
3157f602
XL
68
69 /// The funclet status of each basic block
70 cleanup_kinds: IndexVec<mir::BasicBlock, analyze::CleanupKind>,
71
72 /// This stores the landing-pad block for a given BB, computed lazily on GNU
73 /// and eagerly on MSVC.
32a655c1 74 landing_pads: IndexVec<mir::BasicBlock, Option<BasicBlockRef>>,
92a42be0 75
9cc50fc6 76 /// Cached unreachable block
32a655c1 77 unreachable_block: Option<BasicBlockRef>,
9cc50fc6 78
3157f602 79 /// The location where each MIR arg/var/tmp/ret is stored. This is
92a42be0
SL
80 /// usually an `LvalueRef` representing an alloca, but not always:
81 /// sometimes we can skip the alloca and just store the value
82 /// directly using an `OperandRef`, which makes for tighter LLVM
83 /// IR. The conditions for using an `OperandRef` are as follows:
84 ///
3157f602 85 /// - the type of the local must be judged "immediate" by `type_is_immediate`
92a42be0
SL
86 /// - the operand must never be referenced indirectly
87 /// - we should not take its address using the `&` operator
88 /// - nor should it appear in an lvalue path like `tmp.a`
89 /// - the operand must be defined by an rvalue that can generate immediate
90 /// values
91 ///
92 /// Avoiding allocs can also be important for certain intrinsics,
93 /// notably `expect`.
3157f602 94 locals: IndexVec<mir::Local, LocalRef<'tcx>>,
a7813a04
XL
95
96 /// Debug information for MIR scopes.
9e0c209e 97 scopes: IndexVec<mir::VisibilityScope, debuginfo::MirDebugScope>,
32a655c1
SL
98
99 /// If this function is being monomorphized, this contains the type substitutions used.
100 param_substs: &'tcx Substs<'tcx>,
3157f602
XL
101}
102
32a655c1
SL
103impl<'a, 'tcx> MirContext<'a, 'tcx> {
104 pub fn monomorphize<T>(&self, value: &T) -> T
105 where T: TransNormalize<'tcx> {
106 monomorphize::apply_param_substs(self.ccx.shared(), self.param_substs, value)
107 }
108
109 pub fn set_debug_loc(&mut self, bcx: &Builder, source_info: mir::SourceInfo) {
110 let (scope, span) = self.debug_loc(source_info);
111 debuginfo::set_source_location(&self.debug_context, bcx, scope, span);
112 }
113
114 pub fn debug_loc(&mut self, source_info: mir::SourceInfo) -> (DIScope, Span) {
9e0c209e 115 // Bail out if debug info emission is not enabled.
32a655c1 116 match self.debug_context {
9e0c209e
SL
117 FunctionDebugContext::DebugInfoDisabled |
118 FunctionDebugContext::FunctionWithoutDebugInfo => {
32a655c1 119 return (self.scopes[source_info.scope].scope_metadata, source_info.span);
9e0c209e
SL
120 }
121 FunctionDebugContext::RegularContext(_) =>{}
122 }
123
124 // In order to have a good line stepping behavior in debugger, we overwrite debug
125 // locations of macro expansions with that of the outermost expansion site
126 // (unless the crate is being compiled with `-Z debug-macros`).
127 if source_info.span.expn_id == NO_EXPANSION ||
128 source_info.span.expn_id == COMMAND_LINE_EXPN ||
32a655c1 129 self.ccx.sess().opts.debugging_opts.debug_macros {
9e0c209e 130
32a655c1
SL
131 let scope = self.scope_metadata_for_loc(source_info.scope, source_info.span.lo);
132 (scope, source_info.span)
9e0c209e 133 } else {
32a655c1 134 let cm = self.ccx.sess().codemap();
9e0c209e 135 // Walk up the macro expansion chain until we reach a non-expanded span.
8bb4bdeb
XL
136 // We also stop at the function body level because no line stepping can occurr
137 // at the level above that.
9e0c209e 138 let mut span = source_info.span;
8bb4bdeb
XL
139 while span.expn_id != NO_EXPANSION &&
140 span.expn_id != COMMAND_LINE_EXPN &&
141 span.expn_id != self.mir.span.expn_id {
9e0c209e
SL
142 if let Some(callsite_span) = cm.with_expn_info(span.expn_id,
143 |ei| ei.map(|ei| ei.call_site.clone())) {
144 span = callsite_span;
145 } else {
146 break;
147 }
148 }
32a655c1 149 let scope = self.scope_metadata_for_loc(source_info.scope, span.lo);
8bb4bdeb 150 // Use span of the outermost expansion site, while keeping the original lexical scope.
32a655c1 151 (scope, span)
9e0c209e
SL
152 }
153 }
154
155 // DILocations inherit source file name from the parent DIScope. Due to macro expansions
156 // it may so happen that the current span belongs to a different file than the DIScope
157 // corresponding to span's containing visibility scope. If so, we need to create a DIScope
158 // "extension" into that file.
159 fn scope_metadata_for_loc(&self, scope_id: mir::VisibilityScope, pos: BytePos)
160 -> llvm::debuginfo::DIScope {
161 let scope_metadata = self.scopes[scope_id].scope_metadata;
162 if pos < self.scopes[scope_id].file_start_pos ||
163 pos >= self.scopes[scope_id].file_end_pos {
32a655c1
SL
164 let cm = self.ccx.sess().codemap();
165 debuginfo::extend_scope_to_file(self.ccx, scope_metadata, &cm.lookup_char_pos(pos).file)
9e0c209e
SL
166 } else {
167 scope_metadata
168 }
3157f602 169 }
92a42be0
SL
170}
171
3157f602 172enum LocalRef<'tcx> {
92a42be0
SL
173 Lvalue(LvalueRef<'tcx>),
174 Operand(Option<OperandRef<'tcx>>),
175}
176
3157f602 177impl<'tcx> LocalRef<'tcx> {
32a655c1 178 fn new_operand<'a>(ccx: &CrateContext<'a, 'tcx>,
3157f602 179 ty: ty::Ty<'tcx>) -> LocalRef<'tcx> {
a7813a04
XL
180 if common::type_is_zero_size(ccx, ty) {
181 // Zero-size temporaries aren't always initialized, which
182 // doesn't matter because they don't contain data, but
183 // we need something in the operand.
3157f602
XL
184 let llty = type_of::type_of(ccx, ty);
185 let val = if common::type_is_imm_pair(ccx, ty) {
186 let fields = llty.field_types();
187 OperandValue::Pair(C_null(fields[0]), C_null(fields[1]))
188 } else {
189 OperandValue::Immediate(C_null(llty))
190 };
a7813a04
XL
191 let op = OperandRef {
192 val: val,
193 ty: ty
194 };
3157f602 195 LocalRef::Operand(Some(op))
a7813a04 196 } else {
3157f602 197 LocalRef::Operand(None)
a7813a04
XL
198 }
199 }
200}
201
92a42be0
SL
202///////////////////////////////////////////////////////////////////////////
203
32a655c1
SL
204pub fn trans_mir<'a, 'tcx: 'a>(
205 ccx: &'a CrateContext<'a, 'tcx>,
206 llfn: ValueRef,
32a655c1
SL
207 mir: &'a Mir<'tcx>,
208 instance: Instance<'tcx>,
8bb4bdeb 209 sig: ty::FnSig<'tcx>,
32a655c1 210) {
8bb4bdeb 211 let fn_ty = FnType::new(ccx, sig, &[]);
32a655c1
SL
212 debug!("fn_ty: {:?}", fn_ty);
213 let debug_context =
8bb4bdeb 214 debuginfo::create_function_debug_context(ccx, instance, sig, llfn, mir);
32a655c1
SL
215 let bcx = Builder::new_block(ccx, llfn, "entry-block");
216
217 let cleanup_kinds = analyze::cleanup_kinds(&mir);
92a42be0 218
9e0c209e 219 // Allocate a `Block` for every basic block
32a655c1 220 let block_bcxs: IndexVec<mir::BasicBlock, BasicBlockRef> =
9e0c209e
SL
221 mir.basic_blocks().indices().map(|bb| {
222 if bb == mir::START_BLOCK {
32a655c1 223 bcx.build_sibling_block("start").llbb()
9e0c209e 224 } else {
32a655c1 225 bcx.build_sibling_block(&format!("{:?}", bb)).llbb()
9e0c209e
SL
226 }
227 }).collect();
228
a7813a04 229 // Compute debuginfo scopes from MIR scopes.
32a655c1 230 let scopes = debuginfo::create_mir_scopes(ccx, mir, &debug_context);
a7813a04 231
9e0c209e 232 let mut mircx = MirContext {
32a655c1
SL
233 mir: mir,
234 llfn: llfn,
235 fn_ty: fn_ty,
236 ccx: ccx,
9e0c209e
SL
237 llpersonalityslot: None,
238 blocks: block_bcxs,
239 unreachable_block: None,
240 cleanup_kinds: cleanup_kinds,
241 landing_pads: IndexVec::from_elem(None, mir.basic_blocks()),
242 scopes: scopes,
243 locals: IndexVec::new(),
32a655c1
SL
244 debug_context: debug_context,
245 param_substs: {
246 assert!(!instance.substs.needs_infer());
247 instance.substs
248 },
9e0c209e
SL
249 };
250
32a655c1
SL
251 let lvalue_locals = analyze::lvalue_locals(&mircx);
252
92a42be0 253 // Allocate variable and temp allocas
9e0c209e 254 mircx.locals = {
32a655c1 255 let args = arg_local_refs(&bcx, &mircx, &mircx.scopes, &lvalue_locals);
c30ab7b3
SL
256
257 let mut allocate_local = |local| {
258 let decl = &mir.local_decls[local];
32a655c1 259 let ty = mircx.monomorphize(&decl.ty);
3157f602 260
c30ab7b3
SL
261 if let Some(name) = decl.name {
262 // User variable
263 let source_info = decl.source_info.unwrap();
264 let debug_scope = mircx.scopes[source_info.scope];
265 let dbg = debug_scope.is_valid() && bcx.sess().opts.debuginfo == FullDebugInfo;
a7813a04 266
c30ab7b3
SL
267 if !lvalue_locals.contains(local.index()) && !dbg {
268 debug!("alloc: {:?} ({}) -> operand", local, name);
32a655c1 269 return LocalRef::new_operand(bcx.ccx, ty);
9e0c209e 270 }
c30ab7b3
SL
271
272 debug!("alloc: {:?} ({}) -> lvalue", local, name);
32a655c1 273 assert!(!ty.has_erasable_regions());
c30ab7b3
SL
274 let lvalue = LvalueRef::alloca(&bcx, ty, &name.as_str());
275 if dbg {
32a655c1
SL
276 let (scope, span) = mircx.debug_loc(source_info);
277 declare_local(&bcx, &mircx.debug_context, name, ty, scope,
278 VariableAccess::DirectVariable { alloca: lvalue.llval },
279 VariableKind::LocalVariable, span);
c30ab7b3
SL
280 }
281 LocalRef::Lvalue(lvalue)
3157f602 282 } else {
c30ab7b3 283 // Temporary or return pointer
32a655c1 284 if local == mir::RETURN_POINTER && mircx.fn_ty.ret.is_indirect() {
c30ab7b3 285 debug!("alloc: {:?} (return pointer) -> lvalue", local);
32a655c1
SL
286 let llretptr = llvm::get_param(llfn, 0);
287 LocalRef::Lvalue(LvalueRef::new_sized(llretptr, LvalueTy::from_ty(ty),
288 Alignment::AbiAligned))
c30ab7b3
SL
289 } else if lvalue_locals.contains(local.index()) {
290 debug!("alloc: {:?} -> lvalue", local);
32a655c1
SL
291 assert!(!ty.has_erasable_regions());
292 LocalRef::Lvalue(LvalueRef::alloca(&bcx, ty, &format!("{:?}", local)))
c30ab7b3
SL
293 } else {
294 // If this is an immediate local, we do not create an
295 // alloca in advance. Instead we wait until we see the
296 // definition and update the operand there.
297 debug!("alloc: {:?} -> operand", local);
32a655c1 298 LocalRef::new_operand(bcx.ccx, ty)
c30ab7b3 299 }
3157f602 300 }
c30ab7b3
SL
301 };
302
303 let retptr = allocate_local(mir::RETURN_POINTER);
304 iter::once(retptr)
305 .chain(args.into_iter())
306 .chain(mir.vars_and_temps_iter().map(allocate_local))
307 .collect()
3157f602 308 };
92a42be0 309
92a42be0 310 // Branch to the START block
9e0c209e 311 let start_bcx = mircx.blocks[mir::START_BLOCK];
32a655c1 312 bcx.br(start_bcx);
92a42be0 313
a7813a04
XL
314 // Up until here, IR instructions for this function have explicitly not been annotated with
315 // source code location, so we don't step into call setup code. From here on, source location
316 // emitting should be enabled.
32a655c1
SL
317 debuginfo::start_emitting_source_locations(&mircx.debug_context);
318
319 let funclets: IndexVec<mir::BasicBlock, Option<Funclet>> =
320 mircx.cleanup_kinds.iter_enumerated().map(|(bb, cleanup_kind)| {
321 if let CleanupKind::Funclet = *cleanup_kind {
322 let bcx = mircx.get_builder(bb);
8bb4bdeb
XL
323 unsafe {
324 llvm::LLVMSetPersonalityFn(mircx.llfn, mircx.ccx.eh_personality());
325 }
32a655c1
SL
326 if base::wants_msvc_seh(ccx.sess()) {
327 return Some(Funclet::new(bcx.cleanup_pad(None, &[])));
328 }
329 }
3157f602 330
32a655c1
SL
331 None
332 }).collect();
3157f602 333
32a655c1
SL
334 let rpo = traversal::reverse_postorder(&mir);
335 let mut visited = BitVector::new(mir.basic_blocks().len());
54a0048b 336
54a0048b
SL
337 // Translate the body of each block using reverse postorder
338 for (bb, _) in rpo {
339 visited.insert(bb.index());
32a655c1 340 mircx.trans_block(bb, &funclets);
92a42be0 341 }
54a0048b
SL
342
343 // Remove blocks that haven't been visited, or have no
344 // predecessors.
3157f602 345 for bb in mir.basic_blocks().indices() {
54a0048b
SL
346 // Unreachable block
347 if !visited.contains(bb.index()) {
3157f602 348 debug!("trans_mir: block {:?} was not visited", bb);
32a655c1
SL
349 unsafe {
350 llvm::LLVMDeleteBasicBlock(mircx.blocks[bb]);
351 }
54a0048b
SL
352 }
353 }
92a42be0
SL
354}
355
356/// Produce, for each argument, a `ValueRef` pointing at the
357/// argument's value. As arguments are lvalues, these are always
358/// indirect.
32a655c1
SL
359fn arg_local_refs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
360 mircx: &MirContext<'a, 'tcx>,
361 scopes: &IndexVec<mir::VisibilityScope, debuginfo::MirDebugScope>,
362 lvalue_locals: &BitVector)
363 -> Vec<LocalRef<'tcx>> {
364 let mir = mircx.mir;
92a42be0 365 let tcx = bcx.tcx();
54a0048b 366 let mut idx = 0;
32a655c1 367 let mut llarg_idx = mircx.fn_ty.ret.is_indirect() as usize;
a7813a04 368
3157f602
XL
369 // Get the argument scope, if it exists and if we need it.
370 let arg_scope = scopes[mir::ARGUMENT_VISIBILITY_SCOPE];
9e0c209e
SL
371 let arg_scope = if arg_scope.is_valid() && bcx.sess().opts.debuginfo == FullDebugInfo {
372 Some(arg_scope.scope_metadata)
3157f602
XL
373 } else {
374 None
375 };
a7813a04 376
c30ab7b3
SL
377 mir.args_iter().enumerate().map(|(arg_index, local)| {
378 let arg_decl = &mir.local_decls[local];
32a655c1 379 let arg_ty = mircx.monomorphize(&arg_decl.ty);
c30ab7b3
SL
380
381 if Some(local) == mir.spread_arg {
54a0048b
SL
382 // This argument (e.g. the last argument in the "rust-call" ABI)
383 // is a tuple that was spread at the ABI level and now we have
384 // to reconstruct it into a tuple local variable, from multiple
385 // individual LLVM function arguments.
386
387 let tupled_arg_tys = match arg_ty.sty {
8bb4bdeb 388 ty::TyTuple(ref tys, _) => tys,
54a0048b
SL
389 _ => bug!("spread argument isn't a tuple?!")
390 };
391
32a655c1 392 let lvalue = LvalueRef::alloca(bcx, arg_ty, &format!("arg{}", arg_index));
54a0048b 393 for (i, &tupled_arg_ty) in tupled_arg_tys.iter().enumerate() {
32a655c1
SL
394 let dst = bcx.struct_gep(lvalue.llval, i);
395 let arg = &mircx.fn_ty.args[idx];
a7813a04 396 idx += 1;
32a655c1 397 if common::type_is_fat_ptr(bcx.ccx, tupled_arg_ty) {
3157f602
XL
398 // We pass fat pointers as two words, but inside the tuple
399 // they are the two sub-fields of a single aggregate field.
32a655c1 400 let meta = &mircx.fn_ty.args[idx];
54a0048b 401 idx += 1;
32a655c1
SL
402 arg.store_fn_arg(bcx, &mut llarg_idx, base::get_dataptr(bcx, dst));
403 meta.store_fn_arg(bcx, &mut llarg_idx, base::get_meta(bcx, dst));
54a0048b
SL
404 } else {
405 arg.store_fn_arg(bcx, &mut llarg_idx, dst);
406 }
407 }
1bb2cb6e
SL
408
409 // Now that we have one alloca that contains the aggregate value,
410 // we can create one debuginfo entry for the argument.
32a655c1 411 arg_scope.map(|scope| {
1bb2cb6e 412 let variable_access = VariableAccess::DirectVariable {
32a655c1 413 alloca: lvalue.llval
1bb2cb6e 414 };
32a655c1
SL
415 declare_local(
416 bcx,
417 &mircx.debug_context,
418 arg_decl.name.unwrap_or(keywords::Invalid.name()),
419 arg_ty, scope,
420 variable_access,
421 VariableKind::ArgumentVariable(arg_index + 1),
422 DUMMY_SP
423 );
424 });
1bb2cb6e 425
32a655c1 426 return LocalRef::Lvalue(lvalue);
54a0048b
SL
427 }
428
32a655c1 429 let arg = &mircx.fn_ty.args[idx];
54a0048b 430 idx += 1;
a7813a04 431 let llval = if arg.is_indirect() && bcx.sess().opts.debuginfo != FullDebugInfo {
54a0048b
SL
432 // Don't copy an indirect argument to an alloca, the caller
433 // already put it in a temporary alloca and gave it up, unless
434 // we emit extra-debug-info, which requires local allocas :(.
a7813a04 435 // FIXME: lifetimes
3157f602
XL
436 if arg.pad.is_some() {
437 llarg_idx += 1;
438 }
32a655c1 439 let llarg = llvm::get_param(bcx.llfn(), llarg_idx as c_uint);
54a0048b
SL
440 llarg_idx += 1;
441 llarg
3157f602
XL
442 } else if !lvalue_locals.contains(local.index()) &&
443 !arg.is_indirect() && arg.cast.is_none() &&
444 arg_scope.is_none() {
445 if arg.is_ignore() {
32a655c1 446 return LocalRef::new_operand(bcx.ccx, arg_ty);
3157f602
XL
447 }
448
449 // We don't have to cast or keep the argument in the alloca.
450 // FIXME(eddyb): We should figure out how to use llvm.dbg.value instead
451 // of putting everything in allocas just so we can use llvm.dbg.declare.
452 if arg.pad.is_some() {
453 llarg_idx += 1;
454 }
32a655c1 455 let llarg = llvm::get_param(bcx.llfn(), llarg_idx as c_uint);
3157f602 456 llarg_idx += 1;
32a655c1
SL
457 let val = if common::type_is_fat_ptr(bcx.ccx, arg_ty) {
458 let meta = &mircx.fn_ty.args[idx];
3157f602
XL
459 idx += 1;
460 assert_eq!((meta.cast, meta.pad), (None, None));
32a655c1 461 let llmeta = llvm::get_param(bcx.llfn(), llarg_idx as c_uint);
3157f602
XL
462 llarg_idx += 1;
463 OperandValue::Pair(llarg, llmeta)
464 } else {
465 OperandValue::Immediate(llarg)
466 };
467 let operand = OperandRef {
468 val: val,
469 ty: arg_ty
470 };
471 return LocalRef::Operand(Some(operand.unpack_if_pair(bcx)));
54a0048b 472 } else {
32a655c1
SL
473 let lltemp = LvalueRef::alloca(bcx, arg_ty, &format!("arg{}", arg_index));
474 if common::type_is_fat_ptr(bcx.ccx, arg_ty) {
54a0048b
SL
475 // we pass fat pointers as two words, but we want to
476 // represent them internally as a pointer to two words,
477 // so make an alloca to store them in.
32a655c1 478 let meta = &mircx.fn_ty.args[idx];
54a0048b 479 idx += 1;
32a655c1
SL
480 arg.store_fn_arg(bcx, &mut llarg_idx, base::get_dataptr(bcx, lltemp.llval));
481 meta.store_fn_arg(bcx, &mut llarg_idx, base::get_meta(bcx, lltemp.llval));
54a0048b
SL
482 } else {
483 // otherwise, arg is passed by value, so make a
484 // temporary and store it there
32a655c1 485 arg.store_fn_arg(bcx, &mut llarg_idx, lltemp.llval);
54a0048b 486 }
32a655c1 487 lltemp.llval
54a0048b 488 };
32a655c1 489 arg_scope.map(|scope| {
a7813a04
XL
490 // Is this a regular argument?
491 if arg_index > 0 || mir.upvar_decls.is_empty() {
32a655c1
SL
492 declare_local(
493 bcx,
494 &mircx.debug_context,
495 arg_decl.name.unwrap_or(keywords::Invalid.name()),
496 arg_ty,
497 scope,
498 VariableAccess::DirectVariable { alloca: llval },
499 VariableKind::ArgumentVariable(arg_index + 1),
500 DUMMY_SP
501 );
a7813a04
XL
502 return;
503 }
504
505 // Or is it the closure environment?
506 let (closure_ty, env_ref) = if let ty::TyRef(_, mt) = arg_ty.sty {
507 (mt.ty, true)
508 } else {
509 (arg_ty, false)
510 };
476ff2be
SL
511 let upvar_tys = if let ty::TyClosure(def_id, substs) = closure_ty.sty {
512 substs.upvar_tys(def_id, tcx)
a7813a04
XL
513 } else {
514 bug!("upvar_decls with non-closure arg0 type `{}`", closure_ty);
515 };
516
517 // Store the pointer to closure data in an alloca for debuginfo
518 // because that's what the llvm.dbg.declare intrinsic expects.
519
520 // FIXME(eddyb) this shouldn't be necessary but SROA seems to
521 // mishandle DW_OP_plus not preceded by DW_OP_deref, i.e. it
522 // doesn't actually strip the offset when splitting the closure
523 // environment into its components so it ends up out of bounds.
524 let env_ptr = if !env_ref {
32a655c1
SL
525 let alloc = bcx.alloca(common::val_ty(llval), "__debuginfo_env_ptr");
526 bcx.store(llval, alloc, None);
a7813a04
XL
527 alloc
528 } else {
529 llval
530 };
531
32a655c1 532 let layout = bcx.ccx.layout_of(closure_ty);
476ff2be
SL
533 let offsets = match *layout {
534 layout::Univariant { ref variant, .. } => &variant.offsets[..],
535 _ => bug!("Closures are only supposed to be Univariant")
536 };
537
a7813a04 538 for (i, (decl, ty)) in mir.upvar_decls.iter().zip(upvar_tys).enumerate() {
476ff2be
SL
539 let byte_offset_of_var_in_env = offsets[i].bytes();
540
a7813a04 541 let ops = unsafe {
5bcae85e
SL
542 [llvm::LLVMRustDIBuilderCreateOpDeref(),
543 llvm::LLVMRustDIBuilderCreateOpPlus(),
a7813a04 544 byte_offset_of_var_in_env as i64,
5bcae85e 545 llvm::LLVMRustDIBuilderCreateOpDeref()]
a7813a04
XL
546 };
547
548 // The environment and the capture can each be indirect.
549
550 // FIXME(eddyb) see above why we have to keep
551 // a pointer in an alloca for debuginfo atm.
552 let mut ops = if env_ref || true { &ops[..] } else { &ops[1..] };
553
554 let ty = if let (true, &ty::TyRef(_, mt)) = (decl.by_ref, &ty.sty) {
555 mt.ty
556 } else {
557 ops = &ops[..ops.len() - 1];
558 ty
559 };
560
561 let variable_access = VariableAccess::IndirectVariable {
562 alloca: env_ptr,
563 address_operations: &ops
564 };
32a655c1
SL
565 declare_local(
566 bcx,
567 &mircx.debug_context,
568 decl.debug_name,
569 ty,
570 scope,
571 variable_access,
572 VariableKind::CapturedVariable,
573 DUMMY_SP
574 );
a7813a04 575 }
32a655c1
SL
576 });
577 LocalRef::Lvalue(LvalueRef::new_sized(llval, LvalueTy::from_ty(arg_ty),
578 Alignment::AbiAligned))
54a0048b 579 }).collect()
92a42be0
SL
580}
581
582mod analyze;
583mod block;
584mod constant;
32a655c1 585pub mod lvalue;
92a42be0 586mod operand;
7453a54e 587mod rvalue;
92a42be0 588mod statement;