1use llvm_sys::analysis::{LLVMVerifierFailureAction, LLVMVerifyFunction, LLVMViewFunctionCFG, LLVMViewFunctionCFGOnly};
2use llvm_sys::core::{
3 LLVMAddAttributeAtIndex, LLVMGetAttributeCountAtIndex, LLVMGetEnumAttributeAtIndex, LLVMGetStringAttributeAtIndex,
4 LLVMRemoveEnumAttributeAtIndex, LLVMRemoveStringAttributeAtIndex,
5};
6use llvm_sys::core::{
7 LLVMCountBasicBlocks, LLVMCountParams, LLVMDeleteFunction, LLVMGetBasicBlocks, LLVMGetFirstBasicBlock,
8 LLVMGetFirstParam, LLVMGetFunctionCallConv, LLVMGetGC, LLVMGetIntrinsicID, LLVMGetLastBasicBlock, LLVMGetLastParam,
9 LLVMGetLinkage, LLVMGetNextFunction, LLVMGetNextParam, LLVMGetParam, LLVMGetParams, LLVMGetPreviousFunction,
10 LLVMIsAFunction, LLVMIsConstant, LLVMSetFunctionCallConv, LLVMSetGC, LLVMSetLinkage, LLVMSetParamAlignment,
11};
12use llvm_sys::core::{LLVMGetPersonalityFn, LLVMSetPersonalityFn};
13#[llvm_versions(7..)]
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;
24#[llvm_versions(7..)]
25use crate::debug_info::DISubprogram;
26use crate::module::Linkage;
27use crate::support::to_c_str;
28use crate::types::FunctionType;
29use crate::values::traits::{AnyValue, AsValueRef};
30use crate::values::{BasicValueEnum, GlobalValue, Value};
31
32#[derive(PartialEq, Eq, Clone, Copy, Hash)]
33pub struct FunctionValue<'ctx> {
34 fn_value: Value<'ctx>,
35}
36
37impl<'ctx> FunctionValue<'ctx> {
38 pub unsafe fn new(value: LLVMValueRef) -> Option<Self> {
44 if value.is_null() || LLVMIsAFunction(value).is_null() {
45 return None;
46 }
47
48 Some(FunctionValue {
49 fn_value: Value::new(value),
50 })
51 }
52
53 pub fn get_linkage(self) -> Linkage {
54 unsafe { LLVMGetLinkage(self.as_value_ref()).into() }
55 }
56
57 pub fn set_linkage(self, linkage: Linkage) {
58 unsafe { LLVMSetLinkage(self.as_value_ref(), linkage.into()) }
59 }
60
61 pub fn is_null(self) -> bool {
62 self.fn_value.is_null()
63 }
64
65 pub fn is_undef(self) -> bool {
66 self.fn_value.is_undef()
67 }
68
69 pub fn print_to_stderr(self) {
70 self.fn_value.print_to_stderr()
71 }
72
73 pub fn verify(self, print: bool) -> bool {
75 let action = if print {
76 LLVMVerifierFailureAction::LLVMPrintMessageAction
77 } else {
78 LLVMVerifierFailureAction::LLVMReturnStatusAction
79 };
80
81 let code = unsafe { LLVMVerifyFunction(self.fn_value.value, action) };
82
83 code != 1
84 }
85
86 pub fn get_next_function(self) -> Option<Self> {
88 unsafe { FunctionValue::new(LLVMGetNextFunction(self.as_value_ref())) }
89 }
90
91 pub fn get_previous_function(self) -> Option<Self> {
92 unsafe { FunctionValue::new(LLVMGetPreviousFunction(self.as_value_ref())) }
93 }
94
95 pub fn get_first_param(self) -> Option<BasicValueEnum<'ctx>> {
96 let param = unsafe { LLVMGetFirstParam(self.as_value_ref()) };
97
98 if param.is_null() {
99 return None;
100 }
101
102 unsafe { Some(BasicValueEnum::new(param)) }
103 }
104
105 pub fn get_last_param(self) -> Option<BasicValueEnum<'ctx>> {
106 let param = unsafe { LLVMGetLastParam(self.as_value_ref()) };
107
108 if param.is_null() {
109 return None;
110 }
111
112 unsafe { Some(BasicValueEnum::new(param)) }
113 }
114
115 pub fn get_first_basic_block(self) -> Option<BasicBlock<'ctx>> {
116 unsafe { BasicBlock::new(LLVMGetFirstBasicBlock(self.as_value_ref())) }
117 }
118
119 pub fn get_nth_param(self, nth: u32) -> Option<BasicValueEnum<'ctx>> {
120 let count = self.count_params();
121
122 if nth + 1 > count {
123 return None;
124 }
125
126 unsafe { Some(BasicValueEnum::new(LLVMGetParam(self.as_value_ref(), nth))) }
127 }
128
129 pub fn count_params(self) -> u32 {
130 unsafe { LLVMCountParams(self.fn_value.value) }
131 }
132
133 pub fn count_basic_blocks(self) -> u32 {
134 unsafe { LLVMCountBasicBlocks(self.as_value_ref()) }
135 }
136
137 pub fn get_basic_block_iter(self) -> BasicBlockIter<'ctx> {
138 BasicBlockIter(self.get_first_basic_block())
139 }
140
141 pub fn get_basic_blocks(self) -> Vec<BasicBlock<'ctx>> {
142 let count = self.count_basic_blocks();
143 let mut raw_vec: Vec<LLVMBasicBlockRef> = Vec::with_capacity(count as usize);
144 let ptr = raw_vec.as_mut_ptr();
145
146 forget(raw_vec);
147
148 let raw_vec = unsafe {
149 LLVMGetBasicBlocks(self.as_value_ref(), ptr);
150
151 Vec::from_raw_parts(ptr, count as usize, count as usize)
152 };
153
154 raw_vec
155 .iter()
156 .map(|val| unsafe { BasicBlock::new(*val).unwrap() })
157 .collect()
158 }
159
160 pub fn get_param_iter(self) -> ParamValueIter<'ctx> {
161 ParamValueIter {
162 param_iter_value: self.fn_value.value,
163 start: true,
164 _marker: PhantomData,
165 }
166 }
167
168 pub fn get_params(self) -> Vec<BasicValueEnum<'ctx>> {
169 let count = self.count_params();
170 let mut raw_vec: Vec<LLVMValueRef> = Vec::with_capacity(count as usize);
171 let ptr = raw_vec.as_mut_ptr();
172
173 forget(raw_vec);
174
175 let raw_vec = unsafe {
176 LLVMGetParams(self.as_value_ref(), ptr);
177
178 Vec::from_raw_parts(ptr, count as usize, count as usize)
179 };
180
181 raw_vec.iter().map(|val| unsafe { BasicValueEnum::new(*val) }).collect()
182 }
183
184 pub fn get_last_basic_block(self) -> Option<BasicBlock<'ctx>> {
185 unsafe { BasicBlock::new(LLVMGetLastBasicBlock(self.fn_value.value)) }
186 }
187
188 pub fn get_name(&self) -> &CStr {
190 self.fn_value.get_name()
191 }
192
193 pub fn view_function_cfg(self) {
195 unsafe { LLVMViewFunctionCFG(self.as_value_ref()) }
196 }
197
198 pub fn view_function_cfg_only(self) {
200 unsafe { LLVMViewFunctionCFGOnly(self.as_value_ref()) }
201 }
202
203 pub unsafe fn delete(self) {
205 LLVMDeleteFunction(self.as_value_ref())
206 }
207
208 #[llvm_versions(..=7)]
209 pub fn get_type(self) -> FunctionType<'ctx> {
210 use crate::types::PointerType;
211
212 let ptr_type = unsafe { PointerType::new(self.fn_value.get_type()) };
213
214 ptr_type.get_element_type().into_function_type()
215 }
216
217 #[llvm_versions(8..)]
218 pub fn get_type(self) -> FunctionType<'ctx> {
219 unsafe { FunctionType::new(llvm_sys::core::LLVMGlobalGetValueType(self.as_value_ref())) }
220 }
221
222 pub fn has_personality_function(self) -> bool {
224 use llvm_sys::core::LLVMHasPersonalityFn;
225
226 unsafe { LLVMHasPersonalityFn(self.as_value_ref()) == 1 }
227 }
228
229 pub fn get_personality_function(self) -> Option<FunctionValue<'ctx>> {
230 if !self.has_personality_function() {
232 return None;
233 }
234
235 unsafe { FunctionValue::new(LLVMGetPersonalityFn(self.as_value_ref())) }
236 }
237
238 pub fn set_personality_function(self, personality_fn: FunctionValue<'ctx>) {
239 unsafe { LLVMSetPersonalityFn(self.as_value_ref(), personality_fn.as_value_ref()) }
240 }
241
242 pub fn get_intrinsic_id(self) -> u32 {
243 unsafe { LLVMGetIntrinsicID(self.as_value_ref()) }
244 }
245
246 pub fn get_call_conventions(self) -> u32 {
247 unsafe { LLVMGetFunctionCallConv(self.as_value_ref()) }
248 }
249
250 pub fn set_call_conventions(self, call_conventions: u32) {
251 unsafe { LLVMSetFunctionCallConv(self.as_value_ref(), call_conventions) }
252 }
253
254 pub fn get_gc(&self) -> &CStr {
255 unsafe { CStr::from_ptr(LLVMGetGC(self.as_value_ref())) }
256 }
257
258 pub fn set_gc(self, gc: &str) {
259 let c_string = to_c_str(gc);
260
261 unsafe { LLVMSetGC(self.as_value_ref(), c_string.as_ptr()) }
262 }
263
264 pub fn replace_all_uses_with(self, other: FunctionValue<'ctx>) {
265 self.fn_value.replace_all_uses_with(other.as_value_ref())
266 }
267
268 pub fn add_attribute(self, loc: AttributeLoc, attribute: Attribute) {
288 unsafe { LLVMAddAttributeAtIndex(self.as_value_ref(), loc.get_index(), attribute.attribute) }
289 }
290
291 pub fn count_attributes(self, loc: AttributeLoc) -> u32 {
313 unsafe { LLVMGetAttributeCountAtIndex(self.as_value_ref(), loc.get_index()) }
314 }
315
316 pub fn attributes(self, loc: AttributeLoc) -> Vec<Attribute> {
338 use llvm_sys::core::LLVMGetAttributesAtIndex;
339 use std::mem::{ManuallyDrop, MaybeUninit};
340
341 let count = self.count_attributes(loc) as usize;
342
343 let mut attribute_refs: Vec<MaybeUninit<Attribute>> = vec![MaybeUninit::uninit(); count];
345
346 unsafe {
348 LLVMGetAttributesAtIndex(
349 self.as_value_ref(),
350 loc.get_index(),
351 attribute_refs.as_mut_ptr() as *mut _,
352 )
353 }
354
355 unsafe {
357 let mut attribute_refs = ManuallyDrop::new(attribute_refs);
359
360 Vec::from_raw_parts(
361 attribute_refs.as_mut_ptr() as *mut Attribute,
362 attribute_refs.len(),
363 attribute_refs.capacity(),
364 )
365 }
366 }
367
368 pub fn remove_string_attribute(self, loc: AttributeLoc, key: &str) {
387 unsafe {
388 LLVMRemoveStringAttributeAtIndex(
389 self.as_value_ref(),
390 loc.get_index(),
391 key.as_ptr() as *const ::libc::c_char,
392 key.len() as u32,
393 )
394 }
395 }
396
397 pub fn remove_enum_attribute(self, loc: AttributeLoc, kind_id: u32) {
416 unsafe { LLVMRemoveEnumAttributeAtIndex(self.as_value_ref(), loc.get_index(), kind_id) }
417 }
418
419 pub fn get_enum_attribute(self, loc: AttributeLoc, kind_id: u32) -> Option<Attribute> {
440 let ptr = unsafe { LLVMGetEnumAttributeAtIndex(self.as_value_ref(), loc.get_index(), kind_id) };
441
442 if ptr.is_null() {
443 return None;
444 }
445
446 unsafe { Some(Attribute::new(ptr)) }
447 }
448
449 pub fn get_string_attribute(self, loc: AttributeLoc, key: &str) -> Option<Attribute> {
470 let ptr = unsafe {
471 LLVMGetStringAttributeAtIndex(
472 self.as_value_ref(),
473 loc.get_index(),
474 key.as_ptr() as *const ::libc::c_char,
475 key.len() as u32,
476 )
477 };
478
479 if ptr.is_null() {
480 return None;
481 }
482
483 unsafe { Some(Attribute::new(ptr)) }
484 }
485
486 pub fn set_param_alignment(self, param_index: u32, alignment: u32) {
487 if let Some(param) = self.get_nth_param(param_index) {
488 unsafe { LLVMSetParamAlignment(param.as_value_ref(), alignment) }
489 }
490 }
491
492 pub fn as_global_value(self) -> GlobalValue<'ctx> {
496 unsafe { GlobalValue::new(self.as_value_ref()) }
497 }
498
499 #[llvm_versions(7..)]
501 pub fn set_subprogram(self, subprogram: DISubprogram<'ctx>) {
502 unsafe { LLVMSetSubprogram(self.as_value_ref(), subprogram.metadata_ref) }
503 }
504
505 #[llvm_versions(7..)]
507 pub fn get_subprogram(self) -> Option<DISubprogram<'ctx>> {
508 let metadata_ref = unsafe { LLVMGetSubprogram(self.as_value_ref()) };
509
510 if metadata_ref.is_null() {
511 None
512 } else {
513 Some(DISubprogram {
514 metadata_ref,
515 _marker: PhantomData,
516 })
517 }
518 }
519
520 pub fn get_section(&self) -> Option<&CStr> {
522 self.fn_value.get_section()
523 }
524
525 pub fn set_section(self, section: Option<&str>) {
527 self.fn_value.set_section(section)
528 }
529}
530
531unsafe impl AsValueRef for FunctionValue<'_> {
532 fn as_value_ref(&self) -> LLVMValueRef {
533 self.fn_value.value
534 }
535}
536
537impl Display for FunctionValue<'_> {
538 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
539 write!(f, "{}", self.print_to_string())
540 }
541}
542
543impl fmt::Debug for FunctionValue<'_> {
544 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
545 let llvm_value = self.print_to_string();
546 let llvm_type = self.get_type();
547 let name = self.get_name();
548 let is_const = unsafe { LLVMIsConstant(self.fn_value.value) == 1 };
549 let is_null = self.is_null();
550
551 f.debug_struct("FunctionValue")
552 .field("name", &name)
553 .field("address", &self.as_value_ref())
554 .field("is_const", &is_const)
555 .field("is_null", &is_null)
556 .field("llvm_value", &llvm_value)
557 .field("llvm_type", &llvm_type.print_to_string())
558 .finish()
559 }
560}
561
562#[derive(Debug)]
564pub struct BasicBlockIter<'ctx>(Option<BasicBlock<'ctx>>);
565
566impl<'ctx> Iterator for BasicBlockIter<'ctx> {
567 type Item = BasicBlock<'ctx>;
568
569 fn next(&mut self) -> Option<Self::Item> {
570 if let Some(bb) = self.0 {
571 self.0 = bb.get_next_basic_block();
572 Some(bb)
573 } else {
574 None
575 }
576 }
577}
578
579#[derive(Debug)]
580pub struct ParamValueIter<'ctx> {
581 param_iter_value: LLVMValueRef,
582 start: bool,
583 _marker: PhantomData<&'ctx ()>,
584}
585
586impl<'ctx> Iterator for ParamValueIter<'ctx> {
587 type Item = BasicValueEnum<'ctx>;
588
589 fn next(&mut self) -> Option<Self::Item> {
590 if self.start {
591 let first_value = unsafe { LLVMGetFirstParam(self.param_iter_value) };
592
593 if first_value.is_null() {
594 return None;
595 }
596
597 self.start = false;
598
599 self.param_iter_value = first_value;
600
601 return unsafe { Some(Self::Item::new(first_value)) };
602 }
603
604 let next_value = unsafe { LLVMGetNextParam(self.param_iter_value) };
605
606 if next_value.is_null() {
607 return None;
608 }
609
610 self.param_iter_value = next_value;
611
612 unsafe { Some(Self::Item::new(next_value)) }
613 }
614}