Skip to content

Commit 76f2b92

Browse files
committed
Refactor, no functionality change.
Add new is_a_{load,store,alloca}_inst private methods in InstructionValue. Use them to simplify the implementation of methods throughout InstructionValue. Also tighten up some unsafe regions. Apply conditionals to the match arms to simplify the implementation of set_atomic_ordering.
1 parent 50c370b commit 76f2b92

File tree

1 file changed

+39
-56
lines changed

1 file changed

+39
-56
lines changed

Diff for: src/values/instruction_value.rs

+39-56
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,16 @@ pub struct InstructionValue {
9898
}
9999

100100
impl InstructionValue {
101+
fn is_a_load_inst(&self) -> bool {
102+
!unsafe { LLVMIsALoadInst(self.as_value_ref()) }.is_null()
103+
}
104+
fn is_a_store_inst(&self) -> bool {
105+
!unsafe { LLVMIsAStoreInst(self.as_value_ref()) }.is_null()
106+
}
107+
fn is_a_alloca_inst(&self) -> bool {
108+
!unsafe { LLVMIsAAllocaInst(self.as_value_ref()) }.is_null()
109+
}
110+
101111
pub(crate) fn new(instruction_value: LLVMValueRef) -> Self {
102112
debug_assert!(!instruction_value.is_null());
103113

@@ -185,45 +195,32 @@ impl InstructionValue {
185195
// SubTypes: Only apply to memory access instructions
186196
/// Returns whether or not a memory access instruction is volatile.
187197
pub fn get_volatile(&self) -> Result<bool, &'static str> {
188-
let value_ref = self.as_value_ref();
189-
unsafe {
190-
// Although cmpxchg and atomicrmw can have volatile, LLVM's C API
191-
// does not export that functionality.
192-
if LLVMIsALoadInst(value_ref).is_null() &&
193-
LLVMIsAStoreInst(value_ref).is_null() {
194-
return Err("Value is not a load or store.");
195-
}
196-
Ok(LLVMGetVolatile(value_ref) == 1)
198+
// Although cmpxchg and atomicrmw can have volatile, LLVM's C API
199+
// does not export that functionality.
200+
if !self.is_a_load_inst() && !self.is_a_store_inst() {
201+
return Err("Value is not a load or store.");
197202
}
203+
Ok(unsafe { LLVMGetVolatile(self.as_value_ref()) } == 1)
198204
}
199205

200206
// SubTypes: Only apply to memory access instructions
201207
/// Sets whether or not a memory access instruction is volatile.
202208
pub fn set_volatile(&self, volatile: bool) -> Result<(), &'static str> {
203-
let value_ref = self.as_value_ref();
204-
unsafe {
205-
// Although cmpxchg and atomicrmw can have volatile, LLVM's C API
206-
// does not export that functionality.
207-
if LLVMIsALoadInst(value_ref).is_null() &&
208-
LLVMIsAStoreInst(value_ref).is_null() {
209-
return Err("Value is not a load or store.");
210-
}
211-
Ok(LLVMSetVolatile(value_ref, volatile as i32))
209+
// Although cmpxchg and atomicrmw can have volatile, LLVM's C API
210+
// does not export that functionality.
211+
if !self.is_a_load_inst() && !self.is_a_store_inst() {
212+
return Err("Value is not a load or store.");
212213
}
214+
Ok(unsafe { LLVMSetVolatile(self.as_value_ref(), volatile as i32) })
213215
}
214216

215217
// SubTypes: Only apply to memory access and alloca instructions
216218
/// Returns alignment on a memory access instruction or alloca.
217219
pub fn get_alignment(&self) -> Result<u32, &'static str> {
218-
let value_ref = self.as_value_ref();
219-
unsafe {
220-
if LLVMIsAAllocaInst(value_ref).is_null() &&
221-
LLVMIsALoadInst(value_ref).is_null() &&
222-
LLVMIsAStoreInst(value_ref).is_null() {
223-
return Err("Value is not an alloca, load or store.");
224-
}
225-
Ok(LLVMGetAlignment(value_ref))
220+
if !self.is_a_alloca_inst() && !self.is_a_load_inst() && !self.is_a_store_inst() {
221+
return Err("Value is not an alloca, load or store.");
226222
}
223+
Ok(unsafe { LLVMGetAlignment(self.as_value_ref()) })
227224
}
228225

229226
// SubTypes: Only apply to memory access and alloca instructions
@@ -232,54 +229,40 @@ impl InstructionValue {
232229
if !alignment.is_power_of_two() && alignment != 0 {
233230
return Err("Alignment is not a power of 2!");
234231
}
235-
let value_ref = self.as_value_ref();
236-
unsafe {
237-
if LLVMIsAAllocaInst(value_ref).is_null() &&
238-
LLVMIsALoadInst(value_ref).is_null() &&
239-
LLVMIsAStoreInst(value_ref).is_null() {
240-
return Err("Value is not an alloca, load or store.");
241-
}
242-
Ok(LLVMSetAlignment(value_ref, alignment))
232+
if !self.is_a_alloca_inst() && !self.is_a_load_inst() && !self.is_a_store_inst() {
233+
return Err("Value is not an alloca, load or store.");
243234
}
235+
Ok(unsafe { LLVMSetAlignment(self.as_value_ref(), alignment) })
244236
}
245237

246238
// SubTypes: Only apply to memory access instructions
247239
/// Returns atomic ordering on a memory access instruction.
248240
pub fn get_atomic_ordering(&self) -> Result<AtomicOrdering, &'static str> {
249-
let value_ref = self.as_value_ref();
250-
if unsafe { LLVMIsALoadInst(value_ref) }.is_null() &&
251-
unsafe { LLVMIsAStoreInst(value_ref) }.is_null() {
252-
return Err("Value is not a load or store.");
253-
}
254-
Ok(unsafe { LLVMGetOrdering(value_ref) }.into())
241+
if !self.is_a_load_inst() && !self.is_a_store_inst() {
242+
return Err("Value is not a load or store.");
243+
}
244+
Ok(unsafe { LLVMGetOrdering(self.as_value_ref()) }.into())
255245
}
256246

257247
// SubTypes: Only apply to memory access instructions
258248
/// Sets atomic ordering on a memory access instruction.
259249
pub fn set_atomic_ordering(&self, ordering: AtomicOrdering) -> Result<(), &'static str> {
260-
let value_ref = self.as_value_ref();
261-
let is_load = !unsafe { LLVMIsALoadInst(value_ref) }.is_null();
262-
let is_store = !unsafe { LLVMIsAStoreInst(value_ref) }.is_null();
263-
264250
// Although fence and atomicrmw both have an ordering, the LLVM C API
265251
// does not support them. The cmpxchg instruction has two orderings and
266252
// does not work with this API.
267-
if !is_load && !is_store {
253+
if !self.is_a_load_inst() && !self.is_a_store_inst() {
268254
return Err("Value is not a load or store instruction.");
269255
}
270256
match ordering {
271-
AtomicOrdering::Release => {
272-
if is_load { return Err("The release ordering is not valid on load instructions.") }
273-
}
274-
AtomicOrdering::AcquireRelease => {
275-
return Err("The acq_rel ordering is not valid on load or store instructions.")
276-
}
277-
AtomicOrdering::Acquire => {
278-
if is_store { return Err("The acquire ordering is not valid on store instructions.") }
279-
}
280-
_ => { }
257+
AtomicOrdering::Release if self.is_a_load_inst() =>
258+
return Err("The release ordering is not valid on load instructions."),
259+
AtomicOrdering::AcquireRelease =>
260+
return Err("The acq_rel ordering is not valid on load or store instructions."),
261+
AtomicOrdering::Acquire if self.is_a_store_inst() =>
262+
return Err("The acquire ordering is not valid on store instructions."),
263+
_ => { },
281264
};
282-
Ok(unsafe { LLVMSetOrdering(value_ref, ordering.into()) })
265+
Ok(unsafe { LLVMSetOrdering(self.as_value_ref(), ordering.into()) })
283266
}
284267

285268
/// Obtains the number of operands an `InstructionValue` has.

0 commit comments

Comments
 (0)