aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/llvm
diff options
context:
space:
mode:
Diffstat (limited to 'src/llvm')
-rw-r--r--src/llvm/builder.rs16
-rw-r--r--src/llvm/mod.rs2
-rw-r--r--src/llvm/value.rs72
3 files changed, 75 insertions, 15 deletions
diff --git a/src/llvm/builder.rs b/src/llvm/builder.rs
index 8f581f9..da10231 100644
--- a/src/llvm/builder.rs
+++ b/src/llvm/builder.rs
@@ -10,7 +10,7 @@ use llvm_sys::{
use std::marker::PhantomData;
-use super::{BasicBlock, FnValue, Module, Type, Value};
+use super::{BasicBlock, FnValue, Module, PhiValue, Type, Value};
// Definition of LLVM C API functions using our `repr(transparent)` types.
extern "C" {
@@ -131,8 +131,8 @@ impl<'llvm> IRBuilder<'llvm> {
///
/// Panics if LLVM API returns a `null` pointer.
pub fn fcmpult(&self, lhs: Value<'llvm>, rhs: Value<'llvm>) -> Value<'llvm> {
- debug_assert!(lhs.is_f64(), "fcmplt: Expected f64 as lhs operand!");
- debug_assert!(rhs.is_f64(), "fcmplt: Expected f64 as rhs operand!");
+ debug_assert!(lhs.is_f64(), "fcmpult: Expected f64 as lhs operand!");
+ debug_assert!(rhs.is_f64(), "fcmpult: Expected f64 as rhs operand!");
let value_ref = unsafe {
LLVMBuildFCmp(
@@ -140,7 +140,7 @@ impl<'llvm> IRBuilder<'llvm> {
LLVMRealPredicate::LLVMRealULT,
lhs.value_ref(),
rhs.value_ref(),
- b"fcmplt\0".as_ptr().cast(),
+ b"fcmpult\0".as_ptr().cast(),
)
};
Value::new(value_ref)
@@ -152,8 +152,8 @@ impl<'llvm> IRBuilder<'llvm> {
///
/// Panics if LLVM API returns a `null` pointer.
pub fn fcmpone(&self, lhs: Value<'llvm>, rhs: Value<'llvm>) -> Value<'llvm> {
- debug_assert!(lhs.is_f64(), "fcmplt: Expected f64 as lhs operand!");
- debug_assert!(rhs.is_f64(), "fcmplt: Expected f64 as rhs operand!");
+ debug_assert!(lhs.is_f64(), "fcmone: Expected f64 as lhs operand!");
+ debug_assert!(rhs.is_f64(), "fcmone: Expected f64 as rhs operand!");
let value_ref = unsafe {
LLVMBuildFCmp(
@@ -251,7 +251,7 @@ impl<'llvm> IRBuilder<'llvm> {
&self,
phi_type: Type<'llvm>,
incoming: &[(Value<'llvm>, BasicBlock<'llvm>)],
- ) -> Value<'llvm> {
+ ) -> PhiValue<'llvm> {
let phi_ref =
unsafe { LLVMBuildPhi(self.builder, phi_type.type_ref(), b"phi\0".as_ptr().cast()) };
assert!(!phi_ref.is_null());
@@ -268,7 +268,7 @@ impl<'llvm> IRBuilder<'llvm> {
}
}
- Value::new(phi_ref)
+ PhiValue::new(phi_ref)
}
}
diff --git a/src/llvm/mod.rs b/src/llvm/mod.rs
index c9f17b6..1eb9c57 100644
--- a/src/llvm/mod.rs
+++ b/src/llvm/mod.rs
@@ -33,7 +33,7 @@ pub use lljit::{LLJit, ResourceTracker};
pub use module::Module;
pub use pass_manager::FunctionPassManager;
pub use type_::Type;
-pub use value::{FnValue, Value};
+pub use value::{FnValue, PhiValue, Value};
struct Error<'llvm>(&'llvm mut libc::c_char);
diff --git a/src/llvm/value.rs b/src/llvm/value.rs
index 219c855..912c14e 100644
--- a/src/llvm/value.rs
+++ b/src/llvm/value.rs
@@ -1,9 +1,11 @@
+#![allow(unused)]
+
use llvm_sys::{
analysis::{LLVMVerifierFailureAction, LLVMVerifyFunction},
core::{
- LLVMAppendExistingBasicBlock, LLVMCountBasicBlocks, LLVMCountParams, LLVMDumpValue,
- LLVMGetParam, LLVMGetReturnType, LLVMGetValueKind, LLVMGetValueName2, LLVMSetValueName2,
- LLVMTypeOf,
+ LLVMAddIncoming, LLVMAppendExistingBasicBlock, LLVMCountBasicBlocks, LLVMCountParams,
+ LLVMDumpValue, LLVMGetParam, LLVMGetReturnType, LLVMGetValueKind, LLVMGetValueName2,
+ LLVMIsAFunction, LLVMIsAPHINode, LLVMSetValueName2, LLVMTypeOf,
},
prelude::LLVMValueRef,
LLVMTypeKind, LLVMValueKind,
@@ -43,6 +45,18 @@ impl<'llvm> Value<'llvm> {
unsafe { LLVMGetValueKind(self.value_ref()) }
}
+ /// Check if value is `function` type.
+ pub(super) fn is_function(&self) -> bool {
+ let cast = unsafe { LLVMIsAFunction(self.value_ref()) };
+ !cast.is_null()
+ }
+
+ /// Check if value is `phinode` type.
+ pub(super) fn is_phinode(&self) -> bool {
+ let cast = unsafe { LLVMIsAPHINode(self.value_ref()) };
+ !cast.is_null()
+ }
+
/// Dump the LLVM Value to stdout.
pub fn dump(&self) {
unsafe { LLVMDumpValue(self.value_ref()) };
@@ -117,9 +131,8 @@ impl<'llvm> FnValue<'llvm> {
/// Panics if `value_ref` is a null pointer.
pub(super) fn new(value_ref: LLVMValueRef) -> Self {
let value = Value::new(value_ref);
- debug_assert_eq!(
- value.kind(),
- LLVMValueKind::LLVMFunctionValueKind,
+ debug_assert!(
+ value.is_function(),
"Expected a fn value when constructing FnValue!"
);
@@ -175,3 +188,50 @@ impl<'llvm> FnValue<'llvm> {
}
}
}
+
+/// Wrapper for a LLVM Value Reference specialized for contexts where phi values are needed.
+#[derive(Copy, Clone)]
+#[repr(transparent)]
+pub struct PhiValue<'llvm>(Value<'llvm>);
+
+impl<'llvm> Deref for PhiValue<'llvm> {
+ type Target = Value<'llvm>;
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+impl<'llvm> PhiValue<'llvm> {
+ /// Create a new PhiValue instance.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `value_ref` is a null pointer.
+ pub(super) fn new(value_ref: LLVMValueRef) -> Self {
+ let value = Value::new(value_ref);
+ debug_assert!(
+ value.is_phinode(),
+ "Expected a phinode value when constructing PhiValue!"
+ );
+
+ PhiValue(value)
+ }
+
+ /// Add an incoming value to the end of a PHI list.
+ pub fn add_incoming(&self, ival: Value<'llvm>, ibb: BasicBlock<'llvm>) {
+ debug_assert_eq!(
+ ival.type_of().kind(),
+ self.type_of().kind(),
+ "Type of incoming phi value must be the same as the type used to build the phi node."
+ );
+
+ unsafe {
+ LLVMAddIncoming(
+ self.value_ref(),
+ &mut ival.value_ref() as _,
+ &mut ibb.bb_ref() as _,
+ 1,
+ );
+ }
+ }
+}