move backend to separate file
authorJacob Lifshay <programmerjake@gmail.com>
Wed, 10 Oct 2018 05:57:06 +0000 (22:57 -0700)
committerJacob Lifshay <programmerjake@gmail.com>
Wed, 10 Oct 2018 05:57:06 +0000 (22:57 -0700)
shader-compiler/src/backend/mod.rs [new file with mode: 0644]
shader-compiler/src/lib.rs

diff --git a/shader-compiler/src/backend/mod.rs b/shader-compiler/src/backend/mod.rs
new file mode 100644 (file)
index 0000000..71b18e4
--- /dev/null
@@ -0,0 +1,536 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+// Copyright 2018 Jacob Lifshay
+
+//! Shader Compiler Backend traits
+
+use std::cell::UnsafeCell;
+use std::fmt::Debug;
+use std::hash::Hash;
+use std::marker::PhantomData;
+use std::ops::{Deref, DerefMut};
+
+#[macro_export]
+macro_rules! buildable_struct_helper {
+    {
+        struct $name:ident {
+            $($member_name:ident: $member_type:ty,)*
+        }
+    } => {
+        impl $crate::backend::BuildableType for $name {
+            fn build<'a, Ty: $crate::backend::Type<'a>, TB: $crate::backend::TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
+                type_builder.build_struct(&[$(<$member_type as $crate::backend::BuildableType>::build(type_builder),)*])
+            }
+        }
+
+        impl $crate::backend::BuildableStruct for $name {
+            fn get_members(
+            ) -> &'static [$crate::backend::BuildableStructMemberDescriptor] {
+                #[allow(dead_code, non_camel_case_types)]
+                #[repr(usize)]
+                enum MemberIndices {
+                    $($member_name,)*
+                    __Last,
+                }
+                const MEMBERS: &'static [$crate::backend::BuildableStructMemberDescriptor] = &[
+                    $($crate::backend::BuildableStructMemberDescriptor {
+                        name: stringify!($member_name),
+                        index: MemberIndices::$member_name as usize,
+                    },)*
+                ];
+                MEMBERS
+            }
+        }
+    }
+}
+
+#[macro_export]
+macro_rules! buildable_struct {
+    {
+        $(#[derive($derives:ident)])*
+        pub struct $name:ident {
+            $($member_name:ident: $member_type:ty,)*
+        }
+    } => {
+        $(#[derive($derives)])*
+        #[repr(C)]
+        pub struct $name {
+            $($member_name: $member_type,)*
+        }
+
+        buildable_struct_helper!{
+            struct $name {
+                $($member_name: $member_type,)*
+            }
+        }
+    };
+    {
+        $(#[derive($derives:ident)])*
+        struct $name:ident {
+            $($member_name:ident: $member_type:ty,)*
+        }
+    } => {
+        $(#[derive($derives)])*
+        #[repr(C)]
+        struct $name {
+            $($member_name: $member_type,)*
+        }
+
+        buildable_struct_helper!{
+            struct $name {
+                $($member_name: $member_type,)*
+            }
+        }
+    };
+}
+
+/// length of a vector
+pub enum VectorLength {
+    /// fixed length vector
+    Fixed {
+        /// length in elements
+        length: u32,
+    },
+    /// variable length vector
+    Variable {
+        /// base length in elements which the runtime vector length is a multiple of
+        base_length: u32,
+    },
+}
+
+/// equivalent to LLVM's 'Type'
+pub trait Type<'a>: Clone + Eq + Hash + Debug {}
+
+/// trait for building types
+pub trait TypeBuilder<'a, Ty: Type<'a>> {
+    /// build a `bool` type
+    fn build_bool(&self) -> Ty;
+    /// build an 8-bit sign-agnostic integer type
+    fn build_i8(&self) -> Ty;
+    /// build an 16-bit sign-agnostic integer type
+    fn build_i16(&self) -> Ty;
+    /// build an 32-bit sign-agnostic integer type
+    fn build_i32(&self) -> Ty;
+    /// build an 64-bit sign-agnostic integer type
+    fn build_i64(&self) -> Ty;
+    /// build an 32-bit IEEE 754 floating-point type
+    fn build_f32(&self) -> Ty;
+    /// build an 64-bit IEEE 754 floating-point type
+    fn build_f64(&self) -> Ty;
+    /// build a pointer
+    fn build_pointer(&self, target: Ty) -> Ty;
+    /// build an array
+    fn build_array(&self, element: Ty, count: usize) -> Ty;
+    /// build a vector
+    fn build_vector(&self, element: Ty, length: VectorLength) -> Ty;
+    /// build a struct
+    fn build_struct(&self, members: &[Ty]) -> Ty;
+    /// build a function type
+    fn build_function(&self, arguments: &[Ty], return_type: Option<Ty>) -> Ty;
+    /// build a type
+    fn build<T: BuildableType>(&self) -> Ty
+    where
+        Self: Sized,
+    {
+        T::build(self)
+    }
+}
+
+impl<'a, 'b, Ty: Type<'a>> TypeBuilder<'a, Ty> for &'b TypeBuilder<'a, Ty> {
+    fn build_bool(&self) -> Ty {
+        (*self).build_bool()
+    }
+    fn build_i8(&self) -> Ty {
+        (*self).build_i8()
+    }
+    fn build_i16(&self) -> Ty {
+        (*self).build_i16()
+    }
+    fn build_i32(&self) -> Ty {
+        (*self).build_i32()
+    }
+    fn build_i64(&self) -> Ty {
+        (*self).build_i64()
+    }
+    fn build_f32(&self) -> Ty {
+        (*self).build_f32()
+    }
+    fn build_f64(&self) -> Ty {
+        (*self).build_f64()
+    }
+    fn build_pointer(&self, target: Ty) -> Ty {
+        (*self).build_pointer(target)
+    }
+    fn build_array(&self, element: Ty, count: usize) -> Ty {
+        (*self).build_array(element, count)
+    }
+    fn build_vector(&self, element: Ty, length: VectorLength) -> Ty {
+        (*self).build_vector(element, length)
+    }
+    fn build_struct(&self, members: &[Ty]) -> Ty {
+        (*self).build_struct(members)
+    }
+    fn build_function(&self, arguments: &[Ty], return_type: Option<Ty>) -> Ty {
+        (*self).build_function(arguments, return_type)
+    }
+}
+
+/// trait for rust types that can be built using `TypeBuilder`
+pub trait BuildableType {
+    /// build the type represented by `Self`
+    fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty;
+}
+
+impl<T: BuildableType> BuildableType for UnsafeCell<T> {
+    fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
+        T::build(type_builder)
+    }
+}
+
+mod hidden {
+    pub trait ScalarBuildableTypeBase {}
+}
+
+impl<T: hidden::ScalarBuildableTypeBase> hidden::ScalarBuildableTypeBase for UnsafeCell<T> {}
+
+/// trait for rust types that can be an element of a vector and be built using `TypeBuilder`
+pub trait ScalarBuildableType: BuildableType + hidden::ScalarBuildableTypeBase {}
+
+impl<T: ScalarBuildableType> ScalarBuildableType for UnsafeCell<T> {}
+
+/// descriptor for members of types implementing `BuildableStruct`
+pub struct BuildableStructMemberDescriptor {
+    /// name of member
+    pub name: &'static str,
+    /// index of member
+    pub index: usize,
+}
+
+/// trait for structs that can be built using TypeBuilder
+/// implementing types are usually created using `buildable_struct!`
+pub trait BuildableStruct: BuildableType {
+    /// get the list of members for `Self`
+    fn get_members() -> &'static [BuildableStructMemberDescriptor];
+    /// get the member for `Self` that is named `name`
+    fn get_member_by_name(name: &str) -> &'static BuildableStructMemberDescriptor {
+        for member in Self::get_members() {
+            if name == member.name {
+                return member;
+            }
+        }
+        unreachable!("{} is not a member", name);
+    }
+}
+
+macro_rules! build_basic_scalar {
+    ($type:ty, $build_fn:ident) => {
+        impl BuildableType for $type {
+            fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
+                type_builder.$build_fn()
+            }
+        }
+
+        impl hidden::ScalarBuildableTypeBase for $type {}
+
+        impl ScalarBuildableType for $type {}
+    };
+}
+
+build_basic_scalar!(bool, build_bool);
+build_basic_scalar!(u8, build_i8);
+build_basic_scalar!(i8, build_i8);
+build_basic_scalar!(u16, build_i16);
+build_basic_scalar!(i16, build_i16);
+build_basic_scalar!(u32, build_i32);
+build_basic_scalar!(i32, build_i32);
+build_basic_scalar!(u64, build_i64);
+build_basic_scalar!(i64, build_i64);
+build_basic_scalar!(f32, build_f32);
+build_basic_scalar!(f64, build_f64);
+
+impl<'b, T: BuildableType> BuildableType for &'b T {
+    fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
+        type_builder.build_pointer(T::build(type_builder))
+    }
+}
+
+impl<'b, T: BuildableType> hidden::ScalarBuildableTypeBase for &'b T {}
+
+impl<'b, T: BuildableType> ScalarBuildableType for &'b T {}
+
+impl<'b, T: BuildableType> BuildableType for &'b mut T {
+    fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
+        type_builder.build_pointer(T::build(type_builder))
+    }
+}
+
+impl<'b, T: BuildableType> hidden::ScalarBuildableTypeBase for &'b mut T {}
+
+impl<'b, T: BuildableType> ScalarBuildableType for &'b mut T {}
+
+impl<T: BuildableType> BuildableType for *mut T {
+    fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
+        type_builder.build_pointer(T::build(type_builder))
+    }
+}
+
+impl<'b, T: BuildableType> hidden::ScalarBuildableTypeBase for *mut T {}
+
+impl<'b, T: BuildableType> ScalarBuildableType for *mut T {}
+
+impl<T: BuildableType> BuildableType for *const T {
+    fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
+        type_builder.build_pointer(T::build(type_builder))
+    }
+}
+
+impl<'b, T: BuildableType> hidden::ScalarBuildableTypeBase for *const T {}
+
+impl<'b, T: BuildableType> ScalarBuildableType for *const T {}
+
+macro_rules! build_unit_function_type {
+        ($($arguments:ident,)*) => {
+            impl<$($arguments: BuildableType),*> BuildableType for Option<unsafe extern "C" fn($($arguments,)*)> {
+                fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
+                    type_builder.build_function(&[$($arguments::build(type_builder),)*], None)
+                }
+            }
+
+            impl<$($arguments: BuildableType),*> hidden::ScalarBuildableTypeBase for Option<unsafe extern "C" fn($($arguments,)*)> {}
+
+            impl<$($arguments: BuildableType),*> ScalarBuildableType for Option<unsafe extern "C" fn($($arguments,)*)> {}
+        };
+    }
+
+macro_rules! build_function_type {
+        ($($arguments:ident,)*) => {
+            impl<R: BuildableType, $($arguments: BuildableType),*> BuildableType for Option<unsafe extern "C" fn($($arguments,)*) -> R> {
+                fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
+                    type_builder.build_function(&[$($arguments::build(type_builder),)*], Some(R::build(type_builder)))
+                }
+            }
+
+            impl<R: BuildableType, $($arguments: BuildableType),*> hidden::ScalarBuildableTypeBase for Option<unsafe extern "C" fn($($arguments,)*) -> R> {}
+
+            impl<R: BuildableType, $($arguments: BuildableType),*> ScalarBuildableType for Option<unsafe extern "C" fn($($arguments,)*) -> R> {}
+        };
+    }
+
+macro_rules! build_function_types {
+        () => {
+            build_unit_function_type!();
+            build_function_type!();
+        };
+        ($first_argument:ident, $($arguments:ident,)*) => {
+            build_unit_function_type!($first_argument, $($arguments,)*);
+            build_function_type!($first_argument, $($arguments,)*);
+            build_function_types!($($arguments,)*);
+        }
+    }
+
+build_function_types!(
+    T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19,
+);
+
+macro_rules! build_array0 {
+    ($length:expr) => {
+        impl<T: BuildableType> BuildableType for [T; $length + 1] {
+            fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
+                type_builder.build_array(T::build(type_builder), $length + 1)
+            }
+        }
+    };
+}
+
+macro_rules! build_array1 {
+    ($length:expr) => {
+        build_array0!($length * 2);
+        build_array0!($length * 2 + 1);
+    };
+}
+
+macro_rules! build_array2 {
+    ($length:expr) => {
+        build_array1!($length * 2);
+        build_array1!($length * 2 + 1);
+    };
+}
+
+macro_rules! build_array3 {
+    ($length:expr) => {
+        build_array2!($length * 2);
+        build_array2!($length * 2 + 1);
+    };
+}
+
+macro_rules! build_array4 {
+    ($length:expr) => {
+        build_array3!($length * 2);
+        build_array3!($length * 2 + 1);
+    };
+}
+
+macro_rules! build_array5 {
+    ($length:expr) => {
+        build_array4!($length * 2);
+        build_array4!($length * 2 + 1);
+    };
+}
+
+build_array5!(0);
+build_array5!(1);
+
+/// buildable vector types
+pub trait Vector: BuildableType {
+    /// element type
+    type Element: ScalarBuildableType;
+    /// vector length
+    const LENGTH: VectorLength;
+}
+
+#[doc(hidden)]
+pub enum __VectorNeverType {}
+
+macro_rules! build_fixed_vector {
+    ($name:ident, $length:expr) => {
+        /// Vector of elements `Element`
+        #[derive(Copy, Clone)]
+        pub struct $name<Element: ScalarBuildableType> {
+            /// elements of the vector `Self`
+            pub elements: [Element; $length],
+        }
+
+        impl<Element: ScalarBuildableType> Deref for $name<Element> {
+            type Target = [Element; $length];
+            fn deref(&self) -> &Self::Target {
+                &self.elements
+            }
+        }
+
+        impl<Element: ScalarBuildableType> DerefMut for $name<Element> {
+            fn deref_mut(&mut self) -> &mut Self::Target {
+                &mut self.elements
+            }
+        }
+
+        impl<Element: ScalarBuildableType> BuildableType for $name<Element> {
+            fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
+                type_builder.build_vector(Element::build(type_builder), Self::LENGTH)
+            }
+        }
+
+        impl<Element: ScalarBuildableType> Vector for $name<Element> {
+            type Element = Element;
+            const LENGTH: VectorLength = { VectorLength::Fixed { length: $length } };
+        }
+    };
+}
+
+macro_rules! build_variable_vector {
+    ($name:ident, $base_length:expr) => {
+        /// Vector of elements `Element`
+        pub enum $name<Element: ScalarBuildableType> {
+            #[doc(hidden)]
+            __Dummy(__VectorNeverType, PhantomData<Element>),
+        }
+
+        impl<Element: ScalarBuildableType> BuildableType for $name<Element> {
+            fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
+                type_builder.build_vector(Element::build(type_builder), Self::LENGTH)
+            }
+        }
+
+        impl<Element: ScalarBuildableType> Vector for $name<Element> {
+            type Element = Element;
+            const LENGTH: VectorLength = {
+                VectorLength::Variable {
+                    base_length: $base_length,
+                }
+            };
+        }
+    };
+}
+
+/// alternate name for `VecNx1`
+pub type VecN<Element> = VecNx1<Element>;
+
+build_fixed_vector!(Vec1, 1);
+build_fixed_vector!(Vec2, 2);
+build_fixed_vector!(Vec3, 3);
+build_fixed_vector!(Vec4, 4);
+build_fixed_vector!(Vec5, 5);
+build_fixed_vector!(Vec6, 6);
+build_fixed_vector!(Vec7, 7);
+build_fixed_vector!(Vec8, 8);
+build_fixed_vector!(Vec9, 9);
+build_fixed_vector!(Vec10, 10);
+build_fixed_vector!(Vec11, 11);
+build_fixed_vector!(Vec12, 12);
+build_fixed_vector!(Vec13, 13);
+build_fixed_vector!(Vec14, 14);
+build_fixed_vector!(Vec15, 15);
+build_fixed_vector!(Vec16, 16);
+build_variable_vector!(VecNx1, 1);
+build_variable_vector!(VecNx2, 2);
+build_variable_vector!(VecNx3, 3);
+build_variable_vector!(VecNx4, 4);
+build_variable_vector!(VecNx5, 5);
+build_variable_vector!(VecNx6, 6);
+build_variable_vector!(VecNx7, 7);
+build_variable_vector!(VecNx8, 8);
+build_variable_vector!(VecNx9, 9);
+build_variable_vector!(VecNx10, 10);
+build_variable_vector!(VecNx11, 11);
+build_variable_vector!(VecNx12, 12);
+build_variable_vector!(VecNx13, 13);
+build_variable_vector!(VecNx14, 14);
+build_variable_vector!(VecNx15, 15);
+build_variable_vector!(VecNx16, 16);
+
+/// equivalent to LLVM's 'IRBuilder'
+pub trait Builder<'a> {}
+
+/// equivalent to LLVM's 'Module'
+pub trait Module<'a> {
+    /// set's the source file name for this module
+    fn set_source_file_name(&mut self, source_file_name: &str);
+}
+
+/// instance of a compiler backend; equivalent to LLVM's `LLVMContext`
+pub trait Context<'a> {
+    /// the `Module` type
+    type Module: Module<'a>;
+    /// the `Builder` type
+    type Builder: Builder<'a>;
+    /// the `Type` type
+    type Type: Type<'a>;
+    /// the `TypeBuilder` type
+    type TypeBuilder: TypeBuilder<'a, Self::Type>;
+    /// create a new `Module`
+    fn create_module(&self, name: &str) -> Self::Module;
+    /// create a new `Builder`
+    fn create_builder(&self) -> Self::Builder;
+    /// create a new `TypeBuilder`
+    fn create_type_builder(&self) -> Self::TypeBuilder;
+}
+
+/// trait that the user of `ShaderCompiler` implements
+pub trait ShaderCompilerUser {
+    /// the return type of `run_with_context`
+    type ReturnType;
+    /// the function that the user of `ShaderCompiler` implements
+    fn run_with_context<'a, C: Context<'a>>(self, context: &'a C) -> Self::ReturnType;
+}
+
+/// main shader compiler backend trait
+pub trait ShaderCompiler: Send + Sync + 'static {
+    /// the shader compiler's configuration
+    type Config: Default + Clone;
+    /// get shader compiler's name
+    fn name() -> &'static str;
+    /// run a passed-in function with a new compiler context.
+    /// this round-about method is used because generic associated types are not in stable Rust yet
+    fn run_with_user<SCU: ShaderCompilerUser>(
+        shader_compiler_user: SCU,
+        config: Self::Config,
+    ) -> SCU::ReturnType;
+}
index fe2ab5df9d4145ee437ddc51368096150518ce61..16b875ec7566695717969c8f1559a9e9d3a4955d 100644 (file)
@@ -4,540 +4,8 @@
 
 //! Shader Compiler for Kazan
 
-#[macro_export]
-macro_rules! buildable_struct_helper {
-    {
-        struct $name:ident {
-            $($member_name:ident: $member_type:ty,)*
-        }
-    } => {
-        impl $crate::backend::BuildableType for $name {
-            fn build<'a, Ty: $crate::backend::Type<'a>, TB: $crate::backend::TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
-                type_builder.build_struct(&[$(<$member_type as $crate::backend::BuildableType>::build(type_builder),)*])
-            }
-        }
-
-        impl $crate::backend::BuildableStruct for $name {
-            fn get_members(
-            ) -> &'static [$crate::backend::BuildableStructMemberDescriptor] {
-                #[allow(dead_code, non_camel_case_types)]
-                #[repr(usize)]
-                enum MemberIndices {
-                    $($member_name,)*
-                    __Last,
-                }
-                const MEMBERS: &'static [$crate::backend::BuildableStructMemberDescriptor] = &[
-                    $($crate::backend::BuildableStructMemberDescriptor {
-                        name: stringify!($member_name),
-                        index: MemberIndices::$member_name as usize,
-                    },)*
-                ];
-                MEMBERS
-            }
-        }
-    }
-}
-
-#[macro_export]
-macro_rules! buildable_struct {
-    {
-        $(#[derive($derives:ident)])*
-        pub struct $name:ident {
-            $($member_name:ident: $member_type:ty,)*
-        }
-    } => {
-        $(#[derive($derives)])*
-        #[repr(C)]
-        pub struct $name {
-            $($member_name: $member_type,)*
-        }
-
-        buildable_struct_helper!{
-            struct $name {
-                $($member_name: $member_type,)*
-            }
-        }
-    };
-    {
-        $(#[derive($derives:ident)])*
-        struct $name:ident {
-            $($member_name:ident: $member_type:ty,)*
-        }
-    } => {
-        $(#[derive($derives)])*
-        #[repr(C)]
-        struct $name {
-            $($member_name: $member_type,)*
-        }
-
-        buildable_struct_helper!{
-            struct $name {
-                $($member_name: $member_type,)*
-            }
-        }
-    };
-}
-
-/// Shader Compiler Backend traits
-pub mod backend {
-    use std::cell::UnsafeCell;
-    use std::fmt::Debug;
-    use std::hash::Hash;
-    use std::marker::PhantomData;
-    use std::ops::{Deref, DerefMut};
-
-    /// length of a vector
-    pub enum VectorLength {
-        /// fixed length vector
-        Fixed {
-            /// length in elements
-            length: u32,
-        },
-        /// variable length vector
-        Variable {
-            /// base length in elements which the runtime vector length is a multiple of
-            base_length: u32,
-        },
-    }
-
-    /// equivalent to LLVM's 'Type'
-    pub trait Type<'a>: Clone + Eq + Hash + Debug {}
-
-    /// trait for building types
-    pub trait TypeBuilder<'a, Ty: Type<'a>> {
-        /// build a `bool` type
-        fn build_bool(&self) -> Ty;
-        /// build an 8-bit sign-agnostic integer type
-        fn build_i8(&self) -> Ty;
-        /// build an 16-bit sign-agnostic integer type
-        fn build_i16(&self) -> Ty;
-        /// build an 32-bit sign-agnostic integer type
-        fn build_i32(&self) -> Ty;
-        /// build an 64-bit sign-agnostic integer type
-        fn build_i64(&self) -> Ty;
-        /// build an 32-bit IEEE 754 floating-point type
-        fn build_f32(&self) -> Ty;
-        /// build an 64-bit IEEE 754 floating-point type
-        fn build_f64(&self) -> Ty;
-        /// build a pointer
-        fn build_pointer(&self, target: Ty) -> Ty;
-        /// build an array
-        fn build_array(&self, element: Ty, count: usize) -> Ty;
-        /// build a vector
-        fn build_vector(&self, element: Ty, length: VectorLength) -> Ty;
-        /// build a struct
-        fn build_struct(&self, members: &[Ty]) -> Ty;
-        /// build a function type
-        fn build_function(&self, arguments: &[Ty], return_type: Option<Ty>) -> Ty;
-        /// build a type
-        fn build<T: BuildableType>(&self) -> Ty
-        where
-            Self: Sized,
-        {
-            T::build(self)
-        }
-    }
-
-    impl<'a, 'b, Ty: Type<'a>> TypeBuilder<'a, Ty> for &'b TypeBuilder<'a, Ty> {
-        fn build_bool(&self) -> Ty {
-            (*self).build_bool()
-        }
-        fn build_i8(&self) -> Ty {
-            (*self).build_i8()
-        }
-        fn build_i16(&self) -> Ty {
-            (*self).build_i16()
-        }
-        fn build_i32(&self) -> Ty {
-            (*self).build_i32()
-        }
-        fn build_i64(&self) -> Ty {
-            (*self).build_i64()
-        }
-        fn build_f32(&self) -> Ty {
-            (*self).build_f32()
-        }
-        fn build_f64(&self) -> Ty {
-            (*self).build_f64()
-        }
-        fn build_pointer(&self, target: Ty) -> Ty {
-            (*self).build_pointer(target)
-        }
-        fn build_array(&self, element: Ty, count: usize) -> Ty {
-            (*self).build_array(element, count)
-        }
-        fn build_vector(&self, element: Ty, length: VectorLength) -> Ty {
-            (*self).build_vector(element, length)
-        }
-        fn build_struct(&self, members: &[Ty]) -> Ty {
-            (*self).build_struct(members)
-        }
-        fn build_function(&self, arguments: &[Ty], return_type: Option<Ty>) -> Ty {
-            (*self).build_function(arguments, return_type)
-        }
-    }
-
-    /// trait for rust types that can be built using `TypeBuilder`
-    pub trait BuildableType {
-        /// build the type represented by `Self`
-        fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty;
-    }
-
-    impl<T: BuildableType> BuildableType for UnsafeCell<T> {
-        fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
-            T::build(type_builder)
-        }
-    }
-
-    mod hidden {
-        pub trait ScalarBuildableTypeBase {}
-    }
-
-    impl<T: hidden::ScalarBuildableTypeBase> hidden::ScalarBuildableTypeBase for UnsafeCell<T> {}
-
-    /// trait for rust types that can be an element of a vector and be built using `TypeBuilder`
-    pub trait ScalarBuildableType: BuildableType + hidden::ScalarBuildableTypeBase {}
-
-    impl<T: ScalarBuildableType> ScalarBuildableType for UnsafeCell<T> {}
-
-    /// descriptor for members of types implementing `BuildableStruct`
-    pub struct BuildableStructMemberDescriptor {
-        /// name of member
-        pub name: &'static str,
-        /// index of member
-        pub index: usize,
-    }
-
-    /// trait for structs that can be built using TypeBuilder
-    /// implementing types are usually created using `buildable_struct!`
-    pub trait BuildableStruct: BuildableType {
-        /// get the list of members for `Self`
-        fn get_members() -> &'static [BuildableStructMemberDescriptor];
-        /// get the member for `Self` that is named `name`
-        fn get_member_by_name(name: &str) -> &'static BuildableStructMemberDescriptor {
-            for member in Self::get_members() {
-                if name == member.name {
-                    return member;
-                }
-            }
-            unreachable!("{} is not a member", name);
-        }
-    }
-
-    macro_rules! build_basic_scalar {
-        ($type:ty, $build_fn:ident) => {
-            impl BuildableType for $type {
-                fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
-                    type_builder.$build_fn()
-                }
-            }
-
-            impl hidden::ScalarBuildableTypeBase for $type {}
-
-            impl ScalarBuildableType for $type {}
-        };
-    }
-
-    build_basic_scalar!(bool, build_bool);
-    build_basic_scalar!(u8, build_i8);
-    build_basic_scalar!(i8, build_i8);
-    build_basic_scalar!(u16, build_i16);
-    build_basic_scalar!(i16, build_i16);
-    build_basic_scalar!(u32, build_i32);
-    build_basic_scalar!(i32, build_i32);
-    build_basic_scalar!(u64, build_i64);
-    build_basic_scalar!(i64, build_i64);
-    build_basic_scalar!(f32, build_f32);
-    build_basic_scalar!(f64, build_f64);
-
-    impl<'b, T: BuildableType> BuildableType for &'b T {
-        fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
-            type_builder.build_pointer(T::build(type_builder))
-        }
-    }
-
-    impl<'b, T: BuildableType> hidden::ScalarBuildableTypeBase for &'b T {}
-
-    impl<'b, T: BuildableType> ScalarBuildableType for &'b T {}
-
-    impl<'b, T: BuildableType> BuildableType for &'b mut T {
-        fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
-            type_builder.build_pointer(T::build(type_builder))
-        }
-    }
-
-    impl<'b, T: BuildableType> hidden::ScalarBuildableTypeBase for &'b mut T {}
-
-    impl<'b, T: BuildableType> ScalarBuildableType for &'b mut T {}
-
-    impl<T: BuildableType> BuildableType for *mut T {
-        fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
-            type_builder.build_pointer(T::build(type_builder))
-        }
-    }
-
-    impl<'b, T: BuildableType> hidden::ScalarBuildableTypeBase for *mut T {}
-
-    impl<'b, T: BuildableType> ScalarBuildableType for *mut T {}
-
-    impl<T: BuildableType> BuildableType for *const T {
-        fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
-            type_builder.build_pointer(T::build(type_builder))
-        }
-    }
-
-    impl<'b, T: BuildableType> hidden::ScalarBuildableTypeBase for *const T {}
-
-    impl<'b, T: BuildableType> ScalarBuildableType for *const T {}
-
-    macro_rules! build_unit_function_type {
-        ($($arguments:ident,)*) => {
-            impl<$($arguments: BuildableType),*> BuildableType for Option<unsafe extern "C" fn($($arguments,)*)> {
-                fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
-                    type_builder.build_function(&[$($arguments::build(type_builder),)*], None)
-                }
-            }
-
-            impl<$($arguments: BuildableType),*> hidden::ScalarBuildableTypeBase for Option<unsafe extern "C" fn($($arguments,)*)> {}
-
-            impl<$($arguments: BuildableType),*> ScalarBuildableType for Option<unsafe extern "C" fn($($arguments,)*)> {}
-        };
-    }
-
-    macro_rules! build_function_type {
-        ($($arguments:ident,)*) => {
-            impl<R: BuildableType, $($arguments: BuildableType),*> BuildableType for Option<unsafe extern "C" fn($($arguments,)*) -> R> {
-                fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
-                    type_builder.build_function(&[$($arguments::build(type_builder),)*], Some(R::build(type_builder)))
-                }
-            }
-
-            impl<R: BuildableType, $($arguments: BuildableType),*> hidden::ScalarBuildableTypeBase for Option<unsafe extern "C" fn($($arguments,)*) -> R> {}
-
-            impl<R: BuildableType, $($arguments: BuildableType),*> ScalarBuildableType for Option<unsafe extern "C" fn($($arguments,)*) -> R> {}
-        };
-    }
-
-    macro_rules! build_function_types {
-        () => {
-            build_unit_function_type!();
-            build_function_type!();
-        };
-        ($first_argument:ident, $($arguments:ident,)*) => {
-            build_unit_function_type!($first_argument, $($arguments,)*);
-            build_function_type!($first_argument, $($arguments,)*);
-            build_function_types!($($arguments,)*);
-        }
-    }
-
-    build_function_types!(
-        T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19,
-    );
-
-    macro_rules! build_array0 {
-        ($length:expr) => {
-            impl<T: BuildableType> BuildableType for [T; $length + 1] {
-                fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
-                    type_builder.build_array(T::build(type_builder), $length + 1)
-                }
-            }
-        };
-    }
-
-    macro_rules! build_array1 {
-        ($length:expr) => {
-            build_array0!($length * 2);
-            build_array0!($length * 2 + 1);
-        };
-    }
-
-    macro_rules! build_array2 {
-        ($length:expr) => {
-            build_array1!($length * 2);
-            build_array1!($length * 2 + 1);
-        };
-    }
-
-    macro_rules! build_array3 {
-        ($length:expr) => {
-            build_array2!($length * 2);
-            build_array2!($length * 2 + 1);
-        };
-    }
-
-    macro_rules! build_array4 {
-        ($length:expr) => {
-            build_array3!($length * 2);
-            build_array3!($length * 2 + 1);
-        };
-    }
-
-    macro_rules! build_array5 {
-        ($length:expr) => {
-            build_array4!($length * 2);
-            build_array4!($length * 2 + 1);
-        };
-    }
-
-    build_array5!(0);
-    build_array5!(1);
-
-    /// buildable vector types
-    pub trait Vector: BuildableType {
-        /// element type
-        type Element: ScalarBuildableType;
-        /// vector length
-        const LENGTH: VectorLength;
-    }
-
-    #[doc(hidden)]
-    pub enum __VectorNeverType {}
-
-    macro_rules! build_fixed_vector {
-        ($name:ident, $length:expr) => {
-            /// Vector of elements `Element`
-            #[derive(Copy, Clone)]
-            pub struct $name<Element: ScalarBuildableType> {
-                /// elements of the vector `Self`
-                pub elements: [Element; $length],
-            }
-
-            impl<Element: ScalarBuildableType> Deref for $name<Element> {
-                type Target = [Element; $length];
-                fn deref(&self) -> &Self::Target {
-                    &self.elements
-                }
-            }
-
-            impl<Element: ScalarBuildableType> DerefMut for $name<Element> {
-                fn deref_mut(&mut self) -> &mut Self::Target {
-                    &mut self.elements
-                }
-            }
-
-            impl<Element: ScalarBuildableType> BuildableType for $name<Element> {
-                fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
-                    type_builder.build_vector(Element::build(type_builder), Self::LENGTH)
-                }
-            }
-
-            impl<Element: ScalarBuildableType> Vector for $name<Element> {
-                type Element = Element;
-                const LENGTH: VectorLength = { VectorLength::Fixed { length: $length } };
-            }
-        };
-    }
-
-    macro_rules! build_variable_vector {
-        ($name:ident, $base_length:expr) => {
-            /// Vector of elements `Element`
-            pub enum $name<Element: ScalarBuildableType> {
-                #[doc(hidden)]
-                __Dummy(__VectorNeverType, PhantomData<Element>),
-            }
-
-            impl<Element: ScalarBuildableType> BuildableType for $name<Element> {
-                fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
-                    type_builder.build_vector(Element::build(type_builder), Self::LENGTH)
-                }
-            }
-
-            impl<Element: ScalarBuildableType> Vector for $name<Element> {
-                type Element = Element;
-                const LENGTH: VectorLength = {
-                    VectorLength::Variable {
-                        base_length: $base_length,
-                    }
-                };
-            }
-        };
-    }
-
-    /// alternate name for `VecNx1`
-    pub type VecN<Element> = VecNx1<Element>;
-
-    build_fixed_vector!(Vec1, 1);
-    build_fixed_vector!(Vec2, 2);
-    build_fixed_vector!(Vec3, 3);
-    build_fixed_vector!(Vec4, 4);
-    build_fixed_vector!(Vec5, 5);
-    build_fixed_vector!(Vec6, 6);
-    build_fixed_vector!(Vec7, 7);
-    build_fixed_vector!(Vec8, 8);
-    build_fixed_vector!(Vec9, 9);
-    build_fixed_vector!(Vec10, 10);
-    build_fixed_vector!(Vec11, 11);
-    build_fixed_vector!(Vec12, 12);
-    build_fixed_vector!(Vec13, 13);
-    build_fixed_vector!(Vec14, 14);
-    build_fixed_vector!(Vec15, 15);
-    build_fixed_vector!(Vec16, 16);
-    build_variable_vector!(VecNx1, 1);
-    build_variable_vector!(VecNx2, 2);
-    build_variable_vector!(VecNx3, 3);
-    build_variable_vector!(VecNx4, 4);
-    build_variable_vector!(VecNx5, 5);
-    build_variable_vector!(VecNx6, 6);
-    build_variable_vector!(VecNx7, 7);
-    build_variable_vector!(VecNx8, 8);
-    build_variable_vector!(VecNx9, 9);
-    build_variable_vector!(VecNx10, 10);
-    build_variable_vector!(VecNx11, 11);
-    build_variable_vector!(VecNx12, 12);
-    build_variable_vector!(VecNx13, 13);
-    build_variable_vector!(VecNx14, 14);
-    build_variable_vector!(VecNx15, 15);
-    build_variable_vector!(VecNx16, 16);
-
-    /// equivalent to LLVM's 'IRBuilder'
-    pub trait Builder<'a> {}
-
-    /// equivalent to LLVM's 'Module'
-    pub trait Module<'a> {
-        /// set's the source file name for this module
-        fn set_source_file_name(&mut self, source_file_name: &str);
-    }
-
-    /// instance of a compiler backend; equivalent to LLVM's `LLVMContext`
-    pub trait Context<'a> {
-        /// the `Module` type
-        type Module: Module<'a>;
-        /// the `Builder` type
-        type Builder: Builder<'a>;
-        /// the `Type` type
-        type Type: Type<'a>;
-        /// the `TypeBuilder` type
-        type TypeBuilder: TypeBuilder<'a, Self::Type>;
-        /// create a new `Module`
-        fn create_module(&self, name: &str) -> Self::Module;
-        /// create a new `Builder`
-        fn create_builder(&self) -> Self::Builder;
-        /// create a new `TypeBuilder`
-        fn create_type_builder(&self) -> Self::TypeBuilder;
-    }
-
-    /// trait that the user of `ShaderCompiler` implements
-    pub trait ShaderCompilerUser {
-        /// the return type of `run_with_context`
-        type ReturnType;
-        /// the function that the user of `ShaderCompiler` implements
-        fn run_with_context<'a, C: Context<'a>>(self, context: &'a C) -> Self::ReturnType;
-    }
-
-    /// main shader compiler backend trait
-    pub trait ShaderCompiler: Send + Sync + 'static {
-        /// the shader compiler's configuration
-        type Config: Default + Clone;
-        /// get shader compiler's name
-        fn name() -> &'static str;
-        /// run a passed-in function with a new compiler context.
-        /// this round-about method is used because generic associated types are not in stable Rust yet
-        fn run_with_user<SCU: ShaderCompilerUser>(
-            shader_compiler_user: SCU,
-            config: Self::Config,
-        ) -> SCU::ReturnType;
-    }
-}
+#[macro_use]
+pub mod backend;
 
 #[cfg(test)]
 mod test {