diff --git a/src/basic_block.rs b/src/basic_block.rs index da41ee85c38..63f154a2009 100644 --- a/src/basic_block.rs +++ b/src/basic_block.rs @@ -506,7 +506,7 @@ impl<'ctx> BasicBlock<'ctx> { /// /// bb1.replace_all_uses_with(&bb2); /// - /// assert_eq!(branch_inst.get_operand(0).unwrap().right().unwrap(), bb2); + /// assert_eq!(branch_inst.get_operand(0).unwrap().into_basic_block().unwrap(), bb2); /// ``` pub fn replace_all_uses_with(self, other: &BasicBlock<'ctx>) { let value = unsafe { LLVMBasicBlockAsValue(self.basic_block) }; @@ -591,6 +591,12 @@ impl<'ctx> BasicBlock<'ctx> { } } +unsafe impl AsValueRef for BasicBlock<'_> { + fn as_value_ref(&self) -> LLVMValueRef { + self.basic_block as LLVMValueRef + } +} + impl fmt::Debug for BasicBlock<'_> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let llvm_value = unsafe { CStr::from_ptr(LLVMPrintValueToString(self.basic_block as LLVMValueRef)) }; diff --git a/src/debug_info.rs b/src/debug_info.rs index e33da152d24..6c5ebaedac2 100644 --- a/src/debug_info.rs +++ b/src/debug_info.rs @@ -171,7 +171,11 @@ pub struct DIScope<'ctx> { _marker: PhantomData<&'ctx Context>, } -impl DIScope<'_> { +impl<'ctx> DIScope<'ctx> { + pub fn as_metadata_value(&self, context: impl AsContextRef<'ctx>) -> MetadataValue<'ctx> { + unsafe { MetadataValue::new(LLVMMetadataAsValue(context.as_ctx_ref(), self.metadata_ref)) } + } + /// Acquires the underlying raw pointer belonging to this `DIScope` type. pub fn as_mut_ptr(&self) -> LLVMMetadataRef { self.metadata_ref @@ -1108,7 +1112,11 @@ impl<'ctx> AsDIScope<'ctx> for DIFile<'ctx> { } } -impl DIFile<'_> { +impl<'ctx> DIFile<'ctx> { + pub fn as_metadata_value(&self, context: impl AsContextRef<'ctx>) -> MetadataValue<'ctx> { + unsafe { MetadataValue::new(LLVMMetadataAsValue(context.as_ctx_ref(), self.metadata_ref)) } + } + /// Acquires the underlying raw pointer belonging to this `DIFile` type. pub fn as_mut_ptr(&self) -> LLVMMetadataRef { self.metadata_ref @@ -1128,6 +1136,10 @@ impl<'ctx> DICompileUnit<'ctx> { self.file } + pub fn as_metadata_value(&self, context: impl AsContextRef<'ctx>) -> MetadataValue<'ctx> { + unsafe { MetadataValue::new(LLVMMetadataAsValue(context.as_ctx_ref(), self.metadata_ref)) } + } + /// Acquires the underlying raw pointer belonging to this `DICompileUnit` type. pub fn as_mut_ptr(&self) -> LLVMMetadataRef { self.metadata_ref @@ -1150,7 +1162,11 @@ pub struct DINamespace<'ctx> { _marker: PhantomData<&'ctx Context>, } -impl DINamespace<'_> { +impl<'ctx> DINamespace<'ctx> { + pub fn as_metadata_value(&self, context: impl AsContextRef<'ctx>) -> MetadataValue<'ctx> { + unsafe { MetadataValue::new(LLVMMetadataAsValue(context.as_ctx_ref(), self.metadata_ref)) } + } + /// Acquires the underlying raw pointer belonging to this `DINamespace` type. pub fn as_mut_ptr(&self) -> LLVMMetadataRef { self.metadata_ref @@ -1182,7 +1198,11 @@ impl<'ctx> AsDIScope<'ctx> for DISubprogram<'ctx> { } } -impl DISubprogram<'_> { +impl<'ctx> DISubprogram<'ctx> { + pub fn as_metadata_value(&self, context: impl AsContextRef<'ctx>) -> MetadataValue<'ctx> { + unsafe { MetadataValue::new(LLVMMetadataAsValue(context.as_ctx_ref(), self.metadata_ref)) } + } + /// Acquires the underlying raw pointer belonging to this `DISubprogram` type. pub fn as_mut_ptr(&self) -> LLVMMetadataRef { self.metadata_ref @@ -1196,7 +1216,7 @@ pub struct DIType<'ctx> { _marker: PhantomData<&'ctx Context>, } -impl DIType<'_> { +impl<'ctx> DIType<'ctx> { pub fn get_size_in_bits(&self) -> u64 { unsafe { LLVMDITypeGetSizeInBits(self.metadata_ref) } } @@ -1209,6 +1229,10 @@ impl DIType<'_> { unsafe { LLVMDITypeGetOffsetInBits(self.metadata_ref) } } + pub fn as_metadata_value(&self, context: impl AsContextRef<'ctx>) -> MetadataValue<'ctx> { + unsafe { MetadataValue::new(LLVMMetadataAsValue(context.as_ctx_ref(), self.metadata_ref)) } + } + /// Acquires the underlying raw pointer belonging to this `DIType` type. pub fn as_mut_ptr(&self) -> LLVMMetadataRef { self.metadata_ref @@ -1240,7 +1264,11 @@ impl<'ctx> DIDerivedType<'ctx> { } } -impl DIDerivedType<'_> { +impl<'ctx> DIDerivedType<'ctx> { + pub fn as_metadata_value(&self, context: impl AsContextRef<'ctx>) -> MetadataValue<'ctx> { + unsafe { MetadataValue::new(LLVMMetadataAsValue(context.as_ctx_ref(), self.metadata_ref)) } + } + pub fn as_mut_ptr(&self) -> LLVMMetadataRef { self.metadata_ref } @@ -1270,6 +1298,10 @@ impl<'ctx> DIBasicType<'ctx> { } } + pub fn as_metadata_value(&self, context: impl AsContextRef<'ctx>) -> MetadataValue<'ctx> { + unsafe { MetadataValue::new(LLVMMetadataAsValue(context.as_ctx_ref(), self.metadata_ref)) } + } + /// Acquires the underlying raw pointer belonging to this `DIBasicType` type. pub fn as_mut_ptr(&self) -> LLVMMetadataRef { self.metadata_ref @@ -1299,6 +1331,10 @@ impl<'ctx> DICompositeType<'ctx> { } } + pub fn as_metadata_value(&self, context: impl AsContextRef<'ctx>) -> MetadataValue<'ctx> { + unsafe { MetadataValue::new(LLVMMetadataAsValue(context.as_ctx_ref(), self.metadata_ref)) } + } + /// Acquires the underlying raw pointer belonging to this `DICompositeType` type. pub fn as_mut_ptr(&self) -> LLVMMetadataRef { self.metadata_ref @@ -1337,11 +1373,15 @@ impl<'ctx> AsDIScope<'ctx> for DILexicalBlock<'ctx> { } } -impl DILexicalBlock<'_> { +impl<'ctx> DILexicalBlock<'ctx> { /// Acquires the underlying raw pointer belonging to this `DILexicalBlock` type. pub fn as_mut_ptr(&self) -> LLVMMetadataRef { self.metadata_ref } + + pub fn as_metadata_value(&self, context: impl AsContextRef<'ctx>) -> MetadataValue<'ctx> { + unsafe { MetadataValue::new(LLVMMetadataAsValue(context.as_ctx_ref(), self.metadata_ref)) } + } } /// A debug location within the source code. Contains the following information: @@ -1374,6 +1414,10 @@ impl<'ctx> DILocation<'ctx> { } } + pub fn as_metadata_value(&self, context: impl AsContextRef<'ctx>) -> MetadataValue<'ctx> { + unsafe { MetadataValue::new(LLVMMetadataAsValue(context.as_ctx_ref(), self.metadata_ref)) } + } + /// Acquires the underlying raw pointer belonging to this `DILocation` type. pub fn as_mut_ptr(&self) -> LLVMMetadataRef { self.metadata_ref @@ -1387,7 +1431,11 @@ pub struct DILocalVariable<'ctx> { _marker: PhantomData<&'ctx Context>, } -impl DILocalVariable<'_> { +impl<'ctx> DILocalVariable<'ctx> { + pub fn as_metadata_value(&self, context: impl AsContextRef<'ctx>) -> MetadataValue<'ctx> { + unsafe { MetadataValue::new(LLVMMetadataAsValue(context.as_ctx_ref(), self.metadata_ref)) } + } + /// Acquires the underlying raw pointer belonging to this `DILocalVariable` type. pub fn as_mut_ptr(&self) -> LLVMMetadataRef { self.metadata_ref @@ -1422,7 +1470,11 @@ pub struct DIExpression<'ctx> { _marker: PhantomData<&'ctx Context>, } -impl DIExpression<'_> { +impl<'ctx> DIExpression<'ctx> { + pub fn as_metadata_value(&self, context: impl AsContextRef<'ctx>) -> MetadataValue<'_> { + unsafe { MetadataValue::new(LLVMMetadataAsValue(context.as_ctx_ref(), self.metadata_ref)) } + } + /// Acquires the underlying raw pointer belonging to this `DIExpression` type. pub fn as_mut_ptr(&self) -> LLVMMetadataRef { self.metadata_ref diff --git a/src/module.rs b/src/module.rs index ed096ecfa8f..104d3ac1728 100644 --- a/src/module.rs +++ b/src/module.rs @@ -56,6 +56,8 @@ use crate::support::{to_c_str, LLVMString}; use crate::targets::TargetMachine; use crate::targets::{CodeModel, InitializationConfig, Target, TargetTriple}; use crate::types::{AsTypeRef, BasicType, FunctionType, StructType}; +#[llvm_versions(19..)] +use llvm_sys::core::{LLVMIsNewDbgInfoFormat, LLVMSetIsNewDbgInfoFormat}; use crate::values::BasicValue; use crate::values::{AsValueRef, FunctionValue, GlobalValue, MetadataValue}; @@ -1640,6 +1642,20 @@ impl<'ctx> Module<'ctx> { } } } + + /// https://llvm.org/docs/RemoveDIsDebugInfo.html + /// Set true to use new debug information format. + #[llvm_versions(19..)] + pub fn set_new_debug_format(&self, value: bool) { + unsafe { LLVMSetIsNewDbgInfoFormat(self.module.get(), value.into()) } + } + + /// https://llvm.org/docs/RemoveDIsDebugInfo.html + /// Returns true if this module is set to utilize the new debug format. + #[llvm_versions(19..)] + pub fn is_new_debug_format(&self) -> bool { + unsafe { LLVMIsNewDbgInfoFormat(self.module.get()) != 0 } + } } impl Clone for Module<'_> { diff --git a/src/values/basic_value_use.rs b/src/values/basic_value_use.rs index e847c9f004b..fcc15b87076 100644 --- a/src/values/basic_value_use.rs +++ b/src/values/basic_value_use.rs @@ -160,7 +160,7 @@ impl<'ctx> BasicValueUse<'ctx> { /// let free_instruction = builder.build_free(arg1).unwrap(); /// let return_instruction = builder.build_return(None).unwrap(); /// - /// let free_operand0 = free_instruction.get_operand(0).unwrap().left().unwrap(); + /// let free_operand0 = free_instruction.get_operand(0).unwrap().into_basic_value().unwrap(); /// let free_operand0_instruction = free_operand0.as_instruction_value().unwrap(); /// let bitcast_use_value = free_operand0_instruction /// .get_first_use() diff --git a/src/values/enums.rs b/src/values/enums.rs index 13bc82eb9a1..1b63d4f2a25 100644 --- a/src/values/enums.rs +++ b/src/values/enums.rs @@ -116,7 +116,9 @@ impl<'ctx> AnyValueEnum<'ctx> { } AnyValueEnum::InstructionValue(InstructionValue::new(value)) }, - LLVMTypeKind::LLVMMetadataTypeKind => panic!("Metadata values are not supported as AnyValue's."), + LLVMTypeKind::LLVMMetadataTypeKind => { + panic!("Metadata values are not supported as AnyValue's.") + }, _ => panic!("The given type is not supported."), } } @@ -263,7 +265,8 @@ impl<'ctx> BasicValueEnum<'ctx> { /// /// The ref must be valid and of supported enum type options ([LLVMTypeKind]). pub unsafe fn new(value: LLVMValueRef) -> Self { - match LLVMGetTypeKind(LLVMTypeOf(value)) { + let kind = LLVMGetTypeKind(LLVMTypeOf(value)); + match kind { LLVMTypeKind::LLVMFloatTypeKind | LLVMTypeKind::LLVMFP128TypeKind | LLVMTypeKind::LLVMDoubleTypeKind @@ -290,7 +293,7 @@ impl<'ctx> BasicValueEnum<'ctx> { LLVMTypeKind::LLVMScalableVectorTypeKind => { BasicValueEnum::ScalableVectorValue(ScalableVectorValue::new(value)) }, - _ => unreachable!("The given type is not a basic type."), + _ => unreachable!("The given type is not a basic type: {:?}", kind), } } diff --git a/src/values/instruction_value.rs b/src/values/instruction_value.rs index 043007c9c49..1ed45684062 100644 --- a/src/values/instruction_value.rs +++ b/src/values/instruction_value.rs @@ -1,33 +1,28 @@ -use either::{ - Either, - Either::{Left, Right}, -}; #[llvm_versions(14..)] use llvm_sys::core::LLVMGetGEPSourceElementType; use llvm_sys::core::{ LLVMGetAlignment, LLVMGetAllocatedType, LLVMGetFCmpPredicate, LLVMGetICmpPredicate, LLVMGetInstructionOpcode, LLVMGetInstructionParent, LLVMGetMetadata, LLVMGetNextInstruction, LLVMGetNumOperands, LLVMGetOperand, - LLVMGetOperandUse, LLVMGetPreviousInstruction, LLVMGetVolatile, LLVMHasMetadata, LLVMInstructionClone, - LLVMInstructionEraseFromParent, LLVMInstructionRemoveFromParent, LLVMIsAAllocaInst, LLVMIsABasicBlock, - LLVMIsAGetElementPtrInst, LLVMIsALoadInst, LLVMIsAStoreInst, LLVMIsATerminatorInst, LLVMIsConditional, - LLVMIsTailCall, LLVMSetAlignment, LLVMSetMetadata, LLVMSetOperand, LLVMSetVolatile, LLVMValueAsBasicBlock, + LLVMGetOperandUse, LLVMGetPreviousInstruction, LLVMGetTypeKind, LLVMGetVolatile, LLVMHasMetadata, + LLVMInstructionClone, LLVMInstructionEraseFromParent, LLVMInstructionRemoveFromParent, LLVMIsAAllocaInst, + LLVMIsABasicBlock, LLVMIsAGetElementPtrInst, LLVMIsALoadInst, LLVMIsAStoreInst, LLVMIsATerminatorInst, + LLVMIsConditional, LLVMIsTailCall, LLVMSetAlignment, LLVMSetMetadata, LLVMSetOperand, LLVMSetVolatile, LLVMTypeOf, + LLVMValueAsBasicBlock, }; use llvm_sys::core::{LLVMGetOrdering, LLVMSetOrdering}; #[llvm_versions(10..)] use llvm_sys::core::{LLVMIsAAtomicCmpXchgInst, LLVMIsAAtomicRMWInst}; use llvm_sys::prelude::LLVMValueRef; -use llvm_sys::LLVMOpcode; +use llvm_sys::{LLVMOpcode, LLVMTypeKind}; use std::{ffi::CStr, fmt, fmt::Display}; use crate::error::AlignmentError; -use crate::values::{BasicValue, BasicValueEnum, BasicValueUse, MetadataValue, Value}; +use crate::values::{AnyValue, BasicMetadataValueEnum, BasicValueEnum, BasicValueUse, MetadataValue, Value}; use crate::{basic_block::BasicBlock, types::AnyTypeEnum}; use crate::{types::BasicTypeEnum, values::traits::AsValueRef}; use crate::{AtomicOrdering, FloatPredicate, IntPredicate}; -use super::AnyValue; - /// Errors for atomic operations on load/store instructions. #[derive(Debug, thiserror::Error, PartialEq, Eq)] pub enum AtomicError { @@ -660,7 +655,7 @@ impl<'ctx> InstructionValue<'ctx> { /// 3) Function call has two: i8 pointer %1 argument, and the free function itself /// 4) Void return has zero: void is not a value and does not count as an operand /// even though the return instruction can take values. - pub fn get_operand(self, index: u32) -> Option, BasicBlock<'ctx>>> { + pub fn get_operand(self, index: u32) -> Option> { let num_operands = self.get_num_operands(); if index >= num_operands { @@ -675,7 +670,7 @@ impl<'ctx> InstructionValue<'ctx> { /// # Safety /// /// The index must be less than [InstructionValue::get_num_operands]. - pub unsafe fn get_operand_unchecked(self, index: u32) -> Option, BasicBlock<'ctx>>> { + pub unsafe fn get_operand_unchecked(self, index: u32) -> Option> { let operand = unsafe { LLVMGetOperand(self.as_value_ref(), index) }; if operand.is_null() { @@ -683,13 +678,18 @@ impl<'ctx> InstructionValue<'ctx> { } let is_basic_block = unsafe { !LLVMIsABasicBlock(operand).is_null() }; + let is_metadata = unsafe { LLVMGetTypeKind(LLVMTypeOf(operand)) == LLVMTypeKind::LLVMMetadataTypeKind }; if is_basic_block { let bb = unsafe { BasicBlock::new(LLVMValueAsBasicBlock(operand)) }; - Some(Right(bb.expect("BasicBlock should always be valid"))) + Some(OperandValue::BasicBlock(bb.expect("BasicBlock should always be valid"))) + } else if is_metadata { + Some(OperandValue::BasicMetadataValue(unsafe { + BasicMetadataValueEnum::new(operand) + })) } else { - Some(Left(unsafe { BasicValueEnum::new(operand) })) + Some(OperandValue::BasicValue(unsafe { BasicValueEnum::new(operand) })) } } @@ -734,16 +734,16 @@ impl<'ctx> InstructionValue<'ctx> { /// // This will produce invalid IR: /// free_instruction.set_operand(0, f32_val); /// - /// assert_eq!(free_instruction.get_operand(0).unwrap().left().unwrap(), f32_val); + /// assert_eq!(free_instruction.get_operand(0).unwrap().into_basic_value().unwrap(), f32_val); /// ``` - pub fn set_operand>(self, index: u32, val: BV) -> bool { + pub fn set_operand>>(self, index: u32, val: BV) -> bool { let num_operands = self.get_num_operands(); if index >= num_operands { return false; } - unsafe { LLVMSetOperand(self.as_value_ref(), index, val.as_value_ref()) } + unsafe { LLVMSetOperand(self.as_value_ref(), index, val.into().as_value_ref()) } true } @@ -930,6 +930,82 @@ impl Display for InstructionValue<'_> { } } +/// An operand within a given instruction can be a value, basic block, or metadata. +/// This is a wrapper type to handle those variations returned by `InstructionValue::get_operand` family. +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] +pub enum OperandValue<'ctx> { + BasicValue(BasicValueEnum<'ctx>), + BasicBlock(BasicBlock<'ctx>), + BasicMetadataValue(BasicMetadataValueEnum<'ctx>), +} +impl<'ctx> OperandValue<'ctx> { + pub fn into_basic_value(self) -> BasicValueEnum<'ctx> { + match self { + OperandValue::BasicValue(value) => value, + _ => panic!("Found {self:?} but expected the BasicValue variant"), + } + } + pub fn into_basic_block(self) -> BasicBlock<'ctx> { + match self { + OperandValue::BasicBlock(value) => value, + _ => panic!("Found {self:?} but expected the BasicBlock variant"), + } + } + + pub fn into_metadata_value(self) -> BasicMetadataValueEnum<'ctx> { + match self { + OperandValue::BasicMetadataValue(value) => value, + _ => panic!("Found {self:?} but expected the VectorValue variant"), + } + } +} + +unsafe impl AsValueRef for OperandValue<'_> { + fn as_value_ref(&self) -> LLVMValueRef { + match self { + OperandValue::BasicValue(value) => value.as_value_ref(), + OperandValue::BasicBlock(value) => value.as_value_ref(), + OperandValue::BasicMetadataValue(value) => value.as_value_ref(), + } + } +} +impl<'ctx, T: Into>> From for OperandValue<'ctx> { + fn from(value: T) -> Self { + Self::BasicValue(value.into()) + } +} +impl<'ctx> From> for OperandValue<'ctx> { + fn from(value: BasicBlock<'ctx>) -> Self { + Self::BasicBlock(value) + } +} +impl<'ctx> From> for OperandValue<'ctx> { + fn from(value: BasicMetadataValueEnum<'ctx>) -> Self { + Self::BasicMetadataValue(value) + } +} +impl<'ctx> TryFrom> for BasicValueEnum<'ctx> { + type Error = (); + + fn try_from(value: OperandValue<'ctx>) -> Result { + Ok(value.into_basic_value()) + } +} +impl<'ctx> TryFrom> for BasicBlock<'ctx> { + type Error = (); + + fn try_from(value: OperandValue<'ctx>) -> Result { + Ok(value.into_basic_block()) + } +} +impl<'ctx> TryFrom> for BasicMetadataValueEnum<'ctx> { + type Error = (); + + fn try_from(value: OperandValue<'ctx>) -> Result { + Ok(value.into_metadata_value()) + } +} + /// Iterate over all the operands of an instruction value. #[derive(Debug)] pub struct OperandIter<'ctx> { @@ -939,7 +1015,7 @@ pub struct OperandIter<'ctx> { } impl<'ctx> Iterator for OperandIter<'ctx> { - type Item = Option, BasicBlock<'ctx>>>; + type Item = Option>; fn next(&mut self) -> Option { if self.i < self.count { diff --git a/src/values/metadata_value.rs b/src/values/metadata_value.rs index 2db3d5d050e..10f9af0064f 100644 --- a/src/values/metadata_value.rs +++ b/src/values/metadata_value.rs @@ -117,7 +117,13 @@ impl<'ctx> MetadataValue<'ctx> { }; vec.iter() - .map(|val| unsafe { BasicMetadataValueEnum::new(*val) }) + .filter_map(|val| { + if !val.is_null() { + unsafe { Some(BasicMetadataValueEnum::new(*val)) } + } else { + None + } + }) .collect() } diff --git a/src/values/mod.rs b/src/values/mod.rs index 9edca9206a2..f65f1e608a8 100644 --- a/src/values/mod.rs +++ b/src/values/mod.rs @@ -59,7 +59,7 @@ pub use crate::values::global_value::GlobalValue; pub use crate::values::global_value::UnnamedAddress; pub use crate::values::instruction_value::{ - AtomicError, InstructionOpcode, InstructionValue, InstructionValueError, OperandIter, OperandUseIter, + AtomicError, InstructionOpcode, InstructionValue, InstructionValueError, OperandIter, OperandUseIter, OperandValue, }; pub use crate::values::int_value::IntValue; pub use crate::values::metadata_value::{MetadataValue, FIRST_CUSTOM_METADATA_KIND_ID}; diff --git a/tests/all/test_basic_block.rs b/tests/all/test_basic_block.rs index 39ad35fa859..71e2c884f52 100644 --- a/tests/all/test_basic_block.rs +++ b/tests/all/test_basic_block.rs @@ -1,3 +1,4 @@ +use inkwell::basic_block::BasicBlock; use inkwell::context::Context; use inkwell::values::InstructionOpcode; @@ -185,7 +186,7 @@ fn test_rauw() { bb1.replace_all_uses_with(&bb1); // no-op bb1.replace_all_uses_with(&bb2); - assert_eq!(branch_inst.get_operand(0).unwrap().right().unwrap(), bb2); + assert_eq!(BasicBlock::try_from(branch_inst.get_operand(0).unwrap()).unwrap(), bb2); } #[test] diff --git a/tests/all/test_instruction_values.rs b/tests/all/test_instruction_values.rs index 6eaed48b414..a93c0a84580 100644 --- a/tests/all/test_instruction_values.rs +++ b/tests/all/test_instruction_values.rs @@ -47,8 +47,8 @@ fn test_operands() { let store_operand0 = store_instruction.get_operand(0).unwrap(); let store_operand1 = store_instruction.get_operand(1).unwrap(); - assert_eq!(store_operand0.left().unwrap(), f32_val); // f32 const - assert_eq!(store_operand1.left().unwrap(), arg1); // f32* arg1 + assert_eq!(store_operand0.into_basic_value().unwrap(), f32_val); // f32 const + assert_eq!(store_operand1.into_basic_value().unwrap(), arg1); // f32* arg1 assert!(store_instruction.get_operand(2).is_none()); assert!(store_instruction.get_operand(3).is_none()); assert!(store_instruction.get_operand(4).is_none()); @@ -57,12 +57,12 @@ fn test_operands() { let store_operand0 = store_operands.next().unwrap().unwrap(); let store_operand1 = store_operands.next().unwrap().unwrap(); - assert_eq!(store_operand0.left().unwrap(), f32_val); // f32 const - assert_eq!(store_operand1.left().unwrap(), arg1); // f32* arg1 + assert_eq!(store_operand0.into_basic_value().unwrap(), f32_val); // f32 const + assert_eq!(store_operand1.into_basic_value().unwrap(), arg1); // f32* arg1 assert!(store_operands.next().is_none()); - let free_operand0 = free_instruction.get_operand(0).unwrap().left().unwrap(); - let free_operand1 = free_instruction.get_operand(1).unwrap().left().unwrap(); + let free_operand0 = free_instruction.get_operand(0).unwrap().into_basic_value().unwrap(); + let free_operand1 = free_instruction.get_operand(1).unwrap().into_basic_value().unwrap(); assert!(free_operand0.is_pointer_value()); // (implicitly casted) i8* arg1 assert!(free_operand1.is_pointer_value()); // Free function ptr @@ -72,7 +72,14 @@ fn test_operands() { let free_operand0_instruction = free_operand0.as_instruction_value().unwrap(); assert_eq!(free_operand0_instruction.get_opcode(), BitCast); - assert_eq!(free_operand0_instruction.get_operand(0).unwrap().left().unwrap(), arg1); + assert_eq!( + free_operand0_instruction + .get_operand(0) + .unwrap() + .into_basic_value() + .unwrap(), + arg1 + ); assert!(free_operand0_instruction.get_operand(1).is_none()); assert!(free_operand0_instruction.get_operand(2).is_none()); @@ -106,7 +113,7 @@ fn test_operands() { .get_used_value() .left() .unwrap(); - let free_call_param = free_instruction.get_operand(0).unwrap().left().unwrap(); + let free_call_param = free_instruction.get_operand(0).unwrap().into_basic_value().unwrap(); assert_eq!(bit_cast_use_value, free_call_param); @@ -195,7 +202,7 @@ fn test_basic_block_operand() { builder.position_at_end(basic_block); let branch_instruction = builder.build_unconditional_branch(basic_block2).unwrap(); - let bb_operand = branch_instruction.get_operand(0).unwrap().right().unwrap(); + let bb_operand = branch_instruction.get_operand(0).unwrap().into_basic_block().unwrap(); assert_eq!(bb_operand, basic_block2);