working on shader compiler
[kazan.git] / shader-compiler-llvm-7 / src / backend.rs
1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 // Copyright 2018 Jacob Lifshay
3 use llvm_sys;
4 use shader_compiler::backend::*;
5 use std::ffi::{CStr, CString};
6 use std::fmt;
7 use std::ops::Deref;
8 use std::os::raw::c_char;
9 use std::ptr::NonNull;
10
11 #[derive(Clone)]
12 pub struct LLVM7ShaderCompilerConfig {
13 pub variable_vector_length_multiplier: u32,
14 }
15
16 impl Default for LLVM7ShaderCompilerConfig {
17 fn default() -> Self {
18 Self {
19 variable_vector_length_multiplier: 1,
20 }
21 }
22 }
23
24 #[repr(transparent)]
25 struct LLVM7String(NonNull<c_char>);
26
27 impl Drop for LLVM7String {
28 fn drop(&mut self) {
29 unsafe {
30 llvm_sys::core::LLVMDisposeMessage(self.0.as_ptr());
31 }
32 }
33 }
34
35 impl Deref for LLVM7String {
36 type Target = CStr;
37 fn deref(&self) -> &CStr {
38 unsafe { CStr::from_ptr(self.0.as_ptr()) }
39 }
40 }
41
42 impl Clone for LLVM7String {
43 fn clone(&self) -> Self {
44 Self::new(self)
45 }
46 }
47
48 impl LLVM7String {
49 fn new(v: &CStr) -> Self {
50 unsafe { Self::from_ptr(llvm_sys::core::LLVMCreateMessage(v.as_ptr())).unwrap() }
51 }
52 unsafe fn from_nonnull(v: NonNull<c_char>) -> Self {
53 LLVM7String(v)
54 }
55 unsafe fn from_ptr(v: *mut c_char) -> Option<Self> {
56 NonNull::new(v).map(LLVM7String)
57 }
58 }
59
60 #[derive(Clone, Eq, PartialEq, Hash)]
61 #[repr(transparent)]
62 pub struct LLVM7Type(llvm_sys::prelude::LLVMTypeRef);
63
64 impl fmt::Debug for LLVM7Type {
65 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
66 unsafe {
67 let string = LLVM7String::from_ptr(llvm_sys::core::LLVMPrintTypeToString(self.0))
68 .ok_or(fmt::Error)?;
69 f.write_str(&string.to_string_lossy())
70 }
71 }
72 }
73
74 impl<'a> Type<'a> for LLVM7Type {}
75
76 pub struct LLVM7TypeBuilder {
77 context: llvm_sys::prelude::LLVMContextRef,
78 variable_vector_length_multiplier: u32,
79 }
80
81 impl<'a> TypeBuilder<'a> for LLVM7TypeBuilder {
82 type Type = LLVM7Type;
83 fn build_bool(&self) -> LLVM7Type {
84 unsafe { LLVM7Type(llvm_sys::core::LLVMInt1TypeInContext(self.context)) }
85 }
86 fn build_i8(&self) -> LLVM7Type {
87 unsafe { LLVM7Type(llvm_sys::core::LLVMInt8TypeInContext(self.context)) }
88 }
89 fn build_i16(&self) -> LLVM7Type {
90 unsafe { LLVM7Type(llvm_sys::core::LLVMInt16TypeInContext(self.context)) }
91 }
92 fn build_i32(&self) -> LLVM7Type {
93 unsafe { LLVM7Type(llvm_sys::core::LLVMInt32TypeInContext(self.context)) }
94 }
95 fn build_i64(&self) -> LLVM7Type {
96 unsafe { LLVM7Type(llvm_sys::core::LLVMInt64TypeInContext(self.context)) }
97 }
98 fn build_f32(&self) -> LLVM7Type {
99 unsafe { LLVM7Type(llvm_sys::core::LLVMFloatTypeInContext(self.context)) }
100 }
101 fn build_f64(&self) -> LLVM7Type {
102 unsafe { LLVM7Type(llvm_sys::core::LLVMDoubleTypeInContext(self.context)) }
103 }
104 fn build_pointer(&self, target: LLVM7Type) -> LLVM7Type {
105 unsafe { LLVM7Type(llvm_sys::core::LLVMPointerType(target.0, 0)) }
106 }
107 fn build_array(&self, element: LLVM7Type, count: usize) -> LLVM7Type {
108 assert_eq!(count as u32 as usize, count);
109 unsafe { LLVM7Type(llvm_sys::core::LLVMArrayType(element.0, count as u32)) }
110 }
111 fn build_vector(&self, element: LLVM7Type, length: VectorLength) -> LLVM7Type {
112 let length = match length {
113 VectorLength::Fixed { length } => length,
114 VectorLength::Variable { base_length } => base_length
115 .checked_mul(self.variable_vector_length_multiplier)
116 .unwrap(),
117 };
118 assert_ne!(length, 0);
119 unsafe { LLVM7Type(llvm_sys::core::LLVMVectorType(element.0, length)) }
120 }
121 }
122
123 pub struct LLVM7Context {
124 context: llvm_sys::prelude::LLVMContextRef,
125 config: LLVM7ShaderCompilerConfig,
126 }
127
128 impl Drop for LLVM7Context {
129 fn drop(&mut self) {
130 unsafe {
131 llvm_sys::core::LLVMContextDispose(self.context);
132 }
133 }
134 }
135
136 impl<'a> Context<'a> for LLVM7Context {
137 type Type = LLVM7Type;
138 type TypeBuilder = LLVM7TypeBuilder;
139 type Module = LLVM7Module;
140 type Builder = LLVM7Builder;
141 fn create_module(&self, name: &str) -> LLVM7Module {
142 let name = CString::new(name).unwrap();
143 unsafe {
144 LLVM7Module(llvm_sys::core::LLVMModuleCreateWithNameInContext(
145 name.as_ptr(),
146 self.context,
147 ))
148 }
149 }
150 fn create_builder(&self) -> LLVM7Builder {
151 unsafe { LLVM7Builder(llvm_sys::core::LLVMCreateBuilderInContext(self.context)) }
152 }
153 fn create_type_builder(&self) -> LLVM7TypeBuilder {
154 LLVM7TypeBuilder {
155 context: self.context,
156 variable_vector_length_multiplier: self.config.variable_vector_length_multiplier,
157 }
158 }
159 }
160
161 #[repr(transparent)]
162 pub struct LLVM7Builder(llvm_sys::prelude::LLVMBuilderRef);
163
164 impl Drop for LLVM7Builder {
165 fn drop(&mut self) {
166 unsafe {
167 llvm_sys::core::LLVMDisposeBuilder(self.0);
168 }
169 }
170 }
171
172 impl<'a> Builder<'a> for LLVM7Builder {}
173
174 #[repr(transparent)]
175 pub struct LLVM7Module(llvm_sys::prelude::LLVMModuleRef);
176
177 impl Drop for LLVM7Module {
178 fn drop(&mut self) {
179 unsafe {
180 llvm_sys::core::LLVMDisposeModule(self.0);
181 }
182 }
183 }
184
185 impl<'a> Module<'a> for LLVM7Module {
186 fn set_source_file_name(&mut self, source_file_name: &str) {
187 unsafe {
188 llvm_sys::core::LLVMSetSourceFileName(
189 self.0,
190 source_file_name.as_ptr() as *const c_char,
191 source_file_name.len(),
192 )
193 }
194 }
195 }
196
197 pub struct LLVM7ShaderCompiler;
198
199 impl ShaderCompiler for LLVM7ShaderCompiler {
200 type Config = LLVM7ShaderCompilerConfig;
201 fn name() -> &'static str {
202 "LLVM 7"
203 }
204 fn run_with_user<SCU: ShaderCompilerUser>(
205 shader_compiler_user: SCU,
206 config: LLVM7ShaderCompilerConfig,
207 ) -> SCU::ReturnType {
208 let context = unsafe {
209 LLVM7Context {
210 context: llvm_sys::core::LLVMContextCreate(),
211 config,
212 }
213 };
214 shader_compiler_user.run_with_context(&context)
215 }
216 }