Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add set_alignment and get_alignment on InstructionValue. #114

Merged
merged 4 commits into from
Sep 3, 2019
Merged
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion src/values/instruction_value.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use either::{Either, Either::{Left, Right}};
use llvm_sys::core::{LLVMGetInstructionOpcode, LLVMIsTailCall, LLVMGetPreviousInstruction, LLVMGetNextInstruction, LLVMGetInstructionParent, LLVMInstructionEraseFromParent, LLVMInstructionClone, LLVMSetVolatile, LLVMGetVolatile, LLVMGetNumOperands, LLVMGetOperand, LLVMGetOperandUse, LLVMSetOperand, LLVMValueAsBasicBlock, LLVMIsABasicBlock, LLVMGetICmpPredicate, LLVMGetFCmpPredicate};
use llvm_sys::core::{LLVMGetAlignment, LLVMSetAlignment, LLVMGetInstructionOpcode, LLVMIsTailCall, LLVMGetPreviousInstruction, LLVMGetNextInstruction, LLVMGetInstructionParent, LLVMInstructionEraseFromParent, LLVMInstructionClone, LLVMSetVolatile, LLVMGetVolatile, LLVMGetNumOperands, LLVMGetOperand, LLVMGetOperandUse, LLVMSetOperand, LLVMValueAsBasicBlock, LLVMIsABasicBlock, LLVMGetICmpPredicate, LLVMGetFCmpPredicate};
#[llvm_versions(3.9..=latest)]
use llvm_sys::core::LLVMInstructionRemoveFromParent;
use llvm_sys::LLVMOpcode;
@@ -198,6 +198,25 @@ impl InstructionValue {
}
}

// SubTypes: Only apply to memory access and alloca instructions
/// Returns alignment on a memory access instruction or alloca.
pub fn get_alignment(&self) -> u32 {
unsafe {
LLVMGetAlignment(self.as_value_ref())
}
}

// SubTypes: Only apply to memory access and alloca instructions
/// Sets alignment on a memory access instruction or alloca.
pub fn set_alignment(&self, alignment: u32) -> Result<(), &'static str> {
nlewycky marked this conversation as resolved.
Show resolved Hide resolved
if !alignment.is_power_of_two() && alignment != 0 {
return Err("Alignment is not a power of 2!");
}
unsafe {
Ok(LLVMSetAlignment(self.as_value_ref(), alignment))
}
}

/// Obtains the number of operands an `InstructionValue` has.
/// An operand is a `BasicValue` used in an IR instruction.
///
53 changes: 53 additions & 0 deletions tests/all/test_instruction_values.rs
Original file line number Diff line number Diff line change
@@ -250,3 +250,56 @@ fn test_instructions() {

assert_eq!(instruction_clone, instruction_clone_copy);
}

#[test]
fn test_mem_instructions() {
let context = Context::create();
let module = context.create_module("testing");
let builder = context.create_builder();

let void_type = context.void_type();
let f32_type = context.f32_type();
let f32_ptr_type = f32_type.ptr_type(AddressSpace::Generic);
let fn_type = void_type.fn_type(&[f32_ptr_type.into(), f32_type.into()], false);

let function = module.add_function("mem_inst", fn_type, None);
let basic_block = context.append_basic_block(&function, "entry");

builder.position_at_end(&basic_block);

let arg1 = function.get_first_param().unwrap().into_pointer_value();
let arg2 = function.get_nth_param(1).unwrap().into_float_value();

assert!(arg1.get_first_use().is_none());
assert!(arg2.get_first_use().is_none());

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

let store_instruction = builder.build_store(arg1, f32_val);
let load_instruction = builder.build_load(arg1, "").as_instruction_value().unwrap();

assert_eq!(store_instruction.get_volatile(), false);
assert_eq!(load_instruction.get_volatile(), false);
store_instruction.set_volatile(true);
load_instruction.set_volatile(true);
assert_eq!(store_instruction.get_volatile(), true);
assert_eq!(load_instruction.get_volatile(), true);
store_instruction.set_volatile(false);
load_instruction.set_volatile(false);
assert_eq!(store_instruction.get_volatile(), false);
assert_eq!(load_instruction.get_volatile(), false);

assert_eq!(store_instruction.get_alignment(), 0);
assert_eq!(load_instruction.get_alignment(), 0);
assert!(store_instruction.set_alignment(16).is_ok());
assert!(load_instruction.set_alignment(16).is_ok());
assert_eq!(store_instruction.get_alignment(), 16);
assert_eq!(load_instruction.get_alignment(), 16);
assert!(store_instruction.set_alignment(0).is_ok());
assert!(load_instruction.set_alignment(0).is_ok());
assert_eq!(store_instruction.get_alignment(), 0);
assert_eq!(load_instruction.get_alignment(), 0);

assert!(store_instruction.set_alignment(14).is_err());
assert_eq!(store_instruction.get_alignment(), 0);
}