From: Jacob Lifshay Date: Wed, 10 Oct 2018 05:57:06 +0000 (-0700) Subject: move backend to separate file X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=3f85e1be9ec084da67bb09c2eebc5525ff5afaad;p=kazan.git move backend to separate file --- diff --git a/shader-compiler/src/backend/mod.rs b/shader-compiler/src/backend/mod.rs new file mode 100644 index 0000000..71b18e4 --- /dev/null +++ b/shader-compiler/src/backend/mod.rs @@ -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; + /// build a type + fn build(&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 { + (*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 BuildableType for UnsafeCell { + fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty { + T::build(type_builder) + } +} + +mod hidden { + pub trait ScalarBuildableTypeBase {} +} + +impl hidden::ScalarBuildableTypeBase for UnsafeCell {} + +/// trait for rust types that can be an element of a vector and be built using `TypeBuilder` +pub trait ScalarBuildableType: BuildableType + hidden::ScalarBuildableTypeBase {} + +impl ScalarBuildableType for UnsafeCell {} + +/// 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 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 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 { + 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 {} + + impl<$($arguments: BuildableType),*> ScalarBuildableType for Option {} + }; + } + +macro_rules! build_function_type { + ($($arguments:ident,)*) => { + impl BuildableType for Option 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 hidden::ScalarBuildableTypeBase for Option R> {} + + impl ScalarBuildableType for Option 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 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 { + /// elements of the vector `Self` + pub elements: [Element; $length], + } + + impl Deref for $name { + type Target = [Element; $length]; + fn deref(&self) -> &Self::Target { + &self.elements + } + } + + impl DerefMut for $name { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.elements + } + } + + impl BuildableType for $name { + 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 Vector for $name { + 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 { + #[doc(hidden)] + __Dummy(__VectorNeverType, PhantomData), + } + + impl BuildableType for $name { + 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 Vector for $name { + type Element = Element; + const LENGTH: VectorLength = { + VectorLength::Variable { + base_length: $base_length, + } + }; + } + }; +} + +/// alternate name for `VecNx1` +pub type VecN = VecNx1; + +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( + shader_compiler_user: SCU, + config: Self::Config, + ) -> SCU::ReturnType; +} diff --git a/shader-compiler/src/lib.rs b/shader-compiler/src/lib.rs index fe2ab5d..16b875e 100644 --- a/shader-compiler/src/lib.rs +++ b/shader-compiler/src/lib.rs @@ -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; - /// build a type - fn build(&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 { - (*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 BuildableType for UnsafeCell { - fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty { - T::build(type_builder) - } - } - - mod hidden { - pub trait ScalarBuildableTypeBase {} - } - - impl hidden::ScalarBuildableTypeBase for UnsafeCell {} - - /// trait for rust types that can be an element of a vector and be built using `TypeBuilder` - pub trait ScalarBuildableType: BuildableType + hidden::ScalarBuildableTypeBase {} - - impl ScalarBuildableType for UnsafeCell {} - - /// 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 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 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 { - 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 {} - - impl<$($arguments: BuildableType),*> ScalarBuildableType for Option {} - }; - } - - macro_rules! build_function_type { - ($($arguments:ident,)*) => { - impl BuildableType for Option 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 hidden::ScalarBuildableTypeBase for Option R> {} - - impl ScalarBuildableType for Option 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 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 { - /// elements of the vector `Self` - pub elements: [Element; $length], - } - - impl Deref for $name { - type Target = [Element; $length]; - fn deref(&self) -> &Self::Target { - &self.elements - } - } - - impl DerefMut for $name { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.elements - } - } - - impl BuildableType for $name { - 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 Vector for $name { - 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 { - #[doc(hidden)] - __Dummy(__VectorNeverType, PhantomData), - } - - impl BuildableType for $name { - 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 Vector for $name { - type Element = Element; - const LENGTH: VectorLength = { - VectorLength::Variable { - base_length: $base_length, - } - }; - } - }; - } - - /// alternate name for `VecNx1` - pub type VecN = VecNx1; - - 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( - shader_compiler_user: SCU, - config: Self::Config, - ) -> SCU::ReturnType; - } -} +#[macro_use] +pub mod backend; #[cfg(test)] mod test {