From c42e80e3d29cbe733d998eb8ffd62344eaa4c4d1 Mon Sep 17 00:00:00 2001 From: AmrDeveloper Date: Thu, 5 Dec 2024 21:16:34 +0100 Subject: [PATCH] feat: Implement `m_or`, `m_and`, `m_xor`, `m_c_or`, `m_c_and`, `m_c_xor`, Matchers --- docs/InstructionMatcher.md | 14 +++- src/functions/matchers/binary.rs | 70 +++++++++++++++++ src/functions/matchers/mod.rs | 1 + src/functions/mod.rs | 5 ++ src/matchers/binary.rs | 128 +++++++++++++++++++++++++++++++ src/matchers/mod.rs | 1 + src/matchers/shifts.rs | 3 +- 7 files changed, 220 insertions(+), 2 deletions(-) create mode 100644 src/functions/matchers/binary.rs create mode 100644 src/matchers/binary.rs diff --git a/docs/InstructionMatcher.md b/docs/InstructionMatcher.md index 31b7157..38e31de 100644 --- a/docs/InstructionMatcher.md +++ b/docs/InstructionMatcher.md @@ -113,4 +113,16 @@ Instructions Matchers are functions that build a instruction matcher to match ag | m_ashr | (lhs: InstMatcher, rhs: InstMatcher) | InstMatcher | Build Inst Matcher that match ashr Instruction | | m_c_shl | (lhs: InstMatcher, rhs: InstMatcher) | InstMatcher | Build Inst Matcher that match shl Instruction with commutatively | | m_c_shr | (lhs: InstMatcher, rhs: InstMatcher) | InstMatcher | Build Inst Matcher that match shr Instruction with commutatively | -| m_c_ashr | (lhs: InstMatcher, rhs: InstMatcher) | InstMatcher | Build Inst Matcher that match ashr Instruction with commutatively | \ No newline at end of file +| m_c_ashr | (lhs: InstMatcher, rhs: InstMatcher) | InstMatcher | Build Inst Matcher that match ashr Instruction with commutatively | + + +### Logical and Bitwise Instructions Matchers functions + +| Function | Parameters | Return | Description | +| :------: | :----------------------------------: | :---------: | :---------------------------------------------------------: | +| m_or | (lhs: InstMatcher, rhs: InstMatcher) | InstMatcher | Build Inst Matcher that match or Instruction | +| m_and | (lhs: InstMatcher, rhs: InstMatcher) | InstMatcher | Build Inst Matcher that match and Instruction | +| m_xor | (lhs: InstMatcher, rhs: InstMatcher) | InstMatcher | Build Inst Matcher that match xor Instruction | +| m_c_or | (lhs: InstMatcher, rhs: InstMatcher) | InstMatcher | Build Inst Matcher that match or Instruction commutatively | +| m_c_and | (lhs: InstMatcher, rhs: InstMatcher) | InstMatcher | Build Inst Matcher that match and Instruction commutatively | +| m_c_xor | (lhs: InstMatcher, rhs: InstMatcher) | InstMatcher | Build Inst Matcher that match xor Instruction commutatively | \ No newline at end of file diff --git a/src/functions/matchers/binary.rs b/src/functions/matchers/binary.rs new file mode 100644 index 0000000..22b8567 --- /dev/null +++ b/src/functions/matchers/binary.rs @@ -0,0 +1,70 @@ +use std::collections::HashMap; + +use gitql_core::signature::Function; +use gitql_core::signature::Signature; +use gitql_core::values::base::Value; + +use crate::functions::binary_matcher_signature; +use crate::functions::binary_matchers_sides; +use crate::ir::values::InstMatcherValue; +use crate::matchers::binary::BinaryInstMatcher; + +#[inline(always)] +pub fn register_binary_inst_matchers_functions(map: &mut HashMap<&'static str, Function>) { + map.insert("m_or", match_or_inst); + map.insert("m_and", match_and_inst); + map.insert("m_xor", match_xor_inst); + + map.insert("m_c_or", match_commutatively_or_inst); + map.insert("m_c_and", match_commutatively_and_inst); + map.insert("m_c_xor", match_commutatively_xor_inst); +} + +#[inline(always)] +pub fn register_binary_inst_matchers_function_signatures( + map: &mut HashMap<&'static str, Signature>, +) { + map.insert("m_or", binary_matcher_signature()); + map.insert("m_and", binary_matcher_signature()); + map.insert("m_xor", binary_matcher_signature()); + + map.insert("m_c_or", binary_matcher_signature()); + map.insert("m_c_and", binary_matcher_signature()); + map.insert("m_c_xor", binary_matcher_signature()); +} + +fn match_or_inst(values: &[Box]) -> Box { + let (lhs_matcher, rhs_matcher) = binary_matchers_sides(values); + let matcher = BinaryInstMatcher::create_or(lhs_matcher, rhs_matcher); + Box::new(InstMatcherValue { matcher }) +} + +fn match_and_inst(values: &[Box]) -> Box { + let (lhs_matcher, rhs_matcher) = binary_matchers_sides(values); + let matcher = BinaryInstMatcher::create_and(lhs_matcher, rhs_matcher); + Box::new(InstMatcherValue { matcher }) +} + +fn match_xor_inst(values: &[Box]) -> Box { + let (lhs_matcher, rhs_matcher) = binary_matchers_sides(values); + let matcher = BinaryInstMatcher::create_xor(lhs_matcher, rhs_matcher); + Box::new(InstMatcherValue { matcher }) +} + +fn match_commutatively_or_inst(values: &[Box]) -> Box { + let (lhs_matcher, rhs_matcher) = binary_matchers_sides(values); + let matcher = BinaryInstMatcher::create_commutatively_or(lhs_matcher, rhs_matcher); + Box::new(InstMatcherValue { matcher }) +} + +fn match_commutatively_and_inst(values: &[Box]) -> Box { + let (lhs_matcher, rhs_matcher) = binary_matchers_sides(values); + let matcher = BinaryInstMatcher::create_commutatively_and(lhs_matcher, rhs_matcher); + Box::new(InstMatcherValue { matcher }) +} + +fn match_commutatively_xor_inst(values: &[Box]) -> Box { + let (lhs_matcher, rhs_matcher) = binary_matchers_sides(values); + let matcher = BinaryInstMatcher::create_commutatively_xor(lhs_matcher, rhs_matcher); + Box::new(InstMatcherValue { matcher }) +} diff --git a/src/functions/matchers/mod.rs b/src/functions/matchers/mod.rs index 7f18edd..66227ad 100644 --- a/src/functions/matchers/mod.rs +++ b/src/functions/matchers/mod.rs @@ -1,4 +1,5 @@ pub mod arithmetic; +pub mod binary; pub mod constants; pub mod fcmp; pub mod icmp; diff --git a/src/functions/mod.rs b/src/functions/mod.rs index 79ff386..30daff8 100644 --- a/src/functions/mod.rs +++ b/src/functions/mod.rs @@ -7,8 +7,11 @@ use gitql_core::signature::Signature; use gitql_core::values::base::Value; use gitql_std::function::standard_function_signatures; use gitql_std::function::standard_functions; + use matchers::arithmetic::register_arithmetic_matchers_function_signatures; use matchers::arithmetic::register_arithmetic_matchers_functions; +use matchers::binary::register_binary_inst_matchers_function_signatures; +use matchers::binary::register_binary_inst_matchers_functions; use matchers::constants::register_constants_matchers_function_signatures; use matchers::constants::register_constants_matchers_functions; use matchers::fcmp::register_float_comparisons_matchers_function_signatures; @@ -43,6 +46,7 @@ pub fn llvm_ir_functions() -> &'static HashMap<&'static str, Function> { register_constants_matchers_functions(&mut map); register_other_inst_matchers_functions(&mut map); register_shift_matchers_functions(&mut map); + register_binary_inst_matchers_functions(&mut map); map }) } @@ -57,6 +61,7 @@ pub fn llvm_ir_function_signatures() -> HashMap<&'static str, Signature> { register_constants_matchers_function_signatures(&mut map); register_other_inst_matchers_function_signatures(&mut map); register_shift_matchers_function_signatures(&mut map); + register_binary_inst_matchers_function_signatures(&mut map); map } diff --git a/src/matchers/binary.rs b/src/matchers/binary.rs new file mode 100644 index 0000000..9b90f1f --- /dev/null +++ b/src/matchers/binary.rs @@ -0,0 +1,128 @@ +use inkwell::llvm_sys::core::LLVMGetInstructionOpcode; +use inkwell::llvm_sys::core::LLVMGetOperand; +use inkwell::llvm_sys::prelude::LLVMValueRef; +use inkwell::llvm_sys::LLVMOpcode; + +use super::InstMatcher; + +#[derive(Clone)] +pub enum BinaryOperator { + And, + Or, + Xor, +} + +impl BinaryOperator { + pub fn llvm_opcode(&self) -> LLVMOpcode { + match self { + BinaryOperator::And => LLVMOpcode::LLVMAnd, + BinaryOperator::Or => LLVMOpcode::LLVMOr, + BinaryOperator::Xor => LLVMOpcode::LLVMXor, + } + } +} + +/// General Binary Instruction Matcher +#[derive(Clone)] +pub struct BinaryInstMatcher { + pub lhs_matcher: Box, + pub rhs_matcher: Box, + pub operator: BinaryOperator, + pub commutatively: bool, +} + +impl BinaryInstMatcher { + pub fn create_and( + lhs: Box, + rhs: Box, + ) -> Box { + Box::new(BinaryInstMatcher { + lhs_matcher: lhs, + rhs_matcher: rhs, + operator: BinaryOperator::Or, + commutatively: false, + }) + } + + pub fn create_or(lhs: Box, rhs: Box) -> Box { + Box::new(BinaryInstMatcher { + lhs_matcher: lhs, + rhs_matcher: rhs, + operator: BinaryOperator::And, + commutatively: false, + }) + } + + pub fn create_xor( + lhs: Box, + rhs: Box, + ) -> Box { + Box::new(BinaryInstMatcher { + lhs_matcher: lhs, + rhs_matcher: rhs, + operator: BinaryOperator::Xor, + commutatively: false, + }) + } + + pub fn create_commutatively_and( + lhs: Box, + rhs: Box, + ) -> Box { + Box::new(BinaryInstMatcher { + lhs_matcher: lhs, + rhs_matcher: rhs, + operator: BinaryOperator::Or, + commutatively: true, + }) + } + + pub fn create_commutatively_or( + lhs: Box, + rhs: Box, + ) -> Box { + Box::new(BinaryInstMatcher { + lhs_matcher: lhs, + rhs_matcher: rhs, + operator: BinaryOperator::And, + commutatively: true, + }) + } + + pub fn create_commutatively_xor( + lhs: Box, + rhs: Box, + ) -> Box { + Box::new(BinaryInstMatcher { + lhs_matcher: lhs, + rhs_matcher: rhs, + operator: BinaryOperator::Xor, + commutatively: true, + }) + } +} + +impl InstMatcher for BinaryInstMatcher { + #[allow(clippy::not_unsafe_ptr_arg_deref)] + fn is_match(&self, instruction: LLVMValueRef) -> bool { + unsafe { + let opcode = LLVMGetInstructionOpcode(instruction); + if opcode == self.operator.llvm_opcode() { + let rhs = LLVMGetOperand(instruction, 1); + let lhs = LLVMGetOperand(instruction, 0); + + if self.lhs_matcher.is_match(lhs) && self.rhs_matcher.is_match(rhs) { + return true; + } + + if self.commutatively + && self.lhs_matcher.is_match(rhs) + && self.rhs_matcher.is_match(lhs) + { + return true; + } + } + false + } + } +} diff --git a/src/matchers/mod.rs b/src/matchers/mod.rs index 1af8626..0046cf0 100644 --- a/src/matchers/mod.rs +++ b/src/matchers/mod.rs @@ -44,3 +44,4 @@ pub mod other; pub mod shifts; pub mod types; pub mod usage; +pub mod binary; \ No newline at end of file diff --git a/src/matchers/shifts.rs b/src/matchers/shifts.rs index 05629d8..51ac425 100644 --- a/src/matchers/shifts.rs +++ b/src/matchers/shifts.rs @@ -1,4 +1,5 @@ -use inkwell::llvm_sys::core::{LLVMGetInstructionOpcode, LLVMGetOperand}; +use inkwell::llvm_sys::core::LLVMGetInstructionOpcode; +use inkwell::llvm_sys::core::LLVMGetOperand; use inkwell::llvm_sys::prelude::LLVMValueRef; use inkwell::llvm_sys::LLVMOpcode;