Skip to content

Commit c2976a6

Browse files
committed
feat: Implement m_operands_number Matcher
1 parent aa18a22 commit c2976a6

File tree

3 files changed

+50
-17
lines changed

3 files changed

+50
-17
lines changed

docs/InstructionMatcher.md

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,21 @@ Instructions Matchers are functions that build a instruction matcher to match ag
44

55
### General Instructions Matchers functions
66

7-
| Function | Parameters | Return | Description |
8-
| :-------------: | :----------------------------------: | :---------: | :----------------------------------------------------------------------: |
9-
| m_inst | (i: Instruction, m: InstMatcher) | Bool | Check if instruction is matched with Matcher |
10-
| m_extract_value | (m : InstMatcher?, indices: ...Int?) | InstMatcher | Build Inst Matcher that match ExtractValue Instruction |
11-
| m_inst_type | (m : TypeMatcher?) | InstMatcher | Build Inst Matcher that match instruction returned type |
12-
| m_any_inst | () | InstMatcher | Build Inst Matcher that match any Instruction |
13-
| m_poison | () | InstMatcher | Build Inst Matcher that match poison value |
14-
| m_label | (n : Text?) | InstMatcher | Build Inst Matcher that match Label with optional name |
15-
| m_argument | (n : Text?, m : TypeMatcher?) | InstMatcher | Build Inst Matcher that match Argument value with optional name and type |
16-
| m_return | (m : InstMatcher?) | InstMatcher | Build Inst Matcher that match Return Instruction |
17-
| m_unreachable | () | InstMatcher | Build Inst Matcher that match unreachable Instruction |
18-
| m_unused | (m : InstMatcher?) | InstMatcher | Build Inst Matcher that match instruction that unused at all |
19-
| m_has_one_use | (m : InstMatcher?) | InstMatcher | Build Inst Matcher that match instruction that has exactly on use |
20-
| m_has_n_uses | (m : InstMatcher?, n: Int) | InstMatcher | Build Inst Matcher that match instruction that has n number of uses |
7+
| Function | Parameters | Return | Description |
8+
| :---------------: | :----------------------------------: | :---------: | :----------------------------------------------------------------------: |
9+
| m_inst | (i: Instruction, m: InstMatcher) | Bool | Check if instruction is matched with Matcher |
10+
| m_extract_value | (m : InstMatcher?, indices: ...Int?) | InstMatcher | Build Inst Matcher that match ExtractValue Instruction |
11+
| m_inst_type | (m : TypeMatcher?) | InstMatcher | Build Inst Matcher that match instruction returned type |
12+
| m_any_inst | () | InstMatcher | Build Inst Matcher that match any Instruction |
13+
| m_poison | () | InstMatcher | Build Inst Matcher that match poison value |
14+
| m_label | (n : Text?) | InstMatcher | Build Inst Matcher that match Label with optional name |
15+
| m_argument | (n : Text?, m : TypeMatcher?) | InstMatcher | Build Inst Matcher that match Argument value with optional name and type |
16+
| m_return | (m : InstMatcher?) | InstMatcher | Build Inst Matcher that match Return Instruction |
17+
| m_unreachable | () | InstMatcher | Build Inst Matcher that match unreachable Instruction |
18+
| m_unused | (m : InstMatcher?) | InstMatcher | Build Inst Matcher that match instruction that unused at all |
19+
| m_has_one_use | (m : InstMatcher?) | InstMatcher | Build Inst Matcher that match instruction that has exactly on use |
20+
| m_has_n_uses | (m : InstMatcher?, n: Int) | InstMatcher | Build Inst Matcher that match instruction that has n number of uses |
21+
| m_operands_number | (n: Int) | InstMatcher | Built Inst Matcher that match number of instruction operands |
2122

2223
---
2324

src/functions/matchers/other.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use crate::matchers::other::ArgumentMatcher;
2121
use crate::matchers::other::ExtractValueInstMatcher;
2222
use crate::matchers::other::InstTypeMatcher;
2323
use crate::matchers::other::LabelInstMatcher;
24+
use crate::matchers::other::OperandCountMatcher;
2425
use crate::matchers::other::PoisonValueMatcher;
2526
use crate::matchers::other::ReturnInstMatcher;
2627
use crate::matchers::other::UnreachableInstMatcher;
@@ -37,6 +38,7 @@ pub fn register_other_inst_matchers_functions(map: &mut HashMap<&'static str, St
3738
map.insert("m_argument", match_argument_inst);
3839
map.insert("m_return", match_return_inst);
3940
map.insert("m_unreachable", match_unreachable_inst);
41+
map.insert("m_operands_number", match_operands_number);
4042
}
4143

4244
#[inline(always)]
@@ -120,6 +122,11 @@ pub fn register_other_inst_matchers_function_signatures(
120122
return_type: Box::new(InstMatcherType),
121123
},
122124
);
125+
126+
map.insert(
127+
"m_operands_number",
128+
Signature::with_return(Box::new(InstMatcherType)).add_parameter(Box::new(IntType)),
129+
);
123130
}
124131

125132
fn match_inst(values: &[Box<dyn Value>]) -> Box<dyn Value> {
@@ -243,7 +250,12 @@ fn match_argument_inst(values: &[Box<dyn Value>]) -> Box<dyn Value> {
243250
}
244251

245252
fn match_unreachable_inst(_values: &[Box<dyn Value>]) -> Box<dyn Value> {
246-
Box::new(InstMatcherValue {
247-
matcher: Box::new(UnreachableInstMatcher),
248-
})
253+
let matcher = Box::new(UnreachableInstMatcher);
254+
Box::new(InstMatcherValue { matcher })
255+
}
256+
257+
fn match_operands_number(values: &[Box<dyn Value>]) -> Box<dyn Value> {
258+
let expected_number = values[0].as_int().unwrap() as i32;
259+
let matcher = Box::new(OperandCountMatcher::has_n_operands(expected_number));
260+
Box::new(InstMatcherValue { matcher })
249261
}

src/matchers/other.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::ffi::CStr;
33
use inkwell::llvm_sys::core::LLVMGetIndices;
44
use inkwell::llvm_sys::core::LLVMGetInstructionOpcode;
55
use inkwell::llvm_sys::core::LLVMGetNumIndices;
6+
use inkwell::llvm_sys::core::LLVMGetNumOperands;
67
use inkwell::llvm_sys::core::LLVMGetOperand;
78
use inkwell::llvm_sys::core::LLVMGetValueKind;
89
use inkwell::llvm_sys::core::LLVMGetValueName2;
@@ -171,3 +172,22 @@ impl InstMatcher for UnreachableInstMatcher {
171172
unsafe { LLVMGetInstructionOpcode(instruction) == LLVMOpcode::LLVMUnreachable }
172173
}
173174
}
175+
176+
/// Match the number of operands in LLVM instruction
177+
#[derive(Clone)]
178+
pub struct OperandCountMatcher {
179+
expected_number: i32,
180+
}
181+
182+
impl OperandCountMatcher {
183+
pub fn has_n_operands(expected_number: i32) -> Self {
184+
OperandCountMatcher { expected_number }
185+
}
186+
}
187+
188+
impl InstMatcher for OperandCountMatcher {
189+
#[allow(clippy::not_unsafe_ptr_arg_deref)]
190+
fn is_match(&self, instruction: LLVMValueRef) -> bool {
191+
unsafe { LLVMGetNumOperands(instruction) == self.expected_number }
192+
}
193+
}

0 commit comments

Comments
 (0)