Skip to content

Commit

Permalink
feat: Implement m_or, m_and, m_xor, m_c_or, m_c_and, `m_c_x…
Browse files Browse the repository at this point in the history
…or`, Matchers
  • Loading branch information
AmrDeveloper committed Dec 5, 2024
1 parent d5ada89 commit c42e80e
Show file tree
Hide file tree
Showing 7 changed files with 220 additions and 2 deletions.
14 changes: 13 additions & 1 deletion docs/InstructionMatcher.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 |
| 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 |
70 changes: 70 additions & 0 deletions src/functions/matchers/binary.rs
Original file line number Diff line number Diff line change
@@ -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<dyn Value>]) -> Box<dyn Value> {
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<dyn Value>]) -> Box<dyn Value> {
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<dyn Value>]) -> Box<dyn Value> {
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<dyn Value>]) -> Box<dyn Value> {
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<dyn Value>]) -> Box<dyn Value> {
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<dyn Value>]) -> Box<dyn Value> {
let (lhs_matcher, rhs_matcher) = binary_matchers_sides(values);
let matcher = BinaryInstMatcher::create_commutatively_xor(lhs_matcher, rhs_matcher);
Box::new(InstMatcherValue { matcher })
}
1 change: 1 addition & 0 deletions src/functions/matchers/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod arithmetic;
pub mod binary;
pub mod constants;
pub mod fcmp;
pub mod icmp;
Expand Down
5 changes: 5 additions & 0 deletions src/functions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
})
}
Expand All @@ -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
}

Expand Down
128 changes: 128 additions & 0 deletions src/matchers/binary.rs
Original file line number Diff line number Diff line change
@@ -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<dyn InstMatcher>,
pub rhs_matcher: Box<dyn InstMatcher>,
pub operator: BinaryOperator,
pub commutatively: bool,
}

impl BinaryInstMatcher {
pub fn create_and(
lhs: Box<dyn InstMatcher>,
rhs: Box<dyn InstMatcher>,
) -> Box<dyn InstMatcher> {
Box::new(BinaryInstMatcher {
lhs_matcher: lhs,
rhs_matcher: rhs,
operator: BinaryOperator::Or,
commutatively: false,
})
}

pub fn create_or(lhs: Box<dyn InstMatcher>, rhs: Box<dyn InstMatcher>) -> Box<dyn InstMatcher> {
Box::new(BinaryInstMatcher {
lhs_matcher: lhs,
rhs_matcher: rhs,
operator: BinaryOperator::And,
commutatively: false,
})
}

pub fn create_xor(
lhs: Box<dyn InstMatcher>,
rhs: Box<dyn InstMatcher>,
) -> Box<dyn InstMatcher> {
Box::new(BinaryInstMatcher {
lhs_matcher: lhs,
rhs_matcher: rhs,
operator: BinaryOperator::Xor,
commutatively: false,
})
}

pub fn create_commutatively_and(
lhs: Box<dyn InstMatcher>,
rhs: Box<dyn InstMatcher>,
) -> Box<dyn InstMatcher> {
Box::new(BinaryInstMatcher {
lhs_matcher: lhs,
rhs_matcher: rhs,
operator: BinaryOperator::Or,
commutatively: true,
})
}

pub fn create_commutatively_or(
lhs: Box<dyn InstMatcher>,
rhs: Box<dyn InstMatcher>,
) -> Box<dyn InstMatcher> {
Box::new(BinaryInstMatcher {
lhs_matcher: lhs,
rhs_matcher: rhs,
operator: BinaryOperator::And,
commutatively: true,
})
}

pub fn create_commutatively_xor(
lhs: Box<dyn InstMatcher>,
rhs: Box<dyn InstMatcher>,
) -> Box<dyn InstMatcher> {
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
}
}
}
1 change: 1 addition & 0 deletions src/matchers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,4 @@ pub mod other;
pub mod shifts;
pub mod types;
pub mod usage;
pub mod binary;
3 changes: 2 additions & 1 deletion src/matchers/shifts.rs
Original file line number Diff line number Diff line change
@@ -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;

Expand Down

0 comments on commit c42e80e

Please sign in to comment.