]> git.lizzy.rs Git - rust.git/blob - src/librustc_trans/debuginfo/source_loc.rs
Auto merge of #35585 - Kha:gdb-qualified, r=michaelwoerister
[rust.git] / src / librustc_trans / debuginfo / source_loc.rs
1 // Copyright 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 use self::InternalDebugLocation::*;
12
13 use super::utils::{debug_context, span_start};
14 use super::metadata::{UNKNOWN_COLUMN_NUMBER};
15 use super::{FunctionDebugContext, DebugLoc};
16
17 use llvm;
18 use llvm::debuginfo::DIScope;
19 use builder::Builder;
20 use common::{CrateContext, FunctionContext};
21
22 use libc::c_uint;
23 use std::ptr;
24 use syntax_pos::Pos;
25
26 /// Sets the current debug location at the beginning of the span.
27 ///
28 /// Maps to a call to llvm::LLVMSetCurrentDebugLocation(...).
29 pub fn set_source_location(fcx: &FunctionContext,
30                            builder: Option<&Builder>,
31                            debug_loc: DebugLoc) {
32     let builder = builder.map(|b| b.llbuilder);
33     let function_debug_context = match fcx.debug_context {
34         FunctionDebugContext::DebugInfoDisabled => return,
35         FunctionDebugContext::FunctionWithoutDebugInfo => {
36             set_debug_location(fcx.ccx, builder, UnknownLocation);
37             return;
38         }
39         FunctionDebugContext::RegularContext(box ref data) => data
40     };
41
42     if function_debug_context.source_location_override.get() {
43         // Just ignore any attempts to set a new debug location while
44         // the override is active.
45         return;
46     }
47
48     let dbg_loc = if function_debug_context.source_locations_enabled.get() {
49         let (scope, span) = match debug_loc {
50             DebugLoc::ScopeAt(scope, span) => (scope, span),
51             DebugLoc::None => {
52                 set_debug_location(fcx.ccx, builder, UnknownLocation);
53                 return;
54             }
55         };
56
57         debug!("set_source_location: {}",
58                fcx.ccx.sess().codemap().span_to_string(span));
59         let loc = span_start(fcx.ccx, span);
60         InternalDebugLocation::new(scope, loc.line, loc.col.to_usize())
61     } else {
62         UnknownLocation
63     };
64     set_debug_location(fcx.ccx, builder, dbg_loc);
65 }
66
67 /// Enables emitting source locations for the given functions.
68 ///
69 /// Since we don't want source locations to be emitted for the function prelude,
70 /// they are disabled when beginning to translate a new function. This functions
71 /// switches source location emitting on and must therefore be called before the
72 /// first real statement/expression of the function is translated.
73 pub fn start_emitting_source_locations(fcx: &FunctionContext) {
74     match fcx.debug_context {
75         FunctionDebugContext::RegularContext(box ref data) => {
76             data.source_locations_enabled.set(true)
77         },
78         _ => { /* safe to ignore */ }
79     }
80 }
81
82
83 #[derive(Copy, Clone, PartialEq)]
84 pub enum InternalDebugLocation {
85     KnownLocation { scope: DIScope, line: usize, col: usize },
86     UnknownLocation
87 }
88
89 impl InternalDebugLocation {
90     pub fn new(scope: DIScope, line: usize, col: usize) -> InternalDebugLocation {
91         KnownLocation {
92             scope: scope,
93             line: line,
94             col: col,
95         }
96     }
97 }
98
99 pub fn set_debug_location(cx: &CrateContext,
100                           builder: Option<llvm::BuilderRef>,
101                           debug_location: InternalDebugLocation) {
102     if builder.is_none() {
103         if debug_location == debug_context(cx).current_debug_location.get() {
104             return;
105         }
106     }
107
108     let metadata_node = match debug_location {
109         KnownLocation { scope, line, .. } => {
110             // Always set the column to zero like Clang and GCC
111             let col = UNKNOWN_COLUMN_NUMBER;
112             debug!("setting debug location to {} {}", line, col);
113
114             unsafe {
115                 llvm::LLVMRustDIBuilderCreateDebugLocation(
116                     debug_context(cx).llcontext,
117                     line as c_uint,
118                     col as c_uint,
119                     scope,
120                     ptr::null_mut())
121             }
122         }
123         UnknownLocation => {
124             debug!("clearing debug location ");
125             ptr::null_mut()
126         }
127     };
128
129     if builder.is_none() {
130         debug_context(cx).current_debug_location.set(debug_location);
131     }
132
133     let builder = builder.unwrap_or_else(|| cx.raw_builder());
134     unsafe {
135         llvm::LLVMSetCurrentDebugLocation(builder, metadata_node);
136     }
137 }