1use std::cmp::{Ordering, PartialOrd};
2use std::fmt;
3
4#[derive(PartialEq, Eq, Clone, Debug, Hash)]
6pub struct DebugLoc {
7 pub line: u32,
9 pub col: Option<u32>,
15 pub filename: String,
17 pub directory: Option<String>,
19}
20
21impl PartialOrd for DebugLoc {
22 #[rustfmt::skip] fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
24 Some(
26 (&self.directory, &self.filename, &self.line, &self.col)
27 .cmp(&(&other.directory, &other.filename, &other.line, &other.col))
28 )
29 }
30}
31
32impl Ord for DebugLoc {
33 #[rustfmt::skip] fn cmp(&self, other: &Self) -> Ordering {
35 (&self.directory, &self.filename, &self.line, &self.col)
37 .cmp(&(&other.directory, &other.filename, &other.line, &other.col))
38 }
39}
40
41impl fmt::Display for DebugLoc {
42 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
43 let pretty_directory = match &self.directory {
44 Some(dir) => dir,
45 None => "",
46 };
47 let need_slash = match &self.directory {
48 Some(dir) => !dir.is_empty() && !dir.ends_with('/') && !self.filename.starts_with('/'),
49 None => false,
50 };
51 let pretty_filename = match &self.filename as &str {
52 "" => "<no filename available>",
53 filename if !pretty_directory.is_empty() => {
54 filename.trim_start_matches(pretty_directory)
55 },
56 filename => filename,
57 };
58 let pretty_column = match self.col {
59 Some(col) => format!(", col {}", col),
60 None => String::new(),
61 };
62 write!(
63 f,
64 "{}{}{}, line {}{}",
65 pretty_directory,
66 if need_slash { "/" } else { "" },
67 pretty_filename,
68 self.line,
69 pretty_column,
70 )
71 }
72}
73
74pub trait HasDebugLoc {
75 fn get_debug_loc(&self) -> &Option<DebugLoc>;
85}
86
87use crate::from_llvm::*;
92use crate::llvm_sys::*;
93
94impl DebugLoc {
95 pub(crate) fn from_llvm_no_col(value: LLVMValueRef) -> Option<Self> {
99 match unsafe { get_debugloc_filename(value) } {
100 None => None, Some(filename) => Some(Self {
102 line: unsafe { LLVMGetDebugLocLine(value) },
103 col: None,
104 filename,
105 directory: unsafe { get_debugloc_directory(value) },
106 }),
107 }
108 }
109
110 pub(crate) fn from_llvm_with_col(value: LLVMValueRef) -> Option<Self> {
114 match Self::from_llvm_no_col(value) {
115 Some(mut debugloc) => {
116 debugloc.col = Some(unsafe { LLVMGetDebugLocColumn(value) });
117 Some(debugloc)
118 },
119 None => None,
120 }
121 }
122}