llvm_plugin_inkwell/values/
global_value.rs1#[llvm_versions(8.0..=latest)]
2use llvm_sys::core::LLVMGlobalSetMetadata;
3#[llvm_versions(4.0..=7.0)]
4use 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)]
12use 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)]
20use llvm_sys::core::{LLVMGetUnnamedAddress, LLVMSetUnnamedAddress};
21#[llvm_versions(4.0..=6.0)]
22use llvm_sys::core::{LLVMHasUnnamedAddr, LLVMSetUnnamedAddr};
23use llvm_sys::prelude::LLVMValueRef;
24use llvm_sys::LLVMThreadLocalMode;
25#[llvm_versions(7.0..=latest)]
26use llvm_sys::LLVMUnnamedAddr;
27
28use std::ffi::CStr;
29use std::fmt::{self, Display};
30
31#[llvm_versions(7.0..=latest)]
32use crate::comdat::Comdat;
33use crate::module::Linkage;
34use crate::values::traits::AsValueRef;
35#[llvm_versions(8.0..=latest)]
36use crate::values::MetadataValue;
37use crate::values::{BasicValue, BasicValueEnum, PointerValue, Value};
38use crate::{DLLStorageClass, GlobalVisibility, ThreadLocalMode};
39
40use super::AnyValue;
41
42#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
45pub struct GlobalValue<'ctx> {
46 global_value: Value<'ctx>,
47}
48
49impl<'ctx> GlobalValue<'ctx> {
50 pub(crate) unsafe fn new(value: LLVMValueRef) -> Self {
51 assert!(!value.is_null());
52
53 GlobalValue {
54 global_value: Value::new(value),
55 }
56 }
57
58 pub fn get_name(&self) -> &CStr {
60 self.global_value.get_name()
61 }
62
63 pub fn set_name(&self, name: &str) {
65 self.global_value.set_name(name)
66 }
67
68 pub fn get_previous_global(self) -> Option<GlobalValue<'ctx>> {
69 let value = unsafe { LLVMGetPreviousGlobal(self.as_value_ref()) };
70
71 if value.is_null() {
72 return None;
73 }
74
75 unsafe { Some(GlobalValue::new(value)) }
76 }
77
78 pub fn get_next_global(self) -> Option<GlobalValue<'ctx>> {
79 let value = unsafe { LLVMGetNextGlobal(self.as_value_ref()) };
80
81 if value.is_null() {
82 return None;
83 }
84
85 unsafe { Some(GlobalValue::new(value)) }
86 }
87
88 pub fn get_dll_storage_class(self) -> DLLStorageClass {
89 let dll_storage_class = unsafe { LLVMGetDLLStorageClass(self.as_value_ref()) };
90
91 DLLStorageClass::new(dll_storage_class)
92 }
93
94 pub fn set_dll_storage_class(self, dll_storage_class: DLLStorageClass) {
95 unsafe { LLVMSetDLLStorageClass(self.as_value_ref(), dll_storage_class.into()) }
96 }
97
98 pub fn get_initializer(self) -> Option<BasicValueEnum<'ctx>> {
99 let value = unsafe { LLVMGetInitializer(self.as_value_ref()) };
100
101 if value.is_null() {
102 return None;
103 }
104
105 unsafe { Some(BasicValueEnum::new(value)) }
106 }
107
108 pub fn set_initializer(self, value: &dyn BasicValue<'ctx>) {
110 unsafe { LLVMSetInitializer(self.as_value_ref(), value.as_value_ref()) }
111 }
112
113 pub fn is_thread_local(self) -> bool {
114 unsafe { LLVMIsThreadLocal(self.as_value_ref()) == 1 }
115 }
116
117 pub fn set_thread_local(self, is_thread_local: bool) {
119 unsafe { LLVMSetThreadLocal(self.as_value_ref(), is_thread_local as i32) }
120 }
121
122 pub fn get_thread_local_mode(self) -> Option<ThreadLocalMode> {
123 let thread_local_mode = unsafe { LLVMGetThreadLocalMode(self.as_value_ref()) };
124
125 ThreadLocalMode::new(thread_local_mode)
126 }
127
128 pub fn set_thread_local_mode(self, thread_local_mode: Option<ThreadLocalMode>) {
131 let thread_local_mode = match thread_local_mode {
132 Some(mode) => mode.as_llvm_mode(),
133 None => LLVMThreadLocalMode::LLVMNotThreadLocal,
134 };
135
136 unsafe { LLVMSetThreadLocalMode(self.as_value_ref(), thread_local_mode) }
137 }
138
139 pub fn is_declaration(self) -> bool {
161 unsafe { LLVMIsDeclaration(self.as_value_ref()) == 1 }
162 }
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 pub fn has_unnamed_addr(self) -> bool {
171 unsafe { LLVMGetUnnamedAddress(self.as_value_ref()) == LLVMUnnamedAddr::LLVMGlobalUnnamedAddr }
172 }
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 pub fn set_unnamed_addr(self, has_unnamed_addr: bool) {
181 unsafe {
182 if has_unnamed_addr {
183 LLVMSetUnnamedAddress(self.as_value_ref(), UnnamedAddress::Global.into())
184 } else {
185 LLVMSetUnnamedAddress(self.as_value_ref(), UnnamedAddress::None.into())
186 }
187 }
188 }
189
190 pub fn is_constant(self) -> bool {
191 unsafe { LLVMIsGlobalConstant(self.as_value_ref()) == 1 }
192 }
193
194 pub fn set_constant(self, is_constant: bool) {
195 unsafe { LLVMSetGlobalConstant(self.as_value_ref(), is_constant as i32) }
196 }
197
198 pub fn is_externally_initialized(self) -> bool {
199 unsafe { LLVMIsExternallyInitialized(self.as_value_ref()) == 1 }
200 }
201
202 pub fn set_externally_initialized(self, externally_initialized: bool) {
203 unsafe { LLVMSetExternallyInitialized(self.as_value_ref(), externally_initialized as i32) }
204 }
205
206 pub fn set_visibility(self, visibility: GlobalVisibility) {
207 unsafe { LLVMSetVisibility(self.as_value_ref(), visibility.into()) }
208 }
209
210 pub fn get_visibility(self) -> GlobalVisibility {
211 let visibility = unsafe { LLVMGetVisibility(self.as_value_ref()) };
212
213 GlobalVisibility::new(visibility)
214 }
215
216 pub fn get_section(&self) -> Option<&CStr> {
218 self.global_value.get_section()
219 }
220
221 pub fn set_section(self, section: Option<&str>) {
223 self.global_value.set_section(section)
224 }
225
226 pub unsafe fn delete(self) {
227 LLVMDeleteGlobal(self.as_value_ref())
228 }
229
230 pub fn as_pointer_value(self) -> PointerValue<'ctx> {
231 unsafe { PointerValue::new(self.as_value_ref()) }
232 }
233
234 pub fn get_alignment(self) -> u32 {
235 unsafe { LLVMGetAlignment(self.as_value_ref()) }
236 }
237
238 pub fn set_alignment(self, alignment: u32) {
239 unsafe { LLVMSetAlignment(self.as_value_ref(), alignment) }
240 }
241
242 #[llvm_versions(8.0..=latest)]
244 pub fn set_metadata(self, metadata: MetadataValue<'ctx>, kind_id: u32) {
245 unsafe { LLVMGlobalSetMetadata(self.as_value_ref(), kind_id, metadata.as_metadata_ref()) }
246 }
247
248 #[llvm_versions(7.0..=latest)]
250 pub fn get_comdat(self) -> Option<Comdat> {
251 use llvm_sys::comdat::LLVMGetComdat;
252
253 let comdat_ptr = unsafe { LLVMGetComdat(self.as_value_ref()) };
254
255 if comdat_ptr.is_null() {
256 return None;
257 }
258
259 unsafe { Some(Comdat::new(comdat_ptr)) }
260 }
261
262 #[llvm_versions(7.0..=latest)]
264 pub fn set_comdat(self, comdat: Comdat) {
265 use llvm_sys::comdat::LLVMSetComdat;
266
267 unsafe { LLVMSetComdat(self.as_value_ref(), comdat.0) }
268 }
269
270 #[llvm_versions(7.0..=latest)]
271 pub fn get_unnamed_address(self) -> UnnamedAddress {
272 use llvm_sys::core::LLVMGetUnnamedAddress;
273
274 let unnamed_address = unsafe { LLVMGetUnnamedAddress(self.as_value_ref()) };
275
276 UnnamedAddress::new(unnamed_address)
277 }
278
279 #[llvm_versions(7.0..=latest)]
280 pub fn set_unnamed_address(self, address: UnnamedAddress) {
281 use llvm_sys::core::LLVMSetUnnamedAddress;
282
283 unsafe { LLVMSetUnnamedAddress(self.as_value_ref(), address.into()) }
284 }
285
286 pub fn get_linkage(self) -> Linkage {
287 unsafe { LLVMGetLinkage(self.as_value_ref()).into() }
288 }
289
290 pub fn set_linkage(self, linkage: Linkage) {
291 unsafe { LLVMSetLinkage(self.as_value_ref(), linkage.into()) }
292 }
293}
294
295unsafe impl AsValueRef for GlobalValue<'_> {
296 fn as_value_ref(&self) -> LLVMValueRef {
297 self.global_value.value
298 }
299}
300
301impl Display for GlobalValue<'_> {
302 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
303 write!(f, "{}", self.print_to_string())
304 }
305}
306
307#[llvm_versions(7.0..=latest)]
309#[llvm_enum(LLVMUnnamedAddr)]
310#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
311pub enum UnnamedAddress {
312 #[llvm_variant(LLVMNoUnnamedAddr)]
314 None,
315
316 #[llvm_variant(LLVMLocalUnnamedAddr)]
318 Local,
319
320 #[llvm_variant(LLVMGlobalUnnamedAddr)]
322 Global,
323}