]> git.lizzy.rs Git - rust.git/blob - src/librustc_trans/debuginfo/source_loc.rs
rustc_trans: remove the bulk of old trans and most of its support code.
[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::{scope_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::At(node_id, span) => {
51                 (scope_metadata(fcx, node_id, span), span)
52             }
53             DebugLoc::ScopeAt(scope, span) => (scope, span),
54             DebugLoc::None => {
55                 set_debug_location(fcx.ccx, builder, UnknownLocation);
56                 return;
57             }
58         };
59
60         debug!("set_source_location: {}",
61                fcx.ccx.sess().codemap().span_to_string(span));
62         let loc = span_start(fcx.ccx, span);
63         InternalDebugLocation::new(scope, loc.line, loc.col.to_usize())
64     } else {
65         UnknownLocation
66     };
67     set_debug_location(fcx.ccx, builder, dbg_loc);
68 }
69
70 /// Enables emitting source locations for the given functions.
71 ///
72 /// Since we don't want source locations to be emitted for the function prelude,
73 /// they are disabled when beginning to translate a new function. This functions
74 /// switches source location emitting on and must therefore be called before the
75 /// first real statement/expression of the function is translated.
76 pub fn start_emitting_source_locations(fcx: &FunctionContext) {
77     match fcx.debug_context {
78         FunctionDebugContext::RegularContext(box ref data) => {
79             data.source_locations_enabled.set(true)
80         },
81         _ => { /* safe to ignore */ }
82     }
83 }
84
85
86 #[derive(Copy, Clone, PartialEq)]
87 pub enum InternalDebugLocation {
88     KnownLocation { scope: DIScope, line: usize, col: usize },
89     UnknownLocation
90 }
91
92 impl InternalDebugLocation {
93     pub fn new(scope: DIScope, line: usize, col: usize) -> InternalDebugLocation {
94         KnownLocation {
95             scope: scope,
96             line: line,
97             col: col,
98         }
99     }
100 }
101
102 pub fn set_debug_location(cx: &CrateContext,
103                           builder: Option<llvm::BuilderRef>,
104                           debug_location: InternalDebugLocation) {
105     if builder.is_none() {
106         if debug_location == debug_context(cx).current_debug_location.get() {
107             return;
108         }
109     }
110
111     let metadata_node = match debug_location {
112         KnownLocation { scope, line, .. } => {
113             // Always set the column to zero like Clang and GCC
114             let col = UNKNOWN_COLUMN_NUMBER;
115             debug!("setting debug location to {} {}", line, col);
116
117             unsafe {
118                 llvm::LLVMRustDIBuilderCreateDebugLocation(
119                     debug_context(cx).llcontext,
120                     line as c_uint,
121                     col as c_uint,
122                     scope,
123                     ptr::null_mut())
124             }
125         }
126         UnknownLocation => {
127             debug!("clearing debug location ");
128             ptr::null_mut()
129         }
130     };
131
132     if builder.is_none() {
133         debug_context(cx).current_debug_location.set(debug_location);
134     }
135
136     let builder = builder.unwrap_or_else(|| cx.raw_builder());
137     unsafe {
138         llvm::LLVMSetCurrentDebugLocation(builder, metadata_node);
139     }
140 }