extracted FunctionCfg as it's own class
This commit is contained in:
parent
5087a051b5
commit
c19231a1bd
@ -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()
|
||||
|
||||
@ -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/
|
||||
|
||||
@ -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/
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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,9 +138,9 @@ 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 */
|
||||
bool liveAnal; /* Procedure has been analysed already */
|
||||
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),
|
||||
hasCase(false),liveIn(0),liveOut(0),liveAnal(0)//,next(0),prev(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();
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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 */
|
||||
|
||||
|
||||
@ -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'
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -1,10 +1,13 @@
|
||||
/*****************************************************************************
|
||||
/*
|
||||
****************************************************************************
|
||||
* CFG, BB and interval related definitions
|
||||
* (C) Cristina Cifuentes
|
||||
****************************************************************************/
|
||||
* ( 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 */
|
||||
|
||||
@ -64,8 +68,8 @@ typedef std::list<BB *> queue;
|
||||
|
||||
struct interval
|
||||
{
|
||||
uint8_t numInt; /* # of the interval */
|
||||
uint8_t numOutEdges; /* Number of out edges */
|
||||
uint8_t numInt; /* # of the interval */
|
||||
uint8_t numOutEdges; /* Number of out edges */
|
||||
queue nodes; /* Nodes of the interval*/
|
||||
queue::iterator currNode; /* Current node */
|
||||
interval *next; /* Next interval */
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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() */
|
||||
|
||||
@ -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;
|
||||
@ -226,7 +225,7 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode,
|
||||
return;
|
||||
|
||||
/* Check type of loop/node and process code */
|
||||
if ( loopType) /* there is a loop */
|
||||
if ( loopType ) /* there is a loop */
|
||||
{
|
||||
assert(latch);
|
||||
if (this != latch) /* loop is over several bbs */
|
||||
@ -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()
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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);
|
||||
|
||||
211
src/dataflow.cpp
211
src/dataflow.cpp
@ -45,7 +45,6 @@ void ExpStack::init()
|
||||
expStk.clear();
|
||||
}
|
||||
|
||||
|
||||
/* Pushes the given expression onto the local stack (expStk). */
|
||||
void ExpStack::push(COND_EXPR *expr)
|
||||
{
|
||||
@ -114,7 +113,7 @@ static COND_EXPR *dstIdent (const LLInst & ll_insn, Function * pProc, iICODE i,
|
||||
/* Eliminates all condition codes and generates new hlIcode instructions */
|
||||
void Function::elimCondCodes ()
|
||||
{
|
||||
// int i;
|
||||
// int i;
|
||||
|
||||
uint8_t use; /* Used flags bit vector */
|
||||
uint8_t def; /* Defined flags bit vector */
|
||||
@ -125,19 +124,11 @@ void Function::elimCondCodes ()
|
||||
//BB * pBB; /* Pointer to BBs in dfs last ordering */
|
||||
riICODE useAt; /* Instruction that used flag */
|
||||
riICODE defAt; /* Instruction that defined flag */
|
||||
//lhs=rhs=_expr=0;
|
||||
//lhs=rhs=_expr=0;
|
||||
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 */
|
||||
Function * pcallee; /* invoked subroutine */
|
||||
//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,22 +338,22 @@ 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:
|
||||
ticode.du1.numRegsDef = 2;
|
||||
break;
|
||||
case TYPE_WORD_SIGN: case TYPE_WORD_UNSIGN:
|
||||
case TYPE_BYTE_SIGN: case TYPE_BYTE_UNSIGN:
|
||||
ticode.du1.numRegsDef = 1;
|
||||
break;
|
||||
default:
|
||||
ticode.du1.numRegsDef = 0;
|
||||
//fprintf(stderr,"Function::liveRegAnalysis : Unknown return type %d, assume 0\n",pcallee->retVal.type);
|
||||
case TYPE_LONG_SIGN: case TYPE_LONG_UNSIGN:
|
||||
ticode.du1.numRegsDef = 2;
|
||||
break;
|
||||
case TYPE_WORD_SIGN: case TYPE_WORD_UNSIGN:
|
||||
case TYPE_BYTE_SIGN: case TYPE_BYTE_UNSIGN:
|
||||
ticode.du1.numRegsDef = 1;
|
||||
break;
|
||||
default:
|
||||
ticode.du1.numRegsDef = 0;
|
||||
//fprintf(stderr,"Function::liveRegAnalysis : Unknown return type %d, assume 0\n",pcallee->retVal.type);
|
||||
} /*eos*/
|
||||
|
||||
/* Propagate def/use results to calling icode */
|
||||
@ -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++;
|
||||
@ -734,47 +723,47 @@ void LOCAL_ID::processTargetIcode(iICODE picode, int &numHlIcodes, iICODE ticode
|
||||
HLTYPE &t_hl(*ticode->hl());
|
||||
switch (t_hl.opcode)
|
||||
{
|
||||
case HLI_ASSIGN:
|
||||
if(isLong)
|
||||
{
|
||||
forwardSubsLong (p_hl.asgn.lhs->expr.ident.idNode.longIdx,
|
||||
p_hl.asgn.rhs, picode,ticode,
|
||||
&numHlIcodes);
|
||||
}
|
||||
else
|
||||
this->forwardSubs (p_hl.asgn.lhs, p_hl.asgn.rhs, picode, ticode, numHlIcodes);
|
||||
break;
|
||||
case HLI_ASSIGN:
|
||||
if(isLong)
|
||||
{
|
||||
forwardSubsLong (p_hl.asgn.lhs->expr.ident.idNode.longIdx,
|
||||
p_hl.asgn.rhs, picode,ticode,
|
||||
&numHlIcodes);
|
||||
}
|
||||
else
|
||||
this->forwardSubs (p_hl.asgn.lhs, p_hl.asgn.rhs, picode, ticode, numHlIcodes);
|
||||
break;
|
||||
|
||||
case HLI_JCOND: case HLI_PUSH: case HLI_RET:
|
||||
if(isLong)
|
||||
{
|
||||
res = COND_EXPR::insertSubTreeLongReg (
|
||||
p_hl.asgn.rhs,
|
||||
&t_hl.exp.v,
|
||||
p_hl.asgn.lhs->expr.ident.idNode.longIdx);
|
||||
}
|
||||
else
|
||||
{
|
||||
res = COND_EXPR::insertSubTreeReg (
|
||||
t_hl.exp.v,
|
||||
p_hl.asgn.rhs,
|
||||
id_arr[p_hl.asgn.lhs->expr.ident.idNode.regiIdx].id.regi,
|
||||
case HLI_JCOND: case HLI_PUSH: case HLI_RET:
|
||||
if(isLong)
|
||||
{
|
||||
res = COND_EXPR::insertSubTreeLongReg (
|
||||
p_hl.asgn.rhs,
|
||||
&t_hl.exp.v,
|
||||
p_hl.asgn.lhs->expr.ident.idNode.longIdx);
|
||||
}
|
||||
else
|
||||
{
|
||||
res = COND_EXPR::insertSubTreeReg (
|
||||
t_hl.exp.v,
|
||||
p_hl.asgn.rhs,
|
||||
id_arr[p_hl.asgn.lhs->expr.ident.idNode.regiIdx].id.regi,
|
||||
this);
|
||||
}
|
||||
if (res)
|
||||
{
|
||||
}
|
||||
if (res)
|
||||
{
|
||||
picode->invalidate();
|
||||
numHlIcodes--;
|
||||
}
|
||||
break;
|
||||
|
||||
case HLI_CALL: /* register arguments */
|
||||
newRegArg ( picode, ticode);
|
||||
picode->invalidate();
|
||||
numHlIcodes--;
|
||||
}
|
||||
break;
|
||||
|
||||
case HLI_CALL: /* register arguments */
|
||||
newRegArg ( picode, ticode);
|
||||
picode->invalidate();
|
||||
numHlIcodes--;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"unhandled LOCAL_ID::processTargetIcode opcode %d\n",t_hl.opcode);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"unhandled LOCAL_ID::processTargetIcode opcode %d\n",t_hl.opcode);
|
||||
|
||||
}
|
||||
}
|
||||
@ -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 */
|
||||
@ -910,7 +897,7 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
|
||||
res = COND_EXPR::insertSubTreeReg (ti_hl->exp.v,
|
||||
_exp,
|
||||
locals.id_arr[_icHl.expr()->expr.ident.idNode.regiIdx].id.regi,
|
||||
&locals);
|
||||
&locals);
|
||||
if (res)
|
||||
{
|
||||
picode->invalidate();
|
||||
@ -1060,7 +1047,7 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
|
||||
res = COND_EXPR::insertSubTreeLongReg (_exp,
|
||||
&ticode->hl()->exp.v,
|
||||
locals.newLongReg ( _retVal->type, _retVal->id.longId.h,
|
||||
_retVal->id.longId.l, picode.base()));
|
||||
_retVal->id.longId.l, picode.base()));
|
||||
if (res) /* was substituted */
|
||||
{
|
||||
picode->invalidate();
|
||||
@ -1125,11 +1112,11 @@ void Function::findExps()
|
||||
g_exp_stk.init();
|
||||
|
||||
/* Traverse tree in dfsLast order */
|
||||
// for (i = 0; i < numBBs; i++)
|
||||
// for (i = 0; i < numBBs; i++)
|
||||
for(BB *pbb : m_dfsLast)
|
||||
{
|
||||
/* Process one BB */
|
||||
// pbb = m_dfsLast[i];
|
||||
// pbb = m_dfsLast[i];
|
||||
if (not pbb->valid())
|
||||
continue;
|
||||
pbb->findBBExps( this->localId, this);
|
||||
@ -1137,25 +1124,25 @@ void Function::findExps()
|
||||
}
|
||||
}
|
||||
|
||||
void Function::preprocessReturnDU(std::bitset<32> &_liveOut)
|
||||
void Function::preprocessReturnDU(LivenessSet &_liveOut)
|
||||
{
|
||||
if (_liveOut.any())
|
||||
{
|
||||
// int idx;
|
||||
// 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);
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -10,18 +10,28 @@
|
||||
#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 */
|
||||
0xFFEFFF, 0xFFDFFF, 0xFFBFFF, 0xFF7FFF, /* uint8_t regs */
|
||||
0xFEFFFF, 0xFDFFFF, 0xFBFFFF, 0xF7FFFF,
|
||||
0xEFFFFF, /* tmp reg */
|
||||
0xFFFFB7, 0xFFFF77, 0xFFFF9F, 0xFFFF5F, /* index regs */
|
||||
0xFFFFBF, 0xFFFF7F, 0xFFFFDF, 0xFFFFF7 };
|
||||
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 */
|
||||
0xFFFFB7, 0xFFFF77, 0xFFFF9F, 0xFFFF5F, /* index regs */
|
||||
0xFFFFBF, 0xFFFF7F, 0xFFFFDF, 0xFFFFF7 };
|
||||
|
||||
static char buf[lineSize]; /* Line buffer for hl icode output */
|
||||
|
||||
|
||||
@ -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,9 +28,7 @@ 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
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -99,11 +99,10 @@ static void appendNodeInt (queue &pqH, BB *node, interval *pI)
|
||||
void derSeq_Entry::findIntervals (Function *c)
|
||||
{
|
||||
interval *pI, /* Interval being processed */
|
||||
*J; /* ^ last interval in derivedGi->Ii */
|
||||
*J; /* ^ last interval in derivedGi->Ii */
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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/
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user