Coverage Report

Created: 2024-10-16 07:58

/rust/registry/src/index.crates.io-6f17d22bba15001f/inkwell-0.1.1/src/values/global_value.rs
Line
Count
Source (jump to first uncovered line)
1
#[llvm_versions(8.0..=latest)]
2
use llvm_sys::core::LLVMGlobalSetMetadata;
3
#[llvm_versions(4.0..=7.0)]
4
use llvm_sys::core::{
5
    LLVMDeleteGlobal, LLVMGetAlignment, LLVMGetDLLStorageClass, LLVMGetInitializer, LLVMGetLinkage, LLVMGetNextGlobal,
6
    LLVMGetPreviousGlobal, LLVMGetSection, LLVMGetThreadLocalMode, LLVMGetVisibility, LLVMIsDeclaration,
7
    LLVMIsExternallyInitialized, LLVMIsGlobalConstant, LLVMIsThreadLocal, LLVMSetAlignment, LLVMSetDLLStorageClass,
8
    LLVMSetExternallyInitialized, LLVMSetGlobalConstant, LLVMSetInitializer, LLVMSetLinkage, LLVMSetSection,
9
    LLVMSetThreadLocal, LLVMSetThreadLocalMode, LLVMSetVisibility,
10
};
11
#[llvm_versions(8.0..=latest)]
12
use llvm_sys::core::{
13
    LLVMDeleteGlobal, LLVMGetAlignment, LLVMGetDLLStorageClass, LLVMGetInitializer, LLVMGetLinkage, LLVMGetNextGlobal,
14
    LLVMGetPreviousGlobal, LLVMGetThreadLocalMode, LLVMGetVisibility, LLVMIsDeclaration, LLVMIsExternallyInitialized,
15
    LLVMIsGlobalConstant, LLVMIsThreadLocal, LLVMSetAlignment, LLVMSetDLLStorageClass, LLVMSetExternallyInitialized,
16
    LLVMSetGlobalConstant, LLVMSetInitializer, LLVMSetLinkage, LLVMSetThreadLocal, LLVMSetThreadLocalMode,
17
    LLVMSetVisibility,
18
};
19
#[llvm_versions(7.0..=latest)]
20
use llvm_sys::core::{LLVMGetUnnamedAddress, LLVMSetUnnamedAddress};
21
#[llvm_versions(4.0..=6.0)]
22
use llvm_sys::core::{LLVMHasUnnamedAddr, LLVMSetUnnamedAddr};
23
use llvm_sys::prelude::LLVMValueRef;
24
use llvm_sys::LLVMThreadLocalMode;
25
#[llvm_versions(7.0..=latest)]
26
use llvm_sys::LLVMUnnamedAddr;
27
28
use std::ffi::CStr;
29
use std::fmt::{self, Display};
30
31
#[llvm_versions(7.0..=latest)]
32
use crate::comdat::Comdat;
33
use crate::module::Linkage;
34
use crate::values::traits::AsValueRef;
35
#[llvm_versions(8.0..=latest)]
36
use crate::values::MetadataValue;
37
use crate::values::{BasicValue, BasicValueEnum, PointerValue, Value};
38
use crate::{DLLStorageClass, GlobalVisibility, ThreadLocalMode};
39
40
use super::AnyValue;
41
42
// REVIEW: GlobalValues are always PointerValues. With SubTypes, we should
43
// compress this into a PointerValue<Global> type
44
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
45
pub struct GlobalValue<'ctx> {
46
    global_value: Value<'ctx>,
47
}
48
49
impl<'ctx> GlobalValue<'ctx> {
50
483k
    pub(crate) unsafe fn new(value: LLVMValueRef) -> Self {
51
483k
        assert!(!value.is_null());
52
53
483k
        GlobalValue {
54
483k
            global_value: Value::new(value),
55
483k
        }
56
483k
    }
57
58
    /// Get name of the `GlobalValue`.
59
0
    pub fn get_name(&self) -> &CStr {
60
0
        self.global_value.get_name()
61
0
    }
62
63
    /// Set name of the `GlobalValue`.
64
0
    pub fn set_name(&self, name: &str) {
65
0
        self.global_value.set_name(name)
66
0
    }
67
68
0
    pub fn get_previous_global(self) -> Option<GlobalValue<'ctx>> {
69
0
        let value = unsafe { LLVMGetPreviousGlobal(self.as_value_ref()) };
70
0
71
0
        if value.is_null() {
72
0
            return None;
73
0
        }
74
0
75
0
        unsafe { Some(GlobalValue::new(value)) }
76
0
    }
77
78
0
    pub fn get_next_global(self) -> Option<GlobalValue<'ctx>> {
79
0
        let value = unsafe { LLVMGetNextGlobal(self.as_value_ref()) };
80
0
81
0
        if value.is_null() {
82
0
            return None;
83
0
        }
84
0
85
0
        unsafe { Some(GlobalValue::new(value)) }
86
0
    }
87
88
0
    pub fn get_dll_storage_class(self) -> DLLStorageClass {
89
0
        let dll_storage_class = unsafe { LLVMGetDLLStorageClass(self.as_value_ref()) };
90
0
91
0
        DLLStorageClass::new(dll_storage_class)
92
0
    }
93
94
159k
    pub fn set_dll_storage_class(self, dll_storage_class: DLLStorageClass) {
95
159k
        unsafe { LLVMSetDLLStorageClass(self.as_value_ref(), dll_storage_class.into()) }
96
159k
    }
97
98
0
    pub fn get_initializer(self) -> Option<BasicValueEnum<'ctx>> {
99
0
        let value = unsafe { LLVMGetInitializer(self.as_value_ref()) };
100
0
101
0
        if value.is_null() {
102
0
            return None;
103
0
        }
104
0
105
0
        unsafe { Some(BasicValueEnum::new(value)) }
106
0
    }
107
108
    // SubType: This input type should be tied to the BasicType
109
0
    pub fn set_initializer(self, value: &dyn BasicValue<'ctx>) {
110
0
        unsafe { LLVMSetInitializer(self.as_value_ref(), value.as_value_ref()) }
111
0
    }
112
113
0
    pub fn is_thread_local(self) -> bool {
114
0
        unsafe { LLVMIsThreadLocal(self.as_value_ref()) == 1 }
115
0
    }
116
117
    // TODOC: Setting this to true is the same as setting GeneralDynamicTLSModel
118
0
    pub fn set_thread_local(self, is_thread_local: bool) {
119
0
        unsafe { LLVMSetThreadLocal(self.as_value_ref(), is_thread_local as i32) }
120
0
    }
121
122
0
    pub fn get_thread_local_mode(self) -> Option<ThreadLocalMode> {
123
0
        let thread_local_mode = unsafe { LLVMGetThreadLocalMode(self.as_value_ref()) };
124
0
125
0
        ThreadLocalMode::new(thread_local_mode)
126
0
    }
127
128
    // REVIEW: Does this have any bad behavior if it isn't thread local or just a noop?
129
    // or should it call self.set_thread_local(true)?
130
0
    pub fn set_thread_local_mode(self, thread_local_mode: Option<ThreadLocalMode>) {
131
0
        let thread_local_mode = match thread_local_mode {
132
0
            Some(mode) => mode.as_llvm_mode(),
133
0
            None => LLVMThreadLocalMode::LLVMNotThreadLocal,
134
        };
135
136
0
        unsafe { LLVMSetThreadLocalMode(self.as_value_ref(), thread_local_mode) }
137
0
    }
138
139
    // SubType: This should be moved into the type. GlobalValue<Initialized/Uninitialized>
140
    /// Determines whether or not a `GlobalValue` is a declaration or a definition.
141
    ///
142
    /// # Example
143
    ///
144
    /// ```no_run
145
    /// use inkwell::context::Context;
146
    ///
147
    /// let context = Context::create();
148
    /// let builder = context.create_builder();
149
    /// let module = context.create_module("my_mod");
150
    /// let void_type = context.void_type();
151
    /// let fn_type = void_type.fn_type(&[], false);
152
    /// let fn_value = module.add_function("my_func", fn_type, None);
153
    ///
154
    /// assert!(fn_value.as_global_value().is_declaration());
155
    ///
156
    /// context.append_basic_block(fn_value, "entry");
157
    ///
158
    /// assert!(!fn_value.as_global_value().is_declaration());
159
    /// ```
160
0
    pub fn is_declaration(self) -> bool {
161
0
        unsafe { LLVMIsDeclaration(self.as_value_ref()) == 1 }
162
0
    }
163
164
    #[llvm_versions(4.0..=6.0)]
165
    pub fn has_unnamed_addr(self) -> bool {
166
        unsafe { LLVMHasUnnamedAddr(self.as_value_ref()) == 1 }
167
    }
168
169
    #[llvm_versions(7.0..=latest)]
170
0
    pub fn has_unnamed_addr(self) -> bool {
171
0
        unsafe { LLVMGetUnnamedAddress(self.as_value_ref()) == LLVMUnnamedAddr::LLVMGlobalUnnamedAddr }
172
0
    }
173
174
    #[llvm_versions(4.0..=6.0)]
175
    pub fn set_unnamed_addr(self, has_unnamed_addr: bool) {
176
        unsafe { LLVMSetUnnamedAddr(self.as_value_ref(), has_unnamed_addr as i32) }
177
    }
178
179
    #[llvm_versions(7.0..=latest)]
180
0
    pub fn set_unnamed_addr(self, has_unnamed_addr: bool) {
181
0
        unsafe {
182
0
            if has_unnamed_addr {
183
0
                LLVMSetUnnamedAddress(self.as_value_ref(), UnnamedAddress::Global.into())
184
            } else {
185
0
                LLVMSetUnnamedAddress(self.as_value_ref(), UnnamedAddress::None.into())
186
            }
187
        }
188
0
    }
189
190
0
    pub fn is_constant(self) -> bool {
191
0
        unsafe { LLVMIsGlobalConstant(self.as_value_ref()) == 1 }
192
0
    }
193
194
0
    pub fn set_constant(self, is_constant: bool) {
195
0
        unsafe { LLVMSetGlobalConstant(self.as_value_ref(), is_constant as i32) }
196
0
    }
197
198
0
    pub fn is_externally_initialized(self) -> bool {
199
0
        unsafe { LLVMIsExternallyInitialized(self.as_value_ref()) == 1 }
200
0
    }
201
202
0
    pub fn set_externally_initialized(self, externally_initialized: bool) {
203
0
        unsafe { LLVMSetExternallyInitialized(self.as_value_ref(), externally_initialized as i32) }
204
0
    }
205
206
0
    pub fn set_visibility(self, visibility: GlobalVisibility) {
207
0
        unsafe { LLVMSetVisibility(self.as_value_ref(), visibility.into()) }
208
0
    }
209
210
0
    pub fn get_visibility(self) -> GlobalVisibility {
211
0
        let visibility = unsafe { LLVMGetVisibility(self.as_value_ref()) };
212
0
213
0
        GlobalVisibility::new(visibility)
214
0
    }
215
216
    /// Get section, this global value belongs to
217
0
    pub fn get_section(&self) -> Option<&CStr> {
218
0
        self.global_value.get_section()
219
0
    }
220
221
    /// Set section, this global value belongs to
222
159k
    pub fn set_section(self, section: Option<&str>) {
223
159k
        self.global_value.set_section(section)
224
159k
    }
225
226
0
    pub unsafe fn delete(self) {
227
0
        LLVMDeleteGlobal(self.as_value_ref())
228
0
    }
229
230
107k
    pub fn as_pointer_value(self) -> PointerValue<'ctx> {
231
107k
        unsafe { PointerValue::new(self.as_value_ref()) }
232
107k
    }
233
234
0
    pub fn get_alignment(self) -> u32 {
235
0
        unsafe { LLVMGetAlignment(self.as_value_ref()) }
236
0
    }
237
238
0
    pub fn set_alignment(self, alignment: u32) {
239
0
        unsafe { LLVMSetAlignment(self.as_value_ref(), alignment) }
240
0
    }
241
242
    /// Sets a metadata of the given type on the GlobalValue
243
    #[llvm_versions(8.0..=latest)]
244
0
    pub fn set_metadata(self, metadata: MetadataValue<'ctx>, kind_id: u32) {
245
0
        unsafe { LLVMGlobalSetMetadata(self.as_value_ref(), kind_id, metadata.as_metadata_ref()) }
246
0
    }
247
248
    /// Gets a `Comdat` assigned to this `GlobalValue`, if any.
249
    #[llvm_versions(7.0..=latest)]
250
0
    pub fn get_comdat(self) -> Option<Comdat> {
251
0
        use llvm_sys::comdat::LLVMGetComdat;
252
0
253
0
        let comdat_ptr = unsafe { LLVMGetComdat(self.as_value_ref()) };
254
0
255
0
        if comdat_ptr.is_null() {
256
0
            return None;
257
0
        }
258
0
259
0
        unsafe { Some(Comdat::new(comdat_ptr)) }
260
0
    }
261
262
    /// Assigns a `Comdat` to this `GlobalValue`.
263
    #[llvm_versions(7.0..=latest)]
264
0
    pub fn set_comdat(self, comdat: Comdat) {
265
0
        use llvm_sys::comdat::LLVMSetComdat;
266
0
267
0
        unsafe { LLVMSetComdat(self.as_value_ref(), comdat.0) }
268
0
    }
269
270
    #[llvm_versions(7.0..=latest)]
271
0
    pub fn get_unnamed_address(self) -> UnnamedAddress {
272
0
        use llvm_sys::core::LLVMGetUnnamedAddress;
273
0
274
0
        let unnamed_address = unsafe { LLVMGetUnnamedAddress(self.as_value_ref()) };
275
0
276
0
        UnnamedAddress::new(unnamed_address)
277
0
    }
278
279
    #[llvm_versions(7.0..=latest)]
280
0
    pub fn set_unnamed_address(self, address: UnnamedAddress) {
281
0
        use llvm_sys::core::LLVMSetUnnamedAddress;
282
0
283
0
        unsafe { LLVMSetUnnamedAddress(self.as_value_ref(), address.into()) }
284
0
    }
285
286
0
    pub fn get_linkage(self) -> Linkage {
287
0
        unsafe { LLVMGetLinkage(self.as_value_ref()).into() }
288
0
    }
289
290
57.2k
    pub fn set_linkage(self, linkage: Linkage) {
291
57.2k
        unsafe { LLVMSetLinkage(self.as_value_ref(), linkage.into()) }
292
57.2k
    }
293
}
294
295
unsafe impl AsValueRef for GlobalValue<'_> {
296
323k
    fn as_value_ref(&self) -> LLVMValueRef {
297
323k
        self.global_value.value
298
323k
    }
299
}
300
301
impl Display for GlobalValue<'_> {
302
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
303
0
        write!(f, "{}", self.print_to_string())
304
0
    }
305
}
306
307
/// This enum determines the significance of a `GlobalValue`'s address.
308
#[llvm_versions(7.0..=latest)]
309
0
#[llvm_enum(LLVMUnnamedAddr)]
Unexecuted instantiation: <inkwell::values::global_value::UnnamedAddress as core::convert::Into<llvm_sys::LLVMUnnamedAddr>>::into
Unexecuted instantiation: <inkwell::values::global_value::UnnamedAddress>::new
Unexecuted instantiation: <inkwell::values::global_value::UnnamedAddress as core::convert::From<llvm_sys::LLVMUnnamedAddr>>::from
310
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
311
pub enum UnnamedAddress {
312
    /// Address of the `GlobalValue` is significant.
313
    #[llvm_variant(LLVMNoUnnamedAddr)]
314
    None,
315
316
    /// Address of the `GlobalValue` is locally insignificant.
317
    #[llvm_variant(LLVMLocalUnnamedAddr)]
318
    Local,
319
320
    /// Address of the `GlobalValue` is globally insignificant.
321
    #[llvm_variant(LLVMGlobalUnnamedAddr)]
322
    Global,
323
}