extracted FunctionCfg as it's own class

This commit is contained in:
Artur K 2012-07-15 16:52:59 +02:00
parent 5087a051b5
commit c19231a1bd
28 changed files with 315 additions and 291 deletions

View File

@ -3,7 +3,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
OPTION(dcc_build_tests "Enable unit tests." OFF)
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS -D__UNIX__ -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS)
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS -D__UNIX__ -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS)
IF(CMAKE_BUILD_TOOL MATCHES "(msdev|devenv|nmake)")
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS -D__UNIX__ -D_CRT_NONSTDC_NO_DEPRECATE)
ADD_DEFINITIONS(/W4)
@ -14,7 +14,7 @@ ELSE()
ENDIF()
SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMakeScripts;${CMAKE_MODULE_PATH})
include(cotire)
FIND_PACKAGE(LLVM)
FIND_PACKAGE(Boost)
IF(dcc_build_tests)
@ -59,6 +59,7 @@ set(dcc_LIB_SOURCES
src/idioms/shift_idioms.cpp
src/idioms/xor_idioms.cpp
src/locident.cpp
src/liveness_set.cpp
src/parser.cpp
src/perfhlib.cpp
src/procs.cpp
@ -110,11 +111,11 @@ SOURCE_GROUP(Source FILES ${dcc_SOURCES})
SOURCE_GROUP(Headers FILES ${dcc_HEADERS})
ADD_LIBRARY(dcc_lib STATIC ${dcc_LIB_SOURCES} ${dcc_HEADERS})
cotire(dcc_lib)
ADD_EXECUTABLE(dcc_original ${dcc_SOURCES} ${dcc_HEADERS})
ADD_DEPENDENCIES(dcc_original dcc_lib)
TARGET_LINK_LIBRARIES(dcc_original dcc_lib disasm_s ${REQ_LLVM_LIBRARIES})
if(dcc_build_tests)
ADD_SUBDIRECTORY(src)
endif()

View File

@ -1,6 +1,6 @@
#!/bin/bash
cd bld
make -j5
cd ..
#cd bld
#make -j5
#cd ..
./test_use_base.sh
./regression_tester.rb ./bld/dcc_original -s -c 2>stderr >stdout; diff tests/prev/ tests/outputs/
./regression_tester.rb ./dcc_original -s -c 2>stderr >stdout; diff tests/prev/ tests/outputs/

View File

@ -1,3 +1,3 @@
#!/bin/bash
./test_use_all.sh
./regression_tester.rb ./bld/dcc_original -s -c 2>stderr >stdout; diff tests/prev/ tests/outputs/
./regression_tester.rb ./dcc_original -s -c 2>stderr >stdout; diff tests/prev/ tests/outputs/

View File

@ -5,7 +5,7 @@
#include <string>
#include <llvm/ADT/ilist.h>
#include <llvm/ADT/ilist_node.h>
#include <boost/range.hpp>
#include <boost/range/iterator_range.hpp>
#include "icode.h"
#include "types.h"
#include "graph.h"
@ -27,10 +27,9 @@ struct TYPEADR_TYPE
TYPEADR_TYPE(interval *v) : ip(0),BBptr(nullptr),intPtr(v)
{}
};
struct BB : public llvm::ilist_node<BB>
{
friend struct Function;
private:
BB(const BB&);
BB() : nodeType(0),traversed(DFS_NONE),
@ -46,6 +45,7 @@ private:
//friend class SymbolTableListTraits<BB, Function>;
typedef boost::iterator_range<iICODE> rCODE;
rCODE instructions;
rCODE &my_range() {return instructions;}
public:
struct ValidFunctor
@ -77,29 +77,25 @@ public:
interval *inInterval; /* Node's interval */
/* For derived sequence construction */
interval *correspInt; /* Corresponding interval in
* derived graph Gi-1 */
/* For live register analysis
* LiveIn(b) = LiveUse(b) U (LiveOut(b) - Def(b)) */
std::bitset<32> liveUse; /* LiveUse(b) */
std::bitset<32> def; /* Def(b) */
std::bitset<32> liveIn; /* LiveIn(b) */
std::bitset<32> liveOut; /* LiveOut(b) */
interval *correspInt; //!< Corresponding interval in derived graph Gi-1
// For live register analysis
// LiveIn(b) = LiveUse(b) U (LiveOut(b) - Def(b))
LivenessSet liveUse; /* LiveUse(b) */
LivenessSet def; /* Def(b) */
LivenessSet liveIn; /* LiveIn(b) */
LivenessSet liveOut; /* LiveOut(b) */
/* For structuring analysis */
int dfsFirstNum; /* DFS #: first visit of node */
int dfsLastNum; /* DFS #: last visit of node */
int immedDom; /* Immediate dominator (dfsLast
* index) */
int immedDom; /* Immediate dominator (dfsLast index) */
int ifFollow; /* node that ends the if */
int loopType; /* Type of loop (if any) */
int latchNode; /* latching node of the loop */
size_t numBackEdges; /* # of back edges */
int loopHead; /* most nested loop head to which this node belongs (dfsLast) */
int loopFollow; /* node that follows the loop */
int caseHead; /* most nested case to which this
node belongs (dfsLast) */
int caseHead; /* most nested case to which this node belongs (dfsLast) */
int caseTail; /* tail node for the case */
int index; /* Index, used in several ways */
@ -134,7 +130,7 @@ public:
void RemoveUnusedDefs(eReg regi, int defRegIdx, iICODE picode);
private:
bool FindUseBeforeDef(eReg regi, int defRegIdx, iICODE start_at);
void ProcessUseDefForFunc(eReg regi, int defRegIdx, iICODE picode);
void ProcessUseDefForFunc(eReg regi, int defRegIdx, ICODE &picode);
bool isEndOfPath(int latch_node_idx) const;
Function *Parent;

View File

@ -86,7 +86,26 @@ struct JumpTable
size_t entrySize() { return 2;}
void pruneEntries(uint16_t cs);
};
class FunctionCfg
{
std::list<BB*> m_listBB; /* Ptr. to BB list/CFG */
public:
typedef std::list<BB*>::iterator iterator;
iterator begin() {
return m_listBB.begin();
}
iterator end() {
return m_listBB.end();
}
BB * &front() { return m_listBB.front();}
void nodeSplitting()
{
/* Converts the irreducible graph G into an equivalent reducible one, by
* means of node splitting. */
fprintf(stderr,"Attempt to perform node splitting: NOT IMPLEMENTED\n");
}
void push_back(BB *v) { m_listBB.push_back(v);}
};
struct Function : public llvm::ilist_node<Function>
{
typedef llvm::iplist<BB> BasicBlockListType;
@ -109,6 +128,7 @@ public:
/* Icodes and control flow graph */
CIcodeRec Icode; /* Object with ICODE records */
FunctionCfg m_actual_cfg;
std::list<BB*> m_cfg; /* Ptr. to BB list/CFG */
std::vector<BB*> m_dfsLast;
std::list<BB*> heldBBs;
@ -118,8 +138,8 @@ public:
bool hasCase; /* Procedure has a case node */
/* For interprocedural live analysis */
std::bitset<32> liveIn; /* Registers used before defined */
std::bitset<32> liveOut; /* Registers that may be used in successors */
LivenessSet liveIn; /* Registers used before defined */
LivenessSet liveOut; /* Registers that may be used in successors */
bool liveAnal; /* Procedure has been analysed already */
Function(void */*ty*/=0) : procEntry(0),depth(0),flg(0),cbParam(0),m_cfg(0),m_dfsLast(0),numBBs(0),
@ -140,7 +160,7 @@ public:
void writeProcComments();
void lowLevelAnalysis();
void bindIcodeOff();
void dataFlow(std::bitset<32> &liveOut);
void dataFlow(LivenessSet &liveOut);
void compressCFG();
void highLevelGen();
void structure(derSeq *derivedG);
@ -166,7 +186,7 @@ public:
void displayStats();
void processHliCall(COND_EXPR *exp, iICODE picode);
void preprocessReturnDU(std::bitset<32> &_liveOut);
void preprocessReturnDU(LivenessSet &_liveOut);
protected:
void extractJumpTableRange(ICODE& pIcode, STATE *pstate, JumpTable &table);
bool followAllTableEntries(JumpTable &table, uint32_t cs, ICODE &pIcode, CALL_GRAPH *pcallGraph, STATE *pstate);
@ -190,7 +210,7 @@ protected:
void findExps();
void genDU1();
void elimCondCodes();
void liveRegAnalysis(std::bitset<32> &in_liveOut);
void liveRegAnalysis(LivenessSet &in_liveOut);
void findIdioms();
void propLong();
void genLiveKtes();

View File

@ -7,8 +7,8 @@
#pragma once
#include <cstring>
#include <list>
#include <boost/range/iterator_range.hpp>
#include "Enums.h"
#include <boost/range.hpp>
static const int operandSize=20;
/* The following definitions and types define the Conditional Expression
* attributed syntax tree, as defined by the following EBNF:

View File

@ -62,10 +62,10 @@ typedef struct { /* Command line option flags */
extern OPTION option; /* Command line options */
#include "BinaryImage.h"
extern std::bitset<32> duReg[30]; /* def/use bits for registers */
extern LivenessSet duReg[30]; /* def/use bits for registers */
//extern uint32_t duReg[30]; /* def/use bits for registers */
extern std::bitset<32> maskDuReg[30]; /* masks off du bits for regs */
extern LivenessSet maskDuReg[30]; /* masks off du bits for regs */
/* Registers used by icode instructions */

View File

@ -1,9 +1,10 @@
/****************************************************************************
* dcc project disassembler header
* (C) Mike van Emmerik
****************************************************************************/
/*
***************************************************************************
dcc project disassembler header
(C) Mike van Emmerik
***************************************************************************
*/
#pragma once
#include <sstream>
#include <fstream>
#include <vector>
#include "bundle.h"
@ -32,24 +33,6 @@ public:
#define EXT 0x100 /* "Extended" flag */
#ifdef __MSDOS__
#define KEY_DOWN EXT+'P'
#define KEY_LEFT EXT+'K'
#define KEY_UP EXT+'H'
#define KEY_RIGHT EXT+'M'
#define KEY_NPAGE EXT+'Q'
#define KEY_PPAGE EXT+'I'
#endif
#ifdef _CONSOLE
#define KEY_DOWN 0x50 /* Same as keypad scancodes */
#define KEY_LEFT 0x4B
#define KEY_UP 0x48
#define KEY_RIGHT 0x4D
#define KEY_NPAGE 0x51
#define KEY_PPAGE 0x49
#endif
#ifdef __UNIX__
#define KEY_DOWN EXT+'B'
#define KEY_LEFT EXT+'D'

View File

@ -1,8 +1,11 @@
/***************************************************************************
/*
=**************************************************************************
* File : dosdcc.h
* Purpose : include file for files decompiled by dcc.
* Copyright (c) Cristina Cifuentes - QUT - 1992
**************************************************************************/
*************************************************************************
*/
/* Type definitions for intel 80x86 architecture */
typedef unsigned int uint16_t; /* 16 bits */

View File

@ -1,10 +1,13 @@
/*****************************************************************************
/*
****************************************************************************
* CFG, BB and interval related definitions
* ( C ) Cristina Cifuentes
****************************************************************************/
****************************************************************************
*/
#pragma once
#include <stdint.h>
#include <list>
#include <vector>
struct Function;
/* Types of basic block nodes */
/* Real basic blocks: type defined according to their out-edges */
@ -55,6 +58,7 @@ enum eNodeHeaderType
#define ELSE 1 /* else edge */
/* Basic Block (BB) flags */
#define INVALID_BB 0x0001 /* BB is not valid any more */
#define IS_LATCH_NODE 0x0002 /* BB is the latching node of a loop */
@ -76,6 +80,7 @@ struct interval
currNode=nodes.end();
next=0;
}
void appendNodeInt(queue &pqH, BB *node);
};
@ -83,6 +88,7 @@ struct interval
struct derSeq_Entry
{
BB * Gi; /* Graph pointer */
std::list<interval *> m_intervals;
interval * Ii; /* Interval list of Gi */
derSeq_Entry() : Gi(0),Ii(0)
{

View File

@ -9,12 +9,9 @@
#include <bitset>
#include <llvm/ADT/ilist.h>
#include <llvm/ADT/ilist_node.h>
#include <llvm/CodeGen/MachineInstr.h>
#include <llvm/MC/MCInst.h>
#include <llvm/MC/MCAsmInfo.h>
#include <llvm/Value.h>
#include <llvm/Instruction.h>
#include <boost/range.hpp>
#include <boost/range/iterator_range.hpp>
#include "libdis.h"
#include "Enums.h"
#include "state.h" // State depends on INDEXBASE, but later need STATE
@ -32,7 +29,45 @@ typedef std::list<ICODE>::iterator iICODE;
typedef std::list<ICODE>::reverse_iterator riICODE;
typedef boost::iterator_range<iICODE> rCODE;
extern std::bitset<32> duReg[30];
struct LivenessSet : public std::bitset<32>
{
LivenessSet(int val=0) : std::bitset<32>(val) {}
LivenessSet(const LivenessSet &other)
{
(std::bitset<32> &)*this = (std::bitset<32> &)other;
}
LivenessSet(const std::bitset<32> &other)
{
(std::bitset<32> &)*this = other;
}
// LivenessSet(LivenessSet &&other) : LivenessSet()
// {
// swap(*this,other);
// }
LivenessSet &operator=(LivenessSet other)
{
swap(*this,other);
return *this;
}
friend void swap(LivenessSet& first, LivenessSet& second) // nothrow
{
// enable ADL (not necessary in our case, but good practice)
using std::swap;
// by swapping the members of two classes,
// the two classes are effectively swapped
swap((std::bitset<32> &)first, (std::bitset<32> &)second);
}
LivenessSet &setReg(int r);
LivenessSet &addReg(int r);
bool testReg(int r)
{
return test(r-rAX);
}
};
extern LivenessSet duReg[30];
/* uint8_t and uint16_t registers */
/* Def/use of flags - low 4 bits represent flags */
@ -350,14 +385,13 @@ public:
use.reset();
lastDefRegi.reset();
}
std::bitset<32> def; // For Registers: position in bitset is reg index
std::bitset<32> use; // For Registers: position in uint32_t is reg index
std::bitset<32> lastDefRegi;// Bit set if last def of this register in BB
LivenessSet def; // For Registers: position in bitset is reg index
LivenessSet use; // For Registers: position in uint32_t is reg index
LivenessSet lastDefRegi;// Bit set if last def of this register in BB
void addDefinedAndUsed(eReg r)
{
def |= duReg[r];
use |= duReg[r];
def.addReg(r);
use.addReg(r);
}
};
struct DU1

View File

@ -73,7 +73,7 @@ public:
ostr << regName(eReg(j))<<" ";
}
}
static eReg subRegH(eReg reg); //TODO: move these into machine_x86
static eReg subRegH(eReg reg);
static eReg subRegL(eReg reg);
static bool isMemOff(eReg r);

View File

@ -3,10 +3,7 @@
hashing functions
* (C) Mike van Emmerik
*/
//#define bool unsigned char
#define uint8_t unsigned char
#define uint16_t unsigned short
#include <stdint.h>
/* Prototypes */
void hashCleanup(void); /* Frees memory allocated by hashParams() */

View File

@ -36,7 +36,7 @@ BB *BB::Create(const rCODE &r,uint8_t _nodeType, Function *parent)
//setInBB should automatically handle if our range is empty
parent->Icode.SetInBB(pnewBB->instructions, pnewBB);
parent->heldBBs.push_back(pnewBB);
parent->m_cfg.push_back(pnewBB);
parent->m_actual_cfg.push_back(pnewBB);
pnewBB->Parent = parent;
}
@ -127,13 +127,11 @@ void BB::displayDfs()
pb.BBptr->displayDfs();
}
}
/* Recursive procedure that writes the code for the given procedure, pointed
* to by pBB.
* Parameters: pBB: pointer to the cfg.
* Icode: pointer to the Icode array for the cfg graph of the
* current procedure.
* indLevel: indentation level - used for formatting.
* numLoc: last # assigned to local variables */
/** Recursive procedure that writes the code for the given procedure, pointed
to by pBB.
\param indLevel indentation level - used for formatting.
\param numLoc: last # assigned to local variables
*/
ICODE* BB::writeLoopHeader(int &indLevel, Function* pProc, int *numLoc, BB *&latch, boolT &repCond)
{
latch = pProc->m_dfsLast[this->latchNode];
@ -177,6 +175,7 @@ ICODE* BB::writeLoopHeader(int &indLevel, Function* pProc, int *numLoc, BB *&lat
case ENDLESS_TYPE:
ostr << "\n"<<indentStr(indLevel)<<"for (;;) {\n";
picode = &latch->back();
}
cCode.appendCode(ostr.str());
stats.numHLIcode += 1;
@ -391,16 +390,16 @@ void BB::writeBB(std::ostream &ostr,int lev, Function * pProc, int *numLoc)
iICODE BB::begin()
{
return instructions.begin();//range_start;
return instructions.begin();
}
iICODE BB::end() const
{
return instructions.end();//range_end
return instructions.end();
}
ICODE &BB::back()
{
return instructions.back();//*rbegin();
return instructions.back();
}
size_t BB::size()
@ -411,7 +410,7 @@ size_t BB::size()
ICODE &BB::front()
{
return instructions.front();//*begin();
return instructions.front();
}
riICODE BB::rbegin()

View File

@ -43,15 +43,14 @@ void ICODE::setRegDU (eReg regi, operDu du_in)
switch (du_in)
{
case eDEF:
du.def |= duReg[regi];
du.def.addReg(regi);
du1.numRegsDef++;
break;
case eUSE:
du.use |= duReg[regi];
du.use.addReg(regi);
break;
case USE_DEF:
du.def |= duReg[regi];
du.use |= duReg[regi];
du.addDefinedAndUsed(regi);
du1.numRegsDef++;
break;
case NONE: /* do nothing */

View File

@ -266,7 +266,7 @@ void Function::codeGen (std::ostream &fs)
}
else /* generate C */
{
m_cfg.front()->writeCode (1, this, &numLoc, MAX, UN_INIT);
m_actual_cfg.front()->writeCode (1, this, &numLoc, MAX, UN_INIT);
}
cCode.appendCode( "}\n\n");

View File

@ -337,8 +337,7 @@ void SetupLibCheck(void)
PatLen, /* The length of the pattern to be hashed */
256, /* The character set of the pattern (0-FF) */
0, /* Minimum pattern character value */
numVert); /* Specifies c, the sparseness of the graph.
See Czech, Havas and Majewski for details */
numVert); /* Specifies c, the sparseness of the graph. See Czech, Havas and Majewski for details */
T1base = g_pattern_hasher.readT1();
T2base = g_pattern_hasher.readT2();
g = g_pattern_hasher.readG();
@ -462,8 +461,7 @@ bool LibCheck(Function & pProc)
//memmove(pat, &prog.Image[fileOffset], PATLEN);
fixWildCards(pat); /* Fix wild cards in the copy */
h = g_pattern_hasher.hash(pat); /* Hash the found proc */
/* We always have to compare keys, because the hash function will
always return a valid index */
/* We always have to compare keys, because the hash function will always return a valid index */
if (memcmp(ht[h].htPat, pat, PATLEN) == 0)
{
/* We have a match. Save the name, if not already set */
@ -494,13 +492,13 @@ bool LibCheck(Function & pProc)
pProc.flg |= PROC_IS_FUNC;
switch (pProc.retVal.type) {
case TYPE_LONG_SIGN: case TYPE_LONG_UNSIGN:
pProc.liveOut = duReg[rDX] | duReg[rAX];
pProc.liveOut.setReg(rDX) |= duReg[rAX];
break;
case TYPE_WORD_SIGN: case TYPE_WORD_UNSIGN:
pProc.liveOut = duReg[rAX];
pProc.liveOut.setReg(rAX);
break;
case TYPE_BYTE_SIGN: case TYPE_BYTE_UNSIGN:
pProc.liveOut = duReg[rAL];
pProc.liveOut.setReg(rAL);
break;
default:
fprintf(stderr,"Unknown retval type %d in LibCheck\n",pProc.retVal.type);

View File

@ -45,7 +45,6 @@ void ExpStack::init()
expStk.clear();
}
/* Pushes the given expression onto the local stack (expStk). */
void ExpStack::push(COND_EXPR *expr)
{
@ -129,15 +128,7 @@ void Function::elimCondCodes ()
auto valid_reversed_bbs = (m_dfsLast | reversed | filtered(BB::ValidFunctor()) );
for( BB * pBB : valid_reversed_bbs)
{
// for (size_t i = 0; i < numBBs; i++)
// {
// pBB = m_dfsLast[i];
// if (pBB->flg & INVALID_BB)
// continue; /* Do not process invalid BBs */
// auto v(pBB | boost::adaptors::reversed);
// for (const ICODE &useAt : v)
// {}
//auto reversed_instructions = pBB->range() | reversed;
for (useAt = pBB->rbegin(); useAt != pBB->rend(); useAt++)
{
llIcode useAtOp = llIcode(useAt->ll()->getOpcode());
@ -234,7 +225,6 @@ void Function::elimCondCodes ()
else if (defAt == pBB->rend())
{
reportError(DEF_NOT_FOUND,useAtOp);
//fatalError (DEF_NOT_FOUND, Icode.getOpcode(useAt-1));
}
}
}
@ -250,7 +240,7 @@ void Function::elimCondCodes ()
void Function::genLiveKtes ()
{
BB * pbb;
bitset<32> liveUse, def;
LivenessSet liveUse, def;
for (size_t i = 0; i < numBBs; i++)
{
@ -276,15 +266,15 @@ void Function::genLiveKtes ()
/* Generates the liveIn() and liveOut() sets for each basic block via an
* iterative approach.
* Propagates register usage information to the procedure call. */
void Function::liveRegAnalysis (std::bitset<32> &in_liveOut)
void Function::liveRegAnalysis (LivenessSet &in_liveOut)
{
using namespace boost::adaptors;
using namespace boost::assign;
BB * pbb=0; /* pointer to current basic block */
//BB * pbb=0; /* pointer to current basic block */
Function * pcallee; /* invoked subroutine */
//ICODE *ticode /* icode that invokes a subroutine */
;
std::bitset<32> prevLiveOut, /* previous live out */
LivenessSet prevLiveOut, /* previous live out */
prevLiveIn; /* previous live in */
boolT change; /* is there change in the live sets?*/
@ -297,9 +287,8 @@ void Function::liveRegAnalysis (std::bitset<32> &in_liveOut)
/* Process nodes in reverse postorder order */
change = false;
auto valid_reversed_bbs = (m_dfsLast | reversed | filtered(BB::ValidFunctor()) );
for( BB * _pbb : valid_reversed_bbs)
for( BB * pbb : valid_reversed_bbs) // for each valid pbb in reversed dfs order
{
pbb = _pbb;//*iBB;//m_dfsLast[i-1];
/* Get current liveIn() and liveOut() sets */
prevLiveIn = pbb->liveIn;
@ -349,10 +338,10 @@ void Function::liveRegAnalysis (std::bitset<32> &in_liveOut)
)
pbb->liveOut = pcallee->liveOut;
else
pbb->liveOut = 0;
pbb->liveOut.reset();
}
if ((! (pcallee->flg & PROC_ISLIB)) || (pbb->liveOut != 0))
if ((! (pcallee->flg & PROC_ISLIB)) || ( pbb->liveOut.any() ))
{
switch (pcallee->retVal.type) {
case TYPE_LONG_SIGN: case TYPE_LONG_UNSIGN:
@ -375,28 +364,28 @@ void Function::liveRegAnalysis (std::bitset<32> &in_liveOut)
}
/* liveIn(b) = liveUse(b) U (liveOut(b) - def(b) */
pbb->liveIn = pbb->liveUse | (pbb->liveOut & ~pbb->def);
pbb->liveIn = LivenessSet(pbb->liveUse | (pbb->liveOut & ~pbb->def));
/* Check if live sets have been modified */
if ((prevLiveIn != pbb->liveIn) || (prevLiveOut != pbb->liveOut))
change = true;
}
}
BB *pbb = m_dfsLast.front();
/* Propagate liveIn(b) to procedure header */
if (pbb->liveIn != 0) /* uses registers */
if (pbb->liveIn.any()) /* uses registers */
liveIn = pbb->liveIn;
/* Remove any references to register variables */
if (flg & SI_REGVAR)
{
liveIn &= maskDuReg[rSI];
pbb->liveIn &= maskDuReg[rSI];
liveIn.set(rSI,0);
pbb->liveIn.set(rSI,0);
}
if (flg & DI_REGVAR)
{
liveIn &= maskDuReg[rDI];
pbb->liveIn &= maskDuReg[rDI];
liveIn.set(rDI,0);
pbb->liveIn.set(rDI,0);
}
}
@ -434,13 +423,13 @@ bool BB::FindUseBeforeDef(eReg regi, int defRegIdx, iICODE start_at)
/* Check if last definition of this register */
if ((not (ticode->du.def & duReg[regi]).any()) and (liveOut & duReg[regi]).any())
start_at->du.lastDefRegi |= duReg[regi];
start_at->du.lastDefRegi.addReg(regi);
}
else /* only 1 instruction in this basic block */
{
/* Check if last definition of this register */
if ((liveOut & duReg[regi]).any())
start_at->du.lastDefRegi |= duReg[regi];
start_at->du.lastDefRegi.addReg(regi);
}
return false;
}
@ -448,10 +437,10 @@ bool BB::FindUseBeforeDef(eReg regi, int defRegIdx, iICODE start_at)
* that are functions. The target icode is in the
* next basic block (unoptimized code) or somewhere else
* on optimized code. */
void BB::ProcessUseDefForFunc(eReg regi, int defRegIdx, iICODE picode)
void BB::ProcessUseDefForFunc(eReg regi, int defRegIdx, ICODE &picode)
{
if ((picode->hl()->opcode == HLI_CALL) &&
(picode->hl()->call.proc->flg & PROC_IS_FUNC))
if ((picode.hl()->opcode == HLI_CALL) &&
(picode.hl()->call.proc->flg & PROC_IS_FUNC))
{
BB *tbb = this->edges[0].BBptr;
auto target_instructions = tbb->instructions | filtered(ICODE::select_high_level);
@ -459,7 +448,7 @@ void BB::ProcessUseDefForFunc(eReg regi, int defRegIdx, iICODE picode)
{
/* if used, get icode index */
if ((iter->du.use & duReg[regi]).any())
picode->du1.recordUse(defRegIdx,iter.base());
picode.du1.recordUse(defRegIdx,iter.base());
/* if defined, stop finding uses for this reg */
if ((iter->du.def & duReg[regi]).any())
break;
@ -468,8 +457,8 @@ void BB::ProcessUseDefForFunc(eReg regi, int defRegIdx, iICODE picode)
/* if not used in this basic block, check if the
* register is live out, if so, make it the last
* definition of this register */
if ( picode->du1.used(defRegIdx) && (tbb->liveOut & duReg[regi]).any())
picode->du.lastDefRegi |= duReg[regi];
if ( picode.du1.used(defRegIdx) && (tbb->liveOut & duReg[regi]).any())
picode.du.lastDefRegi.addReg(regi);
}
}
@ -502,7 +491,7 @@ void BB::RemoveUnusedDefs(eReg regi, int defRegIdx, iICODE picode)
}
}
else /* liveOut */
picode->du.lastDefRegi |= duReg[regi];
picode->du.lastDefRegi.addReg(regi);
}
}
@ -529,7 +518,7 @@ void BB::genDU1()
if(FindUseBeforeDef(regi,defRegIdx, picode.base()))
continue;
ProcessUseDefForFunc(regi, defRegIdx,picode.base());
ProcessUseDefForFunc(regi, defRegIdx,*picode);
RemoveUnusedDefs(regi, defRegIdx, picode.base());
defRegIdx++;
@ -857,8 +846,6 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
auto valid_and_highlevel = instructions | filtered(ICODE::TypeAndValidFilter<HIGH_LEVEL>());
for (auto picode = valid_and_highlevel.begin(); picode != valid_and_highlevel.end(); picode++)
{
// if ((picode->type != HIGH_LEVEL) || ( ! picode->valid() ))
// continue;
HLTYPE &_icHl(*picode->hl());
numHlIcodes++;
if (picode->du1.numRegsDef == 1) /* uint8_t/uint16_t regs */
@ -1137,25 +1124,25 @@ void Function::findExps()
}
}
void Function::preprocessReturnDU(std::bitset<32> &_liveOut)
void Function::preprocessReturnDU(LivenessSet &_liveOut)
{
if (_liveOut.any())
{
// int idx;
bool isAx, isBx, isCx, isDx;
flg |= PROC_IS_FUNC;
isAx = _liveOut.test(rAX - rAX);
isBx = _liveOut.test(rBX - rAX);
isCx = _liveOut.test(rCX - rAX);
isDx = _liveOut.test(rDX - rAX);
bool isAL = !isAx && _liveOut.test(rAL - rAX);
bool isAH = !isAx && _liveOut.test(rAH - rAX);
bool isBL = !isBx && _liveOut.test(rBL - rAX);
bool isBH = !isBx && _liveOut.test(rBH - rAX);
bool isCL = !isCx && _liveOut.test(rCL - rAX);
bool isCH = !isCx && _liveOut.test(rCH - rAX);
bool isDL = !isDx && _liveOut.test(rDL - rAX);
bool isDH = !isDx && _liveOut.test(rDH - rAX);
isAx = _liveOut.testReg(rAX);
isBx = _liveOut.testReg(rBX);
isCx = _liveOut.testReg(rCX);
isDx = _liveOut.testReg(rDX);
bool isAL = !isAx && _liveOut.testReg(rAL);
bool isAH = !isAx && _liveOut.testReg(rAH);
bool isBL = !isBx && _liveOut.testReg(rBL);
bool isBH = !isBx && _liveOut.testReg(rBH);
bool isCL = !isCx && _liveOut.testReg(rCL);
bool isCH = !isCx && _liveOut.testReg(rCH);
bool isDL = !isDx && _liveOut.testReg(rDL);
bool isDH = !isDx && _liveOut.testReg(rDH);
if(isAL && isAH)
{
isAx = true;
@ -1217,17 +1204,17 @@ void Function::preprocessReturnDU(std::bitset<32> &_liveOut)
}
}
}
/** Invokes procedures related with data flow analysis. Works on a procedure
* at a time basis.
* Note: indirect recursion in liveRegAnalysis is possible. */
void Function::dataFlow(std::bitset<32> &_liveOut)
/** Invokes procedures related with data flow analysis.
* Works on a procedure at a time basis.
\note indirect recursion in liveRegAnalysis is possible. */
void Function::dataFlow(LivenessSet &_liveOut)
{
/* Remove references to register variables */
if (flg & SI_REGVAR)
_liveOut &= maskDuReg[rSI];
_liveOut.set(rSI,0);
if (flg & DI_REGVAR)
_liveOut &= maskDuReg[rDI];
_liveOut.set(rDI,0);
/* Function - return value register(s) */
preprocessReturnDU(_liveOut);

View File

@ -3,10 +3,11 @@
* Loads a program into simulated main memory and builds the procedure list.
* (C) Cristina Cifuentes
****************************************************************************/
#define __STDC_FORMAT_MACROS
#include "dcc.h"
#include "disassem.h"
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>

View File

@ -35,7 +35,7 @@ void Function::createCFG()
* 5) Repeated string instructions
* 6) End of procedure
*/
int i;
BB * psBB;
BB * pBB;
iICODE pIcode = Icode.begin();
@ -209,7 +209,7 @@ void Function::compressCFG()
/* First pass over BB list removes redundant jumps of the form
* (Un)Conditional -> Unconditional jump */
for (BB *pBB : m_cfg)
for (BB *pBB : m_actual_cfg) //m_cfg
{
if(pBB->inEdges.empty() || (pBB->nodeType != ONE_BRANCH && pBB->nodeType != TWO_BRANCH))
continue;
@ -231,18 +231,17 @@ void Function::compressCFG()
/* Next is a depth-first traversal merging any FALL_NODE or
* ONE_BRANCH that fall through to a node with that as their only
* in-edge. */
m_cfg.front()->mergeFallThrough(Icode);
m_actual_cfg.front()->mergeFallThrough(Icode);
/* Remove redundant BBs created by the above compressions
* and allocate in-edge arrays as required. */
stats.numBBaft = stats.numBBbef;
for(auto iter=m_cfg.begin(); iter!=m_cfg.end(); ++iter)
bool entry_node=true;
for(BB *pBB : m_actual_cfg)
{
BB * pBB = *iter;
if (pBB->inEdges.empty())
{
if (iter == m_cfg.begin()) /* Init it misses out on */
if (entry_node) /* Init it misses out on */
pBB->index = UN_INIT;
else
{
@ -254,6 +253,7 @@ void Function::compressCFG()
{
pBB->inEdgeCount = pBB->inEdges.size();
}
entry_node=false;
}
/* Allocate storage for dfsLast[] array */
@ -262,7 +262,7 @@ void Function::compressCFG()
/* Now do a dfs numbering traversal and fill in the inEdges[] array */
last = numBBs - 1;
m_cfg.front()->dfsNumbering(m_dfsLast, &first, &last);
m_actual_cfg.front()->dfsNumbering(m_dfsLast, &first, &last);
}

View File

@ -10,13 +10,23 @@
#include <sstream>
#include "dcc.h"
using namespace std;
#define ICODE_DELTA 25
/* Masks off bits set by duReg[] */
std::bitset<32> maskDuReg[] = { 0x00,
0xFEEFFE, 0xFDDFFD, 0xFBB00B, 0xF77007, /* uint16_t regs */
0xFFFFEF, 0xFFFFDF, 0xFFFFBF, 0xFFFF7F,
0xFFFEFF, 0xFFFDFF, 0xFFFBFF, 0xFFF7FF, /* seg regs */
LivenessSet maskDuReg[] = { 0x00,
/* uint16_t regs */
0xFEEFFE, //rAX
0xFDDFFD, //rCX
0xFBB00B, //rDX
0xF77007, //rBX
0xFFFFEF, //rSP
0xFFFFDF, //rBP
0xFFFFBF, //rSI
0xFFFF7F, //rDI
0xFFFEFF,
0xFFFDFF,
0xFFFBFF,
0xFFF7FF, /* seg regs */
0xFFEFFF, 0xFFDFFF, 0xFFBFFF, 0xFF7FFF, /* uint8_t regs */
0xFEFFFF, 0xFDFFFF, 0xFBFFFF, 0xF7FFFF,
0xEFFFFF, /* tmp reg */

View File

@ -2,15 +2,12 @@
// (C) 1997 Mike Van Emmerik
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include "dcc.h"
#include "types.h" // Common types like uint8_t, etc
#include "ast.h" // Some icode types depend on these
#include "icode.h"
#define ICODE_DELTA 25 // Amount to allocate for new chunk
ICODE::TypeFilter<HIGH_LEVEL> ICODE::select_high_level;
ICODE::TypeAndValidFilter<HIGH_LEVEL> ICODE::select_valid_high_level;
@ -31,10 +28,8 @@ ICODE * CIcodeRec::addIcode(ICODE *pIcode)
void CIcodeRec::SetInBB(rCODE &rang, BB *pnewBB)
{
for(ICODE &ic : rang)
{
ic.setParent(pnewBB);
}
}
/* labelSrchRepl - Searches the icodes for instruction with label = target, and
replaces *pIndex with an icode index */

View File

@ -16,13 +16,11 @@ bool LONGID_TYPE::srcDstRegMatch(iICODE a, iICODE b) const
ID::ID() : type(TYPE_UNKNOWN),illegal(false),loc(STK_FRAME),hasMacro(false)
{
name[0]=0;
macro[0]=0;
memset(&id,0,sizeof(id));
}
ID::ID(hlType t, frameType f) : type(t),illegal(false),hasMacro(false)
{
name[0]=0;
macro[0]=0;
memset(&id,0,sizeof(id));
loc=f;
@ -273,7 +271,7 @@ int LOCAL_ID::newLongStk(hlType t, int offH, int offL)
* number in an expression record. */
int LOCAL_ID::newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix,operDu du, LLInst &atOffset)
{
size_t idx;
size_t idx = ~0; //WARNING: clients of this method might propagate this bogus value!
const LLOperand *pmH, *pmL;
LLInst &p_ll(*pIcode->ll());
if (f == LOW_FIRST)

View File

@ -2,7 +2,7 @@
* dcc project procedure list builder
* (C) Cristina Cifuentes, Mike van Emmerik, Jeff Ledermann
****************************************************************************/
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#include <string.h>
#include <stdlib.h> /* For exit() */
@ -886,7 +886,7 @@ static void setBits(int16_t type, uint32_t start, uint32_t len)
}
/* DU bit definitions for each reg value - including index registers */
std::bitset<32> duReg[] = { 0x00,
LivenessSet duReg[] = { 0x00,
//AH AL . . AX, BH
0x11001, 0x22002, 0x44004, 0x88008, /* uint16_t regs */
0x10, 0x20, 0x40, 0x80,
@ -1066,7 +1066,7 @@ void Function::process_operands(ICODE & pIcode, STATE * pstate)
case iDIV: case iIDIV:
use(SRC, pIcode, this, pstate, cb);
if (cb == 1)
pIcode.du.use |= duReg[rTMP];
pIcode.du.use.addReg(rTMP);
break;
case iMUL: case iIMUL:
@ -1076,12 +1076,12 @@ void Function::process_operands(ICODE & pIcode, STATE * pstate)
use (DST, pIcode, this, pstate, cb);
if (cb == 1)
{
pIcode.du.def |= duReg[rAX];
pIcode.du.def.addReg(rAX);
pIcode.du1.numRegsDef++;
}
else
{
pIcode.du.def |= (duReg[rAX] | duReg[rDX]);
pIcode.du.def.addReg(rAX).addReg(rDX);
pIcode.du1.numRegsDef += 2;
}
}
@ -1093,15 +1093,15 @@ void Function::process_operands(ICODE & pIcode, STATE * pstate)
cb = pIcode.ll()->testFlags(SRC_B) ? 1 : 2;
if (cb == 1) /* uint8_t */
{
pIcode.du.def |= duReg[rAX];
pIcode.du.def.addReg(rAX);
pIcode.du1.numRegsDef++;
pIcode.du.use |= duReg[rAL];
pIcode.du.use.addReg(rAL);
}
else /* uint16_t */
{
pIcode.du.def |= (duReg[rDX] | duReg[rAX]);
pIcode.du.def.addReg(rDX).addReg(rAX);
pIcode.du1.numRegsDef += 2;
pIcode.du.use |= duReg[rAX];
pIcode.du.use.addReg(rAX);
}
break;
@ -1121,7 +1121,7 @@ void Function::process_operands(ICODE & pIcode, STATE * pstate)
break;
case iLDS: case iLES:
pIcode.du.def |= duReg[(pIcode.ll()->getOpcode() == iLDS) ? rDS : rES];
pIcode.du.def.addReg(((pIcode.ll()->getOpcode() == iLDS) ? rDS : rES));
pIcode.du1.numRegsDef++;
cb = 4;
case iMOV:
@ -1147,10 +1147,10 @@ void Function::process_operands(ICODE & pIcode, STATE * pstate)
break;
case iLOOP: case iLOOPE: case iLOOPNE:
pIcode.du.def |= duReg[rCX];
pIcode.du.def.addReg(rCX);
pIcode.du1.numRegsDef++;
case iJCXZ:
pIcode.du.use |= duReg[rCX];
pIcode.du.use.addReg(rCX);
break;
case iREPNE_CMPS: case iREPE_CMPS: case iREP_MOVS:
@ -1160,22 +1160,22 @@ void Function::process_operands(ICODE & pIcode, STATE * pstate)
pIcode.du.addDefinedAndUsed(rSI);
pIcode.du.addDefinedAndUsed(rDI);
pIcode.du1.numRegsDef += 2;
pIcode.du.use |= duReg[rES] | duReg[sseg];
pIcode.du.use.addReg(rES).addReg(sseg);
break;
case iREPNE_SCAS: case iREPE_SCAS: case iREP_STOS: case iREP_INS:
pIcode.du.addDefinedAndUsed(rCX);
pIcode.du1.numRegsDef++;
case iSCAS: case iSTOS: case iINS:
pIcode.du.def |= duReg[rDI];
pIcode.du.def.addReg(rDI);
pIcode.du1.numRegsDef++;
if (pIcode.ll()->getOpcode() == iREP_INS || pIcode.ll()->getOpcode()== iINS)
{
pIcode.du.use |= duReg[rDI] | duReg[rES] | duReg[rDX];
pIcode.du.use.addReg(rDI).addReg(rES).addReg(rDX);
}
else
{
pIcode.du.use |= duReg[rDI] | duReg[rES] | duReg[(cb == 2)? rAX: rAL];
pIcode.du.use.addReg(rDI).addReg(rES).addReg((cb == 2)? rAX: rAL);
}
break;

View File

@ -5,10 +5,10 @@
********************************************************************/
#include <algorithm>
#include <cassert>
#include <cstdio>
#include <cstring>
#include <stdint.h>
#include "dcc.h"
#include <stdio.h>
#include <malloc.h> /* For free() */
#include <string.h>
static int numInt; /* Number of intervals */
@ -66,16 +66,16 @@ BB *interval::firstOfInt ()
* node->inInterval.
* Note: nodes are added to the interval list in interval order (which
* topsorts the dominance relation). */
static void appendNodeInt (queue &pqH, BB *node, interval *pI)
void interval::appendNodeInt(queue &pqH, BB *node)
{
queue::iterator pq; /* Pointer to current node of the list */
/* Append node if it is not already in the interval list */
pq = appendQueue (pI->nodes, node);
pq = appendQueue (nodes, node);
/* Update currNode if necessary */
if (pI->currNode == pI->nodes.end())
pI->currNode = pq;
if (currNode == nodes.end())
currNode = pq;
/* Check header list for occurrence of node, if found, remove it
* and decrement number of out-edges from this interval. */
@ -84,12 +84,12 @@ static void appendNodeInt (queue &pqH, BB *node, interval *pI)
auto found_iter=std::find(pqH.begin(),pqH.end(),node);
if(found_iter!=pqH.end())
{
pI->numOutEdges -= (uint8_t)(*found_iter)->inEdges.size() - 1;
numOutEdges -= (uint8_t)(*found_iter)->inEdges.size() - 1;
pqH.erase(found_iter);
}
}
/* Update interval header information for this basic block */
node->inInterval = pI;
node->inInterval = this;
}
@ -103,7 +103,6 @@ void derSeq_Entry::findIntervals (Function *c)
BB *h, /* Node being processed */
*header, /* Current interval's header node */
*succ; /* Successor basic block */
//int i; /* Counter */
queue H; /* Queue of possible header nodes */
boolT first = true; /* First pass through the loop */
@ -118,8 +117,11 @@ void derSeq_Entry::findIntervals (Function *c)
pI = new interval;
pI->numInt = (uint8_t)numInt++;
if (first) /* ^ to first interval */
{
Ii = J = pI;
appendNodeInt (H, header, pI); /* pI(header) = {header} */
m_intervals.push_back(pI);
}
pI->appendNodeInt (H, header); /* pI(header) = {header} */
/* Process all nodes in the current interval list */
while ((h = pI->firstOfInt()) != NULL)
@ -134,7 +136,7 @@ void derSeq_Entry::findIntervals (Function *c)
{
succ->reachingInt = header;
if (succ->inEdgeCount == 0)
appendNodeInt (H, succ, pI);
pI->appendNodeInt (H, succ);
else if (! succ->beenOnH) /* out edge */
{
appendQueue (H, succ);
@ -148,7 +150,7 @@ void derSeq_Entry::findIntervals (Function *c)
if (succ->reachingInt == header || succ->inInterval == pI) /* same interval */
{
if (succ != header)
appendNodeInt (H, succ, pI);
pI->appendNodeInt (H, succ);
}
else /* out edge */
pI->numOutEdges++;
@ -161,6 +163,7 @@ void derSeq_Entry::findIntervals (Function *c)
/* Link interval I to list of intervals */
if (! first)
{
m_intervals.push_back(pI);
J->next = pI;
J = pI;
}
@ -333,13 +336,6 @@ uint8_t Function::findDerivedSeq (derSeq &derivedGi)
return true;
}
/* Converts the irreducible graph G into an equivalent reducible one, by
* means of node splitting. */
static void nodeSplitting (std::list<BB *> &/*G*/)
{
fprintf(stderr,"Attempt to perform node splitting: NOT IMPLEMENTED\n");
}
/* Displays the derived sequence and intervals of the graph G */
void derSeq::display()
{
@ -369,13 +365,13 @@ derSeq * Function::checkReducibility()
stats.nOrder = 1; /* nOrder(cfg) = 1 */
der_seq = new derSeq;
der_seq->resize(1);
der_seq->back().Gi = m_cfg.front();
der_seq->back().Gi = *m_actual_cfg.begin(); /*m_cfg.front()*/;
reducible = findDerivedSeq(*der_seq);
if (! reducible)
{
flg |= GRAPH_IRRED;
nodeSplitting (m_cfg);
m_actual_cfg.nodeSplitting();
}
return der_seq;
}

View File

@ -30,7 +30,7 @@
#define TABLESIZE 16 /* Number of entries added each expansion */
/* Probably has to be a power of 2 */
#define STRTABSIZE 256 /* Size string table is inc'd by */
#define NIL ((uint16_t)-1)
using namespace std;
static char *pStrTab; /* Pointer to the current string table */
static int strTabNext; /* Next free index into pStrTab */

View File

@ -60,7 +60,8 @@ void Function::controlFlowAnalysis()
if (option.verbose)
{
printf("\nDepth first traversal - Proc %s\n", name.c_str());
m_cfg.front()->displayDfs();
(*m_actual_cfg.begin())->displayDfs();
//m_cfg.front()->displayDfs();
}
/* Free storage occupied by this procedure */
@ -82,7 +83,7 @@ void udm(void)
/* Data flow analysis - eliminate condition codes, extraneous registers
* and intermediate instructions. Find expressions by forward
* substitution algorithm */
std::bitset<32> live_regs;
LivenessSet live_regs;
Project::get()->pProcList.front().dataFlow (live_regs);
/* Control flow analysis - structuring algorithm */
@ -98,7 +99,7 @@ void udm(void)
void Function::displayCFG()
{
printf("\nBasic Block List - Proc %s", name.c_str());
for (BB *pBB : m_cfg)
for (BB *pBB : /*m_cfg*/m_actual_cfg)
{
pBB->display();
}

View File

@ -3,4 +3,4 @@ cd bld
make -j5
cd ..
./test_use_base.sh
./valgrind_tester ./bld/dcc_original -s -c 2>stderr >stdout; diff tests/prev/ tests/outputs/
./valgrind_tester ./dcc_original -s -c 2>stderr >stdout; diff tests/prev/ tests/outputs/