#![cfg(feature = "normalized_dev")] use crate::mir::join_ir::{JoinFuncId, JoinFunction, JoinInst, JoinModule}; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub(crate) enum NormalizedDevShape { Pattern1Mini, Pattern2Mini, JsonparserSkipWsMini, JsonparserAtoiMini, } pub(crate) fn supported_shapes(module: &JoinModule) -> Vec { let mut shapes = Vec::new(); if is_jsonparser_atoi_mini(module) { shapes.push(NormalizedDevShape::JsonparserAtoiMini); } if is_jsonparser_skip_ws_mini(module) { shapes.push(NormalizedDevShape::JsonparserSkipWsMini); } if is_pattern2_mini(module) { shapes.push(NormalizedDevShape::Pattern2Mini); } if is_pattern1_mini(module) { shapes.push(NormalizedDevShape::Pattern1Mini); } shapes } pub(crate) fn is_pattern1_mini(module: &JoinModule) -> bool { module.is_structured() && find_loop_step(module).is_some() } pub(crate) fn is_pattern2_mini(module: &JoinModule) -> bool { if !module.is_structured() || module.functions.len() != 3 { return false; } let loop_func = match find_loop_step(module) { Some(f) => f, None => return false, }; if !(1..=3).contains(&loop_func.params.len()) { return false; } let has_cond_jump = loop_func .body .iter() .any(|inst| matches!(inst, JoinInst::Jump { cond: Some(_), .. })); let has_tail_call = loop_func .body .iter() .any(|inst| matches!(inst, JoinInst::Call { k_next: None, .. })); has_cond_jump && has_tail_call } pub(crate) fn is_jsonparser_skip_ws_mini(module: &JoinModule) -> bool { is_pattern2_mini(module) && module .functions .values() .any(|f| f.name == "jsonparser_skip_ws_mini") } pub(crate) fn is_jsonparser_atoi_mini(module: &JoinModule) -> bool { if !module.is_structured() || module.functions.len() != 3 { return false; } let loop_func = match find_loop_step(module) { Some(f) => f, None => return false, }; if !(3..=8).contains(&loop_func.params.len()) { return false; } let has_cond_jump = loop_func .body .iter() .any(|inst| matches!(inst, JoinInst::Jump { cond: Some(_), .. })); let has_tail_call = loop_func .body .iter() .any(|inst| matches!(inst, JoinInst::Call { k_next: None, .. })); has_cond_jump && has_tail_call && module .functions .values() .any(|f| f.name.contains("atoi")) } fn find_loop_step(module: &JoinModule) -> Option<&JoinFunction> { module .functions .values() .find(|f| f.name == "loop_step") .or_else(|| module.functions.get(&JoinFuncId::new(1))) }