1use crate::*;
2
3#[derive(Copy)]
5pub struct Value<'a>(NonNull<llvm::LLVMValue>, PhantomData<&'a ()>);
6
7llvm_inner_impl!(Value<'a>, llvm::LLVMValue);
8
9pub type ValueKind = llvm::LLVMValueKind;
11
12#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
14pub enum AttributeIndex {
15 Return,
17
18 Param(u32),
20
21 Func,
23}
24
25impl AttributeIndex {
26 pub(crate) fn get_index(self) -> u32 {
27 match self {
28 AttributeIndex::Return => llvm::LLVMAttributeReturnIndex,
29 AttributeIndex::Param(index) => {
30 assert!(
31 index <= u32::max_value() - 2,
32 "Param index must be <= u32::max_value() - 2"
33 );
34
35 index + 1
36 }
37 AttributeIndex::Func => llvm::LLVMAttributeFunctionIndex,
38 }
39 }
40}
41
42impl<'a> AsRef<Value<'a>> for Value<'a> {
43 fn as_ref(&self) -> &Value<'a> {
44 self
45 }
46}
47
48impl<'a> Clone for Value<'a> {
49 fn clone(&self) -> Value<'a> {
50 Value(self.0, PhantomData)
51 }
52}
53
54impl<'a> Value<'a> {
55 pub fn from_inner(ptr: *mut llvm::LLVMValue) -> Result<Value<'a>, Error> {
57 let t = wrap_inner(ptr)?;
58 Ok(Value(t, PhantomData))
59 }
60
61 pub fn to_metadata(self) -> Metadata<'a> {
63 Metadata(self)
64 }
65
66 pub fn is_basic_block(self) -> bool {
68 unsafe { llvm::core::LLVMValueIsBasicBlock(self.llvm()) == 0 }
69 }
70
71 pub fn kind(self) -> ValueKind {
73 unsafe { llvm::core::LLVMGetValueKind(self.llvm()) }
74 }
75
76 pub fn is(self, kind: ValueKind) -> bool {
78 self.kind() == kind
79 }
80
81 pub fn type_of(self) -> Result<Type<'a>, Error> {
83 let t = unsafe { llvm::core::LLVMTypeOf(self.llvm()) };
84 Type::from_inner(t)
85 }
86
87 pub(crate) fn into_context(self) -> Result<Context<'a>, Error> {
88 self.type_of()?.into_context()
89 }
90
91 pub fn context(self) -> Result<Context<'a>, Error> {
93 self.type_of()?.into_context()
94 }
95
96 pub fn name(self) -> Result<&'a str, Error> {
98 let mut size = 0;
99 unsafe {
100 let s = llvm::core::LLVMGetValueName2(self.llvm(), &mut size);
101 let s = std::slice::from_raw_parts(s as *const u8, size);
102 let s = std::str::from_utf8(s)?;
103 Ok(s)
104 }
105 }
106
107 pub fn set_name(&mut self, name: impl AsRef<str>) {
109 let len = name.as_ref().len();
110 let name = cstr!(name.as_ref());
111 unsafe { llvm::core::LLVMSetValueName2(self.llvm(), name.as_ptr(), len) }
112 }
113
114 pub fn replace_all_uses_with(self, other: impl AsRef<Value<'a>>) {
116 unsafe { llvm::core::LLVMReplaceAllUsesWith(self.llvm(), other.as_ref().llvm()) }
117 }
118
119 pub fn delete_global(self) {
121 unsafe { llvm::core::LLVMDeleteGlobal(self.llvm()) }
122 }
123
124 pub fn initializer(self) -> Result<Value<'a>, Error> {
126 unsafe { Value::from_inner(llvm::core::LLVMGetInitializer(self.llvm())) }
127 }
128
129 pub fn set_initializer(&mut self, val: Const<'a>) {
131 unsafe { llvm::core::LLVMSetInitializer(self.llvm(), val.as_ref().llvm()) }
132 }
133
134 pub fn is_global_constant(self) -> bool {
136 unsafe { llvm::core::LLVMIsGlobalConstant(self.llvm()) == 1 }
137 }
138
139 pub fn set_global_constant(&mut self, b: bool) {
141 unsafe { llvm::core::LLVMSetGlobalConstant(self.llvm(), b as c_int) }
142 }
143
144 pub fn is_extern(self) -> bool {
146 unsafe { llvm::core::LLVMIsExternallyInitialized(self.llvm()) == 1 }
147 }
148
149 pub fn set_extern(&mut self, b: bool) {
151 unsafe { llvm::core::LLVMSetExternallyInitialized(self.llvm(), if b { 1 } else { 0 }) }
152 }
153
154 pub fn is_thread_local(self) -> bool {
156 unsafe { llvm::core::LLVMIsThreadLocal(self.llvm()) == 1 }
157 }
158
159 pub fn set_thread_local(&mut self, b: bool) {
161 unsafe { llvm::core::LLVMSetThreadLocal(self.llvm(), if b { 1 } else { 0 }) }
162 }
163
164 pub fn is_const(self) -> bool {
166 unsafe { llvm::core::LLVMIsConstant(self.llvm()) == 1 }
167 }
168
169 pub fn to_const(self) -> Result<Const<'a>, Error> {
171 if !self.is_const() {
172 return Err(Error::InvalidConst);
173 }
174
175 Ok(Const(self))
176 }
177
178 pub fn to_basic_block(self) -> Result<BasicBlock<'a>, Error> {
180 if !self.is_basic_block() {
181 return Err(Error::InvalidBasicBlock);
182 }
183
184 let ptr = unsafe { llvm::core::LLVMValueAsBasicBlock(self.llvm()) };
185 BasicBlock::from_inner(ptr)
186 }
187
188 pub fn is_undef(self) -> bool {
190 unsafe { llvm::core::LLVMIsUndef(self.llvm()) == 1 }
191 }
192
193 pub fn is_null(self) -> bool {
195 unsafe { llvm::core::LLVMIsNull(self.llvm()) == 1 }
196 }
197
198 pub fn is_constant_string(self) -> bool {
200 unsafe { llvm::core::LLVMIsConstantString(self.llvm()) == 1 }
201 }
202}
203
204impl<'a> std::fmt::Display for Value<'a> {
205 fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
206 let message = unsafe { Message::from_raw(llvm::core::LLVMPrintValueToString(self.llvm())) };
207 write!(fmt, "{}", message.as_ref())
208 }
209}
210
211#[derive(Clone, Copy)]
213pub struct Func<'a>(pub Value<'a>);
214
215impl<'a> AsRef<Value<'a>> for Func<'a> {
216 fn as_ref(&self) -> &Value<'a> {
217 &self.0
218 }
219}
220
221impl<'a> From<Func<'a>> for Value<'a> {
222 fn from(x: Func<'a>) -> Value<'a> {
223 x.0
224 }
225}
226
227impl<'a> Func<'a> {
228 pub fn name(self) -> Result<&'a str, Error> {
230 self.0.name()
231 }
232
233 pub fn param_count(self) -> usize {
235 let n = unsafe { llvm::core::LLVMCountParams(self.as_ref().llvm()) };
236 n as usize
237 }
238
239 pub fn func_type(self) -> Result<FuncType<'a>, Error> {
241 let t = self.0.type_of()?;
242 t.to_func_type()
243 }
244
245 pub fn param(self, i: usize) -> Result<Value<'a>, Error> {
247 unsafe { Value::from_inner(llvm::core::LLVMGetParam(self.as_ref().llvm(), i as u32)) }
248 }
249
250 pub fn params(self) -> Vec<Value<'a>> {
252 let len = self.param_count();
253 let mut data = vec![std::ptr::null_mut(); len];
254
255 unsafe { llvm::core::LLVMGetParams(self.as_ref().llvm(), data.as_mut_ptr()) }
256 data.into_iter()
257 .map(|x| Value::from_inner(x).unwrap())
258 .collect()
259 }
260
261 pub fn verify(self) -> Result<(), Error> {
263 let ok = unsafe {
264 llvm::analysis::LLVMVerifyFunction(
265 self.as_ref().llvm(),
266 llvm::analysis::LLVMVerifierFailureAction::LLVMPrintMessageAction,
267 ) == 0
268 };
269
270 if !ok {
271 return Err(Error::InvalidFunction);
272 }
273
274 Ok(())
275 }
276
277 pub fn next_function(self) -> Result<Func<'a>, Error> {
279 let v = unsafe { llvm::core::LLVMGetNextFunction(self.as_ref().llvm()) };
280 Value::from_inner(v).map(Func)
281 }
282
283 pub fn prev_function(self) -> Result<Func<'a>, Error> {
285 let v = unsafe { llvm::core::LLVMGetPreviousFunction(self.as_ref().llvm()) };
286 Value::from_inner(v).map(Func)
287 }
288
289 pub fn delete(self) {
291 unsafe { llvm::core::LLVMDeleteFunction(self.as_ref().llvm()) }
292 }
293
294 pub fn has_personality_fn(self) -> bool {
296 unsafe { llvm::core::LLVMHasPersonalityFn(self.as_ref().llvm()) == 1 }
297 }
298
299 pub fn personality_fn(self) -> Result<Value<'a>, Error> {
301 unsafe { Value::from_inner(llvm::core::LLVMGetPersonalityFn(self.as_ref().llvm())) }
302 }
303
304 pub fn set_personality_fn(&mut self, f: impl AsRef<Value<'a>>) {
306 unsafe { llvm::core::LLVMSetPersonalityFn(self.as_ref().llvm(), f.as_ref().llvm()) }
307 }
308
309 pub fn gc(self) -> Option<&'a str> {
311 let gc = unsafe { llvm::core::LLVMGetGC(self.as_ref().llvm()) };
312 if gc.is_null() {
313 return None;
314 }
315
316 unsafe {
317 let slice = std::slice::from_raw_parts(gc as *const u8, strlen(gc));
318 Some(std::str::from_utf8_unchecked(slice))
319 }
320 }
321
322 pub fn set_gc(&mut self, name: impl AsRef<str>) {
324 let name = cstr!(name.as_ref());
325 unsafe { llvm::core::LLVMSetGC(self.as_ref().llvm(), name.as_ptr()) }
326 }
327
328 pub fn call_conv(self) -> CallConv {
330 unsafe { std::mem::transmute(llvm::core::LLVMGetFunctionCallConv(self.as_ref().llvm())) }
331 }
332
333 pub fn set_call_conv(&mut self, conv: CallConv) {
335 unsafe { llvm::core::LLVMSetFunctionCallConv(self.as_ref().llvm(), conv as u32) }
336 }
337
338 pub fn add_attribute(&mut self, index: AttributeIndex, attr: &Attribute<'a>) {
340 unsafe {
341 llvm::core::LLVMAddAttributeAtIndex(
342 self.as_ref().llvm(),
343 index.get_index(),
344 attr.llvm(),
345 )
346 }
347 }
348
349 pub fn remove_enum_atribute(&mut self, index: AttributeIndex, kind_id: u32) {
351 unsafe {
352 llvm::core::LLVMRemoveEnumAttributeAtIndex(
353 self.as_ref().llvm(),
354 index.get_index(),
355 kind_id,
356 )
357 }
358 }
359
360 pub fn remove_string_atribute(&mut self, index: AttributeIndex, k: impl AsRef<str>) {
362 let len = k.as_ref().len();
363 let k = cstr!(k.as_ref());
364 unsafe {
365 llvm::core::LLVMRemoveStringAttributeAtIndex(
366 self.as_ref().llvm(),
367 index.get_index(),
368 k.as_ptr(),
369 len as u32,
370 )
371 }
372 }
373
374 pub fn attributes(self, index: usize) -> Vec<Attribute<'a>> {
376 let count = unsafe {
377 llvm::core::LLVMGetAttributeCountAtIndex(self.as_ref().llvm(), index as c_uint)
378 };
379
380 let mut output = vec![std::ptr::null_mut(); count as usize];
381
382 unsafe {
383 llvm::core::LLVMGetAttributesAtIndex(
384 self.as_ref().llvm(),
385 index as c_uint,
386 output.as_mut_ptr(),
387 );
388 }
389
390 output
391 .into_iter()
392 .map(|x| Attribute::from_inner(x).unwrap())
393 .collect()
394 }
395
396 pub fn inline_asm_intel(
398 t: impl AsRef<Type<'a>>,
399 s: impl AsRef<str>,
400 constraints: impl AsRef<str>,
401 has_side_effects: bool,
402 is_align_stack: bool,
403 can_throw: bool,
404 ) -> Result<Value<'a>, Error> {
405 unsafe {
406 Value::from_inner(llvm::core::LLVMGetInlineAsm(
407 t.as_ref().llvm(),
408 s.as_ref().as_ptr() as *mut c_char,
409 s.as_ref().len(),
410 constraints.as_ref().as_ptr() as *mut c_char,
411 constraints.as_ref().len(),
412 has_side_effects as c_int,
413 is_align_stack as c_int,
414 llvm::LLVMInlineAsmDialect::LLVMInlineAsmDialectIntel,
415 can_throw as c_int,
416 ))
417 }
418 }
419
420 pub fn inline_asm_att(
422 t: impl AsRef<Type<'a>>,
423 s: impl AsRef<str>,
424 constraints: impl AsRef<str>,
425 has_side_effects: bool,
426 is_align_stack: bool,
427 can_throw: bool,
428 ) -> Result<Value<'a>, Error> {
429 unsafe {
430 Value::from_inner(llvm::core::LLVMGetInlineAsm(
431 t.as_ref().llvm(),
432 s.as_ref().as_ptr() as *mut c_char,
433 s.as_ref().len(),
434 constraints.as_ref().as_ptr() as *mut c_char,
435 constraints.as_ref().len(),
436 has_side_effects as c_int,
437 is_align_stack as c_int,
438 llvm::LLVMInlineAsmDialect::LLVMInlineAsmDialectATT,
439 can_throw as c_int,
440 ))
441 }
442 }
443
444 pub fn alignment(self) -> usize {
446 unsafe { llvm::core::LLVMGetAlignment(self.as_ref().llvm()) as usize }
447 }
448
449 pub fn set_alignment(&mut self, align: usize) {
451 unsafe { llvm::core::LLVMSetAlignment(self.as_ref().llvm(), align as u32) }
452 }
453
454 pub fn global_linkage(self) -> Linkage {
456 unsafe { llvm::core::LLVMGetLinkage(self.as_ref().llvm()) }
457 }
458
459 pub fn set_global_linkage(&mut self, l: Linkage) {
461 unsafe { llvm::core::LLVMSetLinkage(self.as_ref().llvm(), l) }
462 }
463
464 pub fn global_visibility(self) -> Visibility {
466 unsafe { llvm::core::LLVMGetVisibility(self.as_ref().llvm()) }
467 }
468
469 pub fn set_global_visibility(&mut self, l: Visibility) {
471 unsafe { llvm::core::LLVMSetVisibility(self.as_ref().llvm(), l) }
472 }
473
474 pub fn count_basic_blocks(self) -> usize {
476 unsafe { llvm::core::LLVMCountBasicBlocks(self.0.llvm()) as usize }
477 }
478
479 pub fn basic_blocks(self) -> Vec<BasicBlock<'a>> {
481 let count = self.count_basic_blocks();
482 let ptr = std::ptr::null_mut();
483 unsafe { llvm::core::LLVMGetBasicBlocks(self.0.llvm(), ptr) }
484 let slice = unsafe { std::slice::from_raw_parts(ptr, count) };
485 slice
486 .iter()
487 .map(|x| BasicBlock::from_inner(*x).unwrap())
488 .collect()
489 }
490
491 pub fn first_basic_block(self) -> Result<BasicBlock<'a>, Error> {
493 BasicBlock::from_inner(unsafe { llvm::core::LLVMGetFirstBasicBlock(self.0.llvm()) })
494 }
495
496 pub fn last_basic_block(self) -> Result<BasicBlock<'a>, Error> {
498 BasicBlock::from_inner(unsafe { llvm::core::LLVMGetLastBasicBlock(self.0.llvm()) })
499 }
500
501 pub fn entry_basic_block(self) -> Result<BasicBlock<'a>, Error> {
503 BasicBlock::from_inner(unsafe { llvm::core::LLVMGetEntryBasicBlock(self.0.llvm()) })
504 }
505
506 pub fn append_basic_block(self, bb: BasicBlock<'a>) {
508 unsafe { llvm::core::LLVMAppendExistingBasicBlock(self.0.llvm(), bb.llvm()) }
509 }
510}