Program Listing for File StmtInfoCollect.h#
↰ Return to documentation for file (src/midend/astUtil/astSupport/StmtInfoCollect.h)
#ifndef STMT_INFO_COLLECT_H
#define STMT_INFO_COLLECT_H
#include "AstInterface.h"
#include "SinglyLinkedList.h"
#include "ProcessAstTree.h"
#include "AnalysisInterface.h"
#include "union_find.h"
#include <map>
#include <list>
#include <sstream>
class StmtInfoCollect : public ProcessAstTreeBase
{
protected:
struct ModRecord{
AstNodePtr rhs;
bool readlhs;
ModRecord() : readlhs(false) {}
ModRecord( const AstNodePtr& _rhs, bool _readlhs)
: rhs(_rhs), readlhs(_readlhs) {}
};
typedef std::map<AstNodePtr, ModRecord, std::less<AstNodePtr> > ModMap;
struct ModStackEntry {
AstNodePtr root;
ModMap modmap;
ModStackEntry(const AstNodePtr& r) : root(r) {}
};
std::list<ModStackEntry> modstack;
AstNodePtr curstmt;
protected:
virtual void AppendModLoc( AstInterface& fa, const AstNodePtr& mod,
const AstNodePtr& rhs = AstNodePtr()) = 0;
virtual void AppendReadLoc( AstInterface& fa, const AstNodePtr& read) = 0;
virtual void AppendFuncCall( AstInterface& fa, const AstNodePtr& fc) = 0;
void AppendFuncCallArguments( AstInterface& fa, const AstNodePtr& fc) ;
void AppendFuncCallWrite( AstInterface& fa, const AstNodePtr& fc) ;
virtual bool ProcessTree( AstInterface &_fa, const AstNodePtr& s,
AstInterface::TraversalVisitType t);
public:
void operator()( AstInterface& fa, const AstNodePtr& h) ;
};
class FunctionSideEffectInterface;
class StmtSideEffectCollect
: public StmtInfoCollect, public SideEffectAnalysisInterface
{
private:
bool modunknown, readunknown;
FunctionSideEffectInterface* funcanal;
CollectObject< std::pair<AstNodePtr,AstNodePtr> > *modcollect, *readcollect, *killcollect;
virtual void AppendModLoc( AstInterface& fa, const AstNodePtr& mod,
const AstNodePtr& rhs = AstNodePtr()) ;
virtual void AppendReadLoc( AstInterface& fa, const AstNodePtr& read) ;
virtual void AppendFuncCall( AstInterface& fa, const AstNodePtr& fc);
public:
StmtSideEffectCollect( FunctionSideEffectInterface* a=0)
: modunknown(false), readunknown(false),funcanal(a), modcollect(0),
readcollect(0), killcollect(0) {}
bool get_side_effect(AstInterface& fa, const AstNodePtr& h,
CollectObject<std::pair<AstNodePtr,AstNodePtr> >* collectmod,
CollectObject<std::pair<AstNodePtr,AstNodePtr> >* collectread = 0,
CollectObject<std::pair<AstNodePtr,AstNodePtr> >* collectkill = 0)
{ return operator()( fa, h, collectmod, collectread, collectkill); }
bool operator()( AstInterface& fa, const AstNodePtr& h,
CollectObject< std::pair<AstNodePtr,AstNodePtr> >* mod,
CollectObject< std::pair<AstNodePtr,AstNodePtr> >* read=0,
CollectObject< std::pair<AstNodePtr,AstNodePtr> >* kill = 0)
{
modcollect = mod;
readcollect = read;
killcollect = kill;
modunknown = readunknown = false;
StmtInfoCollect::operator()(fa, h);
return !modunknown && !readunknown;
}
};
class Ast2StringMap {
typedef std::map<AstNodePtr, std::string, std::less<AstNodePtr> > MapType;
MapType astmap;
int cur;
static Ast2StringMap* handle;
Ast2StringMap() : cur(0) {}
~Ast2StringMap() {}
public:
static Ast2StringMap* inst();
std::string get_string( const AstNodePtr& s);
std::string get_string( const AstNodePtr& s) const;
std::string lookup_string( const AstNodePtr& s) const;
};
class InterProcVariableUniqueRepr {
public:
static std:: string // get name for the ith parameter of function
get_unique_name(const std::string& fname, int i) {
std::stringstream out;
out << i;
std::string res = fname + "-" + out.str();
return res;
}
static std:: string
get_unique_name(const std::string& fname, const AstNodePtr& scope,
const std::string& varname)
{ return fname + "-" + (scope==0? "" : Ast2StringMap::inst()->get_string(scope))
+ "-" + varname; }
static std:: string
get_unique_name(AstInterface& fa, const AstNodePtr& exp);
static std:: string
get_unique_name(AstInterface& fa, const AstNodePtr& scope, const std::string& varname);
};
class FunctionAliasInterface;
// flow insensitive alias analysis for named variables only
class StmtVarAliasCollect
: public StmtInfoCollect, public AliasAnalysisInterface
{
public:
class VarAliasMap { // name -> disjoint-set ID, we only need to check if two variables belong to the same group
std::map<std::string, UF_elem*, std::less<std::string> > aliasmap;
static Ast2StringMap scopemap;
public:
~VarAliasMap() {
for (std::map<std::string, UF_elem*, std::less<std::string> >::
const_iterator p = aliasmap.begin(); p != aliasmap.end(); ++p) {
delete (*p).second;
}
}
UF_elem* get_alias_map( const std::string& varname, const AstNodePtr& scope);
};
private:
FunctionAliasInterface* funcanal;
VarAliasMap aliasmap;
bool hasunknown, hasresult;
UF_elem* get_alias_map( const std::string& varname, const AstNodePtr& scope);
virtual void AppendModLoc( AstInterface& fa, const AstNodePtr& mod,
const AstNodePtr& rhs = AstNodePtr());
virtual void AppendFuncCall( AstInterface& fa, const AstNodePtr& fc);
virtual void AppendReadLoc( AstInterface& fa, const AstNodePtr& read) {}
public:
StmtVarAliasCollect( FunctionAliasInterface* a = 0)
: funcanal(a), hasunknown(false), hasresult(false) {}
virtual void analyze(AstInterface& fa, const AstNodePtr& funcdefinition);
void operator()( AstInterface& fa, const AstNodePtr& funcdefinition);
bool may_alias(AstInterface& fa, const AstNodePtr& r1,
const AstNodePtr& r2);
};
template <class Select>
class ModifyVariableMap
: public CollectObject<std::pair<AstNodePtr,AstNodePtr> >,
public StmtSideEffectCollect
{
AstInterface& ai;
class VarModSet : public std::set<AstNodePtr> {};
typedef std::map <std::string, VarModSet, std::less<std::string> > VarModInfo;
VarModInfo varmodInfo;
Select sel;
bool operator()(const std::pair<AstNodePtr,AstNodePtr>& cur)
{
std::string varname;
if (ai.IsVarRef(cur.first,0, &varname)) {
AstNodePtr l = ai.GetParent(cur.first);
VarModSet& cur = varmodInfo[varname];
for ( ; l != AST_NULL; l = ai.GetParent(l)) {
if (sel(ai,l))
cur.insert(l);
}
}
return true;
}
public:
AstInterface& get_astInterface() { return ai; }
ModifyVariableMap(AstInterface& _ai, Select _sel,
FunctionSideEffectInterface* a=0)
: StmtSideEffectCollect(a), ai(_ai), sel(_sel) {}
void Collect(const AstNodePtr& root)
{
StmtSideEffectCollect::get_side_effect(ai, root, this);
}
bool Modify( const AstNodePtr& l, const std::string& varname) const
{
typename VarModInfo::const_iterator p = varmodInfo.find(varname);
if (p != varmodInfo.end()) {
if (l == AST_NULL)
return true;
const VarModSet& cur = (*p).second;
return cur.find(l) != cur.end();
}
else
return false;
}
};
#endif