|
1 | 1 | use either::{Either, Either::{Left, Right}};
|
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, LLVMGetMetadata, LLVMHasMetadata, LLVMSetMetadata}; |
| 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, LLVMGetMetadata, LLVMHasMetadata, LLVMSetMetadata, LLVMIsAAtomicRMWInst, LLVMIsAAtomicCmpXchgInst}; |
3 | 3 | #[llvm_versions(3.8..=latest)]
|
4 | 4 | use llvm_sys::core::{LLVMGetOrdering, LLVMSetOrdering};
|
5 | 5 | #[llvm_versions(3.9..=latest)]
|
@@ -113,6 +113,12 @@ impl<'ctx> InstructionValue<'ctx> {
|
113 | 113 | fn is_a_alloca_inst(self) -> bool {
|
114 | 114 | !unsafe { LLVMIsAAllocaInst(self.as_value_ref()) }.is_null()
|
115 | 115 | }
|
| 116 | + fn is_a_atomicrmw_inst(self) -> bool { |
| 117 | + !unsafe { LLVMIsAAtomicRMWInst(self.as_value_ref()) }.is_null() |
| 118 | + } |
| 119 | + fn is_a_cmpxchg_inst(self) -> bool { |
| 120 | + !unsafe { LLVMIsAAtomicCmpXchgInst(self.as_value_ref()) }.is_null() |
| 121 | + } |
116 | 122 |
|
117 | 123 | pub(crate) fn new(instruction_value: LLVMValueRef) -> Self {
|
118 | 124 | debug_assert!(!instruction_value.is_null());
|
@@ -203,25 +209,49 @@ impl<'ctx> InstructionValue<'ctx> {
|
203 | 209 |
|
204 | 210 | // SubTypes: Only apply to memory access instructions
|
205 | 211 | /// Returns whether or not a memory access instruction is volatile.
|
| 212 | + #[llvm_versions(3.6..=9.0)] |
206 | 213 | pub fn get_volatile(self) -> Result<bool, &'static str> {
|
207 | 214 | // Although cmpxchg and atomicrmw can have volatile, LLVM's C API
|
208 |
| - // does not export that functionality. |
| 215 | + // does not export that functionality until 10.0. |
209 | 216 | if !self.is_a_load_inst() && !self.is_a_store_inst() {
|
210 | 217 | return Err("Value is not a load or store.");
|
211 | 218 | }
|
212 | 219 | Ok(unsafe { LLVMGetVolatile(self.as_value_ref()) } == 1)
|
213 | 220 | }
|
214 | 221 |
|
| 222 | + // SubTypes: Only apply to memory access instructions |
| 223 | + /// Returns whether or not a memory access instruction is volatile. |
| 224 | + #[llvm_versions(10.0..=latest)] |
| 225 | + pub fn get_volatile(self) -> Result<bool, &'static str> { |
| 226 | + if !self.is_a_load_inst() && !self.is_a_store_inst() && |
| 227 | + !self.is_a_atomicrmw_inst() && !self.is_a_cmpxchg_inst() { |
| 228 | + return Err("Value is not a load, store, atomicrmw or cmpxchg."); |
| 229 | + } |
| 230 | + Ok(unsafe { LLVMGetVolatile(self.as_value_ref()) } == 1) |
| 231 | + } |
| 232 | + |
215 | 233 | // SubTypes: Only apply to memory access instructions
|
216 | 234 | /// Sets whether or not a memory access instruction is volatile.
|
| 235 | + #[llvm_versions(3.6..=9.0)] |
217 | 236 | pub fn set_volatile(self, volatile: bool) -> Result<(), &'static str> {
|
218 | 237 | // Although cmpxchg and atomicrmw can have volatile, LLVM's C API
|
219 |
| - // does not export that functionality. |
| 238 | + // does not export that functionality until 10.0. |
220 | 239 | if !self.is_a_load_inst() && !self.is_a_store_inst() {
|
221 | 240 | return Err("Value is not a load or store.");
|
222 | 241 | }
|
223 | 242 | Ok(unsafe { LLVMSetVolatile(self.as_value_ref(), volatile as i32) })
|
224 | 243 | }
|
| 244 | + |
| 245 | + // SubTypes: Only apply to memory access instructions |
| 246 | + /// Sets whether or not a memory access instruction is volatile. |
| 247 | + #[llvm_versions(10.0..=latest)] |
| 248 | + pub fn set_volatile(self, volatile: bool) -> Result<(), &'static str> { |
| 249 | + if !self.is_a_load_inst() && !self.is_a_store_inst() && |
| 250 | + !self.is_a_atomicrmw_inst() && !self.is_a_cmpxchg_inst() { |
| 251 | + return Err("Value is not a load, store, atomicrmw or cmpxchg."); |
| 252 | + } |
| 253 | + Ok(unsafe { LLVMSetVolatile(self.as_value_ref(), volatile as i32) }) |
| 254 | + } |
225 | 255 |
|
226 | 256 | // SubTypes: Only apply to memory access and alloca instructions
|
227 | 257 | /// Returns alignment on a memory access instruction or alloca.
|
|
0 commit comments