Browse Source

Refactoring idioms into objects with match/action methods

Artur K 12 years ago
parent
commit
11ae65efba
5 changed files with 341 additions and 0 deletions
  1. 39 0
      include/epilogue_idioms.h
  2. 15 0
      include/idiom.h
  3. 16 0
      include/idiom1.h
  4. 139 0
      src/epilogue_idioms.cpp
  5. 132 0
      src/idiom1.cpp

+ 39 - 0
include/epilogue_idioms.h

@@ -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 - 0
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;
+};

+ 16 - 0
include/idiom1.h

@@ -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 - 0
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; 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 - 0
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<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();
+}