/rust/registry/src/index.crates.io-6f17d22bba15001f/inkwell-0.1.1/src/values/fn_value.rs
Line | Count | Source (jump to first uncovered line) |
1 | | use llvm_sys::analysis::{LLVMVerifierFailureAction, LLVMVerifyFunction, LLVMViewFunctionCFG, LLVMViewFunctionCFGOnly}; |
2 | | use llvm_sys::core::{ |
3 | | LLVMAddAttributeAtIndex, LLVMGetAttributeCountAtIndex, LLVMGetEnumAttributeAtIndex, LLVMGetStringAttributeAtIndex, |
4 | | LLVMRemoveEnumAttributeAtIndex, LLVMRemoveStringAttributeAtIndex, |
5 | | }; |
6 | | use 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 | | }; |
12 | | use llvm_sys::core::{LLVMGetPersonalityFn, LLVMSetPersonalityFn}; |
13 | | #[llvm_versions(7.0..=latest)] |
14 | | use llvm_sys::debuginfo::{LLVMGetSubprogram, LLVMSetSubprogram}; |
15 | | use llvm_sys::prelude::{LLVMBasicBlockRef, LLVMValueRef}; |
16 | | |
17 | | use std::ffi::CStr; |
18 | | use std::fmt::{self, Display}; |
19 | | use std::marker::PhantomData; |
20 | | use std::mem::forget; |
21 | | |
22 | | use crate::attributes::{Attribute, AttributeLoc}; |
23 | | use crate::basic_block::BasicBlock; |
24 | | #[llvm_versions(7.0..=latest)] |
25 | | use crate::debug_info::DISubprogram; |
26 | | use crate::module::Linkage; |
27 | | use crate::support::to_c_str; |
28 | | use crate::types::FunctionType; |
29 | | use crate::values::traits::{AnyValue, AsValueRef}; |
30 | | use crate::values::{BasicValueEnum, GlobalValue, Value}; |
31 | | |
32 | | #[derive(PartialEq, Eq, Clone, Copy, Hash)] |
33 | | pub struct FunctionValue<'ctx> { |
34 | | fn_value: Value<'ctx>, |
35 | | } |
36 | | |
37 | | impl<'ctx> FunctionValue<'ctx> { |
38 | 15.4M | pub(crate) unsafe fn new(value: LLVMValueRef) -> Option<Self> { |
39 | 15.4M | if value.is_null() { |
40 | 0 | return None; |
41 | 15.4M | } |
42 | 15.4M | |
43 | 15.4M | assert!(!LLVMIsAFunction(value).is_null()); |
44 | | |
45 | 15.4M | Some(FunctionValue { |
46 | 15.4M | fn_value: Value::new(value), |
47 | 15.4M | }) |
48 | 15.4M | } |
49 | | |
50 | 0 | pub fn get_linkage(self) -> Linkage { |
51 | 0 | unsafe { LLVMGetLinkage(self.as_value_ref()).into() } |
52 | 0 | } |
53 | | |
54 | 425k | pub fn set_linkage(self, linkage: Linkage) { |
55 | 425k | unsafe { LLVMSetLinkage(self.as_value_ref(), linkage.into()) } |
56 | 425k | } |
57 | | |
58 | 0 | pub fn is_null(self) -> bool { |
59 | 0 | self.fn_value.is_null() |
60 | 0 | } |
61 | | |
62 | 0 | pub fn is_undef(self) -> bool { |
63 | 0 | self.fn_value.is_undef() |
64 | 0 | } |
65 | | |
66 | 0 | pub fn print_to_stderr(self) { |
67 | 0 | self.fn_value.print_to_stderr() |
68 | 0 | } |
69 | | |
70 | | // FIXME: Better error returns, code 1 is error |
71 | 0 | pub fn verify(self, print: bool) -> bool { |
72 | 0 | let action = if print { |
73 | 0 | LLVMVerifierFailureAction::LLVMPrintMessageAction |
74 | | } else { |
75 | 0 | LLVMVerifierFailureAction::LLVMReturnStatusAction |
76 | | }; |
77 | | |
78 | 0 | let code = unsafe { LLVMVerifyFunction(self.fn_value.value, action) }; |
79 | 0 |
|
80 | 0 | code != 1 |
81 | 0 | } |
82 | | |
83 | | // REVIEW: If there's a demand, could easily create a module.get_functions() -> Iterator |
84 | 0 | pub fn get_next_function(self) -> Option<Self> { |
85 | 0 | unsafe { FunctionValue::new(LLVMGetNextFunction(self.as_value_ref())) } |
86 | 0 | } |
87 | | |
88 | 0 | pub fn get_previous_function(self) -> Option<Self> { |
89 | 0 | unsafe { FunctionValue::new(LLVMGetPreviousFunction(self.as_value_ref())) } |
90 | 0 | } |
91 | | |
92 | 9.76k | pub fn get_first_param(self) -> Option<BasicValueEnum<'ctx>> { |
93 | 9.76k | let param = unsafe { LLVMGetFirstParam(self.as_value_ref()) }; |
94 | 9.76k | |
95 | 9.76k | if param.is_null() { |
96 | 0 | return None; |
97 | 9.76k | } |
98 | 9.76k | |
99 | 9.76k | unsafe { Some(BasicValueEnum::new(param)) } |
100 | 9.76k | } |
101 | | |
102 | 0 | pub fn get_last_param(self) -> Option<BasicValueEnum<'ctx>> { |
103 | 0 | let param = unsafe { LLVMGetLastParam(self.as_value_ref()) }; |
104 | 0 |
|
105 | 0 | if param.is_null() { |
106 | 0 | return None; |
107 | 0 | } |
108 | 0 |
|
109 | 0 | unsafe { Some(BasicValueEnum::new(param)) } |
110 | 0 | } |
111 | | |
112 | 0 | pub fn get_first_basic_block(self) -> Option<BasicBlock<'ctx>> { |
113 | 0 | unsafe { BasicBlock::new(LLVMGetFirstBasicBlock(self.as_value_ref())) } |
114 | 0 | } |
115 | | |
116 | 514k | pub fn get_nth_param(self, nth: u32) -> Option<BasicValueEnum<'ctx>> { |
117 | 514k | let count = self.count_params(); |
118 | 514k | |
119 | 514k | if nth + 1 > count { |
120 | 0 | return None; |
121 | 514k | } |
122 | 514k | |
123 | 514k | unsafe { Some(BasicValueEnum::new(LLVMGetParam(self.as_value_ref(), nth))) } |
124 | 514k | } |
125 | | |
126 | 572k | pub fn count_params(self) -> u32 { |
127 | 572k | unsafe { LLVMCountParams(self.fn_value.value) } |
128 | 572k | } |
129 | | |
130 | 0 | pub fn count_basic_blocks(self) -> u32 { |
131 | 0 | unsafe { LLVMCountBasicBlocks(self.as_value_ref()) } |
132 | 0 | } |
133 | | |
134 | 0 | pub fn get_basic_blocks(self) -> Vec<BasicBlock<'ctx>> { |
135 | 0 | let count = self.count_basic_blocks(); |
136 | 0 | let mut raw_vec: Vec<LLVMBasicBlockRef> = Vec::with_capacity(count as usize); |
137 | 0 | let ptr = raw_vec.as_mut_ptr(); |
138 | 0 |
|
139 | 0 | forget(raw_vec); |
140 | 0 |
|
141 | 0 | let raw_vec = unsafe { |
142 | 0 | LLVMGetBasicBlocks(self.as_value_ref(), ptr); |
143 | 0 |
|
144 | 0 | Vec::from_raw_parts(ptr, count as usize, count as usize) |
145 | 0 | }; |
146 | 0 |
|
147 | 0 | raw_vec |
148 | 0 | .iter() |
149 | 0 | .map(|val| unsafe { BasicBlock::new(*val).unwrap() }) |
150 | 0 | .collect() |
151 | 0 | } |
152 | | |
153 | 0 | pub fn get_param_iter(self) -> ParamValueIter<'ctx> { |
154 | 0 | ParamValueIter { |
155 | 0 | param_iter_value: self.fn_value.value, |
156 | 0 | start: true, |
157 | 0 | _marker: PhantomData, |
158 | 0 | } |
159 | 0 | } |
160 | | |
161 | 57.2k | pub fn get_params(self) -> Vec<BasicValueEnum<'ctx>> { |
162 | 57.2k | let count = self.count_params(); |
163 | 57.2k | let mut raw_vec: Vec<LLVMValueRef> = Vec::with_capacity(count as usize); |
164 | 57.2k | let ptr = raw_vec.as_mut_ptr(); |
165 | 57.2k | |
166 | 57.2k | forget(raw_vec); |
167 | 57.2k | |
168 | 57.2k | let raw_vec = unsafe { |
169 | 57.2k | LLVMGetParams(self.as_value_ref(), ptr); |
170 | 57.2k | |
171 | 57.2k | Vec::from_raw_parts(ptr, count as usize, count as usize) |
172 | 57.2k | }; |
173 | 57.2k | |
174 | 171k | raw_vec.iter().map(|val| unsafe { BasicValueEnum::new(*val) }).collect() |
175 | 57.2k | } |
176 | | |
177 | 0 | pub fn get_last_basic_block(self) -> Option<BasicBlock<'ctx>> { |
178 | 0 | unsafe { BasicBlock::new(LLVMGetLastBasicBlock(self.fn_value.value)) } |
179 | 0 | } |
180 | | |
181 | | /// Gets the name of a `FunctionValue`. |
182 | 0 | pub fn get_name(&self) -> &CStr { |
183 | 0 | self.fn_value.get_name() |
184 | 0 | } |
185 | | |
186 | | /// View the control flow graph and produce a .dot file |
187 | 0 | pub fn view_function_cfg(self) { |
188 | 0 | unsafe { LLVMViewFunctionCFG(self.as_value_ref()) } |
189 | 0 | } |
190 | | |
191 | | /// Only view the control flow graph |
192 | 0 | pub fn view_function_cfg_only(self) { |
193 | 0 | unsafe { LLVMViewFunctionCFGOnly(self.as_value_ref()) } |
194 | 0 | } |
195 | | |
196 | | // TODO: Look for ways to prevent use after delete but maybe not possible |
197 | 0 | pub unsafe fn delete(self) { |
198 | 0 | LLVMDeleteFunction(self.as_value_ref()) |
199 | 0 | } |
200 | | |
201 | | #[llvm_versions(4.0..=7.0)] |
202 | | pub fn get_type(self) -> FunctionType<'ctx> { |
203 | | use crate::types::PointerType; |
204 | | |
205 | | let ptr_type = unsafe { PointerType::new(self.fn_value.get_type()) }; |
206 | | |
207 | | ptr_type.get_element_type().into_function_type() |
208 | | } |
209 | | |
210 | | #[llvm_versions(8.0..=latest)] |
211 | 661k | pub fn get_type(self) -> FunctionType<'ctx> { |
212 | 661k | unsafe { FunctionType::new(llvm_sys::core::LLVMGlobalGetValueType(self.as_value_ref())) } |
213 | 661k | } |
214 | | |
215 | | // TODOC: How this works as an exception handler |
216 | 0 | pub fn has_personality_function(self) -> bool { |
217 | 0 | use llvm_sys::core::LLVMHasPersonalityFn; |
218 | 0 |
|
219 | 0 | unsafe { LLVMHasPersonalityFn(self.as_value_ref()) == 1 } |
220 | 0 | } |
221 | | |
222 | 0 | pub fn get_personality_function(self) -> Option<FunctionValue<'ctx>> { |
223 | 0 | // This prevents a segfault when not having a pfn |
224 | 0 | if !self.has_personality_function() { |
225 | 0 | return None; |
226 | 0 | } |
227 | 0 |
|
228 | 0 | unsafe { FunctionValue::new(LLVMGetPersonalityFn(self.as_value_ref())) } |
229 | 0 | } |
230 | | |
231 | 101k | pub fn set_personality_function(self, personality_fn: FunctionValue<'ctx>) { |
232 | 101k | unsafe { LLVMSetPersonalityFn(self.as_value_ref(), personality_fn.as_value_ref()) } |
233 | 101k | } |
234 | | |
235 | 0 | pub fn get_intrinsic_id(self) -> u32 { |
236 | 0 | unsafe { LLVMGetIntrinsicID(self.as_value_ref()) } |
237 | 0 | } |
238 | | |
239 | 0 | pub fn get_call_conventions(self) -> u32 { |
240 | 0 | unsafe { LLVMGetFunctionCallConv(self.as_value_ref()) } |
241 | 0 | } |
242 | | |
243 | 0 | pub fn set_call_conventions(self, call_conventions: u32) { |
244 | 0 | unsafe { LLVMSetFunctionCallConv(self.as_value_ref(), call_conventions) } |
245 | 0 | } |
246 | | |
247 | 0 | pub fn get_gc(&self) -> &CStr { |
248 | 0 | unsafe { CStr::from_ptr(LLVMGetGC(self.as_value_ref())) } |
249 | 0 | } |
250 | | |
251 | 0 | pub fn set_gc(self, gc: &str) { |
252 | 0 | let c_string = to_c_str(gc); |
253 | 0 |
|
254 | 0 | unsafe { LLVMSetGC(self.as_value_ref(), c_string.as_ptr()) } |
255 | 0 | } |
256 | | |
257 | 0 | pub fn replace_all_uses_with(self, other: FunctionValue<'ctx>) { |
258 | 0 | self.fn_value.replace_all_uses_with(other.as_value_ref()) |
259 | 0 | } |
260 | | |
261 | | /// Adds an `Attribute` to a particular location in this `FunctionValue`. |
262 | | /// |
263 | | /// # Example |
264 | | /// |
265 | | /// ```no_run |
266 | | /// use inkwell::attributes::AttributeLoc; |
267 | | /// use inkwell::context::Context; |
268 | | /// |
269 | | /// let context = Context::create(); |
270 | | /// let module = context.create_module("my_mod"); |
271 | | /// let void_type = context.void_type(); |
272 | | /// let fn_type = void_type.fn_type(&[], false); |
273 | | /// let fn_value = module.add_function("my_fn", fn_type, None); |
274 | | /// let string_attribute = context.create_string_attribute("my_key", "my_val"); |
275 | | /// let enum_attribute = context.create_enum_attribute(1, 1); |
276 | | /// |
277 | | /// fn_value.add_attribute(AttributeLoc::Return, string_attribute); |
278 | | /// fn_value.add_attribute(AttributeLoc::Return, enum_attribute); |
279 | | /// ``` |
280 | 754k | pub fn add_attribute(self, loc: AttributeLoc, attribute: Attribute) { |
281 | 754k | unsafe { LLVMAddAttributeAtIndex(self.as_value_ref(), loc.get_index(), attribute.attribute) } |
282 | 754k | } |
283 | | |
284 | | /// Counts the number of `Attribute`s belonging to the specified location in this `FunctionValue`. |
285 | | /// |
286 | | /// # Example |
287 | | /// |
288 | | /// ```no_run |
289 | | /// use inkwell::attributes::AttributeLoc; |
290 | | /// use inkwell::context::Context; |
291 | | /// |
292 | | /// let context = Context::create(); |
293 | | /// let module = context.create_module("my_mod"); |
294 | | /// let void_type = context.void_type(); |
295 | | /// let fn_type = void_type.fn_type(&[], false); |
296 | | /// let fn_value = module.add_function("my_fn", fn_type, None); |
297 | | /// let string_attribute = context.create_string_attribute("my_key", "my_val"); |
298 | | /// let enum_attribute = context.create_enum_attribute(1, 1); |
299 | | /// |
300 | | /// fn_value.add_attribute(AttributeLoc::Return, string_attribute); |
301 | | /// fn_value.add_attribute(AttributeLoc::Return, enum_attribute); |
302 | | /// |
303 | | /// assert_eq!(fn_value.count_attributes(AttributeLoc::Return), 2); |
304 | | /// ``` |
305 | 0 | pub fn count_attributes(self, loc: AttributeLoc) -> u32 { |
306 | 0 | unsafe { LLVMGetAttributeCountAtIndex(self.as_value_ref(), loc.get_index()) } |
307 | 0 | } |
308 | | |
309 | | /// Get all `Attribute`s belonging to the specified location in this `FunctionValue`. |
310 | | /// |
311 | | /// # Example |
312 | | /// |
313 | | /// ```no_run |
314 | | /// use inkwell::attributes::AttributeLoc; |
315 | | /// use inkwell::context::Context; |
316 | | /// |
317 | | /// let context = Context::create(); |
318 | | /// let module = context.create_module("my_mod"); |
319 | | /// let void_type = context.void_type(); |
320 | | /// let fn_type = void_type.fn_type(&[], false); |
321 | | /// let fn_value = module.add_function("my_fn", fn_type, None); |
322 | | /// let string_attribute = context.create_string_attribute("my_key", "my_val"); |
323 | | /// let enum_attribute = context.create_enum_attribute(1, 1); |
324 | | /// |
325 | | /// fn_value.add_attribute(AttributeLoc::Return, string_attribute); |
326 | | /// fn_value.add_attribute(AttributeLoc::Return, enum_attribute); |
327 | | /// |
328 | | /// assert_eq!(fn_value.attributes(AttributeLoc::Return), vec![string_attribute, enum_attribute]); |
329 | | /// ``` |
330 | 0 | pub fn attributes(self, loc: AttributeLoc) -> Vec<Attribute> { |
331 | 0 | use llvm_sys::core::LLVMGetAttributesAtIndex; |
332 | 0 | use std::mem::{ManuallyDrop, MaybeUninit}; |
333 | 0 |
|
334 | 0 | let count = self.count_attributes(loc) as usize; |
335 | 0 |
|
336 | 0 | // initialize a vector, but leave each element uninitialized |
337 | 0 | let mut attribute_refs: Vec<MaybeUninit<Attribute>> = vec![MaybeUninit::uninit(); count]; |
338 | 0 |
|
339 | 0 | // Safety: relies on `Attribute` having the same in-memory representation as `LLVMAttributeRef` |
340 | 0 | unsafe { |
341 | 0 | LLVMGetAttributesAtIndex( |
342 | 0 | self.as_value_ref(), |
343 | 0 | loc.get_index(), |
344 | 0 | attribute_refs.as_mut_ptr() as *mut _, |
345 | 0 | ) |
346 | 0 | } |
347 | 0 |
|
348 | 0 | // Safety: all elements are initialized |
349 | 0 | unsafe { |
350 | 0 | // ensure the vector is not dropped |
351 | 0 | let mut attribute_refs = ManuallyDrop::new(attribute_refs); |
352 | 0 |
|
353 | 0 | Vec::from_raw_parts( |
354 | 0 | attribute_refs.as_mut_ptr() as *mut Attribute, |
355 | 0 | attribute_refs.len(), |
356 | 0 | attribute_refs.capacity(), |
357 | 0 | ) |
358 | 0 | } |
359 | 0 | } |
360 | | |
361 | | /// Removes a string `Attribute` belonging to the specified location in this `FunctionValue`. |
362 | | /// |
363 | | /// # Example |
364 | | /// |
365 | | /// ```no_run |
366 | | /// use inkwell::attributes::AttributeLoc; |
367 | | /// use inkwell::context::Context; |
368 | | /// |
369 | | /// let context = Context::create(); |
370 | | /// let module = context.create_module("my_mod"); |
371 | | /// let void_type = context.void_type(); |
372 | | /// let fn_type = void_type.fn_type(&[], false); |
373 | | /// let fn_value = module.add_function("my_fn", fn_type, None); |
374 | | /// let string_attribute = context.create_string_attribute("my_key", "my_val"); |
375 | | /// |
376 | | /// fn_value.add_attribute(AttributeLoc::Return, string_attribute); |
377 | | /// fn_value.remove_string_attribute(AttributeLoc::Return, "my_key"); |
378 | | /// ``` |
379 | 0 | pub fn remove_string_attribute(self, loc: AttributeLoc, key: &str) { |
380 | 0 | unsafe { |
381 | 0 | LLVMRemoveStringAttributeAtIndex( |
382 | 0 | self.as_value_ref(), |
383 | 0 | loc.get_index(), |
384 | 0 | key.as_ptr() as *const ::libc::c_char, |
385 | 0 | key.len() as u32, |
386 | 0 | ) |
387 | 0 | } |
388 | 0 | } |
389 | | |
390 | | /// Removes an enum `Attribute` belonging to the specified location in this `FunctionValue`. |
391 | | /// |
392 | | /// # Example |
393 | | /// |
394 | | /// ```no_run |
395 | | /// use inkwell::attributes::AttributeLoc; |
396 | | /// use inkwell::context::Context; |
397 | | /// |
398 | | /// let context = Context::create(); |
399 | | /// let module = context.create_module("my_mod"); |
400 | | /// let void_type = context.void_type(); |
401 | | /// let fn_type = void_type.fn_type(&[], false); |
402 | | /// let fn_value = module.add_function("my_fn", fn_type, None); |
403 | | /// let enum_attribute = context.create_enum_attribute(1, 1); |
404 | | /// |
405 | | /// fn_value.add_attribute(AttributeLoc::Return, enum_attribute); |
406 | | /// fn_value.remove_enum_attribute(AttributeLoc::Return, 1); |
407 | | /// ``` |
408 | 0 | pub fn remove_enum_attribute(self, loc: AttributeLoc, kind_id: u32) { |
409 | 0 | unsafe { LLVMRemoveEnumAttributeAtIndex(self.as_value_ref(), loc.get_index(), kind_id) } |
410 | 0 | } |
411 | | |
412 | | /// Gets an enum `Attribute` belonging to the specified location in this `FunctionValue`. |
413 | | /// |
414 | | /// # Example |
415 | | /// |
416 | | /// ```no_run |
417 | | /// use inkwell::attributes::AttributeLoc; |
418 | | /// use inkwell::context::Context; |
419 | | /// |
420 | | /// let context = Context::create(); |
421 | | /// let module = context.create_module("my_mod"); |
422 | | /// let void_type = context.void_type(); |
423 | | /// let fn_type = void_type.fn_type(&[], false); |
424 | | /// let fn_value = module.add_function("my_fn", fn_type, None); |
425 | | /// let enum_attribute = context.create_enum_attribute(1, 1); |
426 | | /// |
427 | | /// fn_value.add_attribute(AttributeLoc::Return, enum_attribute); |
428 | | /// |
429 | | /// assert_eq!(fn_value.get_enum_attribute(AttributeLoc::Return, 1), Some(enum_attribute)); |
430 | | /// ``` |
431 | | // SubTypes: -> Option<Attribute<Enum>> |
432 | 101k | pub fn get_enum_attribute(self, loc: AttributeLoc, kind_id: u32) -> Option<Attribute> { |
433 | 101k | let ptr = unsafe { LLVMGetEnumAttributeAtIndex(self.as_value_ref(), loc.get_index(), kind_id) }; |
434 | 101k | |
435 | 101k | if ptr.is_null() { |
436 | 92.2k | return None; |
437 | 9.76k | } |
438 | 9.76k | |
439 | 9.76k | unsafe { Some(Attribute::new(ptr)) } |
440 | 101k | } |
441 | | |
442 | | /// Gets a string `Attribute` belonging to the specified location in this `FunctionValue`. |
443 | | /// |
444 | | /// # Example |
445 | | /// |
446 | | /// ```no_run |
447 | | /// use inkwell::attributes::AttributeLoc; |
448 | | /// use inkwell::context::Context; |
449 | | /// |
450 | | /// let context = Context::create(); |
451 | | /// let module = context.create_module("my_mod"); |
452 | | /// let void_type = context.void_type(); |
453 | | /// let fn_type = void_type.fn_type(&[], false); |
454 | | /// let fn_value = module.add_function("my_fn", fn_type, None); |
455 | | /// let string_attribute = context.create_string_attribute("my_key", "my_val"); |
456 | | /// |
457 | | /// fn_value.add_attribute(AttributeLoc::Return, string_attribute); |
458 | | /// |
459 | | /// assert_eq!(fn_value.get_string_attribute(AttributeLoc::Return, "my_key"), Some(string_attribute)); |
460 | | /// ``` |
461 | | // SubTypes: -> Option<Attribute<String>> |
462 | 0 | pub fn get_string_attribute(self, loc: AttributeLoc, key: &str) -> Option<Attribute> { |
463 | 0 | let ptr = unsafe { |
464 | 0 | LLVMGetStringAttributeAtIndex( |
465 | 0 | self.as_value_ref(), |
466 | 0 | loc.get_index(), |
467 | 0 | key.as_ptr() as *const ::libc::c_char, |
468 | 0 | key.len() as u32, |
469 | 0 | ) |
470 | 0 | }; |
471 | 0 |
|
472 | 0 | if ptr.is_null() { |
473 | 0 | return None; |
474 | 0 | } |
475 | 0 |
|
476 | 0 | unsafe { Some(Attribute::new(ptr)) } |
477 | 0 | } |
478 | | |
479 | 0 | pub fn set_param_alignment(self, param_index: u32, alignment: u32) { |
480 | 0 | if let Some(param) = self.get_nth_param(param_index) { |
481 | 0 | unsafe { LLVMSetParamAlignment(param.as_value_ref(), alignment) } |
482 | 0 | } |
483 | 0 | } |
484 | | |
485 | | /// Gets the `GlobalValue` version of this `FunctionValue`. This allows |
486 | | /// you to further inspect its global properties or even convert it to |
487 | | /// a `PointerValue`. |
488 | 483k | pub fn as_global_value(self) -> GlobalValue<'ctx> { |
489 | 483k | unsafe { GlobalValue::new(self.as_value_ref()) } |
490 | 483k | } |
491 | | |
492 | | /// Set the debug info descriptor |
493 | | #[llvm_versions(7.0..=latest)] |
494 | 0 | pub fn set_subprogram(self, subprogram: DISubprogram<'ctx>) { |
495 | 0 | unsafe { LLVMSetSubprogram(self.as_value_ref(), subprogram.metadata_ref) } |
496 | 0 | } |
497 | | |
498 | | /// Get the debug info descriptor |
499 | | #[llvm_versions(7.0..=latest)] |
500 | 0 | pub fn get_subprogram(self) -> Option<DISubprogram<'ctx>> { |
501 | 0 | let metadata_ref = unsafe { LLVMGetSubprogram(self.as_value_ref()) }; |
502 | 0 |
|
503 | 0 | if metadata_ref.is_null() { |
504 | 0 | None |
505 | | } else { |
506 | 0 | Some(DISubprogram { |
507 | 0 | metadata_ref, |
508 | 0 | _marker: PhantomData, |
509 | 0 | }) |
510 | | } |
511 | 0 | } |
512 | | |
513 | | /// Get the section to which this function belongs |
514 | 0 | pub fn get_section(&self) -> Option<&CStr> { |
515 | 0 | self.fn_value.get_section() |
516 | 0 | } |
517 | | |
518 | | /// Set the section to which this function should belong |
519 | 0 | pub fn set_section(self, section: Option<&str>) { |
520 | 0 | self.fn_value.set_section(section) |
521 | 0 | } |
522 | | } |
523 | | |
524 | | unsafe impl AsValueRef for FunctionValue<'_> { |
525 | 4.55M | fn as_value_ref(&self) -> LLVMValueRef { |
526 | 4.55M | self.fn_value.value |
527 | 4.55M | } |
528 | | } |
529 | | |
530 | | impl Display for FunctionValue<'_> { |
531 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
532 | 0 | write!(f, "{}", self.print_to_string()) |
533 | 0 | } |
534 | | } |
535 | | |
536 | | impl fmt::Debug for FunctionValue<'_> { |
537 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
538 | 0 | let llvm_value = self.print_to_string(); |
539 | 0 | let llvm_type = self.get_type(); |
540 | 0 | let name = self.get_name(); |
541 | 0 | let is_const = unsafe { LLVMIsConstant(self.fn_value.value) == 1 }; |
542 | 0 | let is_null = self.is_null(); |
543 | 0 |
|
544 | 0 | f.debug_struct("FunctionValue") |
545 | 0 | .field("name", &name) |
546 | 0 | .field("address", &self.as_value_ref()) |
547 | 0 | .field("is_const", &is_const) |
548 | 0 | .field("is_null", &is_null) |
549 | 0 | .field("llvm_value", &llvm_value) |
550 | 0 | .field("llvm_type", &llvm_type.print_to_string()) |
551 | 0 | .finish() |
552 | 0 | } |
553 | | } |
554 | | |
555 | | #[derive(Debug)] |
556 | | pub struct ParamValueIter<'ctx> { |
557 | | param_iter_value: LLVMValueRef, |
558 | | start: bool, |
559 | | _marker: PhantomData<&'ctx ()>, |
560 | | } |
561 | | |
562 | | impl<'ctx> Iterator for ParamValueIter<'ctx> { |
563 | | type Item = BasicValueEnum<'ctx>; |
564 | | |
565 | 0 | fn next(&mut self) -> Option<Self::Item> { |
566 | 0 | if self.start { |
567 | 0 | let first_value = unsafe { LLVMGetFirstParam(self.param_iter_value) }; |
568 | 0 |
|
569 | 0 | if first_value.is_null() { |
570 | 0 | return None; |
571 | 0 | } |
572 | 0 |
|
573 | 0 | self.start = false; |
574 | 0 |
|
575 | 0 | self.param_iter_value = first_value; |
576 | 0 |
|
577 | 0 | return unsafe { Some(Self::Item::new(first_value)) }; |
578 | 0 | } |
579 | 0 |
|
580 | 0 | let next_value = unsafe { LLVMGetNextParam(self.param_iter_value) }; |
581 | 0 |
|
582 | 0 | if next_value.is_null() { |
583 | 0 | return None; |
584 | 0 | } |
585 | 0 |
|
586 | 0 | self.param_iter_value = next_value; |
587 | 0 |
|
588 | 0 | unsafe { Some(Self::Item::new(next_value)) } |
589 | 0 | } |
590 | | } |