Skip to content

Commit

Permalink
Initial support for generic values
Browse files Browse the repository at this point in the history
  • Loading branch information
TheDan64 committed Sep 7, 2017
1 parent 5d8ea13 commit 65bd81a
Show file tree
Hide file tree
Showing 7 changed files with 121 additions and 3 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ categories = ["development-tools::ffi"]
[dependencies]
either = "1.1.0"
enum-methods = "0.0.6"
libc = "*"
llvm-sys = "37.0.5" # TODO: Configure based on feature toggle. GH#1

[badges]
Expand Down
32 changes: 31 additions & 1 deletion src/builder.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use either::Either;
use llvm_sys::core::{LLVMBuildAdd, LLVMBuildAlloca, LLVMBuildAnd, LLVMBuildArrayAlloca, LLVMBuildArrayMalloc, LLVMBuildBr, LLVMBuildCall, LLVMBuildCast, LLVMBuildCondBr, LLVMBuildExtractValue, LLVMBuildFAdd, LLVMBuildFCmp, LLVMBuildFDiv, LLVMBuildFence, LLVMBuildFMul, LLVMBuildFNeg, LLVMBuildFree, LLVMBuildFSub, LLVMBuildGEP, LLVMBuildICmp, LLVMBuildInsertValue, LLVMBuildIsNotNull, LLVMBuildIsNull, LLVMBuildLoad, LLVMBuildMalloc, LLVMBuildMul, LLVMBuildNeg, LLVMBuildNot, LLVMBuildOr, LLVMBuildPhi, LLVMBuildPointerCast, LLVMBuildRet, LLVMBuildRetVoid, LLVMBuildStore, LLVMBuildSub, LLVMBuildUDiv, LLVMBuildUnreachable, LLVMBuildXor, LLVMDisposeBuilder, LLVMGetElementType, LLVMGetInsertBlock, LLVMGetReturnType, LLVMGetTypeKind, LLVMInsertIntoBuilder, LLVMPositionBuilderAtEnd, LLVMTypeOf, LLVMSetTailCall, LLVMBuildExtractElement, LLVMBuildInsertElement, LLVMBuildIntToPtr, LLVMBuildPtrToInt, LLVMInsertIntoBuilderWithName, LLVMClearInsertionPosition, LLVMCreateBuilder, LLVMPositionBuilder, LLVMPositionBuilderBefore, LLVMBuildAggregateRet, LLVMBuildStructGEP, LLVMBuildInBoundsGEP, LLVMBuildPtrDiff, LLVMBuildNSWAdd, LLVMBuildNUWAdd, LLVMBuildNSWSub, LLVMBuildNUWSub, LLVMBuildNSWMul, LLVMBuildNUWMul, LLVMBuildSDiv, LLVMBuildSRem, LLVMBuildURem, LLVMBuildFRem, LLVMBuildNSWNeg, LLVMBuildNUWNeg, LLVMBuildFPToUI, LLVMBuildFPToSI, LLVMBuildSIToFP, LLVMBuildUIToFP, LLVMBuildFPTrunc, LLVMBuildFPExt, LLVMBuildIntCast, LLVMBuildFPCast};
use llvm_sys::core::{LLVMBuildAdd, LLVMBuildAlloca, LLVMBuildAnd, LLVMBuildArrayAlloca, LLVMBuildArrayMalloc, LLVMBuildBr, LLVMBuildCall, LLVMBuildCast, LLVMBuildCondBr, LLVMBuildExtractValue, LLVMBuildFAdd, LLVMBuildFCmp, LLVMBuildFDiv, LLVMBuildFence, LLVMBuildFMul, LLVMBuildFNeg, LLVMBuildFree, LLVMBuildFSub, LLVMBuildGEP, LLVMBuildICmp, LLVMBuildInsertValue, LLVMBuildIsNotNull, LLVMBuildIsNull, LLVMBuildLoad, LLVMBuildMalloc, LLVMBuildMul, LLVMBuildNeg, LLVMBuildNot, LLVMBuildOr, LLVMBuildPhi, LLVMBuildPointerCast, LLVMBuildRet, LLVMBuildRetVoid, LLVMBuildStore, LLVMBuildSub, LLVMBuildUDiv, LLVMBuildUnreachable, LLVMBuildXor, LLVMDisposeBuilder, LLVMGetElementType, LLVMGetInsertBlock, LLVMGetReturnType, LLVMGetTypeKind, LLVMInsertIntoBuilder, LLVMPositionBuilderAtEnd, LLVMTypeOf, LLVMSetTailCall, LLVMBuildExtractElement, LLVMBuildInsertElement, LLVMBuildIntToPtr, LLVMBuildPtrToInt, LLVMInsertIntoBuilderWithName, LLVMClearInsertionPosition, LLVMCreateBuilder, LLVMPositionBuilder, LLVMPositionBuilderBefore, LLVMBuildAggregateRet, LLVMBuildStructGEP, LLVMBuildInBoundsGEP, LLVMBuildPtrDiff, LLVMBuildNSWAdd, LLVMBuildNUWAdd, LLVMBuildNSWSub, LLVMBuildNUWSub, LLVMBuildNSWMul, LLVMBuildNUWMul, LLVMBuildSDiv, LLVMBuildSRem, LLVMBuildURem, LLVMBuildFRem, LLVMBuildNSWNeg, LLVMBuildNUWNeg, LLVMBuildFPToUI, LLVMBuildFPToSI, LLVMBuildSIToFP, LLVMBuildUIToFP, LLVMBuildFPTrunc, LLVMBuildFPExt, LLVMBuildIntCast, LLVMBuildFPCast, LLVMBuildSExtOrBitCast, LLVMBuildZExtOrBitCast, LLVMBuildTruncOrBitCast};
use llvm_sys::prelude::{LLVMBuilderRef, LLVMValueRef};
use llvm_sys::{LLVMOpcode, LLVMIntPredicate, LLVMTypeKind, LLVMRealPredicate, LLVMAtomicOrdering};

Expand Down Expand Up @@ -287,6 +287,36 @@ impl Builder {
IntValue::new(value)
}

pub fn build_int_s_extend_or_bit_cast(&self, int_value: &IntValue, int_type: &IntType, name: &str) -> IntValue {
let c_string = CString::new(name).expect("Conversion to CString failed unexpectedly");

let value = unsafe {
LLVMBuildSExtOrBitCast(self.builder, int_value.as_value_ref(), int_type.as_type_ref(), c_string.as_ptr())
};

IntValue::new(value)
}

pub fn build_int_z_extend_or_bit_cast(&self, int_value: &IntValue, int_type: &IntType, name: &str) -> IntValue {
let c_string = CString::new(name).expect("Conversion to CString failed unexpectedly");

let value = unsafe {
LLVMBuildZExtOrBitCast(self.builder, int_value.as_value_ref(), int_type.as_type_ref(), c_string.as_ptr())
};

IntValue::new(value)
}

pub fn build_int_truncate_or_bit_cast(&self, int_value: &IntValue, int_type: &IntType, name: &str) -> IntValue {
let c_string = CString::new(name).expect("Conversion to CString failed unexpectedly");

let value = unsafe {
LLVMBuildTruncOrBitCast(self.builder, int_value.as_value_ref(), int_type.as_type_ref(), c_string.as_ptr())
};

IntValue::new(value)
}

pub fn build_float_rem(&self, lhs: &FloatValue, rhs: &FloatValue, name: &str) -> FloatValue {
let c_string = CString::new(name).expect("Conversion to CString failed unexpectedly");

Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
extern crate either;
#[macro_use]
extern crate enum_methods;
extern crate libc;
extern crate llvm_sys;

pub mod basic_block;
Expand Down
11 changes: 10 additions & 1 deletion src/types/float_type.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
use llvm_sys::core::{LLVMConstReal, LLVMConstNull, LLVMHalfType, LLVMFloatType, LLVMDoubleType, LLVMFP128Type, LLVMPPCFP128Type, LLVMConstRealOfString};
use llvm_sys::execution_engine::LLVMCreateGenericValueOfFloat;
use llvm_sys::prelude::LLVMTypeRef;

use std::ffi::{CString, CStr};

use context::ContextRef;
use types::traits::AsTypeRef;
use types::{Type, PointerType, FunctionType, BasicType, ArrayType, VectorType};
use values::{FloatValue, PointerValue, IntValue};
use values::{FloatValue, GenericValue, PointerValue, IntValue};

#[derive(Debug, PartialEq, Eq)]
pub struct FloatType {
Expand Down Expand Up @@ -134,6 +135,14 @@ impl FloatType {
pub fn get_undef(&self) -> FloatValue {
FloatValue::new(self.float_type.get_undef())
}

pub fn create_generic_value(&self, value: f64) -> GenericValue {
let value = unsafe {
LLVMCreateGenericValueOfFloat(self.as_type_ref(), value)
};

GenericValue::new(value)
}
}

impl AsTypeRef for FloatType {
Expand Down
11 changes: 10 additions & 1 deletion src/types/int_type.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
use llvm_sys::core::{LLVMInt1Type, LLVMInt8Type, LLVMInt16Type, LLVMInt32Type, LLVMInt64Type, LLVMConstInt, LLVMConstNull, LLVMConstAllOnes, LLVMIntType, LLVMGetIntTypeWidth, LLVMConstIntOfString};
use llvm_sys::execution_engine::LLVMCreateGenericValueOfInt;
use llvm_sys::prelude::LLVMTypeRef;

use std::ffi::{CString, CStr};

use context::ContextRef;
use types::traits::AsTypeRef;
use types::{Type, ArrayType, BasicType, VectorType, PointerType, FunctionType};
use values::{IntValue, PointerValue};
use values::{GenericValue, IntValue, PointerValue};

#[derive(Debug, PartialEq, Eq)]
pub struct IntType {
Expand Down Expand Up @@ -163,6 +164,14 @@ impl IntType {
pub fn get_undef(&self) -> IntValue {
IntValue::new(self.int_type.get_undef())
}

pub fn create_generic_value(&self, value: u64, is_signed: bool) -> GenericValue {
let value = unsafe {
LLVMCreateGenericValueOfInt(self.as_type_ref(), value, is_signed as i32)
};

GenericValue::new(value)
}
}

impl AsTypeRef for IntType {
Expand Down
66 changes: 66 additions & 0 deletions src/values/generic_value.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
use libc::c_void;
use llvm_sys::execution_engine::{LLVMCreateGenericValueOfPointer, LLVMDisposeGenericValue, LLVMGenericValueIntWidth, LLVMGenericValueRef, LLVMGenericValueToInt, LLVMGenericValueToFloat, LLVMGenericValueToPointer};

use types::{AsTypeRef, FloatType};

// SubTypes: GenericValue<IntValue, FloatValue, or PointerValue>
pub struct GenericValue {
generic_value: LLVMGenericValueRef,
}

impl GenericValue {
pub(crate) fn new(generic_value: LLVMGenericValueRef) -> Self {
assert!(!generic_value.is_null());

GenericValue {
generic_value,
}
}

// SubType: GenericValue<IntValue> only
pub fn int_width(&self) -> u32 {
unsafe {
LLVMGenericValueIntWidth(self.generic_value)
}
}

// SubType: create_generic_value() -> GenericValue<PointerValue>
// REVIEW: How safe is this really?
pub unsafe fn create_generic_value_of_pointer<T>(value: &mut T) -> Self {
let value = unsafe {
LLVMCreateGenericValueOfPointer(value as *mut _ as *mut c_void)
};

GenericValue::new(value)
}

// SubType: impl only for GenericValue<IntValue>
pub fn into_int(self, is_signed: bool) -> u64 {
unsafe {
LLVMGenericValueToInt(self.generic_value, is_signed as i32)
}
}

// SubType: impl only for GenericValue<FloatValue>
pub fn into_float(self, float_type: &FloatType) -> f64 {
unsafe {
LLVMGenericValueToFloat(float_type.as_type_ref(), self.generic_value)
}
}

// SubType: impl only for GenericValue<PointerValue, T>
// REVIEW: How safe is this really?
pub unsafe fn into_pointer<T>(self) -> *mut T {
unsafe {
LLVMGenericValueToPointer(self.generic_value) as *mut T
}
}
}

impl Drop for GenericValue {
fn drop(&mut self) {
unsafe {
LLVMDisposeGenericValue(self.generic_value)
}
}
}
2 changes: 2 additions & 0 deletions src/values/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ mod array_value;
mod enums;
mod float_value;
mod fn_value;
mod generic_value;
mod instruction_value;
mod int_value;
mod metadata_value;
Expand All @@ -15,6 +16,7 @@ pub use values::array_value::ArrayValue;
pub use values::enums::{AnyValueEnum, AggregateValueEnum, BasicValueEnum, BasicMetadataValueEnum};
pub use values::float_value::FloatValue;
pub use values::fn_value::FunctionValue;
pub use values::generic_value::GenericValue;
pub use values::instruction_value::{InstructionValue, InstructionOpcode};
pub use values::int_value::IntValue;
pub use values::metadata_value::{MetadataValue, FIRST_CUSTOM_METADATA_KIND_ID};
Expand Down

0 comments on commit 65bd81a

Please sign in to comment.