Skip to content

Commit da3760a

Browse files
authored
Merge pull request rust-lang#114 from wasmerio/mem-alignment
Add set_alignment and get_alignment on InstructionValue.
2 parents 3630b97 + 3464374 commit da3760a

File tree

2 files changed

+90
-1
lines changed

2 files changed

+90
-1
lines changed

src/values/instruction_value.rs

+32-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, LLVMGetICmpPredicate, LLVMGetFCmpPredicate};
2+
use llvm_sys::core::{LLVMGetAlignment, LLVMSetAlignment, LLVMGetInstructionOpcode, LLVMIsTailCall, LLVMGetPreviousInstruction, LLVMGetNextInstruction, LLVMGetInstructionParent, LLVMInstructionEraseFromParent, LLVMInstructionClone, LLVMSetVolatile, LLVMGetVolatile, LLVMGetNumOperands, LLVMGetOperand, LLVMGetOperandUse, LLVMSetOperand, LLVMValueAsBasicBlock, LLVMIsABasicBlock, LLVMGetICmpPredicate, LLVMGetFCmpPredicate, LLVMIsAAllocaInst, LLVMIsALoadInst, LLVMIsAStoreInst};
33
#[llvm_versions(3.9..=latest)]
44
use llvm_sys::core::LLVMInstructionRemoveFromParent;
55
use llvm_sys::LLVMOpcode;
@@ -198,6 +198,37 @@ impl InstructionValue {
198198
}
199199
}
200200

201+
// SubTypes: Only apply to memory access and alloca instructions
202+
/// Returns alignment on a memory access instruction or alloca.
203+
pub fn get_alignment(&self) -> Result<u32, &'static str> {
204+
let value_ref = self.as_value_ref();
205+
unsafe {
206+
if LLVMIsAAllocaInst(value_ref).is_null() &&
207+
LLVMIsALoadInst(value_ref).is_null() &&
208+
LLVMIsAStoreInst(value_ref).is_null() {
209+
return Err("Value is not an alloca, load or store.");
210+
}
211+
Ok(LLVMGetAlignment(value_ref))
212+
}
213+
}
214+
215+
// SubTypes: Only apply to memory access and alloca instructions
216+
/// Sets alignment on a memory access instruction or alloca.
217+
pub fn set_alignment(&self, alignment: u32) -> Result<(), &'static str> {
218+
if !alignment.is_power_of_two() && alignment != 0 {
219+
return Err("Alignment is not a power of 2!");
220+
}
221+
let value_ref = self.as_value_ref();
222+
unsafe {
223+
if LLVMIsAAllocaInst(value_ref).is_null() &&
224+
LLVMIsALoadInst(value_ref).is_null() &&
225+
LLVMIsAStoreInst(value_ref).is_null() {
226+
return Err("Value is not an alloca, load or store.");
227+
}
228+
Ok(LLVMSetAlignment(value_ref, alignment))
229+
}
230+
}
231+
201232
/// Obtains the number of operands an `InstructionValue` has.
202233
/// An operand is a `BasicValue` used in an IR instruction.
203234
///

tests/all/test_instruction_values.rs

+58
Original file line numberDiff line numberDiff line change
@@ -250,3 +250,61 @@ fn test_instructions() {
250250

251251
assert_eq!(instruction_clone, instruction_clone_copy);
252252
}
253+
254+
#[test]
255+
fn test_mem_instructions() {
256+
let context = Context::create();
257+
let module = context.create_module("testing");
258+
let builder = context.create_builder();
259+
260+
let void_type = context.void_type();
261+
let f32_type = context.f32_type();
262+
let f32_ptr_type = f32_type.ptr_type(AddressSpace::Generic);
263+
let fn_type = void_type.fn_type(&[f32_ptr_type.into(), f32_type.into()], false);
264+
265+
let function = module.add_function("mem_inst", fn_type, None);
266+
let basic_block = context.append_basic_block(&function, "entry");
267+
268+
builder.position_at_end(&basic_block);
269+
270+
let arg1 = function.get_first_param().unwrap().into_pointer_value();
271+
let arg2 = function.get_nth_param(1).unwrap().into_float_value();
272+
273+
assert!(arg1.get_first_use().is_none());
274+
assert!(arg2.get_first_use().is_none());
275+
276+
let f32_val = f32_type.const_float(::std::f64::consts::PI);
277+
278+
let store_instruction = builder.build_store(arg1, f32_val);
279+
let load = builder.build_load(arg1, "");
280+
let load_instruction = load.as_instruction_value().unwrap();
281+
282+
assert_eq!(store_instruction.get_volatile(), false);
283+
assert_eq!(load_instruction.get_volatile(), false);
284+
store_instruction.set_volatile(true);
285+
load_instruction.set_volatile(true);
286+
assert_eq!(store_instruction.get_volatile(), true);
287+
assert_eq!(load_instruction.get_volatile(), true);
288+
store_instruction.set_volatile(false);
289+
load_instruction.set_volatile(false);
290+
assert_eq!(store_instruction.get_volatile(), false);
291+
assert_eq!(load_instruction.get_volatile(), false);
292+
293+
assert_eq!(store_instruction.get_alignment().unwrap(), 0);
294+
assert_eq!(load_instruction.get_alignment().unwrap(), 0);
295+
assert!(store_instruction.set_alignment(16).is_ok());
296+
assert!(load_instruction.set_alignment(16).is_ok());
297+
assert_eq!(store_instruction.get_alignment().unwrap(), 16);
298+
assert_eq!(load_instruction.get_alignment().unwrap(), 16);
299+
assert!(store_instruction.set_alignment(0).is_ok());
300+
assert!(load_instruction.set_alignment(0).is_ok());
301+
assert_eq!(store_instruction.get_alignment().unwrap(), 0);
302+
assert_eq!(load_instruction.get_alignment().unwrap(), 0);
303+
304+
assert!(store_instruction.set_alignment(14).is_err());
305+
assert_eq!(store_instruction.get_alignment().unwrap(), 0);
306+
307+
let fadd_instruction = builder.build_float_add(load.into_float_value(), f32_val, "").as_instruction_value().unwrap();
308+
assert!(fadd_instruction.get_alignment().is_err());
309+
assert!(fadd_instruction.set_alignment(16).is_err());
310+
}

0 commit comments

Comments
 (0)