Skip to main content

llir/values/instruction/
instr.rs

1use llvm_sys::core::LLVMGetInstructionOpcode;
2use llvm_sys::prelude::LLVMValueRef;
3use llvm_sys::LLVMOpcode;
4
5use crate::values::*;
6use crate::*;
7
8/// [Instruction](https://llvm.org/docs/LangRef.html#instruction-reference)
9#[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}