Static Value-Flow Analysis
Loading...
Searching...
No Matches
Public Member Functions | Protected Member Functions | Private Member Functions | Private Attributes | List of all members
SVF::SVFIRBuilder Class Reference

#include <SVFIRBuilder.h>

Inheritance diagram for SVF::SVFIRBuilder:

Public Member Functions

 SVFIRBuilder ()
 Constructor.
 
virtual ~SVFIRBuilder ()
 Destructor.
 
virtual SVFIRbuild ()
 Start building SVFIR here.
 
SVFIRgetPAG () const
 Return SVFIR.
 
void createFunObjVars ()
 
void initFunObjVar ()
 
void initialiseNodes ()
 Initialize nodes and edges.
 
void initialiseBaseObjVars ()
 
void initialiseValVars ()
 
void initSVFBasicBlock (const Function *func)
 
void initDomTree (FunObjVar *func, const Function *f)
 
void addEdge (NodeID src, NodeID dst, SVFStmt::PEDGEK kind, APOffset offset=0, Instruction *cs=nullptr)
 
void sanityCheck ()
 Sanity check for SVFIR.
 
NodeID getValueNode (const Value *V)
 Get different kinds of node.
 
NodeID getObjectNode (const Value *V)
 GetObject - Return the object node (stack/global/heap/function) according to a LLVM Value.
 
NodeID getReturnNode (const FunObjVar *func)
 getReturnNode - Return the node representing the unique return value of a function.
 
NodeID getVarargNode (const FunObjVar *func)
 getVarargNode - Return the node representing the unique variadic argument of a function.
 
virtual void visitAllocaInst (AllocaInst &AI)
 Our visit overrides.
 
void visitPHINode (PHINode &I)
 
void visitStoreInst (StoreInst &I)
 
void visitLoadInst (LoadInst &I)
 
void visitGetElementPtrInst (GetElementPtrInst &I)
 
void visitCallInst (CallInst &I)
 
void visitInvokeInst (InvokeInst &II)
 
void visitCallBrInst (CallBrInst &I)
 
void visitCallSite (CallBase *cs)
 
void visitReturnInst (ReturnInst &I)
 
void visitCastInst (CastInst &I)
 
void visitSelectInst (SelectInst &I)
 
void visitExtractValueInst (ExtractValueInst &EVI)
 
void visitBranchInst (BranchInst &I)
 
void visitSwitchInst (SwitchInst &I)
 The following implementation follows ICFGBuilder::processFunBody.
 
void visitInsertValueInst (InsertValueInst &I)
 
void visitBinaryOperator (BinaryOperator &I)
 
void visitUnaryOperator (UnaryOperator &I)
 
void visitCmpInst (CmpInst &I)
 
void visitVAArgInst (VAArgInst &)
 
void visitVACopyInst (VACopyInst &)
 
void visitVAEndInst (VAEndInst &)
 
void visitVAStartInst (VAStartInst &)
 
void visitFreezeInst (FreezeInst &I)
 
void visitExtractElementInst (ExtractElementInst &I)
 
void visitInsertElementInst (InsertElementInst &I)
 
void visitShuffleVectorInst (ShuffleVectorInst &I)
 
void visitLandingPadInst (LandingPadInst &I)
 
void visitResumeInst (ResumeInst &)
 Instruction not that often.
 
void visitUnreachableInst (UnreachableInst &)
 
void visitFenceInst (FenceInst &I)
 
void visitAtomicCmpXchgInst (AtomicCmpXchgInst &I)
 
void visitAtomicRMWInst (AtomicRMWInst &I)
 
void visitInstruction (Instruction &)
 Provide base case for our instruction visit.
 
void updateCallGraph (CallGraph *callgraph)
 connect PAG edges based on callgraph
 

Protected Member Functions

void visitGlobal ()
 Handle globals including (global variable and functions)
 
void InitialGlobal (const GlobalVariable *gvar, Constant *C, u32_t offset)
 
NodeID getGlobalVarField (const GlobalVariable *gvar, u32_t offset, SVFType *tpy)
 
void processCE (const Value *val)
 Process constant expression.
 
u32_t inferFieldIdxFromByteOffset (const llvm::GEPOperator *gepOp, DataLayout *dl, AccessPath &ap, APOffset idx)
 Infer field index from byteoffset.
 
bool computeGepOffset (const User *V, AccessPath &ap)
 Compute offset of a gep instruction or gep constant expression.
 
const ValuegetBaseValueForExtArg (const Value *V)
 Get the base value of (i8* src and i8* dst) for external argument (e.g. memcpy(i8* dst, i8* src, int size))
 
void handleDirectCall (CallBase *cs, const Function *F)
 Handle direct call.
 
void handleIndCall (CallBase *cs)
 Handle indirect call.
 
virtual const TypegetBaseTypeAndFlattenedFields (const Value *V, std::vector< AccessPath > &fields, const Value *szValue)
 Handle external call.
 
virtual void addComplexConsForExt (Value *D, Value *S, const Value *sz)
 
virtual void handleExtCall (const CallBase *cs, const Function *callee)
 
void setCurrentLocation (const Value *val, const BasicBlock *bb)
 Set current basic block in order to keep track of control flow information.
 
void setCurrentLocation (const Value *val, const SVFBasicBlock *bb)
 
const ValuegetCurrentValue () const
 
const SVFBasicBlockgetCurrentBB () const
 
void addGlobalBlackHoleAddrEdge (NodeID node, const ConstantExpr *int2Ptrce)
 Add global black hole Address edge.
 
NodeID addNullPtrNode ()
 Add NullPtr PAGNode.
 
NodeID getGepValVar (const Value *val, const AccessPath &ap, const SVFType *elementType)
 
void setCurrentBBAndValueForPAGEdge (PAGEdge *edge)
 
void addBlackHoleAddrEdge (NodeID node)
 
AddrStmtaddAddrEdge (NodeID src, NodeID dst)
 Add Address edge.
 
AddrStmtaddAddrWithStackArraySz (NodeID src, NodeID dst, llvm::AllocaInst &inst)
 Add Address edge from allocinst with arraysize like "%4 = alloca i8, i64 3".
 
AddrStmtaddAddrWithHeapSz (NodeID src, NodeID dst, const CallBase *cs)
 Add Address edge from ext call with args like "%5 = call i8* @malloc(i64 noundef 5)".
 
CopyStmtaddCopyEdge (NodeID src, NodeID dst, CopyStmt::CopyKind kind)
 
CopyStmt::CopyKind getCopyKind (const Value *val)
 
void addPhiStmt (NodeID res, NodeID opnd, const ICFGNode *pred)
 Add Copy edge.
 
void addSelectStmt (NodeID res, NodeID op1, NodeID op2, NodeID cond)
 Add SelectStmt.
 
void addCmpEdge (NodeID op1, NodeID op2, NodeID dst, u32_t predict)
 Add Copy edge.
 
void addBinaryOPEdge (NodeID op1, NodeID op2, NodeID dst, u32_t opcode)
 Add Copy edge.
 
void addUnaryOPEdge (NodeID src, NodeID dst, u32_t opcode)
 Add Unary edge.
 
void addBranchStmt (NodeID br, NodeID cond, const BranchStmt::SuccAndCondPairVec &succs)
 Add Branch statement.
 
void addLoadEdge (NodeID src, NodeID dst)
 Add Load edge.
 
void addStoreEdge (NodeID src, NodeID dst)
 Add Store edge.
 
void addCallEdge (NodeID src, NodeID dst, const CallICFGNode *cs, const FunEntryICFGNode *entry)
 Add Call edge.
 
void addRetEdge (NodeID src, NodeID dst, const CallICFGNode *cs, const FunExitICFGNode *exit)
 Add Return edge.
 
void addGepEdge (NodeID src, NodeID dst, const AccessPath &ap, bool constGep)
 Add Gep edge.
 
void addNormalGepEdge (NodeID src, NodeID dst, const AccessPath &ap)
 Add Offset(Gep) edge.
 
void addVariantGepEdge (NodeID src, NodeID dst, const AccessPath &ap)
 Add Variant(Gep) edge.
 
void addThreadForkEdge (NodeID src, NodeID dst, const CallICFGNode *cs, const FunEntryICFGNode *entry)
 Add Thread fork edge for parameter passing.
 
void addThreadJoinEdge (NodeID src, NodeID dst, const CallICFGNode *cs, const FunExitICFGNode *exit)
 Add Thread join edge for parameter passing.
 
AccessPath getAccessPathFromBaseNode (NodeID nodeId)
 

Private Member Functions

LLVMModuleSetllvmModuleSet ()
 

Private Attributes

SVFIRpag
 
const SVFBasicBlockcurBB
 Current basic block during SVFIR construction when visiting the module.
 
const ValuecurVal
 Current Value during SVFIR construction when visiting the module.
 

Detailed Description

SVFIR Builder to create SVF variables and statements and PAG

Definition at line 47 of file SVFIRBuilder.h.

Constructor & Destructor Documentation

◆ SVFIRBuilder()

SVF::SVFIRBuilder::SVFIRBuilder ( )
inline

Constructor.

Definition at line 57 of file SVFIRBuilder.h.

57 : pag(SVFIR::getPAG()), curBB(nullptr),curVal(nullptr)
58 {
59 }
const Value * curVal
Current Value during SVFIR construction when visiting the module.
const SVFBasicBlock * curBB
Current basic block during SVFIR construction when visiting the module.
static SVFIR * getPAG(bool buildFromFile=false)
Singleton design here to make sure we only have one instance during any analysis.
Definition SVFIR.h:116

◆ ~SVFIRBuilder()

virtual SVF::SVFIRBuilder::~SVFIRBuilder ( )
inlinevirtual

Destructor.

Definition at line 61 of file SVFIRBuilder.h.

62 {
63 }

Member Function Documentation

◆ addAddrEdge()

AddrStmt * SVF::SVFIRBuilder::addAddrEdge ( NodeID  src,
NodeID  dst 
)
inlineprotected

Add Address edge.

Definition at line 301 of file SVFIRBuilder.h.

302 {
303 if(AddrStmt *edge = pag->addAddrStmt(src, dst))
304 {
306 return edge;
307 }
308 return nullptr;
309 }
void setCurrentBBAndValueForPAGEdge(PAGEdge *edge)
AddrStmt * addAddrStmt(NodeID src, NodeID dst)
Add an edge into SVFIR.
Definition SVFIR.cpp:63
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:74

◆ addAddrWithHeapSz()

AddrStmt * SVF::SVFIRBuilder::addAddrWithHeapSz ( NodeID  src,
NodeID  dst,
const CallBase cs 
)
inlineprotected

Add Address edge from ext call with args like "%5 = call i8* @malloc(i64 noundef 5)".

Definition at line 323 of file SVFIRBuilder.h.

324 {
325 // get name of called function
326 AddrStmt* edge = addAddrEdge(src, dst);
327
328 llvm::Function* calledFunc = cs->getCalledFunction();
329 std::string functionName;
330 if (calledFunc)
331 {
332 functionName = calledFunc->getName().str();
333 }
334 else
335 {
336 SVFUtil::wrnMsg("not support indirect call to add AddrStmt.\n");
337 }
338 if (functionName == "malloc")
339 {
340 if (cs->arg_size() > 0)
341 {
342 const llvm::Value* val = cs->getArgOperand(0);
343 edge->addArrSize(pag->getGNode(getValueNode(val)));
344 }
345 }
346 // Check if the function called is 'calloc' and process its arguments.
347 // e.g. "%5 = call i8* @calloc(1, 8)", edge should add two SVFValue (1 and 8)
348 else if (functionName == "calloc")
349 {
350 if (cs->arg_size() > 1)
351 {
352 edge->addArrSize(
353 pag->getGNode(getValueNode(cs->getArgOperand(0))));
354 edge->addArrSize(
355 pag->getGNode(getValueNode(cs->getArgOperand(1))));
356 }
357 }
358 else
359 {
360 if (cs->arg_size() > 0)
361 {
362 const llvm::Value* val = cs->getArgOperand(0);
363 edge->addArrSize(pag->getGNode(getValueNode(val)));
364 }
365 }
366 return edge;
367 }
NodeType * getGNode(NodeID id) const
Get a node.
AddrStmt * addAddrEdge(NodeID src, NodeID dst)
Add Address edge.
NodeID getValueNode(const Value *V)
Get different kinds of node.
std::string wrnMsg(const std::string &msg)
Returns warning message by converting a string into yellow string output.
Definition SVFUtil.cpp:63

◆ addAddrWithStackArraySz()

AddrStmt * SVF::SVFIRBuilder::addAddrWithStackArraySz ( NodeID  src,
NodeID  dst,
llvm::AllocaInst &  inst 
)
inlineprotected

Add Address edge from allocinst with arraysize like "%4 = alloca i8, i64 3".

Definition at line 312 of file SVFIRBuilder.h.

313 {
314 AddrStmt* edge = addAddrEdge(src, dst);
315 if (inst.getArraySize())
316 {
317 edge->addArrSize(pag->getGNode(getValueNode(inst.getArraySize())));
318 }
319 return edge;
320 }

◆ addBinaryOPEdge()

void SVF::SVFIRBuilder::addBinaryOPEdge ( NodeID  op1,
NodeID  op2,
NodeID  dst,
u32_t  opcode 
)
inlineprotected

Add Copy edge.

Definition at line 436 of file SVFIRBuilder.h.

437 {
438 if(BinaryOPStmt *edge = pag->addBinaryOPStmt(op1, op2, dst, opcode))
440 }
BinaryOPStmt * addBinaryOPStmt(NodeID op1, NodeID op2, NodeID dst, u32_t opcode)
Add Copy edge.
Definition SVFIR.cpp:165

◆ addBlackHoleAddrEdge()

void SVF::SVFIRBuilder::addBlackHoleAddrEdge ( NodeID  node)
inlineprotected

Definition at line 294 of file SVFIRBuilder.h.

295 {
298 }
SVFStmt * addBlackHoleAddrStmt(NodeID node)
Set a pointer points-to black hole (e.g. int2ptr)
Definition SVFIR.cpp:294
SVFStmt PAGEdge
Definition IRGraph.h:43

◆ addBranchStmt()

void SVF::SVFIRBuilder::addBranchStmt ( NodeID  br,
NodeID  cond,
const BranchStmt::SuccAndCondPairVec succs 
)
inlineprotected

Add Branch statement.

Definition at line 448 of file SVFIRBuilder.h.

449 {
450 if(BranchStmt *edge = pag->addBranchStmt(br, cond, succs))
452 }
BranchStmt * addBranchStmt(NodeID br, NodeID cond, const BranchStmt::SuccAndCondPairVec &succs)
Add BranchStmt.
Definition SVFIR.cpp:203

◆ addCallEdge()

void SVF::SVFIRBuilder::addCallEdge ( NodeID  src,
NodeID  dst,
const CallICFGNode cs,
const FunEntryICFGNode entry 
)
inlineprotected

Add Call edge.

Definition at line 472 of file SVFIRBuilder.h.

473 {
474 if (CallPE* edge = pag->addCallPE(src, dst, cs, entry))
476 }
CallPE * addCallPE(NodeID src, NodeID dst, const CallICFGNode *cs, const FunEntryICFGNode *entry)
Add Call edge.
Definition SVFIR.cpp:258

◆ addCmpEdge()

void SVF::SVFIRBuilder::addCmpEdge ( NodeID  op1,
NodeID  op2,
NodeID  dst,
u32_t  predict 
)
inlineprotected

Add Copy edge.

Definition at line 430 of file SVFIRBuilder.h.

431 {
432 if(CmpStmt *edge = pag->addCmpStmt(op1, op2, dst, predict))
434 }
CmpStmt * addCmpStmt(NodeID op1, NodeID op2, NodeID dst, u32_t predict)
Add Copy edge.
Definition SVFIR.cpp:144

◆ addComplexConsForExt()

void SVFIRBuilder::addComplexConsForExt ( Value D,
Value S,
const Value szValue 
)
protectedvirtual

Add the load/store constraints and temp. nodes for the complex constraint *D = *S (where D/S may point to structs).

If sz is 0, we will add edges for all fields.

Definition at line 82 of file SVFIRExtAPI.cpp.

83{
84 assert(D && S);
86 if(!vnD || !vnS)
87 return;
88
89 std::vector<AccessPath> fields;
90
91 //Get the max possible size of the copy, unless it was provided.
92 std::vector<AccessPath> srcFields;
93 std::vector<AccessPath> dstFields;
96 if(srcFields.size() > dstFields.size())
97 fields = dstFields;
98 else
99 fields = srcFields;
100
102 u32_t sz = fields.size();
103
104 if (fields.size() == 1 && (LLVMUtil::isConstDataOrAggData(D) || LLVMUtil::isConstDataOrAggData(S)))
105 {
109 return;
110 }
111
112 //For each field (i), add (Ti = *S + i) and (*D + i = Ti).
113 for (u32_t index = 0; index < sz; index++)
114 {
117 fields[index].getConstantStructFldIdx());
119 fields[index].getConstantStructFldIdx());
125 }
126}
unsigned u32_t
Definition CommandLine.h:18
int index
Definition cJSON.h:170
const SVFType * getFlatternedElemType(const SVFType *baseType, u32_t flatten_idx)
Return the type of a flattened element given a flattened index.
Definition IRGraph.cpp:123
static LLVMModuleSet * getLLVMModuleSet()
Definition LLVMModule.h:131
void addStoreEdge(NodeID src, NodeID dst)
Add Store edge.
void addLoadEdge(NodeID src, NodeID dst)
Add Load edge.
virtual const Type * getBaseTypeAndFlattenedFields(const Value *V, std::vector< AccessPath > &fields, const Value *szValue)
Handle external call.
NodeID getGepValVar(const Value *val, const AccessPath &ap, const SVFType *elementType)
NodeID addDummyValNode()
Definition SVFIR.h:487
bool isConstDataOrAggData(const Value *val)
Return true if the value refers to constant data, e.g., i32 0.
Definition LLVMUtil.h:368
llvm::Type Type
Definition BasicTypes.h:83
u32_t NodeID
Definition GeneralType.h:56

◆ addCopyEdge()

CopyStmt * SVF::SVFIRBuilder::addCopyEdge ( NodeID  src,
NodeID  dst,
CopyStmt::CopyKind  kind 
)
inlineprotected

Definition at line 369 of file SVFIRBuilder.h.

370 {
371 if(CopyStmt *edge = pag->addCopyStmt(src, dst, kind))
372 {
374 return edge;
375 }
376 return nullptr;
377 }
CopyStmt * addCopyStmt(NodeID src, NodeID dst, CopyStmt::CopyKind type)
Add Copy edge.
Definition SVFIR.cpp:81

◆ addEdge()

void SVF::SVFIRBuilder::addEdge ( NodeID  src,
NodeID  dst,
SVFStmt::PEDGEK  kind,
APOffset  offset = 0,
Instruction cs = nullptr 
)

◆ addGepEdge()

void SVF::SVFIRBuilder::addGepEdge ( NodeID  src,
NodeID  dst,
const AccessPath ap,
bool  constGep 
)
inlineprotected

Add Gep edge.

Definition at line 484 of file SVFIRBuilder.h.

485 {
486 if (GepStmt* edge = pag->addGepStmt(src, dst, ap, constGep))
488 }
GepStmt * addGepStmt(NodeID src, NodeID dst, const AccessPath &ap, bool constGep)
Add Gep edge.
Definition SVFIR.cpp:344

◆ addGlobalBlackHoleAddrEdge()

void SVF::SVFIRBuilder::addGlobalBlackHoleAddrEdge ( NodeID  node,
const ConstantExpr int2Ptrce 
)
inlineprotected

Add global black hole Address edge.

Definition at line 269 of file SVFIRBuilder.h.

270 {
271 const Value* cval = getCurrentValue();
272 const SVFBasicBlock* cbb = getCurrentBB();
273 setCurrentLocation(int2Ptrce,(SVFBasicBlock*) nullptr);
276 }
void setCurrentLocation(const Value *val, const BasicBlock *bb)
Set current basic block in order to keep track of control flow information.
void addBlackHoleAddrEdge(NodeID node)
const SVFBasicBlock * getCurrentBB() const
const Value * getCurrentValue() const
llvm::Value Value
LLVM Basic classes.
Definition BasicTypes.h:82

◆ addLoadEdge()

void SVF::SVFIRBuilder::addLoadEdge ( NodeID  src,
NodeID  dst 
)
inlineprotected

Add Load edge.

Definition at line 454 of file SVFIRBuilder.h.

455 {
456 if(LoadStmt *edge = pag->addLoadStmt(src, dst))
458 }
LoadStmt * addLoadStmt(NodeID src, NodeID dst)
Add Load edge.
Definition SVFIR.cpp:221

◆ addNormalGepEdge()

void SVF::SVFIRBuilder::addNormalGepEdge ( NodeID  src,
NodeID  dst,
const AccessPath ap 
)
inlineprotected

Add Offset(Gep) edge.

Definition at line 490 of file SVFIRBuilder.h.

491 {
492 if (GepStmt* edge = pag->addNormalGepStmt(src, dst, ap))
494 }
GepStmt * addNormalGepStmt(NodeID src, NodeID dst, const AccessPath &ap)
Add Offset(Gep) edge.
Definition SVFIR.cpp:363

◆ addNullPtrNode()

NodeID SVF::SVFIRBuilder::addNullPtrNode ( )
inlineprotected

Add NullPtr PAGNode.

Definition at line 279 of file SVFIRBuilder.h.

280 {
282 ConstantPointerNull* constNull = ConstantPointerNull::get(PointerType::getUnqual(cxt));
283 NodeID nullPtr = pag->addConstantNullPtrValNode(pag->getNullPtr(), nullptr, llvmModuleSet()->getSVFType(constNull->getType()));
285 setCurrentLocation(constNull, (SVFBasicBlock*) nullptr);
287 return nullPtr;
288 }
NodeID getBlkPtr() const
Definition IRGraph.h:255
NodeID getNullPtr() const
Definition IRGraph.h:259
void addToSVFVar2LLVMValueMap(const Value *val, SVFValue *svfBaseNode)
LLVMContext & getContext() const
Definition LLVMModule.h:381
LLVMModuleSet * llvmModuleSet()
NodeID addConstantNullPtrValNode(const NodeID i, const ICFGNode *icfgNode, const SVFType *type)
Definition SVFIR.h:593
llvm::ConstantPointerNull ConstantPointerNull
Definition BasicTypes.h:127
llvm::LLVMContext LLVMContext
Definition BasicTypes.h:70

◆ addPhiStmt()

void SVF::SVFIRBuilder::addPhiStmt ( NodeID  res,
NodeID  opnd,
const ICFGNode pred 
)
inlineprotected

Add Copy edge.

If we already added this phi node, then skip this adding

Definition at line 417 of file SVFIRBuilder.h.

418 {
420 if(PhiStmt *edge = pag->addPhiStmt(res,opnd,pred))
422 }
PhiStmt * addPhiStmt(NodeID res, NodeID opnd, const ICFGNode *pred)
Add phi node information.
Definition SVFIR.cpp:99

◆ addRetEdge()

void SVF::SVFIRBuilder::addRetEdge ( NodeID  src,
NodeID  dst,
const CallICFGNode cs,
const FunExitICFGNode exit 
)
inlineprotected

Add Return edge.

Definition at line 478 of file SVFIRBuilder.h.

479 {
480 if (RetPE* edge = pag->addRetPE(src, dst, cs, exit))
482 }
RetPE * addRetPE(NodeID src, NodeID dst, const CallICFGNode *cs, const FunExitICFGNode *exit)
Add Return edge.
Definition SVFIR.cpp:276

◆ addSelectStmt()

void SVF::SVFIRBuilder::addSelectStmt ( NodeID  res,
NodeID  op1,
NodeID  op2,
NodeID  cond 
)
inlineprotected

Add SelectStmt.

Definition at line 424 of file SVFIRBuilder.h.

425 {
426 if(SelectStmt *edge = pag->addSelectStmt(res,op1,op2,cond))
428 }
SelectStmt * addSelectStmt(NodeID res, NodeID op1, NodeID op2, NodeID cond)
Add SelectStmt.
Definition SVFIR.cpp:123

◆ addStoreEdge()

void SVF::SVFIRBuilder::addStoreEdge ( NodeID  src,
NodeID  dst 
)
inlineprotected

Add Store edge.

Definition at line 460 of file SVFIRBuilder.h.

461 {
462 ICFGNode* node;
463 if (const Instruction* inst = SVFUtil::dyn_cast<Instruction>(curVal))
464 node = llvmModuleSet()->getICFGNode(
465 SVFUtil::cast<Instruction>(inst));
466 else
467 node = nullptr;
468 if (StoreStmt* edge = pag->addStoreStmt(src, dst, node))
470 }
ICFGNode * getICFGNode(const Instruction *inst)
Get a basic block ICFGNode.
StoreStmt * addStoreStmt(NodeID src, NodeID dst, const ICFGNode *val)
Add Store edge.
Definition SVFIR.cpp:240
llvm::Instruction Instruction
Definition BasicTypes.h:87

◆ addThreadForkEdge()

void SVF::SVFIRBuilder::addThreadForkEdge ( NodeID  src,
NodeID  dst,
const CallICFGNode cs,
const FunEntryICFGNode entry 
)
inlineprotected

Add Thread fork edge for parameter passing.

Definition at line 502 of file SVFIRBuilder.h.

503 {
504 if (TDForkPE* edge = pag->addThreadForkPE(src, dst, cs, entry))
506 }
TDForkPE * addThreadForkPE(NodeID src, NodeID dst, const CallICFGNode *cs, const FunEntryICFGNode *entry)
Add Thread fork edge for parameter passing.
Definition SVFIR.cpp:305

◆ addThreadJoinEdge()

void SVF::SVFIRBuilder::addThreadJoinEdge ( NodeID  src,
NodeID  dst,
const CallICFGNode cs,
const FunExitICFGNode exit 
)
inlineprotected

Add Thread join edge for parameter passing.

Definition at line 508 of file SVFIRBuilder.h.

509 {
510 if (TDJoinPE* edge = pag->addThreadJoinPE(src, dst, cs, exit))
512 }
TDJoinPE * addThreadJoinPE(NodeID src, NodeID dst, const CallICFGNode *cs, const FunExitICFGNode *exit)
Add Thread join edge for parameter passing.
Definition SVFIR.cpp:323

◆ addUnaryOPEdge()

void SVF::SVFIRBuilder::addUnaryOPEdge ( NodeID  src,
NodeID  dst,
u32_t  opcode 
)
inlineprotected

Add Unary edge.

Definition at line 442 of file SVFIRBuilder.h.

443 {
444 if(UnaryOPStmt *edge = pag->addUnaryOPStmt(src, dst, opcode))
446 }
UnaryOPStmt * addUnaryOPStmt(NodeID src, NodeID dst, u32_t opcode)
Add Unary edge.
Definition SVFIR.cpp:185

◆ addVariantGepEdge()

void SVF::SVFIRBuilder::addVariantGepEdge ( NodeID  src,
NodeID  dst,
const AccessPath ap 
)
inlineprotected

Add Variant(Gep) edge.

Definition at line 496 of file SVFIRBuilder.h.

497 {
498 if (GepStmt* edge = pag->addVariantGepStmt(src, dst, ap))
500 }
GepStmt * addVariantGepStmt(NodeID src, NodeID dst, const AccessPath &ap)
Add Variant(Gep) edge.
Definition SVFIR.cpp:382

◆ build()

SVFIR * SVFIRBuilder::build ( )
virtual

Start building SVFIR here.

Start building SVFIR here

build icfg

initial external library information initial SVFIR nodes

initial SVFIR edges: // handle globals

build callgraph

handle functions

collect return node of function fun

Return SVFIR node will not be created for function which can not reach the return instruction due to call to abort(), exit(), etc. In 176.gcc of SPEC 2000, function build_objc_string() from c-lang.c shows an example when fun.doesNotReturn() evaluates to TRUE because of abort().

To be noted, we do not record arguments which are in declared function without body TODO: what about external functions with SVFIR imported by commandline?

Definition at line 54 of file SVFIRBuilder.cpp.

55{
56 double startTime = SVFStat::getClk(true);
57
58 DBOUT(DGENERAL, outs() << pasMsg("\t Building SVFIR ...\n"));
59
60 // We read SVFIR from a user-defined txt instead of parsing SVFIR from LLVM IR
62 {
64 return fileBuilder.build();
65 }
66
67 // If the SVFIR has been built before, then we return the unique SVFIR of the program
69 return pag;
70
71
73
76 pag->icfg = icfgbuilder.build();
77
85
86
87
90 std::vector<const FunObjVar*> funset;
91 for (const auto& item: llvmModuleSet()->getFunctionSet())
92 {
94 }
95 pag->callGraph = callGraphBuilder.buildSVFIRCallGraph(funset);
96
97 CHGraph* chg = new CHGraph();
99 chgbuilder.buildCHG();
100 pag->setCHG(chg);
101
103 for (Module& M : llvmModuleSet()->getLLVMModules())
104 {
105 for (Module::const_iterator F = M.begin(), E = M.end(); F != E; ++F)
106 {
107 const Function& fun = *F;
108 const FunObjVar* svffun = llvmModuleSet()->getFunObjVar(&fun);
110 if(!fun.isDeclaration())
111 {
117 if (fun.doesNotReturn() == false &&
118 fun.getReturnType()->isVoidTy() == false)
119 {
122 }
123
126 for (Function::const_arg_iterator I = fun.arg_begin(), E = fun.arg_end();
127 I != E; ++I)
128 {
129 setCurrentLocation(&*I,&fun.getEntryBlock());
131 // if this is the function does not have caller (e.g. main)
132 // or a dead function, shall we create a black hole address edge for it?
133 // it is (1) too conservative, and (2) make FormalParmVFGNode defined at blackhole address PAGEdge.
134 // if(SVFUtil::ArgInNoCallerFunction(&*I)) {
135 // if(I->getType()->isPointerTy())
136 // addBlackHoleAddrEdge(argValNodeId);
137 //}
139 }
140 }
141 for (Function::const_iterator bit = fun.begin(), ebit = fun.end();
142 bit != ebit; ++bit)
143 {
144 const BasicBlock& bb = *bit;
145 for (BasicBlock::const_iterator it = bb.begin(), eit = bb.end();
146 it != eit; ++it)
147 {
148 const Instruction& inst = *it;
149 setCurrentLocation(&inst,&bb);
150 visit(const_cast<Instruction&>(inst));
151 }
152 }
153 }
154 }
155
156 sanityCheck();
157
159
161
162 // dump SVFIR
164 pag->dump("svfir_initial");
165
166 // print to command line of the SVFIR graph
167 if (Options::PAGPrint())
168 pag->print();
169
170 // dump ICFG
171 if (Options::DumpICFG())
172 pag->getICFG()->dump("icfg_initial");
173
175 {
178 }
179
180 // dump SVFIR as JSON
181 if (!Options::DumpJson().empty())
182 {
183 assert(false && "please implement SVFIRWriter::writeJsonToPath");
184 }
185
186 double endTime = SVFStat::getClk(true);
187 SVFStat::timeOfBuildingSVFIR = (endTime - startTime) / TIMEINTERVAL;
188
189 return pag;
190}
#define DBOUT(TYPE, X)
LLVM debug macros, define type of your DBUG model of each pass.
Definition SVFType.h:512
#define TIMEINTERVAL
Definition SVFType.h:540
#define DGENERAL
Definition SVFType.h:518
cJSON * item
Definition cJSON.h:222
u32_t getTotalNodeNum() const
Get total number of node/edge.
void dump(const std::string &file, bool simple=false)
Dump graph into dot file.
Definition ICFG.cpp:411
u32_t getNodeNumAfterPAGBuild() const
Definition IRGraph.h:313
void dump(std::string name)
Dump SVFIR.
Definition IRGraph.cpp:310
NodeID getReturnNode(const FunObjVar *func) const
GetReturnNode - Return the unique node representing the return value of a function.
Definition IRGraph.cpp:60
void setNodeNumAfterPAGBuild(u32_t num)
Definition IRGraph.h:317
virtual void build(ICFG *icfg)
Start from here.
NodeID getValueNode(const Value *V)
const FunObjVar * getFunObjVar(const Function *fun) const
Definition LLVMModule.h:267
static const Option< bool > PAGDotGraph
Definition Options.h:118
static const Option< std::string > DumpJson
Definition Options.h:121
static const Option< bool > PAGPrint
Definition Options.h:124
static const Option< bool > LoopAnalysis
Definition Options.h:239
static const Option< bool > DumpICFG
Definition Options.h:120
void sanityCheck()
Sanity check for SVFIR.
void visitGlobal()
Handle globals including (global variable and functions)
void initialiseNodes()
Initialize nodes and edges.
void print()
Print SVFIR.
Definition SVFIR.cpp:557
void addFunArgs(const FunObjVar *fun, const SVFVar *arg)
Get/set method for function/callsite arguments and returns.
Definition SVFIR.h:523
void addFunRet(const FunObjVar *fun, const SVFVar *ret)
Add function returns.
Definition SVFIR.h:530
static std::string pagFileName()
Definition SVFIR.h:202
static bool pagReadFromTXT()
Definition SVFIR.h:207
CallGraph * callGraph
all the callsites of a program
Definition SVFIR.h:99
ICFG * getICFG() const
Definition SVFIR.h:163
void setCHG(CommonCHGraph *c)
Set/Get CHG.
Definition SVFIR.h:169
ICFG * icfg
Definition SVFIR.h:96
void initialiseCandidatePointers()
Initialize candidate pointers.
Definition SVFIR.cpp:642
static double getClk(bool mark=false)
Definition SVFStat.cpp:48
static double timeOfBuildingSVFIR
Definition SVFStat.h:95
const FunObjVar * getFunObjVar(const std::string &name)
Definition LLVMUtil.cpp:435
std::string pasMsg(const std::string &msg)
Print each pass/phase message by converting a string into blue string output.
Definition SVFUtil.cpp:101
std::ostream & outs()
Overwrite llvm::outs()
Definition SVFUtil.h:52
llvm::BasicBlock BasicBlock
Definition BasicTypes.h:86
llvm::Function Function
Definition BasicTypes.h:85
llvm::Module Module
Definition BasicTypes.h:84

◆ computeGepOffset()

bool SVFIRBuilder::computeGepOffset ( const User V,
AccessPath ap 
)
protected

Compute offset of a gep instruction or gep constant expression.

Return the object node offset according to GEP insn (V). Given a gep edge p = q + i, if "i" is a constant then we return its offset size otherwise if "i" is a variable determined by runtime, then it is a variant offset Return TRUE if the offset of this GEP insn is a constant.

Definition at line 642 of file SVFIRBuilder.cpp.

643{
644 assert(V);
645
646 const llvm::GEPOperator *gepOp = SVFUtil::dyn_cast<const llvm::GEPOperator>(V);
647 DataLayout * dataLayout = getDataLayout(llvmModuleSet()->getMainLLVMModule());
648 llvm::APInt byteOffset(dataLayout->getIndexSizeInBits(gepOp->getPointerAddressSpace()),0,true);
649 if(gepOp && dataLayout && gepOp->accumulateConstantOffset(*dataLayout,byteOffset))
650 {
651 //s32_t bo = byteOffset.getSExtValue();
652 }
653
654 bool isConst = true;
655
656 bool prevPtrOperand = false;
658 gi != ge; ++gi)
659 {
660 const Type* gepTy = *gi;
662
663 assert((prevPtrOperand && svfGepTy->isPointerTy()) == false &&
664 "Expect no more than one gep operand to be of a pointer type");
665 if(!prevPtrOperand && svfGepTy->isPointerTy()) prevPtrOperand = true;
666 const Value* offsetVal = gi.getOperand();
667 assert(gepTy != offsetVal->getType() && "iteration and operand have the same type?");
669
670 //The int value of the current index operand
671 const ConstantInt* op = SVFUtil::dyn_cast<ConstantInt>(offsetVal);
672
673 // if Options::ModelConsts() is disabled. We will treat whole array as one,
674 // but we can distinguish different field of an array of struct, e.g. s[1].f1 is different from s[0].f2
675 if(const ArrayType* arrTy = SVFUtil::dyn_cast<ArrayType>(gepTy))
676 {
677 if(!op || (arrTy->getArrayNumElements() <= (u32_t)LLVMUtil::getIntegerValue(op).first))
678 continue;
682 }
683 else if (const StructType *ST = SVFUtil::dyn_cast<StructType>(gepTy))
684 {
685 assert(op && "non-const offset accessing a struct");
686 //The actual index
690 }
691 else if (gepTy->isSingleValueType())
692 {
693 // If it's a non-constant offset access
694 // If its point-to target is struct or array, it's likely an array accessing (%result = gep %struct.A* %a, i32 %non-const-index)
695 // If its point-to target is single value (pointer arithmetic), then it's a variant gep (%result = gep i8* %p, i32 %non-const-index)
696 if(!op && gepTy->isPointerTy() && gepOp->getSourceElementType()->isSingleValueType())
697 {
698 isConst = false;
699 }
700
701 // The actual index
702 //s32_t idx = op->getSExtValue();
703
704 // For pointer arithmetic we ignore the byte offset
705 // consider using inferFieldIdxFromByteOffset(geopOp,dataLayout,ap,idx)?
706 // ap.setFldIdx(ap.getConstantFieldIdx() + inferFieldIdxFromByteOffset(geopOp,idx));
707 }
708 }
709 return isConst;
710}
buffer offset
Definition cJSON.cpp:1113
bool addOffsetVarAndGepTypePair(const SVFVar *var, const SVFType *gepIterType)
APOffset getConstantStructFldIdx() const
Get methods.
Definition AccessPath.h:99
void setFldIdx(APOffset idx)
Definition AccessPath.h:103
u32_t getFlattenedElemIdx(const SVFType *T, u32_t origId)
Flattened element idx of an array or struct by considering stride.
Definition IRGraph.cpp:144
SVFType * getSVFType(const Type *T)
Get or create SVFType and typeinfo.
SVFIR * getPAG() const
Return SVFIR.
std::pair< s64_t, u64_t > getIntegerValue(const ConstantInt *intValue)
Definition LLVMUtil.h:82
static DataLayout * getDataLayout(Module *mod)
Definition LLVMUtil.h:313
llvm::DataLayout DataLayout
Definition BasicTypes.h:108
llvm::ArrayType ArrayType
Definition BasicTypes.h:95
llvm::StructType StructType
LLVM types.
Definition BasicTypes.h:94
s64_t APOffset
Definition GeneralType.h:60
unsigned u32_t
Definition GeneralType.h:47
llvm::ConstantInt ConstantInt
Definition BasicTypes.h:125
bridge_gep_iterator bridge_gep_end(const User *GEP)
bridge_gep_iterator bridge_gep_begin(const User *GEP)

◆ createFunObjVars()

void SVFIRBuilder::createFunObjVars ( )

set fun in bb

Definition at line 331 of file SVFIRBuilder.cpp.

332{
333 std::vector<FunObjVar*> funset;
334 // Iterate over all object symbols in the symbol table
335 for (const auto* fun: llvmModuleSet()->getFunctionSet())
336 {
337 u32_t id = llvmModuleSet()->objSyms()[fun];
338 // Debug output for adding object node
339 DBOUT(DPAGBuild, outs() << "add obj node " << id << "\n");
340
341 // Check if the value is a function and add a function object node
342 pag->addFunObjNode(id, pag->getObjTypeInfo(id), llvmModuleSet()->getSVFType(fun->getType()), nullptr);
344
345 FunObjVar *funObjVar = SVFUtil::cast<FunObjVar>(pag->getGNode(id));
346 funset.push_back(funObjVar);
347
348 funObjVar->initFunObjVar(fun->isDeclaration(), LLVMUtil::isIntrinsicFun(fun), fun->hasAddressTaken(),
350 SVFUtil::cast<SVFFunctionType>(llvmModuleSet()->getSVFType(fun->getFunctionType())),
351 new SVFLoopAndDomInfo, nullptr, nullptr,
352 {}, nullptr);
353 BasicBlockGraph* bbGraph = new BasicBlockGraph();
354 funObjVar->setBasicBlockGraph(bbGraph);
355
356
357 for (const BasicBlock& bb : *fun)
358 {
359 llvmModuleSet()->addBasicBlock(funObjVar, &bb);
360 }
361
363 for (auto& bb: *funObjVar->bbGraph)
364 {
365 bb.second->setFun(funObjVar);
366 }
368 }
369
371}
#define DPAGBuild
Definition SVFType.h:520
void setBasicBlockGraph(BasicBlockGraph *graph)
void initFunObjVar(bool decl, bool intrinc, bool addr, bool uncalled, bool notret, bool vararg, const SVFFunctionType *ft, SVFLoopAndDomInfo *ld, const FunObjVar *real, BasicBlockGraph *bbg, const std::vector< const ArgValVar * > &allarg, const SVFBasicBlock *exit)
ObjTypeInfo * getObjTypeInfo(NodeID id) const
Definition IRGraph.h:234
LLVMFun2FunObjVarMap LLVMFun2FunObjVar
Map an LLVM Function to an SVF Funobjvar.
Definition LLVMModule.h:99
ValueToIDMapTy & objSyms()
Definition LLVMModule.h:212
void addBasicBlock(FunObjVar *fun, const BasicBlock *bb)
Definition LLVMModule.h:232
NodeID addFunObjNode(NodeID id, ObjTypeInfo *ti, const SVFType *type, const ICFGNode *node)
Definition SVFIR.h:644
bool isUncalledFunction(const Function *fun)
whether this is a function without any possible caller?
Definition LLVMUtil.cpp:157
bool isIntrinsicFun(const Function *func)
Definition LLVMUtil.cpp:189
bool functionDoesNotRet(const Function *fun)
Definition LLVMUtil.cpp:122

◆ getAccessPathFromBaseNode()

AccessPath SVFIRBuilder::getAccessPathFromBaseNode ( NodeID  nodeId)
protected

Get a base SVFVar given a pointer Return the source node of its connected normal gep edge Otherwise return the node id itself s32_t offset : gep offset

if this node is already a base node

Definition at line 1806 of file SVFIRBuilder.cpp.

1807{
1808 SVFVar* node = pag->getGNode(nodeId);
1811 if(geps.empty())
1812 return AccessPath(0);
1813
1814 assert(geps.size()==1 && "one node can only be connected by at most one gep edge!");
1815 SVFVar::iterator it = geps.begin();
1816 const GepStmt* gepEdge = SVFUtil::cast<GepStmt>(*it);
1817 if(gepEdge->isVariantFieldGep())
1818 return AccessPath(0);
1819 else
1820 return gepEdge->getAccessPath();
1821}
GEdgeSetTy::iterator iterator
GenericNode< SVFVar, SVFStmt >::GEdgeSetTy SVFStmtSetTy
SVFStmt::SVFStmtSetTy & getIncomingEdges(SVFStmt::PEDGEK kind)
Edge accessors and checkers.

◆ getBaseTypeAndFlattenedFields()

const Type * SVFIRBuilder::getBaseTypeAndFlattenedFields ( const Value V,
std::vector< AccessPath > &  fields,
const Value szValue 
)
protectedvirtual

Handle external call.

Find the base type and the max possible offset of an object pointed to by (V).

use user-specified size for this copy operation if the size is a constaint int

Definition at line 44 of file SVFIRExtAPI.cpp.

45{
46 assert(V);
47 const Value* value = getBaseValueForExtArg(V);
51 if(szValue && SVFUtil::isa<ConstantInt>(szValue))
52 {
53 auto szIntVal = LLVMUtil::getIntegerValue(SVFUtil::cast<ConstantInt>(szValue));
54 numOfElems = (numOfElems > szIntVal.first) ? szIntVal.first : numOfElems;
55 }
56
58 for(u32_t ei = 0; ei < numOfElems; ei++)
59 {
61 // make a ConstantInt and create char for the content type due to byte-wise copy
62 const ConstantInt* offset = ConstantInt::get(context, llvm::APInt(32, ei));
63 if (!llvmModuleSet()->hasValueNode(offset))
64 {
66 builder.collectSym(offset);
68 pag->addConstantIntValNode(id, LLVMUtil::getIntegerValue(offset), nullptr, llvmModuleSet()->getSVFType(offset->getType()));
70 pag->getGNode(id));
71 }
72 ls.addOffsetVarAndGepTypePair(getPAG()->getGNode(llvmModuleSet()->getValueNode(offset)), nullptr);
73 fields.push_back(ls);
74 }
75 return objType;
76}
u32_t getNumOfFlattenElements(const SVFType *T)
Definition IRGraph.cpp:169
ObjTypeInference * getTypeInference()
const Type * inferObjType(const Value *var)
get or infer the type of the object pointed by the value
const Value * getBaseValueForExtArg(const Value *V)
Get the base value of (i8* src and i8* dst) for external argument (e.g. memcpy(i8* dst,...
NodeID addConstantIntValNode(NodeID i, const std::pair< s64_t, u64_t > &intValue, const ICFGNode *icfgNode, const SVFType *type)
Definition SVFIR.h:586

◆ getBaseValueForExtArg()

const Value * SVFIRBuilder::getBaseValueForExtArg ( const Value V)
protected

Get the base value of (i8* src and i8* dst) for external argument (e.g. memcpy(i8* dst, i8* src, int size))

Example 1:

%0 = getelementptr inbounds struct.outer, struct.inner base, i32 0, i32 0 call void @llvm.memcpy(ptr inner, ptr %0, i64 24, i1 false) The base value for %0 is base. Note: the base is recognized as the base value if the offset (field index) is 0

Example 2: https://github.com/SVF-tools/SVF/issues/1650 https://github.com/SVF-tools/SVF/pull/1652

@i1 = dso_local global struct.inner { i32 0, ptr @f1, ptr @f2 } @n1 = dso_local global struct.outer { i32 0, ptr @i1 }

inner = alloca struct.inner %0 = load ptr, ptr getelementptr inbounds (struct.outer, ptr @n1, i32 0, i32 1) call void @llvm.memcpy(ptr inner, ptr %0, i64 24, i1 false)

The base value for %0 is @i1

Example 3:

@conststruct = internal global <{ [40 x i8], [4 x i8], [4 x i8], [2512 x i8] }> <{ [40 x i8] undef, [4 x i8] zeroinitializer, [4 x i8] undef, [2512 x i8] zeroinitializer }>, align 8

%0 = load ptr, ptr getelementptr inbounds (<{ [40 x i8], [4 x i8], [4 x i8], [2512 x i8] }>, ptr @conststruct, i64 0, i32 0, i64 16)

The base value for %0 is still %0

Definition at line 1537 of file SVFIRBuilder.cpp.

1538{
1539 const Value* value = stripAllCasts(V);
1540 assert(value && "null ptr?");
1541 if(const GetElementPtrInst* gep = SVFUtil::dyn_cast<GetElementPtrInst>(value))
1542 {
1543 APOffset totalidx = 0;
1545 {
1546 if(const ConstantInt* op = SVFUtil::dyn_cast<ConstantInt>(gi.getOperand()))
1548 }
1549 if(totalidx == 0 && !SVFUtil::isa<StructType>(value->getType()))
1550 value = gep->getPointerOperand();
1551 }
1552 else if (const LoadInst* load = SVFUtil::dyn_cast<LoadInst>(value))
1553 {
1554 const Value* loadP = load->getPointerOperand();
1555 if (const GetElementPtrInst* gep = SVFUtil::dyn_cast<GetElementPtrInst>(loadP))
1556 {
1557 APOffset totalidx = 0;
1559 {
1560 if(const ConstantInt* op = SVFUtil::dyn_cast<ConstantInt>(gi.getOperand()))
1562 }
1563 const Value * pointer_operand = gep->getPointerOperand();
1564 if (auto *glob = SVFUtil::dyn_cast<GlobalVariable>(pointer_operand))
1565 {
1566 if (glob->hasInitializer())
1567 {
1568 if (auto *initializer = SVFUtil::dyn_cast<
1569 ConstantStruct>(glob->getInitializer()))
1570 {
1571 /*
1572 *@conststruct = internal global <{ [40 x i8], [4 x i8], [4 x i8], [2512 x i8] }>
1573 <{ [40 x i8] undef, [4 x i8] zeroinitializer, [4 x i8] undef, [2512 x i8] zeroinitializer }>, align 8
1574
1575 %0 = load ptr, ptr getelementptr inbounds (<{ [40 x i8], [4 x i8], [4 x i8], [2512 x i8] }>,
1576 ptr @conststruct, i64 0, i32 0, i64 16)
1577 in this case, totalidx is 16 while initializer->getNumOperands() is 4, so we return value as the base
1578 */
1579 if (totalidx >= initializer->getNumOperands()) return value;
1580 auto *ptrField = initializer->getOperand(totalidx);
1581 if (auto *ptrValue = SVFUtil::dyn_cast<llvm::GlobalVariable>(ptrField))
1582 {
1583 return ptrValue;
1584 }
1585 }
1586 }
1587 }
1588 }
1589 }
1590
1591 return value;
1592}
const Value * stripAllCasts(const Value *val)
Strip off the all casts.
Definition LLVMUtil.cpp:249
LLVM_NODISCARD std::enable_if_t<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type > dyn_cast(const Y &Val)
Definition Casting.h:405
llvm::ConstantStruct ConstantStruct
Definition BasicTypes.h:106
llvm::LoadInst LoadInst
Definition BasicTypes.h:149
llvm::GetElementPtrInst GetElementPtrInst
Definition BasicTypes.h:162

◆ getCopyKind()

CopyStmt::CopyKind SVF::SVFIRBuilder::getCopyKind ( const Value val)
inlineprotected

Definition at line 379 of file SVFIRBuilder.h.

380 {
381 // COPYVAL, ZEXT, SEXT, BITCAST, FPTRUNC, FPTOUI, FPTOSI, UITOFP, SITOFP, INTTOPTR, PTRTOINT
382 if (const Instruction* inst = SVFUtil::dyn_cast<Instruction>(val))
383 {
384 switch (inst->getOpcode())
385 {
386 case Instruction::ZExt:
387 return CopyStmt::ZEXT;
388 case Instruction::SExt:
389 return CopyStmt::SEXT;
390 case Instruction::BitCast:
391 return CopyStmt::BITCAST;
392 case Instruction ::Trunc:
393 return CopyStmt::TRUNC;
394 case Instruction::FPTrunc:
395 return CopyStmt::FPTRUNC;
396 case Instruction::FPToUI:
397 return CopyStmt::FPTOUI;
398 case Instruction::FPToSI:
399 return CopyStmt::FPTOSI;
400 case Instruction::UIToFP:
401 return CopyStmt::UITOFP;
402 case Instruction::SIToFP:
403 return CopyStmt::SITOFP;
404 case Instruction::IntToPtr:
405 return CopyStmt::INTTOPTR;
406 case Instruction::PtrToInt:
407 return CopyStmt::PTRTOINT;
408 default:
409 return CopyStmt::COPYVAL;
410 }
411 }
412 assert (false && "Unknown cast inst!");
413 abort();
414 }

◆ getCurrentBB()

const SVFBasicBlock * SVF::SVFIRBuilder::getCurrentBB ( ) const
inlineprotected

Definition at line 263 of file SVFIRBuilder.h.

264 {
265 return curBB;
266 }

◆ getCurrentValue()

const Value * SVF::SVFIRBuilder::getCurrentValue ( ) const
inlineprotected

Definition at line 259 of file SVFIRBuilder.h.

260 {
261 return curVal;
262 }

◆ getGepValVar()

NodeID SVFIRBuilder::getGepValVar ( const Value val,
const AccessPath ap,
const SVFType elementType 
)
protected

Add a temp field value node according to base value and offset this node is after the initial node method, it is out of scope of symInfo table

Definition at line 1664 of file SVFIRBuilder.cpp.

1665{
1666 NodeID base = getValueNode(val);
1668 if (gepval==UINT_MAX)
1669 {
1670 assert(((int) UINT_MAX)==-1 && "maximum limit of unsigned int is not -1?");
1671 /*
1672 * getGepValVar can only be called from two places:
1673 * 1. SVFIRBuilder::addComplexConsForExt to handle external calls
1674 * 2. SVFIRBuilder::getGlobalVarField to initialize global variable
1675 * so curVal can only be
1676 * 1. Instruction
1677 * 2. GlobalVariable
1678 */
1679 assert(
1680 (SVFUtil::isa<Instruction>(curVal) || SVFUtil::isa<GlobalVariable>(curVal)) && "curVal not an instruction or a globalvariable?");
1681
1682 // We assume every GepValNode and its GepEdge to the baseNode are unique across the whole program
1683 // We preserve the current BB information to restore it after creating the gepNode
1684 const Value* cval = getCurrentValue();
1685 const SVFBasicBlock* cbb = getCurrentBB();
1688 const ICFGNode* node = nullptr;
1689 if (const Instruction* inst = SVFUtil::dyn_cast<Instruction>(curVal))
1690 if (llvmmodule->hasICFGNode(inst))
1691 {
1692 node = llvmmodule->getICFGNode(inst);
1693 }
1695 NodeIDAllocator::get()->allocateValueId(),
1696 llvmmodule->getSVFType(PointerType::getUnqual(llvmmodule->getContext())), node);
1697 addGepEdge(base, gepNode, ap, true);
1699 return gepNode;
1700 }
1701 else
1702 return gepval;
1703}
static NodeIDAllocator * get(void)
Return (singleton) allocator.
void addGepEdge(NodeID src, NodeID dst, const AccessPath &ap, bool constGep)
Add Gep edge.
NodeID getGepValVar(NodeID curInst, NodeID base, const AccessPath &ap) const
Due to constraint expression, curInst is used to distinguish different instructions (e....
Definition SVFIR.cpp:522
NodeID addGepValNode(NodeID curInst, const ValVar *base, const AccessPath &ap, NodeID i, const SVFType *type, const ICFGNode *node)
Add a temp field value node, this method can only invoked by getGepValVar.
Definition SVFIR.cpp:403

◆ getGlobalVarField()

NodeID SVFIRBuilder::getGlobalVarField ( const GlobalVariable gvar,
u32_t  offset,
SVFType tpy 
)
protected

Get the field of the global variable node FIXME:Here we only get the field that actually used in the program We ignore the initialization of global variable field that not used in the program

if we did not find the constant expression in the program, then we need to create a gep node for this field

Definition at line 846 of file SVFIRBuilder.cpp.

847{
848
849 // if the global variable do not have any field needs to be initialized
850 if (offset == 0 && gvar->getInitializer()->getType()->isSingleValueType())
851 {
852 return getValueNode(gvar);
853 }
856 else
857 {
859 }
860}

◆ getObjectNode()

NodeID SVF::SVFIRBuilder::getObjectNode ( const Value V)
inline

GetObject - Return the object node (stack/global/heap/function) according to a LLVM Value.

Definition at line 107 of file SVFIRBuilder.h.

108 {
109 return llvmModuleSet()->getObjectNode(V);
110 }
NodeID getObjectNode(const Value *V)

◆ getPAG()

SVFIR * SVF::SVFIRBuilder::getPAG ( ) const
inline

Return SVFIR.

Definition at line 69 of file SVFIRBuilder.h.

70 {
71 return pag;
72 }

◆ getReturnNode()

NodeID SVF::SVFIRBuilder::getReturnNode ( const FunObjVar func)
inline

getReturnNode - Return the node representing the unique return value of a function.

Definition at line 113 of file SVFIRBuilder.h.

114 {
115 return pag->getReturnNode(func);
116 }

◆ getValueNode()

NodeID SVF::SVFIRBuilder::getValueNode ( const Value V)
inline

Get different kinds of node.

Definition at line 97 of file SVFIRBuilder.h.

98 {
99 // first handle gep edge if val if a constant expression
100 processCE(V);
101
102 // strip off the constant cast and return the value node
103 return llvmModuleSet()->getValueNode(V);
104 }
void processCE(const Value *val)
Process constant expression.

◆ getVarargNode()

NodeID SVF::SVFIRBuilder::getVarargNode ( const FunObjVar func)
inline

getVarargNode - Return the node representing the unique variadic argument of a function.

Definition at line 119 of file SVFIRBuilder.h.

120 {
121 return pag->getVarargNode(func);
122 }
NodeID getVarargNode(const FunObjVar *func) const
getVarargNode - Return the unique node representing the variadic argument of a variadic function.
Definition IRGraph.cpp:67

◆ handleDirectCall()

void SVFIRBuilder::handleDirectCall ( CallBase cs,
const Function F 
)
protected

Handle direct call.

Add the constraints for a direct, non-external call.

FIXME: this assertion should be placed for correct checking except bug program like 188.ammp, 300.twolf

Definition at line 1443 of file SVFIRBuilder.cpp.

1444{
1445
1446 assert(F);
1450 outs() << "handle direct call " << LLVMUtil::dumpValue(cs) << " callee " << F->getName().str() << "\n");
1451
1452 //Only handle the ret.val. if it's used as a ptr.
1454 //Does it actually return a ptr?
1455 if (!cs->getType()->isVoidTy())
1456 {
1460 }
1461 //Iterators for the actual and formal parameters
1462 u32_t itA = 0, ieA = cs->arg_size();
1463 Function::const_arg_iterator itF = F->arg_begin(), ieF = F->arg_end();
1464 //Go through the fixed parameters.
1465 DBOUT(DPAGBuild, outs() << " args:");
1466 for (; itF != ieF; ++itA, ++itF)
1467 {
1468 //Some programs (e.g. Linux kernel) leave unneeded parameters empty.
1469 if (itA == ieA)
1470 {
1471 DBOUT(DPAGBuild, outs() << " !! not enough args\n");
1472 break;
1473 }
1474 const Value* AA = cs->getArgOperand(itA), *FA = &*itF; //current actual/formal arg
1475
1476 DBOUT(DPAGBuild, outs() << "process actual parm " << llvmModuleSet()->getSVFValue(AA)->toString() << " \n");
1477
1482 }
1483 //Any remaining actual args must be varargs.
1484 if (F->isVarArg())
1485 {
1487 DBOUT(DPAGBuild, outs() << "\n varargs:");
1488 for (; itA != ieA; ++itA)
1489 {
1490 const Value* AA = cs->getArgOperand(itA);
1494 }
1495 }
1496 if(itA != ieA)
1497 {
1500 writeWrnMsg("too many args to non-vararg func.");
1501 writeWrnMsg("(" + callICFGNode->getSourceLoc() + ")");
1502
1503 }
1504}
FunExitICFGNode * getFunExitICFGNode(const FunObjVar *fun)
Add a function exit node.
Definition ICFG.cpp:249
FunEntryICFGNode * getFunEntryICFGNode(const FunObjVar *fun)
Add a function entry node.
Definition ICFG.cpp:242
CallICFGNode * getCallICFGNode(const Instruction *cs)
get a call node
NodeID getVarargNode(const FunObjVar *func)
getVarargNode - Return the node representing the unique variadic argument of a function.
NodeID getReturnNode(const FunObjVar *func)
getReturnNode - Return the node representing the unique return value of a function.
void addRetEdge(NodeID src, NodeID dst, const CallICFGNode *cs, const FunExitICFGNode *exit)
Add Return edge.
void addCallEdge(NodeID src, NodeID dst, const CallICFGNode *cs, const FunEntryICFGNode *entry)
Add Call edge.
std::string dumpValue(const Value *val)
Definition LLVMUtil.cpp:600
void writeWrnMsg(const std::string &msg)
Writes a message run through wrnMsg.
Definition SVFUtil.cpp:68

◆ handleExtCall()

void SVFIRBuilder::handleExtCall ( const CallBase cs,
const Function callee 
)
protectedvirtual

pthread_create has 1 arg. apr_thread_create has 2 arg.

Connect actual parameter to formal parameter of the start routine

handle indirect calls at pthread create APIs e.g., pthread_create(&t1, nullptr, fp, ...); const Value* fun = ThreadAPI::getThreadAPI()->getForkedFun(inst); if(!SVFUtilisa<Function>(fun)) pag->addIndirectCallsites(cs,pag->getValueNode(fun));

If forkedFun does not pass to spawnee as function type but as void pointer remember to update inter-procedural callgraph/SVFIR/SVFG etc. when indirect call targets are resolved We don't connect the callgraph here, further investigation is need to handle mod-ref during SVFG construction.

TODO: inter-procedural SVFIR edges for thread joins

Definition at line 128 of file SVFIRExtAPI.cpp.

129{
131
133 {
137 }
139 {
141 Value* arg = cs->getArgOperand(arg_pos);
142 if (cs->getArgOperand(arg_pos)->getType()->isPointerTy())
143 {
146 NodeID obj = pag->addDummyObjNode(llvmModuleSet()->getSVFType(cs->getArgOperand(arg_pos)->getType()));
147 if (vnArg && dummy && obj)
148 {
151 }
152 }
153 else
154 {
155 writeWrnMsg("Arg receiving new object must be pointer type");
156 }
157 }
159 {
160 // Side-effects similar to void *memcpy(void *dest, const void * src, size_t n)
161 // which copies n characters from memory area 'src' to memory area 'dest'.
162 if(callee->getName().find("iconv") != std::string::npos)
163 addComplexConsForExt(cs->getArgOperand(3), cs->getArgOperand(1), nullptr);
164 else if(callee->getName().find("bcopy") != std::string::npos)
165 addComplexConsForExt(cs->getArgOperand(1), cs->getArgOperand(0), cs->getArgOperand(2));
166 if(cs->arg_size() == 3)
167 addComplexConsForExt(cs->getArgOperand(0), cs->getArgOperand(1), cs->getArgOperand(2));
168 else
169 addComplexConsForExt(cs->getArgOperand(0), cs->getArgOperand(1), nullptr);
170 if(SVFUtil::isa<PointerType>(cs->getType()))
171 addCopyEdge(getValueNode(cs->getArgOperand(0)), getValueNode(cs), CopyStmt::COPYVAL);
172 }
174 {
175 // Side-effects similar to memset(void *str, int c, size_t n)
176 // which copies the character c (an unsigned char) to the first n characters of the string pointed to, by the argument str
177 std::vector<AccessPath> dstFields;
178 const Type *dtype = getBaseTypeAndFlattenedFields(cs->getArgOperand(0), dstFields, cs->getArgOperand(2));
179 u32_t sz = dstFields.size();
180 //For each field (i), add store edge *(arg0 + i) = arg1
181 for (u32_t index = 0; index < sz; index++)
182 {
185 dstFields[index].getConstantStructFldIdx());
186 NodeID dField = getGepValVar(cs->getArgOperand(0), dstFields[index], dElementType);
187 addStoreEdge(getValueNode(cs->getArgOperand(1)),dField);
188 }
189 if(SVFUtil::isa<PointerType>(cs->getType()))
190 addCopyEdge(getValueNode(cs->getArgOperand(0)), getValueNode(cs), CopyStmt::COPYVAL);
191 }
192 else if(callee->getName().compare("dlsym") == 0)
193 {
194 /*
195 Side-effects of void* dlsym( void* handle, const char* funName),
196 Locate the function with the name "funName," then add a "copy" edge between the callsite and that function.
197 dlsym() example:
198 int main() {
199 // Open the shared library
200 void* handle = dlopen("./my_shared_library.so", RTLD_LAZY);
201 // Find the function address
202 void (*myFunctionPtr)() = (void (*)())dlsym(handle, "myFunction");
203 // Call the function
204 myFunctionPtr();
205 }
206 */
207 const Value* src = cs->getArgOperand(1);
208 if(const GetElementPtrInst* gep = SVFUtil::dyn_cast<GetElementPtrInst>(src))
209 src = stripConstantCasts(gep->getPointerOperand());
210
211 auto getHookFn = [](const Value* src)->const Function*
212 {
213 if (!SVFUtil::isa<GlobalVariable>(src))
214 return nullptr;
215
216 auto *glob = SVFUtil::cast<GlobalVariable>(src);
217 if (!glob->hasInitializer() || !SVFUtil::isa<ConstantDataArray>(glob->getInitializer()))
218 return nullptr;
219
220 auto *constarray = SVFUtil::cast<ConstantDataArray>(glob->getInitializer());
221 return LLVMUtil::getProgFunction(constarray->getAsCString().str());
222 };
223
224 if (const Function *fn = getHookFn(src))
225 {
228 }
229 }
230 else if(callee->getName().find("_ZSt29_Rb_tree_insert_and_rebalancebPSt18_Rb_tree_node_baseS0_RS_") != std::string::npos)
231 {
232 // The purpose of this function is to insert a new node into the red-black tree and then rebalance the tree to ensure that the red-black tree properties are maintained.
233 assert(cs->arg_size() == 4 && "_Rb_tree_insert_and_rebalance should have 4 arguments.\n");
234
235 // We have vArg3 points to the entry of _Rb_tree_node_base { color; parent; left; right; }.
236 // Now we calculate the offset from base to vArg3
237 NodeID vnArg3 = llvmModuleSet()->getValueNode(cs->getArgOperand(3));
240
241 // We get all flattened fields of base
243
244 // We summarize the side effects: arg3->parent = arg1, arg3->left = arg1, arg3->right = arg1
245 // Note that arg0 is aligned with "offset".
246 for (APOffset i = offset + 1; i <= offset + 3; ++i)
247 {
248 if((u32_t)i >= fields.size())
249 break;
251 fields[i].getConstantStructFldIdx());
252 NodeID vnD = getGepValVar(cs->getArgOperand(3), fields[i], elementType);
253 NodeID vnS = llvmModuleSet()->getValueNode(cs->getArgOperand(1));
254 if(vnD && vnS)
256 }
257 }
258
260 {
262 if (const FunValVar* funcValVar = SVFUtil::dyn_cast<FunValVar>(valVar))
263 {
268 assert((forkedFun->arg_size() <= 2) && "Size of formal parameter of start routine should be one");
269 if (forkedFun->arg_size() <= 2 && forkedFun->arg_size() >= 1)
270 {
271 const ArgValVar* formalParm = forkedFun->getArg(0);
273 if (actualParm->isPointer() && formalParm->getType()->isPointerTy())
274 {
276 addThreadForkEdge(actualParm->getId(), formalParm->getId(), callICFGNode, entry);
277 }
278 }
279 }
280 else
281 {
286 }
290 }
291
293}
Class representing a function argument variable in the SVFIR.
virtual const FunObjVar * getFunction() const
Get containing function, or null for globals/constants.
const FunObjVar * getDefFunForMultipleModule() const
AddrStmt * addAddrWithHeapSz(NodeID src, NodeID dst, const CallBase *cs)
Add Address edge from ext call with args like "%5 = call i8* @malloc(i64 noundef 5)".
void addThreadForkEdge(NodeID src, NodeID dst, const CallICFGNode *cs, const FunEntryICFGNode *entry)
Add Thread fork edge for parameter passing.
AccessPath getAccessPathFromBaseNode(NodeID nodeId)
CopyStmt * addCopyEdge(NodeID src, NodeID dst, CopyStmt::CopyKind kind)
virtual void addComplexConsForExt(Value *D, Value *S, const Value *sz)
SVFTypeLocSetsPair & getTypeLocSetsMap(NodeID argId)
Given an arg NodeId, get its base SVFType* and all its field location sets.
Definition SVFIR.h:268
NodeID addDummyObjNode(const SVFType *type)
Definition SVFIR.h:491
const Function * getProgFunction(const std::string &funName)
Get program entry function from module.
Definition LLVMUtil.cpp:39
const Value * stripConstantCasts(const Value *val)
Strip off the constant casts.
Definition LLVMUtil.cpp:218
bool isHeapAllocExtCallViaRet(const Instruction *inst)
Definition LLVMUtil.cpp:633
bool isMemcpyExtFun(const Function *fun)
Definition LLVMUtil.cpp:388
bool isHeapAllocExtCallViaArg(const Instruction *inst)
Definition LLVMUtil.cpp:648
bool isMemsetExtFun(const Function *fun)
Definition LLVMUtil.cpp:394
u32_t getHeapAllocHoldingArgPosition(const Function *fun)
Definition LLVMUtil.cpp:400
bool isThreadForkCall(const CallICFGNode *inst)
Definition SVFUtil.h:360
const ValVar * getActualParmAtForkSite(const CallICFGNode *cs)
Return sole argument of the thread routine.
Definition SVFUtil.h:408
const ValVar * getForkedFun(const CallICFGNode *inst)
Return thread fork function.
Definition SVFUtil.h:331

◆ handleIndCall()

void SVFIRBuilder::handleIndCall ( CallBase cs)
protected

Handle indirect call.

Indirect call is resolved on-the-fly during pointer analysis

Definition at line 1597 of file SVFIRBuilder.cpp.

1598{
1600 pag->addIndirectCallsites(cbn,llvmModuleSet()->getValueNode(cs->getCalledOperand()));
1601}
void addIndirectCallsites(const CallICFGNode *cs, NodeID funPtr)
Add indirect callsites.
Definition SVFIR.h:549

◆ inferFieldIdxFromByteOffset()

u32_t SVFIRBuilder::inferFieldIdxFromByteOffset ( const llvm::GEPOperator *  gepOp,
DataLayout dl,
AccessPath ap,
APOffset  idx 
)
protected

Infer field index from byteoffset.

Definition at line 631 of file SVFIRBuilder.cpp.

632{
633 return 0;
634}

◆ initDomTree()

void SVFIRBuilder::initDomTree ( FunObjVar func,
const Function f 
)

Definition at line 263 of file SVFIRBuilder.cpp.

264{
265 if (fun->isDeclaration())
266 return;
267 //process and stored dt & df
270 df.analyze(dt);
272 PostDominatorTree pdt = PostDominatorTree(const_cast<Function&>(*fun));
273 SVFLoopAndDomInfo* ld = svffun->getLoopAndDomInfo();
274
276 for (DominanceFrontierBase::const_iterator dfIter = df.begin(), eDfIter = df.end(); dfIter != eDfIter; dfIter++)
277 {
278 const BasicBlock* keyBB = dfIter->first;
279 const std::set<BasicBlock* >& domSet = dfIter->second;
281 for (const BasicBlock* bbValue:domSet)
282 {
283 valueBasicBlocks.insert(llvmModuleSet()->getSVFBasicBlock(bbValue));
284 }
285 }
286 std::vector<const SVFBasicBlock*> reachableBBs;
287 LLVMUtil::getFunReachableBBs(fun, reachableBBs);
288 ld->setReachableBBs(reachableBBs);
289
290 for (Function::const_iterator bit = fun->begin(), beit = fun->end(); bit!=beit; ++bit)
291 {
292 const BasicBlock &bb = *bit;
294 if (DomTreeNode* dtNode = dt.getNode(&bb))
295 {
296 SVFLoopAndDomInfo::BBSet& bbSet = ld->getDomTreeMap()[svfBB];
297 for (const auto domBB : *dtNode)
298 {
299 const auto* domSVFBB = llvmModuleSet()->getSVFBasicBlock(domBB->getBlock());
300 bbSet.insert(domSVFBB);
301 }
302 }
303
304 if (DomTreeNode* pdtNode = pdt.getNode(&bb))
305 {
306 u32_t level = pdtNode->getLevel();
307 ld->getBBPDomLevel()[svfBB] = level;
308 BasicBlock* idomBB = pdtNode->getIDom()->getBlock();
310 ld->getBB2PIdom()[svfBB] = idom;
311
312 SVFLoopAndDomInfo::BBSet& bbSet = ld->getPostDomTreeMap()[svfBB];
313 for (const auto domBB : *pdtNode)
314 {
315 const auto* domSVFBB = llvmModuleSet()->getSVFBasicBlock(domBB->getBlock());
316 bbSet.insert(domSVFBB);
317 }
318 }
319
320 if (const Loop* loop = loopInfo.getLoopFor(&bb))
321 {
322 for (const BasicBlock* loopBlock : loop->getBlocks())
323 {
325 ld->addToBB2LoopMap(svfBB, loopbb);
326 }
327 }
328 }
329}
SVFBasicBlock * getSVFBasicBlock(const BasicBlock *bb)
Definition LLVMModule.h:298
DominatorTree & getDomTree(const Function *fun)
const Map< const SVFBasicBlock *, BBSet > & getDomFrontierMap() const
Set< const SVFBasicBlock * > BBSet
#define NULL
Definition extapi.c:5
void getFunReachableBBs(const Function *svfFun, std::vector< const SVFBasicBlock * > &bbs)
Get reachable basic block from function entry.
Definition LLVMUtil.cpp:74
llvm::LoopInfo LoopInfo
Definition BasicTypes.h:141
llvm::DomTreeNode DomTreeNode
Definition BasicTypes.h:134
llvm::PostDominatorTree PostDominatorTree
Definition BasicTypes.h:136
llvm::DominanceFrontier DominanceFrontier
Definition BasicTypes.h:135
llvm::Loop Loop
LLVM Loop.
Definition BasicTypes.h:140
llvm::DominatorTree DominatorTree
LLVM Dominators.
Definition BasicTypes.h:133

◆ initFunObjVar()

void SVFIRBuilder::initFunObjVar ( )

Function

set realDefFun for all functions

Definition at line 192 of file SVFIRBuilder.cpp.

193{
194 for (Module& mod : llvmModuleSet()->getLLVMModules())
195 {
197 for (const Function& f : mod.functions())
198 {
201
202 if (!LLVMUtil::isExtCall(&f))
203 {
205 }
208 svffun->setRelDefFun(realfun == nullptr ? nullptr : llvmModuleSet()->getFunObjVar(realfun));
209 }
210 }
211
212 // Store annotations of functions in extapi.bc
213 for (const auto& pair : llvmModuleSet()->ExtFun2Annotations)
214 {
216 }
217
218}
static ExtAPI * getExtAPI()
Definition ExtAPI.cpp:44
void setExtFuncAnnotations(const FunObjVar *fun, const std::vector< std::string > &funcAnnotations)
Definition ExtAPI.cpp:223
const Function * getRealDefFun(const Function *fun) const
Definition LLVMModule.h:185
void initSVFBasicBlock(const Function *func)
void initDomTree(FunObjVar *func, const Function *f)
bool isExtCall(const Function *fun)
Definition LLVMUtil.cpp:383

◆ InitialGlobal()

void SVFIRBuilder::InitialGlobal ( const GlobalVariable gvar,
Constant C,
u32_t  offset 
)
protected

src should not point to anything yet

Definition at line 873 of file SVFIRBuilder.cpp.

875{
876 DBOUT(DPAGBuild, outs() << "global " << llvmModuleSet()->getSVFValue(gvar)->toString() << " constant initializer: " << llvmModuleSet()->getSVFValue(C)->toString() << "\n");
877 if (C->getType()->isSingleValueType())
878 {
879 NodeID src = getValueNode(C);
880 // get the field value if it is available, otherwise we create a dummy field node.
882 NodeID field = getGlobalVarField(gvar, offset, llvmModuleSet()->getSVFType(C->getType()));
883
884 if (SVFUtil::isa<GlobalVariable, Function>(C))
885 {
887 addStoreEdge(src, field);
888 }
889 else if (SVFUtil::isa<ConstantExpr>(C))
890 {
891 // add gep edge of C1 itself is a constant expression
892 processCE(C);
894 addStoreEdge(src, field);
895 }
896 else if (SVFUtil::isa<BlockAddress>(C))
897 {
898 // blockaddress instruction (e.g. i8* blockaddress(@run_vm, %182))
899 // is treated as constant data object for now, see LLVMUtil.h:397, SymbolTableInfo.cpp:674 and SVFIRBuilder.cpp:183-194
900 processCE(C);
903 }
904 else
905 {
907 addStoreEdge(src, field);
909 if (C->getType()->isPtrOrPtrVectorTy() && src != pag->getNullPtr())
911 }
912 }
913 else if (SVFUtil::isa<ConstantArray, ConstantStruct>(C))
914 {
916 return;
917 for (u32_t i = 0, e = C->getNumOperands(); i != e; i++)
918 {
920 InitialGlobal(gvar, SVFUtil::cast<Constant>(C->getOperand(i)), offset + off);
921 }
922 }
923 else if(ConstantData* data = SVFUtil::dyn_cast<ConstantData>(C))
924 {
926 {
927 if(ConstantDataSequential* seq = SVFUtil::dyn_cast<ConstantDataSequential>(data))
928 {
929 for(u32_t i = 0; i < seq->getNumElements(); i++)
930 {
931 u32_t off = pag->getFlattenedElemIdx(llvmModuleSet()->getSVFType(C->getType()), i);
932 Constant* ct = seq->getElementAsConstant(i);
934 }
935 }
936 else
937 {
938 assert((SVFUtil::isa<ConstantAggregateZero, UndefValue>(data)) && "Single value type data should have been handled!");
939 }
940 }
941 }
942 else
943 {
944 //TODO:assert(SVFUtil::isa<ConstantVector>(C),"what else do we have");
945 }
946}
NodeID getConstantNode() const
Definition IRGraph.h:251
static Option< bool > ModelConsts
Definition Options.h:184
static const Option< bool > VtableInSVFIR
Definition Options.h:214
void InitialGlobal(const GlobalVariable *gvar, Constant *C, u32_t offset)
NodeID getGlobalVarField(const GlobalVariable *gvar, u32_t offset, SVFType *tpy)
bool isValVtbl(const Value *val)
Definition CppUtil.cpp:336
llvm::ConstantData ConstantData
Definition BasicTypes.h:116
llvm::Constant Constant
Definition BasicTypes.h:124
llvm::ConstantDataSequential ConstantDataSequential
Definition BasicTypes.h:119

◆ initialiseBaseObjVars()

void SVFIRBuilder::initialiseBaseObjVars ( )

Definition at line 373 of file SVFIRBuilder.cpp.

374{
375 // Iterate over all object symbols in the symbol table
376 for (LLVMModuleSet::ValueToIDMapTy::iterator iter =
377 llvmModuleSet()->objSyms().begin(); iter != llvmModuleSet()->objSyms().end();
378 ++iter)
379 {
380 // Debug output for adding object node
381 DBOUT(DPAGBuild, outs() << "add obj node " << iter->second << "\n");
382
383 // Skip blackhole and constant symbols
384 if(iter->second == pag->blackholeSymID() || iter->second == pag->constantSymID())
385 continue;
386
387 // Get the LLVM value corresponding to the symbol
388 const Value* llvmValue = iter->first;
389
390 const ICFGNode* icfgNode = nullptr;
391 if (const Instruction* inst = SVFUtil::dyn_cast<Instruction>(llvmValue))
392 {
393 if(llvmModuleSet()->hasICFGNode(inst))
394 icfgNode = llvmModuleSet()->getICFGNode(inst);
395 }
396
397 // Check if the value is a function and add a function object node
398 if (SVFUtil::dyn_cast<Function>(llvmValue))
399 {
400 // already one
401 }
402 // Check if the value is a heap object and add a heap object node
404 {
405 NodeID id = llvmModuleSet()->getObjectNode(iter->first);
406 pag->addHeapObjNode(iter->second, pag->getObjTypeInfo(id), llvmModuleSet()->getSVFType(llvmValue->getType()), icfgNode);
407 }
408 // Check if the value is an alloca instruction and add a stack object node
410 {
411 NodeID id = llvmModuleSet()->getObjectNode(iter->first);
412 pag->addStackObjNode(iter->second, pag->getObjTypeInfo(id), llvmModuleSet()->getSVFType(llvmValue->getType()), icfgNode);
413 }
414 else if (auto fpValue = SVFUtil::dyn_cast<ConstantFP>(llvmValue))
415 {
416 NodeID id = llvmModuleSet()->getObjectNode(iter->first);
417 pag->addConstantFPObjNode(iter->second, pag->getObjTypeInfo(id), LLVMUtil::getDoubleValue(fpValue), llvmModuleSet()->getSVFType(llvmValue->getType()), icfgNode);
418 }
419 else if (auto intValue = SVFUtil::dyn_cast<ConstantInt>(llvmValue))
420 {
421 NodeID id = llvmModuleSet()->getObjectNode(iter->first);
422 pag->addConstantIntObjNode(iter->second, pag->getObjTypeInfo(id), LLVMUtil::getIntegerValue(intValue), llvmModuleSet()->getSVFType(llvmValue->getType()), icfgNode);
423 }
424 else if (SVFUtil::isa<ConstantPointerNull>(llvmValue))
425 {
426 NodeID id = llvmModuleSet()->getObjectNode(iter->first);
427 pag->addConstantNullPtrObjNode(iter->second, pag->getObjTypeInfo(id), llvmModuleSet()->getSVFType(llvmValue->getType()), icfgNode);
428 }
429 else if (SVFUtil::isa<GlobalValue>(llvmValue))
430 {
431 NodeID id = llvmModuleSet()->getObjectNode(iter->first);
432 pag->addGlobalObjNode(iter->second,
433 pag->getObjTypeInfo(id),
434 llvmModuleSet()->getSVFType(llvmValue->getType()), icfgNode);
435 }
436 else if (SVFUtil::isa<ConstantData, MetadataAsValue, BlockAddress>(llvmValue))
437 {
438 NodeID id = llvmModuleSet()->getObjectNode(iter->first);
439 pag->addConstantDataObjNode(iter->second, pag->getObjTypeInfo(id), llvmModuleSet()->getSVFType(llvmValue->getType()), icfgNode);
440 }
441 else if (SVFUtil::isa<ConstantAggregate>(llvmValue))
442 {
443 NodeID id = llvmModuleSet()->getObjectNode(iter->first);
444 pag->addConstantAggObjNode(iter->second, pag->getObjTypeInfo(id), llvmModuleSet()->getSVFType(llvmValue->getType()), icfgNode);
445 }
446 // Add a generic object node for other types of values
447 else
448 {
449 NodeID id = llvmModuleSet()->getObjectNode(iter->first);
450 pag->addObjNode(iter->second,
451 pag->getObjTypeInfo(id), llvmModuleSet()->getSVFType(llvmValue->getType()), icfgNode);
452 }
454 }
455
456}
NodeID constantSymID() const
Definition IRGraph.h:188
NodeID blackholeSymID() const
Definition IRGraph.h:193
NodeID addObjNode(NodeID i, ObjTypeInfo *ti, const SVFType *type, const ICFGNode *node)
Add a memory obj node.
Definition SVFIR.h:619
NodeID addGlobalObjNode(const NodeID i, ObjTypeInfo *ti, const SVFType *type, const ICFGNode *node)
Definition SVFIR.h:676
NodeID addConstantFPObjNode(NodeID i, ObjTypeInfo *ti, double dval, const SVFType *type, const ICFGNode *node)
Definition SVFIR.h:652
NodeID addHeapObjNode(NodeID i, ObjTypeInfo *ti, const SVFType *type, const ICFGNode *node)
Definition SVFIR.h:627
NodeID addStackObjNode(NodeID i, ObjTypeInfo *ti, const SVFType *type, const ICFGNode *node)
Definition SVFIR.h:637
NodeID addConstantDataObjNode(const NodeID i, ObjTypeInfo *ti, const SVFType *type, const ICFGNode *node)
Definition SVFIR.h:688
NodeID addConstantAggObjNode(const NodeID i, ObjTypeInfo *ti, const SVFType *type, const ICFGNode *node)
Definition SVFIR.h:682
NodeID addConstantNullPtrObjNode(const NodeID i, ObjTypeInfo *ti, const SVFType *type, const ICFGNode *node)
Definition SVFIR.h:669
NodeID addConstantIntObjNode(NodeID i, ObjTypeInfo *ti, const std::pair< s64_t, u64_t > &intValue, const SVFType *type, const ICFGNode *node)
Definition SVFIR.h:660
double getDoubleValue(const ConstantFP *fpValue)
Definition LLVMUtil.h:54
bool isHeapObj(const Value *val)
Definition LLVMUtil.cpp:682
bool isStackObj(const Value *val)
Definition LLVMUtil.cpp:704

◆ initialiseNodes()

void SVFIRBuilder::initialiseNodes ( )

Initialize nodes and edges.

add address edges for constant nodes.

add argvalvar for svffunctions

Definition at line 536 of file SVFIRBuilder.cpp.

537{
538 DBOUT(DPAGBuild, outs() << "Initialise SVFIR Nodes ...\n");
539
540
545
548
549 for (LLVMModuleSet::FunToIDMapTy::iterator iter =
550 llvmModuleSet()->retSyms().begin(); iter != llvmModuleSet()->retSyms().end();
551 ++iter)
552 {
553 const Value* llvmValue = iter->first;
554 const ICFGNode* icfgNode = nullptr;
555 if (const Instruction* inst = SVFUtil::dyn_cast<Instruction>(llvmValue))
556 {
557 if(llvmModuleSet()->hasICFGNode(inst))
558 icfgNode = llvmModuleSet()->getICFGNode(inst);
559 }
560 DBOUT(DPAGBuild, outs() << "add ret node " << iter->second << "\n");
561 pag->addRetNode(iter->second,
562 llvmModuleSet()->getFunObjVar(SVFUtil::cast<Function>(llvmValue)),
563 llvmModuleSet()->getSVFType(iter->first->getType()), icfgNode);
565 const FunObjVar* funObjVar = llvmModuleSet()->getFunObjVar(SVFUtil::cast<Function>(llvmValue));
566 pag->returnFunObjSymMap[funObjVar] = iter->second;
567 }
568
569 for (LLVMModuleSet::FunToIDMapTy::iterator iter =
570 llvmModuleSet()->varargSyms().begin();
571 iter != llvmModuleSet()->varargSyms().end(); ++iter)
572 {
573 const Value* llvmValue = iter->first;
574
575 const ICFGNode *icfgNode = nullptr;
576 if (const Instruction *inst = SVFUtil::dyn_cast<Instruction>(llvmValue))
577 {
578 if (llvmModuleSet()->hasICFGNode(inst))
579 icfgNode = llvmModuleSet()->getICFGNode(inst);
580 }
581 DBOUT(DPAGBuild, outs() << "add vararg node " << iter->second << "\n");
582 pag->addVarargNode(iter->second,
583 llvmModuleSet()->getFunObjVar(SVFUtil::cast<Function>(llvmValue)),
584 llvmModuleSet()->getSVFType(iter->first->getType()), icfgNode);
586 const FunObjVar* funObjVar = llvmModuleSet()->getFunObjVar(SVFUtil::cast<Function>(llvmValue));
587 pag->varargFunObjSymMap[funObjVar] = iter->second;
588 }
589
591 for (LLVMModuleSet::ValueToIDMapTy::iterator iter =
592 llvmModuleSet()->objSyms().begin(); iter != llvmModuleSet()->objSyms().end(); ++iter)
593 {
594 DBOUT(DPAGBuild, outs() << "add address edges for constant node " << iter->second << "\n");
595 const Value* val = iter->first;
597 {
599 if(ptr!= pag->getBlkPtr() && ptr!= pag->getNullPtr())
600 {
602 addAddrEdge(iter->second, ptr);
603 }
604 }
605 }
606
608 && "not all node have been initialized!!!");
609
611 for (auto& fun: llvmModuleSet()->getFunctionSet())
612 {
613 for (const Argument& arg : fun->args())
614 {
615 const_cast<FunObjVar*>(llvmModuleSet()->getFunObjVar(fun))->addArgument(SVFUtil::cast<ArgValVar>(
617 }
618 }
619
620}
u32_t getTotalSymNum() const
Statistics.
Definition IRGraph.h:200
FunObjVarToIDMapTy varargFunObjSymMap
vararg map
Definition IRGraph.h:87
FunObjVarToIDMapTy returnFunObjSymMap
return map
Definition IRGraph.h:86
FunToIDMapTy & retSyms()
Definition LLVMModule.h:274
bool hasICFGNode(const Instruction *inst)
FunToIDMapTy & varargSyms()
Definition LLVMModule.h:279
NodeID addNullPtrNode()
Add NullPtr PAGNode.
NodeID addBlackholePtrNode()
Definition SVFIR.h:751
NodeID addBlackholeObjNode()
Definition SVFIR.h:743
NodeID addVarargNode(NodeID i, const FunObjVar *val, const SVFType *type, const ICFGNode *n)
Add a unique vararg node for a procedure.
Definition SVFIR.h:702
NodeID addRetNode(NodeID i, const FunObjVar *callGraphNode, const SVFType *type, const ICFGNode *icn)
Add a unique return node for a procedure.
Definition SVFIR.h:696
NodeID addConstantObjNode()
Definition SVFIR.h:747
bool isConstantObjSym(const Value *val)
Check whether this value points-to a constant object.
Definition CppUtil.cpp:672
llvm::Argument Argument
Definition BasicTypes.h:145

◆ initialiseValVars()

void SVFIRBuilder::initialiseValVars ( )

Definition at line 458 of file SVFIRBuilder.cpp.

459{
460 // Iterate over all value symbols in the symbol table
461 for (LLVMModuleSet::ValueToIDMapTy::iterator iter =
462 llvmModuleSet()->valSyms().begin(); iter != llvmModuleSet()->valSyms().end();
463 ++iter)
464 {
465 // Debug output for adding value node
466 DBOUT(DPAGBuild, outs() << "add val node " << iter->second << "\n");
467
468 // Skip blackhole and null pointer symbols
469 if(iter->second == pag->blkPtrSymID() || iter->second == pag->nullPtrSymID())
470 continue;
471
472 const ICFGNode* icfgNode = nullptr;
473 auto llvmValue = iter->first;
474 if (const Instruction* inst =
475 SVFUtil::dyn_cast<Instruction>(llvmValue))
476 {
477 if (llvmModuleSet()->hasICFGNode(inst))
478 {
479 icfgNode = llvmModuleSet()->getICFGNode(inst);
480 }
481 }
482
483 // Check if the value is a function and get its call graph node
484 if (const Function* func = SVFUtil::dyn_cast<Function>(llvmValue))
485 {
486 // add value node representing the function
487 pag->addFunValNode(iter->second, icfgNode, llvmModuleSet()->getFunObjVar(func), llvmModuleSet()->getSVFType(llvmValue->getType()));
488 }
489 else if (auto argval = SVFUtil::dyn_cast<Argument>(llvmValue))
490 {
492 iter->second, argval->getArgNo(), icfgNode,
493 llvmModuleSet()->getFunObjVar(argval->getParent()),llvmModuleSet()->getSVFType(llvmValue->getType()));
494 if (!argval->hasName())
495 pag->getGNode(iter->second)->setName("arg_" + std::to_string(argval->getArgNo()));
496 }
497 else if (auto fpValue = SVFUtil::dyn_cast<ConstantFP>(llvmValue))
498 {
499 pag->addConstantFPValNode(iter->second, LLVMUtil::getDoubleValue(fpValue), icfgNode, llvmModuleSet()->getSVFType(llvmValue->getType()));
500 }
501 else if (auto intValue = SVFUtil::dyn_cast<ConstantInt>(llvmValue))
502 {
503 pag->addConstantIntValNode(iter->second, LLVMUtil::getIntegerValue(intValue), icfgNode, llvmModuleSet()->getSVFType(llvmValue->getType()));
504 }
505 else if (SVFUtil::isa<ConstantPointerNull>(llvmValue))
506 {
507 pag->addConstantNullPtrValNode(iter->second, icfgNode, llvmModuleSet()->getSVFType(llvmValue->getType()));
508 }
509 else if (SVFUtil::isa<GlobalValue>(llvmValue))
510 {
511 pag->addGlobalValNode(iter->second, icfgNode,
512 llvmModuleSet()->getSVFType(llvmValue->getType()));
513 }
514 else if (SVFUtil::isa<ConstantData, MetadataAsValue, BlockAddress>(llvmValue))
515 {
516 pag->addConstantDataValNode(iter->second, icfgNode, llvmModuleSet()->getSVFType(llvmValue->getType()));
517 }
518 else if (SVFUtil::isa<ConstantAggregate>(llvmValue))
519 {
520 pag->addConstantAggValNode(iter->second, icfgNode, llvmModuleSet()->getSVFType(llvmValue->getType()));
521 }
522 else
523 {
524 // Add value node to PAG
525 pag->addValNode(iter->second, llvmModuleSet()->getSVFType(llvmValue->getType()), icfgNode);
526 }
528 pag->getGNode(iter->second));
529 }
530}
NodeID blkPtrSymID() const
Definition IRGraph.h:178
NodeID nullPtrSymID() const
Definition IRGraph.h:183
ValueToIDMapTy & valSyms()
Definition LLVMModule.h:207
NodeID addGlobalValNode(const NodeID i, const ICFGNode *icfgNode, const SVFType *svfType)
Definition SVFIR.h:599
NodeID addConstantDataValNode(const NodeID i, const ICFGNode *icfgNode, const SVFType *type)
Definition SVFIR.h:611
NodeID addFunValNode(NodeID i, const ICFGNode *icfgNode, const FunObjVar *funObjVar, const SVFType *type)
Definition SVFIR.h:566
NodeID addConstantFPValNode(const NodeID i, double dval, const ICFGNode *icfgNode, const SVFType *type)
Definition SVFIR.h:579
NodeID addConstantAggValNode(const NodeID i, const ICFGNode *icfgNode, const SVFType *svfType)
Definition SVFIR.h:605
NodeID addValNode(NodeID i, const SVFType *type, const ICFGNode *icfgNode)
add node into SVFIR
Definition SVFIR.h:560
NodeID addArgValNode(NodeID i, u32_t argNo, const ICFGNode *icfgNode, const FunObjVar *callGraphNode, const SVFType *type)
Definition SVFIR.h:572
virtual void setName(const std::string &nameInfo)
Definition SVFValue.h:176

◆ initSVFBasicBlock()

void SVFIRBuilder::initSVFBasicBlock ( const Function func)

set exit block: exit basic block must have no successors and have a return instruction

Definition at line 220 of file SVFIRBuilder.cpp.

221{
223 for (Function::const_iterator bit = func->begin(), ebit = func->end(); bit != ebit; ++bit)
224 {
225 const BasicBlock* bb = &*bit;
228 {
231 }
233 {
236 }
237
239 if (svfbb->getSuccessors().empty())
240 {
242 {
244 SVFUtil::isa<ReturnInst>(bb->back())) &&
245 "last inst must be return inst");
246 svfFun->setExitBlock(svfbb);
247 }
248 }
249 }
250 // For no return functions, we set the last block as exit BB
251 // This ensures that each function that has definition must have an exit BB
252 if (svfFun->hasBasicBlock() && svfFun->exitBlock == nullptr)
253 {
254 SVFBasicBlock* retBB = const_cast<SVFBasicBlock*>(svfFun->back());
256 SVFUtil::isa<ReturnInst>(&func->back().back())) &&
257 "last inst must be return inst");
258 svfFun->setExitBlock(retBB);
259 }
260}
void addPredBasicBlock(const SVFBasicBlock *pred2)
void addSuccBasicBlock(const SVFBasicBlock *succ2)
bool basicBlockHasRetInst(const BasicBlock *bb)
Return true if the function has a return instruction.
Definition LLVMUtil.cpp:108
llvm::succ_const_iterator succ_const_iterator
LLVM Iterators.
Definition BasicTypes.h:276
llvm::const_pred_iterator const_pred_iterator
Definition BasicTypes.h:254

◆ llvmModuleSet()

LLVMModuleSet * SVF::SVFIRBuilder::llvmModuleSet ( )
inlineprivate

Definition at line 518 of file SVFIRBuilder.h.

519 {
521 }

◆ processCE()

void SVFIRBuilder::processCE ( const Value val)
protected

Process constant expression.

Handle constant expression, and connect the gep edge

Definition at line 715 of file SVFIRBuilder.cpp.

716{
717 if (const Constant* ref = SVFUtil::dyn_cast<Constant>(val))
718 {
720 {
721 DBOUT(DPAGBuild, outs() << "handle gep constant expression " << llvmModuleSet()->getSVFValue(ref)->toString() << "\n");
722 const Constant* opnd = gepce->getOperand(0);
723 // handle recursive constant express case (gep (bitcast (gep X 1)) 1)
725 auto &GEPOp = llvm::cast<llvm::GEPOperator>(*gepce);
726 Type *pType = GEPOp.getSourceElementType();
727 AccessPath ap(0, llvmModuleSet()->getSVFType(pType));
728 bool constGep = computeGepOffset(gepce, ap);
729 // must invoke pag methods here, otherwise it will be a dead recursion cycle
730 const Value* cval = getCurrentValue();
731 const SVFBasicBlock* cbb = getCurrentBB();
733 /*
734 * The gep edge created are like constexpr (same edge may appear at multiple callsites)
735 * so bb/inst of this edge may be rewritten several times, we treat it as global here.
736 */
739 }
740 else if (const ConstantExpr* castce = isCastConstantExpr(ref))
741 {
742 DBOUT(DPAGBuild, outs() << "handle cast constant expression " << llvmModuleSet()->getSVFValue(ref)->toString() << "\n");
743 const Constant* opnd = castce->getOperand(0);
745 const Value* cval = getCurrentValue();
746 const SVFBasicBlock* cbb = getCurrentBB();
750 }
752 {
753 DBOUT(DPAGBuild, outs() << "handle select constant expression " << llvmModuleSet()->getSVFValue(ref)->toString() << "\n");
754 const Constant* src1 = selectce->getOperand(1);
755 const Constant* src2 = selectce->getOperand(2);
758 const Value* cval = getCurrentValue();
759 const SVFBasicBlock* cbb = getCurrentBB();
761 NodeID cond = llvmModuleSet()->getValueNode(selectce->getOperand(0));
767 }
768 // if we meet a int2ptr, then it points-to black hole
770 {
771 const Constant* opnd = int2Ptrce->getOperand(0);
773 const SVFBasicBlock* cbb = getCurrentBB();
774 const Value* cval = getCurrentValue();
778 }
780 {
781 const Constant* opnd = ptr2Intce->getOperand(0);
783 const SVFBasicBlock* cbb = getCurrentBB();
784 const Value* cval = getCurrentValue();
788 }
790 {
791 // we don't handle trunc and cmp instruction for now
792 const Value* cval = getCurrentValue();
793 const SVFBasicBlock* cbb = getCurrentBB();
798 }
799 else if (isBinaryConstantExpr(ref))
800 {
801 // we don't handle binary constant expression like add(x,y) now
802 const Value* cval = getCurrentValue();
803 const SVFBasicBlock* cbb = getCurrentBB();
808 }
809 else if (isUnaryConstantExpr(ref))
810 {
811 // we don't handle unary constant expression like fneg(x) now
812 const Value* cval = getCurrentValue();
813 const SVFBasicBlock* cbb = getCurrentBB();
818 }
819 else if (SVFUtil::isa<ConstantAggregate>(ref))
820 {
821 // we don't handle constant aggregate like constant vectors
822 }
823 else if (SVFUtil::isa<BlockAddress>(ref))
824 {
825 // blockaddress instruction (e.g. i8* blockaddress(@run_vm, %182))
826 // is treated as constant data object for now, see LLVMUtil.h:397, SymbolTableInfo.cpp:674 and SVFIRBuilder.cpp:183-194
827 const Value* cval = getCurrentValue();
828 const SVFBasicBlock* cbb = getCurrentBB();
833 }
834 else
835 {
836 if(SVFUtil::isa<ConstantExpr>(val))
837 assert(false && "we don't handle all other constant expression for now!");
838 }
839 }
840}
void addSelectStmt(NodeID res, NodeID op1, NodeID op2, NodeID cond)
Add SelectStmt.
bool computeGepOffset(const User *V, AccessPath &ap)
Compute offset of a gep instruction or gep constant expression.
const ConstantExpr * isBinaryConstantExpr(const Value *val)
Definition LLVMUtil.h:290
const ConstantExpr * isInt2PtrConstantExpr(const Value *val)
Definition LLVMUtil.h:225
const ConstantExpr * isSelectConstantExpr(const Value *val)
Definition LLVMUtil.h:255
const ConstantExpr * isTruncConstantExpr(const Value *val)
Definition LLVMUtil.h:265
const ConstantExpr * isPtr2IntConstantExpr(const Value *val)
Definition LLVMUtil.h:235
const ConstantExpr * isUnaryConstantExpr(const Value *val)
Definition LLVMUtil.h:301
const ConstantExpr * isCastConstantExpr(const Value *val)
Definition LLVMUtil.h:245
const ConstantExpr * isGepConstantExpr(const Value *val)
Return corresponding constant expression, otherwise return nullptr.
Definition LLVMUtil.h:215
const ConstantExpr * isCmpConstantExpr(const Value *val)
Definition LLVMUtil.h:279
llvm::ConstantExpr ConstantExpr
Definition BasicTypes.h:120

◆ sanityCheck()

void SVFIRBuilder::sanityCheck ( )

Sanity check for SVFIR.

Definition at line 1638 of file SVFIRBuilder.cpp.

1639{
1640 for (SVFIR::iterator nIter = pag->begin(); nIter != pag->end(); ++nIter)
1641 {
1642 (void) pag->getGNode(nIter->first);
1643 //TODO::
1644 // (1) every source(root) node of a pag tree should be object node
1645 // if a node has no incoming edge, but has outgoing edges
1646 // then it has to be an object node.
1647 // (2) make sure every variable should be initialized
1648 // otherwise it causes the a null pointer, the aliasing relation may not be captured
1649 // when loading a pointer value should make sure
1650 // some value has been store into this pointer before
1651 // q = load p, some value should stored into p first like store w p;
1652 // (3) make sure PAGNode should not have a const expr value (pointer should have unique def)
1653 // (4) look closely into addComplexConsForExt, make sure program locations(e.g.,inst bb)
1654 // are set correctly for dummy gepval node
1655 // (5) reduce unnecessary copy edge (const casts) and ensure correctness.
1656 }
1657}
iterator begin()
Iterators.
IDToNodeMapTy::iterator iterator
Node Iterators.

◆ setCurrentBBAndValueForPAGEdge()

void SVFIRBuilder::setCurrentBBAndValueForPAGEdge ( PAGEdge edge)
protected

We assume every GepValVar and its GepStmt are unique across whole program

We will have one unique function exit ICFGNode for all returns

Definition at line 1719 of file SVFIRBuilder.cpp.

1720{
1722 return;
1723
1724 assert(curVal && "current Val is nullptr?");
1725 edge->setBB(curBB!=nullptr ? curBB : nullptr);
1727 ICFGNode* icfgNode = pag->getICFG()->getGlobalICFGNode();
1729 if (const Instruction* curInst = SVFUtil::dyn_cast<Instruction>(curVal))
1730 {
1731 const FunObjVar* srcFun = edge->getSrcNode()->getFunction();
1732 const FunObjVar* dstFun = edge->getDstNode()->getFunction();
1733 if(srcFun!=nullptr && !SVFUtil::isa<RetPE>(edge) && !SVFUtil::isa<FunValVar>(edge->getSrcNode()) && !SVFUtil::isa<FunObjVar>(edge->getSrcNode()))
1734 {
1735 assert(srcFun==llvmMS->getFunObjVar(curInst->getFunction()) && "SrcNode of the PAGEdge not in the same function?");
1736 }
1737 if(dstFun!=nullptr && !SVFUtil::isa<CallPE>(edge) && !SVFUtil::isa<RetValPN>(edge->getDstNode()))
1738 {
1739 assert(dstFun==llvmMS->getFunObjVar(curInst->getFunction()) && "DstNode of the PAGEdge not in the same function?");
1740 }
1741
1743 if (!(SVFUtil::isa<GepStmt>(edge) && SVFUtil::isa<GepValVar>(edge->getDstNode())))
1744 assert(curBB && "instruction does not have a basic block??");
1745
1747 if(SVFUtil::isa<ReturnInst>(curInst))
1748 {
1749 icfgNode = pag->getICFG()->getFunExitICFGNode(llvmMS->getFunObjVar(curInst->getFunction()));
1750 }
1751 else
1752 {
1753 if(SVFUtil::isa<RetPE>(edge))
1754 icfgNode = llvmMS->getRetICFGNode(SVFUtil::cast<Instruction>(curInst));
1755 else
1756 icfgNode = llvmMS->getICFGNode(SVFUtil::cast<Instruction>(curInst));
1757 }
1758 }
1759 else if (const Argument* arg = SVFUtil::dyn_cast<Argument>(curVal))
1760 {
1762 icfgNode = pag->getICFG()->getFunEntryICFGNode(
1763 llvmModuleSet()->getFunObjVar(SVFUtil::cast<Function>(arg->getParent())));
1764 }
1765 else if (SVFUtil::isa<Constant>(curVal) ||
1766 SVFUtil::isa<Function>(curVal) ||
1767 SVFUtil::isa<MetadataAsValue>(curVal))
1768 {
1769 if (!curBB)
1771 else
1772 {
1773 icfgNode = const_cast<ICFGNode*>(curBB->front());
1774 }
1775 }
1776 else
1777 {
1778 assert(false && "what else value can we have?");
1779 }
1780
1781 pag->addToSVFStmtList(icfgNode,edge);
1782 icfgNode->addSVFStmt(edge);
1783 if(const CallPE* callPE = SVFUtil::dyn_cast<CallPE>(edge))
1784 {
1785 CallICFGNode* callNode = const_cast<CallICFGNode*>(callPE->getCallSite());
1786 FunEntryICFGNode* entryNode = const_cast<FunEntryICFGNode*>(callPE->getFunEntryICFGNode());
1788 SVFUtil::cast<CallCFGEdge>(edge)->addCallPE(callPE);
1789 }
1790 else if(const RetPE* retPE = SVFUtil::dyn_cast<RetPE>(edge))
1791 {
1792 RetICFGNode* retNode = const_cast<RetICFGNode*>(retPE->getCallSite()->getRetICFGNode());
1793 FunExitICFGNode* exitNode = const_cast<FunExitICFGNode*>(retPE->getFunExitICFGNode());
1795 SVFUtil::cast<RetCFGEdge>(edge)->addRetPE(retPE);
1796 }
1797}
const SVFBasicBlock * getEntryBlock() const
void addSVFStmt(const SVFStmt *edge)
Definition ICFGNode.h:112
ICFGEdge * hasInterICFGEdge(ICFGNode *src, ICFGNode *dst, ICFGEdge::ICFGEdgeK kind)
Definition ICFG.cpp:276
GlobalICFGNode * getGlobalICFGNode() const
Definition ICFG.h:230
const FunObjVar * getParent() const
const ICFGNode * front() const
void addToSVFStmtList(ICFGNode *inst, SVFStmt *edge)
Add a SVFStmt into instruction map.
Definition SVFIR.h:255
void addGlobalPAGEdge(const SVFStmt *edge)
Add global PAGEdges (not in a procedure)
Definition SVFIR.h:787

◆ setCurrentLocation() [1/2]

void SVF::SVFIRBuilder::setCurrentLocation ( const Value val,
const BasicBlock bb 
)
inlineprotected

Set current basic block in order to keep track of control flow information.

Definition at line 249 of file SVFIRBuilder.h.

250 {
251 curBB = (bb == nullptr? nullptr : llvmModuleSet()->getSVFBasicBlock(bb));
252 curVal = (val == nullptr ? nullptr: val);
253 }

◆ setCurrentLocation() [2/2]

void SVF::SVFIRBuilder::setCurrentLocation ( const Value val,
const SVFBasicBlock bb 
)
inlineprotected

Definition at line 254 of file SVFIRBuilder.h.

255 {
256 curBB = bb;
257 curVal = val;
258 }

◆ updateCallGraph()

void SVFIRBuilder::updateCallGraph ( CallGraph callgraph)

connect PAG edges based on callgraph

Definition at line 1603 of file SVFIRBuilder.cpp.

1604{
1605 CallGraph::CallEdgeMap::const_iterator iter = callgraph->getIndCallMap().begin();
1606 CallGraph::CallEdgeMap::const_iterator eiter = callgraph->getIndCallMap().end();
1607 for (; iter != eiter; iter++)
1608 {
1609 const CallICFGNode* callBlock = iter->first;
1610 const CallBase* callbase = SVFUtil::cast<CallBase>(llvmModuleSet()->getLLVMValue(callBlock));
1611 assert(callBlock->isIndirectCall() && "this is not an indirect call?");
1612 const CallGraph::FunctionSet& functions = iter->second;
1613 for (CallGraph::FunctionSet::const_iterator func_iter = functions.begin(); func_iter != functions.end(); func_iter++)
1614 {
1615 const Function* callee = SVFUtil::cast<Function>(llvmModuleSet()->getLLVMValue(*func_iter));
1616
1617 if (isExtCall(*func_iter))
1618 {
1619 setCurrentLocation(callee, callee->empty() ? nullptr : &callee->getEntryBlock());
1621 }
1622 else
1623 {
1624 setCurrentLocation(llvmModuleSet()->getLLVMValue(callBlock), callBlock->getBB());
1625 handleDirectCall(const_cast<CallBase*>(callbase), callee);
1626 }
1627 }
1628 }
1629
1630 // dump SVFIR
1632 pag->dump("svfir_final");
1633}
CallEdgeMap & getIndCallMap()
Get callees from an indirect callsite.
Definition CallGraph.h:319
Set< const FunObjVar * > FunctionSet
Definition CallGraph.h:244
void handleDirectCall(CallBase *cs, const Function *F)
Handle direct call.
virtual void handleExtCall(const CallBase *cs, const Function *callee)
llvm::CallBase CallBase
Definition BasicTypes.h:146

◆ visitAllocaInst()

void SVFIRBuilder::visitAllocaInst ( AllocaInst inst)
virtual

Our visit overrides.

Visit alloca instructions Add edge V (dst) <– O (src), V here is a value node on SVFIR, O is object node on SVFIR

Definition at line 1004 of file SVFIRBuilder.cpp.

1005{
1006
1007 // AllocaInst should always be a pointer type
1008 assert(SVFUtil::isa<PointerType>(inst.getType()));
1009
1010 DBOUT(DPAGBuild, outs() << "process alloca " << llvmModuleSet()->getSVFValue(&inst)->toString() << " \n");
1011 NodeID dst = getValueNode(&inst);
1012
1013 NodeID src = getObjectNode(&inst);
1014
1015 addAddrWithStackArraySz(src, dst, inst);
1016
1017}
NodeID getObjectNode(const Value *V)
GetObject - Return the object node (stack/global/heap/function) according to a LLVM Value.
AddrStmt * addAddrWithStackArraySz(NodeID src, NodeID dst, llvm::AllocaInst &inst)
Add Address edge from allocinst with arraysize like "%4 = alloca i8, i64 3".

◆ visitAtomicCmpXchgInst()

void SVF::SVFIRBuilder::visitAtomicCmpXchgInst ( AtomicCmpXchgInst I)
inline

Definition at line 194 of file SVFIRBuilder.h.

195 {
197 }

◆ visitAtomicRMWInst()

void SVF::SVFIRBuilder::visitAtomicRMWInst ( AtomicRMWInst I)
inline

Definition at line 198 of file SVFIRBuilder.h.

199 {
201 }

◆ visitBinaryOperator()

void SVFIRBuilder::visitBinaryOperator ( BinaryOperator inst)

Visit Binary Operator

Definition at line 1119 of file SVFIRBuilder.cpp.

1120{
1121 NodeID dst = getValueNode(&inst);
1122 assert(inst.getNumOperands() == 2 && "not two operands for BinaryOperator?");
1123 Value* op1 = inst.getOperand(0);
1125 Value* op2 = inst.getOperand(1);
1127 u32_t opcode = inst.getOpcode();
1128 addBinaryOPEdge(op1Node, op2Node, dst, opcode);
1129}
void addBinaryOPEdge(NodeID op1, NodeID op2, NodeID dst, u32_t opcode)
Add Copy edge.

◆ visitBranchInst()

void SVFIRBuilder::visitBranchInst ( BranchInst inst)

Branch and switch instructions are treated as UnaryOP br cmp label if.then, label if.else

set conditional svf var

Definition at line 1298 of file SVFIRBuilder.cpp.

1299{
1300 NodeID brinst = getValueNode(&inst);
1301 NodeID cond;
1302 if (inst.isConditional())
1303 cond = getValueNode(inst.getCondition());
1304 else
1305 cond = pag->getNullPtr();
1306
1307 assert(inst.getNumSuccessors() <= 2 && "if/else has more than two branches?");
1308
1310 std::vector<const Instruction*> nextInsts;
1312 u32_t branchID = 0;
1313 for (const Instruction* succInst : nextInsts)
1314 {
1315 assert(branchID <= 1 && "if/else has more than two branches?");
1316 const ICFGNode* icfgNode = llvmModuleSet()->getICFGNode(succInst);
1317 successors.push_back(std::make_pair(icfgNode, 1-branchID));
1318 branchID++;
1319 }
1320 addBranchStmt(brinst, cond, successors);
1322 if (inst.isConditional())
1323 {
1324 for (auto& edge : llvmModuleSet()->getICFGNode(&inst)->getOutEdges())
1325 {
1326 if (IntraCFGEdge* intraEdge = SVFUtil::dyn_cast<IntraCFGEdge>(edge))
1327 {
1328 intraEdge->setConditionVar(pag->getGNode(cond));
1329 }
1330 }
1331 }
1332}
std::vector< std::pair< const ICFGNode *, s32_t > > SuccAndCondPairVec
void addBranchStmt(NodeID br, NodeID cond, const BranchStmt::SuccAndCondPairVec &succs)
Add Branch statement.
void getNextInsts(const Instruction *curInst, std::vector< const Instruction * > &instList)
Get the next instructions following control flow.
Definition LLVMUtil.cpp:573

◆ visitCallBrInst()

void SVFIRBuilder::visitCallBrInst ( CallBrInst I)

Definition at line 1186 of file SVFIRBuilder.cpp.

1187{
1188 visitCallSite(&i);
1189}
void visitCallSite(CallBase *cs)

◆ visitCallInst()

void SVFIRBuilder::visitCallInst ( CallInst I)

Definition at line 1176 of file SVFIRBuilder.cpp.

1177{
1178 visitCallSite(&i);
1179}

◆ visitCallSite()

void SVFIRBuilder::visitCallSite ( CallBase cs)

Collect callsite arguments and returns

Definition at line 1194 of file SVFIRBuilder.cpp.

1195{
1196
1197 // skip llvm intrinsics
1198 if(isIntrinsicInst(cs))
1199 return;
1200
1202 outs() << "process callsite " << svfcall->valueOnlyToString() << "\n");
1203
1204
1205 CallICFGNode* callBlockNode = llvmModuleSet()->getCallICFGNode(cs);
1207
1208 pag->addCallSite(callBlockNode);
1209
1211 for (u32_t i = 0; i < cs->arg_size(); i++)
1213 callBlockNode,
1214 SVFUtil::cast<ValVar>(pag->getGNode(getValueNode(cs->getArgOperand(i)))));
1215
1216 if(!cs->getType()->isVoidTy())
1218
1219 if (callBlockNode->isVirtualCall())
1220 {
1221 const Value* value = cppUtil::getVCallVtblPtr(cs);
1222 callBlockNode->setVtablePtr(pag->getGNode(getValueNode(value)));
1223 }
1224 if (const Function *callee = LLVMUtil::getCallee(cs))
1225 {
1227 {
1228 handleExtCall(cs, callee);
1229 }
1230 else
1231 {
1233 }
1234 }
1235 else
1236 {
1237 //If the callee was not identified as a function (null F), this is indirect.
1238 handleIndCall(cs);
1239 }
1240}
bool isVirtualCall() const
Definition ICFGNode.h:521
void setVtablePtr(SVFVar *v)
Definition ICFGNode.h:526
RetICFGNode * getRetICFGNode(const Instruction *cs)
get a return node
void handleIndCall(CallBase *cs)
Handle indirect call.
void addCallSiteRets(RetICFGNode *retBlockNode, const SVFVar *arg)
Add callsite returns.
Definition SVFIR.h:543
void addCallSiteArgs(CallICFGNode *callBlockNode, const ValVar *arg)
Add callsite arguments.
Definition SVFIR.h:537
void addCallSite(const CallICFGNode *call)
Add callsites.
Definition SVFIR.h:792
bool isIntrinsicInst(const Instruction *inst)
Return true if it is an intrinsic instruction.
Definition LLVMUtil.cpp:202
const Function * getCallee(const CallBase *cs)
Definition LLVMUtil.h:97
const Value * getVCallVtblPtr(const CallBase *cs)
Definition CppUtil.cpp:537

◆ visitCastInst()

void SVFIRBuilder::visitCastInst ( CastInst I)

Definition at line 1105 of file SVFIRBuilder.cpp.

1106{
1107
1108 DBOUT(DPAGBuild, outs() << "process cast " << llvmModuleSet()->getSVFValue(&inst)->toString() << " \n");
1109 NodeID dst = getValueNode(&inst);
1110
1111 const Value* opnd = inst.getOperand(0);
1112 NodeID src = getValueNode(opnd);
1113 addCopyEdge(src, dst, getCopyKind(&inst));
1114}
CopyStmt::CopyKind getCopyKind(const Value *val)

◆ visitCmpInst()

void SVFIRBuilder::visitCmpInst ( CmpInst inst)

Visit compare instruction

Definition at line 1147 of file SVFIRBuilder.cpp.

1148{
1149 NodeID dst = getValueNode(&inst);
1150 assert(inst.getNumOperands() == 2 && "not two operands for compare instruction?");
1151 Value* op1 = inst.getOperand(0);
1153 Value* op2 = inst.getOperand(1);
1155 u32_t predicate = inst.getPredicate();
1156 addCmpEdge(op1Node, op2Node, dst, predicate);
1157}
void addCmpEdge(NodeID op1, NodeID op2, NodeID dst, u32_t predict)
Add Copy edge.

◆ visitExtractElementInst()

void SVFIRBuilder::visitExtractElementInst ( ExtractElementInst inst)

The �extractelement� instruction extracts a single scalar element from a vector at a specified index. TODO: for now we just assume the pointer after extraction points to blackhole The first operand of an �extractelement� instruction is a value of vector type. The second operand is an index indicating the position from which to extract the element.

<result> = extractelement <4 x i32> vec, i32 0 ; yields i32

Definition at line 1288 of file SVFIRBuilder.cpp.

1289{
1290 NodeID dst = getValueNode(&inst);
1292}

◆ visitExtractValueInst()

void SVFIRBuilder::visitExtractValueInst ( ExtractValueInst inst)

visit extract value instructions for structures in registers TODO: for now we just assume the pointer after extraction points to blackhole for example %24 = extractvalue { i32, struct.s_hash* } call34, 0 %24 is a pointer points to first field of a register value call34 however we can not create call34 as an memory object, as it is register value. Is that necessary treat extract value as getelementptr instruction later to get more precise results?

Definition at line 1274 of file SVFIRBuilder.cpp.

1275{
1276 NodeID dst = getValueNode(&inst);
1278}

◆ visitFenceInst()

void SVF::SVFIRBuilder::visitFenceInst ( FenceInst I)
inline

Definition at line 190 of file SVFIRBuilder.h.

191 {
193 }

◆ visitFreezeInst()

void SVFIRBuilder::visitFreezeInst ( FreezeInst inst)

<result> = freeze ty <val> If <val> is undef or poison, ‘freeze’ returns an arbitrary, but fixed value of type ty Otherwise, this instruction is a no-op and returns the input <val>

<result> = freeze ty <val> If <val> is undef or poison, ‘freeze’ returns an arbitrary, but fixed value of type ty Otherwise, this instruction is a no-op and returns the input <val> For now, we assume <val> is never a poison or undef.

Definition at line 1428 of file SVFIRBuilder.cpp.

1429{
1430 NodeID dst = getValueNode(&inst);
1431 for (u32_t i = 0; i < inst.getNumOperands(); i++)
1432 {
1433 Value* opnd = inst.getOperand(i);
1434 NodeID src = getValueNode(opnd);
1435 addCopyEdge(src, dst, CopyStmt::COPYVAL);
1436 }
1437}

◆ visitGetElementPtrInst()

void SVFIRBuilder::visitGetElementPtrInst ( GetElementPtrInst inst)

Visit getelementptr instructions

Definition at line 1079 of file SVFIRBuilder.cpp.

1080{
1081
1082 NodeID dst = getValueNode(&inst);
1083 // GetElementPtrInst should always be a pointer or a vector contains pointers
1084 // for now we don't handle vector type here
1085 if(SVFUtil::isa<VectorType>(inst.getType()))
1086 {
1088 return;
1089 }
1090
1091 assert(SVFUtil::isa<PointerType>(inst.getType()));
1092
1093 DBOUT(DPAGBuild, outs() << "process gep " << llvmModuleSet()->getSVFValue(&inst)->toString() << " \n");
1094
1095 NodeID src = getValueNode(inst.getPointerOperand());
1096
1097 AccessPath ap(0, llvmModuleSet()->getSVFType(inst.getSourceElementType()));
1098 bool constGep = computeGepOffset(&inst, ap);
1099 addGepEdge(src, dst, ap, constGep);
1100}

◆ visitGlobal()

void SVFIRBuilder::visitGlobal ( )
protected

Handle globals including (global variable and functions)

Visit global variables for building SVFIR

initialize global variable

initialize global functions

Definition at line 951 of file SVFIRBuilder.cpp.

952{
953
955 for (Module &M : llvmModuleSet()->getLLVMModules())
956 {
957 for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I)
958 {
959 GlobalVariable *gvar = &*I;
962
965
966 if (gvar->hasInitializer())
967 {
968 Constant *C = gvar->getInitializer();
969 DBOUT(DPAGBuild, outs() << "add global var node " << llvmModuleSet()->getSVFValue(gvar)->toString() << "\n");
970 InitialGlobal(gvar, C, 0);
971 }
972 }
973
974
976 for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I)
977 {
978 const Function* fun = &*I;
979 NodeID idx = getValueNode(fun);
980 NodeID obj = getObjectNode(fun);
981
982 DBOUT(DPAGBuild, outs() << "add global function node " << fun->getName().str() << "\n");
983 setCurrentLocation(fun, (SVFBasicBlock*) nullptr);
985 }
986
987 // Handle global aliases (due to linkage of multiple bc files), e.g., @x = internal alias @y. We need to add a copy from y to x.
988 for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); I != E; I++)
989 {
990 const GlobalAlias* alias = &*I;
991 NodeID dst = llvmModuleSet()->getValueNode(alias);
992 NodeID src = llvmModuleSet()->getValueNode(alias->getAliasee());
993 processCE(alias->getAliasee());
994 setCurrentLocation(alias, (SVFBasicBlock*) nullptr);
996 }
997 }
998}
llvm::GlobalVariable GlobalVariable
Definition BasicTypes.h:130
llvm::GlobalAlias GlobalAlias
Definition BasicTypes.h:128

◆ visitInsertElementInst()

void SVF::SVFIRBuilder::visitInsertElementInst ( InsertElementInst I)
inline

Definition at line 170 of file SVFIRBuilder.h.

171 {
173 }

◆ visitInsertValueInst()

void SVF::SVFIRBuilder::visitInsertValueInst ( InsertValueInst I)
inline

Definition at line 144 of file SVFIRBuilder.h.

145 {
147 }

◆ visitInstruction()

void SVF::SVFIRBuilder::visitInstruction ( Instruction )
inline

Provide base case for our instruction visit.

Definition at line 204 of file SVFIRBuilder.h.

205 {
206 // If a new instruction is added to LLVM that we don't handle.
207 // TODO: ignore here:
208 }

◆ visitInvokeInst()

void SVFIRBuilder::visitInvokeInst ( InvokeInst II)

Definition at line 1181 of file SVFIRBuilder.cpp.

1182{
1183 visitCallSite(&i);
1184}

◆ visitLandingPadInst()

void SVF::SVFIRBuilder::visitLandingPadInst ( LandingPadInst I)
inline

Definition at line 178 of file SVFIRBuilder.h.

179 {
181 }

◆ visitLoadInst()

void SVFIRBuilder::visitLoadInst ( LoadInst I)

Definition at line 1047 of file SVFIRBuilder.cpp.

1048{
1049 DBOUT(DPAGBuild, outs() << "process load " << llvmModuleSet()->getSVFValue(&inst)->toString() << " \n");
1050
1051 NodeID dst = getValueNode(&inst);
1052
1053 NodeID src = getValueNode(inst.getPointerOperand());
1054
1055 addLoadEdge(src, dst);
1056}

◆ visitPHINode()

void SVFIRBuilder::visitPHINode ( PHINode inst)

Visit phi instructions

Definition at line 1022 of file SVFIRBuilder.cpp.

1023{
1024
1025 DBOUT(DPAGBuild, outs() << "process phi " << llvmModuleSet()->getSVFValue(&inst)->toString() << " \n");
1026
1027 NodeID dst = getValueNode(&inst);
1028
1029 for (u32_t i = 0; i < inst.getNumIncomingValues(); ++i)
1030 {
1031 const Value* val = inst.getIncomingValue(i);
1032 const Instruction* incomingInst = SVFUtil::dyn_cast<Instruction>(val);
1033 bool matched = (incomingInst == nullptr ||
1034 incomingInst->getFunction() == inst.getFunction());
1035 (void) matched; // Suppress warning of unused variable under release build
1036 assert(matched && "incomingInst's Function incorrect");
1037 const Instruction* predInst = &inst.getIncomingBlock(i)->back();
1038 const ICFGNode* icfgNode = llvmModuleSet()->getICFGNode(predInst);
1039 NodeID src = getValueNode(val);
1040 addPhiStmt(dst,src,icfgNode);
1041 }
1042}
void addPhiStmt(NodeID res, NodeID opnd, const ICFGNode *pred)
Add Copy edge.

◆ visitResumeInst()

void SVF::SVFIRBuilder::visitResumeInst ( ResumeInst )
inline

Instruction not that often.

Definition at line 184 of file SVFIRBuilder.h.

185 {
186 }

◆ visitReturnInst()

void SVFIRBuilder::visitReturnInst ( ReturnInst inst)

Visit return instructions of a function

Definition at line 1245 of file SVFIRBuilder.cpp.

1246{
1247
1248 // ReturnInst itself should always not be a pointer type
1249 assert(!SVFUtil::isa<PointerType>(inst.getType()));
1250
1251 DBOUT(DPAGBuild, outs() << "process return " << llvmModuleSet()->getSVFValue(&inst)->toString() << " \n");
1252
1253 if(Value* src = inst.getReturnValue())
1254 {
1255 const FunObjVar *F = llvmModuleSet()->getFunObjVar(inst.getParent()->getParent());
1256
1258 NodeID vnS = getValueNode(src);
1259 const ICFGNode* icfgNode = llvmModuleSet()->getICFGNode(&inst);
1260 //vnS may be null if src is a null ptr
1261 addPhiStmt(rnF,vnS,icfgNode);
1262 }
1263}

◆ visitSelectInst()

void SVFIRBuilder::visitSelectInst ( SelectInst inst)

Visit select instructions

Two operands have same incoming basic block, both are the current BB

Definition at line 1163 of file SVFIRBuilder.cpp.

1164{
1165
1166 DBOUT(DPAGBuild, outs() << "process select " << llvmModuleSet()->getSVFValue(&inst)->toString() << " \n");
1167
1168 NodeID dst = getValueNode(&inst);
1169 NodeID src1 = getValueNode(inst.getTrueValue());
1170 NodeID src2 = getValueNode(inst.getFalseValue());
1171 NodeID cond = getValueNode(inst.getCondition());
1173 addSelectStmt(dst,src1,src2, cond);
1174}

◆ visitShuffleVectorInst()

void SVF::SVFIRBuilder::visitShuffleVectorInst ( ShuffleVectorInst I)
inline

Definition at line 174 of file SVFIRBuilder.h.

175 {
177 }

◆ visitStoreInst()

void SVFIRBuilder::visitStoreInst ( StoreInst inst)

Visit store instructions

Definition at line 1061 of file SVFIRBuilder.cpp.

1062{
1063 // StoreInst itself should always not be a pointer type
1064 assert(!SVFUtil::isa<PointerType>(inst.getType()));
1065
1066 DBOUT(DPAGBuild, outs() << "process store " << llvmModuleSet()->getSVFValue(&inst)->toString() << " \n");
1067
1068 NodeID dst = getValueNode(inst.getPointerOperand());
1069
1070 NodeID src = getValueNode(inst.getValueOperand());
1071
1072 addStoreEdge(src, dst);
1073
1074}

◆ visitSwitchInst()

void SVFIRBuilder::visitSwitchInst ( SwitchInst inst)

The following implementation follows ICFGBuilder::processFunBody.

See more: https://github.com/SVF-tools/SVF/pull/1191

Given the code:

switch (a) { case 0: printf("0\n"); break; case 1: case 2: case 3: printf("a >=1 && a <= 3\n"); break; case 4: case 6: case 7: printf("a >= 4 && a <=7\n"); break; default: printf("a < 0 || a > 7"); break; }

Generate the IR:

switch i32 %0, label sw.default [ i32 0, label sw.bb i32 1, label sw.bb1 i32 2, label sw.bb1 i32 3, label sw.bb1 i32 4, label sw.bb3 i32 6, label sw.bb3 i32 7, label sw.bb3 ]

We can get every case basic block and related case value: [ {sw.default, -1}, {sw.bb, 0}, {sw.bb1, 1}, {sw.bb1, 2}, {sw.bb1, 3}, {sw.bb3, 4}, {sw.bb3, 6}, {sw.bb3, 7}, ] Note: default case value is nullptr For larger number, we preserve case value just -1 now see more: https://github.com/SVF-tools/SVF/pull/992

branch condition value

default case is set to -1;

set conditional svf var

Definition at line 1380 of file SVFIRBuilder.cpp.

1381{
1382 NodeID brinst = getValueNode(&inst);
1383 NodeID cond = getValueNode(inst.getCondition());
1384
1386 std::vector<const Instruction*> nextInsts;
1388 for (const Instruction* succInst : nextInsts)
1389 {
1391 const ConstantInt* condVal = inst.findCaseDest(const_cast<BasicBlock*>(succInst->getParent()));
1393 s64_t val = -1;
1394 if (condVal && condVal->getBitWidth() <= 64)
1396 const ICFGNode* icfgNode = llvmModuleSet()->getICFGNode(succInst);
1397 successors.push_back(std::make_pair(icfgNode, val));
1398 }
1399 addBranchStmt(brinst, cond, successors);
1401 for (auto& edge : llvmModuleSet()->getICFGNode(&inst)->getOutEdges())
1402 {
1403 if (IntraCFGEdge* intraEdge = SVFUtil::dyn_cast<IntraCFGEdge>(edge))
1404 {
1405 intraEdge->setConditionVar(pag->getGNode(cond));
1406 }
1407 }
1408}
signed long long s64_t
Definition GeneralType.h:50

◆ visitUnaryOperator()

void SVFIRBuilder::visitUnaryOperator ( UnaryOperator inst)

Visit Unary Operator

Definition at line 1134 of file SVFIRBuilder.cpp.

1135{
1136 NodeID dst = getValueNode(&inst);
1137 assert(inst.getNumOperands() == 1 && "not one operand for Unary instruction?");
1138 Value* opnd = inst.getOperand(0);
1139 NodeID src = getValueNode(opnd);
1140 u32_t opcode = inst.getOpcode();
1141 addUnaryOPEdge(src, dst, opcode);
1142}
void addUnaryOPEdge(NodeID src, NodeID dst, u32_t opcode)
Add Unary edge.

◆ visitUnreachableInst()

void SVF::SVFIRBuilder::visitUnreachableInst ( UnreachableInst )
inline

Definition at line 187 of file SVFIRBuilder.h.

188 {
189 }

◆ visitVAArgInst()

void SVFIRBuilder::visitVAArgInst ( VAArgInst inst)

TODO: var arguments need to be handled. https://llvm.org/docs/LangRef.html#id1911

ap = alloca struct.va_list ap2 = bitcast struct.va_list* ap to i8* ; Read a single integer argument from ap2 tmp = va_arg i8* ap2, i32 (VAArgInst) TODO: for now, create a copy edge from ap2 to tmp, we assume here tmp should point to the n-th argument of the var_args

Definition at line 1416 of file SVFIRBuilder.cpp.

1417{
1418 NodeID dst = getValueNode(&inst);
1419 Value* opnd = inst.getPointerOperand();
1420 NodeID src = getValueNode(opnd);
1421 addCopyEdge(src, dst, CopyStmt::COPYVAL);
1422}

◆ visitVACopyInst()

void SVF::SVFIRBuilder::visitVACopyInst ( VACopyInst )
inline

Definition at line 159 of file SVFIRBuilder.h.

159{}

◆ visitVAEndInst()

void SVF::SVFIRBuilder::visitVAEndInst ( VAEndInst )
inline

Definition at line 160 of file SVFIRBuilder.h.

160{}

◆ visitVAStartInst()

void SVF::SVFIRBuilder::visitVAStartInst ( VAStartInst )
inline

Definition at line 161 of file SVFIRBuilder.h.

161{}

Member Data Documentation

◆ curBB

const SVFBasicBlock* SVF::SVFIRBuilder::curBB
private

Current basic block during SVFIR construction when visiting the module.

Definition at line 52 of file SVFIRBuilder.h.

◆ curVal

const Value* SVF::SVFIRBuilder::curVal
private

Current Value during SVFIR construction when visiting the module.

Definition at line 53 of file SVFIRBuilder.h.

◆ pag

SVFIR* SVF::SVFIRBuilder::pag
private

Definition at line 51 of file SVFIRBuilder.h.


The documentation for this class was generated from the following files: