]>
Commit | Line | Data |
---|---|---|
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 | ||
11 | use libc::c_uint; | |
32a655c1 SL |
12 | use llvm::{self, ValueRef, BasicBlockRef}; |
13 | use llvm::debuginfo::DIScope; | |
476ff2be | 14 | use rustc::ty::{self, layout}; |
32a655c1 | 15 | use rustc::mir::{self, Mir}; |
92a42be0 | 16 | use rustc::mir::tcx::LvalueTy; |
32a655c1 SL |
17 | use rustc::ty::subst::Substs; |
18 | use rustc::infer::TransNormalize; | |
19 | use rustc::ty::TypeFoldable; | |
a7813a04 | 20 | use session::config::FullDebugInfo; |
54a0048b | 21 | use base; |
32a655c1 SL |
22 | use builder::Builder; |
23 | use common::{self, CrateContext, C_null, Funclet}; | |
24 | use debuginfo::{self, declare_local, VariableAccess, VariableKind, FunctionDebugContext}; | |
25 | use monomorphize::{self, Instance}; | |
26 | use abi::FnType; | |
a7813a04 XL |
27 | use type_of; |
28 | ||
32a655c1 | 29 | use syntax_pos::{DUMMY_SP, NO_EXPANSION, COMMAND_LINE_EXPN, BytePos, Span}; |
476ff2be | 30 | use syntax::symbol::keywords; |
54a0048b | 31 | |
5bcae85e | 32 | use std::iter; |
54a0048b | 33 | |
54a0048b | 34 | use rustc_data_structures::bitvec::BitVector; |
3157f602 | 35 | use rustc_data_structures::indexed_vec::{IndexVec, Idx}; |
54a0048b | 36 | |
a7813a04 XL |
37 | pub use self::constant::trans_static_initializer; |
38 | ||
32a655c1 SL |
39 | use self::analyze::CleanupKind; |
40 | use self::lvalue::{Alignment, LvalueRef}; | |
3157f602 | 41 | use rustc::mir::traversal; |
92a42be0 | 42 | |
a7813a04 | 43 | use self::operand::{OperandRef, OperandValue}; |
92a42be0 | 44 | |
92a42be0 | 45 | /// Master context for translating MIR. |
32a655c1 SL |
46 | pub 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 |
103 | impl<'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 | 172 | enum LocalRef<'tcx> { |
92a42be0 SL |
173 | Lvalue(LvalueRef<'tcx>), |
174 | Operand(Option<OperandRef<'tcx>>), | |
175 | } | |
176 | ||
3157f602 | 177 | impl<'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 |
204 | pub 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 |
359 | fn 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 | ||
582 | mod analyze; | |
583 | mod block; | |
584 | mod constant; | |
32a655c1 | 585 | pub mod lvalue; |
92a42be0 | 586 | mod operand; |
7453a54e | 587 | mod rvalue; |
92a42be0 | 588 | mod statement; |