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 $(
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 )?;
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 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 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);