inkwell/values/
global_value.rs1use llvm_sys::core::LLVMGlobalSetMetadata;
2
3use llvm_sys::core::{
4 LLVMDeleteGlobal, LLVMGetAlignment, LLVMGetDLLStorageClass, LLVMGetInitializer, LLVMGetLinkage, LLVMGetNextGlobal,
5 LLVMGetPreviousGlobal, LLVMGetThreadLocalMode, LLVMGetVisibility, LLVMIsDeclaration, LLVMIsExternallyInitialized,
6 LLVMIsGlobalConstant, LLVMIsThreadLocal, LLVMSetAlignment, LLVMSetDLLStorageClass, LLVMSetExternallyInitialized,
7 LLVMSetGlobalConstant, LLVMSetInitializer, LLVMSetLinkage, LLVMSetThreadLocal, LLVMSetThreadLocalMode,
8 LLVMSetVisibility,
9};
10
11use llvm_sys::core::{LLVMGetUnnamedAddress, LLVMSetUnnamedAddress};
12use llvm_sys::prelude::LLVMValueRef;
13use llvm_sys::LLVMThreadLocalMode;
14
15use llvm_sys::LLVMUnnamedAddr;
16
17use std::ffi::CStr;
18use std::fmt::{self, Display};
19
20use crate::comdat::Comdat;
21use crate::module::Linkage;
22use crate::types::AnyTypeEnum;
23use crate::values::traits::AsValueRef;
24
25use crate::values::MetadataValue;
26use crate::values::{BasicValue, BasicValueEnum, PointerValue, Value};
27use crate::{DLLStorageClass, GlobalVisibility, ThreadLocalMode};
28
29use super::AnyValue;
30
31#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
34pub struct GlobalValue<'ctx> {
35 global_value: Value<'ctx>,
36}
37
38impl<'ctx> GlobalValue<'ctx> {
39 pub unsafe fn new(value: LLVMValueRef) -> Self {
45 assert!(!value.is_null());
46
47 GlobalValue {
48 global_value: Value::new(value),
49 }
50 }
51
52 pub fn get_name(&self) -> &CStr {
54 self.global_value.get_name()
55 }
56
57 pub fn set_name(&self, name: &str) {
59 self.global_value.set_name(name)
60 }
61
62 pub fn get_previous_global(self) -> Option<GlobalValue<'ctx>> {
63 let value = unsafe { LLVMGetPreviousGlobal(self.as_value_ref()) };
64
65 if value.is_null() {
66 return None;
67 }
68
69 unsafe { Some(GlobalValue::new(value)) }
70 }
71
72 pub fn get_next_global(self) -> Option<GlobalValue<'ctx>> {
73 let value = unsafe { LLVMGetNextGlobal(self.as_value_ref()) };
74
75 if value.is_null() {
76 return None;
77 }
78
79 unsafe { Some(GlobalValue::new(value)) }
80 }
81
82 pub fn get_dll_storage_class(self) -> DLLStorageClass {
83 let dll_storage_class = unsafe { LLVMGetDLLStorageClass(self.as_value_ref()) };
84
85 DLLStorageClass::new(dll_storage_class)
86 }
87
88 pub fn set_dll_storage_class(self, dll_storage_class: DLLStorageClass) {
89 unsafe { LLVMSetDLLStorageClass(self.as_value_ref(), dll_storage_class.into()) }
90 }
91
92 pub fn get_initializer(self) -> Option<BasicValueEnum<'ctx>> {
93 let value = unsafe { LLVMGetInitializer(self.as_value_ref()) };
94
95 if value.is_null() {
96 return None;
97 }
98
99 unsafe { Some(BasicValueEnum::new(value)) }
100 }
101
102 pub fn set_initializer(self, value: &dyn BasicValue<'ctx>) {
104 unsafe { LLVMSetInitializer(self.as_value_ref(), value.as_value_ref()) }
105 }
106
107 pub fn is_thread_local(self) -> bool {
108 unsafe { LLVMIsThreadLocal(self.as_value_ref()) == 1 }
109 }
110
111 pub fn set_thread_local(self, is_thread_local: bool) {
113 unsafe { LLVMSetThreadLocal(self.as_value_ref(), is_thread_local as i32) }
114 }
115
116 pub fn get_thread_local_mode(self) -> Option<ThreadLocalMode> {
117 let thread_local_mode = unsafe { LLVMGetThreadLocalMode(self.as_value_ref()) };
118
119 ThreadLocalMode::new(thread_local_mode)
120 }
121
122 pub fn set_thread_local_mode(self, thread_local_mode: Option<ThreadLocalMode>) {
125 let thread_local_mode = match thread_local_mode {
126 Some(mode) => mode.as_llvm_mode(),
127 None => LLVMThreadLocalMode::LLVMNotThreadLocal,
128 };
129
130 unsafe { LLVMSetThreadLocalMode(self.as_value_ref(), thread_local_mode) }
131 }
132
133 pub fn is_declaration(self) -> bool {
155 unsafe { LLVMIsDeclaration(self.as_value_ref()) == 1 }
156 }
157
158 pub fn has_unnamed_addr(self) -> bool {
159 unsafe { LLVMGetUnnamedAddress(self.as_value_ref()) == LLVMUnnamedAddr::LLVMGlobalUnnamedAddr }
160 }
161
162 pub fn set_unnamed_addr(self, has_unnamed_addr: bool) {
163 unsafe {
164 if has_unnamed_addr {
165 LLVMSetUnnamedAddress(self.as_value_ref(), UnnamedAddress::Global.into())
166 } else {
167 LLVMSetUnnamedAddress(self.as_value_ref(), UnnamedAddress::None.into())
168 }
169 }
170 }
171
172 pub fn is_constant(self) -> bool {
173 unsafe { LLVMIsGlobalConstant(self.as_value_ref()) == 1 }
174 }
175
176 pub fn set_constant(self, is_constant: bool) {
177 unsafe { LLVMSetGlobalConstant(self.as_value_ref(), is_constant as i32) }
178 }
179
180 pub fn is_externally_initialized(self) -> bool {
181 unsafe { LLVMIsExternallyInitialized(self.as_value_ref()) == 1 }
182 }
183
184 pub fn set_externally_initialized(self, externally_initialized: bool) {
185 unsafe { LLVMSetExternallyInitialized(self.as_value_ref(), externally_initialized as i32) }
186 }
187
188 pub fn set_visibility(self, visibility: GlobalVisibility) {
189 unsafe { LLVMSetVisibility(self.as_value_ref(), visibility.into()) }
190 }
191
192 pub fn get_visibility(self) -> GlobalVisibility {
193 let visibility = unsafe { LLVMGetVisibility(self.as_value_ref()) };
194
195 GlobalVisibility::new(visibility)
196 }
197
198 pub fn get_section(&self) -> Option<&CStr> {
200 self.global_value.get_section()
201 }
202
203 pub fn set_section(self, section: Option<&str>) {
205 self.global_value.set_section(section)
206 }
207
208 pub unsafe fn delete(self) {
209 LLVMDeleteGlobal(self.as_value_ref())
210 }
211
212 pub fn as_pointer_value(self) -> PointerValue<'ctx> {
213 unsafe { PointerValue::new(self.as_value_ref()) }
214 }
215
216 pub fn get_alignment(self) -> u32 {
217 unsafe { LLVMGetAlignment(self.as_value_ref()) }
218 }
219
220 pub fn set_alignment(self, alignment: u32) {
221 unsafe { LLVMSetAlignment(self.as_value_ref(), alignment) }
222 }
223
224 pub fn set_metadata(self, metadata: MetadataValue<'ctx>, kind_id: u32) {
226 unsafe { LLVMGlobalSetMetadata(self.as_value_ref(), kind_id, metadata.as_metadata_ref()) }
227 }
228
229 pub fn get_comdat(self) -> Option<Comdat> {
231 use llvm_sys::comdat::LLVMGetComdat;
232
233 let comdat_ptr = unsafe { LLVMGetComdat(self.as_value_ref()) };
234
235 if comdat_ptr.is_null() {
236 return None;
237 }
238
239 unsafe { Some(Comdat::new(comdat_ptr)) }
240 }
241
242 pub fn set_comdat(self, comdat: Comdat) {
244 use llvm_sys::comdat::LLVMSetComdat;
245
246 unsafe { LLVMSetComdat(self.as_value_ref(), comdat.0) }
247 }
248
249 pub fn get_unnamed_address(self) -> UnnamedAddress {
250 use llvm_sys::core::LLVMGetUnnamedAddress;
251
252 let unnamed_address = unsafe { LLVMGetUnnamedAddress(self.as_value_ref()) };
253
254 UnnamedAddress::new(unnamed_address)
255 }
256
257 pub fn set_unnamed_address(self, address: UnnamedAddress) {
258 use llvm_sys::core::LLVMSetUnnamedAddress;
259
260 unsafe { LLVMSetUnnamedAddress(self.as_value_ref(), address.into()) }
261 }
262
263 pub fn get_linkage(self) -> Linkage {
264 unsafe { LLVMGetLinkage(self.as_value_ref()).into() }
265 }
266
267 pub fn set_linkage(self, linkage: Linkage) {
268 unsafe { LLVMSetLinkage(self.as_value_ref(), linkage.into()) }
269 }
270
271 pub fn get_value_type(self) -> AnyTypeEnum<'ctx> {
272 unsafe { AnyTypeEnum::new(llvm_sys::core::LLVMGlobalGetValueType(self.as_value_ref())) }
273 }
274}
275
276unsafe impl AsValueRef for GlobalValue<'_> {
277 fn as_value_ref(&self) -> LLVMValueRef {
278 self.global_value.value
279 }
280}
281
282impl Display for GlobalValue<'_> {
283 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
284 write!(f, "{}", self.print_to_string())
285 }
286}
287
288#[llvm_enum(LLVMUnnamedAddr)]
291#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
292pub enum UnnamedAddress {
293 #[llvm_variant(LLVMNoUnnamedAddr)]
295 None,
296
297 #[llvm_variant(LLVMLocalUnnamedAddr)]
299 Local,
300
301 #[llvm_variant(LLVMGlobalUnnamedAddr)]
303 Global,
304}