llama/
value.rs

1use crate::*;
2
3/// LLVM Value wrapper
4#[derive(Copy)]
5pub struct Value<'a>(NonNull<llvm::LLVMValue>, PhantomData<&'a ()>);
6
7llvm_inner_impl!(Value<'a>, llvm::LLVMValue);
8
9/// An enumeration of possible Value kinds
10pub type ValueKind = llvm::LLVMValueKind;
11
12/// Attribute placement index
13#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
14pub enum AttributeIndex {
15    /// Return attribute
16    Return,
17
18    /// Param attribute
19    Param(u32),
20
21    /// Func attribute
22    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    /// Wrap an LLVMValue pointer
56    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    /// Convert from value to metadata
62    pub fn to_metadata(self) -> Metadata<'a> {
63        Metadata(self)
64    }
65
66    /// Returns true if the value is a `BasicBlock`
67    pub fn is_basic_block(self) -> bool {
68        unsafe { llvm::core::LLVMValueIsBasicBlock(self.llvm()) == 0 }
69    }
70
71    /// Get the value kind
72    pub fn kind(self) -> ValueKind {
73        unsafe { llvm::core::LLVMGetValueKind(self.llvm()) }
74    }
75
76    /// Returns true when the value kind matches `kind`
77    pub fn is(self, kind: ValueKind) -> bool {
78        self.kind() == kind
79    }
80
81    /// Get the `Type` of a value
82    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    /// Get the context associated with a value
92    pub fn context(self) -> Result<Context<'a>, Error> {
93        self.type_of()?.into_context()
94    }
95
96    /// Get the name of a value
97    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    /// Set the name of a value
108    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    /// Replace all uses of a value with another value
115    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    /// Delete a global value
120    pub fn delete_global(self) {
121        unsafe { llvm::core::LLVMDeleteGlobal(self.llvm()) }
122    }
123
124    /// Get value initializer
125    pub fn initializer(self) -> Result<Value<'a>, Error> {
126        unsafe { Value::from_inner(llvm::core::LLVMGetInitializer(self.llvm())) }
127    }
128
129    /// Set value initializer
130    pub fn set_initializer(&mut self, val: Const<'a>) {
131        unsafe { llvm::core::LLVMSetInitializer(self.llvm(), val.as_ref().llvm()) }
132    }
133
134    /// Returns true if the value is a global constant
135    pub fn is_global_constant(self) -> bool {
136        unsafe { llvm::core::LLVMIsGlobalConstant(self.llvm()) == 1 }
137    }
138
139    /// Toggle whether or not the value is a global constant
140    pub fn set_global_constant(&mut self, b: bool) {
141        unsafe { llvm::core::LLVMSetGlobalConstant(self.llvm(), b as c_int) }
142    }
143
144    /// Returns true if the value is externally defined
145    pub fn is_extern(self) -> bool {
146        unsafe { llvm::core::LLVMIsExternallyInitialized(self.llvm()) == 1 }
147    }
148
149    /// Toggle whether or not the value is externally declared
150    pub fn set_extern(&mut self, b: bool) {
151        unsafe { llvm::core::LLVMSetExternallyInitialized(self.llvm(), if b { 1 } else { 0 }) }
152    }
153
154    /// Returns true if the value is thread local
155    pub fn is_thread_local(self) -> bool {
156        unsafe { llvm::core::LLVMIsThreadLocal(self.llvm()) == 1 }
157    }
158
159    /// Set whether or not a value is thread local
160    pub fn set_thread_local(&mut self, b: bool) {
161        unsafe { llvm::core::LLVMSetThreadLocal(self.llvm(), if b { 1 } else { 0 }) }
162    }
163
164    /// Returns true when the value is a `Const`
165    pub fn is_const(self) -> bool {
166        unsafe { llvm::core::LLVMIsConstant(self.llvm()) == 1 }
167    }
168
169    /// Convert from value to `Const`
170    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    /// Convert from value to `BasicBlock`
179    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    /// Returns true if the value is undefined
189    pub fn is_undef(self) -> bool {
190        unsafe { llvm::core::LLVMIsUndef(self.llvm()) == 1 }
191    }
192
193    /// Returns true if the value is null
194    pub fn is_null(self) -> bool {
195        unsafe { llvm::core::LLVMIsNull(self.llvm()) == 1 }
196    }
197
198    /// Returns true if the value is a constant string
199    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/// Functions
212#[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    /// Get the name of a value
229    pub fn name(self) -> Result<&'a str, Error> {
230        self.0.name()
231    }
232
233    /// Get the number of params
234    pub fn param_count(self) -> usize {
235        let n = unsafe { llvm::core::LLVMCountParams(self.as_ref().llvm()) };
236        n as usize
237    }
238
239    /// Get the `FuncType`
240    pub fn func_type(self) -> Result<FuncType<'a>, Error> {
241        let t = self.0.type_of()?;
242        t.to_func_type()
243    }
244
245    /// Get a single param by index
246    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    /// Get all params
251    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    /// Verify the function, returning an error on failure
262    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    /// Get the next function
278    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    /// Get the previous function
284    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    /// Delete a function
290    pub fn delete(self) {
291        unsafe { llvm::core::LLVMDeleteFunction(self.as_ref().llvm()) }
292    }
293
294    /// Returns true when the value has a `personality_fn`
295    pub fn has_personality_fn(self) -> bool {
296        unsafe { llvm::core::LLVMHasPersonalityFn(self.as_ref().llvm()) == 1 }
297    }
298
299    /// Returns the `personality_fn`
300    pub fn personality_fn(self) -> Result<Value<'a>, Error> {
301        unsafe { Value::from_inner(llvm::core::LLVMGetPersonalityFn(self.as_ref().llvm())) }
302    }
303
304    /// Set the `personality_fn`
305    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    /// Get garbage collection scheme name
310    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    /// Set garbage collection scheme name
323    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    /// Get calling convention
329    pub fn call_conv(self) -> CallConv {
330        unsafe { std::mem::transmute(llvm::core::LLVMGetFunctionCallConv(self.as_ref().llvm())) }
331    }
332
333    /// Set calling convention
334    pub fn set_call_conv(&mut self, conv: CallConv) {
335        unsafe { llvm::core::LLVMSetFunctionCallConv(self.as_ref().llvm(), conv as u32) }
336    }
337
338    /// Set attribute
339    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    /// Remove an enum attribute
350    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    /// Remove a string attribute
361    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    /// Get all attributes
375    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    /// Create specified uniqued inline asm string (intel syntax)
397    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    /// Create specified uniqued inline asm string (att syntax)
421    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    /// Get value alignment
445    pub fn alignment(self) -> usize {
446        unsafe { llvm::core::LLVMGetAlignment(self.as_ref().llvm()) as usize }
447    }
448
449    /// Set value alignment
450    pub fn set_alignment(&mut self, align: usize) {
451        unsafe { llvm::core::LLVMSetAlignment(self.as_ref().llvm(), align as u32) }
452    }
453
454    /// Get global linkage
455    pub fn global_linkage(self) -> Linkage {
456        unsafe { llvm::core::LLVMGetLinkage(self.as_ref().llvm()) }
457    }
458
459    /// Set global linkage
460    pub fn set_global_linkage(&mut self, l: Linkage) {
461        unsafe { llvm::core::LLVMSetLinkage(self.as_ref().llvm(), l) }
462    }
463
464    /// Get global visibility
465    pub fn global_visibility(self) -> Visibility {
466        unsafe { llvm::core::LLVMGetVisibility(self.as_ref().llvm()) }
467    }
468
469    /// Set global visibility
470    pub fn set_global_visibility(&mut self, l: Visibility) {
471        unsafe { llvm::core::LLVMSetVisibility(self.as_ref().llvm(), l) }
472    }
473
474    /// Count the number of basic blocks
475    pub fn count_basic_blocks(self) -> usize {
476        unsafe { llvm::core::LLVMCountBasicBlocks(self.0.llvm()) as usize }
477    }
478
479    /// Get a list of all basic blocks
480    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    /// Get first basic block
492    pub fn first_basic_block(self) -> Result<BasicBlock<'a>, Error> {
493        BasicBlock::from_inner(unsafe { llvm::core::LLVMGetFirstBasicBlock(self.0.llvm()) })
494    }
495
496    /// Get last basic block
497    pub fn last_basic_block(self) -> Result<BasicBlock<'a>, Error> {
498        BasicBlock::from_inner(unsafe { llvm::core::LLVMGetLastBasicBlock(self.0.llvm()) })
499    }
500
501    /// Get entry block
502    pub fn entry_basic_block(self) -> Result<BasicBlock<'a>, Error> {
503        BasicBlock::from_inner(unsafe { llvm::core::LLVMGetEntryBasicBlock(self.0.llvm()) })
504    }
505
506    /// Append a new block
507    pub fn append_basic_block(self, bb: BasicBlock<'a>) {
508        unsafe { llvm::core::LLVMAppendExistingBasicBlock(self.0.llvm(), bb.llvm()) }
509    }
510}