1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 // Copyright 2018 Jacob Lifshay
4 use shader_compiler::backend::*;
5 use std::ffi::{CStr, CString};
8 use std::os::raw::c_char;
12 pub struct LLVM7ShaderCompilerConfig {
13 pub variable_vector_length_multiplier: u32,
16 impl Default for LLVM7ShaderCompilerConfig {
17 fn default() -> Self {
19 variable_vector_length_multiplier: 1,
25 struct LLVM7String(NonNull<c_char>);
27 impl Drop for LLVM7String {
30 llvm_sys::core::LLVMDisposeMessage(self.0.as_ptr());
35 impl Deref for LLVM7String {
37 fn deref(&self) -> &CStr {
38 unsafe { CStr::from_ptr(self.0.as_ptr()) }
42 impl Clone for LLVM7String {
43 fn clone(&self) -> Self {
49 fn new(v: &CStr) -> Self {
50 unsafe { Self::from_ptr(llvm_sys::core::LLVMCreateMessage(v.as_ptr())).unwrap() }
52 unsafe fn from_nonnull(v: NonNull<c_char>) -> Self {
55 unsafe fn from_ptr(v: *mut c_char) -> Option<Self> {
56 NonNull::new(v).map(LLVM7String)
60 #[derive(Clone, Eq, PartialEq, Hash)]
62 pub struct LLVM7Type(llvm_sys::prelude::LLVMTypeRef);
64 impl fmt::Debug for LLVM7Type {
65 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
67 let string = LLVM7String::from_ptr(llvm_sys::core::LLVMPrintTypeToString(self.0))
69 f.write_str(&string.to_string_lossy())
74 impl<'a> Type<'a> for LLVM7Type {}
76 pub struct LLVM7TypeBuilder {
77 context: llvm_sys::prelude::LLVMContextRef,
78 variable_vector_length_multiplier: u32,
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)) }
86 fn build_i8(&self) -> LLVM7Type {
87 unsafe { LLVM7Type(llvm_sys::core::LLVMInt8TypeInContext(self.context)) }
89 fn build_i16(&self) -> LLVM7Type {
90 unsafe { LLVM7Type(llvm_sys::core::LLVMInt16TypeInContext(self.context)) }
92 fn build_i32(&self) -> LLVM7Type {
93 unsafe { LLVM7Type(llvm_sys::core::LLVMInt32TypeInContext(self.context)) }
95 fn build_i64(&self) -> LLVM7Type {
96 unsafe { LLVM7Type(llvm_sys::core::LLVMInt64TypeInContext(self.context)) }
98 fn build_f32(&self) -> LLVM7Type {
99 unsafe { LLVM7Type(llvm_sys::core::LLVMFloatTypeInContext(self.context)) }
101 fn build_f64(&self) -> LLVM7Type {
102 unsafe { LLVM7Type(llvm_sys::core::LLVMDoubleTypeInContext(self.context)) }
104 fn build_pointer(&self, target: LLVM7Type) -> LLVM7Type {
105 unsafe { LLVM7Type(llvm_sys::core::LLVMPointerType(target.0, 0)) }
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)) }
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)
118 assert_ne!(length, 0);
119 unsafe { LLVM7Type(llvm_sys::core::LLVMVectorType(element.0, length)) }
123 pub struct LLVM7Context {
124 context: llvm_sys::prelude::LLVMContextRef,
125 config: LLVM7ShaderCompilerConfig,
128 impl Drop for LLVM7Context {
131 llvm_sys::core::LLVMContextDispose(self.context);
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();
144 LLVM7Module(llvm_sys::core::LLVMModuleCreateWithNameInContext(
150 fn create_builder(&self) -> LLVM7Builder {
151 unsafe { LLVM7Builder(llvm_sys::core::LLVMCreateBuilderInContext(self.context)) }
153 fn create_type_builder(&self) -> LLVM7TypeBuilder {
155 context: self.context,
156 variable_vector_length_multiplier: self.config.variable_vector_length_multiplier,
162 pub struct LLVM7Builder(llvm_sys::prelude::LLVMBuilderRef);
164 impl Drop for LLVM7Builder {
167 llvm_sys::core::LLVMDisposeBuilder(self.0);
172 impl<'a> Builder<'a> for LLVM7Builder {}
175 pub struct LLVM7Module(llvm_sys::prelude::LLVMModuleRef);
177 impl Drop for LLVM7Module {
180 llvm_sys::core::LLVMDisposeModule(self.0);
185 impl<'a> Module<'a> for LLVM7Module {
186 fn set_source_file_name(&mut self, source_file_name: &str) {
188 llvm_sys::core::LLVMSetSourceFileName(
190 source_file_name.as_ptr() as *const c_char,
191 source_file_name.len(),
197 pub struct LLVM7ShaderCompiler;
199 impl ShaderCompiler for LLVM7ShaderCompiler {
200 type Config = LLVM7ShaderCompilerConfig;
201 fn name() -> &'static str {
204 fn run_with_user<SCU: ShaderCompilerUser>(
205 shader_compiler_user: SCU,
206 config: LLVM7ShaderCompilerConfig,
207 ) -> SCU::ReturnType {
208 let context = unsafe {
210 context: llvm_sys::core::LLVMContextCreate(),
214 shader_compiler_user.run_with_context(&context)