1use llvm_sys::analysis::{LLVMVerifierFailureAction, LLVMVerifyFunction, LLVMViewFunctionCFG, LLVMViewFunctionCFGOnly};
2use llvm_sys::core::LLVMAppendExistingBasicBlock;
3use llvm_sys::core::{
4 LLVMAddAttributeAtIndex, LLVMGetAttributeCountAtIndex, LLVMGetEnumAttributeAtIndex, LLVMGetStringAttributeAtIndex,
5 LLVMRemoveEnumAttributeAtIndex, LLVMRemoveStringAttributeAtIndex,
6};
7use llvm_sys::core::{
8 LLVMCountBasicBlocks, LLVMCountParams, LLVMDeleteFunction, LLVMGetBasicBlocks, LLVMGetFirstBasicBlock,
9 LLVMGetFirstParam, LLVMGetFunctionCallConv, LLVMGetGC, LLVMGetIntrinsicID, LLVMGetLastBasicBlock, LLVMGetLastParam,
10 LLVMGetLinkage, LLVMGetNextFunction, LLVMGetNextParam, LLVMGetParam, LLVMGetParams, LLVMGetPreviousFunction,
11 LLVMIsAFunction, LLVMIsConstant, LLVMSetFunctionCallConv, LLVMSetGC, LLVMSetLinkage, LLVMSetParamAlignment,
12};
13use llvm_sys::core::{LLVMGetPersonalityFn, LLVMSetPersonalityFn};
14use llvm_sys::debuginfo::{LLVMGetSubprogram, LLVMSetSubprogram};
15use llvm_sys::prelude::{LLVMBasicBlockRef, LLVMValueRef};
16
17use std::ffi::CStr;
18use std::fmt::{self, Display};
19use std::marker::PhantomData;
20use std::mem::forget;
21
22use crate::attributes::{Attribute, AttributeLoc};
23use crate::basic_block::BasicBlock;
24use crate::debug_info::DISubprogram;
25use crate::module::Linkage;
26use crate::support::to_c_str;
27use crate::types::FunctionType;
28use crate::values::traits::{AnyValue, AsValueRef};
29use crate::values::{BasicValueEnum, GlobalValue, Value};
30
31#[derive(PartialEq, Eq, Clone, Copy, Hash)]
32pub struct FunctionValue<'ctx> {
33 fn_value: Value<'ctx>,
34}
35
36impl<'ctx> FunctionValue<'ctx> {
37 pub unsafe fn new(value: LLVMValueRef) -> Option<Self> {
43 if value.is_null() || LLVMIsAFunction(value).is_null() {
44 return None;
45 }
46
47 Some(FunctionValue {
48 fn_value: Value::new(value),
49 })
50 }
51
52 pub fn get_linkage(self) -> Linkage {
53 unsafe { LLVMGetLinkage(self.as_value_ref()).into() }
54 }
55
56 pub fn set_linkage(self, linkage: Linkage) {
57 unsafe { LLVMSetLinkage(self.as_value_ref(), linkage.into()) }
58 }
59
60 pub fn is_null(self) -> bool {
61 self.fn_value.is_null()
62 }
63
64 pub fn is_undef(self) -> bool {
65 self.fn_value.is_undef()
66 }
67
68 pub fn print_to_stderr(self) {
69 self.fn_value.print_to_stderr()
70 }
71
72 pub fn verify(self, print: bool) -> bool {
74 let action = if print {
75 LLVMVerifierFailureAction::LLVMPrintMessageAction
76 } else {
77 LLVMVerifierFailureAction::LLVMReturnStatusAction
78 };
79
80 let code = unsafe { LLVMVerifyFunction(self.fn_value.value, action) };
81
82 code != 1
83 }
84
85 pub fn get_next_function(self) -> Option<Self> {
87 unsafe { FunctionValue::new(LLVMGetNextFunction(self.as_value_ref())) }
88 }
89
90 pub fn get_previous_function(self) -> Option<Self> {
91 unsafe { FunctionValue::new(LLVMGetPreviousFunction(self.as_value_ref())) }
92 }
93
94 pub fn get_first_param(self) -> Option<BasicValueEnum<'ctx>> {
95 let param = unsafe { LLVMGetFirstParam(self.as_value_ref()) };
96
97 if param.is_null() {
98 return None;
99 }
100
101 unsafe { Some(BasicValueEnum::new(param)) }
102 }
103
104 pub fn get_last_param(self) -> Option<BasicValueEnum<'ctx>> {
105 let param = unsafe { LLVMGetLastParam(self.as_value_ref()) };
106
107 if param.is_null() {
108 return None;
109 }
110
111 unsafe { Some(BasicValueEnum::new(param)) }
112 }
113
114 pub fn get_first_basic_block(self) -> Option<BasicBlock<'ctx>> {
115 unsafe { BasicBlock::new(LLVMGetFirstBasicBlock(self.as_value_ref())) }
116 }
117
118 pub fn get_nth_param(self, nth: u32) -> Option<BasicValueEnum<'ctx>> {
119 let count = self.count_params();
120
121 if nth + 1 > count {
122 return None;
123 }
124
125 unsafe { Some(BasicValueEnum::new(LLVMGetParam(self.as_value_ref(), nth))) }
126 }
127
128 pub fn count_params(self) -> u32 {
129 unsafe { LLVMCountParams(self.fn_value.value) }
130 }
131
132 pub fn count_basic_blocks(self) -> u32 {
133 unsafe { LLVMCountBasicBlocks(self.as_value_ref()) }
134 }
135
136 pub fn get_basic_block_iter(self) -> BasicBlockIter<'ctx> {
137 BasicBlockIter(self.get_first_basic_block())
138 }
139
140 pub fn get_basic_blocks(self) -> Vec<BasicBlock<'ctx>> {
141 let count = self.count_basic_blocks();
142 let mut raw_vec: Vec<LLVMBasicBlockRef> = Vec::with_capacity(count as usize);
143 let ptr = raw_vec.as_mut_ptr();
144
145 forget(raw_vec);
146
147 let raw_vec = unsafe {
148 LLVMGetBasicBlocks(self.as_value_ref(), ptr);
149
150 Vec::from_raw_parts(ptr, count as usize, count as usize)
151 };
152
153 raw_vec
154 .iter()
155 .map(|val| unsafe { BasicBlock::new(*val).unwrap() })
156 .collect()
157 }
158
159 pub fn get_param_iter(self) -> ParamValueIter<'ctx> {
160 ParamValueIter {
161 param_iter_value: self.fn_value.value,
162 start: true,
163 _marker: PhantomData,
164 }
165 }
166
167 pub fn get_params(self) -> Vec<BasicValueEnum<'ctx>> {
168 let count = self.count_params();
169 let mut raw_vec: Vec<LLVMValueRef> = Vec::with_capacity(count as usize);
170 let ptr = raw_vec.as_mut_ptr();
171
172 forget(raw_vec);
173
174 let raw_vec = unsafe {
175 LLVMGetParams(self.as_value_ref(), ptr);
176
177 Vec::from_raw_parts(ptr, count as usize, count as usize)
178 };
179
180 raw_vec.iter().map(|val| unsafe { BasicValueEnum::new(*val) }).collect()
181 }
182
183 pub fn get_last_basic_block(self) -> Option<BasicBlock<'ctx>> {
184 unsafe { BasicBlock::new(LLVMGetLastBasicBlock(self.fn_value.value)) }
185 }
186
187 pub fn get_name(&self) -> &CStr {
189 self.fn_value.get_name()
190 }
191
192 pub fn view_function_cfg(self) {
194 unsafe { LLVMViewFunctionCFG(self.as_value_ref()) }
195 }
196
197 pub fn view_function_cfg_only(self) {
199 unsafe { LLVMViewFunctionCFGOnly(self.as_value_ref()) }
200 }
201
202 pub unsafe fn delete(self) {
204 LLVMDeleteFunction(self.as_value_ref())
205 }
206
207 pub fn get_type(self) -> FunctionType<'ctx> {
208 unsafe { FunctionType::new(llvm_sys::core::LLVMGlobalGetValueType(self.as_value_ref())) }
209 }
210
211 pub fn has_personality_function(self) -> bool {
213 use llvm_sys::core::LLVMHasPersonalityFn;
214
215 unsafe { LLVMHasPersonalityFn(self.as_value_ref()) == 1 }
216 }
217
218 pub fn get_personality_function(self) -> Option<FunctionValue<'ctx>> {
219 if !self.has_personality_function() {
221 return None;
222 }
223
224 unsafe { FunctionValue::new(LLVMGetPersonalityFn(self.as_value_ref())) }
225 }
226
227 pub fn set_personality_function(self, personality_fn: FunctionValue<'ctx>) {
228 unsafe { LLVMSetPersonalityFn(self.as_value_ref(), personality_fn.as_value_ref()) }
229 }
230
231 pub fn get_intrinsic_id(self) -> u32 {
232 unsafe { LLVMGetIntrinsicID(self.as_value_ref()) }
233 }
234
235 pub fn get_call_conventions(self) -> u32 {
236 unsafe { LLVMGetFunctionCallConv(self.as_value_ref()) }
237 }
238
239 pub fn set_call_conventions(self, call_conventions: u32) {
240 unsafe { LLVMSetFunctionCallConv(self.as_value_ref(), call_conventions) }
241 }
242
243 pub fn get_gc(&self) -> &CStr {
244 unsafe { CStr::from_ptr(LLVMGetGC(self.as_value_ref())) }
245 }
246
247 pub fn set_gc(self, gc: &str) {
248 let c_string = to_c_str(gc);
249
250 unsafe { LLVMSetGC(self.as_value_ref(), c_string.as_ptr()) }
251 }
252
253 pub fn replace_all_uses_with(self, other: FunctionValue<'ctx>) {
254 self.fn_value.replace_all_uses_with(other.as_value_ref())
255 }
256
257 pub fn add_attribute(self, loc: AttributeLoc, attribute: Attribute) {
277 unsafe { LLVMAddAttributeAtIndex(self.as_value_ref(), loc.get_index(), attribute.attribute) }
278 }
279
280 pub fn count_attributes(self, loc: AttributeLoc) -> u32 {
302 unsafe { LLVMGetAttributeCountAtIndex(self.as_value_ref(), loc.get_index()) }
303 }
304
305 pub fn attributes(self, loc: AttributeLoc) -> Vec<Attribute> {
327 use llvm_sys::core::LLVMGetAttributesAtIndex;
328 use std::mem::{ManuallyDrop, MaybeUninit};
329
330 let count = self.count_attributes(loc) as usize;
331
332 let mut attribute_refs: Vec<MaybeUninit<Attribute>> = vec![MaybeUninit::uninit(); count];
334
335 unsafe {
337 LLVMGetAttributesAtIndex(
338 self.as_value_ref(),
339 loc.get_index(),
340 attribute_refs.as_mut_ptr() as *mut _,
341 )
342 }
343
344 unsafe {
346 let mut attribute_refs = ManuallyDrop::new(attribute_refs);
348
349 Vec::from_raw_parts(
350 attribute_refs.as_mut_ptr() as *mut Attribute,
351 attribute_refs.len(),
352 attribute_refs.capacity(),
353 )
354 }
355 }
356
357 pub fn remove_string_attribute(self, loc: AttributeLoc, key: &str) {
376 unsafe {
377 LLVMRemoveStringAttributeAtIndex(
378 self.as_value_ref(),
379 loc.get_index(),
380 key.as_ptr() as *const ::libc::c_char,
381 key.len() as u32,
382 )
383 }
384 }
385
386 pub fn remove_enum_attribute(self, loc: AttributeLoc, kind_id: u32) {
405 unsafe { LLVMRemoveEnumAttributeAtIndex(self.as_value_ref(), loc.get_index(), kind_id) }
406 }
407
408 pub fn get_enum_attribute(self, loc: AttributeLoc, kind_id: u32) -> Option<Attribute> {
429 let ptr = unsafe { LLVMGetEnumAttributeAtIndex(self.as_value_ref(), loc.get_index(), kind_id) };
430
431 if ptr.is_null() {
432 return None;
433 }
434
435 unsafe { Some(Attribute::new(ptr)) }
436 }
437
438 pub fn get_string_attribute(self, loc: AttributeLoc, key: &str) -> Option<Attribute> {
459 let ptr = unsafe {
460 LLVMGetStringAttributeAtIndex(
461 self.as_value_ref(),
462 loc.get_index(),
463 key.as_ptr() as *const ::libc::c_char,
464 key.len() as u32,
465 )
466 };
467
468 if ptr.is_null() {
469 return None;
470 }
471
472 unsafe { Some(Attribute::new(ptr)) }
473 }
474
475 pub fn set_param_alignment(self, param_index: u32, alignment: u32) {
476 if let Some(param) = self.get_nth_param(param_index) {
477 unsafe { LLVMSetParamAlignment(param.as_value_ref(), alignment) }
478 }
479 }
480
481 pub fn as_global_value(self) -> GlobalValue<'ctx> {
485 unsafe { GlobalValue::new(self.as_value_ref()) }
486 }
487
488 pub fn set_subprogram(self, subprogram: DISubprogram<'ctx>) {
490 unsafe { LLVMSetSubprogram(self.as_value_ref(), subprogram.metadata_ref) }
491 }
492
493 pub fn get_subprogram(self) -> Option<DISubprogram<'ctx>> {
495 let metadata_ref = unsafe { LLVMGetSubprogram(self.as_value_ref()) };
496
497 if metadata_ref.is_null() {
498 None
499 } else {
500 Some(DISubprogram {
501 metadata_ref,
502 _marker: PhantomData,
503 })
504 }
505 }
506
507 pub fn get_section(&self) -> Option<&CStr> {
509 self.fn_value.get_section()
510 }
511
512 pub fn set_section(self, section: Option<&str>) {
514 self.fn_value.set_section(section)
515 }
516
517 pub fn append_existing_basic_block(&self, basic_block: BasicBlock<'ctx>) {
518 unsafe {
519 LLVMAppendExistingBasicBlock(self.as_value_ref(), basic_block.as_mut_ptr());
520 }
521 }
522}
523
524unsafe impl AsValueRef for FunctionValue<'_> {
525 fn as_value_ref(&self) -> LLVMValueRef {
526 self.fn_value.value
527 }
528}
529
530impl Display for FunctionValue<'_> {
531 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
532 write!(f, "{}", self.print_to_string())
533 }
534}
535
536impl fmt::Debug for FunctionValue<'_> {
537 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
538 let llvm_value = self.print_to_string();
539 let llvm_type = self.get_type();
540 let name = self.get_name();
541 let is_const = unsafe { LLVMIsConstant(self.fn_value.value) == 1 };
542 let is_null = self.is_null();
543
544 f.debug_struct("FunctionValue")
545 .field("name", &name)
546 .field("address", &self.as_value_ref())
547 .field("is_const", &is_const)
548 .field("is_null", &is_null)
549 .field("llvm_value", &llvm_value)
550 .field("llvm_type", &llvm_type.print_to_string())
551 .finish()
552 }
553}
554
555#[derive(Debug)]
557pub struct BasicBlockIter<'ctx>(Option<BasicBlock<'ctx>>);
558
559impl<'ctx> Iterator for BasicBlockIter<'ctx> {
560 type Item = BasicBlock<'ctx>;
561
562 fn next(&mut self) -> Option<Self::Item> {
563 if let Some(bb) = self.0 {
564 self.0 = bb.get_next_basic_block();
565 Some(bb)
566 } else {
567 None
568 }
569 }
570}
571
572#[derive(Debug)]
573pub struct ParamValueIter<'ctx> {
574 param_iter_value: LLVMValueRef,
575 start: bool,
576 _marker: PhantomData<&'ctx ()>,
577}
578
579impl<'ctx> Iterator for ParamValueIter<'ctx> {
580 type Item = BasicValueEnum<'ctx>;
581
582 fn next(&mut self) -> Option<Self::Item> {
583 if self.start {
584 let first_value = unsafe { LLVMGetFirstParam(self.param_iter_value) };
585
586 if first_value.is_null() {
587 return None;
588 }
589
590 self.start = false;
591
592 self.param_iter_value = first_value;
593
594 return unsafe { Some(Self::Item::new(first_value)) };
595 }
596
597 let next_value = unsafe { LLVMGetNextParam(self.param_iter_value) };
598
599 if next_value.is_null() {
600 return None;
601 }
602
603 self.param_iter_value = next_value;
604
605 unsafe { Some(Self::Item::new(next_value)) }
606 }
607}