mod.rs 23.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use libc::c_uint;
M
Mark-Simulacrum 已提交
12
use llvm::{self, ValueRef, BasicBlockRef};
M
Mark-Simulacrum 已提交
13
use llvm::debuginfo::DIScope;
14
use rustc::ty::{self, TypeFoldable};
15
use rustc::ty::layout::{LayoutOf, TyLayout};
M
Mark-Simulacrum 已提交
16
use rustc::mir::{self, Mir};
17 18
use rustc::ty::subst::Substs;
use rustc::infer::TransNormalize;
19
use rustc::session::config::FullDebugInfo;
20
use base;
21
use builder::Builder;
22
use common::{CrateContext, Funclet};
M
Mark-Simulacrum 已提交
23
use debuginfo::{self, declare_local, VariableAccess, VariableKind, FunctionDebugContext};
24
use monomorphize::Instance;
25
use abi::{ArgAttribute, FnType, PassMode};
26

27
use syntax_pos::{DUMMY_SP, NO_EXPANSION, BytePos, Span};
28
use syntax::symbol::keywords;
29

30
use std::iter;
31

32
use rustc_data_structures::bitvec::BitVector;
33
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
34

35 36
pub use self::constant::trans_static_initializer;

M
Mark Simulacrum 已提交
37
use self::analyze::CleanupKind;
38
use self::lvalue::{Alignment, LvalueRef};
39
use rustc::mir::traversal;
40

41
use self::operand::{OperandRef, OperandValue};
42 43

/// Master context for translating MIR.
M
Mark Simulacrum 已提交
44
pub struct MirContext<'a, 'tcx:'a> {
45
    mir: &'a mir::Mir<'tcx>,
46

47
    debug_context: debuginfo::FunctionDebugContext,
48

M
Mark Simulacrum 已提交
49
    llfn: ValueRef,
50

M
Mark Simulacrum 已提交
51 52
    ccx: &'a CrateContext<'a, 'tcx>,

53
    fn_ty: FnType<'tcx>,
54

55 56 57 58 59 60 61
    /// When unwinding is initiated, we have to store this personality
    /// value somewhere so that we can load it and re-use it in the
    /// resume instruction. The personality is (afaik) some kind of
    /// value used for C++ unwinding, which must filter by type: we
    /// don't really care about it very much. Anyway, this value
    /// contains an alloca into which the personality is stored and
    /// then later loaded when generating the DIVERGE_BLOCK.
62
    personality_slot: Option<LvalueRef<'tcx>>,
63 64

    /// A `Block` for each MIR `BasicBlock`
M
Mark-Simulacrum 已提交
65
    blocks: IndexVec<mir::BasicBlock, BasicBlockRef>,
66

67
    /// The funclet status of each basic block
68
    cleanup_kinds: IndexVec<mir::BasicBlock, analyze::CleanupKind>,
69

70 71 72 73
    /// When targeting MSVC, this stores the cleanup info for each funclet
    /// BB. This is initialized as we compute the funclets' head block in RPO.
    funclets: &'a IndexVec<mir::BasicBlock, Option<Funclet>>,

74 75
    /// This stores the landing-pad block for a given BB, computed lazily on GNU
    /// and eagerly on MSVC.
M
Mark-Simulacrum 已提交
76
    landing_pads: IndexVec<mir::BasicBlock, Option<BasicBlockRef>>,
77

78
    /// Cached unreachable block
M
Mark-Simulacrum 已提交
79
    unreachable_block: Option<BasicBlockRef>,
80

81
    /// The location where each MIR arg/var/tmp/ret is stored. This is
82 83 84 85 86
    /// usually an `LvalueRef` representing an alloca, but not always:
    /// sometimes we can skip the alloca and just store the value
    /// directly using an `OperandRef`, which makes for tighter LLVM
    /// IR. The conditions for using an `OperandRef` are as follows:
    ///
87
    /// - the type of the local must be judged "immediate" by `is_llvm_immediate`
88 89 90 91 92
    /// - the operand must never be referenced indirectly
    ///     - we should not take its address using the `&` operator
    ///     - nor should it appear in an lvalue path like `tmp.a`
    /// - the operand must be defined by an rvalue that can generate immediate
    ///   values
N
Niko Matsakis 已提交
93 94 95
    ///
    /// Avoiding allocs can also be important for certain intrinsics,
    /// notably `expect`.
96
    locals: IndexVec<mir::Local, LocalRef<'tcx>>,
97 98

    /// Debug information for MIR scopes.
99
    scopes: IndexVec<mir::VisibilityScope, debuginfo::MirDebugScope>,
100 101 102

    /// If this function is being monomorphized, this contains the type substitutions used.
    param_substs: &'tcx Substs<'tcx>,
103 104
}

M
Mark Simulacrum 已提交
105
impl<'a, 'tcx> MirContext<'a, 'tcx> {
106
    pub fn monomorphize<T>(&self, value: &T) -> T
107 108 109
        where T: TransNormalize<'tcx>
    {
        self.ccx.tcx().trans_apply_param_substs(self.param_substs, value)
110 111
    }

112
    pub fn set_debug_loc(&mut self, bcx: &Builder, source_info: mir::SourceInfo) {
113 114 115 116
        let (scope, span) = self.debug_loc(source_info);
        debuginfo::set_source_location(&self.debug_context, bcx, scope, span);
    }

M
Mark-Simulacrum 已提交
117
    pub fn debug_loc(&mut self, source_info: mir::SourceInfo) -> (DIScope, Span) {
118
        // Bail out if debug info emission is not enabled.
119
        match self.debug_context {
120 121
            FunctionDebugContext::DebugInfoDisabled |
            FunctionDebugContext::FunctionWithoutDebugInfo => {
M
Mark-Simulacrum 已提交
122
                return (self.scopes[source_info.scope].scope_metadata, source_info.span);
123 124 125 126 127 128 129
            }
            FunctionDebugContext::RegularContext(_) =>{}
        }

        // In order to have a good line stepping behavior in debugger, we overwrite debug
        // locations of macro expansions with that of the outermost expansion site
        // (unless the crate is being compiled with `-Z debug-macros`).
130
        if source_info.span.ctxt() == NO_EXPANSION ||
131
           self.ccx.sess().opts.debugging_opts.debug_macros {
132
            let scope = self.scope_metadata_for_loc(source_info.scope, source_info.span.lo());
133
            (scope, source_info.span)
134 135
        } else {
            // Walk up the macro expansion chain until we reach a non-expanded span.
B
Bastien Orivel 已提交
136
            // We also stop at the function body level because no line stepping can occur
V
Vadim Chugunov 已提交
137
            // at the level above that.
138
            let mut span = source_info.span;
139 140
            while span.ctxt() != NO_EXPANSION && span.ctxt() != self.mir.span.ctxt() {
                if let Some(info) = span.ctxt().outer().expn_info() {
141
                    span = info.call_site;
142 143 144 145
                } else {
                    break;
                }
            }
146
            let scope = self.scope_metadata_for_loc(source_info.scope, span.lo());
147
            // Use span of the outermost expansion site, while keeping the original lexical scope.
148
            (scope, span)
149 150 151 152 153 154 155 156 157 158 159 160
        }
    }

    // DILocations inherit source file name from the parent DIScope.  Due to macro expansions
    // it may so happen that the current span belongs to a different file than the DIScope
    // corresponding to span's containing visibility scope.  If so, we need to create a DIScope
    // "extension" into that file.
    fn scope_metadata_for_loc(&self, scope_id: mir::VisibilityScope, pos: BytePos)
                               -> llvm::debuginfo::DIScope {
        let scope_metadata = self.scopes[scope_id].scope_metadata;
        if pos < self.scopes[scope_id].file_start_pos ||
           pos >= self.scopes[scope_id].file_end_pos {
M
Mark Simulacrum 已提交
161
            let cm = self.ccx.sess().codemap();
162 163 164 165 166
            let defining_crate = self.debug_context.get_ref(DUMMY_SP).defining_crate;
            debuginfo::extend_scope_to_file(self.ccx,
                                            scope_metadata,
                                            &cm.lookup_char_pos(pos).file,
                                            defining_crate)
167 168 169
        } else {
            scope_metadata
        }
170 171 172
    }
}

173
enum LocalRef<'tcx> {
174 175 176 177
    Lvalue(LvalueRef<'tcx>),
    Operand(Option<OperandRef<'tcx>>),
}

178
impl<'a, 'tcx> LocalRef<'tcx> {
179
    fn new_operand(ccx: &CrateContext<'a, 'tcx>, layout: TyLayout<'tcx>) -> LocalRef<'tcx> {
180
        if layout.is_zst() {
181 182 183
            // Zero-size temporaries aren't always initialized, which
            // doesn't matter because they don't contain data, but
            // we need something in the operand.
184
            LocalRef::Operand(Some(OperandRef::new_zst(ccx, layout)))
185
        } else {
186
            LocalRef::Operand(None)
187
        }
J
James Miller 已提交
188 189 190
    }
}

191 192
///////////////////////////////////////////////////////////////////////////

193
pub fn trans_mir<'a, 'tcx: 'a>(
M
Mark Simulacrum 已提交
194 195
    ccx: &'a CrateContext<'a, 'tcx>,
    llfn: ValueRef,
196 197
    mir: &'a Mir<'tcx>,
    instance: Instance<'tcx>,
198
    sig: ty::FnSig<'tcx>,
199
) {
200
    let fn_ty = FnType::new(ccx, sig, &[]);
201
    debug!("fn_ty: {:?}", fn_ty);
202
    let debug_context =
203
        debuginfo::create_function_debug_context(ccx, instance, sig, llfn, mir);
204
    let bcx = Builder::new_block(ccx, llfn, "start");
205

206 207 208
    if mir.basic_blocks().iter().any(|bb| bb.is_cleanup) {
        bcx.set_personality_fn(ccx.eh_personality());
    }
209

210
    let cleanup_kinds = analyze::cleanup_kinds(&mir);
211 212 213
    // Allocate a `Block` for every basic block, except
    // the start block, if nothing loops back to it.
    let reentrant_start_block = !mir.predecessors_for(mir::START_BLOCK).is_empty();
M
Mark-Simulacrum 已提交
214
    let block_bcxs: IndexVec<mir::BasicBlock, BasicBlockRef> =
215
        mir.basic_blocks().indices().map(|bb| {
216 217
            if bb == mir::START_BLOCK && !reentrant_start_block {
                bcx.llbb()
218
            } else {
219
                bcx.build_sibling_block(&format!("{:?}", bb)).llbb()
220 221 222
            }
        }).collect();

223
    // Compute debuginfo scopes from MIR scopes.
M
Mark Simulacrum 已提交
224
    let scopes = debuginfo::create_mir_scopes(ccx, mir, &debug_context);
225
    let (landing_pads, funclets) = create_funclets(&bcx, &cleanup_kinds, &block_bcxs);
226

227
    let mut mircx = MirContext {
228 229 230 231
        mir,
        llfn,
        fn_ty,
        ccx,
232
        personality_slot: None,
233 234
        blocks: block_bcxs,
        unreachable_block: None,
235 236
        cleanup_kinds,
        landing_pads,
237
        funclets: &funclets,
238
        scopes,
239
        locals: IndexVec::new(),
240
        debug_context,
241 242 243 244
        param_substs: {
            assert!(!instance.substs.needs_infer());
            instance.substs
        },
245 246
    };

247
    let lvalue_locals = analyze::lvalue_locals(&mircx);
248

249
    // Allocate variable and temp allocas
250
    mircx.locals = {
251
        let args = arg_local_refs(&bcx, &mircx, &mircx.scopes, &lvalue_locals);
252 253 254

        let mut allocate_local = |local| {
            let decl = &mir.local_decls[local];
255 256
            let layout = bcx.ccx.layout_of(mircx.monomorphize(&decl.ty));
            assert!(!layout.ty.has_erasable_regions());
257

258 259
            if let Some(name) = decl.name {
                // User variable
260
                let debug_scope = mircx.scopes[decl.source_info.scope];
261
                let dbg = debug_scope.is_valid() && bcx.sess().opts.debuginfo == FullDebugInfo;
262

263 264
                if !lvalue_locals.contains(local.index()) && !dbg {
                    debug!("alloc: {:?} ({}) -> operand", local, name);
265
                    return LocalRef::new_operand(bcx.ccx, layout);
266
                }
267 268

                debug!("alloc: {:?} ({}) -> lvalue", local, name);
269
                let lvalue = LvalueRef::alloca(&bcx, layout, &name.as_str());
270
                if dbg {
271
                    let (scope, span) = mircx.debug_loc(decl.source_info);
272
                    declare_local(&bcx, &mircx.debug_context, name, layout.ty, scope,
M
Mark-Simulacrum 已提交
273 274
                        VariableAccess::DirectVariable { alloca: lvalue.llval },
                        VariableKind::LocalVariable, span);
275 276
                }
                LocalRef::Lvalue(lvalue)
277
            } else {
278
                // Temporary or return pointer
279
                if local == mir::RETURN_POINTER && mircx.fn_ty.ret.is_indirect() {
280
                    debug!("alloc: {:?} (return pointer) -> lvalue", local);
M
Mark Simulacrum 已提交
281
                    let llretptr = llvm::get_param(llfn, 0);
282 283 284
                    LocalRef::Lvalue(LvalueRef::new_sized(llretptr,
                                                          layout,
                                                          Alignment::AbiAligned))
285 286
                } else if lvalue_locals.contains(local.index()) {
                    debug!("alloc: {:?} -> lvalue", local);
287
                    LocalRef::Lvalue(LvalueRef::alloca(&bcx, layout, &format!("{:?}", local)))
288 289 290 291 292
                } else {
                    // If this is an immediate local, we do not create an
                    // alloca in advance. Instead we wait until we see the
                    // definition and update the operand there.
                    debug!("alloc: {:?} -> operand", local);
293
                    LocalRef::new_operand(bcx.ccx, layout)
294
                }
295
            }
296 297 298 299 300
        };

        let retptr = allocate_local(mir::RETURN_POINTER);
        iter::once(retptr)
            .chain(args.into_iter())
301
            .chain(mir.vars_and_temps_iter().map(allocate_local))
302
            .collect()
303
    };
304

305 306 307 308
    // Branch to the START block, if it's not the entry block.
    if reentrant_start_block {
        bcx.br(mircx.blocks[mir::START_BLOCK]);
    }
309

310 311 312
    // Up until here, IR instructions for this function have explicitly not been annotated with
    // source code location, so we don't step into call setup code. From here on, source location
    // emitting should be enabled.
313
    debuginfo::start_emitting_source_locations(&mircx.debug_context);
314

M
Mark Simulacrum 已提交
315 316
    let rpo = traversal::reverse_postorder(&mir);
    let mut visited = BitVector::new(mir.basic_blocks().len());
317

318 319
    // Translate the body of each block using reverse postorder
    for (bb, _) in rpo {
320
        visited.insert(bb.index());
321
        mircx.trans_block(bb);
322
    }
323

324 325
    // Remove blocks that haven't been visited, or have no
    // predecessors.
326
    for bb in mir.basic_blocks().indices() {
327
        // Unreachable block
328
        if !visited.contains(bb.index()) {
329
            debug!("trans_mir: block {:?} was not visited", bb);
330 331 332
            unsafe {
                llvm::LLVMDeleteBasicBlock(mircx.blocks[bb]);
            }
333 334
        }
    }
335 336
}

337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356
fn create_funclets<'a, 'tcx>(
    bcx: &Builder<'a, 'tcx>,
    cleanup_kinds: &IndexVec<mir::BasicBlock, CleanupKind>,
    block_bcxs: &IndexVec<mir::BasicBlock, BasicBlockRef>)
    -> (IndexVec<mir::BasicBlock, Option<BasicBlockRef>>,
        IndexVec<mir::BasicBlock, Option<Funclet>>)
{
    block_bcxs.iter_enumerated().zip(cleanup_kinds).map(|((bb, &llbb), cleanup_kind)| {
        match *cleanup_kind {
            CleanupKind::Funclet if base::wants_msvc_seh(bcx.sess()) => {
                let cleanup_bcx = bcx.build_sibling_block(&format!("funclet_{:?}", bb));
                let cleanup = cleanup_bcx.cleanup_pad(None, &[]);
                cleanup_bcx.br(llbb);
                (Some(cleanup_bcx.llbb()), Some(Funclet::new(cleanup)))
            }
            _ => (None, None)
        }
    }).unzip()
}

357 358 359
/// Produce, for each argument, a `ValueRef` pointing at the
/// argument's value. As arguments are lvalues, these are always
/// indirect.
360
fn arg_local_refs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
361
                            mircx: &MirContext<'a, 'tcx>,
M
Mark Simulacrum 已提交
362 363 364
                            scopes: &IndexVec<mir::VisibilityScope, debuginfo::MirDebugScope>,
                            lvalue_locals: &BitVector)
                            -> Vec<LocalRef<'tcx>> {
365
    let mir = mircx.mir;
366
    let tcx = bcx.tcx();
367
    let mut idx = 0;
368
    let mut llarg_idx = mircx.fn_ty.ret.is_indirect() as usize;
369

370
    // Get the argument scope, if it exists and if we need it.
371
    let arg_scope = scopes[mir::ARGUMENT_VISIBILITY_SCOPE];
372
    let arg_scope = if arg_scope.is_valid() && bcx.sess().opts.debuginfo == FullDebugInfo {
373
        Some(arg_scope.scope_metadata)
374 375 376
    } else {
        None
    };
377

378 379 380 381
    let deref_op = unsafe {
        [llvm::LLVMRustDIBuilderCreateOpDeref()]
    };

382
    mir.args_iter().enumerate().map(|(arg_index, local)| {
383
        let arg_decl = &mir.local_decls[local];
384

385 386 387 388 389 390
        let name = if let Some(name) = arg_decl.name {
            name.as_str().to_string()
        } else {
            format!("arg{}", arg_index)
        };

J
Jonas Schievink 已提交
391 392 393 394 395 396
        if Some(local) == mir.spread_arg {
            // This argument (e.g. the last argument in the "rust-call" ABI)
            // is a tuple that was spread at the ABI level and now we have
            // to reconstruct it into a tuple local variable, from multiple
            // individual LLVM function arguments.

397
            let arg_ty = mircx.monomorphize(&arg_decl.ty);
J
Jonas Schievink 已提交
398
            let tupled_arg_tys = match arg_ty.sty {
A
Andrew Cann 已提交
399
                ty::TyTuple(ref tys, _) => tys,
J
Jonas Schievink 已提交
400 401
                _ => bug!("spread argument isn't a tuple?!")
            };
402

403
            let lvalue = LvalueRef::alloca(bcx, bcx.ccx.layout_of(arg_ty), &name);
404
            for i in 0..tupled_arg_tys.len() {
405
                let arg = &mircx.fn_ty.args[idx];
J
Jonas Schievink 已提交
406
                idx += 1;
407
                arg.store_fn_arg(bcx, &mut llarg_idx, lvalue.project_field(bcx, i));
408
            }
409 410 411

            // Now that we have one alloca that contains the aggregate value,
            // we can create one debuginfo entry for the argument.
412
            arg_scope.map(|scope| {
413
                let variable_access = VariableAccess::DirectVariable {
414
                    alloca: lvalue.llval
415
                };
416 417 418 419 420 421 422 423 424
                declare_local(
                    bcx,
                    &mircx.debug_context,
                    arg_decl.name.unwrap_or(keywords::Invalid.name()),
                    arg_ty, scope,
                    variable_access,
                    VariableKind::ArgumentVariable(arg_index + 1),
                    DUMMY_SP
                );
425
            });
426

427
            return LocalRef::Lvalue(lvalue);
428 429
        }

430
        let arg = &mircx.fn_ty.args[idx];
431
        idx += 1;
432
        if arg.pad.is_some() {
433
            llarg_idx += 1;
434
        }
435

436
        if arg_scope.is_none() && !lvalue_locals.contains(local.index()) {
437 438 439
            // We don't have to cast or keep the argument in the alloca.
            // FIXME(eddyb): We should figure out how to use llvm.dbg.value instead
            // of putting everything in allocas just so we can use llvm.dbg.declare.
440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466
            let local = |op| LocalRef::Operand(Some(op));
            match arg.mode {
                PassMode::Ignore => {
                    return local(OperandRef::new_zst(bcx.ccx, arg.layout));
                }
                PassMode::Direct(_) => {
                    let llarg = llvm::get_param(bcx.llfn(), llarg_idx as c_uint);
                    bcx.set_value_name(llarg, &name);
                    llarg_idx += 1;
                    return local(
                        OperandRef::from_immediate_or_packed_pair(bcx, llarg, arg.layout));
                }
                PassMode::Pair(..) => {
                    let a = llvm::get_param(bcx.llfn(), llarg_idx as c_uint);
                    bcx.set_value_name(a, &(name.clone() + ".0"));
                    llarg_idx += 1;

                    let b = llvm::get_param(bcx.llfn(), llarg_idx as c_uint);
                    bcx.set_value_name(b, &(name + ".1"));
                    llarg_idx += 1;

                    return local(OperandRef {
                        val: OperandValue::Pair(a, b),
                        layout: arg.layout
                    });
                }
                _ => {}
467
            }
468 469 470 471 472 473
        }

        let lvalue = if arg.is_indirect() {
            // Don't copy an indirect argument to an alloca, the caller
            // already put it in a temporary alloca and gave it up.
            // FIXME: lifetimes
474 475 476
            let llarg = llvm::get_param(bcx.llfn(), llarg_idx as c_uint);
            bcx.set_value_name(llarg, &name);
            llarg_idx += 1;
477
            LvalueRef::new_sized(llarg, arg.layout, Alignment::AbiAligned)
478
        } else {
479
            let tmp = LvalueRef::alloca(bcx, arg.layout, &name);
480
            arg.store_fn_arg(bcx, &mut llarg_idx, tmp);
481
            tmp
482
        };
483
        arg_scope.map(|scope| {
484 485
            // Is this a regular argument?
            if arg_index > 0 || mir.upvar_decls.is_empty() {
486 487 488
                // The Rust ABI passes indirect variables using a pointer and a manual copy, so we
                // need to insert a deref here, but the C ABI uses a pointer and a copy using the
                // byval attribute, for which LLVM does the deref itself, so we must not add it.
489 490
                let mut variable_access = VariableAccess::DirectVariable {
                    alloca: lvalue.llval
491 492
                };

493 494 495 496 497 498 499 500 501
                if let PassMode::Indirect(ref attrs) = arg.mode {
                    if !attrs.contains(ArgAttribute::ByVal) {
                        variable_access = VariableAccess::IndirectVariable {
                            alloca: lvalue.llval,
                            address_operations: &deref_op,
                        };
                    }
                }

502 503 504 505
                declare_local(
                    bcx,
                    &mircx.debug_context,
                    arg_decl.name.unwrap_or(keywords::Invalid.name()),
506
                    arg.layout.ty,
507
                    scope,
508
                    variable_access,
509 510 511
                    VariableKind::ArgumentVariable(arg_index + 1),
                    DUMMY_SP
                );
512 513 514 515
                return;
            }

            // Or is it the closure environment?
516 517 518
            let (closure_layout, env_ref) = match arg.layout.ty.sty {
                ty::TyRef(_, mt) | ty::TyRawPtr(mt) => (bcx.ccx.layout_of(mt.ty), true),
                _ => (arg.layout, false)
519
            };
A
Alex Crichton 已提交
520

521
            let upvar_tys = match closure_layout.ty.sty {
J
John Kåre Alsaker 已提交
522 523
                ty::TyClosure(def_id, substs) |
                ty::TyGenerator(def_id, substs, _) => substs.upvar_tys(def_id, tcx),
524
                _ => bug!("upvar_decls with non-closure arg0 type `{}`", closure_layout.ty)
525 526 527 528 529 530 531 532 533 534
            };

            // Store the pointer to closure data in an alloca for debuginfo
            // because that's what the llvm.dbg.declare intrinsic expects.

            // FIXME(eddyb) this shouldn't be necessary but SROA seems to
            // mishandle DW_OP_plus not preceded by DW_OP_deref, i.e. it
            // doesn't actually strip the offset when splitting the closure
            // environment into its components so it ends up out of bounds.
            let env_ptr = if !env_ref {
535 536 537
                let alloc = LvalueRef::alloca(bcx,
                    bcx.ccx.layout_of(tcx.mk_mut_ptr(arg.layout.ty)),
                    "__debuginfo_env_ptr");
538 539
                bcx.store(lvalue.llval, alloc.llval, None);
                alloc.llval
540
            } else {
541
                lvalue.llval
542 543 544
            };

            for (i, (decl, ty)) in mir.upvar_decls.iter().zip(upvar_tys).enumerate() {
545
                let byte_offset_of_var_in_env = closure_layout.fields.offset(i).bytes();
A
Austin Hicks 已提交
546

547
                let ops = unsafe {
548 549
                    [llvm::LLVMRustDIBuilderCreateOpDeref(),
                     llvm::LLVMRustDIBuilderCreateOpPlus(),
550
                     byte_offset_of_var_in_env as i64,
551
                     llvm::LLVMRustDIBuilderCreateOpDeref()]
552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570
                };

                // The environment and the capture can each be indirect.

                // FIXME(eddyb) see above why we have to keep
                // a pointer in an alloca for debuginfo atm.
                let mut ops = if env_ref || true { &ops[..] } else { &ops[1..] };

                let ty = if let (true, &ty::TyRef(_, mt)) = (decl.by_ref, &ty.sty) {
                    mt.ty
                } else {
                    ops = &ops[..ops.len() - 1];
                    ty
                };

                let variable_access = VariableAccess::IndirectVariable {
                    alloca: env_ptr,
                    address_operations: &ops
                };
571 572 573 574 575 576 577 578 579 580
                declare_local(
                    bcx,
                    &mircx.debug_context,
                    decl.debug_name,
                    ty,
                    scope,
                    variable_access,
                    VariableKind::CapturedVariable,
                    DUMMY_SP
                );
581
            }
582
        });
583
        LocalRef::Lvalue(lvalue)
584
    }).collect()
585 586
}

587
mod analyze;
588 589
mod block;
mod constant;
590
pub mod lvalue;
591
pub mod operand;
592
mod rvalue;
593
mod statement;