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 a return instruction
27 value: Option<<Self::Context as Context<'a>>::Value>,
28 ) -> <Self::Context as Context<'a>>::DetachedBuilder;
31 /// equivalent to LLVM's 'IRBuilder'
32 pub trait DetachedBuilder<'a>: Sized {
33 /// the `Context` type
34 type Context: Context<'a>;
35 /// attach `basic_block` to `Self`, converting into an `AttachedBuilder`
38 basic_block: <Self::Context as Context<'a>>::BuildableBasicBlock,
39 ) -> <Self::Context as Context<'a>>::AttachedBuilder;
42 /// equivalent to LLVM's 'Value'
43 pub trait Value<'a>: Clone + Debug {
44 /// the `Context` type
45 type Context: Context<'a>;
48 /// equivalent to LLVM's 'BasicBlock'
49 pub trait BasicBlock<'a>: Clone + Debug {
50 /// the `Context` type
51 type Context: Context<'a>;
52 /// get the `Value` corresponding to `Self`
53 fn as_value(&self) -> <Self::Context as Context<'a>>::Value;
56 /// equivalent to LLVM's 'BasicBlock'
57 pub trait BuildableBasicBlock<'a>: Debug + Sized {
58 /// the `Context` type
59 type Context: Context<'a>;
60 /// get the `BasicBlock` corresponding to `Self`
61 fn as_basic_block(&self) -> <Self::Context as Context<'a>>::BasicBlock;
62 /// get the `Value` corresponding to `Self`
63 fn as_value(&self) -> <Self::Context as Context<'a>>::Value {
64 self.as_basic_block().as_value()
68 /// equivalent to LLVM's 'Function'
69 pub trait Function<'a>: Debug + Sized {
70 /// the `Context` type
71 type Context: Context<'a>;
72 /// get the `Value` corresponding to `Self`
73 fn as_value(&self) -> <Self::Context as Context<'a>>::Value;
74 /// append a new `BasicBlock` to `Self`
75 fn append_new_basic_block(
78 ) -> <Self::Context as Context<'a>>::BuildableBasicBlock;
79 /// get this function's parameters
80 fn parameters(&self) -> &[<Self::Context as Context<'a>>::Value];
83 /// module verification failure; returned from `Module::verify`
84 pub struct VerificationFailure<'a, M: Module<'a>> {
87 _phantom_data: PhantomData<&'a ()>,
90 impl<'a, M: Module<'a>> VerificationFailure<'a, M> {
91 /// create a new `VerificationFailure`
92 pub fn new<T: ToString + ?Sized>(module: M, message: &T) -> Self {
95 message: message.to_string(),
96 _phantom_data: PhantomData,
99 /// get the `Module` that failed verification
100 pub fn into_module(self) -> M {
105 impl<'a, M: Module<'a>> fmt::Display for VerificationFailure<'a, M> {
106 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
107 write!(f, "module verification failure: {}", self.message,)
111 impl<'a, M: Module<'a>> Debug for VerificationFailure<'a, M> {
112 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
113 f.debug_struct("VerificationFailure")
114 .field("message", &self.message)
115 .field("module", &self.module)
120 impl<'a, M: Module<'a>> Error for VerificationFailure<'a, M> {}
122 impl<'a, M: Module<'a>> From<VerificationFailure<'a, M>> for io::Error {
123 fn from(v: VerificationFailure<'a, M>) -> Self {
124 io::Error::new(io::ErrorKind::Other, format!("{}", v))
128 /// equivalent to LLVM's 'Module'
129 pub trait Module<'a>: Debug + Sized {
130 /// the `Context` type
131 type Context: Context<'a>;
132 /// set's the source file name for this module
133 fn set_source_file_name(&mut self, source_file_name: &str);
134 /// add a new empty function to `Self`
138 ty: <Self::Context as Context<'a>>::Type,
139 ) -> <Self::Context as Context<'a>>::Function;
140 /// verify `Self`, converting into a `VerifiedModule`
143 ) -> Result<<Self::Context as Context<'a>>::VerifiedModule, VerificationFailure<'a, Self>>;
144 /// convert into a `VerifiedModule` without verifing
145 unsafe fn to_verified_module_unchecked(self) -> <Self::Context as Context<'a>>::VerifiedModule;
148 /// equivalent to LLVM's 'Module'; create using `Module::verify` or `Module::to_verified_module_unchecked`
149 pub trait VerifiedModule<'a>: Debug + Sized {
150 /// the `Context` type
151 type Context: Context<'a>;
152 /// convert back to an unverified module
153 fn into_module(self) -> <Self::Context as Context<'a>>::Module;
156 /// instance of a compiler backend; equivalent to LLVM's `LLVMContext`
157 pub trait Context<'a>: Sized {
159 type Value: Value<'a, Context = Self>;
160 /// the `BasicBlock` type
161 type BasicBlock: BasicBlock<'a, Context = Self>;
162 /// the `BuildableBasicBlock` type
163 type BuildableBasicBlock: BuildableBasicBlock<'a, Context = Self>;
164 /// the `Function` type
165 type Function: Function<'a, Context = Self>;
166 /// the `Module` type
167 type Module: Module<'a, Context = Self>;
168 /// the `VerifiedModule` type
169 type VerifiedModule: VerifiedModule<'a, Context = Self>;
170 /// the `AttachedBuilder` type
171 type AttachedBuilder: AttachedBuilder<'a, Context = Self>;
172 /// the `DetachedBuilder` type
173 type DetachedBuilder: DetachedBuilder<'a, Context = Self>;
175 type Type: types::Type<'a, Context = Self>;
176 /// the `TypeBuilder` type
177 type TypeBuilder: types::TypeBuilder<'a, Self::Type>;
178 /// create a new `Module`
179 fn create_module(&self, name: &str) -> Self::Module;
180 /// create a new `DetachedBuilder`
181 fn create_builder(&self) -> Self::DetachedBuilder;
182 /// create a new `TypeBuilder`
183 fn create_type_builder(&self) -> Self::TypeBuilder;
186 /// inputs to the final compilation
187 pub struct CompileInputs<'a, C: Context<'a>, K: Hash + Eq + Send + Sync + 'static> {
189 pub module: C::VerifiedModule,
190 /// the list of functions that can be called from the final `CompiledCode`
191 pub callable_functions: HashMap<K, C::Function>,
194 /// the final compiled code
195 pub trait CompiledCode<K: Hash + Eq + Send + Sync + 'static>: Send + Sync {
196 /// get a function in the final compiled code.
197 /// the returned function needs to be cast to the correct type and
198 /// `Self` needs to still exist while the returned function exists
199 fn get(&self, which: &K) -> Option<unsafe extern "C" fn()>;
202 /// trait that the user of `Compiler` implements
203 pub trait CompilerUser {
204 /// the type used as a key for visible functions
205 type FunctionKey: Hash + Eq + Send + Sync + 'static;
206 /// the user's error type
208 /// create an instance of `Error`
209 fn create_error(message: String) -> Self::Error;
210 /// the function that the user of `Compiler` implements
211 fn run<'a, C: Context<'a>>(
214 ) -> Result<CompileInputs<'a, C, Self::FunctionKey>, Self::Error>;
217 /// optimization mode
218 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
219 pub enum OptimizationMode {
220 /// no optimizations are enabled
222 /// default optimizations are enabled
226 impl Default for OptimizationMode {
227 fn default() -> Self {
228 OptimizationMode::Normal
232 /// compiler independent config options
233 #[derive(Clone, Debug, Default)]
234 pub struct CompilerIndependentConfig {
235 /// optimization mode
236 pub optimization_mode: OptimizationMode,
239 /// main compiler backend trait
240 pub trait Compiler: Copy + Send + Sync + 'static {
241 /// the compiler's configuration
242 type Config: Default + Clone + From<CompilerIndependentConfig> + Send + Sync;
243 /// get shader compiler's name
244 fn name(self) -> &'static str;
245 /// run a passed-in function with a new compiler context.
246 /// this round-about method is used because generic associated types are not in stable Rust yet
247 fn run<U: CompilerUser>(
250 config: Self::Config,
251 ) -> Result<Box<dyn CompiledCode<U::FunctionKey>>, U::Error>;
272 v: ::types::VecNx4<f32>,