Coverage Report

Created: 2024-10-16 07:58

/rust/registry/src/index.crates.io-6f17d22bba15001f/inkwell-0.1.1/src/types/mod.rs
Line
Count
Source (jump to first uncovered line)
1
//! A type is a classification which determines how data is used.
2
3
#[deny(missing_docs)]
4
mod array_type;
5
mod enums;
6
#[deny(missing_docs)]
7
mod float_type;
8
#[deny(missing_docs)]
9
mod fn_type;
10
#[deny(missing_docs)]
11
mod int_type;
12
#[deny(missing_docs)]
13
mod metadata_type;
14
#[deny(missing_docs)]
15
mod ptr_type;
16
#[deny(missing_docs)]
17
mod struct_type;
18
#[deny(missing_docs)]
19
mod traits;
20
#[deny(missing_docs)]
21
mod vec_type;
22
#[deny(missing_docs)]
23
mod void_type;
24
25
pub use crate::types::array_type::ArrayType;
26
pub use crate::types::enums::{AnyTypeEnum, BasicMetadataTypeEnum, BasicTypeEnum};
27
pub use crate::types::float_type::FloatType;
28
pub use crate::types::fn_type::FunctionType;
29
pub use crate::types::int_type::{IntType, StringRadix};
30
pub use crate::types::metadata_type::MetadataType;
31
pub use crate::types::ptr_type::PointerType;
32
pub use crate::types::struct_type::StructType;
33
pub use crate::types::traits::{AnyType, AsTypeRef, BasicType, FloatMathType, IntMathType, PointerMathType};
34
pub use crate::types::vec_type::VectorType;
35
pub use crate::types::void_type::VoidType;
36
37
use llvm_sys::core::{
38
    LLVMAlignOf, LLVMArrayType, LLVMConstNull, LLVMConstPointerNull, LLVMFunctionType, LLVMGetElementType,
39
    LLVMGetTypeContext, LLVMGetTypeKind, LLVMGetUndef, LLVMPointerType, LLVMPrintTypeToString, LLVMSizeOf,
40
    LLVMTypeIsSized, LLVMVectorType,
41
};
42
use llvm_sys::prelude::{LLVMTypeRef, LLVMValueRef};
43
use llvm_sys::LLVMTypeKind;
44
#[cfg(feature = "experimental")]
45
use static_alloc::Bump;
46
47
use std::fmt;
48
use std::marker::PhantomData;
49
50
use crate::context::ContextRef;
51
use crate::support::LLVMString;
52
use crate::values::IntValue;
53
use crate::AddressSpace;
54
55
// Worth noting that types seem to be singletons. At the very least, primitives are.
56
// Though this is likely only true per thread since LLVM claims to not be very thread-safe.
57
#[derive(PartialEq, Eq, Clone, Copy)]
58
struct Type<'ctx> {
59
    ty: LLVMTypeRef,
60
    _marker: PhantomData<&'ctx ()>,
61
}
62
63
impl<'ctx> Type<'ctx> {
64
26.4M
    unsafe fn new(ty: LLVMTypeRef) -> Self {
65
26.4M
        assert!(!ty.is_null());
66
67
26.4M
        Type {
68
26.4M
            ty,
69
26.4M
            _marker: PhantomData,
70
26.4M
        }
71
26.4M
    }
72
73
1.52M
    fn const_zero(self) -> LLVMValueRef {
74
1.52M
        unsafe {
75
1.52M
            match LLVMGetTypeKind(self.ty) {
76
0
                LLVMTypeKind::LLVMMetadataTypeKind => LLVMConstPointerNull(self.ty),
77
1.52M
                _ => LLVMConstNull(self.ty),
78
            }
79
        }
80
1.52M
    }
81
82
3.73M
    fn ptr_type(self, address_space: AddressSpace) -> PointerType<'ctx> {
83
3.73M
        unsafe { PointerType::new(LLVMPointerType(self.ty, address_space.0)) }
84
3.73M
    }
85
86
1.69M
    fn vec_type(self, size: u32) -> VectorType<'ctx> {
87
1.69M
        assert!(size != 0, "Vectors of size zero are not allowed.");
88
        // -- https://llvm.org/docs/LangRef.html#vector-type
89
90
1.69M
        unsafe { VectorType::new(LLVMVectorType(self.ty, size)) }
91
1.69M
    }
92
93
    #[cfg(not(feature = "experimental"))]
94
11.5M
    fn fn_type(self, param_types: &[BasicMetadataTypeEnum<'ctx>], is_var_args: bool) -> FunctionType<'ctx> {
95
36.7M
        let mut param_types: Vec<LLVMTypeRef> = param_types.iter().map(|val| val.as_type_ref()).collect();
96
11.5M
        unsafe {
97
11.5M
            FunctionType::new(LLVMFunctionType(
98
11.5M
                self.ty,
99
11.5M
                param_types.as_mut_ptr(),
100
11.5M
                param_types.len() as u32,
101
11.5M
                is_var_args as i32,
102
11.5M
            ))
103
11.5M
        }
104
11.5M
    }
105
106
    #[cfg(feature = "experimental")]
107
    fn fn_type(self, param_types: &[BasicMetadataTypeEnum<'ctx>], is_var_args: bool) -> FunctionType<'ctx> {
108
        let pool: Bump<[usize; 16]> = Bump::uninit();
109
        let mut pool_start = None;
110
111
        for (i, param_type) in param_types.iter().enumerate() {
112
            let addr = pool.leak(param_type.as_type_ref()).expect("Found more than 16 params");
113
114
            if i == 0 {
115
                pool_start = Some(addr as *mut _);
116
            }
117
        }
118
119
        unsafe {
120
            FunctionType::new(LLVMFunctionType(
121
                self.ty,
122
                pool_start.unwrap_or(std::ptr::null_mut()),
123
                param_types.len() as u32,
124
                is_var_args as i32,
125
            ))
126
        }
127
    }
128
129
0
    fn array_type(self, size: u32) -> ArrayType<'ctx> {
130
0
        unsafe { ArrayType::new(LLVMArrayType(self.ty, size)) }
131
0
    }
132
133
11.6k
    fn get_undef(self) -> LLVMValueRef {
134
11.6k
        unsafe { LLVMGetUndef(self.ty) }
135
11.6k
    }
136
137
0
    fn get_alignment(self) -> IntValue<'ctx> {
138
0
        unsafe { IntValue::new(LLVMAlignOf(self.ty)) }
139
0
    }
140
141
16.0k
    fn get_context(self) -> ContextRef<'ctx> {
142
16.0k
        unsafe { ContextRef::new(LLVMGetTypeContext(self.ty)) }
143
16.0k
    }
144
145
    // REVIEW: This should be known at compile time, maybe as a const fn?
146
    // On an enum or trait, this would not be known at compile time (unless
147
    // enum has only sized types for example)
148
0
    fn is_sized(self) -> bool {
149
0
        unsafe { LLVMTypeIsSized(self.ty) == 1 }
150
0
    }
151
152
0
    fn size_of(self) -> Option<IntValue<'ctx>> {
153
0
        if !self.is_sized() {
154
0
            return None;
155
0
        }
156
0
157
0
        unsafe { Some(IntValue::new(LLVMSizeOf(self.ty))) }
158
0
    }
159
160
0
    fn print_to_string(self) -> LLVMString {
161
0
        unsafe { LLVMString::new(LLVMPrintTypeToString(self.ty)) }
162
0
    }
163
164
0
    pub fn get_element_type(self) -> AnyTypeEnum<'ctx> {
165
0
        unsafe { AnyTypeEnum::new(LLVMGetElementType(self.ty)) }
166
0
    }
167
}
168
169
impl fmt::Debug for Type<'_> {
170
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
171
0
        let llvm_type = self.print_to_string();
172
0
173
0
        f.debug_struct("Type")
174
0
            .field("address", &self.ty)
175
0
            .field("llvm_type", &llvm_type)
176
0
            .finish()
177
0
    }
178
}