/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 | | } |