llir/values/instruction/
instr.rs1use llvm_sys::core::LLVMGetInstructionOpcode;
2use llvm_sys::prelude::LLVMValueRef;
3use llvm_sys::LLVMOpcode;
4
5use crate::values::*;
6use crate::*;
7
8#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
10pub enum Instruction<'ctx> {
11 Alloca(AllocaInstruction<'ctx>),
12 Binary(BinaryInstruction<'ctx>),
13 Branch(BranchInstruction<'ctx>),
14 Call(CallInstruction<'ctx>),
15 CallBr(CallBrInstruction<'ctx>),
16 ExtractValue(ExtractValueInstruction<'ctx>),
17 FCmp(FCmpInstruction<'ctx>),
18 GetElementPtr(GetElementPtrInstruction<'ctx>),
19 ICmp(ICmpInstruction<'ctx>),
20 IndirectBranch(IndirectBranchInstruction<'ctx>),
21 InsertValue(InsertValueInstruction<'ctx>),
22 Load(LoadInstruction<'ctx>),
23 Phi(PhiInstruction<'ctx>),
24 Return(ReturnInstruction<'ctx>),
25 Select(SelectInstruction<'ctx>),
26 Store(StoreInstruction<'ctx>),
27 Switch(SwitchInstruction<'ctx>),
28 Unary(UnaryInstruction<'ctx>),
29 Unreachable(UnreachableInstruction<'ctx>),
30 Other(GenericValue<'ctx>),
31}
32
33impl<'ctx> GetDebugMetadata<'ctx> for Instruction<'ctx> {}
34
35impl<'ctx> InstructionDebugLoc for Instruction<'ctx> {}
36
37impl<'ctx> InstructionTrait<'ctx> for Instruction<'ctx> {}
38
39impl<'ctx> ValueOpcode for Instruction<'ctx> {
40 fn opcode(&self) -> Opcode {
41 match self {
42 Self::Alloca(alc_instr) => alc_instr.opcode(),
43 Self::Binary(bin_instr) => bin_instr.opcode(),
44 Self::Branch(br_instr) => br_instr.opcode(),
45 Self::Call(call_instr) => call_instr.opcode(),
46 Self::CallBr(call_br_instr) => call_br_instr.opcode(),
47 Self::ExtractValue(extval_instr) => extval_instr.opcode(),
48 Self::FCmp(fcmp_instr) => fcmp_instr.opcode(),
49 Self::GetElementPtr(gep_instr) => gep_instr.opcode(),
50 Self::ICmp(icmp_instr) => icmp_instr.opcode(),
51 Self::IndirectBranch(indbr_instr) => indbr_instr.opcode(),
52 Self::InsertValue(insval_instr) => insval_instr.opcode(),
53 Self::Load(ld_instr) => ld_instr.opcode(),
54 Self::Phi(phi_instr) => phi_instr.opcode(),
55 Self::Return(ret_instr) => ret_instr.opcode(),
56 Self::Select(sel_instr) => sel_instr.opcode(),
57 Self::Store(st_instr) => st_instr.opcode(),
58 Self::Switch(switch_instr) => switch_instr.opcode(),
59 Self::Unary(una_instr) => una_instr.opcode(),
60 Self::Unreachable(unr_instr) => unr_instr.opcode(),
61 Self::Other(_) => Opcode::Unknown,
62 }
63 }
64}
65
66impl<'ctx> AsInstruction<'ctx> for Instruction<'ctx> {
67 fn as_instruction(&self) -> Self {
68 self.clone()
69 }
70}
71
72impl_as_operand_for_instr!(Instruction);
73
74impl<'ctx> FromLLVMValue for Instruction<'ctx> {
75 fn from_llvm(ptr: LLVMValueRef) -> Self {
76 use LLVMOpcode::*;
77 match unsafe { LLVMGetInstructionOpcode(ptr) } {
78 LLVMAlloca => Self::Alloca(AllocaInstruction::from_llvm(ptr)),
79 LLVMBr => Self::Branch(BranchInstruction::from_llvm(ptr)),
80 LLVMCall => Self::Call(CallInstruction::from_llvm(ptr)),
81 LLVMCallBr => Self::CallBr(CallBrInstruction::from_llvm(ptr)),
82 LLVMExtractValue => Self::ExtractValue(ExtractValueInstruction::from_llvm(ptr)),
83 LLVMFCmp => Self::FCmp(FCmpInstruction::from_llvm(ptr)),
84 LLVMGetElementPtr => Self::GetElementPtr(GetElementPtrInstruction::from_llvm(ptr)),
85 LLVMICmp => Self::ICmp(ICmpInstruction::from_llvm(ptr)),
86 LLVMIndirectBr => Self::IndirectBranch(IndirectBranchInstruction::from_llvm(ptr)),
87 LLVMLoad => Self::Load(LoadInstruction::from_llvm(ptr)),
88 LLVMPHI => Self::Phi(PhiInstruction::from_llvm(ptr)),
89 LLVMRet => Self::Return(ReturnInstruction::from_llvm(ptr)),
90 LLVMSelect => Self::Select(SelectInstruction::from_llvm(ptr)),
91 LLVMStore => Self::Store(StoreInstruction::from_llvm(ptr)),
92 LLVMSwitch => Self::Switch(SwitchInstruction::from_llvm(ptr)),
93 LLVMUnreachable => Self::Unreachable(UnreachableInstruction::from_llvm(ptr)),
94 op if BinaryOpcode::from_llvm(op).is_some() => Self::Binary(BinaryInstruction::from_llvm(ptr)),
95 op if UnaryOpcode::from_llvm(op).is_some() => Self::Unary(UnaryInstruction::from_llvm(ptr)),
96 _ => Self::Other(GenericValue::from_llvm(ptr)),
97 }
98 }
99}
100
101impl<'ctx> ValueRef for Instruction<'ctx> {
102 fn value_ref(&self) -> LLVMValueRef {
103 match self {
104 Self::Alloca(alc_instr) => alc_instr.value_ref(),
105 Self::Binary(bin_instr) => bin_instr.value_ref(),
106 Self::Branch(br_instr) => br_instr.value_ref(),
107 Self::Call(call_instr) => call_instr.value_ref(),
108 Self::CallBr(call_br_instr) => call_br_instr.value_ref(),
109 Self::ExtractValue(extval_instr) => extval_instr.value_ref(),
110 Self::FCmp(fcmp_instr) => fcmp_instr.value_ref(),
111 Self::GetElementPtr(gep_instr) => gep_instr.value_ref(),
112 Self::ICmp(icmp_instr) => icmp_instr.value_ref(),
113 Self::IndirectBranch(indbr_instr) => indbr_instr.value_ref(),
114 Self::InsertValue(insval_instr) => insval_instr.value_ref(),
115 Self::Load(ld_instr) => ld_instr.value_ref(),
116 Self::Phi(phi_instr) => phi_instr.value_ref(),
117 Self::Return(ret_instr) => ret_instr.value_ref(),
118 Self::Select(sel_instr) => sel_instr.value_ref(),
119 Self::Store(st_instr) => st_instr.value_ref(),
120 Self::Switch(switch_instr) => switch_instr.value_ref(),
121 Self::Unary(una_instr) => una_instr.value_ref(),
122 Self::Unreachable(unr_instr) => unr_instr.value_ref(),
123 Self::Other(otr_instr) => otr_instr.value_ref(),
124 }
125 }
126}