1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 // Copyright 2018 Jacob Lifshay
4 //! types in backend IR
7 use std::cell::UnsafeCell;
10 use std::marker::PhantomData;
11 use std::ops::{Deref, DerefMut};
12 use std::ptr::NonNull;
15 macro_rules! buildable_struct_helper {
18 $($member_name:ident: $member_type:ty,)*
21 impl $crate::backend::types::BuildableType for $name {
22 fn build<'a, Ty: $crate::backend::types::Type<'a>, TB: $crate::backend::types::TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
23 type_builder.build_struct(&[$(<$member_type as $crate::backend::types::BuildableType>::build(type_builder),)*])
27 impl $crate::backend::types::BuildableStruct for $name {
29 ) -> &'static [$crate::backend::types::BuildableStructMemberDescriptor] {
30 #[allow(dead_code, non_camel_case_types)]
36 const MEMBERS: &'static [$crate::backend::types::BuildableStructMemberDescriptor] = &[
37 $($crate::backend::types::BuildableStructMemberDescriptor {
38 name: stringify!($member_name),
39 index: MemberIndices::$member_name as usize,
49 macro_rules! buildable_struct {
51 $(#[derive($derives:ident)])*
52 pub struct $name:ident {
53 $($member_name:ident: $member_type:ty,)*
56 $(#[derive($derives)])*
59 $($member_name: $member_type,)*
62 buildable_struct_helper!{
64 $($member_name: $member_type,)*
69 $(#[derive($derives:ident)])*
71 $($member_name:ident: $member_type:ty,)*
74 $(#[derive($derives)])*
77 $($member_name: $member_type,)*
80 buildable_struct_helper!{
82 $($member_name: $member_type,)*
88 /// length of a vector
89 pub enum VectorLength {
90 /// fixed length vector
92 /// length in elements
95 /// variable length vector
97 /// base length in elements which the runtime vector length is a multiple of
102 /// equivalent to LLVM's 'Type'
103 pub trait Type<'a>: Clone + Eq + Hash + Debug {
104 /// the `Context` type
105 type Context: Context<'a>;
108 /// trait for building types
109 pub trait TypeBuilder<'a, Ty: Type<'a>> {
110 /// build a `bool` type
111 fn build_bool(&self) -> Ty;
112 /// build an 8-bit sign-agnostic integer type
113 fn build_i8(&self) -> Ty;
114 /// build an 16-bit sign-agnostic integer type
115 fn build_i16(&self) -> Ty;
116 /// build an 32-bit sign-agnostic integer type
117 fn build_i32(&self) -> Ty;
118 /// build an 64-bit sign-agnostic integer type
119 fn build_i64(&self) -> Ty;
120 /// build an 32-bit IEEE 754 floating-point type
121 fn build_f32(&self) -> Ty;
122 /// build an 64-bit IEEE 754 floating-point type
123 fn build_f64(&self) -> Ty;
125 fn build_pointer(&self, target: Ty) -> Ty;
127 fn build_array(&self, element: Ty, count: usize) -> Ty;
129 fn build_vector(&self, element: Ty, length: VectorLength) -> Ty;
131 fn build_struct(&self, members: &[Ty]) -> Ty;
132 /// build a function type
133 fn build_function(&self, arguments: &[Ty], return_type: Option<Ty>) -> Ty;
135 fn build<T: BuildableType>(&self) -> Ty
143 impl<'a, 'b, Ty: Type<'a>> TypeBuilder<'a, Ty> for &'b TypeBuilder<'a, Ty> {
144 fn build_bool(&self) -> Ty {
147 fn build_i8(&self) -> Ty {
150 fn build_i16(&self) -> Ty {
153 fn build_i32(&self) -> Ty {
156 fn build_i64(&self) -> Ty {
159 fn build_f32(&self) -> Ty {
162 fn build_f64(&self) -> Ty {
165 fn build_pointer(&self, target: Ty) -> Ty {
166 (*self).build_pointer(target)
168 fn build_array(&self, element: Ty, count: usize) -> Ty {
169 (*self).build_array(element, count)
171 fn build_vector(&self, element: Ty, length: VectorLength) -> Ty {
172 (*self).build_vector(element, length)
174 fn build_struct(&self, members: &[Ty]) -> Ty {
175 (*self).build_struct(members)
177 fn build_function(&self, arguments: &[Ty], return_type: Option<Ty>) -> Ty {
178 (*self).build_function(arguments, return_type)
182 /// trait for rust types that can be built using `TypeBuilder`
183 pub trait BuildableType {
184 /// build the type represented by `Self`
185 fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty;
188 impl<T: BuildableType> BuildableType for UnsafeCell<T> {
189 fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
190 T::build(type_builder)
195 pub trait ScalarBuildableTypeBase {}
198 impl<T: hidden::ScalarBuildableTypeBase> hidden::ScalarBuildableTypeBase for UnsafeCell<T> {}
200 /// trait for rust types that can be an element of a vector and be built using `TypeBuilder`
201 pub trait ScalarBuildableType: BuildableType + hidden::ScalarBuildableTypeBase {}
203 impl<T: ScalarBuildableType> ScalarBuildableType for UnsafeCell<T> {}
205 /// descriptor for members of types implementing `BuildableStruct`
206 pub struct BuildableStructMemberDescriptor {
208 pub name: &'static str,
213 /// trait for structs that can be built using TypeBuilder
214 /// implementing types are usually created using `buildable_struct!`
215 pub trait BuildableStruct: BuildableType {
216 /// get the list of members for `Self`
217 fn get_members() -> &'static [BuildableStructMemberDescriptor];
218 /// get the member for `Self` that is named `name`
219 fn get_member_by_name(name: &str) -> &'static BuildableStructMemberDescriptor {
220 for member in Self::get_members() {
221 if name == member.name {
225 unreachable!("{} is not a member", name);
229 macro_rules! build_basic_scalar {
230 ($type:ty, $build_fn:ident) => {
231 impl BuildableType for $type {
232 fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
233 type_builder.$build_fn()
237 impl hidden::ScalarBuildableTypeBase for $type {}
239 impl ScalarBuildableType for $type {}
243 build_basic_scalar!(bool, build_bool);
244 build_basic_scalar!(u8, build_i8);
245 build_basic_scalar!(i8, build_i8);
246 build_basic_scalar!(u16, build_i16);
247 build_basic_scalar!(i16, build_i16);
248 build_basic_scalar!(u32, build_i32);
249 build_basic_scalar!(i32, build_i32);
250 build_basic_scalar!(u64, build_i64);
251 build_basic_scalar!(i64, build_i64);
252 build_basic_scalar!(f32, build_f32);
253 build_basic_scalar!(f64, build_f64);
255 impl<'b, T: BuildableType> BuildableType for Option<&'b T> {
256 fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
257 type_builder.build_pointer(T::build(type_builder))
261 impl<'b, T: BuildableType> hidden::ScalarBuildableTypeBase for Option<&'b T> {}
263 impl<'b, T: BuildableType> ScalarBuildableType for Option<&'b T> {}
265 impl<'b, T: BuildableType> BuildableType for Option<&'b mut T> {
266 fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
267 type_builder.build_pointer(T::build(type_builder))
271 impl<'b, T: BuildableType> hidden::ScalarBuildableTypeBase for Option<&'b mut T> {}
273 impl<'b, T: BuildableType> ScalarBuildableType for Option<&'b mut T> {}
275 impl<'b, T: BuildableType> BuildableType for &'b T {
276 fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
277 type_builder.build_pointer(T::build(type_builder))
281 impl<'b, T: BuildableType> hidden::ScalarBuildableTypeBase for &'b T {}
283 impl<'b, T: BuildableType> ScalarBuildableType for &'b T {}
285 impl<'b, T: BuildableType> BuildableType for &'b mut T {
286 fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
287 type_builder.build_pointer(T::build(type_builder))
291 impl<'b, T: BuildableType> hidden::ScalarBuildableTypeBase for &'b mut T {}
293 impl<'b, T: BuildableType> ScalarBuildableType for &'b mut T {}
295 impl<T: BuildableType> BuildableType for *mut T {
296 fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
297 type_builder.build_pointer(T::build(type_builder))
301 impl<'b, T: BuildableType> hidden::ScalarBuildableTypeBase for *mut T {}
303 impl<'b, T: BuildableType> ScalarBuildableType for *mut T {}
305 impl<T: BuildableType> BuildableType for *const T {
306 fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
307 type_builder.build_pointer(T::build(type_builder))
311 impl<'b, T: BuildableType> hidden::ScalarBuildableTypeBase for *const T {}
313 impl<'b, T: BuildableType> ScalarBuildableType for *const T {}
315 impl<T: BuildableType> BuildableType for NonNull<T> {
316 fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
317 type_builder.build_pointer(T::build(type_builder))
321 impl<'b, T: BuildableType> hidden::ScalarBuildableTypeBase for NonNull<T> {}
323 impl<'b, T: BuildableType> ScalarBuildableType for NonNull<T> {}
325 impl<T: BuildableType> BuildableType for Option<NonNull<T>> {
326 fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
327 type_builder.build_pointer(T::build(type_builder))
331 impl<'b, T: BuildableType> hidden::ScalarBuildableTypeBase for Option<NonNull<T>> {}
333 impl<'b, T: BuildableType> ScalarBuildableType for Option<NonNull<T>> {}
335 macro_rules! build_unit_function_type {
336 ($($arguments:ident,)*) => {
337 impl<$($arguments: BuildableType),*> BuildableType for Option<unsafe extern "C" fn($($arguments,)*)> {
338 fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
339 type_builder.build_function(&[$($arguments::build(type_builder),)*], None)
343 impl<$($arguments: BuildableType),*> hidden::ScalarBuildableTypeBase for Option<unsafe extern "C" fn($($arguments,)*)> {}
345 impl<$($arguments: BuildableType),*> ScalarBuildableType for Option<unsafe extern "C" fn($($arguments,)*)> {}
347 impl<$($arguments: BuildableType),*> BuildableType for unsafe extern "C" fn($($arguments,)*) {
348 fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
349 type_builder.build_function(&[$($arguments::build(type_builder),)*], None)
353 impl<$($arguments: BuildableType),*> hidden::ScalarBuildableTypeBase for unsafe extern "C" fn($($arguments,)*) {}
355 impl<$($arguments: BuildableType),*> ScalarBuildableType for unsafe extern "C" fn($($arguments,)*) {}
359 macro_rules! build_function_type {
360 ($($arguments:ident,)*) => {
361 impl<R: BuildableType, $($arguments: BuildableType),*> BuildableType for Option<unsafe extern "C" fn($($arguments,)*) -> R> {
362 fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
363 type_builder.build_function(&[$($arguments::build(type_builder),)*], Some(R::build(type_builder)))
367 impl<R: BuildableType, $($arguments: BuildableType),*> hidden::ScalarBuildableTypeBase for Option<unsafe extern "C" fn($($arguments,)*) -> R> {}
369 impl<R: BuildableType, $($arguments: BuildableType),*> ScalarBuildableType for Option<unsafe extern "C" fn($($arguments,)*) -> R> {}
371 impl<R: BuildableType, $($arguments: BuildableType),*> BuildableType for unsafe extern "C" fn($($arguments,)*) -> R {
372 fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
373 type_builder.build_function(&[$($arguments::build(type_builder),)*], Some(R::build(type_builder)))
377 impl<R: BuildableType, $($arguments: BuildableType),*> hidden::ScalarBuildableTypeBase for unsafe extern "C" fn($($arguments,)*) -> R {}
379 impl<R: BuildableType, $($arguments: BuildableType),*> ScalarBuildableType for unsafe extern "C" fn($($arguments,)*) -> R {}
384 macro_rules! build_function_types {
386 build_unit_function_type!();
387 build_function_type!();
389 ($first_argument:ident, $($arguments:ident,)*) => {
390 build_unit_function_type!($first_argument, $($arguments,)*);
391 build_function_type!($first_argument, $($arguments,)*);
392 build_function_types!($($arguments,)*);
396 build_function_types!(
397 T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19,
400 macro_rules! build_array0 {
402 impl<T: BuildableType> BuildableType for [T; $length + 1] {
403 fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
404 type_builder.build_array(T::build(type_builder), $length + 1)
410 macro_rules! build_array1 {
412 build_array0!($length * 2);
413 build_array0!($length * 2 + 1);
417 macro_rules! build_array2 {
419 build_array1!($length * 2);
420 build_array1!($length * 2 + 1);
424 macro_rules! build_array3 {
426 build_array2!($length * 2);
427 build_array2!($length * 2 + 1);
431 macro_rules! build_array4 {
433 build_array3!($length * 2);
434 build_array3!($length * 2 + 1);
438 macro_rules! build_array5 {
440 build_array4!($length * 2);
441 build_array4!($length * 2 + 1);
448 /// buildable vector types
449 pub trait Vector: BuildableType {
451 type Element: ScalarBuildableType;
453 const LENGTH: VectorLength;
457 pub enum __VectorNeverType {}
459 macro_rules! build_fixed_vector {
460 ($name:ident, $length:expr) => {
461 /// Vector of elements `Element`
462 #[derive(Copy, Clone)]
463 pub struct $name<Element: ScalarBuildableType> {
464 /// elements of the vector `Self`
465 pub elements: [Element; $length],
468 impl<Element: ScalarBuildableType> Deref for $name<Element> {
469 type Target = [Element; $length];
470 fn deref(&self) -> &Self::Target {
475 impl<Element: ScalarBuildableType> DerefMut for $name<Element> {
476 fn deref_mut(&mut self) -> &mut Self::Target {
481 impl<Element: ScalarBuildableType> BuildableType for $name<Element> {
482 fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
483 type_builder.build_vector(Element::build(type_builder), Self::LENGTH)
487 impl<Element: ScalarBuildableType> Vector for $name<Element> {
488 type Element = Element;
489 const LENGTH: VectorLength = { VectorLength::Fixed { length: $length } };
494 macro_rules! build_variable_vector {
495 ($name:ident, $base_length:expr) => {
496 /// Vector of elements `Element`
497 pub enum $name<Element: ScalarBuildableType> {
499 __Dummy(__VectorNeverType, PhantomData<Element>),
502 impl<Element: ScalarBuildableType> BuildableType for $name<Element> {
503 fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
504 type_builder.build_vector(Element::build(type_builder), Self::LENGTH)
508 impl<Element: ScalarBuildableType> Vector for $name<Element> {
509 type Element = Element;
510 const LENGTH: VectorLength = {
511 VectorLength::Variable {
512 base_length: $base_length,
519 /// alternate name for `VecNx1`
520 pub type VecN<Element> = VecNx1<Element>;
522 build_fixed_vector!(Vec1, 1);
523 build_fixed_vector!(Vec2, 2);
524 build_fixed_vector!(Vec3, 3);
525 build_fixed_vector!(Vec4, 4);
526 build_fixed_vector!(Vec5, 5);
527 build_fixed_vector!(Vec6, 6);
528 build_fixed_vector!(Vec7, 7);
529 build_fixed_vector!(Vec8, 8);
530 build_fixed_vector!(Vec9, 9);
531 build_fixed_vector!(Vec10, 10);
532 build_fixed_vector!(Vec11, 11);
533 build_fixed_vector!(Vec12, 12);
534 build_fixed_vector!(Vec13, 13);
535 build_fixed_vector!(Vec14, 14);
536 build_fixed_vector!(Vec15, 15);
537 build_fixed_vector!(Vec16, 16);
538 build_variable_vector!(VecNx1, 1);
539 build_variable_vector!(VecNx2, 2);
540 build_variable_vector!(VecNx3, 3);
541 build_variable_vector!(VecNx4, 4);
542 build_variable_vector!(VecNx5, 5);
543 build_variable_vector!(VecNx6, 6);
544 build_variable_vector!(VecNx7, 7);
545 build_variable_vector!(VecNx8, 8);
546 build_variable_vector!(VecNx9, 9);
547 build_variable_vector!(VecNx10, 10);
548 build_variable_vector!(VecNx11, 11);
549 build_variable_vector!(VecNx12, 12);
550 build_variable_vector!(VecNx13, 13);
551 build_variable_vector!(VecNx14, 14);
552 build_variable_vector!(VecNx15, 15);
553 build_variable_vector!(VecNx16, 16);