1#![expect(dead_code)]
2
3use libc::{c_char, c_uint};
4
5use super::MetadataKindId;
6use super::ffi::{AttributeKind, BasicBlock, Context, Metadata, Module, Type, Value};
7use crate::llvm::{Bool, Builder};
8
9pub(crate) type CTypeTreeRef = *mut EnzymeTypeTree;
11
12#[repr(C)]
13#[derive(#[automatically_derived]
impl ::core::fmt::Debug for EnzymeTypeTree {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field1_finish(f,
"EnzymeTypeTree", "_unused", &&self._unused)
}
}Debug, #[automatically_derived]
impl ::core::marker::Copy for EnzymeTypeTree { }Copy, #[automatically_derived]
impl ::core::clone::Clone for EnzymeTypeTree {
#[inline]
fn clone(&self) -> EnzymeTypeTree {
let _: ::core::clone::AssertParamIsClone<[u8; 0]>;
*self
}
}Clone)]
14pub(crate) struct EnzymeTypeTree {
15 _unused: [u8; 0],
16}
17
18#[repr(u32)]
19#[derive(#[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::fmt::Debug for CConcreteType {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
CConcreteType::DT_Anything => "DT_Anything",
CConcreteType::DT_Integer => "DT_Integer",
CConcreteType::DT_Pointer => "DT_Pointer",
CConcreteType::DT_Half => "DT_Half",
CConcreteType::DT_Float => "DT_Float",
CConcreteType::DT_Double => "DT_Double",
CConcreteType::DT_Unknown => "DT_Unknown",
CConcreteType::DT_FP128 => "DT_FP128",
})
}
}Debug, #[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::marker::Copy for CConcreteType { }Copy, #[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::clone::Clone for CConcreteType {
#[inline]
fn clone(&self) -> CConcreteType { *self }
}Clone, #[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::hash::Hash for CConcreteType {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
let __self_discr = ::core::intrinsics::discriminant_value(self);
::core::hash::Hash::hash(&__self_discr, state)
}
}Hash, #[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::cmp::PartialEq for CConcreteType {
#[inline]
fn eq(&self, other: &CConcreteType) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}PartialEq, #[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::cmp::Eq for CConcreteType {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {}
}Eq)]
20#[allow(non_camel_case_types)]
21pub(crate) enum CConcreteType {
22 DT_Anything = 0,
23 DT_Integer = 1,
24 DT_Pointer = 2,
25 DT_Half = 3,
26 DT_Float = 4,
27 DT_Double = 5,
28 DT_Unknown = 6,
29 DT_FP128 = 9,
30}
31
32pub(crate) struct TypeTree {
33 pub(crate) inner: CTypeTreeRef,
34}
35
36#[link(name = "llvm-wrapper", kind = "static")]
37unsafe extern "C" {
38 pub(crate) safe fn LLVMRustHasMetadata(I: &Value, KindID: MetadataKindId) -> bool;
40 pub(crate) fn LLVMRustEraseInstUntilInclusive(BB: &BasicBlock, I: &Value);
41 pub(crate) fn LLVMRustGetLastInstruction<'a>(BB: &BasicBlock) -> Option<&'a Value>;
42 pub(crate) fn LLVMRustDIGetInstMetadata(I: &Value) -> Option<&Metadata>;
43 pub(crate) fn LLVMRustEraseInstFromParent(V: &Value);
44 pub(crate) fn LLVMRustGetTerminator<'a>(B: &BasicBlock) -> &'a Value;
45 pub(crate) fn LLVMRustVerifyFunction(V: &Value, action: LLVMRustVerifierFailureAction) -> Bool;
46 pub(crate) fn LLVMRustHasAttributeAtIndex(V: &Value, i: c_uint, Kind: AttributeKind) -> bool;
47 pub(crate) fn LLVMRustGetArrayNumElements(Ty: &Type) -> u64;
48 pub(crate) fn LLVMRustHasFnAttribute(
49 F: &Value,
50 Name: *const c_char,
51 NameLen: libc::size_t,
52 ) -> bool;
53 pub(crate) fn LLVMRustRemoveFnAttribute(F: &Value, Name: *const c_char, NameLen: libc::size_t);
54 pub(crate) fn LLVMGetFirstFunction(M: &Module) -> Option<&Value>;
55 pub(crate) fn LLVMGetNextFunction(Fn: &Value) -> Option<&Value>;
56 pub(crate) fn LLVMRustRemoveEnumAttributeAtIndex(
57 Fn: &Value,
58 index: c_uint,
59 kind: AttributeKind,
60 );
61 pub(crate) fn LLVMRustPositionBefore<'a>(B: &'a Builder<'_>, I: &'a Value);
62 pub(crate) fn LLVMRustPositionAfter<'a>(B: &'a Builder<'_>, I: &'a Value);
63 pub(crate) fn LLVMRustGetFunctionCall(
64 F: &Value,
65 name: *const c_char,
66 NameLen: libc::size_t,
67 ) -> Option<&Value>;
68
69 pub(crate) safe fn LLVMRustIsCall(V: &Value) -> bool;
70}
71
72unsafe extern "C" {
73 pub(crate) fn LLVMDumpModule(M: &Module);
75 pub(crate) fn LLVMDumpValue(V: &Value);
76 pub(crate) fn LLVMGetFunctionCallConv(F: &Value) -> c_uint;
77 pub(crate) fn LLVMGetParams(Fnc: &Value, params: *mut &Value);
78 pub(crate) fn LLVMGetNamedFunction(M: &Module, Name: *const c_char) -> Option<&Value>;
79}
80
81#[repr(C)]
82#[derive(#[automatically_derived]
impl ::core::marker::Copy for LLVMRustVerifierFailureAction { }Copy, #[automatically_derived]
impl ::core::clone::Clone for LLVMRustVerifierFailureAction {
#[inline]
fn clone(&self) -> LLVMRustVerifierFailureAction { *self }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for LLVMRustVerifierFailureAction {
#[inline]
fn eq(&self, other: &LLVMRustVerifierFailureAction) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}PartialEq)]
83pub(crate) enum LLVMRustVerifierFailureAction {
84 LLVMAbortProcessAction = 0,
85 LLVMPrintMessageAction = 1,
86 LLVMReturnStatusAction = 2,
87}
88
89pub(crate) use self::Enzyme_AD::*;
90
91pub(crate) mod Enzyme_AD {
92 use std::ffi::{c_char, c_void};
93 use std::sync::{Mutex, MutexGuard, OnceLock};
94
95 use rustc_middle::bug;
96 use rustc_session::config::{Sysroot, host_tuple};
97 use rustc_session::filesearch;
98
99 use super::{CConcreteType, CTypeTreeRef, Context};
100 use crate::llvm::{EnzymeTypeTree, LLVMRustVersionMajor};
101
102 type EnzymeSetCLBoolFn = unsafe extern "C" fn(*mut c_void, u8);
103 type EnzymeSetCLStringFn = unsafe extern "C" fn(*mut c_void, *const c_char);
104
105 type EnzymeNewTypeTreeFn = unsafe extern "C" fn() -> CTypeTreeRef;
106 type EnzymeNewTypeTreeCTFn = unsafe extern "C" fn(CConcreteType, &Context) -> CTypeTreeRef;
107 type EnzymeNewTypeTreeTRFn = unsafe extern "C" fn(CTypeTreeRef) -> CTypeTreeRef;
108 type EnzymeFreeTypeTreeFn = unsafe extern "C" fn(CTypeTreeRef);
109 type EnzymeMergeTypeTreeFn = unsafe extern "C" fn(CTypeTreeRef, CTypeTreeRef) -> bool;
110 type EnzymeTypeTreeOnlyEqFn = unsafe extern "C" fn(CTypeTreeRef, i64);
111 type EnzymeTypeTreeData0EqFn = unsafe extern "C" fn(CTypeTreeRef);
112 type EnzymeTypeTreeShiftIndiciesEqFn =
113 unsafe extern "C" fn(CTypeTreeRef, *const c_char, i64, i64, u64);
114 type EnzymeTypeTreeInsertEqFn =
115 unsafe extern "C" fn(CTypeTreeRef, *const i64, usize, CConcreteType, &Context);
116 type EnzymeTypeTreeToStringFn = unsafe extern "C" fn(CTypeTreeRef) -> *const c_char;
117 type EnzymeTypeTreeToStringFreeFn = unsafe extern "C" fn(*const c_char);
118
119 #[allow(non_snake_case)]
120 pub(crate) struct EnzymeWrapper {
121 EnzymeNewTypeTree: EnzymeNewTypeTreeFn,
122 EnzymeNewTypeTreeCT: EnzymeNewTypeTreeCTFn,
123 EnzymeNewTypeTreeTR: EnzymeNewTypeTreeTRFn,
124 EnzymeFreeTypeTree: EnzymeFreeTypeTreeFn,
125 EnzymeMergeTypeTree: EnzymeMergeTypeTreeFn,
126 EnzymeTypeTreeOnlyEq: EnzymeTypeTreeOnlyEqFn,
127 EnzymeTypeTreeData0Eq: EnzymeTypeTreeData0EqFn,
128 EnzymeTypeTreeShiftIndiciesEq: EnzymeTypeTreeShiftIndiciesEqFn,
129 EnzymeTypeTreeInsertEq: EnzymeTypeTreeInsertEqFn,
130 EnzymeTypeTreeToString: EnzymeTypeTreeToStringFn,
131 EnzymeTypeTreeToStringFree: EnzymeTypeTreeToStringFreeFn,
132
133 EnzymePrintPerf: *mut c_void,
134 EnzymePrintActivity: *mut c_void,
135 EnzymePrintType: *mut c_void,
136 EnzymeFunctionToAnalyze: *mut c_void,
137 EnzymePrint: *mut c_void,
138 EnzymeStrictAliasing: *mut c_void,
139 EnzymeInline: *mut c_void,
140 EnzymeMaxTypeDepth: *mut c_void,
141 RustTypeRules: *mut c_void,
142 looseTypeAnalysis: *mut c_void,
143
144 EnzymeSetCLBool: EnzymeSetCLBoolFn,
145 EnzymeSetCLString: EnzymeSetCLStringFn,
146 pub registerEnzymeAndPassPipeline: *const c_void,
147 lib: libloading::Library,
148 }
149
150 unsafe impl Sync for EnzymeWrapper {}
151 unsafe impl Send for EnzymeWrapper {}
152
153 fn load_ptr_by_symbol_mut_void(
154 lib: &libloading::Library,
155 bytes: &[u8],
156 ) -> Result<*mut c_void, libloading::Error> {
157 unsafe {
158 let s: libloading::Symbol<'_, *mut c_void> = lib.get(bytes)?;
159 let s = s.try_as_raw_ptr().unwrap();
161 Ok(s)
162 }
163 }
164
165 macro_rules! load_ptrs_by_symbols_mut_void {
171 ($lib:expr, $($name:ident),* $(,)?) => {
172 $(
173 #[allow(non_snake_case)]
174 let $name = load_ptr_by_symbol_mut_void(&$lib, stringify!($name).as_bytes())?;
175 )*
176 };
177 }
178
179 macro_rules! load_ptrs_by_symbols_fn {
185 ($lib:expr, $($name:ident : $ty:ty),* $(,)?) => {
186 $(
187 #[allow(non_snake_case)]
188 let $name: $ty = *unsafe { $lib.get::<$ty>(stringify!($name).as_bytes())? };
189 )*
190 };
191 }
192
193 static ENZYME_INSTANCE: OnceLock<Mutex<EnzymeWrapper>> = OnceLock::new();
194
195 #[derive(#[automatically_derived]
impl ::core::fmt::Debug for EnzymeLibraryError {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
EnzymeLibraryError::NotFound { err: __self_0 } =>
::core::fmt::Formatter::debug_struct_field1_finish(f,
"NotFound", "err", &__self_0),
EnzymeLibraryError::LoadFailed { err: __self_0 } =>
::core::fmt::Formatter::debug_struct_field1_finish(f,
"LoadFailed", "err", &__self_0),
}
}
}Debug)]
196 pub(crate) enum EnzymeLibraryError {
197 NotFound { err: String },
198 LoadFailed { err: String },
199 }
200
201 impl From<libloading::Error> for EnzymeLibraryError {
202 fn from(err: libloading::Error) -> Self {
203 Self::LoadFailed { err: ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?}", err))
})format!("{err:?}") }
204 }
205 }
206
207 impl EnzymeWrapper {
208 pub(crate) fn get_or_init(
211 sysroot: &rustc_session::config::Sysroot,
212 ) -> Result<MutexGuard<'static, Self>, EnzymeLibraryError> {
213 let mtx: &'static Mutex<EnzymeWrapper> = ENZYME_INSTANCE.get_or_try_init(|| {
214 let w = Self::call_dynamic(sysroot)?;
215 Ok::<_, EnzymeLibraryError>(Mutex::new(w))
216 })?;
217
218 Ok(mtx.lock().unwrap())
219 }
220
221 pub(crate) fn get_instance() -> MutexGuard<'static, Self> {
223 ENZYME_INSTANCE
224 .get()
225 .expect("EnzymeWrapper not initialized. Call get_or_init with sysroot first.")
226 .lock()
227 .unwrap()
228 }
229
230 pub(crate) fn new_type_tree(&self) -> CTypeTreeRef {
231 unsafe { (self.EnzymeNewTypeTree)() }
232 }
233
234 pub(crate) fn new_type_tree_ct(
235 &self,
236 t: CConcreteType,
237 ctx: &Context,
238 ) -> *mut EnzymeTypeTree {
239 unsafe { (self.EnzymeNewTypeTreeCT)(t, ctx) }
240 }
241
242 pub(crate) fn new_type_tree_tr(&self, tree: CTypeTreeRef) -> CTypeTreeRef {
243 unsafe { (self.EnzymeNewTypeTreeTR)(tree) }
244 }
245
246 pub(crate) fn free_type_tree(&self, tree: CTypeTreeRef) {
247 unsafe { (self.EnzymeFreeTypeTree)(tree) }
248 }
249
250 pub(crate) fn merge_type_tree(&self, tree1: CTypeTreeRef, tree2: CTypeTreeRef) -> bool {
251 unsafe { (self.EnzymeMergeTypeTree)(tree1, tree2) }
252 }
253
254 pub(crate) fn tree_only_eq(&self, tree: CTypeTreeRef, num: i64) {
255 unsafe { (self.EnzymeTypeTreeOnlyEq)(tree, num) }
256 }
257
258 pub(crate) fn tree_data0_eq(&self, tree: CTypeTreeRef) {
259 unsafe { (self.EnzymeTypeTreeData0Eq)(tree) }
260 }
261
262 pub(crate) fn shift_indicies_eq(
263 &self,
264 tree: CTypeTreeRef,
265 data_layout: *const c_char,
266 offset: i64,
267 max_size: i64,
268 add_offset: u64,
269 ) {
270 unsafe {
271 (self.EnzymeTypeTreeShiftIndiciesEq)(
272 tree,
273 data_layout,
274 offset,
275 max_size,
276 add_offset,
277 )
278 }
279 }
280
281 pub(crate) fn tree_insert_eq(
282 &self,
283 tree: CTypeTreeRef,
284 indices: *const i64,
285 len: usize,
286 ct: CConcreteType,
287 ctx: &Context,
288 ) {
289 unsafe { (self.EnzymeTypeTreeInsertEq)(tree, indices, len, ct, ctx) }
290 }
291
292 pub(crate) fn tree_to_string(&self, tree: *mut EnzymeTypeTree) -> *const c_char {
293 unsafe { (self.EnzymeTypeTreeToString)(tree) }
294 }
295
296 pub(crate) fn tree_to_cstr(&self, tree: *mut EnzymeTypeTree) -> &std::ffi::CStr {
297 let c_str = self.tree_to_string(tree);
298 unsafe { std::ffi::CStr::from_ptr(c_str) }
299 }
300
301 pub(crate) fn tree_to_string_free(&self, ch: *const c_char) {
302 unsafe { (self.EnzymeTypeTreeToStringFree)(ch) }
303 }
304
305 pub(crate) fn get_max_type_depth(&self) -> usize {
306 unsafe { std::ptr::read::<u32>(self.EnzymeMaxTypeDepth as *const u32) as usize }
307 }
308
309 pub(crate) fn set_print_perf(&mut self, print: bool) {
310 unsafe {
311 (self.EnzymeSetCLBool)(self.EnzymePrintPerf, print as u8);
312 }
313 }
314
315 pub(crate) fn set_print_activity(&mut self, print: bool) {
316 unsafe {
317 (self.EnzymeSetCLBool)(self.EnzymePrintActivity, print as u8);
318 }
319 }
320
321 pub(crate) fn set_print_type(&mut self, print: bool) {
322 unsafe {
323 (self.EnzymeSetCLBool)(self.EnzymePrintType, print as u8);
324 }
325 }
326
327 pub(crate) fn set_print_type_fun(&mut self, fun_name: &str) {
328 let c_fun_name = std::ffi::CString::new(fun_name)
329 .unwrap_or_else(|err| ::rustc_middle::util::bug::bug_fmt(format_args!("failed to set_print_type_fun: {0}",
err))bug!("failed to set_print_type_fun: {err}"));
330 unsafe {
331 (self.EnzymeSetCLString)(
332 self.EnzymeFunctionToAnalyze,
333 c_fun_name.as_ptr() as *const c_char,
334 );
335 }
336 }
337
338 pub(crate) fn set_print(&mut self, print: bool) {
339 unsafe {
340 (self.EnzymeSetCLBool)(self.EnzymePrint, print as u8);
341 }
342 }
343
344 pub(crate) fn set_strict_aliasing(&mut self, strict: bool) {
345 unsafe {
346 (self.EnzymeSetCLBool)(self.EnzymeStrictAliasing, strict as u8);
347 }
348 }
349
350 pub(crate) fn set_loose_types(&mut self, loose: bool) {
351 unsafe {
352 (self.EnzymeSetCLBool)(self.looseTypeAnalysis, loose as u8);
353 }
354 }
355
356 pub(crate) fn set_inline(&mut self, val: bool) {
357 unsafe {
358 (self.EnzymeSetCLBool)(self.EnzymeInline, val as u8);
359 }
360 }
361
362 pub(crate) fn set_rust_rules(&mut self, val: bool) {
363 unsafe {
364 (self.EnzymeSetCLBool)(self.RustTypeRules, val as u8);
365 }
366 }
367
368 #[allow(non_snake_case)]
369 fn call_dynamic(
370 sysroot: &rustc_session::config::Sysroot,
371 ) -> Result<Self, EnzymeLibraryError> {
372 let enzyme_path = Self::get_enzyme_path(sysroot)?;
373 let lib = unsafe { libloading::Library::new(enzyme_path)? };
374
375 #[allow(non_snake_case)]
let EnzymeSetCLString: EnzymeSetCLStringFn =
*unsafe {
lib.get::<EnzymeSetCLStringFn>("EnzymeSetCLString".as_bytes())?
};load_ptrs_by_symbols_fn!(
376 lib,
377 EnzymeNewTypeTree: EnzymeNewTypeTreeFn,
378 EnzymeNewTypeTreeCT: EnzymeNewTypeTreeCTFn,
379 EnzymeNewTypeTreeTR: EnzymeNewTypeTreeTRFn,
380 EnzymeFreeTypeTree: EnzymeFreeTypeTreeFn,
381 EnzymeMergeTypeTree: EnzymeMergeTypeTreeFn,
382 EnzymeTypeTreeOnlyEq: EnzymeTypeTreeOnlyEqFn,
383 EnzymeTypeTreeData0Eq: EnzymeTypeTreeData0EqFn,
384 EnzymeTypeTreeShiftIndiciesEq: EnzymeTypeTreeShiftIndiciesEqFn,
385 EnzymeTypeTreeInsertEq: EnzymeTypeTreeInsertEqFn,
386 EnzymeTypeTreeToString: EnzymeTypeTreeToStringFn,
387 EnzymeTypeTreeToStringFree: EnzymeTypeTreeToStringFreeFn,
388 EnzymeSetCLBool: EnzymeSetCLBoolFn,
389 EnzymeSetCLString: EnzymeSetCLStringFn,
390 );
391
392 #[allow(non_snake_case)]
let looseTypeAnalysis =
load_ptr_by_symbol_mut_void(&lib, "looseTypeAnalysis".as_bytes())?;load_ptrs_by_symbols_mut_void!(
393 lib,
394 registerEnzymeAndPassPipeline,
395 EnzymePrintPerf,
396 EnzymePrintActivity,
397 EnzymePrintType,
398 EnzymeFunctionToAnalyze,
399 EnzymePrint,
400 EnzymeStrictAliasing,
401 EnzymeInline,
402 EnzymeMaxTypeDepth,
403 RustTypeRules,
404 looseTypeAnalysis,
405 );
406
407 Ok(Self {
408 EnzymeNewTypeTree,
409 EnzymeNewTypeTreeCT,
410 EnzymeNewTypeTreeTR,
411 EnzymeFreeTypeTree,
412 EnzymeMergeTypeTree,
413 EnzymeTypeTreeOnlyEq,
414 EnzymeTypeTreeData0Eq,
415 EnzymeTypeTreeShiftIndiciesEq,
416 EnzymeTypeTreeInsertEq,
417 EnzymeTypeTreeToString,
418 EnzymeTypeTreeToStringFree,
419 EnzymePrintPerf,
420 EnzymePrintActivity,
421 EnzymePrintType,
422 EnzymeFunctionToAnalyze,
423 EnzymePrint,
424 EnzymeStrictAliasing,
425 EnzymeInline,
426 EnzymeMaxTypeDepth,
427 RustTypeRules,
428 looseTypeAnalysis,
429 EnzymeSetCLBool,
430 EnzymeSetCLString,
431 registerEnzymeAndPassPipeline,
432 lib,
433 })
434 }
435
436 fn get_enzyme_path(sysroot: &Sysroot) -> Result<String, EnzymeLibraryError> {
437 let llvm_version_major = unsafe { LLVMRustVersionMajor() };
438
439 let path_buf = sysroot
440 .all_paths()
441 .map(|sysroot_path| {
442 filesearch::make_target_lib_path(sysroot_path, host_tuple())
443 .join("lib")
444 .with_file_name(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("libEnzyme-{0}",
llvm_version_major))
})format!("libEnzyme-{llvm_version_major}"))
445 .with_extension(std::env::consts::DLL_EXTENSION)
446 })
447 .find(|f| f.exists())
448 .ok_or_else(|| {
449 let candidates = sysroot
450 .all_paths()
451 .map(|p| p.join("lib").display().to_string())
452 .collect::<Vec<String>>()
453 .join("\n* ");
454 EnzymeLibraryError::NotFound {
455 err: ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("failed to find a `libEnzyme-{0}` folder in the sysroot candidates:\n* {1}",
llvm_version_major, candidates))
})format!(
456 "failed to find a `libEnzyme-{llvm_version_major}` folder \
457 in the sysroot candidates:\n* {candidates}"
458 ),
459 }
460 })?;
461
462 Ok(path_buf
463 .to_str()
464 .ok_or_else(|| EnzymeLibraryError::LoadFailed {
465 err: ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("invalid UTF-8 in path: {0}",
path_buf.display()))
})format!("invalid UTF-8 in path: {}", path_buf.display()),
466 })?
467 .to_string())
468 }
469 }
470}
471
472impl TypeTree {
473 pub(crate) fn new() -> TypeTree {
474 let wrapper = EnzymeWrapper::get_instance();
475 let inner = wrapper.new_type_tree();
476 TypeTree { inner }
477 }
478
479 pub(crate) fn from_type(t: CConcreteType, ctx: &Context) -> TypeTree {
480 let wrapper = EnzymeWrapper::get_instance();
481 let inner = wrapper.new_type_tree_ct(t, ctx);
482 TypeTree { inner }
483 }
484
485 pub(crate) fn merge(self, other: Self) -> Self {
486 let wrapper = EnzymeWrapper::get_instance();
487 wrapper.merge_type_tree(self.inner, other.inner);
488 drop(other);
489 self
490 }
491
492 #[must_use]
493 pub(crate) fn shift(
494 self,
495 layout: &str,
496 offset: isize,
497 max_size: isize,
498 add_offset: usize,
499 ) -> Self {
500 let layout = std::ffi::CString::new(layout).unwrap();
501 let wrapper = EnzymeWrapper::get_instance();
502 wrapper.shift_indicies_eq(
503 self.inner,
504 layout.as_ptr(),
505 offset as i64,
506 max_size as i64,
507 add_offset as u64,
508 );
509
510 self
511 }
512
513 pub(crate) fn insert(&mut self, indices: &[i64], ct: CConcreteType, ctx: &Context) {
514 let wrapper = EnzymeWrapper::get_instance();
515 wrapper.tree_insert_eq(self.inner, indices.as_ptr(), indices.len(), ct, ctx);
516 }
517}
518
519impl Clone for TypeTree {
520 fn clone(&self) -> Self {
521 let wrapper = EnzymeWrapper::get_instance();
522 let inner = wrapper.new_type_tree_tr(self.inner);
523 TypeTree { inner }
524 }
525}
526
527impl std::fmt::Display for TypeTree {
528 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
529 let wrapper = EnzymeWrapper::get_instance();
530 let ptr = wrapper.tree_to_string(self.inner);
531 let cstr = unsafe { std::ffi::CStr::from_ptr(ptr) };
532 match cstr.to_str() {
533 Ok(x) => f.write_fmt(format_args!("{0}", x))write!(f, "{}", x)?,
534 Err(err) => f.write_fmt(format_args!("could not parse: {0}", err))write!(f, "could not parse: {}", err)?,
535 }
536
537 wrapper.tree_to_string_free(ptr);
539
540 Ok(())
541 }
542}
543
544impl std::fmt::Debug for TypeTree {
545 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
546 <Self as std::fmt::Display>::fmt(self, f)
547 }
548}
549
550impl Drop for TypeTree {
551 fn drop(&mut self) {
552 let wrapper = EnzymeWrapper::get_instance();
553 wrapper.free_type_tree(self.inner)
554 }
555}