Refactoring idioms into objects with match/action methods
This commit is contained in:
39
include/epilogue_idioms.h
Normal file
39
include/epilogue_idioms.h
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "idiom.h"
|
||||||
|
#include "icode.h"
|
||||||
|
#include <deque>
|
||||||
|
struct EpilogIdiom : public Idiom
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
std::deque<iICODE> 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();
|
||||||
|
};
|
||||||
15
include/idiom.h
Normal file
15
include/idiom.h
Normal file
@@ -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;
|
||||||
|
};
|
||||||
16
include/idiom1.h
Normal file
16
include/idiom1.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "idiom.h"
|
||||||
|
struct Idiom1 : public Idiom
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
std::vector<iICODE> 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();
|
||||||
|
};
|
||||||
139
src/epilogue_idioms.cpp
Normal file
139
src/epilogue_idioms.cpp
Normal file
@@ -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; idx<m_icodes.size()-1; ++idx) // don't invalidate last entry
|
||||||
|
m_icodes[idx]->invalidate();
|
||||||
|
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; idx<m_icodes.size()-1; ++idx) // don't invalidate last entry
|
||||||
|
m_icodes[idx]->invalidate();
|
||||||
|
if(m_param_count)
|
||||||
|
{
|
||||||
|
m_func->cbParam = (int16)m_param_count;
|
||||||
|
m_func->flg |= CALL_PASCAL;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
132
src/idiom1.cpp
Normal file
132
src/idiom1.cpp
Normal file
@@ -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<n; ++i)
|
||||||
|
m_icodes.push_back(picode++); // insert
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PUSH SI
|
||||||
|
* [PUSH DI]
|
||||||
|
* MOV BP, SP */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int n = checkStkVars (picode);
|
||||||
|
if (n > 0)
|
||||||
|
{
|
||||||
|
for(int i=0; i<n; ++i)
|
||||||
|
m_icodes.push_back(picode++);
|
||||||
|
if(picode == m_end)
|
||||||
|
return false;
|
||||||
|
/* Look for MOV BP, SP */
|
||||||
|
if ( picode != m_end &&
|
||||||
|
!picode->ic.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; i<n; ++i)
|
||||||
|
m_icodes.push_back(picode++);
|
||||||
|
|
||||||
|
}
|
||||||
|
return !m_icodes.empty();
|
||||||
|
}
|
||||||
|
int Idiom1::action()
|
||||||
|
{
|
||||||
|
for(iICODE ic : m_icodes)
|
||||||
|
{
|
||||||
|
ic->invalidate();
|
||||||
|
}
|
||||||
|
m_func->flg |= PROC_IS_HLL;
|
||||||
|
if(0!=m_min_off)
|
||||||
|
m_func->args.m_minOff = m_min_off;
|
||||||
|
return m_icodes.size();
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user