@@ -98,6 +98,16 @@ pub struct InstructionValue {
98
98
}
99
99
100
100
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
+
101
111
pub ( crate ) fn new ( instruction_value : LLVMValueRef ) -> Self {
102
112
debug_assert ! ( !instruction_value. is_null( ) ) ;
103
113
@@ -185,45 +195,32 @@ impl InstructionValue {
185
195
// SubTypes: Only apply to memory access instructions
186
196
/// Returns whether or not a memory access instruction is volatile.
187
197
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." ) ;
197
202
}
203
+ Ok ( unsafe { LLVMGetVolatile ( self . as_value_ref ( ) ) } == 1 )
198
204
}
199
205
200
206
// SubTypes: Only apply to memory access instructions
201
207
/// Sets whether or not a memory access instruction is volatile.
202
208
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." ) ;
212
213
}
214
+ Ok ( unsafe { LLVMSetVolatile ( self . as_value_ref ( ) , volatile as i32 ) } )
213
215
}
214
216
215
217
// SubTypes: Only apply to memory access and alloca instructions
216
218
/// Returns alignment on a memory access instruction or alloca.
217
219
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." ) ;
226
222
}
223
+ Ok ( unsafe { LLVMGetAlignment ( self . as_value_ref ( ) ) } )
227
224
}
228
225
229
226
// SubTypes: Only apply to memory access and alloca instructions
@@ -232,54 +229,40 @@ impl InstructionValue {
232
229
if !alignment. is_power_of_two ( ) && alignment != 0 {
233
230
return Err ( "Alignment is not a power of 2!" ) ;
234
231
}
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." ) ;
243
234
}
235
+ Ok ( unsafe { LLVMSetAlignment ( self . as_value_ref ( ) , alignment) } )
244
236
}
245
237
246
238
// SubTypes: Only apply to memory access instructions
247
239
/// Returns atomic ordering on a memory access instruction.
248
240
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 ( ) )
255
245
}
256
246
257
247
// SubTypes: Only apply to memory access instructions
258
248
/// Sets atomic ordering on a memory access instruction.
259
249
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
-
264
250
// Although fence and atomicrmw both have an ordering, the LLVM C API
265
251
// does not support them. The cmpxchg instruction has two orderings and
266
252
// does not work with this API.
267
- if !is_load && !is_store {
253
+ if !self . is_a_load_inst ( ) && !self . is_a_store_inst ( ) {
268
254
return Err ( "Value is not a load or store instruction." ) ;
269
255
}
270
256
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
+ _ => { } ,
281
264
} ;
282
- Ok ( unsafe { LLVMSetOrdering ( value_ref , ordering. into ( ) ) } )
265
+ Ok ( unsafe { LLVMSetOrdering ( self . as_value_ref ( ) , ordering. into ( ) ) } )
283
266
}
284
267
285
268
/// Obtains the number of operands an `InstructionValue` has.
0 commit comments