diff --git a/docs/matchers/cast.md b/docs/matchers/cast.md index 732c641..27decae 100644 --- a/docs/matchers/cast.md +++ b/docs/matchers/cast.md @@ -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 | diff --git a/src/functions/matchers/cast.rs b/src/functions/matchers/cast.rs index eb33a45..3928f52 100644 --- a/src/functions/matchers/cast.rs +++ b/src/functions/matchers/cast.rs @@ -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; @@ -40,52 +41,62 @@ fn cast_function_signature() -> Signature { Signature::with_return(Box::new(InstMatcherType)) } -fn match_trunc(_values: &[Box]) -> Box { - let matcher = Box::new(CastInstMatcher::create_trunc()); +fn match_trunc(values: &[Box]) -> Box { + 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]) -> Box { - let matcher = Box::new(CastInstMatcher::create_fp_to_ui()); +fn match_fp_to_ui(values: &[Box]) -> Box { + 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]) -> Box { - let matcher = Box::new(CastInstMatcher::create_fp_to_si()); +fn match_fp_to_si(values: &[Box]) -> Box { + 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]) -> Box { - let matcher = Box::new(CastInstMatcher::create_fp_trunc()); +fn match_fp_trunc(values: &[Box]) -> Box { + 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]) -> Box { - let matcher = Box::new(CastInstMatcher::create_int_to_ptr()); +fn match_int_to_ptr(values: &[Box]) -> Box { + 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]) -> Box { - let matcher = Box::new(CastInstMatcher::create_ptr_to_int()); +fn match_ptr_to_int(values: &[Box]) -> Box { + 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]) -> Box { - let matcher = Box::new(CastInstMatcher::create_zext()); +fn match_zext(values: &[Box]) -> Box { + 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]) -> Box { - let matcher = Box::new(CastInstMatcher::create_sext()); +fn match_sext(values: &[Box]) -> Box { + 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]) -> Box { - let matcher = Box::new(CastInstMatcher::create_bit_cast()); +fn match_bit_cast(values: &[Box]) -> Box { + 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]) -> Box { - let matcher = Box::new(CastInstMatcher::create_addr_space_cast()); +fn match_addr_space_cast(values: &[Box]) -> Box { + let value_matcher = single_optional_matcher_value(values); + let matcher = Box::new(CastInstMatcher::create_addr_space_cast(value_matcher)); Box::new(InstMatcherValue { matcher }) } diff --git a/src/functions/mod.rs b/src/functions/mod.rs index 17c69fe..cf370d6 100644 --- a/src/functions/mod.rs +++ b/src/functions/mod.rs @@ -133,3 +133,17 @@ pub fn binary_matchers_sides( (lhs_matcher, rhs_matcher) } + +#[inline] +pub fn single_optional_matcher_value(values: &[Box]) -> Box> { + if !values.is_empty() { + values[0] + .as_any() + .downcast_ref::() + .unwrap() + .matcher + .to_owned() + } else { + Box::new(AnyInstMatcher) + } +} diff --git a/src/matchers/cast.rs b/src/matchers/cast.rs index 13cef42..3324313 100644 --- a/src/matchers/cast.rs +++ b/src/matchers/cast.rs @@ -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; @@ -39,64 +39,81 @@ impl CastMatcherKind { #[derive(Clone)] pub struct CastInstMatcher { + value_matcher: Box>, kind: CastMatcherKind, } impl CastInstMatcher { - fn new(kind: CastMatcherKind) -> Self { - CastInstMatcher { kind } + fn new(value_matcher: Box>, 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>) -> 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>) -> 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>) -> 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>) -> CastInstMatcher { + CastInstMatcher::new(value_matcher, CastMatcherKind::FPTrunc) } - pub fn create_fpext() -> CastInstMatcher { - CastInstMatcher::new(CastMatcherKind::FPExt) + pub fn create_fpext(value_matcher: Box>) -> 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>) -> 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>) -> CastInstMatcher { + CastInstMatcher::new(value_matcher, CastMatcherKind::PtrToInt) } - pub fn create_zext() -> CastInstMatcher { - CastInstMatcher::new(CastMatcherKind::ZExt) + pub fn create_zext(value_matcher: Box>) -> CastInstMatcher { + CastInstMatcher::new(value_matcher, CastMatcherKind::ZExt) } - pub fn create_sext() -> CastInstMatcher { - CastInstMatcher::new(CastMatcherKind::SExt) + pub fn create_sext(value_matcher: Box>) -> 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>) -> 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>, + ) -> CastInstMatcher { + CastInstMatcher::new(value_matcher, CastMatcherKind::AddrSpaceCast) } } impl Matcher 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 + } } }