Skip to content

Commit

Permalink
Merge pull request #1017 from xudon9/svfir-json
Browse files Browse the repository at this point in the history
SVFIR Json Writer
  • Loading branch information
yuleisui authored Mar 12, 2023
2 parents 343902d + abfae92 commit 815c037
Show file tree
Hide file tree
Showing 30 changed files with 2,378 additions and 450 deletions.
6 changes: 4 additions & 2 deletions .codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ codecov:
ignore:
- "svf/lib/SVFIR/SVFModuleRW.cpp"
- "svf/include/SVFIR/SVFModuleRW.h"

- "svf/lib/SVFIR/SVFIRRW.cpp"
- "svf/include/SVFIR/SVFIRRW.h"

coverage:
status:
project:
Expand All @@ -25,7 +27,7 @@ parsers:
loop: yes
method: no
macro: no

comment:
layout: "reach,diff,flags,tree"
behavior: default
Expand Down
71 changes: 36 additions & 35 deletions svf-llvm/include/SVF-LLVM/DCHG.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ class DCHNode : public GenericNode<DCHNode, DCHEdge>

typedef std::vector<const Function*> FuncVector;

DCHNode(const DIType *diType, NodeID i = 0, GNodeK k = 0)
DCHNode(const DIType* diType, NodeID i = 0, GNodeK k = 0)
: GenericNode<DCHNode, DCHEdge>(i, k), vtable(nullptr), flags(0)
{
this->diType = diType;
Expand Down Expand Up @@ -210,10 +210,10 @@ class DCHGraph : public CommonCHGraph, public GenericGraph<DCHNode, DCHEdge>
{
public:
/// Returns the DIType beneath the qualifiers. Does not strip away "DW_TAG_members".
static const DIType *stripQualifiers(const DIType *);
static const DIType* stripQualifiers(const DIType*);

/// Returns the DIType beneath all qualifiers and arrays.
static const DIType *stripArray(const DIType *);
static const DIType* stripArray(const DIType*);

/// Returns true if t1 and t2 are equivalent, ignoring qualifiers.
/// For equality...
Expand All @@ -222,13 +222,13 @@ class DCHGraph : public CommonCHGraph, public GenericGraph<DCHNode, DCHEdge>
/// DIDerivedType: base types (teq).
/// DICompositeType: shallow pointer equality.
/// DISubroutineType: shallow pointer equality.
static bool teq(const DIType *t1, const DIType *t2);
static bool teq(const DIType* t1, const DIType* t2);

/// Returns a human-readable version of the DIType.
static std::string diTypeToStr(const DIType *);

// Returns whether t is an array, a struct, a class, a union, or neither.
static bool isAgg(const DIType *t);
static bool isAgg(const DIType* t);

public:
DCHGraph(const SVFModule *svfMod)
Expand Down Expand Up @@ -293,7 +293,7 @@ class DCHGraph : public CommonCHGraph, public GenericGraph<DCHNode, DCHEdge>
/// Returns the type representing all qualifier-variations of t.
/// This should only matter in the case of DerivedTypes where
/// qualifiers and have qualified base types cause a mess.
const DIType *getCanonicalType(const DIType *t);
const DIType* getCanonicalType(const DIType* t);

/// Returns the type of field number idx (flattened) in base.
const DIType *getFieldType(const DIType *base, unsigned idx)
Expand All @@ -314,13 +314,14 @@ class DCHGraph : public CommonCHGraph, public GenericGraph<DCHNode, DCHEdge>

if (base->getTag() == dwarf::DW_TAG_array_type)
{
const DICompositeType *cbase = SVFUtil::dyn_cast<DICompositeType>(base);
const DICompositeType* cbase =
SVFUtil::dyn_cast<DICompositeType>(base);
assert(cbase && "DCHG: bad DIComposite case");
return cbase->getBaseType();
}

if (!(base->getTag() == dwarf::DW_TAG_class_type
|| base->getTag() == dwarf::DW_TAG_structure_type))
if (!(base->getTag() == dwarf::DW_TAG_class_type ||
base->getTag() == dwarf::DW_TAG_structure_type))
{
return nullptr;
}
Expand Down Expand Up @@ -355,64 +356,64 @@ class DCHGraph : public CommonCHGraph, public GenericGraph<DCHNode, DCHEdge>
return containingAggs[base];
}

bool isFirstField(const DIType *f, const DIType *b);
bool isFirstField(const DIType* f, const DIType* b);

protected:
/// SVF Module this CHG is built from.
const SVFModule *svfModule;
const SVFModule* svfModule;
/// Whether this CHG is an extended CHG (first-field). Set by buildCHG.
bool extended = false;
/// Maps DITypes to their nodes.
Map<const DIType *, DCHNode *> diTypeToNodeMap;
Map<const DIType*, DCHNode*> diTypeToNodeMap;
/// Maps VTables to the DIType associated with them.
Map<const SVFGlobalValue *, const DIType *> vtblToTypeMap;
Map<const SVFGlobalValue*, const DIType*> vtblToTypeMap;
/// Maps types to all children (i.e. CHA).
Map<const DIType *, NodeBS> chaMap;
Map<const DIType*, NodeBS> chaMap;
/// Maps types to all children but also considering first field.
Map<const DIType *, NodeBS> chaFFMap;
Map<const DIType*, NodeBS> chaFFMap;
/// Maps types to a set with their vtable and all their children's.
Map<const DIType *, VTableSet> vtblCHAMap;
Map<const DIType*, VTableSet> vtblCHAMap;
/// Maps callsites to a set of potential virtual functions based on CHA.
Map<CallSite, VFunSet> csCHAMap;
/// Maps types to their canonical type (many-to-one).
Map<const DIType *, const DIType *> canonicalTypeMap;
Map<const DIType*, const DIType*> canonicalTypeMap;
/// Set of all possible canonical types (i.e. values of canonicalTypeMap).
Set<const DIType *> canonicalTypes;
Set<const DIType*> canonicalTypes;
/// Maps types to their flattened fields' types.
Map<const DIType *, std::vector<const DIType *>> fieldTypes;
Map<const DIType*, std::vector<const DIType*>> fieldTypes;
/// Maps aggregate types to all the aggregate types it transitively contains.
Map<const DIType *, Set<const DIType *>> containingAggs;
Map<const DIType*, Set<const DIType*>> containingAggs;

private:
/// Construction helper to process DIBasicTypes.
void handleDIBasicType(const DIBasicType *basicType);
void handleDIBasicType(const DIBasicType* basicType);
/// Construction helper to process DICompositeTypes.
void handleDICompositeType(const DICompositeType *compositeType);
void handleDICompositeType(const DICompositeType* compositeType);
/// Construction helper to process DIDerivedTypes.
void handleDIDerivedType(const DIDerivedType *derivedType);
void handleDIDerivedType(const DIDerivedType* derivedType);
/// Construction helper to process DISubroutineTypes.
void handleDISubroutineType(const DISubroutineType *subroutineType);
void handleDISubroutineType(const DISubroutineType* subroutineType);

/// Finds all defined virtual functions and attaches them to nodes.
void buildVTables(const SVFModule &module);
void buildVTables(const SVFModule& module);

/// Returns a set of all children of type (CHA). Also gradually builds chaMap.
const NodeBS &cha(const DIType *type, bool firstField);
const NodeBS& cha(const DIType* type, bool firstField);

/// Attaches the typedef(s) to the base node.
void handleTypedef(const DIType *typedefType);
void handleTypedef(const DIType* typedefType);

/// Populates fieldTypes for type and all its elements.
void flatten(const DICompositeType *type);
void flatten(const DICompositeType* type);

/// Populates containingAggs for type and all its elements.
void gatherAggs(const DICompositeType *type);
void gatherAggs(const DICompositeType* type);

/// Creates a node from type, or returns it if it exists.
DCHNode *getOrCreateNode(const DIType *type);
DCHNode* getOrCreateNode(const DIType* type);

/// Retrieves the metadata associated with a *virtual* callsite.
const DIType *getCSStaticType(CallBase* cs) const
const DIType* getCSStaticType(CallBase* cs) const
{
MDNode *md = cs->getMetadata(cppUtil::ctir::derefMDName);
assert(md != nullptr && "Missing type metadata at virtual callsite");
Expand All @@ -428,14 +429,14 @@ class DCHGraph : public CommonCHGraph, public GenericGraph<DCHNode, DCHEdge>
}

/// Checks if a node exists for type.
bool hasNode(const DIType *type)
bool hasNode(const DIType* type)
{
type = getCanonicalType(type);
return diTypeToNodeMap.find(type) != diTypeToNodeMap.end();
}

/// Returns the node for type (nullptr if it doesn't exist).
DCHNode *getNode(const DIType *type)
DCHNode* getNode(const DIType* type)
{
type = getCanonicalType(type);
if (hasNode(type))
Expand All @@ -448,9 +449,9 @@ class DCHGraph : public CommonCHGraph, public GenericGraph<DCHNode, DCHEdge>


/// Creates an edge between from t1 to t2.
DCHEdge *addEdge(const DIType *t1, const DIType *t2, DCHEdge::GEdgeKind et);
DCHEdge* addEdge(const DIType* t1, const DIType* t2, DCHEdge::GEdgeKind et);
/// Returns the edge between t1 and t2 if it exists, returns nullptr otherwise.
DCHEdge *hasEdge(const DIType *t1, const DIType *t2, DCHEdge::GEdgeKind et);
DCHEdge* hasEdge(const DIType* t1, const DIType* t2, DCHEdge::GEdgeKind et);

/// Number of types (nodes) in the graph.
NodeID numTypes;
Expand Down
5 changes: 0 additions & 5 deletions svf-llvm/lib/LLVMModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,6 @@ using namespace SVF;
#define SVF_GLOBAL_CTORS "llvm.global_ctors"
#define SVF_GLOBAL_DTORS "llvm.global_dtors"

static Option<std::string> dumpJson("dump-json",
"Dump the SVFModule to JSON file", "");

LLVMModuleSet *LLVMModuleSet::llvmModuleSet = nullptr;
std::string SVFModule::pagReadFromTxt = "";

Expand Down Expand Up @@ -123,8 +120,6 @@ SVFModule* LLVMModuleSet::buildSVFModule(const std::vector<std::string> &moduleN

build_symbol_table();

svfModule->writeToJson(dumpJson());

return svfModule.get();
}

Expand Down
12 changes: 10 additions & 2 deletions svf-llvm/lib/SVFIRBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,10 @@
#include "SVF-LLVM/LLVMLoopAnalysis.h"
#include "Util/Options.h"
#include "SVF-LLVM/CHGBuilder.h"
#include "SVFIR/SVFIRRW.h"
#include "SVF-LLVM/SymbolTableBuilder.h"


using namespace std;
using namespace SVF;
using namespace SVFUtil;
Expand All @@ -64,7 +66,7 @@ SVFIR* SVFIRBuilder::build()
icfgbuilder.build(svfModule);
pag->setICFG(icfg);

CHGraph *chg = new CHGraph(pag->getModule());
CHGraph* chg = new CHGraph(pag->getModule());
CHGBuilder chgbuilder(chg);
chgbuilder.buildCHG();
pag->setCHG(chg);
Expand Down Expand Up @@ -162,8 +164,14 @@ SVFIR* SVFIRBuilder::build()
loopAnalysis.build(pag->getICFG());
}

// dump SVFIR as JSON
if (!Options::DumpJson().empty())
{
SVFIRWriter::writeJsonToPath(pag, Options::DumpJson());
}

double endTime = SVFStat::getClk(true);
SVFStat::timeOfBuildingSVFIR = (endTime - startTime)/TIMEINTERVAL;
SVFStat::timeOfBuildingSVFIR = (endTime - startTime) / TIMEINTERVAL;

return pag;
}
Expand Down
4 changes: 4 additions & 0 deletions svf-llvm/tools/WPA/wpa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@
#include "Util/CommandLine.h"
#include "Util/Options.h"


#include "SVFIR/SVFIRRW.h"


using namespace llvm;
using namespace std;
using namespace SVF;
Expand Down
41 changes: 27 additions & 14 deletions svf/include/Graphs/CHG.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ class CommonCHGraph
virtual const VFunSet &getCSVFsBasedonCHA(CallSite cs) = 0;
virtual bool csHasVtblsBasedonCHA(CallSite cs) = 0;
virtual const VTableSet &getCSVtblsBasedonCHA(CallSite cs) = 0;
virtual void getVFnsFromVtbls(CallSite cs, const VTableSet &vtbls, VFunSet &virtualFunctions) = 0;
virtual void getVFnsFromVtbls(CallSite cs, const VTableSet& vtbls,
VFunSet& virtualFunctions) = 0;

CHGKind getKind(void) const
{
Expand All @@ -76,17 +77,19 @@ class CommonCHGraph
typedef GenericEdge<CHNode> GenericCHEdgeTy;
class CHEdge: public GenericCHEdgeTy
{
friend class SVFIRWriter;

public:
typedef enum
{
INHERITANCE = 0x1, // inheritance relation
INSTANTCE = 0x2 // template-instance relation
INSTANTCE = 0x2 // template-instance relation
} CHEDGETYPE;

typedef GenericNode<CHNode,CHEdge>::GEdgeSetTy CHEdgeSetTy;
typedef GenericNode<CHNode, CHEdge>::GEdgeSetTy CHEdgeSetTy;

CHEdge(CHNode *s, CHNode *d, CHEDGETYPE et, GEdgeFlag k = 0):
GenericCHEdgeTy(s,d,k)
CHEdge(CHNode* s, CHNode* d, CHEDGETYPE et, GEdgeFlag k = 0)
: GenericCHEdgeTy(s, d, k)
{
edgeType = et;
}
Expand All @@ -100,9 +103,11 @@ class CHEdge: public GenericCHEdgeTy
CHEDGETYPE edgeType;
};

typedef GenericNode<CHNode,CHEdge> GenericCHNodeTy;
typedef GenericNode<CHNode, CHEdge> GenericCHNodeTy;
class CHNode: public GenericCHNodeTy
{
friend class SVFIRWriter;

public:
typedef enum
{
Expand Down Expand Up @@ -204,9 +209,10 @@ class CHNode: public GenericCHNodeTy
};

/// class hierarchy graph
typedef GenericGraph<CHNode,CHEdge> GenericCHGraphTy;
typedef GenericGraph<CHNode, CHEdge> GenericCHGraphTy;
class CHGraph: public CommonCHGraph, public GenericCHGraphTy
{
friend class SVFIRWriter;
friend class CHGBuilder;

public:
Expand Down Expand Up @@ -311,7 +317,7 @@ class CHGraph: public CommonCHGraph, public GenericCHGraphTy
u32_t classNum;
u32_t vfID;
double buildingCHGTime;
Map<std::string, CHNode *> classNameToNodeMap;
Map<std::string, CHNode*> classNameToNodeMap;
NameToCHNodesMap classNameToDescendantsMap;
NameToCHNodesMap classNameToAncestorsMap;
NameToCHNodesMap classNameToInstAndDescsMap;
Expand All @@ -331,19 +337,26 @@ namespace SVF
* GenericGraphTraits specializations for generic graph algorithms.
* Provide graph traits for traversing from a constraint node using standard graph traversals.
*/
template<> struct GenericGraphTraits<SVF::CHNode*> : public GenericGraphTraits<SVF::GenericNode<SVF::CHNode,SVF::CHEdge>* >
template <>
struct GenericGraphTraits<SVF::CHNode*>
: public GenericGraphTraits<SVF::GenericNode<SVF::CHNode, SVF::CHEdge>*>
{
};

/// Inverse GenericGraphTraits specializations for call graph node, it is used for inverse traversal.
template<>
struct GenericGraphTraits<Inverse<SVF::CHNode*> > : public GenericGraphTraits<Inverse<SVF::GenericNode<SVF::CHNode,SVF::CHEdge>* > >
/// Inverse GenericGraphTraits specializations for call graph node, it is used
/// for inverse traversal.
template <>
struct GenericGraphTraits<Inverse<SVF::CHNode*>>
: public GenericGraphTraits<
Inverse<SVF::GenericNode<SVF::CHNode, SVF::CHEdge>*>>
{
};

template<> struct GenericGraphTraits<SVF::CHGraph*> : public GenericGraphTraits<SVF::GenericGraph<SVF::CHNode,SVF::CHEdge>* >
template <>
struct GenericGraphTraits<SVF::CHGraph*>
: public GenericGraphTraits<SVF::GenericGraph<SVF::CHNode, SVF::CHEdge>*>
{
typedef SVF::CHNode *NodeRef;
typedef SVF::CHNode* NodeRef;
};

} // End namespace llvm
Expand Down
Loading

0 comments on commit 815c037

Please sign in to comment.