Skip to content

Commit 751d3c3

Browse files
committed
Implement m_callbr inst matcher
1 parent 102321c commit 751d3c3

File tree

3 files changed

+52
-1
lines changed

3 files changed

+52
-1
lines changed

docs/matchers/call.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@
22

33
| Function | Parameters | Return | Description |
44
| :---------: | :---------: | :---------: | :-------------------------------------------------------------------------: |
5-
| m_call | (n : Text?) | InstMatcher | Build Inst Matcher that match call instruction with optional name |
5+
| m_call | (n : Text?) | InstMatcher | Build Inst Matcher that match call instruction with optional name |
6+
| m_callbr | (n : Text?) | InstMatcher | Build Inst Matcher that match callbr instruction with optional name |
67
| m_intrinsic | (n : Text?) | InstMatcher | Build Inst Matcher that match intrinsic call instruction with optional name |

src/functions/matchers/call.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@ use gitql_core::values::Value;
88

99
use crate::ir::types::InstMatcherType;
1010
use crate::ir::values::InstMatcherValue;
11+
use crate::matchers::call::CallBrInstMatcher;
1112
use crate::matchers::call::CallInstMatcher;
1213
use crate::matchers::call::IntrinsicInstMatcher;
1314

1415
#[inline(always)]
1516
pub fn register_call_inst_matchers_functions(map: &mut HashMap<&'static str, StandardFunction>) {
1617
map.insert("m_call", match_call_inst);
18+
map.insert("m_callbr", match_callbr_inst);
1719
map.insert("m_intrinsic", match_intrinsic_inst);
1820
}
1921

@@ -25,6 +27,12 @@ pub fn register_call_inst_matchers_function_signatures(map: &mut HashMap<&'stati
2527
.add_parameter(Box::new(OptionType::new(Some(Box::new(TextType))))),
2628
);
2729

30+
map.insert(
31+
"m_callbr",
32+
Signature::with_return(Box::new(InstMatcherType))
33+
.add_parameter(Box::new(OptionType::new(Some(Box::new(TextType))))),
34+
);
35+
2836
map.insert(
2937
"m_intrinsic",
3038
Signature::with_return(Box::new(InstMatcherType))
@@ -43,6 +51,17 @@ fn match_call_inst(values: &[Box<dyn Value>]) -> Box<dyn Value> {
4351
Box::new(InstMatcherValue { matcher })
4452
}
4553

54+
fn match_callbr_inst(values: &[Box<dyn Value>]) -> Box<dyn Value> {
55+
let function_name = if values.is_empty() {
56+
None
57+
} else {
58+
values[0].as_text()
59+
};
60+
61+
let matcher = Box::new(CallBrInstMatcher::create_call(function_name));
62+
Box::new(InstMatcherValue { matcher })
63+
}
64+
4665
fn match_intrinsic_inst(values: &[Box<dyn Value>]) -> Box<dyn Value> {
4766
let intrinsic_name = if values.is_empty() {
4867
None

src/matchers/call.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,37 @@ impl Matcher<LLVMValueRef> for CallInstMatcher {
4040
}
4141
}
4242

43+
#[derive(Clone)]
44+
pub struct CallBrInstMatcher {
45+
pub name: Option<String>,
46+
}
47+
48+
impl CallBrInstMatcher {
49+
pub fn create_call(name: Option<String>) -> Self {
50+
CallBrInstMatcher { name }
51+
}
52+
}
53+
54+
impl Matcher<LLVMValueRef> for CallBrInstMatcher {
55+
#[allow(clippy::not_unsafe_ptr_arg_deref)]
56+
fn is_match(&self, instruction: &LLVMValueRef) -> bool {
57+
unsafe {
58+
if LLVMGetInstructionOpcode(*instruction) == LLVMOpcode::LLVMCallBr {
59+
if let Some(expected_name) = &self.name {
60+
let called_value = LLVMGetCalledValue(*instruction);
61+
let mut len: usize = 0;
62+
let name_ptr = LLVMGetValueName2(called_value, &mut len);
63+
let name_slice = std::slice::from_raw_parts(name_ptr as *const u8, len);
64+
let name = std::str::from_utf8_unchecked(name_slice).to_string();
65+
return name.eq(expected_name);
66+
}
67+
return true;
68+
}
69+
}
70+
false
71+
}
72+
}
73+
4374
#[derive(Clone)]
4475
pub struct IntrinsicInstMatcher {
4576
pub name: Option<String>,

0 commit comments

Comments
 (0)