From 11ae65efbab8bea22e6526604ee474d66c032610 Mon Sep 17 00:00:00 2001 From: Artur K Date: Sun, 26 Feb 2012 23:58:06 +0100 Subject: [PATCH] Refactoring idioms into objects with match/action methods --- include/epilogue_idioms.h | 39 +++++++++++ include/idiom.h | 15 ++++ include/idiom1.h | 16 +++++ src/epilogue_idioms.cpp | 139 ++++++++++++++++++++++++++++++++++++++ src/idiom1.cpp | 132 ++++++++++++++++++++++++++++++++++++ 5 files changed, 341 insertions(+) create mode 100644 include/epilogue_idioms.h create mode 100644 include/idiom.h create mode 100644 include/idiom1.h create mode 100644 src/epilogue_idioms.cpp create mode 100644 src/idiom1.cpp diff --git a/include/epilogue_idioms.h b/include/epilogue_idioms.h new file mode 100644 index 0000000..daf5c0d --- /dev/null +++ b/include/epilogue_idioms.h @@ -0,0 +1,39 @@ +#pragma once +#include "idiom.h" +#include "icode.h" +#include +struct EpilogIdiom : public Idiom +{ +protected: + std::deque m_icodes; // deque to push_front optional icodes from popStkVars + void popStkVars (iICODE pIcode); +public: + virtual ~EpilogIdiom() {} + EpilogIdiom(Function *f) : Idiom(f) + { + } + +}; +struct Idiom2 : public EpilogIdiom +{ + virtual ~Idiom2() {} + Idiom2(Function *f) : EpilogIdiom(f) + { + } + uint8_t minimum_match_length() {return 3;} + bool match(iICODE pIcode); + int action(); +}; +struct Idiom4 : public EpilogIdiom +{ +protected: + int m_param_count; +public: + virtual ~Idiom4() {} + Idiom4(Function *f) : EpilogIdiom(f) + { + } + uint8_t minimum_match_length() {return 1;} + bool match(iICODE pIcode); + int action(); +}; diff --git a/include/idiom.h b/include/idiom.h new file mode 100644 index 0000000..be634ca --- /dev/null +++ b/include/idiom.h @@ -0,0 +1,15 @@ +#pragma once +#include "icode.h" +#include "Procedure.h" +struct Idiom +{ +protected: + Function *m_func; + iICODE m_end; +public: + Idiom(Function *f) : m_func(f),m_end(f->Icode.end()) + { + } + virtual uint8_t minimum_match_length()=0; + virtual bool match(iICODE at)=0; +}; diff --git a/include/idiom1.h b/include/idiom1.h new file mode 100644 index 0000000..9ba6777 --- /dev/null +++ b/include/idiom1.h @@ -0,0 +1,16 @@ +#pragma once +#include "idiom.h" +struct Idiom1 : public Idiom +{ +protected: + std::vector m_icodes; + int m_min_off; + Int checkStkVars (iICODE pIcode); +public: + Idiom1(Function *f) : Idiom(f) + { + } + uint8_t minimum_match_length() {return 1;} + bool match(iICODE picode); + int action(); +}; diff --git a/src/epilogue_idioms.cpp b/src/epilogue_idioms.cpp new file mode 100644 index 0000000..e52df3a --- /dev/null +++ b/src/epilogue_idioms.cpp @@ -0,0 +1,139 @@ +#include "dcc.h" +#include "epilogue_idioms.h" + +/***************************************************************************** + * popStkVars - checks for + * [POP DI] + * [POP SI] + * or [POP SI] + * [POP DI] + ****************************************************************************/ +void EpilogIdiom::popStkVars(iICODE pIcode) +{ + // TODO : only process SI-DI DI-SI pairings, no SI-SI, DI-DI like it's now + /* Match [POP DI] */ + if (pIcode->ic.ll.match(iPOP)) + { + if ((m_func->flg & DI_REGVAR) && pIcode->ic.ll.match(rDI)) + m_icodes.push_front(pIcode); + else if ((m_func->flg & SI_REGVAR) && pIcode->ic.ll.match(rSI)) + m_icodes.push_front(pIcode); + } + ++pIcode; + if(pIcode==m_end) + return; + /* Match [POP SI] */ + if (pIcode->ic.ll.match(iPOP)) + { + if ((m_func->flg & SI_REGVAR) && pIcode->ic.ll.match(rSI)) + m_icodes.push_front(pIcode); + else if ((m_func->flg & DI_REGVAR) && pIcode->ic.ll.match(rDI)) + m_icodes.push_front(pIcode); + } +} + + +/***************************************************************************** + * idiom2 - HLL procedure epilogue; Returns number of instructions matched. + * [POP DI] + * [POP SI] + * MOV SP, BP + * POP BP + * RET(F) + *****************************************************************************/ +bool Idiom2::match(iICODE pIcode) +{ + iICODE nicode; + if(pIcode==m_func->Icode.begin()) // pIcode->loc_ip == 0 + return false; + if ( ((pIcode->ic.ll.flg & I) == I) || not pIcode->ic.ll.match(rSP,rBP)) + return false; + if(distance(pIcode,m_end)<3) + return false; + /* Matched MOV SP, BP */ + m_icodes.clear(); + m_icodes.push_back(pIcode); + /* Get next icode, skip over holes in the icode array */ + nicode = pIcode + 1; + while (nicode->ic.ll.flg & NO_CODE && (nicode != m_end)) + { + nicode++; + } + if(nicode == m_end) + return false; + + if (nicode->ic.ll.match(iPOP,rBP) && ! (nicode->ic.ll.flg & (I | TARGET | CASE)) ) + { + m_icodes.push_back(nicode++); // Matched POP BP + + /* Match RET(F) */ + if ( nicode != m_end && + !(nicode->ic.ll.flg & (I | TARGET | CASE)) && + (nicode->ic.ll.match(iRET) || nicode->ic.ll.match(iRETF)) + ) + { + m_icodes.push_back(nicode); // Matched RET + popStkVars (pIcode-2); // will add optional pop di/si to m_icodes + return true; + } + } + return false; +} +int Idiom2::action() +{ + for(size_t idx=0; idxinvalidate(); + return 3; + +} + +/***************************************************************************** + * idiom4 - Pascal calling convention. + * RET(F) immed + * ==> pProc->cbParam = immed + * sets CALL_PASCAL flag + * - Second version: check for optional pop of stack vars + * [POP DI] + * [POP SI] + * POP BP + * RET(F) [immed] + * - Third version: pop stack vars + * [POP DI] + * [POP SI] + * RET(F) [immed] + ****************************************************************************/ +bool Idiom4::match(iICODE pIcode) +{ + m_param_count = 0; + /* Check for [POP DI] + * [POP SI] */ + if(distance(m_func->Icode.begin(),pIcode)>=3) + popStkVars (pIcode-3); + if(pIcode != m_func->Icode.begin()) + { + iICODE prev1=pIcode-1; + /* Check for POP BP */ + if (prev1->ic.ll.match(iPOP,rBP) && not prev1->ic.ll.anyFlagSet(I) ) + m_icodes.push_back(prev1); + else if(prev1!=m_func->Icode.begin()) + popStkVars (pIcode-2); + } + + /* Check for RET(F) immed */ + if (pIcode->ic.ll.flg & I) + { + m_param_count = (int16)pIcode->ic.ll.src.op(); + } +} +int Idiom4::action() +{ + for(size_t idx=0; idxinvalidate(); + if(m_param_count) + { + m_func->cbParam = (int16)m_param_count; + m_func->flg |= CALL_PASCAL; + } + return 0; +} + diff --git a/src/idiom1.cpp b/src/idiom1.cpp new file mode 100644 index 0000000..1d548af --- /dev/null +++ b/src/idiom1.cpp @@ -0,0 +1,132 @@ +#include "idiom1.h" +#include "dcc.h" + +/***************************************************************************** + * idiom1 - HLL procedure prologue; Returns number of instructions matched. + * PUSH BP ==> ENTER immed, 0 + * MOV BP, SP and sets PROC_HLL flag + * [SUB SP, immed] + * [PUSH SI] + * [PUSH DI] + * - Second version: Push stack variables and then save BP + * PUSH BP + * PUSH SI + * [PUSH DI] + * MOV BP, SP + * - Third version: Stack variables + * [PUSH SI] + * [PUSH DI] + ****************************************************************************/ +/***************************************************************************** +/* checkStkVars - Checks for PUSH SI + * [PUSH DI] + * or PUSH DI + * [PUSH SI] + * In which case, the stack variable flags are set + ****************************************************************************/ +Int Idiom1::checkStkVars (iICODE pIcode) +{ + /* Look for PUSH SI */ + int si_matched=0; + int di_matched=0; + if(pIcode==m_end) + return 0; + if (pIcode->ic.ll.match(iPUSH,rSI)) + { + si_matched = 1; + ++pIcode; + if ((pIcode != m_end) && pIcode->ic.ll.match(iPUSH,rDI)) // Look for PUSH DI + di_matched = 1; + } + else if (pIcode->ic.ll.match(iPUSH,rDI)) + { + di_matched = 1; + ++pIcode; + if ((pIcode != m_end) && pIcode->ic.ll.match(iPUSH,rSI)) // Look for PUSH SI + si_matched = 1; + } + m_func->flg |= (si_matched ? SI_REGVAR : 0) | (di_matched ? DI_REGVAR : 0); + return si_matched+di_matched; +} +bool Idiom1::match(iICODE picode) +{ + uint8_t type = 0; /* type of variable: 1 = reg-var, 2 = local */ + byte regi; /* register of the MOV */ + if(picode==m_end) + return false; + Int n; + m_icodes.clear(); + m_min_off = 0; + /* PUSH BP as first instruction of procedure */ + if ( !(picode->ic.ll.flg & I) && picode->ic.ll.src.regi == rBP) + { + m_icodes.push_back( picode++ ); // insert iPUSH + if(picode==m_end) + return false; + /* MOV BP, SP as next instruction */ + if ( !picode->ic.ll.anyFlagSet(I | TARGET | CASE) && picode->ic.ll.match(iMOV ,rBP,rSP) ) + { + m_icodes.push_back( picode++ ); // insert iMOV + if(picode==m_end) + return false; + m_min_off = 2; + + /* Look for SUB SP, immed */ + if ( + picode->ic.ll.anyFlagSet(I | TARGET | CASE) && picode->ic.ll.match(iSUB,rSP) + ) + { + m_icodes.push_back( picode++ ); // insert iSUB + int n = checkStkVars (picode); // find iPUSH si [iPUSH di] + for(int i=0; i 0) + { + for(int i=0; iic.ll.anyFlagSet(I | TARGET | CASE) && + picode->ic.ll.match(iMOV,rBP,rSP)) + { + m_icodes.push_back(picode); + m_min_off = 2 + (n * 2); + } + else + return false; // Cristina: check this please! + } + else + return false; // Cristina: check this please! + } + } + else // push di [push si] / push si [push di] + { + n = checkStkVars (picode); + for(int i=0; iinvalidate(); + } + m_func->flg |= PROC_IS_HLL; + if(0!=m_min_off) + m_func->args.m_minOff = m_min_off; + return m_icodes.size(); +}