rustc_codegen_llvm/llvm/
enzyme_ffi.rs

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
9// TypeTree types
10pub(crate) type CTypeTreeRef = *mut EnzymeTypeTree;
11
12#[repr(C)]
13#[derive(Debug, Copy, Clone)]
14pub(crate) struct EnzymeTypeTree {
15    _unused: [u8; 0],
16}
17
18#[repr(u32)]
19#[derive(Debug, Copy, Clone, Hash, PartialEq, 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    // Enzyme
39    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}
70
71unsafe extern "C" {
72    // Enzyme
73    pub(crate) fn LLVMDumpModule(M: &Module);
74    pub(crate) fn LLVMDumpValue(V: &Value);
75    pub(crate) fn LLVMGetFunctionCallConv(F: &Value) -> c_uint;
76    pub(crate) fn LLVMGetReturnType(T: &Type) -> &Type;
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(Copy, Clone, PartialEq)]
83pub(crate) enum LLVMRustVerifierFailureAction {
84    LLVMAbortProcessAction = 0,
85    LLVMPrintMessageAction = 1,
86    LLVMReturnStatusAction = 2,
87}
88
89#[cfg(feature = "llvm_enzyme")]
90pub(crate) use self::Enzyme_AD::*;
91
92#[cfg(feature = "llvm_enzyme")]
93pub(crate) mod Enzyme_AD {
94    use std::ffi::{CString, c_char};
95
96    use libc::c_void;
97
98    use super::{CConcreteType, CTypeTreeRef, Context};
99
100    unsafe extern "C" {
101        pub(crate) fn EnzymeSetCLBool(arg1: *mut ::std::os::raw::c_void, arg2: u8);
102        pub(crate) fn EnzymeSetCLString(arg1: *mut ::std::os::raw::c_void, arg2: *const c_char);
103    }
104
105    // TypeTree functions
106    unsafe extern "C" {
107        pub(crate) fn EnzymeNewTypeTree() -> CTypeTreeRef;
108        pub(crate) fn EnzymeNewTypeTreeCT(arg1: CConcreteType, ctx: &Context) -> CTypeTreeRef;
109        pub(crate) fn EnzymeNewTypeTreeTR(arg1: CTypeTreeRef) -> CTypeTreeRef;
110        pub(crate) fn EnzymeFreeTypeTree(CTT: CTypeTreeRef);
111        pub(crate) fn EnzymeMergeTypeTree(arg1: CTypeTreeRef, arg2: CTypeTreeRef) -> bool;
112        pub(crate) fn EnzymeTypeTreeOnlyEq(arg1: CTypeTreeRef, pos: i64);
113        pub(crate) fn EnzymeTypeTreeData0Eq(arg1: CTypeTreeRef);
114        pub(crate) fn EnzymeTypeTreeShiftIndiciesEq(
115            arg1: CTypeTreeRef,
116            data_layout: *const c_char,
117            offset: i64,
118            max_size: i64,
119            add_offset: u64,
120        );
121        pub(crate) fn EnzymeTypeTreeInsertEq(
122            CTT: CTypeTreeRef,
123            indices: *const i64,
124            len: usize,
125            ct: CConcreteType,
126            ctx: &Context,
127        );
128        pub(crate) fn EnzymeTypeTreeToString(arg1: CTypeTreeRef) -> *const c_char;
129        pub(crate) fn EnzymeTypeTreeToStringFree(arg1: *const c_char);
130    }
131
132    unsafe extern "C" {
133        static mut EnzymePrintPerf: c_void;
134        static mut EnzymePrintActivity: c_void;
135        static mut EnzymePrintType: c_void;
136        static mut EnzymeFunctionToAnalyze: c_void;
137        static mut EnzymePrint: c_void;
138        static mut EnzymeStrictAliasing: c_void;
139        static mut looseTypeAnalysis: c_void;
140        static mut EnzymeInline: c_void;
141        static mut RustTypeRules: c_void;
142    }
143    pub(crate) fn set_print_perf(print: bool) {
144        unsafe {
145            EnzymeSetCLBool(std::ptr::addr_of_mut!(EnzymePrintPerf), print as u8);
146        }
147    }
148    pub(crate) fn set_print_activity(print: bool) {
149        unsafe {
150            EnzymeSetCLBool(std::ptr::addr_of_mut!(EnzymePrintActivity), print as u8);
151        }
152    }
153    pub(crate) fn set_print_type(print: bool) {
154        unsafe {
155            EnzymeSetCLBool(std::ptr::addr_of_mut!(EnzymePrintType), print as u8);
156        }
157    }
158    pub(crate) fn set_print_type_fun(fun_name: &str) {
159        let c_fun_name = CString::new(fun_name).unwrap();
160        unsafe {
161            EnzymeSetCLString(
162                std::ptr::addr_of_mut!(EnzymeFunctionToAnalyze),
163                c_fun_name.as_ptr() as *const c_char,
164            );
165        }
166    }
167    pub(crate) fn set_print(print: bool) {
168        unsafe {
169            EnzymeSetCLBool(std::ptr::addr_of_mut!(EnzymePrint), print as u8);
170        }
171    }
172    pub(crate) fn set_strict_aliasing(strict: bool) {
173        unsafe {
174            EnzymeSetCLBool(std::ptr::addr_of_mut!(EnzymeStrictAliasing), strict as u8);
175        }
176    }
177    pub(crate) fn set_loose_types(loose: bool) {
178        unsafe {
179            EnzymeSetCLBool(std::ptr::addr_of_mut!(looseTypeAnalysis), loose as u8);
180        }
181    }
182    pub(crate) fn set_inline(val: bool) {
183        unsafe {
184            EnzymeSetCLBool(std::ptr::addr_of_mut!(EnzymeInline), val as u8);
185        }
186    }
187    pub(crate) fn set_rust_rules(val: bool) {
188        unsafe {
189            EnzymeSetCLBool(std::ptr::addr_of_mut!(RustTypeRules), val as u8);
190        }
191    }
192}
193
194#[cfg(not(feature = "llvm_enzyme"))]
195pub(crate) use self::Fallback_AD::*;
196
197#[cfg(not(feature = "llvm_enzyme"))]
198pub(crate) mod Fallback_AD {
199    #![allow(unused_variables)]
200
201    use libc::c_char;
202
203    use super::{CConcreteType, CTypeTreeRef, Context};
204
205    // TypeTree function fallbacks
206    pub(crate) unsafe fn EnzymeNewTypeTree() -> CTypeTreeRef {
207        unimplemented!()
208    }
209
210    pub(crate) unsafe fn EnzymeNewTypeTreeCT(arg1: CConcreteType, ctx: &Context) -> CTypeTreeRef {
211        unimplemented!()
212    }
213
214    pub(crate) unsafe fn EnzymeNewTypeTreeTR(arg1: CTypeTreeRef) -> CTypeTreeRef {
215        unimplemented!()
216    }
217
218    pub(crate) unsafe fn EnzymeFreeTypeTree(CTT: CTypeTreeRef) {
219        unimplemented!()
220    }
221
222    pub(crate) unsafe fn EnzymeMergeTypeTree(arg1: CTypeTreeRef, arg2: CTypeTreeRef) -> bool {
223        unimplemented!()
224    }
225
226    pub(crate) unsafe fn EnzymeTypeTreeOnlyEq(arg1: CTypeTreeRef, pos: i64) {
227        unimplemented!()
228    }
229
230    pub(crate) unsafe fn EnzymeTypeTreeData0Eq(arg1: CTypeTreeRef) {
231        unimplemented!()
232    }
233
234    pub(crate) unsafe fn EnzymeTypeTreeShiftIndiciesEq(
235        arg1: CTypeTreeRef,
236        data_layout: *const c_char,
237        offset: i64,
238        max_size: i64,
239        add_offset: u64,
240    ) {
241        unimplemented!()
242    }
243
244    pub(crate) unsafe fn EnzymeTypeTreeInsertEq(
245        CTT: CTypeTreeRef,
246        indices: *const i64,
247        len: usize,
248        ct: CConcreteType,
249        ctx: &Context,
250    ) {
251        unimplemented!()
252    }
253
254    pub(crate) unsafe fn EnzymeTypeTreeToString(arg1: CTypeTreeRef) -> *const c_char {
255        unimplemented!()
256    }
257
258    pub(crate) unsafe fn EnzymeTypeTreeToStringFree(arg1: *const c_char) {
259        unimplemented!()
260    }
261
262    pub(crate) fn set_inline(val: bool) {
263        unimplemented!()
264    }
265    pub(crate) fn set_print_perf(print: bool) {
266        unimplemented!()
267    }
268    pub(crate) fn set_print_activity(print: bool) {
269        unimplemented!()
270    }
271    pub(crate) fn set_print_type(print: bool) {
272        unimplemented!()
273    }
274    pub(crate) fn set_print_type_fun(fun_name: &str) {
275        unimplemented!()
276    }
277    pub(crate) fn set_print(print: bool) {
278        unimplemented!()
279    }
280    pub(crate) fn set_strict_aliasing(strict: bool) {
281        unimplemented!()
282    }
283    pub(crate) fn set_loose_types(loose: bool) {
284        unimplemented!()
285    }
286    pub(crate) fn set_rust_rules(val: bool) {
287        unimplemented!()
288    }
289}
290
291impl TypeTree {
292    pub(crate) fn new() -> TypeTree {
293        let inner = unsafe { EnzymeNewTypeTree() };
294        TypeTree { inner }
295    }
296
297    pub(crate) fn from_type(t: CConcreteType, ctx: &Context) -> TypeTree {
298        let inner = unsafe { EnzymeNewTypeTreeCT(t, ctx) };
299        TypeTree { inner }
300    }
301
302    pub(crate) fn merge(self, other: Self) -> Self {
303        unsafe {
304            EnzymeMergeTypeTree(self.inner, other.inner);
305        }
306        drop(other);
307        self
308    }
309
310    #[must_use]
311    pub(crate) fn shift(
312        self,
313        layout: &str,
314        offset: isize,
315        max_size: isize,
316        add_offset: usize,
317    ) -> Self {
318        let layout = std::ffi::CString::new(layout).unwrap();
319
320        unsafe {
321            EnzymeTypeTreeShiftIndiciesEq(
322                self.inner,
323                layout.as_ptr(),
324                offset as i64,
325                max_size as i64,
326                add_offset as u64,
327            );
328        }
329
330        self
331    }
332
333    pub(crate) fn insert(&mut self, indices: &[i64], ct: CConcreteType, ctx: &Context) {
334        unsafe {
335            EnzymeTypeTreeInsertEq(self.inner, indices.as_ptr(), indices.len(), ct, ctx);
336        }
337    }
338}
339
340impl Clone for TypeTree {
341    fn clone(&self) -> Self {
342        let inner = unsafe { EnzymeNewTypeTreeTR(self.inner) };
343        TypeTree { inner }
344    }
345}
346
347impl std::fmt::Display for TypeTree {
348    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
349        let ptr = unsafe { EnzymeTypeTreeToString(self.inner) };
350        let cstr = unsafe { std::ffi::CStr::from_ptr(ptr) };
351        match cstr.to_str() {
352            Ok(x) => write!(f, "{}", x)?,
353            Err(err) => write!(f, "could not parse: {}", err)?,
354        }
355
356        // delete C string pointer
357        unsafe {
358            EnzymeTypeTreeToStringFree(ptr);
359        }
360
361        Ok(())
362    }
363}
364
365impl std::fmt::Debug for TypeTree {
366    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
367        <Self as std::fmt::Display>::fmt(self, f)
368    }
369}
370
371impl Drop for TypeTree {
372    fn drop(&mut self) {
373        unsafe { EnzymeFreeTypeTree(self.inner) }
374    }
375}