Skip to content

Commit

Permalink
Allow Cast matchers to match the value
Browse files Browse the repository at this point in the history
  • Loading branch information
AmrDeveloper committed Feb 9, 2025
1 parent 70ee461 commit 37dca87
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 58 deletions.
24 changes: 12 additions & 12 deletions docs/matchers/cast.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
## Cast Instructions Matchers

| Function | Parameters | Return | Description |
| :---------------: | :--------: | :---------: | :--------------------------------------------------------: |
| m_trunc | | InstMatcher | Build Inst Matcher that matchers trunc instruction |
| m_fp_to_ui | | InstMatcher | Build Inst Matcher that matchers fp to ui instruction |
| m_fp_to_si | | InstMatcher | Build Inst Matcher that matchers fp to si instruction |
| m_fp_trunc | | InstMatcher | Build Inst Matcher that matchers trunc instruction |
| m_int_to_ptr | | InstMatcher | Build Inst Matcher that matchers IntToPtr instruction |
| m_ptr_to_int | | InstMatcher | Build Inst Matcher that matchers PtrToInt instruction |
| m_zext | | InstMatcher | Build Inst Matcher that matchers zext instruction |
| m_sext | | InstMatcher | Build Inst Matcher that matchers sext instruction |
| m_bit_cast | | InstMatcher | Build Inst Matcher that matchers Bit cast instruction |
| m_addr_space_cast | | InstMatcher | Build Inst Matcher that matchers AddrSpaceCast instruction |
| Function | Parameters | Return | Description |
| :---------------: | :-------------------: | :---------: | :--------------------------------------------------------: |
| m_trunc | (value: InstMatcher?) | InstMatcher | Build Inst Matcher that matchers trunc instruction |
| m_fp_to_ui | (value: InstMatcher?) | InstMatcher | Build Inst Matcher that matchers fp to ui instruction |
| m_fp_to_si | (value: InstMatcher?) | InstMatcher | Build Inst Matcher that matchers fp to si instruction |
| m_fp_trunc | (value: InstMatcher?) | InstMatcher | Build Inst Matcher that matchers trunc instruction |
| m_int_to_ptr | (value: InstMatcher?) | InstMatcher | Build Inst Matcher that matchers IntToPtr instruction |
| m_ptr_to_int | (value: InstMatcher?) | InstMatcher | Build Inst Matcher that matchers PtrToInt instruction |
| m_zext | (value: InstMatcher?) | InstMatcher | Build Inst Matcher that matchers zext instruction |
| m_sext | (value: InstMatcher?) | InstMatcher | Build Inst Matcher that matchers sext instruction |
| m_bit_cast | (value: InstMatcher?) | InstMatcher | Build Inst Matcher that matchers Bit cast instruction |
| m_addr_space_cast | (value: InstMatcher?) | InstMatcher | Build Inst Matcher that matchers AddrSpaceCast instruction |
51 changes: 31 additions & 20 deletions src/functions/matchers/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use gitql_core::signature::Signature;
use gitql_core::signature::StandardFunction;
use gitql_core::values::base::Value;

use crate::functions::single_optional_matcher_value;
use crate::ir::types::InstMatcherType;
use crate::ir::values::InstMatcherValue;
use crate::matchers::cast::CastInstMatcher;
Expand Down Expand Up @@ -40,52 +41,62 @@ fn cast_function_signature() -> Signature {
Signature::with_return(Box::new(InstMatcherType))
}

fn match_trunc(_values: &[Box<dyn Value>]) -> Box<dyn Value> {
let matcher = Box::new(CastInstMatcher::create_trunc());
fn match_trunc(values: &[Box<dyn Value>]) -> Box<dyn Value> {
let value_matcher = single_optional_matcher_value(values);
let matcher = Box::new(CastInstMatcher::create_trunc(value_matcher));
Box::new(InstMatcherValue { matcher })
}

fn match_fp_to_ui(_values: &[Box<dyn Value>]) -> Box<dyn Value> {
let matcher = Box::new(CastInstMatcher::create_fp_to_ui());
fn match_fp_to_ui(values: &[Box<dyn Value>]) -> Box<dyn Value> {
let value_matcher = single_optional_matcher_value(values);
let matcher = Box::new(CastInstMatcher::create_fp_to_ui(value_matcher));
Box::new(InstMatcherValue { matcher })
}

fn match_fp_to_si(_values: &[Box<dyn Value>]) -> Box<dyn Value> {
let matcher = Box::new(CastInstMatcher::create_fp_to_si());
fn match_fp_to_si(values: &[Box<dyn Value>]) -> Box<dyn Value> {
let value_matcher = single_optional_matcher_value(values);
let matcher = Box::new(CastInstMatcher::create_fp_to_si(value_matcher));
Box::new(InstMatcherValue { matcher })
}

fn match_fp_trunc(_values: &[Box<dyn Value>]) -> Box<dyn Value> {
let matcher = Box::new(CastInstMatcher::create_fp_trunc());
fn match_fp_trunc(values: &[Box<dyn Value>]) -> Box<dyn Value> {
let value_matcher = single_optional_matcher_value(values);
let matcher = Box::new(CastInstMatcher::create_fp_trunc(value_matcher));
Box::new(InstMatcherValue { matcher })
}

fn match_int_to_ptr(_values: &[Box<dyn Value>]) -> Box<dyn Value> {
let matcher = Box::new(CastInstMatcher::create_int_to_ptr());
fn match_int_to_ptr(values: &[Box<dyn Value>]) -> Box<dyn Value> {
let value_matcher = single_optional_matcher_value(values);
let matcher = Box::new(CastInstMatcher::create_int_to_ptr(value_matcher));
Box::new(InstMatcherValue { matcher })
}

fn match_ptr_to_int(_values: &[Box<dyn Value>]) -> Box<dyn Value> {
let matcher = Box::new(CastInstMatcher::create_ptr_to_int());
fn match_ptr_to_int(values: &[Box<dyn Value>]) -> Box<dyn Value> {
let value_matcher = single_optional_matcher_value(values);
let matcher = Box::new(CastInstMatcher::create_ptr_to_int(value_matcher));
Box::new(InstMatcherValue { matcher })
}

fn match_zext(_values: &[Box<dyn Value>]) -> Box<dyn Value> {
let matcher = Box::new(CastInstMatcher::create_zext());
fn match_zext(values: &[Box<dyn Value>]) -> Box<dyn Value> {
let value_matcher = single_optional_matcher_value(values);
let matcher = Box::new(CastInstMatcher::create_zext(value_matcher));
Box::new(InstMatcherValue { matcher })
}

fn match_sext(_values: &[Box<dyn Value>]) -> Box<dyn Value> {
let matcher = Box::new(CastInstMatcher::create_sext());
fn match_sext(values: &[Box<dyn Value>]) -> Box<dyn Value> {
let value_matcher = single_optional_matcher_value(values);
let matcher = Box::new(CastInstMatcher::create_sext(value_matcher));
Box::new(InstMatcherValue { matcher })
}

fn match_bit_cast(_values: &[Box<dyn Value>]) -> Box<dyn Value> {
let matcher = Box::new(CastInstMatcher::create_bit_cast());
fn match_bit_cast(values: &[Box<dyn Value>]) -> Box<dyn Value> {
let value_matcher = single_optional_matcher_value(values);
let matcher = Box::new(CastInstMatcher::create_bit_cast(value_matcher));
Box::new(InstMatcherValue { matcher })
}

fn match_addr_space_cast(_values: &[Box<dyn Value>]) -> Box<dyn Value> {
let matcher = Box::new(CastInstMatcher::create_addr_space_cast());
fn match_addr_space_cast(values: &[Box<dyn Value>]) -> Box<dyn Value> {
let value_matcher = single_optional_matcher_value(values);
let matcher = Box::new(CastInstMatcher::create_addr_space_cast(value_matcher));
Box::new(InstMatcherValue { matcher })
}
14 changes: 14 additions & 0 deletions src/functions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,3 +133,17 @@ pub fn binary_matchers_sides(

(lhs_matcher, rhs_matcher)
}

#[inline]
pub fn single_optional_matcher_value(values: &[Box<dyn Value>]) -> Box<dyn Matcher<LLVMValueRef>> {
if !values.is_empty() {
values[0]
.as_any()
.downcast_ref::<InstMatcherValue>()
.unwrap()
.matcher
.to_owned()
} else {
Box::new(AnyInstMatcher)
}
}
69 changes: 43 additions & 26 deletions src/matchers/cast.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use inkwell::llvm_sys::core::LLVMGetInstructionOpcode;
use inkwell::llvm_sys::core::{LLVMGetInstructionOpcode, LLVMGetOperand};
use inkwell::llvm_sys::prelude::LLVMValueRef;
use inkwell::llvm_sys::LLVMOpcode;

Expand Down Expand Up @@ -39,64 +39,81 @@ impl CastMatcherKind {

#[derive(Clone)]
pub struct CastInstMatcher {
value_matcher: Box<dyn Matcher<LLVMValueRef>>,
kind: CastMatcherKind,
}

impl CastInstMatcher {
fn new(kind: CastMatcherKind) -> Self {
CastInstMatcher { kind }
fn new(value_matcher: Box<dyn Matcher<LLVMValueRef>>, kind: CastMatcherKind) -> Self {
CastInstMatcher {
value_matcher,
kind,
}
}
}

impl CastInstMatcher {
pub fn create_trunc() -> CastInstMatcher {
CastInstMatcher::new(CastMatcherKind::Trunc)
pub fn create_trunc(value_matcher: Box<dyn Matcher<LLVMValueRef>>) -> CastInstMatcher {
CastInstMatcher::new(value_matcher, CastMatcherKind::Trunc)
}

pub fn create_fp_to_ui() -> CastInstMatcher {
CastInstMatcher::new(CastMatcherKind::FPToUI)
pub fn create_fp_to_ui(value_matcher: Box<dyn Matcher<LLVMValueRef>>) -> CastInstMatcher {
CastInstMatcher::new(value_matcher, CastMatcherKind::FPToUI)
}

pub fn create_fp_to_si() -> CastInstMatcher {
CastInstMatcher::new(CastMatcherKind::FPToSI)
pub fn create_fp_to_si(value_matcher: Box<dyn Matcher<LLVMValueRef>>) -> CastInstMatcher {
CastInstMatcher::new(value_matcher, CastMatcherKind::FPToSI)
}

pub fn create_fp_trunc() -> CastInstMatcher {
CastInstMatcher::new(CastMatcherKind::FPTrunc)
pub fn create_fp_trunc(value_matcher: Box<dyn Matcher<LLVMValueRef>>) -> CastInstMatcher {
CastInstMatcher::new(value_matcher, CastMatcherKind::FPTrunc)
}

pub fn create_fpext() -> CastInstMatcher {
CastInstMatcher::new(CastMatcherKind::FPExt)
pub fn create_fpext(value_matcher: Box<dyn Matcher<LLVMValueRef>>) -> CastInstMatcher {
CastInstMatcher::new(value_matcher, CastMatcherKind::FPExt)
}

pub fn create_int_to_ptr() -> CastInstMatcher {
CastInstMatcher::new(CastMatcherKind::IntToPtr)
pub fn create_int_to_ptr(value_matcher: Box<dyn Matcher<LLVMValueRef>>) -> CastInstMatcher {
CastInstMatcher::new(value_matcher, CastMatcherKind::IntToPtr)
}

pub fn create_ptr_to_int() -> CastInstMatcher {
CastInstMatcher::new(CastMatcherKind::PtrToInt)
pub fn create_ptr_to_int(value_matcher: Box<dyn Matcher<LLVMValueRef>>) -> CastInstMatcher {
CastInstMatcher::new(value_matcher, CastMatcherKind::PtrToInt)
}

pub fn create_zext() -> CastInstMatcher {
CastInstMatcher::new(CastMatcherKind::ZExt)
pub fn create_zext(value_matcher: Box<dyn Matcher<LLVMValueRef>>) -> CastInstMatcher {
CastInstMatcher::new(value_matcher, CastMatcherKind::ZExt)
}

pub fn create_sext() -> CastInstMatcher {
CastInstMatcher::new(CastMatcherKind::SExt)
pub fn create_sext(value_matcher: Box<dyn Matcher<LLVMValueRef>>) -> CastInstMatcher {
CastInstMatcher::new(value_matcher, CastMatcherKind::SExt)
}

pub fn create_bit_cast() -> CastInstMatcher {
CastInstMatcher::new(CastMatcherKind::BitCast)
pub fn create_bit_cast(value_matcher: Box<dyn Matcher<LLVMValueRef>>) -> CastInstMatcher {
CastInstMatcher::new(value_matcher, CastMatcherKind::BitCast)
}

pub fn create_addr_space_cast() -> CastInstMatcher {
CastInstMatcher::new(CastMatcherKind::AddrSpaceCast)
pub fn create_addr_space_cast(
value_matcher: Box<dyn Matcher<LLVMValueRef>>,
) -> CastInstMatcher {
CastInstMatcher::new(value_matcher, CastMatcherKind::AddrSpaceCast)
}
}

impl Matcher<LLVMValueRef> for CastInstMatcher {
#[allow(clippy::not_unsafe_ptr_arg_deref)]
fn is_match(&self, instruction: &LLVMValueRef) -> bool {
unsafe { self.kind.llvm_opcode() == LLVMGetInstructionOpcode(*instruction) }
unsafe {
if self.kind.llvm_opcode() != LLVMGetInstructionOpcode(*instruction) {
return false;
}

let value = LLVMGetOperand(*instruction, 0);
if !self.value_matcher.is_match(&value) {
return false;
}

true
}
}
}

0 comments on commit 37dca87

Please sign in to comment.