working on compiler; need to add CFG and cross-lane behavior passes
[kazan.git] / shader-compiler-backend / src / types.rs
1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 // Copyright 2018 Jacob Lifshay
3
4 //! types in backend IR
5
6 use super::Context;
7 use std::cell::UnsafeCell;
8 use std::fmt::Debug;
9 use std::hash::Hash;
10 use std::marker::PhantomData;
11 use std::ops::{Deref, DerefMut};
12 use std::ptr::NonNull;
13
14 #[macro_export]
15 macro_rules! buildable_struct_helper {
16 {
17 struct $name:ident {
18 $($member_name:ident: $member_type:ty,)*
19 }
20 } => {
21 impl $crate::types::BuildableType for $name {
22 fn build<'a, Ty: $crate::types::Type<'a>, TB: $crate::types::TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
23 type_builder.build_struct(&[$(<$member_type as $crate::types::BuildableType>::build(type_builder),)*])
24 }
25 }
26
27 impl $crate::types::BuildableStruct for $name {
28 fn get_members(
29 ) -> &'static [$crate::types::BuildableStructMemberDescriptor] {
30 #[allow(dead_code, non_camel_case_types)]
31 #[repr(usize)]
32 enum MemberIndices {
33 $($member_name,)*
34 __Last,
35 }
36 const MEMBERS: &'static [$crate::types::BuildableStructMemberDescriptor] = &[
37 $($crate::types::BuildableStructMemberDescriptor {
38 name: stringify!($member_name),
39 index: MemberIndices::$member_name as usize,
40 },)*
41 ];
42 MEMBERS
43 }
44 }
45 }
46 }
47
48 #[macro_export]
49 macro_rules! buildable_struct {
50 {
51 $(#[derive($derives:ident)])*
52 pub struct $name:ident {
53 $($member_name:ident: $member_type:ty,)*
54 }
55 } => {
56 $(#[derive($derives)])*
57 #[repr(C)]
58 pub struct $name {
59 $($member_name: $member_type,)*
60 }
61
62 buildable_struct_helper!{
63 struct $name {
64 $($member_name: $member_type,)*
65 }
66 }
67 };
68 {
69 $(#[derive($derives:ident)])*
70 struct $name:ident {
71 $($member_name:ident: $member_type:ty,)*
72 }
73 } => {
74 $(#[derive($derives)])*
75 #[repr(C)]
76 struct $name {
77 $($member_name: $member_type,)*
78 }
79
80 buildable_struct_helper!{
81 struct $name {
82 $($member_name: $member_type,)*
83 }
84 }
85 };
86 }
87
88 /// length of a vector
89 pub enum VectorLength {
90 /// fixed length vector
91 Fixed {
92 /// length in elements
93 length: u32,
94 },
95 /// variable length vector
96 Variable {
97 /// base length in elements which the runtime vector length is a multiple of
98 base_length: u32,
99 },
100 }
101
102 /// equivalent to LLVM's 'Type'
103 pub trait Type<'a>: Clone + Eq + Hash + Debug {
104 /// the `Context` type
105 type Context: Context<'a>;
106 }
107
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 2's complement integer type
113 fn build_i8(&self) -> Ty;
114 /// build an 16-bit 2's complement integer type
115 fn build_i16(&self) -> Ty;
116 /// build an 32-bit 2's complement integer type
117 fn build_i32(&self) -> Ty;
118 /// build an 64-bit 2's complement integer type
119 fn build_i64(&self) -> Ty;
120 /// build an 8-bit unsigned integer type
121 fn build_u8(&self) -> Ty;
122 /// build an 16-bit unsigned integer type
123 fn build_u16(&self) -> Ty;
124 /// build an 32-bit unsigned integer type
125 fn build_u32(&self) -> Ty;
126 /// build an 64-bit unsigned integer type
127 fn build_u64(&self) -> Ty;
128 /// build an 32-bit IEEE 754 floating-point type
129 fn build_f32(&self) -> Ty;
130 /// build an 64-bit IEEE 754 floating-point type
131 fn build_f64(&self) -> Ty;
132 /// build a pointer
133 fn build_pointer(&self, target: Ty) -> Ty;
134 /// build an array
135 fn build_array(&self, element: Ty, count: usize) -> Ty;
136 /// build a vector
137 fn build_vector(&self, element: Ty, length: VectorLength) -> Ty;
138 /// build a struct
139 fn build_struct(&self, members: &[Ty]) -> Ty;
140 /// build a function type
141 fn build_function(&self, arguments: &[Ty], return_type: Option<Ty>) -> Ty;
142 /// build a type
143 fn build<T: BuildableType>(&self) -> Ty
144 where
145 Self: Sized,
146 {
147 T::build(self)
148 }
149 }
150
151 impl<'a, 'b, Ty: Type<'a>> TypeBuilder<'a, Ty> for &'b TypeBuilder<'a, Ty> {
152 fn build_bool(&self) -> Ty {
153 (*self).build_bool()
154 }
155 fn build_i8(&self) -> Ty {
156 (*self).build_i8()
157 }
158 fn build_i16(&self) -> Ty {
159 (*self).build_i16()
160 }
161 fn build_i32(&self) -> Ty {
162 (*self).build_i32()
163 }
164 fn build_i64(&self) -> Ty {
165 (*self).build_i64()
166 }
167 fn build_u8(&self) -> Ty {
168 (*self).build_u8()
169 }
170 fn build_u16(&self) -> Ty {
171 (*self).build_u16()
172 }
173 fn build_u32(&self) -> Ty {
174 (*self).build_u32()
175 }
176 fn build_u64(&self) -> Ty {
177 (*self).build_u64()
178 }
179 fn build_f32(&self) -> Ty {
180 (*self).build_f32()
181 }
182 fn build_f64(&self) -> Ty {
183 (*self).build_f64()
184 }
185 fn build_pointer(&self, target: Ty) -> Ty {
186 (*self).build_pointer(target)
187 }
188 fn build_array(&self, element: Ty, count: usize) -> Ty {
189 (*self).build_array(element, count)
190 }
191 fn build_vector(&self, element: Ty, length: VectorLength) -> Ty {
192 (*self).build_vector(element, length)
193 }
194 fn build_struct(&self, members: &[Ty]) -> Ty {
195 (*self).build_struct(members)
196 }
197 fn build_function(&self, arguments: &[Ty], return_type: Option<Ty>) -> Ty {
198 (*self).build_function(arguments, return_type)
199 }
200 }
201
202 /// trait for rust types that can be built using `TypeBuilder`
203 pub trait BuildableType {
204 /// build the type represented by `Self`
205 fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty;
206 }
207
208 impl<T: BuildableType> BuildableType for UnsafeCell<T> {
209 fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
210 T::build(type_builder)
211 }
212 }
213
214 mod hidden {
215 pub trait ScalarBuildableTypeBase {}
216 }
217
218 impl<T: hidden::ScalarBuildableTypeBase> hidden::ScalarBuildableTypeBase for UnsafeCell<T> {}
219
220 /// trait for rust types that can be an element of a vector and be built using `TypeBuilder`
221 pub trait ScalarBuildableType: BuildableType + hidden::ScalarBuildableTypeBase {}
222
223 impl<T: ScalarBuildableType> ScalarBuildableType for UnsafeCell<T> {}
224
225 /// descriptor for members of types implementing `BuildableStruct`
226 pub struct BuildableStructMemberDescriptor {
227 /// name of member
228 pub name: &'static str,
229 /// index of member
230 pub index: usize,
231 }
232
233 /// trait for structs that can be built using TypeBuilder
234 /// implementing types are usually created using `buildable_struct!`
235 pub trait BuildableStruct: BuildableType {
236 /// get the list of members for `Self`
237 fn get_members() -> &'static [BuildableStructMemberDescriptor];
238 /// get the member for `Self` that is named `name`
239 fn get_member_by_name(name: &str) -> &'static BuildableStructMemberDescriptor {
240 for member in Self::get_members() {
241 if name == member.name {
242 return member;
243 }
244 }
245 unreachable!("{} is not a member", name);
246 }
247 }
248
249 macro_rules! build_basic_scalar {
250 ($type:ty, $build_fn:ident) => {
251 impl BuildableType for $type {
252 fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
253 type_builder.$build_fn()
254 }
255 }
256
257 impl hidden::ScalarBuildableTypeBase for $type {}
258
259 impl ScalarBuildableType for $type {}
260 };
261 }
262
263 build_basic_scalar!(bool, build_bool);
264 build_basic_scalar!(u8, build_u8);
265 build_basic_scalar!(i8, build_i8);
266 build_basic_scalar!(u16, build_u16);
267 build_basic_scalar!(i16, build_i16);
268 build_basic_scalar!(u32, build_u32);
269 build_basic_scalar!(i32, build_i32);
270 build_basic_scalar!(u64, build_u64);
271 build_basic_scalar!(i64, build_i64);
272 build_basic_scalar!(f32, build_f32);
273 build_basic_scalar!(f64, build_f64);
274
275 impl<'b, T: BuildableType> BuildableType for Option<&'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))
278 }
279 }
280
281 impl<'b, T: BuildableType> hidden::ScalarBuildableTypeBase for Option<&'b T> {}
282
283 impl<'b, T: BuildableType> ScalarBuildableType for Option<&'b T> {}
284
285 impl<'b, T: BuildableType> BuildableType for Option<&'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))
288 }
289 }
290
291 impl<'b, T: BuildableType> hidden::ScalarBuildableTypeBase for Option<&'b mut T> {}
292
293 impl<'b, T: BuildableType> ScalarBuildableType for Option<&'b mut T> {}
294
295 impl<'b, T: BuildableType> BuildableType for &'b 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))
298 }
299 }
300
301 impl<'b, T: BuildableType> hidden::ScalarBuildableTypeBase for &'b T {}
302
303 impl<'b, T: BuildableType> ScalarBuildableType for &'b T {}
304
305 impl<'b, T: BuildableType> BuildableType for &'b mut 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))
308 }
309 }
310
311 impl<'b, T: BuildableType> hidden::ScalarBuildableTypeBase for &'b mut T {}
312
313 impl<'b, T: BuildableType> ScalarBuildableType for &'b mut T {}
314
315 impl<T: BuildableType> BuildableType for *mut 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))
318 }
319 }
320
321 impl<'b, T: BuildableType> hidden::ScalarBuildableTypeBase for *mut T {}
322
323 impl<'b, T: BuildableType> ScalarBuildableType for *mut T {}
324
325 impl<T: BuildableType> BuildableType for *const 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))
328 }
329 }
330
331 impl<'b, T: BuildableType> hidden::ScalarBuildableTypeBase for *const T {}
332
333 impl<'b, T: BuildableType> ScalarBuildableType for *const T {}
334
335 impl<T: BuildableType> BuildableType for NonNull<T> {
336 fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
337 type_builder.build_pointer(T::build(type_builder))
338 }
339 }
340
341 impl<'b, T: BuildableType> hidden::ScalarBuildableTypeBase for NonNull<T> {}
342
343 impl<'b, T: BuildableType> ScalarBuildableType for NonNull<T> {}
344
345 impl<T: BuildableType> BuildableType for Option<NonNull<T>> {
346 fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
347 type_builder.build_pointer(T::build(type_builder))
348 }
349 }
350
351 impl<'b, T: BuildableType> hidden::ScalarBuildableTypeBase for Option<NonNull<T>> {}
352
353 impl<'b, T: BuildableType> ScalarBuildableType for Option<NonNull<T>> {}
354
355 macro_rules! build_unit_function_type {
356 ($($arguments:ident,)*) => {
357 impl<$($arguments: BuildableType),*> BuildableType for Option<unsafe extern "C" fn($($arguments,)*)> {
358 fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
359 type_builder.build_function(&[$($arguments::build(type_builder),)*], None)
360 }
361 }
362
363 impl<$($arguments: BuildableType),*> hidden::ScalarBuildableTypeBase for Option<unsafe extern "C" fn($($arguments,)*)> {}
364
365 impl<$($arguments: BuildableType),*> ScalarBuildableType for Option<unsafe extern "C" fn($($arguments,)*)> {}
366
367 impl<$($arguments: BuildableType),*> BuildableType for unsafe extern "C" fn($($arguments,)*) {
368 fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
369 type_builder.build_function(&[$($arguments::build(type_builder),)*], None)
370 }
371 }
372
373 impl<$($arguments: BuildableType),*> hidden::ScalarBuildableTypeBase for unsafe extern "C" fn($($arguments,)*) {}
374
375 impl<$($arguments: BuildableType),*> ScalarBuildableType for unsafe extern "C" fn($($arguments,)*) {}
376 };
377 }
378
379 macro_rules! build_function_type {
380 ($($arguments:ident,)*) => {
381 impl<R: BuildableType, $($arguments: BuildableType),*> BuildableType for Option<unsafe extern "C" fn($($arguments,)*) -> R> {
382 fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
383 type_builder.build_function(&[$($arguments::build(type_builder),)*], Some(R::build(type_builder)))
384 }
385 }
386
387 impl<R: BuildableType, $($arguments: BuildableType),*> hidden::ScalarBuildableTypeBase for Option<unsafe extern "C" fn($($arguments,)*) -> R> {}
388
389 impl<R: BuildableType, $($arguments: BuildableType),*> ScalarBuildableType for Option<unsafe extern "C" fn($($arguments,)*) -> R> {}
390
391 impl<R: BuildableType, $($arguments: BuildableType),*> BuildableType for unsafe extern "C" fn($($arguments,)*) -> R {
392 fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
393 type_builder.build_function(&[$($arguments::build(type_builder),)*], Some(R::build(type_builder)))
394 }
395 }
396
397 impl<R: BuildableType, $($arguments: BuildableType),*> hidden::ScalarBuildableTypeBase for unsafe extern "C" fn($($arguments,)*) -> R {}
398
399 impl<R: BuildableType, $($arguments: BuildableType),*> ScalarBuildableType for unsafe extern "C" fn($($arguments,)*) -> R {}
400
401 };
402 }
403
404 macro_rules! build_function_types {
405 () => {
406 build_unit_function_type!();
407 build_function_type!();
408 };
409 ($first_argument:ident, $($arguments:ident,)*) => {
410 build_unit_function_type!($first_argument, $($arguments,)*);
411 build_function_type!($first_argument, $($arguments,)*);
412 build_function_types!($($arguments,)*);
413 }
414 }
415
416 build_function_types!(
417 T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19,
418 );
419
420 macro_rules! build_array0 {
421 ($length:expr) => {
422 impl<T: BuildableType> BuildableType for [T; $length + 1] {
423 fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
424 type_builder.build_array(T::build(type_builder), $length + 1)
425 }
426 }
427 };
428 }
429
430 macro_rules! build_array1 {
431 ($length:expr) => {
432 build_array0!($length * 2);
433 build_array0!($length * 2 + 1);
434 };
435 }
436
437 macro_rules! build_array2 {
438 ($length:expr) => {
439 build_array1!($length * 2);
440 build_array1!($length * 2 + 1);
441 };
442 }
443
444 macro_rules! build_array3 {
445 ($length:expr) => {
446 build_array2!($length * 2);
447 build_array2!($length * 2 + 1);
448 };
449 }
450
451 macro_rules! build_array4 {
452 ($length:expr) => {
453 build_array3!($length * 2);
454 build_array3!($length * 2 + 1);
455 };
456 }
457
458 macro_rules! build_array5 {
459 ($length:expr) => {
460 build_array4!($length * 2);
461 build_array4!($length * 2 + 1);
462 };
463 }
464
465 build_array5!(0);
466 build_array5!(1);
467
468 /// buildable vector types
469 pub trait Vector: BuildableType {
470 /// element type
471 type Element: ScalarBuildableType;
472 /// vector length
473 const LENGTH: VectorLength;
474 }
475
476 #[doc(hidden)]
477 pub enum __VectorNeverType {}
478
479 macro_rules! build_fixed_vector {
480 ($name:ident, $length:expr) => {
481 /// Vector of elements `Element`
482 #[derive(Copy, Clone)]
483 pub struct $name<Element: ScalarBuildableType> {
484 /// elements of the vector `Self`
485 pub elements: [Element; $length],
486 }
487
488 impl<Element: ScalarBuildableType> Deref for $name<Element> {
489 type Target = [Element; $length];
490 fn deref(&self) -> &Self::Target {
491 &self.elements
492 }
493 }
494
495 impl<Element: ScalarBuildableType> DerefMut for $name<Element> {
496 fn deref_mut(&mut self) -> &mut Self::Target {
497 &mut self.elements
498 }
499 }
500
501 impl<Element: ScalarBuildableType> BuildableType for $name<Element> {
502 fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
503 type_builder.build_vector(Element::build(type_builder), Self::LENGTH)
504 }
505 }
506
507 impl<Element: ScalarBuildableType> Vector for $name<Element> {
508 type Element = Element;
509 const LENGTH: VectorLength = { VectorLength::Fixed { length: $length } };
510 }
511 };
512 }
513
514 macro_rules! build_variable_vector {
515 ($name:ident, $base_length:expr) => {
516 /// Vector of elements `Element`
517 pub enum $name<Element: ScalarBuildableType> {
518 #[doc(hidden)]
519 __Dummy(__VectorNeverType, PhantomData<Element>),
520 }
521
522 impl<Element: ScalarBuildableType> BuildableType for $name<Element> {
523 fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
524 type_builder.build_vector(Element::build(type_builder), Self::LENGTH)
525 }
526 }
527
528 impl<Element: ScalarBuildableType> Vector for $name<Element> {
529 type Element = Element;
530 const LENGTH: VectorLength = {
531 VectorLength::Variable {
532 base_length: $base_length,
533 }
534 };
535 }
536 };
537 }
538
539 /// alternate name for `VecNx1`
540 pub type VecN<Element> = VecNx1<Element>;
541
542 build_fixed_vector!(Vec1, 1);
543 build_fixed_vector!(Vec2, 2);
544 build_fixed_vector!(Vec3, 3);
545 build_fixed_vector!(Vec4, 4);
546 build_fixed_vector!(Vec5, 5);
547 build_fixed_vector!(Vec6, 6);
548 build_fixed_vector!(Vec7, 7);
549 build_fixed_vector!(Vec8, 8);
550 build_fixed_vector!(Vec9, 9);
551 build_fixed_vector!(Vec10, 10);
552 build_fixed_vector!(Vec11, 11);
553 build_fixed_vector!(Vec12, 12);
554 build_fixed_vector!(Vec13, 13);
555 build_fixed_vector!(Vec14, 14);
556 build_fixed_vector!(Vec15, 15);
557 build_fixed_vector!(Vec16, 16);
558 build_variable_vector!(VecNx1, 1);
559 build_variable_vector!(VecNx2, 2);
560 build_variable_vector!(VecNx3, 3);
561 build_variable_vector!(VecNx4, 4);
562 build_variable_vector!(VecNx5, 5);
563 build_variable_vector!(VecNx6, 6);
564 build_variable_vector!(VecNx7, 7);
565 build_variable_vector!(VecNx8, 8);
566 build_variable_vector!(VecNx9, 9);
567 build_variable_vector!(VecNx10, 10);
568 build_variable_vector!(VecNx11, 11);
569 build_variable_vector!(VecNx12, 12);
570 build_variable_vector!(VecNx13, 13);
571 build_variable_vector!(VecNx14, 14);
572 build_variable_vector!(VecNx15, 15);
573 build_variable_vector!(VecNx16, 16);