add function parameters
[kazan.git] / shader-compiler / src / backend / mod.rs
1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 // Copyright 2018 Jacob Lifshay
3
4 //! Shader Compiler Backend traits
5
6 use std::collections::HashMap;
7 use std::error::Error;
8 use std::fmt;
9 use std::fmt::Debug;
10 use std::hash::Hash;
11 use std::io;
12 use std::marker::PhantomData;
13
14 #[macro_use]
15 pub mod types;
16
17 /// equivalent to LLVM's 'IRBuilder'
18 pub trait AttachedBuilder<'a>: Sized {
19 /// the `Context` type
20 type Context: Context<'a>;
21 /// get the current `BasicBlock`
22 fn current_basic_block(&self) -> <Self::Context as Context<'a>>::BasicBlock;
23 /// build a return instruction
24 fn build_return(
25 self,
26 value: Option<<Self::Context as Context<'a>>::Value>,
27 ) -> <Self::Context as Context<'a>>::DetachedBuilder;
28 }
29
30 /// equivalent to LLVM's 'IRBuilder'
31 pub trait DetachedBuilder<'a>: Sized {
32 /// the `Context` type
33 type Context: Context<'a>;
34 /// attach `basic_block` to `Self`, converting into an `AttachedBuilder`
35 fn attach(
36 self,
37 basic_block: <Self::Context as Context<'a>>::BuildableBasicBlock,
38 ) -> <Self::Context as Context<'a>>::AttachedBuilder;
39 }
40
41 /// equivalent to LLVM's 'Value'
42 pub trait Value<'a>: Clone + Debug {
43 /// the `Context` type
44 type Context: Context<'a>;
45 }
46
47 /// equivalent to LLVM's 'BasicBlock'
48 pub trait BasicBlock<'a>: Clone + Debug {
49 /// the `Context` type
50 type Context: Context<'a>;
51 /// get the `Value` corresponding to `Self`
52 fn as_value(&self) -> <Self::Context as Context<'a>>::Value;
53 }
54
55 /// equivalent to LLVM's 'BasicBlock'
56 pub trait BuildableBasicBlock<'a>: Debug + Sized {
57 /// the `Context` type
58 type Context: Context<'a>;
59 /// get the `BasicBlock` corresponding to `Self`
60 fn as_basic_block(&self) -> <Self::Context as Context<'a>>::BasicBlock;
61 /// get the `Value` corresponding to `Self`
62 fn as_value(&self) -> <Self::Context as Context<'a>>::Value {
63 self.as_basic_block().as_value()
64 }
65 }
66
67 /// equivalent to LLVM's 'Function'
68 pub trait Function<'a>: Debug + Sized {
69 /// the `Context` type
70 type Context: Context<'a>;
71 /// get the `Value` corresponding to `Self`
72 fn as_value(&self) -> <Self::Context as Context<'a>>::Value;
73 /// append a new `BasicBlock` to `Self`
74 fn append_new_basic_block(
75 &mut self,
76 name: Option<&str>,
77 ) -> <Self::Context as Context<'a>>::BuildableBasicBlock;
78 /// get this function's parameters
79 fn parameters(&self) -> &[<Self::Context as Context<'a>>::Value];
80 }
81
82 /// module verification failure; returned from `Module::verify`
83 pub struct VerificationFailure<'a, M: Module<'a>> {
84 module: M,
85 message: String,
86 _phantom_data: PhantomData<&'a ()>,
87 }
88
89 impl<'a, M: Module<'a>> VerificationFailure<'a, M> {
90 /// create a new `VerificationFailure`
91 pub fn new<T: ToString + ?Sized>(module: M, message: &T) -> Self {
92 VerificationFailure {
93 module,
94 message: message.to_string(),
95 _phantom_data: PhantomData,
96 }
97 }
98 /// get the `Module` that failed verification
99 pub fn into_module(self) -> M {
100 self.module
101 }
102 }
103
104 impl<'a, M: Module<'a>> fmt::Display for VerificationFailure<'a, M> {
105 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
106 write!(f, "module verification failure: {}", self.message,)
107 }
108 }
109
110 impl<'a, M: Module<'a>> Debug for VerificationFailure<'a, M> {
111 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
112 f.debug_struct("VerificationFailure")
113 .field("message", &self.message)
114 .field("module", &self.module)
115 .finish()
116 }
117 }
118
119 impl<'a, M: Module<'a>> Error for VerificationFailure<'a, M> {}
120
121 impl<'a, M: Module<'a>> From<VerificationFailure<'a, M>> for io::Error {
122 fn from(v: VerificationFailure<'a, M>) -> Self {
123 io::Error::new(io::ErrorKind::Other, format!("{}", v))
124 }
125 }
126
127 /// equivalent to LLVM's 'Module'
128 pub trait Module<'a>: Debug + Sized {
129 /// the `Context` type
130 type Context: Context<'a>;
131 /// set's the source file name for this module
132 fn set_source_file_name(&mut self, source_file_name: &str);
133 /// add a new empty function to `Self`
134 fn add_function(
135 &mut self,
136 name: &str,
137 ty: <Self::Context as Context<'a>>::Type,
138 ) -> <Self::Context as Context<'a>>::Function;
139 /// verify `Self`, converting into a `VerifiedModule`
140 fn verify(
141 self,
142 ) -> Result<<Self::Context as Context<'a>>::VerifiedModule, VerificationFailure<'a, Self>>;
143 /// convert into a `VerifiedModule` without verifing
144 unsafe fn to_verified_module_unchecked(self) -> <Self::Context as Context<'a>>::VerifiedModule;
145 }
146
147 /// equivalent to LLVM's 'Module'; create using `Module::verify` or `Module::to_verified_module_unchecked`
148 pub trait VerifiedModule<'a>: Debug + Sized {
149 /// the `Context` type
150 type Context: Context<'a>;
151 /// convert back to an unverified module
152 fn into_module(self) -> <Self::Context as Context<'a>>::Module;
153 }
154
155 /// instance of a compiler backend; equivalent to LLVM's `LLVMContext`
156 pub trait Context<'a>: Sized {
157 /// the `Value` type
158 type Value: Value<'a, Context = Self>;
159 /// the `BasicBlock` type
160 type BasicBlock: BasicBlock<'a, Context = Self>;
161 /// the `BuildableBasicBlock` type
162 type BuildableBasicBlock: BuildableBasicBlock<'a, Context = Self>;
163 /// the `Function` type
164 type Function: Function<'a, Context = Self>;
165 /// the `Module` type
166 type Module: Module<'a, Context = Self>;
167 /// the `VerifiedModule` type
168 type VerifiedModule: VerifiedModule<'a, Context = Self>;
169 /// the `AttachedBuilder` type
170 type AttachedBuilder: AttachedBuilder<'a, Context = Self>;
171 /// the `DetachedBuilder` type
172 type DetachedBuilder: DetachedBuilder<'a, Context = Self>;
173 /// the `Type` type
174 type Type: types::Type<'a, Context = Self>;
175 /// the `TypeBuilder` type
176 type TypeBuilder: types::TypeBuilder<'a, Self::Type>;
177 /// create a new `Module`
178 fn create_module(&self, name: &str) -> Self::Module;
179 /// create a new `DetachedBuilder`
180 fn create_builder(&self) -> Self::DetachedBuilder;
181 /// create a new `TypeBuilder`
182 fn create_type_builder(&self) -> Self::TypeBuilder;
183 }
184
185 /// inputs to the final compilation
186 pub struct CompileInputs<'a, C: Context<'a>, K: Hash + Eq + Send + Sync + 'static> {
187 /// the input module
188 pub module: C::VerifiedModule,
189 /// the list of functions that can be called from the final `CompiledCode`
190 pub callable_functions: HashMap<K, C::Function>,
191 }
192
193 /// the final compiled code
194 pub trait CompiledCode<K: Hash + Eq + Send + Sync + 'static>: Send + Sync {
195 /// get a function in the final compiled code.
196 /// the returned function needs to be cast to the correct type and
197 /// `Self` needs to still exist while the returned function exists
198 fn get(&self, which: &K) -> Option<unsafe extern "C" fn()>;
199 }
200
201 /// trait that the user of `Compiler` implements
202 pub trait CompilerUser {
203 /// the type used as a key for visible functions
204 type FunctionKey: Hash + Eq + Send + Sync + 'static;
205 /// the user's error type
206 type Error;
207 /// create an instance of `Error`
208 fn create_error(message: String) -> Self::Error;
209 /// the function that the user of `Compiler` implements
210 fn run<'a, C: Context<'a>>(
211 self,
212 context: &'a C,
213 ) -> Result<CompileInputs<'a, C, Self::FunctionKey>, Self::Error>;
214 }
215
216 /// optimization mode
217 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
218 pub enum OptimizationMode {
219 /// no optimizations are enabled
220 NoOptimizations,
221 /// default optimizations are enabled
222 Normal,
223 }
224
225 impl Default for OptimizationMode {
226 fn default() -> Self {
227 OptimizationMode::Normal
228 }
229 }
230
231 /// compiler independent config options
232 #[derive(Clone, Debug, Default)]
233 pub struct CompilerIndependentConfig {
234 /// optimization mode
235 pub optimization_mode: OptimizationMode,
236 }
237
238 /// main compiler backend trait
239 pub trait Compiler: Copy + Send + Sync + 'static {
240 /// the compiler's configuration
241 type Config: Default + Clone + From<CompilerIndependentConfig> + Send + Sync;
242 /// get shader compiler's name
243 fn name(self) -> &'static str;
244 /// run a passed-in function with a new compiler context.
245 /// this round-about method is used because generic associated types are not in stable Rust yet
246 fn run<U: CompilerUser>(
247 self,
248 user: U,
249 config: Self::Config,
250 ) -> Result<Box<dyn CompiledCode<U::FunctionKey>>, U::Error>;
251 }