1use crate::{
2 context::{Context, ContextRef},
3 ir::{Attribute, AttributeLike},
4 string_ref::StringRef,
5 utility::print_callback,
6};
7use mlir_sys::{
8 mlirLocationCallSiteGet, mlirLocationEqual, mlirLocationFileLineColGet, mlirLocationFusedGet,
9 mlirLocationGetContext, mlirLocationNameGet, mlirLocationPrint, mlirLocationUnknownGet,
10 MlirLocation,
11};
12use std::{
13 ffi::c_void,
14 fmt::{self, Display, Formatter},
15 marker::PhantomData,
16};
17
18#[derive(Clone, Copy, Debug)]
20pub struct Location<'c> {
21 raw: MlirLocation,
22 _context: PhantomData<&'c Context>,
23}
24
25impl<'c> Location<'c> {
26 pub fn new(context: &'c Context, filename: &str, line: usize, column: usize) -> Self {
28 unsafe {
29 Self::from_raw(mlirLocationFileLineColGet(
30 context.to_raw(),
31 StringRef::new(filename).to_raw(),
32 line as u32,
33 column as u32,
34 ))
35 }
36 }
37
38 pub fn fused(context: &'c Context, locations: &[Self], attribute: Attribute) -> Self {
40 unsafe {
41 Self::from_raw(mlirLocationFusedGet(
42 context.to_raw(),
43 locations.len() as isize,
44 locations as *const _ as *const _,
45 attribute.to_raw(),
46 ))
47 }
48 }
49
50 pub fn name(context: &'c Context, name: &str, child: Location) -> Self {
52 unsafe {
53 Self::from_raw(mlirLocationNameGet(
54 context.to_raw(),
55 StringRef::new(name).to_raw(),
56 child.to_raw(),
57 ))
58 }
59 }
60
61 pub fn call_site(callee: Location, caller: Location) -> Self {
63 unsafe { Self::from_raw(mlirLocationCallSiteGet(callee.to_raw(), caller.to_raw())) }
64 }
65
66 pub fn unknown(context: &'c Context) -> Self {
68 unsafe { Self::from_raw(mlirLocationUnknownGet(context.to_raw())) }
69 }
70
71 pub fn context(&self) -> ContextRef<'c> {
73 unsafe { ContextRef::from_raw(mlirLocationGetContext(self.raw)) }
74 }
75
76 pub unsafe fn from_raw(raw: MlirLocation) -> Self {
82 Self {
83 raw,
84 _context: Default::default(),
85 }
86 }
87
88 pub const fn to_raw(self) -> MlirLocation {
90 self.raw
91 }
92}
93
94impl PartialEq for Location<'_> {
95 fn eq(&self, other: &Self) -> bool {
96 unsafe { mlirLocationEqual(self.raw, other.raw) }
97 }
98}
99
100impl Display for Location<'_> {
101 fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
102 let mut data = (formatter, Ok(()));
103
104 unsafe {
105 mlirLocationPrint(
106 self.raw,
107 Some(print_callback),
108 &mut data as *mut _ as *mut c_void,
109 );
110 }
111
112 data.1
113 }
114}
115
116#[cfg(test)]
117mod tests {
118 use super::*;
119 use pretty_assertions::{assert_eq, assert_ne};
120
121 #[test]
122 fn new() {
123 Location::new(&Context::new(), "foo", 42, 42);
124 }
125
126 #[test]
127 fn fused() {
128 let context = Context::new();
129
130 Location::fused(
131 &context,
132 &[
133 Location::new(&Context::new(), "foo", 1, 1),
134 Location::new(&Context::new(), "foo", 2, 2),
135 ],
136 Attribute::parse(&context, "42").unwrap(),
137 );
138 }
139
140 #[test]
141 fn name() {
142 let context = Context::new();
143
144 Location::name(&context, "foo", Location::unknown(&context));
145 }
146
147 #[test]
148 fn call_site() {
149 let context = Context::new();
150
151 Location::call_site(Location::unknown(&context), Location::unknown(&context));
152 }
153
154 #[test]
155 fn unknown() {
156 Location::unknown(&Context::new());
157 }
158
159 #[test]
160 fn context() {
161 Location::new(&Context::new(), "foo", 42, 42).context();
162 }
163
164 #[test]
165 fn equal() {
166 let context = Context::new();
167
168 assert_eq!(Location::unknown(&context), Location::unknown(&context));
169 assert_eq!(
170 Location::new(&context, "foo", 42, 42),
171 Location::new(&context, "foo", 42, 42),
172 );
173 }
174
175 #[test]
176 fn not_equal() {
177 let context = Context::new();
178
179 assert_ne!(
180 Location::new(&context, "foo", 42, 42),
181 Location::unknown(&context)
182 );
183 }
184
185 #[test]
186 fn display() {
187 let context = Context::new();
188
189 assert_eq!(Location::unknown(&context).to_string(), "loc(unknown)");
190 assert_eq!(
191 Location::new(&context, "foo", 42, 42).to_string(),
192 "loc(\"foo\":42:42)"
193 );
194 }
195}