1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 // Copyright 2018 Jacob Lifshay
5 //! Shader Compiler Backend Traits for Kazan
7 use std::collections::HashMap;
13 use std::marker::PhantomData;
18 /// equivalent to LLVM's 'IRBuilder'
19 pub trait AttachedBuilder<'a>: Sized {
20 /// the `Context` type
21 type Context: Context<'a>;
22 /// get the current `BasicBlock`
23 fn current_basic_block(&self) -> <Self::Context as Context<'a>>::BasicBlock;
24 /// build an alloca instruction
27 variable_type: <Self::Context as Context<'a>>::Type,
28 ) -> <Self::Context as Context<'a>>::Value;
29 /// build a return instruction
32 value: Option<<Self::Context as Context<'a>>::Value>,
33 ) -> <Self::Context as Context<'a>>::DetachedBuilder;
36 /// equivalent to LLVM's 'IRBuilder'
37 pub trait DetachedBuilder<'a>: Sized {
38 /// the `Context` type
39 type Context: Context<'a>;
40 /// attach `basic_block` to `Self`, converting into an `AttachedBuilder`
43 basic_block: <Self::Context as Context<'a>>::BuildableBasicBlock,
44 ) -> <Self::Context as Context<'a>>::AttachedBuilder;
47 /// equivalent to LLVM's 'Value'
48 pub trait Value<'a>: Clone + Debug {
49 /// the `Context` type
50 type Context: Context<'a>;
53 /// equivalent to LLVM's 'BasicBlock'
54 pub trait BasicBlock<'a>: Clone + Debug {
55 /// the `Context` type
56 type Context: Context<'a>;
57 /// get the `Value` corresponding to `Self`
58 fn as_value(&self) -> <Self::Context as Context<'a>>::Value;
61 /// equivalent to LLVM's 'BasicBlock'
62 pub trait BuildableBasicBlock<'a>: Debug + Sized {
63 /// the `Context` type
64 type Context: Context<'a>;
65 /// get the `BasicBlock` corresponding to `Self`
66 fn as_basic_block(&self) -> <Self::Context as Context<'a>>::BasicBlock;
67 /// get the `Value` corresponding to `Self`
68 fn as_value(&self) -> <Self::Context as Context<'a>>::Value {
69 self.as_basic_block().as_value()
73 /// equivalent to LLVM's 'Function'
74 pub trait Function<'a>: Debug + Sized {
75 /// the `Context` type
76 type Context: Context<'a>;
77 /// get the `Value` corresponding to `Self`
78 fn as_value(&self) -> <Self::Context as Context<'a>>::Value;
79 /// append a new `BasicBlock` to `Self`
80 fn append_new_basic_block(
83 ) -> <Self::Context as Context<'a>>::BuildableBasicBlock;
84 /// get this function's parameters
85 fn parameters(&self) -> &[<Self::Context as Context<'a>>::Value];
88 /// module verification failure; returned from `Module::verify`
89 pub struct VerificationFailure<'a, M: Module<'a>> {
92 _phantom_data: PhantomData<&'a ()>,
95 impl<'a, M: Module<'a>> VerificationFailure<'a, M> {
96 /// create a new `VerificationFailure`
97 pub fn new<T: ToString + ?Sized>(module: M, message: &T) -> Self {
100 message: message.to_string(),
101 _phantom_data: PhantomData,
104 /// get the `Module` that failed verification
105 pub fn into_module(self) -> M {
110 impl<'a, M: Module<'a>> fmt::Display for VerificationFailure<'a, M> {
111 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
112 write!(f, "module verification failure: {}", self.message,)
116 impl<'a, M: Module<'a>> Debug for VerificationFailure<'a, M> {
117 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
118 f.debug_struct("VerificationFailure")
119 .field("message", &self.message)
120 .field("module", &self.module)
125 impl<'a, M: Module<'a>> Error for VerificationFailure<'a, M> {}
127 impl<'a, M: Module<'a>> From<VerificationFailure<'a, M>> for io::Error {
128 fn from(v: VerificationFailure<'a, M>) -> Self {
129 io::Error::new(io::ErrorKind::Other, format!("{}", v))
133 /// equivalent to LLVM's 'Module'
134 pub trait Module<'a>: Debug + Sized {
135 /// the `Context` type
136 type Context: Context<'a>;
137 /// set's the source file name for this module
138 fn set_source_file_name(&mut self, source_file_name: &str);
139 /// add a new empty function to `Self`
143 ty: <Self::Context as Context<'a>>::Type,
144 ) -> <Self::Context as Context<'a>>::Function;
145 /// verify `Self`, converting into a `VerifiedModule`
148 ) -> Result<<Self::Context as Context<'a>>::VerifiedModule, VerificationFailure<'a, Self>>;
149 /// convert into a `VerifiedModule` without verifing
150 unsafe fn to_verified_module_unchecked(self) -> <Self::Context as Context<'a>>::VerifiedModule;
153 /// equivalent to LLVM's 'Module'; create using `Module::verify` or `Module::to_verified_module_unchecked`
154 pub trait VerifiedModule<'a>: Debug + Sized {
155 /// the `Context` type
156 type Context: Context<'a>;
157 /// convert back to an unverified module
158 fn into_module(self) -> <Self::Context as Context<'a>>::Module;
161 /// instance of a compiler backend; equivalent to LLVM's `LLVMContext`
162 pub trait Context<'a>: Sized + fmt::Debug {
164 type Value: Value<'a, Context = Self>;
165 /// the `BasicBlock` type
166 type BasicBlock: BasicBlock<'a, Context = Self>;
167 /// the `BuildableBasicBlock` type
168 type BuildableBasicBlock: BuildableBasicBlock<'a, Context = Self>;
169 /// the `Function` type
170 type Function: Function<'a, Context = Self>;
171 /// the `Module` type
172 type Module: Module<'a, Context = Self>;
173 /// the `VerifiedModule` type
174 type VerifiedModule: VerifiedModule<'a, Context = Self>;
175 /// the `AttachedBuilder` type
176 type AttachedBuilder: AttachedBuilder<'a, Context = Self>;
177 /// the `DetachedBuilder` type
178 type DetachedBuilder: DetachedBuilder<'a, Context = Self>;
180 type Type: types::Type<'a, Context = Self>;
181 /// the `TypeBuilder` type
182 type TypeBuilder: types::TypeBuilder<'a, Self::Type>;
183 /// create a new `Module`
184 fn create_module(&self, name: &str) -> Self::Module;
185 /// create a new `DetachedBuilder`
186 fn create_builder(&self) -> Self::DetachedBuilder;
187 /// create a new `TypeBuilder`
188 fn create_type_builder(&self) -> Self::TypeBuilder;
191 /// inputs to the final compilation
192 pub struct CompileInputs<'a, C: Context<'a>, K: Hash + Eq + Send + Sync + 'static> {
194 pub module: C::VerifiedModule,
195 /// the list of functions that can be called from the final `CompiledCode`
196 pub callable_functions: HashMap<K, C::Function>,
199 /// the final compiled code
200 pub trait CompiledCode<K: Hash + Eq + Send + Sync + 'static>: Send + Sync {
201 /// get a function in the final compiled code.
202 /// the returned function needs to be cast to the correct type and
203 /// `Self` needs to still exist while the returned function exists
204 fn get(&self, which: &K) -> Option<unsafe extern "C" fn()>;
207 /// trait that the user of `Compiler` implements
208 pub trait CompilerUser {
209 /// the type used as a key for visible functions
210 type FunctionKey: Hash + Eq + Send + Sync + 'static;
211 /// the user's error type
213 /// create an instance of `Error`
214 fn create_error(message: String) -> Self::Error;
215 /// the function that the user of `Compiler` implements
216 fn run<'a, C: Context<'a>>(
219 ) -> Result<CompileInputs<'a, C, Self::FunctionKey>, Self::Error>;
222 /// optimization mode
223 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
224 pub enum OptimizationMode {
225 /// no optimizations are enabled
227 /// default optimizations are enabled
231 impl Default for OptimizationMode {
232 fn default() -> Self {
233 OptimizationMode::Normal
237 /// compiler independent config options
238 #[derive(Clone, Debug, Default)]
239 pub struct CompilerIndependentConfig {
240 /// optimization mode
241 pub optimization_mode: OptimizationMode,
244 /// main compiler backend trait
245 pub trait Compiler: Copy + Send + Sync + 'static {
246 /// the compiler's configuration
247 type Config: Default + Clone + From<CompilerIndependentConfig> + Send + Sync;
248 /// get shader compiler's name
249 fn name(self) -> &'static str;
250 /// run a passed-in function with a new compiler context.
251 /// this round-about method is used because generic associated types are not in stable Rust yet
252 fn run<U: CompilerUser>(
255 config: Self::Config,
256 ) -> Result<Box<dyn CompiledCode<U::FunctionKey>>, U::Error>;
277 v: ::types::VecNx4<f32>,