Skip to content

Commit 65bd81a

Browse files
committed
Initial support for generic values
1 parent 5d8ea13 commit 65bd81a

File tree

7 files changed

+121
-3
lines changed

7 files changed

+121
-3
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ categories = ["development-tools::ffi"]
1313
[dependencies]
1414
either = "1.1.0"
1515
enum-methods = "0.0.6"
16+
libc = "*"
1617
llvm-sys = "37.0.5" # TODO: Configure based on feature toggle. GH#1
1718

1819
[badges]

src/builder.rs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use either::Either;
2-
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};
2+
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};
33
use llvm_sys::prelude::{LLVMBuilderRef, LLVMValueRef};
44
use llvm_sys::{LLVMOpcode, LLVMIntPredicate, LLVMTypeKind, LLVMRealPredicate, LLVMAtomicOrdering};
55

@@ -287,6 +287,36 @@ impl Builder {
287287
IntValue::new(value)
288288
}
289289

290+
pub fn build_int_s_extend_or_bit_cast(&self, int_value: &IntValue, int_type: &IntType, name: &str) -> IntValue {
291+
let c_string = CString::new(name).expect("Conversion to CString failed unexpectedly");
292+
293+
let value = unsafe {
294+
LLVMBuildSExtOrBitCast(self.builder, int_value.as_value_ref(), int_type.as_type_ref(), c_string.as_ptr())
295+
};
296+
297+
IntValue::new(value)
298+
}
299+
300+
pub fn build_int_z_extend_or_bit_cast(&self, int_value: &IntValue, int_type: &IntType, name: &str) -> IntValue {
301+
let c_string = CString::new(name).expect("Conversion to CString failed unexpectedly");
302+
303+
let value = unsafe {
304+
LLVMBuildZExtOrBitCast(self.builder, int_value.as_value_ref(), int_type.as_type_ref(), c_string.as_ptr())
305+
};
306+
307+
IntValue::new(value)
308+
}
309+
310+
pub fn build_int_truncate_or_bit_cast(&self, int_value: &IntValue, int_type: &IntType, name: &str) -> IntValue {
311+
let c_string = CString::new(name).expect("Conversion to CString failed unexpectedly");
312+
313+
let value = unsafe {
314+
LLVMBuildTruncOrBitCast(self.builder, int_value.as_value_ref(), int_type.as_type_ref(), c_string.as_ptr())
315+
};
316+
317+
IntValue::new(value)
318+
}
319+
290320
pub fn build_float_rem(&self, lhs: &FloatValue, rhs: &FloatValue, name: &str) -> FloatValue {
291321
let c_string = CString::new(name).expect("Conversion to CString failed unexpectedly");
292322

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
extern crate either;
22
#[macro_use]
33
extern crate enum_methods;
4+
extern crate libc;
45
extern crate llvm_sys;
56

67
pub mod basic_block;

src/types/float_type.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
use llvm_sys::core::{LLVMConstReal, LLVMConstNull, LLVMHalfType, LLVMFloatType, LLVMDoubleType, LLVMFP128Type, LLVMPPCFP128Type, LLVMConstRealOfString};
2+
use llvm_sys::execution_engine::LLVMCreateGenericValueOfFloat;
23
use llvm_sys::prelude::LLVMTypeRef;
34

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

67
use context::ContextRef;
78
use types::traits::AsTypeRef;
89
use types::{Type, PointerType, FunctionType, BasicType, ArrayType, VectorType};
9-
use values::{FloatValue, PointerValue, IntValue};
10+
use values::{FloatValue, GenericValue, PointerValue, IntValue};
1011

1112
#[derive(Debug, PartialEq, Eq)]
1213
pub struct FloatType {
@@ -134,6 +135,14 @@ impl FloatType {
134135
pub fn get_undef(&self) -> FloatValue {
135136
FloatValue::new(self.float_type.get_undef())
136137
}
138+
139+
pub fn create_generic_value(&self, value: f64) -> GenericValue {
140+
let value = unsafe {
141+
LLVMCreateGenericValueOfFloat(self.as_type_ref(), value)
142+
};
143+
144+
GenericValue::new(value)
145+
}
137146
}
138147

139148
impl AsTypeRef for FloatType {

src/types/int_type.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
use llvm_sys::core::{LLVMInt1Type, LLVMInt8Type, LLVMInt16Type, LLVMInt32Type, LLVMInt64Type, LLVMConstInt, LLVMConstNull, LLVMConstAllOnes, LLVMIntType, LLVMGetIntTypeWidth, LLVMConstIntOfString};
2+
use llvm_sys::execution_engine::LLVMCreateGenericValueOfInt;
23
use llvm_sys::prelude::LLVMTypeRef;
34

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

67
use context::ContextRef;
78
use types::traits::AsTypeRef;
89
use types::{Type, ArrayType, BasicType, VectorType, PointerType, FunctionType};
9-
use values::{IntValue, PointerValue};
10+
use values::{GenericValue, IntValue, PointerValue};
1011

1112
#[derive(Debug, PartialEq, Eq)]
1213
pub struct IntType {
@@ -163,6 +164,14 @@ impl IntType {
163164
pub fn get_undef(&self) -> IntValue {
164165
IntValue::new(self.int_type.get_undef())
165166
}
167+
168+
pub fn create_generic_value(&self, value: u64, is_signed: bool) -> GenericValue {
169+
let value = unsafe {
170+
LLVMCreateGenericValueOfInt(self.as_type_ref(), value, is_signed as i32)
171+
};
172+
173+
GenericValue::new(value)
174+
}
166175
}
167176

168177
impl AsTypeRef for IntType {

src/values/generic_value.rs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
use libc::c_void;
2+
use llvm_sys::execution_engine::{LLVMCreateGenericValueOfPointer, LLVMDisposeGenericValue, LLVMGenericValueIntWidth, LLVMGenericValueRef, LLVMGenericValueToInt, LLVMGenericValueToFloat, LLVMGenericValueToPointer};
3+
4+
use types::{AsTypeRef, FloatType};
5+
6+
// SubTypes: GenericValue<IntValue, FloatValue, or PointerValue>
7+
pub struct GenericValue {
8+
generic_value: LLVMGenericValueRef,
9+
}
10+
11+
impl GenericValue {
12+
pub(crate) fn new(generic_value: LLVMGenericValueRef) -> Self {
13+
assert!(!generic_value.is_null());
14+
15+
GenericValue {
16+
generic_value,
17+
}
18+
}
19+
20+
// SubType: GenericValue<IntValue> only
21+
pub fn int_width(&self) -> u32 {
22+
unsafe {
23+
LLVMGenericValueIntWidth(self.generic_value)
24+
}
25+
}
26+
27+
// SubType: create_generic_value() -> GenericValue<PointerValue>
28+
// REVIEW: How safe is this really?
29+
pub unsafe fn create_generic_value_of_pointer<T>(value: &mut T) -> Self {
30+
let value = unsafe {
31+
LLVMCreateGenericValueOfPointer(value as *mut _ as *mut c_void)
32+
};
33+
34+
GenericValue::new(value)
35+
}
36+
37+
// SubType: impl only for GenericValue<IntValue>
38+
pub fn into_int(self, is_signed: bool) -> u64 {
39+
unsafe {
40+
LLVMGenericValueToInt(self.generic_value, is_signed as i32)
41+
}
42+
}
43+
44+
// SubType: impl only for GenericValue<FloatValue>
45+
pub fn into_float(self, float_type: &FloatType) -> f64 {
46+
unsafe {
47+
LLVMGenericValueToFloat(float_type.as_type_ref(), self.generic_value)
48+
}
49+
}
50+
51+
// SubType: impl only for GenericValue<PointerValue, T>
52+
// REVIEW: How safe is this really?
53+
pub unsafe fn into_pointer<T>(self) -> *mut T {
54+
unsafe {
55+
LLVMGenericValueToPointer(self.generic_value) as *mut T
56+
}
57+
}
58+
}
59+
60+
impl Drop for GenericValue {
61+
fn drop(&mut self) {
62+
unsafe {
63+
LLVMDisposeGenericValue(self.generic_value)
64+
}
65+
}
66+
}

src/values/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ mod array_value;
22
mod enums;
33
mod float_value;
44
mod fn_value;
5+
mod generic_value;
56
mod instruction_value;
67
mod int_value;
78
mod metadata_value;
@@ -15,6 +16,7 @@ pub use values::array_value::ArrayValue;
1516
pub use values::enums::{AnyValueEnum, AggregateValueEnum, BasicValueEnum, BasicMetadataValueEnum};
1617
pub use values::float_value::FloatValue;
1718
pub use values::fn_value::FunctionValue;
19+
pub use values::generic_value::GenericValue;
1820
pub use values::instruction_value::{InstructionValue, InstructionOpcode};
1921
pub use values::int_value::IntValue;
2022
pub use values::metadata_value::{MetadataValue, FIRST_CUSTOM_METADATA_KIND_ID};

0 commit comments

Comments
 (0)