]> git.lizzy.rs Git - rust.git/blob - src/librustc_codegen_ssa/mir/mod.rs
Rollup merge of #61389 - Zoxc:arena-cleanup, r=eddyb
[rust.git] / src / librustc_codegen_ssa / mir / mod.rs
1 use rustc::ty::{self, Ty, TypeFoldable, UpvarSubsts};
2 use rustc::ty::layout::{TyLayout, HasTyCtxt, FnTypeExt};
3 use rustc::mir::{self, Body};
4 use rustc::session::config::DebugInfo;
5 use rustc_mir::monomorphize::Instance;
6 use rustc_target::abi::call::{FnType, PassMode, IgnoreMode};
7 use rustc_target::abi::{Variants, VariantIdx};
8 use crate::base;
9 use crate::debuginfo::{self, VariableAccess, VariableKind, FunctionDebugContext};
10 use crate::traits::*;
11
12 use syntax_pos::{DUMMY_SP, NO_EXPANSION, BytePos, Span};
13 use syntax::symbol::kw;
14
15 use std::iter;
16
17 use rustc_data_structures::bit_set::BitSet;
18 use rustc_data_structures::indexed_vec::IndexVec;
19
20 use self::analyze::CleanupKind;
21 use self::place::PlaceRef;
22 use rustc::mir::traversal;
23
24 use self::operand::{OperandRef, OperandValue};
25
26 /// Master context for codegenning from MIR.
27 pub struct FunctionCx<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> {
28     instance: Instance<'tcx>,
29
30     mir: &'a mir::Body<'tcx>,
31
32     debug_context: FunctionDebugContext<Bx::DIScope>,
33
34     llfn: Bx::Value,
35
36     cx: &'a Bx::CodegenCx,
37
38     fn_ty: FnType<'tcx, Ty<'tcx>>,
39
40     /// When unwinding is initiated, we have to store this personality
41     /// value somewhere so that we can load it and re-use it in the
42     /// resume instruction. The personality is (afaik) some kind of
43     /// value used for C++ unwinding, which must filter by type: we
44     /// don't really care about it very much. Anyway, this value
45     /// contains an alloca into which the personality is stored and
46     /// then later loaded when generating the DIVERGE_BLOCK.
47     personality_slot: Option<PlaceRef<'tcx, Bx::Value,>>,
48
49     /// A `Block` for each MIR `BasicBlock`
50     blocks: IndexVec<mir::BasicBlock, Bx::BasicBlock>,
51
52     /// The funclet status of each basic block
53     cleanup_kinds: IndexVec<mir::BasicBlock, analyze::CleanupKind>,
54
55     /// When targeting MSVC, this stores the cleanup info for each funclet
56     /// BB. This is initialized as we compute the funclets' head block in RPO.
57     funclets: IndexVec<mir::BasicBlock, Option<Bx::Funclet>>,
58
59     /// This stores the landing-pad block for a given BB, computed lazily on GNU
60     /// and eagerly on MSVC.
61     landing_pads: IndexVec<mir::BasicBlock, Option<Bx::BasicBlock>>,
62
63     /// Cached unreachable block
64     unreachable_block: Option<Bx::BasicBlock>,
65
66     /// The location where each MIR arg/var/tmp/ret is stored. This is
67     /// usually an `PlaceRef` representing an alloca, but not always:
68     /// sometimes we can skip the alloca and just store the value
69     /// directly using an `OperandRef`, which makes for tighter LLVM
70     /// IR. The conditions for using an `OperandRef` are as follows:
71     ///
72     /// - the type of the local must be judged "immediate" by `is_llvm_immediate`
73     /// - the operand must never be referenced indirectly
74     ///     - we should not take its address using the `&` operator
75     ///     - nor should it appear in a place path like `tmp.a`
76     /// - the operand must be defined by an rvalue that can generate immediate
77     ///   values
78     ///
79     /// Avoiding allocs can also be important for certain intrinsics,
80     /// notably `expect`.
81     locals: IndexVec<mir::Local, LocalRef<'tcx, Bx::Value>>,
82
83     /// Debug information for MIR scopes.
84     scopes: IndexVec<mir::SourceScope, debuginfo::MirDebugScope<Bx::DIScope>>,
85
86     /// If this function is a C-variadic function, this contains the `PlaceRef` of the
87     /// "spoofed" `VaList`.
88     va_list_ref: Option<PlaceRef<'tcx, Bx::Value>>,
89 }
90
91 impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
92     pub fn monomorphize<T>(&self, value: &T) -> T
93         where T: TypeFoldable<'tcx>
94     {
95         self.cx.tcx().subst_and_normalize_erasing_regions(
96             self.instance.substs,
97             ty::ParamEnv::reveal_all(),
98             value,
99         )
100     }
101
102     pub fn set_debug_loc(
103         &mut self,
104         bx: &mut Bx,
105         source_info: mir::SourceInfo
106     ) {
107         let (scope, span) = self.debug_loc(source_info);
108         bx.set_source_location(&mut self.debug_context, scope, span);
109     }
110
111     pub fn debug_loc(&self, source_info: mir::SourceInfo) -> (Option<Bx::DIScope>, Span) {
112         // Bail out if debug info emission is not enabled.
113         match self.debug_context {
114             FunctionDebugContext::DebugInfoDisabled |
115             FunctionDebugContext::FunctionWithoutDebugInfo => {
116                 return (self.scopes[source_info.scope].scope_metadata, source_info.span);
117             }
118             FunctionDebugContext::RegularContext(_) =>{}
119         }
120
121         // In order to have a good line stepping behavior in debugger, we overwrite debug
122         // locations of macro expansions with that of the outermost expansion site
123         // (unless the crate is being compiled with `-Z debug-macros`).
124         if source_info.span.ctxt() == NO_EXPANSION ||
125            self.cx.sess().opts.debugging_opts.debug_macros {
126             let scope = self.scope_metadata_for_loc(source_info.scope, source_info.span.lo());
127             (scope, source_info.span)
128         } else {
129             // Walk up the macro expansion chain until we reach a non-expanded span.
130             // We also stop at the function body level because no line stepping can occur
131             // at the level above that.
132             let mut span = source_info.span;
133             while span.ctxt() != NO_EXPANSION && span.ctxt() != self.mir.span.ctxt() {
134                 if let Some(info) = span.ctxt().outer_expn_info() {
135                     span = info.call_site;
136                 } else {
137                     break;
138                 }
139             }
140             let scope = self.scope_metadata_for_loc(source_info.scope, span.lo());
141             // Use span of the outermost expansion site, while keeping the original lexical scope.
142             (scope, span)
143         }
144     }
145
146     // DILocations inherit source file name from the parent DIScope.  Due to macro expansions
147     // it may so happen that the current span belongs to a different file than the DIScope
148     // corresponding to span's containing source scope.  If so, we need to create a DIScope
149     // "extension" into that file.
150     fn scope_metadata_for_loc(&self, scope_id: mir::SourceScope, pos: BytePos)
151                               -> Option<Bx::DIScope> {
152         let scope_metadata = self.scopes[scope_id].scope_metadata;
153         if pos < self.scopes[scope_id].file_start_pos ||
154            pos >= self.scopes[scope_id].file_end_pos {
155             let sm = self.cx.sess().source_map();
156             let defining_crate = self.debug_context.get_ref(DUMMY_SP).defining_crate;
157             Some(self.cx.extend_scope_to_file(
158                 scope_metadata.unwrap(),
159                 &sm.lookup_char_pos(pos).file,
160                 defining_crate
161             ))
162         } else {
163             scope_metadata
164         }
165     }
166 }
167
168 enum LocalRef<'tcx, V> {
169     Place(PlaceRef<'tcx, V>),
170     /// `UnsizedPlace(p)`: `p` itself is a thin pointer (indirect place).
171     /// `*p` is the fat pointer that references the actual unsized place.
172     /// Every time it is initialized, we have to reallocate the place
173     /// and update the fat pointer. That's the reason why it is indirect.
174     UnsizedPlace(PlaceRef<'tcx, V>),
175     Operand(Option<OperandRef<'tcx, V>>),
176 }
177
178 impl<'a, 'tcx: 'a, V: CodegenObject> LocalRef<'tcx, V> {
179     fn new_operand<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
180         bx: &mut Bx,
181         layout: TyLayout<'tcx>,
182     ) -> LocalRef<'tcx, V> {
183         if layout.is_zst() {
184             // Zero-size temporaries aren't always initialized, which
185             // doesn't matter because they don't contain data, but
186             // we need something in the operand.
187             LocalRef::Operand(Some(OperandRef::new_zst(bx, layout)))
188         } else {
189             LocalRef::Operand(None)
190         }
191     }
192 }
193
194 ///////////////////////////////////////////////////////////////////////////
195
196 pub fn codegen_mir<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
197     cx: &'a Bx::CodegenCx,
198     llfn: Bx::Value,
199     mir: &'a Body<'tcx>,
200     instance: Instance<'tcx>,
201     sig: ty::FnSig<'tcx>,
202 ) {
203     assert!(!instance.substs.needs_infer());
204
205     let fn_ty = FnType::new(cx, sig, &[]);
206     debug!("fn_ty: {:?}", fn_ty);
207     let mut debug_context =
208         cx.create_function_debug_context(instance, sig, llfn, mir);
209     let mut bx = Bx::new_block(cx, llfn, "start");
210
211     if mir.basic_blocks().iter().any(|bb| bb.is_cleanup) {
212         bx.set_personality_fn(cx.eh_personality());
213     }
214
215     let cleanup_kinds = analyze::cleanup_kinds(&mir);
216     // Allocate a `Block` for every basic block, except
217     // the start block, if nothing loops back to it.
218     let reentrant_start_block = !mir.predecessors_for(mir::START_BLOCK).is_empty();
219     let block_bxs: IndexVec<mir::BasicBlock, Bx::BasicBlock> =
220         mir.basic_blocks().indices().map(|bb| {
221             if bb == mir::START_BLOCK && !reentrant_start_block {
222                 bx.llbb()
223             } else {
224                 bx.build_sibling_block(&format!("{:?}", bb)).llbb()
225             }
226         }).collect();
227
228     // Compute debuginfo scopes from MIR scopes.
229     let scopes = cx.create_mir_scopes(mir, &mut debug_context);
230     let (landing_pads, funclets) = create_funclets(mir, &mut bx, &cleanup_kinds, &block_bxs);
231
232     let mut fx = FunctionCx {
233         instance,
234         mir,
235         llfn,
236         fn_ty,
237         cx,
238         personality_slot: None,
239         blocks: block_bxs,
240         unreachable_block: None,
241         cleanup_kinds,
242         landing_pads,
243         funclets,
244         scopes,
245         locals: IndexVec::new(),
246         debug_context,
247         va_list_ref: None,
248     };
249
250     let memory_locals = analyze::non_ssa_locals(&fx);
251
252     // Allocate variable and temp allocas
253     fx.locals = {
254         // FIXME(dlrobertson): This is ugly. Find a better way of getting the `PlaceRef` or
255         // `LocalRef` from `arg_local_refs`
256         let mut va_list_ref = None;
257         let args = arg_local_refs(&mut bx, &fx, &memory_locals, &mut va_list_ref);
258         fx.va_list_ref = va_list_ref;
259
260         let mut allocate_local = |local| {
261             let decl = &mir.local_decls[local];
262             let layout = bx.layout_of(fx.monomorphize(&decl.ty));
263             assert!(!layout.ty.has_erasable_regions());
264
265             if let Some(name) = decl.name {
266                 // User variable
267                 let debug_scope = fx.scopes[decl.visibility_scope];
268                 let dbg = debug_scope.is_valid() &&
269                     bx.sess().opts.debuginfo == DebugInfo::Full;
270
271                 if !memory_locals.contains(local) && !dbg {
272                     debug!("alloc: {:?} ({}) -> operand", local, name);
273                     return LocalRef::new_operand(&mut bx, layout);
274                 }
275
276                 debug!("alloc: {:?} ({}) -> place", local, name);
277                 if layout.is_unsized() {
278                     let indirect_place =
279                         PlaceRef::alloca_unsized_indirect(&mut bx, layout, &name.as_str());
280                     // FIXME: add an appropriate debuginfo
281                     LocalRef::UnsizedPlace(indirect_place)
282                 } else {
283                     let place = PlaceRef::alloca(&mut bx, layout, &name.as_str());
284                     if dbg {
285                         let (scope, span) = fx.debug_loc(mir::SourceInfo {
286                             span: decl.source_info.span,
287                             scope: decl.visibility_scope,
288                         });
289                         bx.declare_local(&fx.debug_context, name, layout.ty, scope.unwrap(),
290                             VariableAccess::DirectVariable { alloca: place.llval },
291                             VariableKind::LocalVariable, span);
292                     }
293                     LocalRef::Place(place)
294                 }
295             } else {
296                 // Temporary or return place
297                 if local == mir::RETURN_PLACE && fx.fn_ty.ret.is_indirect() {
298                     debug!("alloc: {:?} (return place) -> place", local);
299                     let llretptr = bx.get_param(0);
300                     LocalRef::Place(PlaceRef::new_sized(llretptr, layout, layout.align.abi))
301                 } else if memory_locals.contains(local) {
302                     debug!("alloc: {:?} -> place", local);
303                     if layout.is_unsized() {
304                         let indirect_place = PlaceRef::alloca_unsized_indirect(
305                             &mut bx,
306                             layout,
307                             &format!("{:?}", local),
308                         );
309                         LocalRef::UnsizedPlace(indirect_place)
310                     } else {
311                         LocalRef::Place(PlaceRef::alloca(&mut bx, layout, &format!("{:?}", local)))
312                     }
313                 } else {
314                     // If this is an immediate local, we do not create an
315                     // alloca in advance. Instead we wait until we see the
316                     // definition and update the operand there.
317                     debug!("alloc: {:?} -> operand", local);
318                     LocalRef::new_operand(&mut bx, layout)
319                 }
320             }
321         };
322
323         let retptr = allocate_local(mir::RETURN_PLACE);
324         iter::once(retptr)
325             .chain(args.into_iter())
326             .chain(mir.vars_and_temps_iter().map(allocate_local))
327             .collect()
328     };
329
330     // Branch to the START block, if it's not the entry block.
331     if reentrant_start_block {
332         bx.br(fx.blocks[mir::START_BLOCK]);
333     }
334
335     // Up until here, IR instructions for this function have explicitly not been annotated with
336     // source code location, so we don't step into call setup code. From here on, source location
337     // emitting should be enabled.
338     debuginfo::start_emitting_source_locations(&mut fx.debug_context);
339
340     let rpo = traversal::reverse_postorder(&mir);
341     let mut visited = BitSet::new_empty(mir.basic_blocks().len());
342
343     // Codegen the body of each block using reverse postorder
344     for (bb, _) in rpo {
345         visited.insert(bb.index());
346         fx.codegen_block(bb);
347     }
348
349     // Remove blocks that haven't been visited, or have no
350     // predecessors.
351     for bb in mir.basic_blocks().indices() {
352         // Unreachable block
353         if !visited.contains(bb.index()) {
354             debug!("codegen_mir: block {:?} was not visited", bb);
355             unsafe {
356                 bx.delete_basic_block(fx.blocks[bb]);
357             }
358         }
359     }
360 }
361
362 fn create_funclets<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
363     mir: &'a Body<'tcx>,
364     bx: &mut Bx,
365     cleanup_kinds: &IndexVec<mir::BasicBlock, CleanupKind>,
366     block_bxs: &IndexVec<mir::BasicBlock, Bx::BasicBlock>)
367     -> (IndexVec<mir::BasicBlock, Option<Bx::BasicBlock>>,
368         IndexVec<mir::BasicBlock, Option<Bx::Funclet>>)
369 {
370     block_bxs.iter_enumerated().zip(cleanup_kinds).map(|((bb, &llbb), cleanup_kind)| {
371         match *cleanup_kind {
372             CleanupKind::Funclet if base::wants_msvc_seh(bx.sess()) => {}
373             _ => return (None, None)
374         }
375
376         let funclet;
377         let ret_llbb;
378         match mir[bb].terminator.as_ref().map(|t| &t.kind) {
379             // This is a basic block that we're aborting the program for,
380             // notably in an `extern` function. These basic blocks are inserted
381             // so that we assert that `extern` functions do indeed not panic,
382             // and if they do we abort the process.
383             //
384             // On MSVC these are tricky though (where we're doing funclets). If
385             // we were to do a cleanuppad (like below) the normal functions like
386             // `longjmp` would trigger the abort logic, terminating the
387             // program. Instead we insert the equivalent of `catch(...)` for C++
388             // which magically doesn't trigger when `longjmp` files over this
389             // frame.
390             //
391             // Lots more discussion can be found on #48251 but this codegen is
392             // modeled after clang's for:
393             //
394             //      try {
395             //          foo();
396             //      } catch (...) {
397             //          bar();
398             //      }
399             Some(&mir::TerminatorKind::Abort) => {
400                 let mut cs_bx = bx.build_sibling_block(&format!("cs_funclet{:?}", bb));
401                 let mut cp_bx = bx.build_sibling_block(&format!("cp_funclet{:?}", bb));
402                 ret_llbb = cs_bx.llbb();
403
404                 let cs = cs_bx.catch_switch(None, None, 1);
405                 cs_bx.add_handler(cs, cp_bx.llbb());
406
407                 // The "null" here is actually a RTTI type descriptor for the
408                 // C++ personality function, but `catch (...)` has no type so
409                 // it's null. The 64 here is actually a bitfield which
410                 // represents that this is a catch-all block.
411                 let null = bx.const_null(bx.type_i8p());
412                 let sixty_four = bx.const_i32(64);
413                 funclet = cp_bx.catch_pad(cs, &[null, sixty_four, null]);
414                 cp_bx.br(llbb);
415             }
416             _ => {
417                 let mut cleanup_bx = bx.build_sibling_block(&format!("funclet_{:?}", bb));
418                 ret_llbb = cleanup_bx.llbb();
419                 funclet = cleanup_bx.cleanup_pad(None, &[]);
420                 cleanup_bx.br(llbb);
421             }
422         };
423
424         (Some(ret_llbb), Some(funclet))
425     }).unzip()
426 }
427
428 /// Produces, for each argument, a `Value` pointing at the
429 /// argument's value. As arguments are places, these are always
430 /// indirect.
431 fn arg_local_refs<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
432     bx: &mut Bx,
433     fx: &FunctionCx<'a, 'tcx, Bx>,
434     memory_locals: &BitSet<mir::Local>,
435     va_list_ref: &mut Option<PlaceRef<'tcx, Bx::Value>>,
436 ) -> Vec<LocalRef<'tcx, Bx::Value>> {
437     let mir = fx.mir;
438     let tcx = fx.cx.tcx();
439     let mut idx = 0;
440     let mut llarg_idx = fx.fn_ty.ret.is_indirect() as usize;
441
442     // Get the argument scope, if it exists and if we need it.
443     let arg_scope = fx.scopes[mir::OUTERMOST_SOURCE_SCOPE];
444     let arg_scope = if bx.sess().opts.debuginfo == DebugInfo::Full {
445         arg_scope.scope_metadata
446     } else {
447         None
448     };
449
450     // Store the index of the last argument. This is used to
451     // call va_start on the va_list instead of attempting
452     // to store_fn_arg.
453     let last_arg_idx = if fx.fn_ty.args.is_empty() {
454         None
455     } else {
456         Some(fx.fn_ty.args.len() - 1)
457     };
458
459     mir.args_iter().enumerate().map(|(arg_index, local)| {
460         let arg_decl = &mir.local_decls[local];
461
462         let name = if let Some(name) = arg_decl.name {
463             name.as_str().to_string()
464         } else {
465             format!("arg{}", arg_index)
466         };
467
468         if Some(local) == mir.spread_arg {
469             // This argument (e.g., the last argument in the "rust-call" ABI)
470             // is a tuple that was spread at the ABI level and now we have
471             // to reconstruct it into a tuple local variable, from multiple
472             // individual LLVM function arguments.
473
474             let arg_ty = fx.monomorphize(&arg_decl.ty);
475             let tupled_arg_tys = match arg_ty.sty {
476                 ty::Tuple(ref tys) => tys,
477                 _ => bug!("spread argument isn't a tuple?!")
478             };
479
480             let place = PlaceRef::alloca(bx, bx.layout_of(arg_ty), &name);
481             for i in 0..tupled_arg_tys.len() {
482                 let arg = &fx.fn_ty.args[idx];
483                 idx += 1;
484                 if arg.pad.is_some() {
485                     llarg_idx += 1;
486                 }
487                 let pr_field = place.project_field(bx, i);
488                 bx.store_fn_arg(arg, &mut llarg_idx, pr_field);
489             }
490
491             // Now that we have one alloca that contains the aggregate value,
492             // we can create one debuginfo entry for the argument.
493             arg_scope.map(|scope| {
494                 let variable_access = VariableAccess::DirectVariable {
495                     alloca: place.llval
496                 };
497                 bx.declare_local(
498                     &fx.debug_context,
499                     arg_decl.name.unwrap_or(kw::Invalid),
500                     arg_ty, scope,
501                     variable_access,
502                     VariableKind::ArgumentVariable(arg_index + 1),
503                     DUMMY_SP
504                 );
505             });
506
507             return LocalRef::Place(place);
508         }
509
510         let arg = &fx.fn_ty.args[idx];
511         idx += 1;
512         if arg.pad.is_some() {
513             llarg_idx += 1;
514         }
515
516         if arg_scope.is_none() && !memory_locals.contains(local) {
517             // We don't have to cast or keep the argument in the alloca.
518             // FIXME(eddyb): We should figure out how to use llvm.dbg.value instead
519             // of putting everything in allocas just so we can use llvm.dbg.declare.
520             let local = |op| LocalRef::Operand(Some(op));
521             match arg.mode {
522                 PassMode::Ignore(IgnoreMode::Zst) => {
523                     return local(OperandRef::new_zst(bx, arg.layout));
524                 }
525                 PassMode::Ignore(IgnoreMode::CVarArgs) => {}
526                 PassMode::Direct(_) => {
527                     let llarg = bx.get_param(llarg_idx);
528                     bx.set_value_name(llarg, &name);
529                     llarg_idx += 1;
530                     return local(
531                         OperandRef::from_immediate_or_packed_pair(bx, llarg, arg.layout));
532                 }
533                 PassMode::Pair(..) => {
534                     let a = bx.get_param(llarg_idx);
535                     bx.set_value_name(a, &(name.clone() + ".0"));
536                     llarg_idx += 1;
537
538                     let b = bx.get_param(llarg_idx);
539                     bx.set_value_name(b, &(name + ".1"));
540                     llarg_idx += 1;
541
542                     return local(OperandRef {
543                         val: OperandValue::Pair(a, b),
544                         layout: arg.layout
545                     });
546                 }
547                 _ => {}
548             }
549         }
550
551         let place = if arg.is_sized_indirect() {
552             // Don't copy an indirect argument to an alloca, the caller
553             // already put it in a temporary alloca and gave it up.
554             // FIXME: lifetimes
555             let llarg = bx.get_param(llarg_idx);
556             bx.set_value_name(llarg, &name);
557             llarg_idx += 1;
558             PlaceRef::new_sized(llarg, arg.layout, arg.layout.align.abi)
559         } else if arg.is_unsized_indirect() {
560             // As the storage for the indirect argument lives during
561             // the whole function call, we just copy the fat pointer.
562             let llarg = bx.get_param(llarg_idx);
563             llarg_idx += 1;
564             let llextra = bx.get_param(llarg_idx);
565             llarg_idx += 1;
566             let indirect_operand = OperandValue::Pair(llarg, llextra);
567
568             let tmp = PlaceRef::alloca_unsized_indirect(bx, arg.layout, &name);
569             indirect_operand.store(bx, tmp);
570             tmp
571         } else {
572             if fx.fn_ty.c_variadic && last_arg_idx.map(|idx| arg_index == idx).unwrap_or(false) {
573                 let va_list_impl = match arg_decl.ty.ty_adt_def() {
574                     Some(adt) => adt.non_enum_variant(),
575                     None => bug!("`va_list` language item improperly constructed")
576                 };
577                 match tcx.type_of(va_list_impl.fields[0].did).sty {
578                     ty::Ref(_, ty, _) => {
579                         // If the underlying structure the `VaList` contains is a structure,
580                         // we need to allocate it (e.g., X86_64 on Linux).
581                         let tmp = PlaceRef::alloca(bx, arg.layout, &name);
582                         if let ty::Adt(..) = ty.sty {
583                             let layout = bx.layout_of(ty);
584                             // Create an unnamed allocation for the backing structure
585                             // and store it in the the spoofed `VaList`.
586                             let backing = PlaceRef::alloca(bx, layout, "");
587                             bx.store(backing.llval, tmp.llval, layout.align.abi);
588                         }
589                         // Call `va_start` on the spoofed `VaList`.
590                         bx.va_start(tmp.llval);
591                         *va_list_ref = Some(tmp);
592                         tmp
593                     }
594                     _ => bug!("improperly constructed `va_list` lang item"),
595                 }
596             } else {
597                 let tmp = PlaceRef::alloca(bx, arg.layout, &name);
598                 bx.store_fn_arg(arg, &mut llarg_idx, tmp);
599                 tmp
600             }
601         };
602         let upvar_debuginfo = &mir.__upvar_debuginfo_codegen_only_do_not_use;
603         arg_scope.map(|scope| {
604             // Is this a regular argument?
605             if arg_index > 0 || upvar_debuginfo.is_empty() {
606                 // The Rust ABI passes indirect variables using a pointer and a manual copy, so we
607                 // need to insert a deref here, but the C ABI uses a pointer and a copy using the
608                 // byval attribute, for which LLVM always does the deref itself,
609                 // so we must not add it.
610                 let variable_access = VariableAccess::DirectVariable {
611                     alloca: place.llval
612                 };
613
614                 bx.declare_local(
615                     &fx.debug_context,
616                     arg_decl.name.unwrap_or(kw::Invalid),
617                     arg.layout.ty,
618                     scope,
619                     variable_access,
620                     VariableKind::ArgumentVariable(arg_index + 1),
621                     DUMMY_SP
622                 );
623                 return;
624             }
625
626             let pin_did = tcx.lang_items().pin_type();
627             // Or is it the closure environment?
628             let (closure_layout, env_ref) = match arg.layout.ty.sty {
629                 ty::RawPtr(ty::TypeAndMut { ty, .. }) |
630                 ty::Ref(_, ty, _)  => (bx.layout_of(ty), true),
631                 ty::Adt(def, substs) if Some(def.did) == pin_did => {
632                     match substs.type_at(0).sty {
633                         ty::Ref(_, ty, _)  => (bx.layout_of(ty), true),
634                         _ => (arg.layout, false),
635                     }
636                 }
637                 _ => (arg.layout, false)
638             };
639
640             let (def_id, upvar_substs) = match closure_layout.ty.sty {
641                 ty::Closure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs)),
642                 ty::Generator(def_id, substs, _) => (def_id, UpvarSubsts::Generator(substs)),
643                 _ => bug!("upvar debuginfo with non-closure arg0 type `{}`", closure_layout.ty)
644             };
645             let upvar_tys = upvar_substs.upvar_tys(def_id, tcx);
646
647             let extra_locals = {
648                 let upvars = upvar_debuginfo
649                     .iter()
650                     .zip(upvar_tys)
651                     .enumerate()
652                     .map(|(i, (upvar, ty))| {
653                         (None, i, upvar.debug_name, upvar.by_ref, ty, scope, DUMMY_SP)
654                     });
655
656                 let generator_fields = mir.generator_layout.as_ref().map(|generator_layout| {
657                     let (def_id, gen_substs) = match closure_layout.ty.sty {
658                         ty::Generator(def_id, substs, _) => (def_id, substs),
659                         _ => bug!("generator layout without generator substs"),
660                     };
661                     let state_tys = gen_substs.state_tys(def_id, tcx);
662
663                     generator_layout.variant_fields.iter()
664                         .zip(state_tys)
665                         .enumerate()
666                         .flat_map(move |(variant_idx, (fields, tys))| {
667                             let variant_idx = Some(VariantIdx::from(variant_idx));
668                             fields.iter()
669                                 .zip(tys)
670                                 .enumerate()
671                                 .filter_map(move |(i, (field, ty))| {
672                                     let decl = &generator_layout.
673                                         __local_debuginfo_codegen_only_do_not_use[*field];
674                                     if let Some(name) = decl.name {
675                                         let ty = fx.monomorphize(&ty);
676                                         let (var_scope, var_span) = fx.debug_loc(mir::SourceInfo {
677                                             span: decl.source_info.span,
678                                             scope: decl.visibility_scope,
679                                         });
680                                         let var_scope = var_scope.unwrap_or(scope);
681                                         Some((variant_idx, i, name, false, ty, var_scope, var_span))
682                                     } else {
683                                         None
684                                     }
685                             })
686                         })
687                 }).into_iter().flatten();
688
689                 upvars.chain(generator_fields)
690             };
691
692             for (variant_idx, field, name, by_ref, ty, var_scope, var_span) in extra_locals {
693                 let fields = match variant_idx {
694                     Some(variant_idx) => {
695                         match &closure_layout.variants {
696                             Variants::Multiple { variants, .. } => {
697                                 &variants[variant_idx].fields
698                             },
699                             _ => bug!("variant index on univariant layout"),
700                         }
701                     }
702                     None => &closure_layout.fields,
703                 };
704                 let byte_offset_of_var_in_env = fields.offset(field).bytes();
705
706                 let ops = bx.debuginfo_upvar_ops_sequence(byte_offset_of_var_in_env);
707
708                 // The environment and the capture can each be indirect.
709                 let mut ops = if env_ref { &ops[..] } else { &ops[1..] };
710
711                 let ty = if let (true, &ty::Ref(_, ty, _)) = (by_ref, &ty.sty) {
712                     ty
713                 } else {
714                     ops = &ops[..ops.len() - 1];
715                     ty
716                 };
717
718                 let variable_access = VariableAccess::IndirectVariable {
719                     alloca: place.llval,
720                     address_operations: &ops
721                 };
722                 bx.declare_local(
723                     &fx.debug_context,
724                     name,
725                     ty,
726                     var_scope,
727                     variable_access,
728                     VariableKind::LocalVariable,
729                     var_span
730                 );
731             }
732         });
733         if arg.is_unsized_indirect() {
734             LocalRef::UnsizedPlace(place)
735         } else {
736             LocalRef::Place(place)
737         }
738     }).collect()
739 }
740
741 mod analyze;
742 mod block;
743 pub mod constant;
744 pub mod place;
745 pub mod operand;
746 mod rvalue;
747 mod statement;