diff --git a/docs/InstructionMatcher.md b/docs/InstructionMatcher.md index 7110718..993b46c 100644 --- a/docs/InstructionMatcher.md +++ b/docs/InstructionMatcher.md @@ -4,18 +4,18 @@ Instructions Matchers are functions that build a instruction matcher to match ag ### General Instructions Matchers functions -| Function | Parameters | Return | Description | -| :-----------: | :------------------------------: | :---------: | :-------------------------------------------------------------: | -| m_inst | (i: Instruction, m: InstMatcher) | Bool | Check if instruction is matched with Matcher | -| m_any_inst | () | InstMatcher | Build Inst Matcher that match any Instruction | -| m_const_int | () | InstMatcher | Build Inst Matcher that match constants int value | -| m_const_fp | () | InstMatcher | Build Inst Matcher that match constants float value | -| m_const_null | () | InstMatcher | Build Inst Matcher that match constants pointer null | -| m_poison | () | InstMatcher | Build Inst Matcher that match poison value | -| m_label | (n : Text?) | InstMatcher | Build Inst Matcher that match Label with optional name | -| m_label | (n : Text?) | InstMatcher | Build Inst Matcher that match Argument value with optional name | -| m_return | (m : InstMatcher?) | InstMatcher | Build Inst Matcher that match Return Instruction | -| m_unreachable | () | InstMatcher | Build Inst Matcher that match unreachable Instruction | +| Function | Parameters | Return | Description | +| :-----------: | :------------------------------: | :---------: | :----------------------------------------------------------------------: | +| m_inst | (i: Instruction, m: InstMatcher) | Bool | Check if instruction is matched with Matcher | +| m_any_inst | () | InstMatcher | Build Inst Matcher that match any Instruction | +| m_const_int | () | InstMatcher | Build Inst Matcher that match constants int value | +| m_const_fp | () | InstMatcher | Build Inst Matcher that match constants float value | +| m_const_null | () | InstMatcher | Build Inst Matcher that match constants pointer null | +| m_poison | () | InstMatcher | Build Inst Matcher that match poison value | +| m_label | (n : Text?) | InstMatcher | Build Inst Matcher that match Label with optional name | +| m_argument | (n : Text?, m : TypeMatcher?) | InstMatcher | Build Inst Matcher that match Argument value with optional name and type | +| m_return | (m : InstMatcher?) | InstMatcher | Build Inst Matcher that match Return Instruction | +| m_unreachable | () | InstMatcher | Build Inst Matcher that match unreachable Instruction | ### Arithmetic Instructions Matchers functions diff --git a/src/functions/inst_matcher.rs b/src/functions/inst_matcher.rs index 05763b0..ca0bcf6 100644 --- a/src/functions/inst_matcher.rs +++ b/src/functions/inst_matcher.rs @@ -10,8 +10,10 @@ use gitql_core::values::boolean::BoolValue; use crate::ir::types::InstMatcherType; use crate::ir::types::LLVMInstType; +use crate::ir::types::TypeMatcherType; use crate::ir::values::InstMatcherValue; use crate::ir::values::LLVMInstValue; +use crate::ir::values::TypeMatcherValue; use crate::matchers::instruction_matcher::AnyInstMatcher; use crate::matchers::instruction_matcher::ArgumentMatcher; use crate::matchers::instruction_matcher::ConstFloatMatcher; @@ -120,9 +122,14 @@ pub fn register_inst_matchers_function_signatures(map: &mut HashMap<&'static str map.insert( "m_argument", Signature { - parameters: vec![Box::new(OptionType { - base: Some(Box::new(TextType)), - })], + parameters: vec![ + Box::new(OptionType { + base: Some(Box::new(TextType)), + }), + Box::new(OptionType { + base: Some(Box::new(TypeMatcherType)), + }), + ], return_type: Box::new(InstMatcherType), }, ); @@ -217,8 +224,21 @@ fn match_argument_inst(values: &[Box]) -> Box { values[0].as_text() }; + let type_matcher = if values.len() == 2 { + Some( + values[1] + .as_any() + .downcast_ref::() + .unwrap() + .matcher + .clone(), + ) + } else { + None + }; + Box::new(InstMatcherValue { - matcher: Box::new(ArgumentMatcher { name }), + matcher: Box::new(ArgumentMatcher { name, type_matcher }), }) } diff --git a/src/matchers/instruction_matcher.rs b/src/matchers/instruction_matcher.rs index 188934f..988539e 100644 --- a/src/matchers/instruction_matcher.rs +++ b/src/matchers/instruction_matcher.rs @@ -5,6 +5,7 @@ use inkwell::llvm_sys; use inkwell::llvm_sys::core::LLVMGetFCmpPredicate; use inkwell::llvm_sys::core::LLVMGetICmpPredicate; use inkwell::llvm_sys::core::LLVMGetValueKind; +use inkwell::llvm_sys::core::LLVMTypeOf; use inkwell::llvm_sys::LLVMIntPredicate; use inkwell::llvm_sys::LLVMRealPredicate; use inkwell::llvm_sys::LLVMValueKind; @@ -13,6 +14,8 @@ use llvm_sys::core::LLVMGetOperand; use llvm_sys::prelude::LLVMValueRef; use llvm_sys::LLVMOpcode; +use super::type_matcher::TypeMatcher; + dyn_clone::clone_trait_object!(InstMatcher); /// Instruction matcher used to create matcher that check if rules match the instruction or not @@ -1021,6 +1024,7 @@ impl InstMatcher for PoisonValueMatcher { #[derive(Clone)] pub struct ArgumentMatcher { pub name: Option, + pub type_matcher: Option>, } impl InstMatcher for ArgumentMatcher { @@ -1033,9 +1037,15 @@ impl InstMatcher for ArgumentMatcher { if let Some(name) = &self.name { let label_value_name = llvm_sys::core::LLVMGetValueName(instruction); let name_str = CStr::from_ptr(label_value_name).to_str().unwrap(); - return name.eq(name_str); + let is_name_matches = name.eq(name_str); + if is_name_matches { + if let Some(type_matcher) = &self.type_matcher { + let value_type = LLVMTypeOf(instruction); + return type_matcher.is_match(value_type); + } + return true; + } } - return true; } false }