px_llvm_codegen_utils_core/
lib.rs

1use std::ffi::CStr;
2use std::marker::PhantomData;
3use std::mem::{replace, take, MaybeUninit};
4use std::sync::{Arc, Mutex};
5use std::thread::LocalKey;
6use std::thread_local;
7
8use nonempty::NonEmpty;
9use typenum::Same;
10mod private {
11    pub trait Sealed {}
12}
13
14pub trait Ctx<'a>: Clone + private::Sealed + 'a {}
15pub trait Mod<'a>: Clone + private::Sealed + 'a {
16    type Ctx<'b>: Ctx<'b>
17    where
18        Self: 'b;
19    fn ctx<'b: 'a>(&'b self) -> Self::Ctx<'b>;
20    fn create_mod<'b, 'c, 'd>(a: &'b CStr, ctx: &'c Self::Ctx<'d>) -> Self
21    where
22        'a: 'b + 'c + 'd;
23}
24pub trait Value<'a>: Clone + private::Sealed + 'a {
25    type Tag: 'a;
26    type Kind: for<'b> ValueKind<Val<'a, Self::Tag> = Self, Mod<'b> = Self::Mod<'b>>;
27    type Mod<'b>: Mod<'b>;
28    fn r#mod<'b: 'a>(&'b self) -> Self::Mod<'b>;
29}
30pub trait ValueKind: private::Sealed {
31    type Mod<'a>: Mod<'a>;
32    type Val<'a, K: 'a>: for<'b> Value<'a, Tag = K, Kind = Self, Mod<'b> = Self::Mod<'b>>
33    where
34        K: 'a;
35    type Func<'a>: for<'b> Func<'a, Kind = Self, Mod<'b> = Self::Mod<'b>>;
36    type Ty<'a>: Ty<'a>;
37    fn const_int<'a>(ty: Self::Ty<'a>, n: u64, sext: bool) -> Self::Val<'a, Normal>;
38    fn function<'a, 'b, 'c, 'd: 'a + 'b + 'c>(
39        r#mod: Self::Mod<'a>,
40        name: &'b CStr,
41        ty: Self::Ty<'c>,
42    ) -> Self::Func<'d>;
43}
44pub trait Func<'a>: Clone + private::Sealed + Value<'a, Tag = FuncTag> + 'a {}
45pub trait BB<'a>: Clone + private::Sealed + 'a {
46    type Func<'b>: Func<'b>
47    where
48        'a: 'b,
49        Self: 'b;
50    fn new<'b, 'c>(f: Self::Func<'b>, name: &'c CStr) -> Self
51    where
52        'a: 'b + 'c;
53}
54macro_rules! rest {
55    ($llvm:ident as [$i:ident ($(($l:lifetime) @ $e:ident : $t:ty as |$v:ident|$b:expr),*)]) => {
56        $(let $e= match $e{$v => $b});*;
57        paste::paste!{
58
59        }
60    };
61}
62macro_rules! inst {
63    (($l2:lifetime)@ [$($a:tt)*] => $($b:tt)*) => {
64        inst!(($l2) @ $($a)* => $($b)* => [$($a)*]);
65    };
66    (($l2:lifetime)@ $i:ident ($(($l:lifetime) @ $e:ident : $t:ty as |$v:ident|$b:expr),*) =>  $($llvm:ident )? => $stuff:tt) => {
67        paste::paste!{
68            #[allow(unreachable_code,unused_variables)]
69            fn $i<'b,$($l),*,'res:  $($l + )* 'b>(&'b self, $($e: $t),*) -> <Self::ValKind<'a,'a> as ValueKind>::Val<'res,Normal> where $($l2 : $l),*{
70
71                let builder = |(),$($e : $t),*| -> std::convert::Infallible{
72                    panic!("abstract method used")
73                };
74                let ptr = ();
75                let leaked = |a: std::convert::Infallible,b: Normal| match a{};
76                let mark: Result<std::convert::Infallible,()> = Err(());
77                // macro_rules! shim{
78                //     () => {
79
80                //     };
81                // }
82                $(
83                    rest!($llvm as $stuff);
84                    let builder = $llvm::core::[<LLVMBuild $i >];
85                    let ptr = self.ptr();
86                    let leaked = |a,b|unsafe{crate::LLHandle::leaked(a,b)};
87                    let mark: Result<(),std::convert::Infallible> = Ok(());
88
89                    // shim!()
90                )?;
91
92                let res = unsafe{
93                    builder(ptr,$($e),*)
94                };
95                leaked(res,Normal)
96            }
97        }
98    };
99}
100macro_rules! insts {
101    (($l2:lifetime)@{[$($t0:tt)*], $([$($t:tt)*],)*} => $(<$llvm:ident>)?) => {
102        inst!(($l2)@[$($t0)*] => $($llvm)?);
103        insts!(($l2)@{$([$($t)*],)*} => $(<$llvm>)?);
104    };
105    (($l2:lifetime)@{} => $(<$llvm:ident>)?) => {
106
107    };
108}
109#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord, Debug)]
110#[non_exhaustive]
111pub enum ICmp {
112    Eq,
113    Lt,
114    Lts,
115}
116macro_rules! default_insts {
117    ($l2:lifetime @ $($llvm:ident)?) => {
118        insts!(($l2) @ {
119            [Alloca (('ty) @ ty: Self::Ty<'ty> as |x|x.ptr(), ('name) @ name : &'name CStr as |x|x.as_ptr())],
120            [Load2 (('ty) @ ty: Self::Ty<'ty> as |x|x.ptr(), ('ptr) @ pointer: <Self::ValKind<'a,'a> as ValueKind>::Val<'ptr,Normal> as |x|x.ptr(), ('name) @ name : &'name CStr as |x|x.as_ptr())],
121            [Store (('val) @ value: <Self::ValKind<'a,'a> as ValueKind>::Val<'val,Normal> as |x|x.ptr(), ('ptr) @ pointer: <Self::ValKind<'a,'a> as ValueKind>::Val<'ptr,Normal> as |x|x.ptr())],
122            [Add (('lhs) @ lhs: <Self::ValKind<'a,'a> as ValueKind>::Val<'lhs,Normal> as |x|x.ptr(), ('rhs) @ rhs: <Self::ValKind<'a,'a> as ValueKind>::Val<'rhs,Normal> as |x|x.ptr(), ('name) @ name : &'name CStr as |x|x.as_ptr())],
123            [And (('lhs) @ lhs: <Self::ValKind<'a,'a> as ValueKind>::Val<'lhs,Normal> as |x|x.ptr(), ('rhs) @ rhs: <Self::ValKind<'a,'a> as ValueKind>::Val<'rhs,Normal> as |x|x.ptr(), ('name) @ name : &'name CStr as |x|x.as_ptr())],
124            [Neg (('lhs) @ lhs: <Self::ValKind<'a,'a> as ValueKind>::Val<'lhs,Normal> as |x|x.ptr(),  ('name) @ name : &'name CStr as |x|x.as_ptr())],
125      [  Not (('lhs) @ lhs: <Self::ValKind<'a,'a> as ValueKind>::Val<'lhs,Normal> as |x|x.ptr(), ('name) @ name : &'name CStr as |x|x.as_ptr())],
126      [ TruncOrBitCast (('lhs) @ lhs: <Self::ValKind<'a,'a> as ValueKind>::Val<'lhs,Normal> as |x|x.ptr(),('ty) @ ty: Self::Ty<'ty> as |x|x.ptr(), ('name) @ name : &'name CStr as |x|x.as_ptr())],
127      [Mul (('lhs) @ lhs: <Self::ValKind<'a,'a> as ValueKind>::Val<'lhs,Normal> as |x|x.ptr(), ('rhs) @ rhs: <Self::ValKind<'a,'a> as ValueKind>::Val<'rhs,Normal> as |x|x.ptr(), ('name) @ name : &'name CStr as |x|x.as_ptr())],
128      [Or (('lhs) @ lhs: <Self::ValKind<'a,'a> as ValueKind>::Val<'lhs,Normal> as |x|x.ptr(), ('rhs) @ rhs: <Self::ValKind<'a,'a> as ValueKind>::Val<'rhs,Normal> as |x|x.ptr(), ('name) @ name : &'name CStr as |x|x.as_ptr())],
129     [ Sub (('lhs) @ lhs: <Self::ValKind<'a,'a> as ValueKind>::Val<'lhs,Normal> as |x|x.ptr(), ('rhs) @ rhs: <Self::ValKind<'a,'a> as ValueKind>::Val<'rhs,Normal> as |x|x.ptr(), ('name) @ name : &'name CStr as |x|x.as_ptr())],
130     [Xor (('lhs) @ lhs: <Self::ValKind<'a,'a> as ValueKind>::Val<'lhs,Normal> as |x|x.ptr(), ('rhs) @ rhs: <Self::ValKind<'a,'a> as ValueKind>::Val<'rhs,Normal> as |x|x.ptr(), ('name) @ name : &'name CStr as |x|x.as_ptr())],
131         [ICmp (('op) @ op: crate::ICmp as |a|a.into(),('lhs) @ lhs: <Self::ValKind<'a,'a> as ValueKind>::Val<'lhs,Normal> as |x|x.ptr(), ('rhs) @ rhs: <Self::ValKind<'a,'a> as ValueKind>::Val<'rhs,Normal> as |x|x.ptr(), ('name) @ name : &'name CStr as |x|x.as_ptr())],
132
133     [ Br (('dest) @ dest: Self::BB<'dest,'a,'a> as |x|x.ptr())],
134     [CondBr (('cond) @ r#if: <Self::ValKind<'a,'a> as ValueKind>::Val<'cond,Normal> as |x|x.ptr(), ('then) @ then: Self::BB<'then,'a,'a> as |x|x.ptr(),('e) @ r#else: Self::BB<'e,'a,'a> as |x|x.ptr())],
135        } => $(<$llvm>)?);
136    };
137}
138pub trait Ty<'a>: Clone + private::Sealed + 'a {
139    type Ctx<'b>: Ctx<'b>
140    where
141        Self: 'b;
142    fn int_ty(ctx: Self::Ctx<'a>, size: u32) -> Self;
143    fn ptr_ty(ctx: Self::Ctx<'a>, address_space: u32) -> Self;
144    fn fun_ty(self, params: impl Iterator<Item = Self>) -> Self;
145}
146pub trait Builder<'a>: Clone + private::Sealed + 'a {
147    type BB<'b, 'e, 'd>: BB<'b, Func<'b>: Value<'b, Kind = Self::ValKind<'e, 'd>>>
148    where
149        Self: 'b,
150        'a: 'b,
151        Self: 'e,
152        Self: 'd;
153    type ValKind<'d, 'b>: ValueKind<Ty<'d> = Self::Ty<'d>, Mod<'b> = Self::Mod<'b>>
154    where
155        Self: 'd,
156        Self: 'b;
157    // type InternalValShim<'b: 'a, 'd, 'e, K: 'b>: Value<'b, Tag = K>
158    //     + Same<Output = <Self::ValKind<'d, 'e> as ValueKind>::Val<'b, K>>
159    // where
160    //     Self: 'd,
161    //     Self: 'e;
162    // type Val<'b: 'a, K: 'b>: Value<'b, Tag = K>
163    //     + for<'d, 'e> Into<Self::InternalValShim<'b, 'd, 'e, K>>
164    //     + for<'d, 'e> From<Self::InternalValShim<'b, 'd, 'e, K>>;
165    // type Val<'b, K: 'b>: Value<'b, Tag = K>
166    //     + for<'d, 'e> Same<Output = <Self::ValKind<'d, 'e> as ValueKind>::Val<'b, K>>;
167    type Mod<'b>: Mod<'b, Ctx<'b> = Self::Ctx<'b>>
168    where
169        Self: 'b;
170    type Ty<'b>: Ty<'b>
171    where
172        Self: 'b;
173    type Ctx<'b>: Ctx<'b>
174    where
175        Self: 'b;
176    fn new_in_ctx(ctx: Self::Ctx<'a>) -> Self;
177    fn r#continue<'b, 'c>(&'b self, bb: Self::BB<'c, '_, '_>)
178    where
179        'a: 'b + 'c;
180    fn call<'b, 'c, 'd, 'e, 'f, 'h, 'i, 'g: 'a + 'b + 'c + 'd + 'e + 'f + 'h + 'i>(
181        &'b self,
182        resty: Self::Ty<'c>,
183        r#fn: <Self::ValKind<'_, '_> as ValueKind>::Val<'d, Normal>,
184        args: impl Iterator<Item = <Self::ValKind<'h, 'i> as ValueKind>::Val<'e, Normal>>,
185        name: &'f CStr,
186    ) -> <Self::ValKind<'_, '_> as ValueKind>::Val<'g, Normal>
187    where
188        Self: 'h + 'i;
189    default_insts!('a @ );
190}
191pub struct LLHandle<'a, K, T>(Arc<LLShim<'a, K, T>>);
192impl<'a, K, T> Clone for LLHandle<'a, K, T> {
193    fn clone(&self) -> Self {
194        Self(self.0.clone())
195    }
196}
197impl<'a, K, T> LLHandle<'a, K, T> {
198    pub unsafe fn from_raw_parts(ptr: *mut T, dropper: fn(*mut T, K), key: K) -> Self {
199        LLHandle(Arc::new(LLShim {
200            val: ptr,
201            dropper: dropper,
202            key: MaybeUninit::new(key),
203            phantom: PhantomData,
204        }))
205    }
206    pub unsafe fn leaked(ptr: *mut T, key: K) -> Self {
207        unsafe { Self::from_raw_parts(ptr, |_, _| {}, key) }
208    }
209    pub fn ptr(&self) -> *mut T {
210        return self.0.val;
211    }
212    pub fn key(&self) -> &K {
213        return unsafe { self.0.key.assume_init_ref() };
214    }
215}
216pub struct LLShim<'a, K, T> {
217    val: *mut T,
218    key: MaybeUninit<K>,
219    dropper: fn(*mut T, K),
220    phantom: PhantomData<&'a T>,
221}
222impl<'a, K, T> Drop for LLShim<'a, K, T> {
223    fn drop(&mut self) {
224        (self.dropper)(self.val, unsafe {
225            replace(&mut self.key, MaybeUninit::uninit()).assume_init()
226        })
227    }
228}
229macro_rules! seal {
230    ($(<$($generics:lifetime),*> => $t:ty),* $(,)?) => {
231        $(impl<$($generics),*> private::Sealed for $t{})*
232    };
233}
234pub struct Normal;
235pub struct FuncTag;
236macro_rules! impls {
237    ($l:ident {}) => {
238        const _: () = {
239            use $l as llvm_sys;
240            seal!(
241             <'a>  =>   crate::LLHandle<'a,Normal,llvm_sys::LLVMContext>,
242              <'a>  =>  crate::LLHandle<'a,Normal,llvm_sys::LLVMModule>,
243               <> =>  llvm_sys::LLVMValue,
244              <'a>  =>  crate::LLHandle<'a,Normal,llvm_sys::LLVMBasicBlock>,
245              <'a>  =>  crate::LLHandle<'a,Normal,llvm_sys::LLVMBuilder>,
246              <'a>  =>  crate::LLHandle<'a,Normal,llvm_sys::LLVMType>,
247            );
248            impl From<crate::ICmp> for llvm_sys::LLVMIntPredicate{
249                fn from(a: crate::ICmp) -> Self{
250                    match a{
251                        crate::ICmp::Eq => llvm_sys::LLVMIntPredicate::LLVMIntEQ,
252                        crate ::ICmp::Lt => llvm_sys::LLVMIntPredicate::LLVMIntULT,
253                        crate ::ICmp::Lts => llvm_sys::LLVMIntPredicate::LLVMIntSLT,
254                    }
255                }
256            }
257            impl<'a, K> private::Sealed for crate::LLHandle<'a, K, llvm_sys::LLVMValue> {}
258            impl<'a, K: 'a> crate::Value<'a> for crate::LLHandle<'a, K, llvm_sys::LLVMValue> {
259                type Tag = K;
260                type Kind = llvm_sys::LLVMValue;
261                type Mod<'b> = crate::LLHandle<'b, Normal, llvm_sys::LLVMModule>;
262                fn r#mod<'b: 'a>(&'b self) -> Self::Mod<'b> {
263                    let ptr = self.ptr();
264                    let ptr = unsafe { llvm_sys::core::LLVMGetGlobalParent(ptr) };
265                    unsafe { crate::LLHandle::leaked(ptr, Normal) }
266                }
267            }
268            impl<'a> crate::Ty<'a> for crate::LLHandle<'a, Normal, llvm_sys::LLVMType> {
269                type Ctx<'b>
270                    = crate::LLHandle<'b, Normal, llvm_sys::LLVMContext>
271                where
272                    Self: 'b;
273                fn int_ty(ctx: Self::Ctx<'a>, size: u32) -> Self {
274                    let ptr = ctx.ptr();
275                    let ptr = unsafe { llvm_sys::core::LLVMIntTypeInContext(ptr, size) };
276                    unsafe { LLHandle::leaked(ptr, Normal) }
277                }
278                fn ptr_ty(ctx: Self::Ctx<'a>, address_space: u32) -> Self {
279                    let ptr = ctx.ptr();
280                    let ptr =
281                        unsafe { llvm_sys::core::LLVMPointerTypeInContext(ptr, address_space) };
282                    unsafe { LLHandle::leaked(ptr, Normal) }
283                }
284                fn fun_ty(self, params: impl Iterator<Item = Self>) -> Self {
285                    let ptr = self.ptr();
286                    let mut args = params.map(|p| p.ptr()).collect::<Vec<_>>();
287                    let ptr = unsafe {
288                        llvm_sys::core::LLVMFunctionType(
289                            ptr,
290                            args.as_mut_ptr(),
291                            args.len().try_into().unwrap(),
292                            0,
293                        )
294                    };
295                    unsafe { LLHandle::leaked(ptr, Normal) }
296                }
297            }
298            impl crate::ValueKind for llvm_sys::LLVMValue {
299                type Val<'a, K: 'a> = crate::LLHandle<'a, K, llvm_sys::LLVMValue>;
300                type Mod<'a> = crate::LLHandle<'a, Normal, llvm_sys::LLVMModule>;
301                type Func<'a> = crate::LLHandle<'a, FuncTag, llvm_sys::LLVMValue>;
302                type Ty<'a> = crate::LLHandle<'a, Normal, llvm_sys::LLVMType>;
303                fn const_int<'a>(ty: Self::Ty<'a>, n: u64, sext: bool) -> Self::Val<'a, Normal> {
304                    let ptr = ty.ptr();
305                    let ptr =
306                        unsafe { llvm_sys::core::LLVMConstInt(ptr, n, if sext { 1 } else { 0 }) };
307                    unsafe { crate::LLHandle::leaked(ptr, Normal) }
308                }
309                fn function<'a, 'b, 'c, 'd: 'a + 'b + 'c>(
310                    r#mod: Self::Mod<'a>,
311                    name: &'b CStr,
312                    ty: Self::Ty<'c>,
313                ) -> Self::Func<'d> {
314                    let ptr = unsafe {
315                        llvm_sys::core::LLVMAddFunction(r#mod.ptr(), name.as_ptr(), ty.ptr())
316                    };
317                    unsafe { crate::LLHandle::leaked(ptr, FuncTag) }
318                }
319            }
320            impl<'a> crate::Ctx<'a> for crate::LLHandle<'a, Normal, llvm_sys::LLVMContext> {}
321            impl<'a> crate::Mod<'a> for crate::LLHandle<'a, Normal, llvm_sys::LLVMModule> {
322                type Ctx<'b>
323                    = crate::LLHandle<'b, Normal, llvm_sys::LLVMContext>
324                where
325                    Self: 'b;
326                fn ctx<'b: 'a>(&'b self) -> Self::Ctx<'b> {
327                    let ptr = self.ptr();
328                    let ptr = unsafe { llvm_sys::core::LLVMGetModuleContext(ptr) };
329                    unsafe { crate::LLHandle::leaked(ptr, Normal) }
330                }
331                fn create_mod<'b, 'c, 'd>(a: &'b CStr, ctx: &'c Self::Ctx<'d>) -> Self
332                where
333                    'a: 'b + 'c + 'd,
334                {
335                    let ptr = ctx.ptr();
336                    let ptr = unsafe {
337                        llvm_sys::core::LLVMModuleCreateWithNameInContext(a.as_ptr(), ptr)
338                    };
339                    unsafe {
340                        crate::LLHandle::from_raw_parts(
341                            ptr,
342                            |a, _| llvm_sys::core::LLVMDisposeModule(a),
343                            Normal,
344                        )
345                    }
346                }
347            }
348            impl<'a> crate::Func<'a> for crate::LLHandle<'a, FuncTag, llvm_sys::LLVMValue> {}
349            impl<'a> crate::BB<'a> for crate::LLHandle<'a, Normal, llvm_sys::LLVMBasicBlock> {
350                type Func<'b>
351                    = crate::LLHandle<'b, FuncTag, llvm_sys::LLVMValue>
352                where
353                    'a: 'b,
354                    Self: 'b;
355                fn new<'b, 'c>(f: Self::Func<'b>, name: &'c CStr) -> Self
356                where
357                    'a: 'b + 'c,
358                {
359                    let ptr = f.ptr();
360                    let ptr = unsafe { llvm_sys::core::LLVMAppendBasicBlock(ptr, name.as_ptr()) };
361                    unsafe { crate::LLHandle::leaked(ptr, Normal) }
362                }
363            }
364            impl<'a> crate::Builder<'a> for crate::LLHandle<'a, Normal, llvm_sys::LLVMBuilder> {
365                type BB<'b,'e,'d>
366                    = crate::LLHandle<'b, Normal, llvm_sys::LLVMBasicBlock>
367                where
368                    Self: 'b,
369                    'a: 'b, Self: 'e, Self: 'd;
370                type ValKind<'d, 'b> = llvm_sys::LLVMValue  where
371                Self: 'd,
372                Self: 'b;
373                // type InternalValShim<'b: 'a, 'd, 'e, K: 'b> = crate::LLHandle<'b,K,llvm_sys::LLVMValue> where K: Sized, K: 'b, Self: 'd, Self: 'e;
374                // type Val<'b: 'a,K: 'b> = crate::LLHandle<'b,K,llvm_sys::LLVMValue> where K: Sized, K: 'b;
375                type Ty<'b>
376                    = crate::LLHandle<'b, Normal, llvm_sys::LLVMType>
377                where
378                    Self: 'b;
379                type Ctx<'b>
380                    = crate::LLHandle<'b, Normal, llvm_sys::LLVMContext>
381                where
382                    Self: 'b;
383                type Mod<'b> = crate::LLHandle<'b, Normal, llvm_sys::LLVMModule> where Self: 'b;
384                fn new_in_ctx(ctx: Self::Ctx<'a>) -> Self {
385                    let ptr = ctx.ptr();
386                    let ptr = unsafe { llvm_sys::core::LLVMCreateBuilderInContext(ptr) };
387                    unsafe {
388                        crate::LLHandle::from_raw_parts(
389                            ptr,
390                            |a, _| llvm_sys::core::LLVMDisposeBuilder(a),
391                            Normal,
392                        )
393                    }
394                }
395                fn r#continue<'b, 'c>(&'b self, bb: Self::BB<'c,'a,'a>)
396                where
397                    'a: 'b + 'c,
398                {
399                    unsafe { llvm_sys::core::LLVMPositionBuilderAtEnd(self.ptr(), bb.ptr()) }
400                }
401                fn call<'b, 'c, 'd, 'e, 'f,'h,'i, 'g: 'a + 'b + 'c + 'd + 'e + 'f + 'h + 'i>(
402                    &'b self,
403                    resty: Self::Ty<'c>,
404                    r#fn: <Self::ValKind<'a,'a> as ValueKind>::Val<'d, Normal>,
405                    args: impl Iterator<Item = <Self::ValKind<'h,'i> as ValueKind>::Val<'e, Normal>>,
406                    name: &'f CStr,
407                ) -> <Self::ValKind<'_,'_> as ValueKind>::Val<'g, Normal> where 'a: 'h + 'i, Self: 'c{
408                    let ptr = self.ptr();
409                    let resty = resty.ptr();
410                    let Fn = r#fn.ptr();
411                    let mut args = args.map(|a| a.ptr()).collect::<Vec<_>>();
412                    let res = unsafe {
413                        llvm_sys::core::LLVMBuildCall2(
414                            ptr,
415                            resty,
416                            Fn,
417                            args.as_mut_ptr(),
418                            args.len().try_into().unwrap(),
419                            name.as_ptr(),
420                        )
421                    };
422                    unsafe { crate::LLHandle::leaked(res, Normal) }
423                }
424                default_insts!('a @ llvm_sys);
425            }
426        };
427    };
428}
429
430llvm_codegen_utils_version_macros::vers!({} impls);