]>
Commit | Line | Data |
---|---|---|
d9579d0f AL |
1 | // Copyright 2012-2015 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 | // See doc.rs for documentation. | |
12 | mod doc; | |
13 | ||
14 | use self::VariableAccess::*; | |
15 | use self::VariableKind::*; | |
16 | ||
a7813a04 | 17 | use self::utils::{DIB, span_start, create_DIArray, is_node_local_to_unit}; |
ff7c6d11 | 18 | use self::namespace::mangled_name_of_instance; |
d9579d0f | 19 | use self::type_names::compute_debuginfo_type_name; |
5bcae85e | 20 | use self::metadata::{type_metadata, file_metadata, TypeMap}; |
a7813a04 | 21 | use self::source_loc::InternalDebugLocation::{self, UnknownLocation}; |
d9579d0f AL |
22 | |
23 | use llvm; | |
24 | use llvm::{ModuleRef, ContextRef, ValueRef}; | |
476ff2be | 25 | use llvm::debuginfo::{DIFile, DIType, DIScope, DIBuilderRef, DISubprogram, DIArray, DIFlags}; |
7cac9316 | 26 | use rustc::hir::def_id::{DefId, CrateNum}; |
a7813a04 | 27 | use rustc::ty::subst::Substs; |
54a0048b SL |
28 | |
29 | use abi::Abi; | |
ff7c6d11 | 30 | use common::CrateContext; |
32a655c1 | 31 | use builder::Builder; |
8bb4bdeb | 32 | use monomorphize::Instance; |
54a0048b | 33 | use rustc::ty::{self, Ty}; |
c30ab7b3 | 34 | use rustc::mir; |
7cac9316 XL |
35 | use rustc::session::config::{self, FullDebugInfo, LimitedDebugInfo, NoDebugInfo}; |
36 | use rustc::util::nodemap::{DefIdMap, FxHashMap, FxHashSet}; | |
d9579d0f AL |
37 | |
38 | use libc::c_uint; | |
39 | use std::cell::{Cell, RefCell}; | |
40 | use std::ffi::CString; | |
41 | use std::ptr; | |
e9174d1e | 42 | |
3157f602 XL |
43 | use syntax_pos::{self, Span, Pos}; |
44 | use syntax::ast; | |
7cac9316 | 45 | use syntax::symbol::Symbol; |
ff7c6d11 | 46 | use rustc::ty::layout::{self, LayoutOf}; |
d9579d0f AL |
47 | |
48 | pub mod gdb; | |
49 | mod utils; | |
50 | mod namespace; | |
51 | mod type_names; | |
5bcae85e | 52 | pub mod metadata; |
d9579d0f AL |
53 | mod create_scope_map; |
54 | mod source_loc; | |
55 | ||
9e0c209e | 56 | pub use self::create_scope_map::{create_mir_scopes, MirDebugScope}; |
d9579d0f | 57 | pub use self::source_loc::start_emitting_source_locations; |
d9579d0f | 58 | pub use self::metadata::create_global_var_metadata; |
abe05a73 | 59 | pub use self::metadata::create_vtable_metadata; |
9e0c209e | 60 | pub use self::metadata::extend_scope_to_file; |
32a655c1 | 61 | pub use self::source_loc::set_source_location; |
d9579d0f AL |
62 | |
63 | #[allow(non_upper_case_globals)] | |
64 | const DW_TAG_auto_variable: c_uint = 0x100; | |
65 | #[allow(non_upper_case_globals)] | |
66 | const DW_TAG_arg_variable: c_uint = 0x101; | |
67 | ||
68 | /// A context object for maintaining all state needed by the debuginfo module. | |
69 | pub struct CrateDebugContext<'tcx> { | |
70 | llcontext: ContextRef, | |
041b39d2 | 71 | llmod: ModuleRef, |
d9579d0f | 72 | builder: DIBuilderRef, |
7cac9316 | 73 | created_files: RefCell<FxHashMap<(Symbol, Symbol), DIFile>>, |
ff7c6d11 | 74 | created_enum_disr_types: RefCell<FxHashMap<(DefId, layout::Primitive), DIType>>, |
d9579d0f AL |
75 | |
76 | type_map: RefCell<TypeMap<'tcx>>, | |
a7813a04 | 77 | namespace_map: RefCell<DefIdMap<DIScope>>, |
d9579d0f AL |
78 | |
79 | // This collection is used to assert that composite types (structs, enums, | |
80 | // ...) have their members only set once: | |
476ff2be | 81 | composite_types_completed: RefCell<FxHashSet<DIType>>, |
d9579d0f AL |
82 | } |
83 | ||
84 | impl<'tcx> CrateDebugContext<'tcx> { | |
85 | pub fn new(llmod: ModuleRef) -> CrateDebugContext<'tcx> { | |
86 | debug!("CrateDebugContext::new"); | |
5bcae85e | 87 | let builder = unsafe { llvm::LLVMRustDIBuilderCreate(llmod) }; |
d9579d0f AL |
88 | // DIBuilder inherits context from the module, so we'd better use the same one |
89 | let llcontext = unsafe { llvm::LLVMGetModuleContext(llmod) }; | |
32a655c1 | 90 | CrateDebugContext { |
3b2f2976 XL |
91 | llcontext, |
92 | llmod, | |
93 | builder, | |
476ff2be SL |
94 | created_files: RefCell::new(FxHashMap()), |
95 | created_enum_disr_types: RefCell::new(FxHashMap()), | |
d9579d0f | 96 | type_map: RefCell::new(TypeMap::new()), |
a7813a04 | 97 | namespace_map: RefCell::new(DefIdMap()), |
476ff2be | 98 | composite_types_completed: RefCell::new(FxHashSet()), |
32a655c1 | 99 | } |
d9579d0f AL |
100 | } |
101 | } | |
102 | ||
103 | pub enum FunctionDebugContext { | |
32a655c1 | 104 | RegularContext(FunctionDebugContextData), |
d9579d0f AL |
105 | DebugInfoDisabled, |
106 | FunctionWithoutDebugInfo, | |
107 | } | |
108 | ||
109 | impl FunctionDebugContext { | |
7cac9316 | 110 | pub fn get_ref<'a>(&'a self, span: Span) -> &'a FunctionDebugContextData { |
d9579d0f | 111 | match *self { |
32a655c1 | 112 | FunctionDebugContext::RegularContext(ref data) => data, |
d9579d0f | 113 | FunctionDebugContext::DebugInfoDisabled => { |
32a655c1 | 114 | span_bug!(span, "{}", FunctionDebugContext::debuginfo_disabled_message()); |
d9579d0f AL |
115 | } |
116 | FunctionDebugContext::FunctionWithoutDebugInfo => { | |
32a655c1 | 117 | span_bug!(span, "{}", FunctionDebugContext::should_be_ignored_message()); |
d9579d0f AL |
118 | } |
119 | } | |
120 | } | |
121 | ||
122 | fn debuginfo_disabled_message() -> &'static str { | |
123 | "debuginfo: Error trying to access FunctionDebugContext although debug info is disabled!" | |
124 | } | |
125 | ||
126 | fn should_be_ignored_message() -> &'static str { | |
127 | "debuginfo: Error trying to access FunctionDebugContext for function that should be \ | |
128 | ignored by debug info!" | |
129 | } | |
130 | } | |
131 | ||
9cc50fc6 | 132 | pub struct FunctionDebugContextData { |
d9579d0f | 133 | fn_metadata: DISubprogram, |
d9579d0f | 134 | source_locations_enabled: Cell<bool>, |
7cac9316 | 135 | pub defining_crate: CrateNum, |
d9579d0f AL |
136 | } |
137 | ||
138 | pub enum VariableAccess<'a> { | |
139 | // The llptr given is an alloca containing the variable's value | |
140 | DirectVariable { alloca: ValueRef }, | |
141 | // The llptr given is an alloca containing the start of some pointer chain | |
142 | // leading to the variable's content. | |
143 | IndirectVariable { alloca: ValueRef, address_operations: &'a [i64] } | |
144 | } | |
145 | ||
146 | pub enum VariableKind { | |
147 | ArgumentVariable(usize /*index*/), | |
148 | LocalVariable, | |
149 | CapturedVariable, | |
150 | } | |
151 | ||
152 | /// Create any deferred debug metadata nodes | |
153 | pub fn finalize(cx: &CrateContext) { | |
154 | if cx.dbg_cx().is_none() { | |
155 | return; | |
156 | } | |
157 | ||
158 | debug!("finalize"); | |
d9579d0f AL |
159 | |
160 | if gdb::needs_gdb_debug_scripts_section(cx) { | |
161 | // Add a .debug_gdb_scripts section to this compile-unit. This will | |
162 | // cause GDB to try and load the gdb_load_rust_pretty_printers.py file, | |
163 | // which activates the Rust pretty printers for binary this section is | |
164 | // contained in. | |
165 | gdb::get_or_insert_gdb_debug_scripts_section_global(cx); | |
166 | } | |
167 | ||
168 | unsafe { | |
5bcae85e SL |
169 | llvm::LLVMRustDIBuilderFinalize(DIB(cx)); |
170 | llvm::LLVMRustDIBuilderDispose(DIB(cx)); | |
d9579d0f | 171 | // Debuginfo generation in LLVM by default uses a higher |
cc61c64b | 172 | // version of dwarf than macOS currently understands. We can |
d9579d0f | 173 | // instruct LLVM to emit an older version of dwarf, however, |
cc61c64b | 174 | // for macOS to understand. For more info see #11352 |
d9579d0f AL |
175 | // This can be overridden using --llvm-opts -dwarf-version,N. |
176 | // Android has the same issue (#22398) | |
177 | if cx.sess().target.target.options.is_like_osx || | |
178 | cx.sess().target.target.options.is_like_android { | |
179 | llvm::LLVMRustAddModuleFlag(cx.llmod(), | |
180 | "Dwarf Version\0".as_ptr() as *const _, | |
181 | 2) | |
182 | } | |
183 | ||
7453a54e SL |
184 | // Indicate that we want CodeView debug information on MSVC |
185 | if cx.sess().target.target.options.is_like_msvc { | |
186 | llvm::LLVMRustAddModuleFlag(cx.llmod(), | |
187 | "CodeView\0".as_ptr() as *const _, | |
188 | 1) | |
189 | } | |
190 | ||
d9579d0f AL |
191 | // Prevent bitcode readers from deleting the debug info. |
192 | let ptr = "Debug Info Version\0".as_ptr(); | |
193 | llvm::LLVMRustAddModuleFlag(cx.llmod(), ptr as *const _, | |
62682a34 | 194 | llvm::LLVMRustDebugMetadataVersion()); |
d9579d0f AL |
195 | }; |
196 | } | |
197 | ||
198 | /// Creates the function-specific debug context. | |
199 | /// | |
200 | /// Returns the FunctionDebugContext for the function which holds state needed | |
201 | /// for debug info creation. The function may also return another variant of the | |
202 | /// FunctionDebugContext enum which indicates why no debuginfo should be created | |
203 | /// for the function. | |
204 | pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, | |
a7813a04 | 205 | instance: Instance<'tcx>, |
8bb4bdeb | 206 | sig: ty::FnSig<'tcx>, |
9e0c209e SL |
207 | llfn: ValueRef, |
208 | mir: &mir::Mir) -> FunctionDebugContext { | |
d9579d0f AL |
209 | if cx.sess().opts.debuginfo == NoDebugInfo { |
210 | return FunctionDebugContext::DebugInfoDisabled; | |
211 | } | |
212 | ||
cc61c64b | 213 | for attr in instance.def.attrs(cx.tcx()).iter() { |
32a655c1 SL |
214 | if attr.check_name("no_debug") { |
215 | return FunctionDebugContext::FunctionWithoutDebugInfo; | |
216 | } | |
217 | } | |
d9579d0f | 218 | |
9e0c209e SL |
219 | let containing_scope = get_containing_scope(cx, instance); |
220 | let span = mir.span; | |
d9579d0f AL |
221 | |
222 | // This can be the case for functions inlined from another crate | |
3157f602 | 223 | if span == syntax_pos::DUMMY_SP { |
32a655c1 | 224 | // FIXME(simulacrum): Probably can't happen; remove. |
d9579d0f AL |
225 | return FunctionDebugContext::FunctionWithoutDebugInfo; |
226 | } | |
227 | ||
7cac9316 | 228 | let def_id = instance.def_id(); |
d9579d0f | 229 | let loc = span_start(cx, span); |
7cac9316 | 230 | let file_metadata = file_metadata(cx, &loc.file.name, def_id.krate); |
d9579d0f AL |
231 | |
232 | let function_type_metadata = unsafe { | |
8bb4bdeb | 233 | let fn_signature = get_function_signature(cx, sig); |
5bcae85e | 234 | llvm::LLVMRustDIBuilderCreateSubroutineType(DIB(cx), file_metadata, fn_signature) |
d9579d0f AL |
235 | }; |
236 | ||
a7813a04 | 237 | // Find the enclosing function, in case this is a closure. |
7cac9316 | 238 | let def_key = cx.tcx().def_key(def_id); |
a7813a04 | 239 | let mut name = def_key.disambiguated_data.data.to_string(); |
476ff2be | 240 | |
7cac9316 | 241 | let enclosing_fn_def_id = cx.tcx().closure_base_def_id(def_id); |
a7813a04 | 242 | |
d9579d0f AL |
243 | // Get_template_parameters() will append a `<...>` clause to the function |
244 | // name if necessary. | |
7cac9316 | 245 | let generics = cx.tcx().generics_of(enclosing_fn_def_id); |
476ff2be | 246 | let substs = instance.substs.truncate_to(cx.tcx(), generics); |
d9579d0f | 247 | let template_parameters = get_template_parameters(cx, |
a7813a04 | 248 | &generics, |
476ff2be | 249 | substs, |
d9579d0f | 250 | file_metadata, |
a7813a04 XL |
251 | &mut name); |
252 | ||
ff7c6d11 XL |
253 | // Get the linkage_name, which is just the symbol name |
254 | let linkage_name = mangled_name_of_instance(cx, instance); | |
d9579d0f | 255 | |
a7813a04 | 256 | let scope_line = span_start(cx, span).line; |
d9579d0f | 257 | |
cc61c64b | 258 | let local_id = cx.tcx().hir.as_local_node_id(instance.def_id()); |
a7813a04 | 259 | let is_local_to_unit = local_id.map_or(false, |id| is_node_local_to_unit(cx, id)); |
d9579d0f | 260 | |
a7813a04 | 261 | let function_name = CString::new(name).unwrap(); |
ff7c6d11 | 262 | let linkage_name = CString::new(linkage_name.to_string()).unwrap(); |
a7813a04 | 263 | |
8bb4bdeb XL |
264 | let mut flags = DIFlags::FlagPrototyped; |
265 | match *cx.sess().entry_fn.borrow() { | |
266 | Some((id, _)) => { | |
267 | if local_id == Some(id) { | |
268 | flags = flags | DIFlags::FlagMainSubprogram; | |
269 | } | |
270 | } | |
271 | None => {} | |
272 | }; | |
273 | ||
d9579d0f | 274 | let fn_metadata = unsafe { |
5bcae85e | 275 | llvm::LLVMRustDIBuilderCreateFunction( |
d9579d0f AL |
276 | DIB(cx), |
277 | containing_scope, | |
278 | function_name.as_ptr(), | |
279 | linkage_name.as_ptr(), | |
280 | file_metadata, | |
281 | loc.line as c_uint, | |
282 | function_type_metadata, | |
283 | is_local_to_unit, | |
284 | true, | |
285 | scope_line as c_uint, | |
8bb4bdeb | 286 | flags, |
9cc50fc6 | 287 | cx.sess().opts.optimize != config::OptLevel::No, |
d9579d0f AL |
288 | llfn, |
289 | template_parameters, | |
290 | ptr::null_mut()) | |
291 | }; | |
292 | ||
d9579d0f | 293 | // Initialize fn debug context (including scope map and namespace map) |
32a655c1 | 294 | let fn_debug_context = FunctionDebugContextData { |
3b2f2976 | 295 | fn_metadata, |
d9579d0f | 296 | source_locations_enabled: Cell::new(false), |
7cac9316 | 297 | defining_crate: def_id.krate, |
d9579d0f AL |
298 | }; |
299 | ||
d9579d0f AL |
300 | return FunctionDebugContext::RegularContext(fn_debug_context); |
301 | ||
302 | fn get_function_signature<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, | |
8bb4bdeb | 303 | sig: ty::FnSig<'tcx>) -> DIArray { |
d9579d0f AL |
304 | if cx.sess().opts.debuginfo == LimitedDebugInfo { |
305 | return create_DIArray(DIB(cx), &[]); | |
306 | } | |
307 | ||
476ff2be | 308 | let mut signature = Vec::with_capacity(sig.inputs().len() + 1); |
c1a9b12d SL |
309 | |
310 | // Return type -- llvm::DIBuilder wants this at index 0 | |
476ff2be | 311 | signature.push(match sig.output().sty { |
8bb4bdeb | 312 | ty::TyTuple(ref tys, _) if tys.is_empty() => ptr::null_mut(), |
476ff2be | 313 | _ => type_metadata(cx, sig.output(), syntax_pos::DUMMY_SP) |
c1a9b12d SL |
314 | }); |
315 | ||
8bb4bdeb | 316 | let inputs = if sig.abi == Abi::RustCall { |
476ff2be | 317 | &sig.inputs()[..sig.inputs().len() - 1] |
d9579d0f | 318 | } else { |
476ff2be | 319 | sig.inputs() |
c1a9b12d | 320 | }; |
d9579d0f AL |
321 | |
322 | // Arguments types | |
041b39d2 XL |
323 | if cx.sess().target.target.options.is_like_msvc { |
324 | // FIXME(#42800): | |
325 | // There is a bug in MSDIA that leads to a crash when it encounters | |
326 | // a fixed-size array of `u8` or something zero-sized in a | |
327 | // function-type (see #40477). | |
328 | // As a workaround, we replace those fixed-size arrays with a | |
329 | // pointer-type. So a function `fn foo(a: u8, b: [u8; 4])` would | |
330 | // appear as `fn foo(a: u8, b: *const u8)` in debuginfo, | |
331 | // and a function `fn bar(x: [(); 7])` as `fn bar(x: *const ())`. | |
332 | // This transformed type is wrong, but these function types are | |
333 | // already inaccurate due to ABI adjustments (see #42800). | |
334 | signature.extend(inputs.iter().map(|&t| { | |
335 | let t = match t.sty { | |
336 | ty::TyArray(ct, _) | |
ff7c6d11 | 337 | if (ct == cx.tcx().types.u8) || cx.layout_of(ct).is_zst() => { |
041b39d2 XL |
338 | cx.tcx().mk_imm_ptr(ct) |
339 | } | |
340 | _ => t | |
341 | }; | |
342 | type_metadata(cx, t, syntax_pos::DUMMY_SP) | |
343 | })); | |
344 | } else { | |
345 | signature.extend(inputs.iter().map(|t| { | |
346 | type_metadata(cx, t, syntax_pos::DUMMY_SP) | |
347 | })); | |
d9579d0f AL |
348 | } |
349 | ||
8bb4bdeb XL |
350 | if sig.abi == Abi::RustCall && !sig.inputs().is_empty() { |
351 | if let ty::TyTuple(args, _) = sig.inputs()[sig.inputs().len() - 1].sty { | |
54a0048b | 352 | for &argument_type in args { |
3157f602 | 353 | signature.push(type_metadata(cx, argument_type, syntax_pos::DUMMY_SP)); |
54a0048b SL |
354 | } |
355 | } | |
356 | } | |
357 | ||
d9579d0f AL |
358 | return create_DIArray(DIB(cx), &signature[..]); |
359 | } | |
360 | ||
361 | fn get_template_parameters<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, | |
8bb4bdeb | 362 | generics: &ty::Generics, |
9e0c209e | 363 | substs: &Substs<'tcx>, |
d9579d0f AL |
364 | file_metadata: DIFile, |
365 | name_to_append_suffix_to: &mut String) | |
366 | -> DIArray | |
367 | { | |
9e0c209e | 368 | if substs.types().next().is_none() { |
d9579d0f AL |
369 | return create_DIArray(DIB(cx), &[]); |
370 | } | |
371 | ||
372 | name_to_append_suffix_to.push('<'); | |
9e0c209e SL |
373 | for (i, actual_type) in substs.types().enumerate() { |
374 | if i != 0 { | |
375 | name_to_append_suffix_to.push_str(","); | |
376 | } | |
377 | ||
abe05a73 | 378 | let actual_type = cx.tcx().fully_normalize_associated_types_in(&actual_type); |
d9579d0f AL |
379 | // Add actual type name to <...> clause of function name |
380 | let actual_type_name = compute_debuginfo_type_name(cx, | |
381 | actual_type, | |
382 | true); | |
383 | name_to_append_suffix_to.push_str(&actual_type_name[..]); | |
a7813a04 XL |
384 | } |
385 | name_to_append_suffix_to.push('>'); | |
d9579d0f | 386 | |
a7813a04 XL |
387 | // Again, only create type information if full debuginfo is enabled |
388 | let template_params: Vec<_> = if cx.sess().opts.debuginfo == FullDebugInfo { | |
9e0c209e SL |
389 | let names = get_type_parameter_names(cx, generics); |
390 | substs.types().zip(names).map(|(ty, name)| { | |
abe05a73 | 391 | let actual_type = cx.tcx().fully_normalize_associated_types_in(&ty); |
3157f602 | 392 | let actual_type_metadata = type_metadata(cx, actual_type, syntax_pos::DUMMY_SP); |
9e0c209e | 393 | let name = CString::new(name.as_str().as_bytes()).unwrap(); |
a7813a04 | 394 | unsafe { |
5bcae85e | 395 | llvm::LLVMRustDIBuilderCreateTemplateTypeParameter( |
d9579d0f | 396 | DIB(cx), |
62682a34 | 397 | ptr::null_mut(), |
d9579d0f AL |
398 | name.as_ptr(), |
399 | actual_type_metadata, | |
62682a34 | 400 | file_metadata, |
d9579d0f AL |
401 | 0, |
402 | 0) | |
a7813a04 XL |
403 | } |
404 | }).collect() | |
405 | } else { | |
406 | vec![] | |
407 | }; | |
408 | ||
409 | return create_DIArray(DIB(cx), &template_params[..]); | |
410 | } | |
411 | ||
8bb4bdeb | 412 | fn get_type_parameter_names(cx: &CrateContext, generics: &ty::Generics) -> Vec<ast::Name> { |
9e0c209e | 413 | let mut names = generics.parent.map_or(vec![], |def_id| { |
7cac9316 | 414 | get_type_parameter_names(cx, cx.tcx().generics_of(def_id)) |
9e0c209e SL |
415 | }); |
416 | names.extend(generics.types.iter().map(|param| param.name)); | |
417 | names | |
418 | } | |
419 | ||
420 | fn get_containing_scope<'ccx, 'tcx>(cx: &CrateContext<'ccx, 'tcx>, | |
421 | instance: Instance<'tcx>) | |
422 | -> DIScope { | |
a7813a04 XL |
423 | // First, let's see if this is a method within an inherent impl. Because |
424 | // if yes, we want to make the result subroutine DIE a child of the | |
425 | // subroutine's self-type. | |
cc61c64b | 426 | let self_type = cx.tcx().impl_of_method(instance.def_id()).and_then(|impl_def_id| { |
a7813a04 XL |
427 | // If the method does *not* belong to a trait, proceed |
428 | if cx.tcx().trait_id_of_impl(impl_def_id).is_none() { | |
ff7c6d11 | 429 | let impl_self_ty = cx.tcx().trans_impl_self_ty(impl_def_id, instance.substs); |
9e0c209e SL |
430 | |
431 | // Only "class" methods are generally understood by LLVM, | |
432 | // so avoid methods on other types (e.g. `<*mut T>::null`). | |
433 | match impl_self_ty.sty { | |
32a655c1 | 434 | ty::TyAdt(def, ..) if !def.is_box() => { |
9e0c209e SL |
435 | Some(type_metadata(cx, impl_self_ty, syntax_pos::DUMMY_SP)) |
436 | } | |
437 | _ => None | |
438 | } | |
a7813a04 XL |
439 | } else { |
440 | // For trait method impls we still use the "parallel namespace" | |
441 | // strategy | |
442 | None | |
d9579d0f | 443 | } |
a7813a04 | 444 | }); |
d9579d0f | 445 | |
9e0c209e | 446 | self_type.unwrap_or_else(|| { |
a7813a04 | 447 | namespace::item_namespace(cx, DefId { |
cc61c64b | 448 | krate: instance.def_id().krate, |
a7813a04 | 449 | index: cx.tcx() |
cc61c64b | 450 | .def_key(instance.def_id()) |
a7813a04 | 451 | .parent |
9e0c209e | 452 | .expect("get_containing_scope: missing parent?") |
a7813a04 | 453 | }) |
9e0c209e | 454 | }) |
d9579d0f AL |
455 | } |
456 | } | |
457 | ||
32a655c1 SL |
458 | pub fn declare_local<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, |
459 | dbg_context: &FunctionDebugContext, | |
460 | variable_name: ast::Name, | |
461 | variable_type: Ty<'tcx>, | |
462 | scope_metadata: DIScope, | |
463 | variable_access: VariableAccess, | |
464 | variable_kind: VariableKind, | |
465 | span: Span) { | |
466 | let cx = bcx.ccx; | |
d9579d0f | 467 | |
3157f602 | 468 | let file = span_start(cx, span).file; |
7cac9316 | 469 | let file_metadata = file_metadata(cx, |
ff7c6d11 | 470 | &file.name, |
7cac9316 | 471 | dbg_context.get_ref(span).defining_crate); |
d9579d0f | 472 | |
d9579d0f AL |
473 | let loc = span_start(cx, span); |
474 | let type_metadata = type_metadata(cx, variable_type, span); | |
475 | ||
476 | let (argument_index, dwarf_tag) = match variable_kind { | |
477 | ArgumentVariable(index) => (index as c_uint, DW_TAG_arg_variable), | |
478 | LocalVariable | | |
479 | CapturedVariable => (0, DW_TAG_auto_variable) | |
480 | }; | |
cc61c64b | 481 | let align = cx.align_of(variable_type); |
d9579d0f | 482 | |
c1a9b12d | 483 | let name = CString::new(variable_name.as_str().as_bytes()).unwrap(); |
d9579d0f AL |
484 | match (variable_access, &[][..]) { |
485 | (DirectVariable { alloca }, address_operations) | | |
486 | (IndirectVariable {alloca, address_operations}, _) => { | |
487 | let metadata = unsafe { | |
5bcae85e | 488 | llvm::LLVMRustDIBuilderCreateVariable( |
d9579d0f AL |
489 | DIB(cx), |
490 | dwarf_tag, | |
491 | scope_metadata, | |
492 | name.as_ptr(), | |
493 | file_metadata, | |
494 | loc.line as c_uint, | |
495 | type_metadata, | |
9cc50fc6 | 496 | cx.sess().opts.optimize != config::OptLevel::No, |
476ff2be SL |
497 | DIFlags::FlagZero, |
498 | argument_index, | |
ff7c6d11 | 499 | align.abi() as u32, |
476ff2be | 500 | ) |
d9579d0f | 501 | }; |
32a655c1 | 502 | source_loc::set_debug_location(bcx, |
a7813a04 | 503 | InternalDebugLocation::new(scope_metadata, loc.line, loc.col.to_usize())); |
d9579d0f | 504 | unsafe { |
32a655c1 | 505 | let debug_loc = llvm::LLVMGetCurrentDebugLocation(bcx.llbuilder); |
5bcae85e | 506 | let instr = llvm::LLVMRustDIBuilderInsertDeclareAtEnd( |
d9579d0f AL |
507 | DIB(cx), |
508 | alloca, | |
509 | metadata, | |
510 | address_operations.as_ptr(), | |
511 | address_operations.len() as c_uint, | |
62682a34 | 512 | debug_loc, |
32a655c1 | 513 | bcx.llbb()); |
d9579d0f | 514 | |
32a655c1 | 515 | llvm::LLVMSetInstDebugLocation(bcx.llbuilder, instr); |
d9579d0f AL |
516 | } |
517 | } | |
518 | } | |
519 | ||
520 | match variable_kind { | |
521 | ArgumentVariable(_) | CapturedVariable => { | |
32a655c1 SL |
522 | assert!(!dbg_context.get_ref(span).source_locations_enabled.get()); |
523 | source_loc::set_debug_location(bcx, UnknownLocation); | |
d9579d0f AL |
524 | } |
525 | _ => { /* nothing to do */ } | |
526 | } | |
527 | } |