Skip to content

Commit 67aed4c

Browse files
authored
Merge pull request rust-lang#87 from cdisselkoen/icmp-fcmp-predicates
add bindings for LLVMGet{I,F}CmpPredicate
2 parents 5650064 + 4bdee1c commit 67aed4c

File tree

2 files changed

+57
-3
lines changed

2 files changed

+57
-3
lines changed

src/values/instruction_value.rs

+42-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use either::{Either, Either::{Left, Right}};
2-
use llvm_sys::core::{LLVMGetInstructionOpcode, LLVMIsTailCall, LLVMGetPreviousInstruction, LLVMGetNextInstruction, LLVMGetInstructionParent, LLVMInstructionEraseFromParent, LLVMInstructionClone, LLVMSetVolatile, LLVMGetVolatile, LLVMGetNumOperands, LLVMGetOperand, LLVMGetOperandUse, LLVMSetOperand, LLVMValueAsBasicBlock, LLVMIsABasicBlock};
2+
use llvm_sys::core::{LLVMGetInstructionOpcode, LLVMIsTailCall, LLVMGetPreviousInstruction, LLVMGetNextInstruction, LLVMGetInstructionParent, LLVMInstructionEraseFromParent, LLVMInstructionClone, LLVMSetVolatile, LLVMGetVolatile, LLVMGetNumOperands, LLVMGetOperand, LLVMGetOperandUse, LLVMSetOperand, LLVMValueAsBasicBlock, LLVMIsABasicBlock, LLVMGetICmpPredicate, LLVMGetFCmpPredicate};
33
#[llvm_versions(3.9 => latest)]
44
use llvm_sys::core::LLVMInstructionRemoveFromParent;
55
use llvm_sys::LLVMOpcode;
@@ -8,6 +8,7 @@ use llvm_sys::prelude::LLVMValueRef;
88
use crate::basic_block::BasicBlock;
99
use crate::values::traits::AsValueRef;
1010
use crate::values::{BasicValue, BasicValueEnum, BasicValueUse, Value};
11+
use crate::{IntPredicate, FloatPredicate};
1112

1213
// REVIEW: Split up into structs for SubTypes on InstructionValues?
1314
// REVIEW: This should maybe be split up into InstructionOpcode and ConstOpcode?
@@ -619,6 +620,46 @@ impl InstructionValue {
619620
pub fn get_first_use(&self) -> Option<BasicValueUse> {
620621
self.instruction_value.get_first_use()
621622
}
623+
624+
/// Gets the predicate of an `ICmp` `InstructionValue`.
625+
/// For instance, in the LLVM instruction
626+
/// `%3 = icmp slt i32 %0, %1`
627+
/// this gives the `slt`.
628+
///
629+
/// If the instruction is not an `ICmp`, this returns None.
630+
pub fn get_icmp_predicate(&self) -> Option<IntPredicate> {
631+
// REVIEW: this call to get_opcode() can be inefficient;
632+
// what happens if we don't perform this check, and just call
633+
// LLVMGetICmpPredicate() regardless?
634+
if self.get_opcode() == InstructionOpcode::ICmp {
635+
let pred = unsafe {
636+
LLVMGetICmpPredicate(self.as_value_ref())
637+
};
638+
Some(IntPredicate::new(pred))
639+
} else {
640+
None
641+
}
642+
}
643+
644+
/// Gets the predicate of an `FCmp` `InstructionValue`.
645+
/// For instance, in the LLVM instruction
646+
/// `%3 = fcmp olt float %0, %1`
647+
/// this gives the `olt`.
648+
///
649+
/// If the instruction is not an `FCmp`, this returns None.
650+
pub fn get_fcmp_predicate(&self) -> Option<FloatPredicate> {
651+
// REVIEW: this call to get_opcode() can be inefficient;
652+
// what happens if we don't perform this check, and just call
653+
// LLVMGetFCmpPredicate() regardless?
654+
if self.get_opcode() == InstructionOpcode::FCmp {
655+
let pred = unsafe {
656+
LLVMGetFCmpPredicate(self.as_value_ref())
657+
};
658+
Some(FloatPredicate::new(pred))
659+
} else {
660+
None
661+
}
662+
}
622663
}
623664

624665
impl Clone for InstructionValue {

tests/all/test_instruction_values.rs

+15-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
extern crate inkwell;
22

3-
use self::inkwell::AddressSpace;
3+
use self::inkwell::{AddressSpace, IntPredicate, FloatPredicate};
44
use self::inkwell::context::Context;
55
use self::inkwell::values::{BasicValue, InstructionOpcode::*};
66

@@ -201,28 +201,41 @@ fn test_instructions() {
201201
let i64_type = context.i64_type();
202202
let f32_type = context.f32_type();
203203
let f32_ptr_type = f32_type.ptr_type(AddressSpace::Generic);
204-
let fn_type = void_type.fn_type(&[f32_ptr_type.into()], false);
204+
let fn_type = void_type.fn_type(&[f32_ptr_type.into(), f32_type.into()], false);
205205

206206
let function = module.add_function("free_f32", fn_type, None);
207207
let basic_block = context.append_basic_block(&function, "entry");
208208

209209
builder.position_at_end(&basic_block);
210210

211211
let arg1 = function.get_first_param().unwrap().into_pointer_value();
212+
let arg2 = function.get_nth_param(1).unwrap().into_float_value();
212213

213214
assert!(arg1.get_first_use().is_none());
215+
assert!(arg2.get_first_use().is_none());
214216

215217
let f32_val = f32_type.const_float(::std::f64::consts::PI);
216218

217219
let store_instruction = builder.build_store(arg1, f32_val);
218220
let ptr_val = builder.build_ptr_to_int(arg1, i64_type, "ptr_val");
219221
let ptr = builder.build_int_to_ptr(ptr_val, f32_ptr_type, "ptr");
222+
let icmp = builder.build_int_compare(IntPredicate::EQ, ptr_val, ptr_val, "icmp");
223+
let f32_sum = builder.build_float_add(arg2, f32_val, "f32_sum");
224+
let fcmp = builder.build_float_compare(FloatPredicate::OEQ, f32_sum, arg2, "fcmp");
220225
let free_instruction = builder.build_free(arg1);
221226
let return_instruction = builder.build_return(None);
222227

223228
assert_eq!(store_instruction.get_opcode(), Store);
224229
assert_eq!(ptr_val.as_instruction().unwrap().get_opcode(), PtrToInt);
225230
assert_eq!(ptr.as_instruction().unwrap().get_opcode(), IntToPtr);
231+
assert_eq!(icmp.as_instruction().unwrap().get_opcode(), ICmp);
232+
assert_eq!(ptr.as_instruction().unwrap().get_icmp_predicate(), None);
233+
assert_eq!(icmp.as_instruction().unwrap().get_icmp_predicate().unwrap(), IntPredicate::EQ);
234+
assert_eq!(f32_sum.as_instruction().unwrap().get_opcode(), FAdd);
235+
assert_eq!(fcmp.as_instruction().unwrap().get_opcode(), FCmp);
236+
assert_eq!(f32_sum.as_instruction().unwrap().get_fcmp_predicate(), None);
237+
assert_eq!(icmp.as_instruction().unwrap().get_fcmp_predicate(), None);
238+
assert_eq!(fcmp.as_instruction().unwrap().get_fcmp_predicate().unwrap(), FloatPredicate::OEQ);
226239
assert_eq!(free_instruction.get_opcode(), Call);
227240
assert_eq!(return_instruction.get_opcode(), Return);
228241

0 commit comments

Comments
 (0)