Static Value-Flow Analysis
Loading...
Searching...
No Matches
Public Member Functions | Protected Member Functions | Private Types | Private Member Functions | Static Private Member Functions | Private Attributes | Friends | 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 SVFIR * build ()
 Start building SVFIR here.
 
SVFIR * getPAG () 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)
 Preserve LLVM switch destinations and case values in BranchStmt.
 
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 Value * getBaseValueForExtArg (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 Type * getBaseTypeAndFlattenedFields (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 handleNondetArgStoreAtExtCall (const CallBase *cs, const CallICFGNode *callICFGNode)
 
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 Value * getCurrentValue () const
 
const SVFBasicBlock * getCurrentBB () 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)
 
NodeID getDirectAccessFieldZeroValVar (const Value *ptr, const Type *accessTy)
 
void setCurrentBBAndValueForPAGEdge (PAGEdge *edge)
 
void addBlackHoleAddrEdge (NodeID node)
 
AddrStmt * addAddrEdge (NodeID src, NodeID dst)
 Add Address edge.
 
AddrStmt * addAddrWithStackArraySz (NodeID src, NodeID dst, llvm::AllocaInst &inst)
 Add Address edge from allocinst with arraysize like "%4 = alloca i8, i64 3".
 
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)".
 
CopyStmt * addCopyEdge (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 Types

using AggregateField = std::vector< unsigned >
 
using AggregateFieldKey = std::pair< const Value *, AggregateField >
 Identify a field by its LLVM value and path, rather than by its type alone.
 
using AggregateReturnFields = Map< const Function *, std::set< AggregateField > >
 Field paths extracted from each callee's returned aggregate.
 

Private Member Functions

bool getAggregateFieldOperands (const AggregateFieldKey &field, std::vector< AggregateFieldKey > &operands)
 Describe one field definition without emitting any SVFIR statements.
 
bool getAggregateFieldNode (const Value *aggregate, const AggregateField &indices, NodeID &node)
 
void addExtractedFieldCopy (Instruction &inst)
 
void initialiseAggregateReturns ()
 
AggregateReturnFields discoverAggregateReturnFields ()
 
void createAggregateReturnParams (const Function *fun, const std::set< AggregateField > &fields, const SVFType *pointerType)
 
void createAggregateCallSlots (const Function *fun, const SVFType *pointerType)
 
void addAggregateCallFields (const CallInst *call)
 
void addAggregateReturnStores (ReturnInst &inst)
 
LLVMModuleSet * llvmModuleSet ()
 

Static Private Member Functions

static std::optional< AggregateFieldKey > getExtractedField (const Instruction &inst)
 Decode a pointer extraction; unsupported instructions have no field.
 

Private Attributes

SVFIR * pag
 
const SVFBasicBlock * curBB
 Current basic block during SVFIR construction when visiting the module.
 
const Value * curVal
 Current Value during SVFIR construction when visiting the module.
 
Map< AggregateFieldKey, NodeID > aggregateFieldNodes
 Reuse the same scalar SVFIR node for repeated requests for a field.
 
Map< const Function *, std::map< AggregateField, NodeID > > aggregateReturnParams
 Output parameters of each modeled callee, in field-path order.
 
Map< const CallInst *, std::map< AggregateField, NodeID > > aggregateCallArgs
 

Friends

class GraphDBSVFIRBuilder
 

Detailed Description

SVFIR Builder to create SVF variables and statements and PAG

Definition at line 49 of file SVFIRBuilder.h.

Member Typedef Documentation

◆ AggregateField

Zero-based indices through nested structs, arrays or fixed vector lanes. For {i32, {ptr, ptr}}, {1, 0} selects the first pointer in the inner struct. An empty path denotes a scalar pointer leaf during dependency traversal.

Definition at line 62 of file SVFIRBuilder.h.

◆ AggregateFieldKey

Identify a field by its LLVM value and path, rather than by its type alone.

Definition at line 64 of file SVFIRBuilder.h.

◆ AggregateReturnFields

Field paths extracted from each callee's returned aggregate.

Definition at line 138 of file SVFIRBuilder.h.

Constructor & Destructor Documentation

◆ SVFIRBuilder()

SVF::SVFIRBuilder::SVFIRBuilder ( )
inline

Constructor.

Definition at line 153 of file SVFIRBuilder.h.

153 : pag(SVFIR::getPAG()), curBB(nullptr),curVal(nullptr)
154 {
155 }
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:121

◆ ~SVFIRBuilder()

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

Destructor.

Definition at line 157 of file SVFIRBuilder.h.

158 {
159 }

Member Function Documentation

◆ addAddrEdge()

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

Add Address edge.

Definition at line 406 of file SVFIRBuilder.h.

407 {
408 if(AddrStmt *edge = pag->addAddrStmt(src, dst))
409 {
411 return edge;
412 }
413 return nullptr;
414 }
void setCurrentBBAndValueForPAGEdge(PAGEdge *edge)
AddrStmt * addAddrStmt(NodeID src, NodeID dst)
Add an edge into SVFIR.
Definition SVFIR.cpp:64
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:76

◆ 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 428 of file SVFIRBuilder.h.

429 {
430 // get name of called function
431 AddrStmt* edge = addAddrEdge(src, dst);
432
433 llvm::Function* calledFunc = cs->getCalledFunction();
434 std::string functionName;
435 if (calledFunc)
436 {
437 functionName = calledFunc->getName().str();
438 }
439 else
440 {
441 SVFUtil::writeWrnMsg("not support indirect call to add AddrStmt.\n");
442 }
443 if (functionName == "malloc")
444 {
445 if (cs->arg_size() > 0)
446 {
447 const llvm::Value* val = cs->getArgOperand(0);
448 edge->addArrSize(pag->getGNode(getValueNode(val)));
449 }
450 }
451 // Check if the function called is 'calloc' and process its arguments.
452 // e.g. "%5 = call i8* @calloc(1, 8)", edge should add two SVFValue (1 and 8)
453 else if (functionName == "calloc")
454 {
455 if (cs->arg_size() > 1)
456 {
457 edge->addArrSize(
458 pag->getGNode(getValueNode(cs->getArgOperand(0))));
459 edge->addArrSize(
460 pag->getGNode(getValueNode(cs->getArgOperand(1))));
461 }
462 }
463 else
464 {
465 if (cs->arg_size() > 0)
466 {
467 const llvm::Value* val = cs->getArgOperand(0);
468 edge->addArrSize(pag->getGNode(getValueNode(val)));
469 }
470 }
471 return edge;
472 }
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.
void writeWrnMsg(const std::string &msg)
Writes a message run through wrnMsg.
Definition SVFUtil.cpp:88

◆ 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 417 of file SVFIRBuilder.h.

418 {
419 AddrStmt* edge = addAddrEdge(src, dst);
420 if (inst.getArraySize())
421 {
422 edge->addArrSize(pag->getGNode(getValueNode(inst.getArraySize())));
423 }
424 return edge;
425 }

◆ addAggregateCallFields()

void SVFIRBuilder::addAggregateCallFields ( const CallInst *  call)
private

Append the slot addresses of call as actual output arguments and pass each to the callee's output parameter. createAggregateCallSlots has already created the slots, their addresses and the snapshot loads.

Definition at line 1731 of file SVFIRBuilder.cpp.

1732{
1733 auto found = aggregateCallArgs.find(call);
1734 if (found == aggregateCallArgs.end())
1735 return;
1737 const FunObjVar* callee = llvmModuleSet()->getFunObjVar(call->getCalledFunction());
1739 const auto& params = aggregateReturnParams.at(call->getCalledFunction());
1740 for (const auto& arg : found->second)
1741 {
1743 addCallEdge(arg.second, params.at(arg.first), callNode, entry);
1744 }
1745}
FunEntryICFGNode * getFunEntryICFGNode(const FunObjVar *fun)
Add a function entry node.
Definition ICFG.cpp:243
const FunObjVar * getFunObjVar(const Function *fun) const
Definition LLVMModule.h:274
CallICFGNode * getCallICFGNode(const Instruction *cs)
get a call node
LLVMModuleSet * llvmModuleSet()
Map< const CallInst *, std::map< AggregateField, NodeID > > aggregateCallArgs
void addCallEdge(NodeID src, NodeID dst, const CallICFGNode *cs, const FunEntryICFGNode *entry)
Add Call edge.
Map< const Function *, std::map< AggregateField, NodeID > > aggregateReturnParams
Output parameters of each modeled callee, in field-path order.
void addCallSiteArgs(CallICFGNode *callBlockNode, const ValVar *arg)
Add callsite arguments.
Definition SVFIR.h:642
ICFG * getICFG() const
Definition SVFIR.h:232
const ValVar * getValVar(NodeID id) const
Definition SVFIR.h:140

◆ addAggregateReturnStores()

void SVFIRBuilder::addAggregateReturnStores ( ReturnInst &  inst)
private

Store shared field nodes into the callee's output parameters. An unsupported field gets its own fallback; supported siblings keep their shared definitions.

Definition at line 1749 of file SVFIRBuilder.cpp.

1750{
1751 auto found = aggregateReturnParams.find(inst.getFunction());
1752 if (found == aggregateReturnParams.end() || !inst.getReturnValue())
1753 return;
1754 // Keep each store on its own return path, before the shared function exit.
1756 for (const auto& field : found->second)
1757 {
1758 NodeID value;
1759 if (!getAggregateFieldNode(inst.getReturnValue(), field.first, value))
1760 {
1761 value = pag->addDummyValNode(NodeIDAllocator::get()->allocateValueId(), location);
1762 addBlackHoleAddrEdge(value);
1763 }
1764 addStoreEdge(value, field.second);
1765 }
1766}
ICFGNode * getICFGNode(const Instruction *inst)
Get a basic block ICFGNode.
static NodeIDAllocator * get(void)
Return (singleton) allocator.
void addStoreEdge(NodeID src, NodeID dst)
Add Store edge.
void addBlackHoleAddrEdge(NodeID node)
bool getAggregateFieldNode(const Value *aggregate, const AggregateField &indices, NodeID &node)
NodeID addDummyValNode()
Definition SVFIR.h:566
u32_t NodeID
Definition GeneralType.h:76

◆ addBinaryOPEdge()

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

Add Copy edge.

Definition at line 541 of file SVFIRBuilder.h.

542 {
543 if(BinaryOPStmt *edge = pag->addBinaryOPStmt(op1, op2, dst, opcode))
545 }
BinaryOPStmt * addBinaryOPStmt(NodeID op1, NodeID op2, NodeID dst, u32_t opcode)
Add Copy edge.
Definition SVFIR.cpp:194

◆ addBlackHoleAddrEdge()

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

Definition at line 399 of file SVFIRBuilder.h.

400 {
403 }
SVFStmt * addBlackHoleAddrStmt(NodeID node)
Set a pointer points-to black hole (e.g. int2ptr)
Definition SVFIR.cpp:364
SVFStmt PAGEdge
Definition IRGraph.h:41

◆ addBranchStmt()

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

Add Branch statement.

Definition at line 553 of file SVFIRBuilder.h.

554 {
555 if(BranchStmt *edge = pag->addBranchStmt(br, cond, succs))
557 }
BranchStmt * addBranchStmt(NodeID br, NodeID cond, const BranchStmt::SuccAndCondPairVec &succs)
Add BranchStmt.
Definition SVFIR.cpp:241

◆ addCallEdge()

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

Add Call edge.

Definition at line 577 of file SVFIRBuilder.h.

578 {
579 if (CallPE* edge = pag->addCallPE(src, dst, cs, entry))
581 }
CallPE * addCallPE(NodeID src, NodeID dst, const CallICFGNode *cs, const FunEntryICFGNode *entry)
Add Call edge (phi-like: merges actual params from all call sites into formal param)
Definition SVFIR.cpp:311

◆ addCmpEdge()

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

Add Copy edge.

Definition at line 535 of file SVFIRBuilder.h.

536 {
537 if(CmpStmt *edge = pag->addCmpStmt(op1, op2, dst, predict))
539 }
CmpStmt * addCmpStmt(NodeID op1, NodeID op2, NodeID dst, u32_t predict)
Add Copy edge.
Definition SVFIR.cpp:168

◆ 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 318 of file SVFIRExtAPI.cpp.

319{
320 assert(D && S);
322 if(!vnD || !vnS)
323 return;
324
325 std::vector<AccessPath> fields;
326
327 //Get the max possible size of the copy, unless it was provided.
328 std::vector<AccessPath> srcFields;
329 std::vector<AccessPath> dstFields;
332 if(srcFields.size() > dstFields.size())
333 fields = dstFields;
334 else
335 fields = srcFields;
336
338 u32_t sz = fields.size();
339
340 if (fields.size() == 1 && (LLVMUtil::isConstDataOrAggData(D) || LLVMUtil::isConstDataOrAggData(S)))
341 {
345 return;
346 }
347
354 const bool hasRemappedGlobalBase =
355 (dstFieldBase != D && SVFUtil::isa<GlobalVariable>(dstFieldBase)) ||
356 (srcFieldBase != S && SVFUtil::isa<GlobalVariable>(srcFieldBase));
357 const bool useByteLayoutMemcpy =
360 {
363 std::vector<MemcpyField> dstMemcpyFields = getMemcpyFields(D, dstLayoutType, dstSVFType);
364 std::vector<MemcpyField> srcMemcpyFields = getMemcpyFields(S, srcLayoutType, srcSVFType);
365 if (!dstMemcpyFields.empty() && !srcMemcpyFields.empty())
366 {
367 std::unordered_map<APOffset, MemcpyField> srcFieldsByByteOffset;
368 for (const auto& field : srcMemcpyFields)
370
371 const DataLayout& dl = llvmModuleSet()->getMainLLVMModule()->getDataLayout();
372 APOffset copyBytes = std::min<APOffset>(
373 static_cast<APOffset>(dl.getTypeAllocSize(const_cast<Type*>(dstLayoutType))),
374 static_cast<APOffset>(dl.getTypeAllocSize(const_cast<Type*>(srcLayoutType))));
375 if (szValue && SVFUtil::isa<ConstantInt>(szValue))
376 {
377 auto szIntVal = LLVMUtil::getIntegerValue(SVFUtil::cast<ConstantInt>(szValue));
378 copyBytes = std::min(copyBytes, static_cast<APOffset>(szIntVal.first));
379 }
380
381 for (const auto& dstField : dstMemcpyFields)
382 {
383 if (dstField.byteOffset >= copyBytes)
384 continue;
385 auto it = srcFieldsByByteOffset.find(dstField.byteOffset);
386 if (it == srcFieldsByByteOffset.end())
387 continue;
388
389 NodeID dField = getGepValVar(dstFieldBase, dstField.accessPath, dstField.elementType);
390 NodeID sField = getGepValVar(srcFieldBase, it->second.accessPath, it->second.elementType);
394 }
395 return;
396 }
397 }
398
399 //For each field (i), add (Ti = *S + i) and (*D + i = Ti).
400 for (u32_t index = 0; index < sz; index++)
401 {
404 fields[index].getConstantStructFldIdx());
406 fields[index].getConstantStructFldIdx());
412 }
413}
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:127
Module * getMainLLVMModule() const
Definition LLVMModule.h:373
static LLVMModuleSet * getLLVMModuleSet()
Definition LLVMModule.h:137
SVFType * getSVFType(const Type *T)
Get or create SVFType and typeinfo.
void addLoadEdge(NodeID src, NodeID dst)
Add Load edge.
const Value * getBaseValueForExtArg(const Value *V)
Get the base value of (i8* src and i8* dst) for external argument (e.g. memcpy(i8* dst,...
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)
std::pair< s64_t, u64_t > getIntegerValue(const ConstantInt *intValue)
Definition LLVMUtil.h:99
bool isConstDataOrAggData(const Value *val)
Return true if the value refers to constant data, e.g., i32 0.
Definition LLVMUtil.h:415
bool isObject(const Value *ref)
Return true if this value refers to a object.
Definition LLVMUtil.cpp:61
llvm::DataLayout DataLayout
Definition BasicTypes.h:112
llvm::Type Type
Definition BasicTypes.h:87
s64_t APOffset
Definition GeneralType.h:80
llvm::Value Value
LLVM Basic classes.
Definition BasicTypes.h:86

◆ addCopyEdge()

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

Definition at line 474 of file SVFIRBuilder.h.

475 {
476 if(CopyStmt *edge = pag->addCopyStmt(src, dst, kind))
477 {
479 return edge;
480 }
481 return nullptr;
482 }
CopyStmt * addCopyStmt(NodeID src, NodeID dst, CopyStmt::CopyKind type)
Add Copy edge.
Definition SVFIR.cpp:86

◆ addEdge()

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

◆ addExtractedFieldCopy()

void SVFIRBuilder::addExtractedFieldCopy ( Instruction &  inst)
private

Copy an extracted pointer from its shared field definition. Unsupported fields keep the existing black-hole fallback.

Definition at line 1797 of file SVFIRBuilder.cpp.

1798{
1799 NodeID dst = getValueNode(&inst);
1800 const auto field = getExtractedField(inst);
1801 NodeID src;
1802 if (field && getAggregateFieldNode(field->first, field->second, src))
1803 addCopyEdge(src, dst, CopyStmt::COPYVAL);
1804 else
1806}
static std::optional< AggregateFieldKey > getExtractedField(const Instruction &inst)
Decode a pointer extraction; unsupported instructions have no field.
CopyStmt * addCopyEdge(NodeID src, NodeID dst, CopyStmt::CopyKind kind)

◆ addGepEdge()

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

Add Gep edge.

Definition at line 589 of file SVFIRBuilder.h.

590 {
591 if (GepStmt* edge = pag->addGepStmt(src, dst, ap, constGep))
593 }
GepStmt * addGepStmt(NodeID src, NodeID dst, const AccessPath &ap, bool constGep)
Add Gep edge.
Definition SVFIR.cpp:419

◆ addGlobalBlackHoleAddrEdge()

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

Add global black hole Address edge.

Definition at line 372 of file SVFIRBuilder.h.

373 {
374 const Value* cval = getCurrentValue();
375 const SVFBasicBlock* cbb = getCurrentBB();
376 setCurrentLocation(int2Ptrce,(SVFBasicBlock*) nullptr);
379 }
void setCurrentLocation(const Value *val, const BasicBlock *bb)
Set current basic block in order to keep track of control flow information.
const SVFBasicBlock * getCurrentBB() const
const Value * getCurrentValue() const

◆ addLoadEdge()

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

Add Load edge.

Definition at line 559 of file SVFIRBuilder.h.

560 {
561 if(LoadStmt *edge = pag->addLoadStmt(src, dst))
563 }
LoadStmt * addLoadStmt(NodeID src, NodeID dst)
Add Load edge.
Definition SVFIR.cpp:264

◆ addNormalGepEdge()

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

Add Offset(Gep) edge.

Definition at line 595 of file SVFIRBuilder.h.

596 {
597 if (GepStmt* edge = pag->addNormalGepStmt(src, dst, ap))
599 }
GepStmt * addNormalGepStmt(NodeID src, NodeID dst, const AccessPath &ap)
Add Offset(Gep) edge.
Definition SVFIR.cpp:438

◆ addNullPtrNode()

NodeID SVF::SVFIRBuilder::addNullPtrNode ( )
inlineprotected

Add NullPtr PAGNode.

Definition at line 382 of file SVFIRBuilder.h.

383 {
385 ConstantPointerNull* constNull = ConstantPointerNull::get(PointerType::getUnqual(cxt));
386 NodeID nullPtr = pag->addConstantNullPtrValNode(pag->getNullPtr(), nullptr, llvmModuleSet()->getSVFType(constNull->getType()));
388 setCurrentLocation(constNull, (SVFBasicBlock*) nullptr);
390 return nullPtr;
391 }
NodeID getBlkPtr() const
Definition IRGraph.h:259
NodeID getNullPtr() const
Definition IRGraph.h:263
void addToSVFVar2LLVMValueMap(const Value *val, SVFValue *svfBaseNode)
LLVMContext & getContext() const
Definition LLVMModule.h:393
NodeID addConstantNullPtrValNode(const NodeID i, const ICFGNode *icfgNode, const SVFType *type)
Definition SVFIR.h:698
llvm::ConstantPointerNull ConstantPointerNull
Definition BasicTypes.h:131
llvm::LLVMContext LLVMContext
Definition BasicTypes.h:72

◆ 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 522 of file SVFIRBuilder.h.

523 {
525 if(PhiStmt *edge = pag->addPhiStmt(res,opnd,pred))
527 }
PhiStmt * addPhiStmt(NodeID res, NodeID opnd, const ICFGNode *pred)
Add phi node information.
Definition SVFIR.cpp:109

◆ addRetEdge()

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

Add Return edge.

Definition at line 583 of file SVFIRBuilder.h.

584 {
585 if (RetPE* edge = pag->addRetPE(src, dst, cs, exit))
587 }
RetPE * addRetPE(NodeID src, NodeID dst, const CallICFGNode *cs, const FunExitICFGNode *exit)
Add Return edge.
Definition SVFIR.cpp:341

◆ addSelectStmt()

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

Add SelectStmt.

Definition at line 529 of file SVFIRBuilder.h.

530 {
531 if(SelectStmt *edge = pag->addSelectStmt(res,op1,op2,cond))
533 }
SelectStmt * addSelectStmt(NodeID res, NodeID op1, NodeID op2, NodeID cond)
Add SelectStmt.
Definition SVFIR.cpp:142

◆ addStoreEdge()

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

Add Store edge.

Definition at line 565 of file SVFIRBuilder.h.

566 {
567 ICFGNode* node;
568 if (const Instruction* inst = SVFUtil::dyn_cast<Instruction>(curVal))
569 node = llvmModuleSet()->getICFGNode(
570 SVFUtil::cast<Instruction>(inst));
571 else
572 node = nullptr;
573 if (StoreStmt* edge = pag->addStoreStmt(src, dst, node))
575 }
StoreStmt * addStoreStmt(NodeID src, NodeID dst, const ICFGNode *val)
Add Store edge.
Definition SVFIR.cpp:288
llvm::Instruction Instruction
Definition BasicTypes.h:91

◆ 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 607 of file SVFIRBuilder.h.

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

◆ 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 613 of file SVFIRBuilder.h.

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

◆ addUnaryOPEdge()

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

Add Unary edge.

Definition at line 547 of file SVFIRBuilder.h.

548 {
549 if(UnaryOPStmt *edge = pag->addUnaryOPStmt(src, dst, opcode))
551 }
UnaryOPStmt * addUnaryOPStmt(NodeID src, NodeID dst, u32_t opcode)
Add Unary edge.
Definition SVFIR.cpp:218

◆ addVariantGepEdge()

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

Add Variant(Gep) edge.

Definition at line 601 of file SVFIRBuilder.h.

602 {
603 if (GepStmt* edge = pag->addVariantGepStmt(src, dst, ap))
605 }
GepStmt * addVariantGepStmt(NodeID src, NodeID dst, const AccessPath &ap)
Add Variant(Gep) edge.
Definition SVFIR.cpp:465

◆ 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 55 of file SVFIRBuilder.cpp.

56{
57 double startTime = SVFStat::getClk(true);
58
59 DBOUT(DGENERAL, outs() << pasMsg("\t Building SVFIR ...\n"));
60
61 // If the SVFIR has been built before, then we return the unique SVFIR of the program
63 return pag;
64
65
67
70 pag->icfg = icfgbuilder.build();
71
80
81
82
85 std::vector<const FunObjVar*> funset;
86 for (const auto& item: llvmModuleSet()->getFunctionSet())
87 {
89 }
90 pag->callGraph = callGraphBuilder.buildSVFIRCallGraph(funset);
91
92 CHGraph* chg = new CHGraph();
94 chgbuilder.buildCHG();
95 pag->setCHG(chg);
96
98 for (Module& M : llvmModuleSet()->getLLVMModules())
99 {
100 for (Module::const_iterator F = M.begin(), E = M.end(); F != E; ++F)
101 {
102 const Function& fun = *F;
103 const FunObjVar* svffun = llvmModuleSet()->getFunObjVar(&fun);
105 if(!fun.isDeclaration())
106 {
112 if (fun.doesNotReturn() == false &&
113 fun.getReturnType()->isVoidTy() == false)
114 {
117 }
118
121 for (Function::const_arg_iterator I = fun.arg_begin(), E = fun.arg_end();
122 I != E; ++I)
123 {
124 setCurrentLocation(&*I,&fun.getEntryBlock());
126 // if this is the function does not have caller (e.g. main)
127 // or a dead function, shall we create a black hole address edge for it?
128 // it is (1) too conservative, and (2) make FormalParmVFGNode defined at blackhole address PAGEdge.
129 // if(SVFUtil::ArgInNoCallerFunction(&*I)) {
130 // if(I->getType()->isPointerTy())
131 // addBlackHoleAddrEdge(argValNodeId);
132 //}
134 }
135 auto returns = aggregateReturnParams.find(&fun);
136 if (returns != aggregateReturnParams.end())
137 for (const auto& field : returns->second)
138 pag->addFunArgs(svffun, pag->getValVar(field.second));
139 }
140 for (Function::const_iterator bit = fun.begin(), ebit = fun.end();
141 bit != ebit; ++bit)
142 {
143 const BasicBlock& bb = *bit;
144 for (BasicBlock::const_iterator it = bb.begin(), eit = bb.end();
145 it != eit; ++it)
146 {
147 const Instruction& inst = *it;
148 setCurrentLocation(&inst,&bb);
149 visit(const_cast<Instruction&>(inst));
150 }
151 }
152 }
153 }
154
155 sanityCheck();
156
158
160
161 // dump SVFIR
163 pag->dump("svfir_initial");
164
165 // print to command line of the SVFIR graph
166 if (Options::PAGPrint())
167 pag->print();
168
169 // dump ICFG
170 if (Options::DumpICFG())
171 pag->getICFG()->dump("icfg_initial");
172
174 {
177 }
178
179 // dump SVFIR as JSON
180 if (!Options::DumpJson().empty())
181 {
182 assert(false && "please implement SVFIRWriter::writeJsonToPath");
183 }
184
185 double endTime = SVFStat::getClk(true);
186 SVFStat::timeOfBuildingSVFIR = (endTime - startTime) / TIMEINTERVAL;
187
188 return pag;
189}
#define DBOUT(TYPE, X)
LLVM debug macros, define type of your DBUG model of each pass.
Definition SVFType.h:576
#define TIMEINTERVAL
Definition SVFType.h:604
#define DGENERAL
Definition SVFType.h:582
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:412
u32_t getNodeNumAfterPAGBuild() const
Definition IRGraph.h:325
void dump(std::string name)
Dump SVFIR.
Definition IRGraph.cpp:333
NodeID getReturnNode(const FunObjVar *func) const
GetReturnNode - Return the unique node representing the return value of a function.
Definition IRGraph.cpp:64
void setNodeNumAfterPAGBuild(u32_t num)
Definition IRGraph.h:329
virtual void build(ICFG *icfg)
Start from here.
NodeID getValueNode(const Value *V)
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:233
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 initialiseAggregateReturns()
void initialiseNodes()
Initialize nodes and edges.
void addFunArgs(const FunObjVar *fun, const ValVar *arg)
Get/set method for function/callsite arguments and returns.
Definition SVFIR.h:618
void print()
Print SVFIR.
Definition SVFIR.cpp:649
void addFunRet(const FunObjVar *fun, const ValVar *ret)
Add function returns.
Definition SVFIR.h:630
CallGraph * callGraph
all the callsites of a program
Definition SVFIR.h:104
void setCHG(CommonCHGraph *c)
Set/Get CHG.
Definition SVFIR.h:238
ICFG * icfg
Definition SVFIR.h:101
void initialiseCandidatePointers()
Initialize candidate pointers.
Definition SVFIR.cpp:734
static double getClk(bool mark=false)
Definition SVFStat.cpp:52
static double timeOfBuildingSVFIR
Definition SVFStat.h:98
const FunObjVar * getFunObjVar(const std::string &name)
Definition LLVMUtil.cpp:437
std::string pasMsg(const std::string &msg)
Print each pass/phase message by converting a string into blue string output.
Definition SVFUtil.cpp:121
std::ostream & outs()
Overwrite llvm::outs()
Definition SVFUtil.h:58
llvm::BasicBlock BasicBlock
Definition BasicTypes.h:90
llvm::Function Function
Definition BasicTypes.h:89
llvm::Module Module
Definition BasicTypes.h:88

◆ 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 636 of file SVFIRBuilder.cpp.

637{
638 assert(V);
639
640 const llvm::GEPOperator *gepOp = SVFUtil::dyn_cast<const llvm::GEPOperator>(V);
641 DataLayout * dataLayout = getDataLayout(llvmModuleSet()->getMainLLVMModule());
642 llvm::APInt byteOffset(dataLayout->getIndexSizeInBits(gepOp->getPointerAddressSpace()),0,true);
643 if(gepOp && dataLayout && gepOp->accumulateConstantOffset(*dataLayout,byteOffset))
644 {
645 //s32_t bo = byteOffset.getSExtValue();
646 }
647
648 bool isConst = true;
649
650 bool prevPtrOperand = false;
652 gi != ge; ++gi)
653 {
654 const Type* gepTy = *gi;
656
657 assert((prevPtrOperand && svfGepTy->isPointerTy()) == false &&
658 "Expect no more than one gep operand to be of a pointer type");
659 if(!prevPtrOperand && svfGepTy->isPointerTy()) prevPtrOperand = true;
660 const Value* offsetVal = gi.getOperand();
661 assert(gepTy != offsetVal->getType() && "iteration and operand have the same type?");
662
663 const ArrayType* inferredPtrArrayTy = nullptr;
664 const SVFType* idxGepTy = svfGepTy;
665 if (svfGepTy->isPointerTy() && gepOp->getSourceElementType()->isSingleValueType())
666 {
667 const Type* baseObjType =
669 if (const auto* arrTy = SVFUtil::dyn_cast<ArrayType>(baseObjType))
670 {
671 if (arrTy->getElementType()->isPointerTy())
672 {
675 }
676 }
677 }
678
680
681 //The int value of the current index operand
682 const ConstantInt* op = SVFUtil::dyn_cast<ConstantInt>(offsetVal);
683
684 // if Options::ModelConsts() is disabled. We will treat whole array as one,
685 // but we can distinguish different field of an array of struct, e.g. s[1].f1 is different from s[0].f2
686 if(const ArrayType* arrTy = SVFUtil::dyn_cast<ArrayType>(gepTy))
687 {
688 if (!Options::ModelArrays() && arrTy->getElementType()->isPointerTy())
689 continue;
690 if(!op || (arrTy->getArrayNumElements() <= (u32_t)LLVMUtil::getIntegerValue(op).first))
691 continue;
695 }
696 else if (const StructType *ST = SVFUtil::dyn_cast<StructType>(gepTy))
697 {
698 assert(op && "non-const offset accessing a struct");
699 // guard against negative or out-of-bounds struct indices
700 // (e.g. rust hashbrown bucket back-offset: gep { ... }, ptr %p, i64 -1)
701 // a negative i64 wraps to a huge uint64_t that overflows u32_t,
702 // creating an invalid field index that severs points-to tracking
704 if (rawIdx >= ST->getNumElements())
705 {
706 isConst = false;
707 continue;
708 }
712 }
713 else if (gepTy->isSingleValueType())
714 {
716 {
717 if (!op || (inferredPtrArrayTy->getArrayNumElements() <= (u32_t)LLVMUtil::getIntegerValue(op).first))
718 continue;
722 continue;
723 }
724 // If it's a non-constant offset access
725 // If its point-to target is struct or array, it's likely an array accessing (%result = gep %struct.A* %a, i32 %non-const-index)
726 // If its point-to target is single value (pointer arithmetic), then it's a variant gep (%result = gep i8* %p, i32 %non-const-index)
727 if(!op && gepTy->isPointerTy() && gepOp->getSourceElementType()->isSingleValueType())
728 {
729 isConst = false;
730 }
731
732 // The actual index
733 //s32_t idx = op->getSExtValue();
734
735 // For pointer arithmetic we ignore the byte offset
736 // consider using inferFieldIdxFromByteOffset(geopOp,dataLayout,ap,idx)?
737 // ap.setFldIdx(ap.getConstantFieldIdx() + inferFieldIdxFromByteOffset(geopOp,idx));
738 }
739 }
740 return isConst;
741}
buffer offset
Definition cJSON.cpp:1113
APOffset getConstantStructFldIdx() const
Get methods.
Definition AccessPath.h:102
void setFldIdx(APOffset idx)
Definition AccessPath.h:106
bool addOffsetVarAndGepTypePair(const ValVar *var, const SVFType *gepIterType)
u32_t getFlattenedElemIdx(const SVFType *T, u32_t origId)
Flattened element idx of an array or struct by considering stride.
Definition IRGraph.cpp:148
ObjTypeInference * getTypeInference()
const Type * inferObjType(const Value *var)
get or infer the type of the object pointed by the value
static Option< bool > ModelArrays
Definition Options.h:179
SVFIR * getPAG() const
Return SVFIR.
static DataLayout * getDataLayout(Module *mod)
Definition LLVMUtil.h:333
llvm::ArrayType ArrayType
Definition BasicTypes.h:99
llvm::StructType StructType
LLVM types.
Definition BasicTypes.h:98
unsigned u32_t
Definition GeneralType.h:67
llvm::ConstantInt ConstantInt
Definition BasicTypes.h:129
bridge_gep_iterator bridge_gep_end(const User *GEP)
bridge_gep_iterator bridge_gep_begin(const User *GEP)

◆ createAggregateCallSlots()

void SVFIRBuilder::createAggregateCallSlots ( const Function *  fun,
const SVFType *  pointerType 
)
private

At every call to fun, create a slot, its address and its snapshot for each output parameter (obj, A and V in the aggregate return example). The address is defined at the call, and the snapshot is loaded at the instruction after the call.

Definition at line 1670 of file SVFIRBuilder.cpp.

1672{
1673 const auto& params = aggregateReturnParams.at(fun);
1674 // LLVM use-list order can change on bitcode reload. Order calls by
1675 // their ICFG IDs so each call receives the same slot IDs on readback.
1676 std::vector<const CallInst*> calls;
1677 for (const User* user : fun->users())
1678 calls.push_back(SVFUtil::cast<CallInst>(user));
1679 std::sort(calls.begin(), calls.end(), [this](const CallInst* lhs,
1680 const CallInst* rhs)
1681 {
1682 return llvmModuleSet()->getCallICFGNode(lhs)->getId() <
1683 llvmModuleSet()->getCallICFGNode(rhs)->getId();
1684 });
1685 const Value* savedValue = curVal;
1686 const SVFBasicBlock* savedBB = curBB;
1687 // Include calls with unused results to keep actual/formal lists aligned.
1688 for (const CallInst* call : calls)
1689 {
1690 std::vector<const Instruction*> next;
1692 assert(next.size() == 1 && "ordinary call must have one continuation");
1693 const Instruction* continuation = next.front();
1694 auto& args = aggregateCallArgs[call];
1697 for (const auto& param : params)
1698 {
1699 // DummyObjVar keeps the static slot nonlocal to the callee
1700 // in MemSSA. Later extracts read the SSA snapshot rather
1701 // than the reused slot contents.
1703 pag->getAllFieldsObjVars(object).set(object);
1704 pag->getObjTypeInfo(object)->setNumOfElements(1);
1706 pointerType->getByteSize());
1708 NodeIDAllocator::get()->allocateValueId(), callNode);
1709 NodeID value = pag->addDummyValNode(
1710 NodeIDAllocator::get()->allocateValueId(), resumeNode);
1711 args.emplace(param.first, address);
1712 // Call fields use the same identity as local aggregate fields.
1713 assert(!aggregateFieldNodes.count({call, param.first}) &&
1714 "call field registered twice");
1715 aggregateFieldNodes.emplace(
1716 AggregateFieldKey{call, param.first}, value);
1717 setCurrentLocation(call, call->getParent());
1718 addAddrEdge(object, address);
1719 // Snapshots must precede field statements at the continuation,
1720 // even when LLVM block order differs from dominance order.
1722 addLoadEdge(address, value);
1723 }
1724 }
1726}
item next
Definition cJSON.cpp:2224
ObjTypeInfo * getObjTypeInfo(NodeID id) const
Definition IRGraph.h:238
void setByteSizeOfObj(u32_t size)
Set the byte size of this object.
void setNumOfElements(u32_t num)
Set the number of elements of this object.
Map< AggregateFieldKey, NodeID > aggregateFieldNodes
Reuse the same scalar SVFIR node for repeated requests for a field.
std::pair< const Value *, AggregateField > AggregateFieldKey
Identify a field by its LLVM value and path, rather than by its type alone.
NodeBS & getAllFieldsObjVars(const BaseObjVar *obj)
Get all fields of an object.
Definition SVFIR.cpp:573
NodeID addDummyObjNode(const SVFType *type)
Definition SVFIR.h:570
void set(unsigned Idx)
void getNextInsts(const Instruction *curInst, std::vector< const Instruction * > &instList)
Get the next instructions following control flow.
Definition LLVMUtil.cpp:589
std::enable_if_t<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type > cast(const Y &Val)
Definition Casting.h:360
llvm::CallInst CallInst
Definition BasicTypes.h:154
llvm::User User
Definition BasicTypes.h:149

◆ createAggregateReturnParams()

void SVFIRBuilder::createAggregateReturnParams ( const Function *  fun,
const std::set< AggregateField > &  fields,
const SVFType *  pointerType 
)
private

Add one output parameter to fun for each demanded field, in field-path order (out_obj in the aggregate return example). The LLVM signature does not change.

Definition at line 1645 of file SVFIRBuilder.cpp.

1647{
1648 FunObjVar* svfFun =
1649 const_cast<FunObjVar*>(llvmModuleSet()->getFunObjVar(fun));
1651 auto& params = aggregateReturnParams[fun];
1652 for (const AggregateField& field : fields)
1653 {
1655 pag->addArgValNode(id, svfFun->arg_size(), entry, svfFun, pointerType);
1656 auto* arg = SVFUtil::cast<ArgValVar>(pag->getGNode(id));
1657 svfFun->addArgument(arg);
1658 // Like RetValPN, the synthetic parameter uses its function as a
1659 // diagnostic source; it does not add or replace an LLVM argument.
1661 arg->setName("aggregate_return_" + std::to_string(arg->getArgNo()));
1662 params.emplace(field, id);
1663 }
1664}
NodeID allocateValueId(void)
Allocate a value ID as determined by the strategy.
std::vector< unsigned > AggregateField
NodeID addArgValNode(NodeID i, u32_t argNo, const ICFGNode *icfgNode, const FunObjVar *callGraphNode, const SVFType *type)
Definition SVFIR.h:677

◆ createFunObjVars()

void SVFIRBuilder::createFunObjVars ( )

set fun in bb

Definition at line 334 of file SVFIRBuilder.cpp.

335{
336 std::vector<FunObjVar*> funset;
337 // Iterate over all object symbols in the symbol table
338 for (const auto* fun: llvmModuleSet()->getFunctionSet())
339 {
340 u32_t id = llvmModuleSet()->objSyms()[fun];
341 // Debug output for adding object node
342 DBOUT(DPAGBuild, outs() << "add obj node " << id << "\n");
343
344 // Check if the value is a function and add a function object node
345 pag->addFunObjNode(id, pag->getObjTypeInfo(id), nullptr);
347
348 FunObjVar *funObjVar = SVFUtil::cast<FunObjVar>(pag->getGNode(id));
349 funset.push_back(funObjVar);
350
351 funObjVar->initFunObjVar(fun->isDeclaration(), LLVMUtil::isIntrinsicFun(fun), fun->hasAddressTaken(),
353 SVFUtil::cast<SVFFunctionType>(llvmModuleSet()->getSVFType(fun->getFunctionType())),
354 new SVFLoopAndDomInfo, nullptr, nullptr,
355 {}, nullptr);
356 BasicBlockGraph* bbGraph = new BasicBlockGraph();
357 funObjVar->setBasicBlockGraph(bbGraph);
358
359
360 for (const BasicBlock& bb : *fun)
361 {
362 llvmModuleSet()->addBasicBlock(funObjVar, &bb);
363 }
364
366 for (auto& bb: *funObjVar->bbGraph)
367 {
368 bb.second->setFun(funObjVar);
369 }
371 }
372
374}
#define DPAGBuild
Definition SVFType.h:584
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)
LLVMFun2FunObjVarMap LLVMFun2FunObjVar
Map an LLVM Function to an SVF Funobjvar.
Definition LLVMModule.h:105
ValueToIDMapTy & objSyms()
Definition LLVMModule.h:219
void addBasicBlock(FunObjVar *fun, const BasicBlock *bb)
Definition LLVMModule.h:239
NodeID addFunObjNode(NodeID id, ObjTypeInfo *ti, const ICFGNode *node)
Definition SVFIR.h:741
bool isUncalledFunction(const Function *fun)
whether this is a function without any possible caller?
Definition LLVMUtil.cpp:159
bool isIntrinsicFun(const Function *func)
Definition LLVMUtil.cpp:191
bool functionDoesNotRet(const Function *fun)
Definition LLVMUtil.cpp:124

◆ discoverAggregateReturnFields()

SVFIRBuilder::AggregateReturnFields SVFIRBuilder::discoverAggregateReturnFields ( )
private

Find the fields of each callee's returned aggregate that callers extract, such as field {0} of make in the aggregate return example. Paths that getAggregateFieldOperands cannot follow are skipped; getAggregateFieldNode later decides which extracted fields are modeled.

Definition at line 1599 of file SVFIRBuilder.cpp.

1600{
1601 std::vector<AggregateFieldKey> worklist;
1602 for (Module& module : llvmModuleSet()->getLLVMModules())
1603 for (const Function& fun : module)
1604 for (const BasicBlock& bb : fun)
1605 for (const Instruction& inst : bb)
1606 {
1607 if (auto field = getExtractedField(inst))
1608 worklist.push_back(std::move(*field));
1609 }
1610
1611 // Discover callee demands without materializing local field definitions.
1612 // Calls cross into return operands; other producers use the shared grammar.
1614 Set<AggregateFieldKey> visited;
1615 while (!worklist.empty())
1616 {
1617 AggregateFieldKey field = std::move(worklist.back());
1618 worklist.pop_back();
1619 if (!visited.insert(field).second || field.second.empty())
1620 continue;
1621 if (const auto* call = SVFUtil::dyn_cast<CallInst>(field.first))
1622 {
1623 const Function* callee = call->getCalledFunction();
1625 !demands[callee].insert(field.second).second)
1626 continue;
1627 for (const BasicBlock& bb : *callee)
1628 if (const auto* ret = SVFUtil::dyn_cast<ReturnInst>(bb.getTerminator()))
1629 if (ret->getReturnValue())
1630 worklist.emplace_back(ret->getReturnValue(), field.second);
1631 }
1632 else
1633 {
1634 std::vector<AggregateFieldKey> operands;
1636 worklist.insert(worklist.end(), operands.begin(), operands.end());
1637 }
1638 }
1639 return demands;
1640}
static bool canModelAggregateReturn(const Function *fun)
if(prebuffer< 0)
Definition cJSON.cpp:1269
for(i=0;a &&(i<(size_t) count);i++)
Definition cJSON.cpp:2569
Map< const Function *, std::set< AggregateField > > AggregateReturnFields
Field paths extracted from each callee's returned aggregate.
bool getAggregateFieldOperands(const AggregateFieldKey &field, std::vector< AggregateFieldKey > &operands)
Describe one field definition without emitting any SVFIR statements.
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::ReturnInst ReturnInst
Definition BasicTypes.h:164

◆ 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 2471 of file SVFIRBuilder.cpp.

2472{
2473 SVFVar* node = pag->getGNode(nodeId);
2476 if(geps.empty())
2477 return AccessPath(0);
2478
2479 assert(geps.size()==1 && "one node can only be connected by at most one gep edge!");
2480 SVFVar::iterator it = geps.begin();
2481 const GepStmt* gepEdge = SVFUtil::cast<GepStmt>(*it);
2482 if(gepEdge->isVariantFieldGep())
2483 return AccessPath(0);
2484 else
2485 return gepEdge->getAccessPath();
2486}
GEdgeSetTy::iterator iterator
GenericNode< SVFVar, SVFStmt >::GEdgeSetTy SVFStmtSetTy
SVFStmt::SVFStmtSetTy & getIncomingEdges(SVFStmt::PEDGEK kind)
Edge accessors and checkers.

◆ getAggregateFieldNode()

bool SVFIRBuilder::getAggregateFieldNode ( const Value *  aggregate,
const AggregateField &  indices,
NodeID &  node 
)
private

Return the node for (aggregate, indices), reusing cached fields. Unsupported dependencies return false without changing SVFIR or node.

Here, the field node for (a, {0}) copies p; x copies that node: define ptr @field(ptr p) { a = insertvalue { ptr } poison, ptr p, 0 x = extractvalue { ptr } a, 0 ret ptr x }

Definition at line 1479 of file SVFIRBuilder.cpp.

1481{
1482 const AggregateFieldKey root{aggregate, indices};
1483 // Discovery order keeps field NodeIDs stable across -write-ander and
1484 // -read-ander runs; Value-pointer hash order can swap their points-to sets.
1485 std::vector<std::pair<AggregateFieldKey, std::vector<AggregateFieldKey>>>
1488 std::vector<AggregateFieldKey> worklist{root};
1489 while (!worklist.empty())
1490 {
1491 AggregateFieldKey field = std::move(worklist.back());
1492 worklist.pop_back();
1493 if (aggregateFieldNodes.count(field) ||
1494 !discovered.insert(field).second)
1495 continue;
1496 const Type* type = getAggregateFieldType(field.first->getType(), field.second);
1497 if (!type || !type->isPointerTy())
1498 return false;
1499 definitions.emplace_back(field, std::vector<AggregateFieldKey>());
1500 auto& operands = definitions.back().second;
1502 return false;
1503 worklist.insert(worklist.end(), operands.begin(), operands.end());
1504 }
1505
1506 // Validate the entire dependency graph before changing SVFIR. Allocate every
1507 // field before wiring definitions, including loop-carried Phi/Select cycles.
1508 for (const auto& definition : definitions)
1509 {
1510 const AggregateFieldKey& field = definition.first;
1511 NodeID id;
1512 if (field.second.empty())
1513 id = getValueNode(field.first);
1514 else if (SVFUtil::isa<Constant>(field.first))
1515 id = getValueNode(definition.second.front().first);
1516 else
1517 {
1518 const auto* producer = SVFUtil::cast<Instruction>(field.first);
1519 const Type* type = getAggregateFieldType(producer->getType(), field.second);
1521 pag->addValNode(id, llvmModuleSet()->getSVFType(type),
1522 llvmModuleSet()->getICFGNode(producer));
1524 }
1525 aggregateFieldNodes.emplace(field, id);
1526 }
1527
1528 const Value* savedValue = curVal;
1529 const SVFBasicBlock* savedBB = curBB;
1530 for (const auto& definition : definitions)
1531 {
1532 const AggregateFieldKey& field = definition.first;
1533 if (field.second.empty() || SVFUtil::isa<Constant>(field.first))
1534 continue;
1535 const auto* producer = SVFUtil::cast<Instruction>(field.first);
1536 const auto& operands = definition.second;
1538 setCurrentLocation(producer, producer->getParent());
1539 if (const auto* phi = SVFUtil::dyn_cast<PHINode>(producer))
1540 {
1541 for (unsigned i = 0; i < operands.size(); ++i)
1543 llvmModuleSet()->getICFGNode(phi->getIncomingBlock(i)->getTerminator()));
1544 }
1545 else if (const auto* select = SVFUtil::dyn_cast<SelectInst>(producer))
1547 aggregateFieldNodes.at(operands[1]), getValueNode(select->getCondition()));
1548 else
1550 }
1552 node = aggregateFieldNodes.at(root);
1553 return true;
1554}
static const Type * getAggregateFieldType(const Type *type, const std::vector< unsigned > &indices)
Return the type at a constant aggregate path, including fixed vector lanes.
newitem type
Definition cJSON.cpp:2739
void addPhiStmt(NodeID res, NodeID opnd, const ICFGNode *pred)
Add Copy edge.
void addSelectStmt(NodeID res, NodeID op1, NodeID op2, NodeID cond)
Add SelectStmt.
NodeID addValNode(NodeID i, const SVFType *type, const ICFGNode *icfgNode)
add node into SVFIR
Definition SVFIR.h:665

◆ getAggregateFieldOperands()

bool SVFIRBuilder::getAggregateFieldOperands ( const AggregateFieldKey &  field,
std::vector< AggregateFieldKey > &  operands 
)
private

Describe one field definition without emitting any SVFIR statements.

Definition at line 1378 of file SVFIRBuilder.cpp.

1380{
1381 const Value* value = field.first;
1382 const AggregateField& path = field.second;
1383 if (path.empty())
1384 return value->getType()->isPointerTy() && !SVFUtil::isa<ConstantExpr>(value) &&
1385 !SVFUtil::isa<UndefValue>(value) && llvmModuleSet()->hasValueNode(value);
1386 // insertvalue and insertelement replace one field. For example, in
1387 // %b = insertvalue {ptr, ptr} %a, ptr %q, 1
1388 // field {1} of %b is %q, and field {0} of %b is field {0} of %a.
1389 const Value* original = nullptr;
1390 const Value* inserted = nullptr;
1392 if (const auto* insert = SVFUtil::dyn_cast<InsertValueInst>(value))
1393 {
1394 original = insert->getAggregateOperand();
1395 inserted = insert->getInsertedValueOperand();
1396 insertedPath.assign(insert->idx_begin(), insert->idx_end());
1397 }
1398 else if (const auto* insert = SVFUtil::dyn_cast<InsertElementInst>(value))
1399 {
1400 const auto lane = getFixedVectorLane(insert->getType(),
1401 insert->getOperand(2));
1402 if (!lane)
1403 return false;
1404 original = insert->getOperand(0);
1405 inserted = insert->getOperand(1);
1406 insertedPath = {*lane};
1407 }
1408
1409 if (inserted)
1410 {
1411 const size_t commonLength = std::min(insertedPath.size(), path.size());
1412 if (!std::equal(insertedPath.begin(), insertedPath.begin() + commonLength, path.begin()))
1413 operands.emplace_back(original, path);
1414 else if (insertedPath.size() <= path.size())
1415 operands.emplace_back(inserted,
1416 AggregateField(path.begin() + insertedPath.size(), path.end()));
1417 else
1418 return false;
1419 }
1420 else if (const auto* extract = SVFUtil::dyn_cast<ExtractValueInst>(value))
1421 {
1422 AggregateField outer(extract->idx_begin(), extract->idx_end());
1423 outer.insert(outer.end(), path.begin(), path.end());
1424 operands.emplace_back(extract->getAggregateOperand(), std::move(outer));
1425 }
1426 else if (const auto* phi = SVFUtil::dyn_cast<PHINode>(value))
1427 {
1428 for (const Value* incoming : phi->incoming_values())
1430 }
1431 else if (const auto* select = SVFUtil::dyn_cast<SelectInst>(value))
1432 {
1433 if (!select->getCondition()->getType()->isIntegerTy(1))
1434 return false;
1435 operands.emplace_back(select->getTrueValue(), path);
1436 operands.emplace_back(select->getFalseValue(), path);
1437 }
1438 else if (const auto* freeze = SVFUtil::dyn_cast<FreezeInst>(value))
1439 operands.emplace_back(freeze->getOperand(0), path);
1440 else if (const auto* shuffle = SVFUtil::dyn_cast<ShuffleVectorInst>(value))
1441 {
1442 const auto* vector = SVFUtil::dyn_cast<llvm::FixedVectorType>(shuffle->getOperand(0)->getType());
1443 if (!vector || path.size() != 1)
1444 return false;
1445 int index = shuffle->getMaskValue(path.front());
1446 if (index < 0)
1447 return false;
1448 unsigned width = vector->getNumElements();
1449 operands.emplace_back(shuffle->getOperand(static_cast<unsigned>(index) / width),
1450 AggregateField{static_cast<unsigned>(index) % width});
1451 }
1452 else if (const auto* constant = SVFUtil::dyn_cast<Constant>(value))
1453 {
1454 for (unsigned index : path)
1455 {
1456 constant = constant->getAggregateElement(index);
1457 if (!constant)
1458 return false;
1459 }
1460 operands.emplace_back(constant, AggregateField{});
1461 }
1462 else
1463 // Aggregate arguments, calls and loads need their own field interfaces.
1464 return false;
1465 return !operands.empty();
1466}
static std::optional< unsigned > getFixedVectorLane(const Type *type, const Value *index)
bool hasValueNode(const Value *V)

◆ 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

MaxFieldLimit == 0 denotes field-insensitive analysis, not an empty memory model. The lower bound of one keeps a representative AccessPath; using zero would drop the memcpy/memset effect entirely.

Unsound scalability trade-off: AccessPaths beyond MaxFieldLimit are omitted, so their external-memory effects are not represented in the SVFIR.

Definition at line 273 of file SVFIRExtAPI.cpp.

274{
275 assert(V);
276 const Value* value = getBaseValueForExtArg(V);
280 if(szValue && SVFUtil::isa<ConstantInt>(szValue))
281 {
282 auto szIntVal = LLVMUtil::getIntegerValue(SVFUtil::cast<ConstantInt>(szValue));
283 numOfElems = (numOfElems > szIntVal.first) ? szIntVal.first : numOfElems;
284 }
291 numOfElems = std::min(numOfElems, std::max(Options::MaxFieldLimit(), u32_t{1}));
292
294 for(u32_t ei = 0; ei < numOfElems; ei++)
295 {
297 // make a ConstantInt and create char for the content type due to byte-wise copy
298 const ConstantInt* offset = ConstantInt::get(context, llvm::APInt(32, ei));
299 if (!llvmModuleSet()->hasValueNode(offset))
300 {
302 builder.collectSym(offset);
304 pag->addConstantIntValNode(id, LLVMUtil::getIntegerValue(offset), nullptr, llvmModuleSet()->getSVFType(offset->getType()));
306 pag->getGNode(id));
307 }
308 ls.addOffsetVarAndGepTypePair(getPAG()->getValVar(llvmModuleSet()->getValueNode(offset)), nullptr);
309 fields.push_back(ls);
310 }
311 return objType;
312}
u32_t getNumOfFlattenElements(const SVFType *T)
Definition IRGraph.cpp:186
static const Option< u32_t > MaxFieldLimit
Maximum number of field derivations for an object.
Definition Options.h:34
NodeID addConstantIntValNode(NodeID i, const std::pair< s64_t, u64_t > &intValue, const ICFGNode *icfgNode, const SVFType *type)
Definition SVFIR.h:691

◆ 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 2098 of file SVFIRBuilder.cpp.

2099{
2100 const Value* value = stripAllCasts(V);
2101 assert(value && "null ptr?");
2103 [this](const GlobalVariable* glob, int64_t byteOffset) -> const Value*
2104 {
2105 if (!glob || !glob->hasInitializer())
2106 return nullptr;
2107
2108 auto* initializer = SVFUtil::dyn_cast<ConstantStruct>(glob->getInitializer());
2109 auto* structType = SVFUtil::dyn_cast<StructType>(glob->getValueType());
2110 if (!initializer || !structType)
2111 return nullptr;
2112
2113 DataLayout* dataLayout = getDataLayout(llvmModuleSet()->getMainLLVMModule());
2114 const StructLayout* layout =
2115 dataLayout->getStructLayout(const_cast<StructType*>(structType));
2116 for (u32_t fieldIdx = 0; fieldIdx < initializer->getNumOperands(); ++fieldIdx)
2117 {
2118 if (layout->getElementOffset(fieldIdx) != static_cast<uint64_t>(byteOffset))
2119 continue;
2120 if (auto* ptrValue =
2121 SVFUtil::dyn_cast<llvm::GlobalVariable>(initializer->getOperand(fieldIdx)))
2122 return ptrValue;
2123 return nullptr;
2124 }
2125 return nullptr;
2126 };
2127
2128 if(const GetElementPtrInst* gep = SVFUtil::dyn_cast<GetElementPtrInst>(value))
2129 {
2130 APOffset totalidx = 0;
2132 {
2133 if(const ConstantInt* op = SVFUtil::dyn_cast<ConstantInt>(gi.getOperand()))
2135 }
2136 if(totalidx == 0 && !SVFUtil::isa<StructType>(value->getType()))
2137 value = gep->getPointerOperand();
2138 }
2139 else if (const LoadInst* load = SVFUtil::dyn_cast<LoadInst>(value))
2140 {
2141 const Value* loadP = load->getPointerOperand();
2142 if (const GetElementPtrInst* gep = SVFUtil::dyn_cast<GetElementPtrInst>(loadP))
2143 {
2144 DataLayout* dataLayout = getDataLayout(llvmModuleSet()->getMainLLVMModule());
2145 llvm::APInt byteOffset(dataLayout->getIndexSizeInBits(gep->getPointerAddressSpace()), 0, true);
2146 const bool hasByteOffset = dataLayout && gep->accumulateConstantOffset(*dataLayout, byteOffset);
2147
2148 const Value * pointer_operand = gep->getPointerOperand();
2149 if (auto *glob = SVFUtil::dyn_cast<GlobalVariable>(pointer_operand))
2150 {
2151 if (hasByteOffset)
2152 {
2153 if (const Value* ptrValue = getGlobalFieldFromByteOffset(glob, byteOffset.getSExtValue()))
2154 return ptrValue;
2155 }
2156 }
2157 else if (hasByteOffset && !byteOffset.isNegative() &&
2158 SVFUtil::isa<AllocaInst>(pointer_operand) && load->getType()->isPointerTy())
2159 {
2160 const u64_t offset = byteOffset.getZExtValue();
2161 const u64_t accessBytes = dataLayout->getPointerSize(gep->getPointerAddressSpace());
2162
2163 auto isCoveredByMemcpy = [offset, accessBytes](const CallBase* cs) -> bool
2164 {
2165 if (cs->arg_size() < 3)
2166 return false;
2167
2168 const auto* copySize = SVFUtil::dyn_cast<ConstantInt>(cs->getArgOperand(2));
2169 if (!copySize)
2170 {
2171 return false;
2172 }
2173
2174 const u64_t copyBytes = copySize->getZExtValue();
2176 };
2177
2178 auto hasInterveningWrite = [load](const Instruction* from) -> bool
2179 {
2180 if (from->getParent() != load->getParent() || !from->comesBefore(load))
2181 return true;
2182
2183 auto it = from->getIterator();
2184 const auto end = load->getIterator();
2185 while (++it != end)
2186 {
2187 if (it->mayWriteToMemory())
2188 return true;
2189 }
2190 return false;
2191 };
2192
2193 for (const auto& use : pointer_operand->users())
2194 {
2195 const auto* cs = SVFUtil::dyn_cast<CallBase>(use);
2196 if (!cs || cs->getParent() != load->getParent() ||
2197 cs->arg_size() < 1 ||
2198 stripAllCasts(cs->getArgOperand(0)) != pointer_operand)
2199 continue;
2200
2201 const Function* calledFun = cs->getCalledFunction();
2204 continue;
2205
2206 const Value* copiedFrom = getBaseValueForExtArg(cs->getArgOperand(1));
2207 if (const auto* copiedGlob = SVFUtil::dyn_cast<GlobalVariable>(copiedFrom))
2208 {
2209 if (const Value* ptrValue =
2210 getGlobalFieldFromByteOffset(copiedGlob, byteOffset.getSExtValue()))
2211 return ptrValue;
2212 }
2213 }
2214 }
2215 }
2216 }
2217
2218 return value;
2219}
const Value * stripAllCasts(const Value *val)
Strip off the all casts.
Definition LLVMUtil.cpp:251
bool isMemcpyExtFun(const Function *fun)
Definition LLVMUtil.cpp:390
llvm::GlobalVariable GlobalVariable
Definition BasicTypes.h:137
llvm::CallBase CallBase
Definition BasicTypes.h:153
unsigned long long u64_t
Definition GeneralType.h:69
llvm::StructLayout StructLayout
Definition BasicTypes.h:109
llvm::LoadInst LoadInst
Definition BasicTypes.h:156
llvm::GetElementPtrInst GetElementPtrInst
Definition BasicTypes.h:169

◆ getCopyKind()

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

Definition at line 484 of file SVFIRBuilder.h.

485 {
486 // COPYVAL, ZEXT, SEXT, BITCAST, FPTRUNC, FPTOUI, FPTOSI, UITOFP, SITOFP, INTTOPTR, PTRTOINT
487 if (const Instruction* inst = SVFUtil::dyn_cast<Instruction>(val))
488 {
489 switch (inst->getOpcode())
490 {
491 case Instruction::ZExt:
492 return CopyStmt::ZEXT;
493 case Instruction::SExt:
494 return CopyStmt::SEXT;
495 case Instruction::BitCast:
496 return CopyStmt::BITCAST;
497 case Instruction ::Trunc:
498 return CopyStmt::TRUNC;
499 case Instruction::FPTrunc:
500 return CopyStmt::FPTRUNC;
501 case Instruction::FPToUI:
502 return CopyStmt::FPTOUI;
503 case Instruction::FPToSI:
504 return CopyStmt::FPTOSI;
505 case Instruction::UIToFP:
506 return CopyStmt::UITOFP;
507 case Instruction::SIToFP:
508 return CopyStmt::SITOFP;
509 case Instruction::IntToPtr:
510 return CopyStmt::INTTOPTR;
511 case Instruction::PtrToInt:
512 return CopyStmt::PTRTOINT;
513 default:
514 return CopyStmt::COPYVAL;
515 }
516 }
517 assert (false && "Unknown cast inst!");
518 abort();
519 }

◆ getCurrentBB()

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

Definition at line 366 of file SVFIRBuilder.h.

367 {
368 return curBB;
369 }

◆ getCurrentValue()

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

Definition at line 362 of file SVFIRBuilder.h.

363 {
364 return curVal;
365 }

◆ getDirectAccessFieldZeroValVar()

NodeID SVFIRBuilder::getDirectAccessFieldZeroValVar ( const Value *  ptr,
const Type *  accessTy 
)
protected

Definition at line 2341 of file SVFIRBuilder.cpp.

2342{
2343 if (!Options::ModelArrays() || SVFUtil::isa<llvm::GEPOperator>(ptr))
2344 return 0;
2345
2346 const Type* objTy =
2348 const ArrayType* arrTy = SVFUtil::dyn_cast<ArrayType>(objTy);
2349 if (!arrTy || !arrTy->getElementType()->isPointerTy() ||
2350 arrTy->getElementType() != accessTy)
2351 return 0;
2352
2353 AccessPath ap(0, llvmModuleSet()->getSVFType(arrTy));
2354 return getGepValVar(ptr, ap, llvmModuleSet()->getSVFType(accessTy));
2355}

◆ getExtractedField()

std::optional< SVFIRBuilder::AggregateFieldKey > SVFIRBuilder::getExtractedField ( const Instruction &  inst)
staticprivate

Decode a pointer extraction; unsupported instructions have no field.

Get the aggregate and field path that a pointer extractvalue, or a pointer extractelement with a constant index, reads. For example, x = extractvalue {ptr, ptr} a, 0 reads field {0} of a.

Definition at line 1773 of file SVFIRBuilder.cpp.

1774{
1775 if (!inst.getType()->isPointerTy())
1776 return std::nullopt;
1777 if (const auto* extract = SVFUtil::dyn_cast<ExtractValueInst>(&inst))
1778 {
1779 return AggregateFieldKey
1780 {
1781 extract->getAggregateOperand(),
1782 AggregateField(extract->idx_begin(), extract->idx_end())};
1783 }
1784 const auto* extract = SVFUtil::dyn_cast<ExtractElementInst>(&inst);
1785 if (!extract)
1786 return std::nullopt;
1787 const auto lane = getFixedVectorLane(extract->getVectorOperandType(),
1788 extract->getIndexOperand());
1789 if (!lane)
1790 return std::nullopt;
1791 return AggregateFieldKey{extract->getVectorOperand(),
1793}

◆ 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 2293 of file SVFIRBuilder.cpp.

2294{
2295 NodeID base = getValueNode(val);
2297 if (gepval==UINT_MAX)
2298 {
2299 assert(((int) UINT_MAX)==-1 && "maximum limit of unsigned int is not -1?");
2300 /*
2301 * getGepValVar can only be called from two places:
2302 * 1. SVFIRBuilder::addComplexConsForExt to handle external calls
2303 * 2. SVFIRBuilder::getGlobalVarField to initialize global variable
2304 * so curVal can only be
2305 * 1. Instruction
2306 * 2. GlobalVariable
2307 */
2308 assert(
2309 (SVFUtil::isa<Instruction>(curVal) || SVFUtil::isa<GlobalVariable>(curVal)) && "curVal not an instruction or a globalvariable?");
2310
2311 // We assume every GepValNode and its GepEdge to the baseNode are unique across the whole program
2312 // We preserve the current BB information to restore it after creating the gepNode
2313 const Value* cval = getCurrentValue();
2314 const SVFBasicBlock* cbb = getCurrentBB();
2317 const ICFGNode* node = nullptr;
2318 if (const Instruction* inst = SVFUtil::dyn_cast<Instruction>(curVal))
2319 {
2320 if (llvmmodule->hasICFGNode(inst))
2321 {
2322 node = llvmmodule->getICFGNode(inst);
2323 }
2324 }
2325 else if (SVFUtil::isa<GlobalVariable>(curVal))
2326 {
2327 // GEP on a global variable: the resulting GepValVar belongs to the global ICFG node.
2328 node = pag->getICFG()->getGlobalICFGNode();
2329 }
2331 NodeIDAllocator::get()->allocateValueId(),
2332 llvmmodule->getSVFType(PointerType::getUnqual(llvmmodule->getContext())), node);
2333 addGepEdge(base, gepNode, ap, true);
2335 return gepNode;
2336 }
2337 else
2338 return gepval;
2339}
GlobalICFGNode * getGlobalICFGNode() const
Definition ICFG.h:244
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:614
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:486

◆ 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 880 of file SVFIRBuilder.cpp.

881{
882
883 // if the global variable do not have any field needs to be initialized
884 if (offset == 0 && gvar->getInitializer()->getType()->isSingleValueType())
885 {
886 return getValueNode(gvar);
887 }
890 else
891 {
893 }
894}

◆ 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 203 of file SVFIRBuilder.h.

204 {
205 return llvmModuleSet()->getObjectNode(V);
206 }
NodeID getObjectNode(const Value *V)

◆ getPAG()

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

Return SVFIR.

Definition at line 165 of file SVFIRBuilder.h.

166 {
167 return pag;
168 }

◆ getReturnNode()

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

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

Definition at line 209 of file SVFIRBuilder.h.

210 {
211 return pag->getReturnNode(func);
212 }

◆ getValueNode()

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

Get different kinds of node.

Definition at line 193 of file SVFIRBuilder.h.

194 {
195 // first handle gep edge if val if a constant expression
196 processCE(V);
197
198 // strip off the constant cast and return the value node
199 return llvmModuleSet()->getValueNode(V);
200 }
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 215 of file SVFIRBuilder.h.

216 {
217 return pag->getVarargNode(func);
218 }
NodeID getVarargNode(const FunObjVar *func) const
getVarargNode - Return the unique node representing the variadic argument of a variadic function.
Definition IRGraph.cpp:71

◆ 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 2003 of file SVFIRBuilder.cpp.

2004{
2005
2006 assert(F);
2009 DBOUT(DPAGBuild, outs() << "handle direct call " << LLVMUtil::dumpValue(cs)
2010 << " callee " << F->getName().str() << "\n");
2011
2012 //Only handle the ret.val. if it's used as a ptr.
2014 //Does it actually return a ptr?
2015 if (!cs->getType()->isVoidTy())
2016 {
2020 }
2021 //Iterators for the actual and formal parameters
2022 u32_t itA = 0, ieA = cs->arg_size();
2023 Function::const_arg_iterator itF = F->arg_begin(), ieF = F->arg_end();
2024 //Go through the fixed parameters.
2025 DBOUT(DPAGBuild, outs() << " args:");
2026 for (; itF != ieF; ++itA, ++itF)
2027 {
2028 //Some programs (e.g. Linux kernel) leave unneeded parameters empty.
2029 if (itA == ieA)
2030 {
2031 DBOUT(DPAGBuild, outs() << " !! not enough args\n");
2032 break;
2033 }
2034 const Value* AA = cs->getArgOperand(itA), *FA = &*itF; //current actual/formal arg
2035
2036 DBOUT(DPAGBuild, outs() << "process actual parm "
2037 << LLVMUtil::dumpValue(AA) << "\n");
2038
2043 }
2044 //Any remaining actual args must be varargs.
2045 if (F->isVarArg())
2046 {
2048 DBOUT(DPAGBuild, outs() << "\n varargs:");
2049 for (; itA != ieA; ++itA)
2050 {
2051 const Value* AA = cs->getArgOperand(itA);
2055 }
2056 }
2057 if(itA != ieA)
2058 {
2061 writeWrnMsg("too many args to non-vararg func.");
2062 writeWrnMsg("(" + callICFGNode->getSourceLoc() + ")");
2063
2064 }
2065}
FunExitICFGNode * getFunExitICFGNode(const FunObjVar *fun)
Add a function exit node.
Definition ICFG.cpp:250
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.
std::string dumpValue(const Value *val)
Definition LLVMUtil.cpp:616

◆ 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 471 of file SVFIRExtAPI.cpp.

472{
474
476 {
478 }
480 {
484 }
486 {
488 Value* arg = cs->getArgOperand(arg_pos);
489 if (cs->getArgOperand(arg_pos)->getType()->isPointerTy())
490 {
493 NodeID obj = pag->addDummyObjNode(llvmModuleSet()->getSVFType(cs->getArgOperand(arg_pos)->getType()));
494 if (vnArg && dummy && obj)
495 {
498 }
499 }
500 else
501 {
502 writeWrnMsg("Arg receiving new object must be pointer type");
503 }
504 }
506 {
507 // Side-effects similar to void *memcpy(void *dest, const void * src, size_t n)
508 // which copies n characters from memory area 'src' to memory area 'dest'.
509 if(callee->getName().find("iconv") != std::string::npos)
510 addComplexConsForExt(cs->getArgOperand(3), cs->getArgOperand(1), nullptr);
511 else if(callee->getName().find("bcopy") != std::string::npos)
512 addComplexConsForExt(cs->getArgOperand(1), cs->getArgOperand(0), cs->getArgOperand(2));
513 if(cs->arg_size() == 3)
514 addComplexConsForExt(cs->getArgOperand(0), cs->getArgOperand(1), cs->getArgOperand(2));
515 else
516 addComplexConsForExt(cs->getArgOperand(0), cs->getArgOperand(1), nullptr);
517 if(SVFUtil::isa<PointerType>(cs->getType()))
518 addCopyEdge(getValueNode(cs->getArgOperand(0)), getValueNode(cs), CopyStmt::COPYVAL);
519 }
520 else if (llvmModuleSet()->hasExtFuncAnnotation(callee, "STRLEN"))
521 {
522 // strlen(p) and wcslen(p) read characters, not just p's address.
523 // For char s[4]="ABC", represent reads of s[0..3] so a write
524 // to s[1] in a callee can reach this call through the SVFG.
525 std::vector<AccessPath> fields;
526 const Value* arg = cs->getArgOperand(0);
527 const Type* type = getBaseTypeAndFlattenedFields(arg, fields, nullptr);
528 for (const AccessPath& field : fields)
529 {
530 const SVFType* elementType = pag->getFlatternedElemType(
531 llvmModuleSet()->getSVFType(type),
532 field.getConstantStructFldIdx());
533 NodeID address = getGepValVar(arg, field, elementType);
535 }
536 }
538 {
539 // Side-effects similar to memset(void *str, int c, size_t n)
540 // which copies the character c (an unsigned char) to the first n characters of the string pointed to, by the argument str
541 std::vector<AccessPath> dstFields;
542 const Type *dtype = getBaseTypeAndFlattenedFields(cs->getArgOperand(0), dstFields, cs->getArgOperand(2));
543 u32_t sz = dstFields.size();
544 //For each field (i), add store edge *(arg0 + i) = arg1
545 for (u32_t index = 0; index < sz; index++)
546 {
549 dstFields[index].getConstantStructFldIdx());
550 NodeID dField = getGepValVar(cs->getArgOperand(0), dstFields[index], dElementType);
551 addStoreEdge(getValueNode(cs->getArgOperand(1)),dField);
552 }
553 if(SVFUtil::isa<PointerType>(cs->getType()))
554 addCopyEdge(getValueNode(cs->getArgOperand(0)), getValueNode(cs), CopyStmt::COPYVAL);
555 }
556 else if(callee->getName().compare("dlsym") == 0)
557 {
558 /*
559 Side-effects of void* dlsym( void* handle, const char* funName),
560 Locate the function with the name "funName," then add a "copy" edge between the callsite and that function.
561 dlsym() example:
562 int main() {
563 // Open the shared library
564 void* handle = dlopen("./my_shared_library.so", RTLD_LAZY);
565 // Find the function address
566 void (*myFunctionPtr)() = (void (*)())dlsym(handle, "myFunction");
567 // Call the function
568 myFunctionPtr();
569 }
570 */
571 const Value* src = cs->getArgOperand(1);
572 if(const GetElementPtrInst* gep = SVFUtil::dyn_cast<GetElementPtrInst>(src))
573 src = stripConstantCasts(gep->getPointerOperand());
574
575 auto getHookFn = [](const Value* src)->const Function*
576 {
577 if (!SVFUtil::isa<GlobalVariable>(src))
578 return nullptr;
579
580 auto *glob = SVFUtil::cast<GlobalVariable>(src);
581 if (!glob->hasInitializer() || !SVFUtil::isa<ConstantDataArray>(glob->getInitializer()))
582 return nullptr;
583
584 auto *constarray = SVFUtil::cast<ConstantDataArray>(glob->getInitializer());
585 return LLVMUtil::getProgFunction(constarray->getAsCString().str());
586 };
587
588 if (const Function *fn = getHookFn(src))
589 {
592 }
593 }
594 else if(callee->getName().find("_ZSt29_Rb_tree_insert_and_rebalancebPSt18_Rb_tree_node_baseS0_RS_") != std::string::npos)
595 {
596 // 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.
597 assert(cs->arg_size() == 4 && "_Rb_tree_insert_and_rebalance should have 4 arguments.\n");
598
599 // We have vArg3 points to the entry of _Rb_tree_node_base { color; parent; left; right; }.
600 // Now we calculate the offset from base to vArg3
601 NodeID vnArg3 = llvmModuleSet()->getValueNode(cs->getArgOperand(3));
604
605 // We get all flattened fields of base
607
608 // We summarize the side effects: arg3->parent = arg1, arg3->left = arg1, arg3->right = arg1
609 // Note that arg0 is aligned with "offset".
610 for (APOffset i = offset + 1; i <= offset + 3; ++i)
611 {
612 if((u32_t)i >= fields.size())
613 break;
614 const SVFType* elementType = pag->getFlatternedElemType(pag->getTypeLocSetsMap(vnArg3).first,
615 fields[i].getConstantStructFldIdx());
616 NodeID vnD = getGepValVar(cs->getArgOperand(3), fields[i], elementType);
617 NodeID vnS = llvmModuleSet()->getValueNode(cs->getArgOperand(1));
618 if(vnD && vnS)
620 }
621 }
622
624 {
626 if (const FunValVar* funcValVar = SVFUtil::dyn_cast<FunValVar>(valVar))
627 {
632 assert((forkedFun->arg_size() <= 2) && "Size of formal parameter of start routine should be one");
633 if (forkedFun->arg_size() <= 2 && forkedFun->arg_size() >= 1)
634 {
635 const ArgValVar* formalParm = forkedFun->getArg(0);
637 if (actualParm->isPointer() && formalParm->getType()->isPointerTy())
638 {
640 addThreadForkEdge(actualParm->getId(), formalParm->getId(), callICFGNode, entry);
641 }
642 }
643 }
644 else
645 {
650 }
654 }
655
657}
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)
virtual void handleNondetArgStoreAtExtCall(const CallBase *cs, const CallICFGNode *callICFGNode)
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:342
const Function * getProgFunction(const std::string &funName)
Get program entry function from module.
Definition LLVMUtil.cpp:41
const Value * stripConstantCasts(const Value *val)
Strip off the constant casts.
Definition LLVMUtil.cpp:220
bool isHeapAllocExtCallViaRet(const Instruction *inst)
Definition LLVMUtil.cpp:649
bool isHeapAllocExtCallViaArg(const Instruction *inst)
Definition LLVMUtil.cpp:664
bool isMemsetExtFun(const Function *fun)
Definition LLVMUtil.cpp:396
u32_t getHeapAllocHoldingArgPosition(const Function *fun)
Definition LLVMUtil.cpp:402
bool isThreadForkCall(const CallICFGNode *inst)
Definition SVFUtil.h:365
const ValVar * getActualParmAtForkSite(const CallICFGNode *cs)
Return sole argument of the thread routine.
Definition SVFUtil.h:413
const ValVar * getForkedFun(const CallICFGNode *inst)
Return thread fork function.
Definition SVFUtil.h:336

◆ handleIndCall()

void SVFIRBuilder::handleIndCall ( CallBase *  cs)
protected

Handle indirect call.

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

Definition at line 2224 of file SVFIRBuilder.cpp.

2225{
2227 NodeID indFunPtrId = llvmModuleSet()->getValueNode(cs->getCalledOperand());
2228 const_cast<CallICFGNode*>(cbn)->setIndFunPtr(pag->getGNode(indFunPtrId));
2230}
void addIndirectCallsites(const CallICFGNode *cs, NodeID funPtr)
Add indirect callsites.
Definition SVFIR.h:654

◆ handleNondetArgStoreAtExtCall()

void SVFIRBuilder::handleNondetArgStoreAtExtCall ( const CallBase *  cs,
const CallICFGNode *  callICFGNode 
)
protectedvirtual

Definition at line 415 of file SVFIRExtAPI.cpp.

416{
418 NodeID src = pag->getBlkPtr();
419 const FunObjVar* extFun = callICFGNode->getCalledFunction();
420 if (extFun)
421 {
422 for (const std::string& annotation :
423 ExtAPI::getExtAPI()->getExtFuncAnnotations(extFun))
424 {
427 {
428 if (annotatedFormatArg < cs->arg_size())
429 {
430 src = pag->getBlkPtr();
432 {
433 // scanf("%d", &n) writes a number, not a pointer. Copy BlkPtr
434 // into a non-pointer variable so AE still sees an unknown value.
436 // Keep the call's LLVM value available when printing this variable.
439 }
440 }
441 continue;
442 }
443
444 u32_t firstArg = 0;
446 continue;
447 if (firstArg >= cs->arg_size())
448 continue;
449
450 for (u32_t argIdx = firstArg; argIdx < cs->arg_size(); ++argIdx)
451 storeTopArgs.insert(argIdx);
452 }
453 }
454
456 {
457 const Value* arg = cs->getArgOperand(argIdx);
458 if (!arg->getType()->isPointerTy())
459 continue;
460
461 const Type* storedType =
463 NodeID dst = getValueNode(arg);
465 dst = fieldZero;
466 if (src && dst)
467 addStoreEdge(src, dst);
468 }
469}
NodeID getDirectAccessFieldZeroValVar(const Value *ptr, const Type *accessTy)
static SVFType * getSVFInt8Type()
Definition SVFType.h:222

◆ inferFieldIdxFromByteOffset()

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

Infer field index from byteoffset.

Definition at line 625 of file SVFIRBuilder.cpp.

626{
627 return 0;
628}

◆ initDomTree()

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

Definition at line 262 of file SVFIRBuilder.cpp.

263{
264 if (fun->isDeclaration())
265 return;
266 //process and stored dt & df
269 df.analyze(dt);
271 PostDominatorTree pdt = PostDominatorTree(const_cast<Function&>(*fun));
272 SVFLoopAndDomInfo* ld = svffun->getLoopAndDomInfo();
273
275 for (DominanceFrontierBase::const_iterator dfIter = df.begin(), eDfIter = df.end(); dfIter != eDfIter; dfIter++)
276 {
277 const BasicBlock* keyBB = dfIter->first;
278#if LLVM_VERSION_MAJOR > 16
279 const llvm::SetVector<llvm::BasicBlock* >& domSet = dfIter->second;
280#else
281 const std::set<BasicBlock* >& domSet = dfIter->second;
282#endif
284 for (const BasicBlock* bbValue:domSet)
285 {
286 valueBasicBlocks.insert(llvmModuleSet()->getSVFBasicBlock(bbValue));
287 }
288 }
289 std::vector<const SVFBasicBlock*> reachableBBs;
290 LLVMUtil::getFunReachableBBs(fun, reachableBBs);
291 ld->setReachableBBs(reachableBBs);
292
293 for (Function::const_iterator bit = fun->begin(), beit = fun->end(); bit!=beit; ++bit)
294 {
295 const BasicBlock &bb = *bit;
297 if (DomTreeNode* dtNode = dt.getNode(&bb))
298 {
299 SVFLoopAndDomInfo::BBSet& bbSet = ld->getDomTreeMap()[svfBB];
300 for (const auto domBB : *dtNode)
301 {
302 const auto* domSVFBB = llvmModuleSet()->getSVFBasicBlock(domBB->getBlock());
303 bbSet.insert(domSVFBB);
304 }
305 }
306
307 if (DomTreeNode* pdtNode = pdt.getNode(&bb))
308 {
309 u32_t level = pdtNode->getLevel();
310 ld->getBBPDomLevel()[svfBB] = level;
311 BasicBlock* idomBB = pdtNode->getIDom()->getBlock();
313 ld->getBB2PIdom()[svfBB] = idom;
314
315 SVFLoopAndDomInfo::BBSet& bbSet = ld->getPostDomTreeMap()[svfBB];
316 for (const auto domBB : *pdtNode)
317 {
318 const auto* domSVFBB = llvmModuleSet()->getSVFBasicBlock(domBB->getBlock());
319 bbSet.insert(domSVFBB);
320 }
321 }
322
323 if (const Loop* loop = loopInfo.getLoopFor(&bb))
324 {
325 for (const BasicBlock* loopBlock : loop->getBlocks())
326 {
328 ld->addToBB2LoopMap(svfBB, loopbb);
329 }
330 }
331 }
332}
SVFBasicBlock * getSVFBasicBlock(const BasicBlock *bb)
Definition LLVMModule.h:305
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:76
llvm::LoopInfo LoopInfo
Definition BasicTypes.h:148
llvm::DomTreeNode DomTreeNode
Definition BasicTypes.h:141
llvm::PostDominatorTree PostDominatorTree
Definition BasicTypes.h:143
llvm::DominanceFrontier DominanceFrontier
Definition BasicTypes.h:142
llvm::Loop Loop
LLVM Loop.
Definition BasicTypes.h:147
llvm::DominatorTree DominatorTree
LLVM Dominators.
Definition BasicTypes.h:140

◆ initFunObjVar()

void SVFIRBuilder::initFunObjVar ( )

Function

set realDefFun for all functions

Definition at line 191 of file SVFIRBuilder.cpp.

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

◆ InitialGlobal()

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

src should not point to anything yet

Definition at line 907 of file SVFIRBuilder.cpp.

909{
910 DBOUT(DPAGBuild, outs() << "global " << LLVMUtil::dumpValue(gvar)
911 << " constant initializer: "
912 << LLVMUtil::dumpValue(C) << "\n");
913 if (C->getType()->isSingleValueType())
914 {
915 NodeID src = getValueNode(C);
916 // get the field value if it is available, otherwise we create a dummy field node.
918 NodeID field = getGlobalVarField(gvar, offset, llvmModuleSet()->getSVFType(C->getType()));
919
920 if (SVFUtil::isa<GlobalVariable, Function>(C))
921 {
923 addStoreEdge(src, field);
924 }
925 else if (SVFUtil::isa<ConstantExpr>(C))
926 {
927 // add gep edge of C1 itself is a constant expression
928 processCE(C);
930 addStoreEdge(src, field);
931 }
932 else if (SVFUtil::isa<BlockAddress>(C))
933 {
934 // blockaddress instruction (e.g. i8* blockaddress(@run_vm, %182))
935 // is treated as constant data object for now, see LLVMUtil.h:397, SymbolTableInfo.cpp:674 and SVFIRBuilder.cpp:183-194
936 processCE(C);
939 }
940 else
941 {
943 addStoreEdge(src, field);
945 if (C->getType()->isPtrOrPtrVectorTy() && src != pag->getNullPtr())
947 }
948 }
949 else if (SVFUtil::isa<ConstantArray, ConstantStruct>(C))
950 {
952 return;
953 for (u32_t i = 0, e = C->getNumOperands(); i != e; i++)
954 {
956 InitialGlobal(gvar, SVFUtil::cast<Constant>(C->getOperand(i)), offset + off);
957 }
958 }
959 else if(ConstantData* data = SVFUtil::dyn_cast<ConstantData>(C))
960 {
962 {
963 if(ConstantDataSequential* seq = SVFUtil::dyn_cast<ConstantDataSequential>(data))
964 {
965 for(u32_t i = 0; i < seq->getNumElements(); i++)
966 {
967 u32_t off = pag->getFlattenedElemIdx(llvmModuleSet()->getSVFType(C->getType()), i);
968 Constant* ct = seq->getElementAsConstant(i);
970 }
971 }
972 else
973 {
974 assert((SVFUtil::isa<ConstantAggregateZero, UndefValue>(data)) && "Single value type data should have been handled!");
975 }
976 }
977 }
978 else
979 {
980 //TODO:assert(SVFUtil::isa<ConstantVector>(C),"what else do we have");
981 }
982}
NodeID getConstantNode() const
Definition IRGraph.h:255
static Option< bool > ModelConsts
Definition Options.h:178
static const Option< bool > VtableInSVFIR
Definition Options.h:208
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)
A carefully crafted input such as FakeVTable _ZTV1A = {{nullptr, nullptr}}; can forge a vtable; detec...
Definition CppUtil.cpp:274
llvm::ConstantData ConstantData
Definition BasicTypes.h:120
llvm::Constant Constant
Definition BasicTypes.h:128
llvm::ConstantDataSequential ConstantDataSequential
Definition BasicTypes.h:123

◆ initialiseAggregateReturns()

void SVFIRBuilder::initialiseAggregateReturns ( )
private

Discover demanded fields and preallocate output parameters, slots and snapshots before visiting instructions. See the aggregate return example in SVFIRBuilder.h.

Definition at line 1577 of file SVFIRBuilder.cpp.

1578{
1581 PointerType::getUnqual(llvmModuleSet()->getContext()));
1582 // Serialized points-to sets use NodeIDs. Allocate in function order,
1583 // independent of pointer-keyed hash table iteration.
1584 for (const Function* fun : llvmModuleSet()->getFunctionSet())
1585 {
1586 auto found = demands.find(fun);
1587 if (found == demands.end())
1588 continue;
1591 }
1592}
void createAggregateCallSlots(const Function *fun, const SVFType *pointerType)
AggregateReturnFields discoverAggregateReturnFields()
void createAggregateReturnParams(const Function *fun, const std::set< AggregateField > &fields, const SVFType *pointerType)

◆ initialiseBaseObjVars()

void SVFIRBuilder::initialiseBaseObjVars ( )

Definition at line 376 of file SVFIRBuilder.cpp.

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

◆ initialiseNodes()

void SVFIRBuilder::initialiseNodes ( )

Initialize nodes and edges.

add address edges for constant nodes.

add argvalvar for svffunctions

Definition at line 535 of file SVFIRBuilder.cpp.

536{
537 DBOUT(DPAGBuild, outs() << "Initialise SVFIR Nodes ...\n");
538
539
544
547
548 for (LLVMModuleSet::FunToIDMapTy::iterator iter =
549 llvmModuleSet()->retSyms().begin(); iter != llvmModuleSet()->retSyms().end();
550 ++iter)
551 {
552 const Value* llvmValue = iter->first;
553 // retSyms keys are Function*, not Instruction, so dyn_cast<Instruction> always fails.
554 // RetValPN represents the callee's return value, defined at FunExitICFGNode.
555 // External functions have no exit node, so keep nullptr.
556 const FunObjVar* funObjVar = llvmModuleSet()->getFunObjVar(SVFUtil::cast<Function>(llvmValue));
557 const ICFGNode* icfgNode = funObjVar->isDeclaration() ? nullptr : pag->getICFG()->getFunExitICFGNode(funObjVar);
558 DBOUT(DPAGBuild, outs() << "add ret node " << iter->second << "\n");
559 pag->addRetNode(iter->second,
560 funObjVar,
561 llvmModuleSet()->getSVFType(iter->first->getType()), icfgNode);
563 pag->returnFunObjSymMap[funObjVar] = iter->second;
564 }
565
566 for (LLVMModuleSet::FunToIDMapTy::iterator iter =
567 llvmModuleSet()->varargSyms().begin();
568 iter != llvmModuleSet()->varargSyms().end(); ++iter)
569 {
570 const Value* llvmValue = iter->first;
571 // varargSyms keys are Function*, not Instruction.
572 // Variadic arguments are received at the function entry point.
573 // External functions have no entry node, so keep nullptr.
574 const FunObjVar* funObjVar = llvmModuleSet()->getFunObjVar(SVFUtil::cast<Function>(llvmValue));
575 const ICFGNode* icfgNode = funObjVar->isDeclaration() ? nullptr : pag->getICFG()->getFunEntryICFGNode(funObjVar);
576 DBOUT(DPAGBuild, outs() << "add vararg node " << iter->second << "\n");
577 pag->addVarargNode(iter->second,
578 funObjVar,
579 llvmModuleSet()->getSVFType(iter->first->getType()), icfgNode);
581 pag->varargFunObjSymMap[funObjVar] = iter->second;
582 }
583
585 for (LLVMModuleSet::ValueToIDMapTy::iterator iter =
586 llvmModuleSet()->objSyms().begin(); iter != llvmModuleSet()->objSyms().end(); ++iter)
587 {
588 DBOUT(DPAGBuild, outs() << "add address edges for constant node " << iter->second << "\n");
589 const Value* val = iter->first;
591 {
593 if(ptr!= pag->getBlkPtr() && ptr!= pag->getNullPtr())
594 {
596 addAddrEdge(iter->second, ptr);
597 }
598 }
599 }
600
602 && "not all node have been initialized!!!");
603
605 for (auto& fun: llvmModuleSet()->getFunctionSet())
606 {
607 for (const Argument& arg : fun->args())
608 {
609 const_cast<FunObjVar*>(llvmModuleSet()->getFunObjVar(fun))->addArgument(SVFUtil::cast<ArgValVar>(
611 }
612 }
613
614}
bool isDeclaration() const
u32_t getTotalSymNum() const
Statistics.
Definition IRGraph.h:204
FunObjVarToIDMapTy varargFunObjSymMap
vararg map
Definition IRGraph.h:85
FunObjVarToIDMapTy returnFunObjSymMap
return map
Definition IRGraph.h:84
FunToIDMapTy & retSyms()
Definition LLVMModule.h:281
FunToIDMapTy & varargSyms()
Definition LLVMModule.h:286
NodeID addNullPtrNode()
Add NullPtr PAGNode.
NodeID addBlackholePtrNode()
Definition SVFIR.h:835
NodeID addBlackholeObjNode()
Definition SVFIR.h:827
NodeID addVarargNode(NodeID i, const FunObjVar *val, const SVFType *type, const ICFGNode *n)
Add a unique vararg node for a procedure.
Definition SVFIR.h:787
NodeID addRetNode(NodeID i, const FunObjVar *callGraphNode, const SVFType *type, const ICFGNode *icn)
Add a unique return node for a procedure.
Definition SVFIR.h:781
NodeID addConstantObjNode()
Definition SVFIR.h:831
bool isConstantObjSym(const Value *val)
Check whether this value points-to a constant object.
Definition CppUtil.cpp:684
llvm::Argument Argument
Definition BasicTypes.h:152

◆ initialiseValVars()

void SVFIRBuilder::initialiseValVars ( )

Definition at line 453 of file SVFIRBuilder.cpp.

454{
455 // Iterate over all value symbols in the symbol table
456 for (LLVMModuleSet::ValueToIDMapTy::iterator iter =
457 llvmModuleSet()->valSyms().begin(); iter != llvmModuleSet()->valSyms().end();
458 ++iter)
459 {
460 // Debug output for adding value node
461 DBOUT(DPAGBuild, outs() << "add val node " << iter->second << "\n");
462
463 // Skip blackhole and null pointer symbols
464 if(iter->second == pag->blkPtrSymID() || iter->second == pag->nullPtrSymID())
465 continue;
466
467 const ICFGNode* icfgNode = nullptr;
468 auto llvmValue = iter->first;
469
470 // Check if the value is a function and get its call graph node
471 if (const Function* func = SVFUtil::dyn_cast<Function>(llvmValue))
472 {
473 pag->addFunValNode(iter->second, icfgNode, llvmModuleSet()->getFunObjVar(func), llvmModuleSet()->getSVFType(llvmValue->getType()));
474 }
475 else if (auto argval = SVFUtil::dyn_cast<Argument>(llvmValue))
476 {
477 // Formal params are defined at FunEntryICFGNode (where CallPE copies actual args).
478 // External (declaration-only) functions have no entry node, so keep nullptr.
479 const FunObjVar* funObj = llvmModuleSet()->getFunObjVar(argval->getParent());
480 const ICFGNode* entryNode = funObj->isDeclaration() ? nullptr : pag->getICFG()->getFunEntryICFGNode(funObj);
482 iter->second, argval->getArgNo(), entryNode,
483 funObj, llvmModuleSet()->getSVFType(llvmValue->getType()));
484 if (!argval->hasName())
485 pag->getGNode(iter->second)->setName("arg_" + std::to_string(argval->getArgNo()));
486 }
487 else if (auto fpValue = SVFUtil::dyn_cast<ConstantFP>(llvmValue))
488 {
489 pag->addConstantFPValNode(iter->second, LLVMUtil::getDoubleValue(fpValue), icfgNode, llvmModuleSet()->getSVFType(llvmValue->getType()));
490 }
491 else if (auto intValue = SVFUtil::dyn_cast<ConstantInt>(llvmValue))
492 {
493 pag->addConstantIntValNode(iter->second, LLVMUtil::getIntegerValue(intValue), icfgNode, llvmModuleSet()->getSVFType(llvmValue->getType()));
494 }
495 else if (SVFUtil::isa<ConstantPointerNull>(llvmValue))
496 {
497 pag->addConstantNullPtrValNode(iter->second, icfgNode, llvmModuleSet()->getSVFType(llvmValue->getType()));
498 }
499 else if (SVFUtil::isa<GlobalValue>(llvmValue))
500 {
501 // Global variables are defined at the global ICFG node.
503 llvmModuleSet()->getSVFType(llvmValue->getType()));
504 }
505 else if (SVFUtil::isa<ConstantData, ConstantExpr, MetadataAsValue, BlockAddress, ConstantAggregate>(llvmValue))
506 {
507 pag->addConstantDataValNode(iter->second, icfgNode, llvmModuleSet()->getSVFType(llvmValue->getType()));
508 }
509 else if (SVFUtil::isa<InlineAsm>(llvmValue) ||
510 SVFUtil::isa<DSOLocalEquivalent>(llvmValue) ||
511 SVFUtil::isa<NoCFIValue>(llvmValue))
512 {
513 pag->addAsmPCValNode(iter->second, llvmModuleSet()->getSVFType(llvmValue->getType()));
514 }
515 else if (const Instruction* inst = SVFUtil::dyn_cast<Instruction>(llvmValue))
516 {
518 pag->addIntrinsicValNode(iter->second, llvmModuleSet()->getSVFType(llvmValue->getType()));
519 else
520 {
521 assert(llvmModuleSet()->hasICFGNode(inst) && "LLVM instruction is not associated with an ICFGNode");
522 icfgNode = llvmModuleSet()->getICFGNode(inst);
523 pag->addValNode(iter->second, llvmModuleSet()->getSVFType(llvmValue->getType()), icfgNode);
524 }
525 }
527 pag->getGNode(iter->second));
528 }
529}
NodeID blkPtrSymID() const
Definition IRGraph.h:182
NodeID nullPtrSymID() const
Definition IRGraph.h:187
ValueToIDMapTy & valSyms()
Definition LLVMModule.h:214
NodeID addGlobalValNode(const NodeID i, const ICFGNode *icfgNode, const SVFType *svfType)
Definition SVFIR.h:704
NodeID addConstantDataValNode(const NodeID i, const ICFGNode *icfgNode, const SVFType *type)
Definition SVFIR.h:710
NodeID addIntrinsicValNode(NodeID i, const SVFType *type)
Definition SVFIR.h:839
NodeID addFunValNode(NodeID i, const ICFGNode *icfgNode, const FunObjVar *funObjVar, const SVFType *type)
Definition SVFIR.h:671
NodeID addConstantFPValNode(const NodeID i, double dval, const ICFGNode *icfgNode, const SVFType *type)
Definition SVFIR.h:684
NodeID addAsmPCValNode(NodeID i, const SVFType *type)
Definition SVFIR.h:843
virtual void setName(const std::string &nameInfo)
Definition SVFValue.h:174
bool isIntrinsicInst(const Instruction *inst)
Return true if it is an intrinsic instruction.
Definition LLVMUtil.cpp:204

◆ 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 219 of file SVFIRBuilder.cpp.

220{
222 for (Function::const_iterator bit = func->begin(), ebit = func->end(); bit != ebit; ++bit)
223 {
224 const BasicBlock* bb = &*bit;
227 {
230 }
232 {
235 }
236
238 if (svfbb->getSuccessors().empty())
239 {
241 {
243 SVFUtil::isa<ReturnInst>(bb->back())) &&
244 "last inst must be return inst");
245 svfFun->setExitBlock(svfbb);
246 }
247 }
248 }
249 // For no return functions, we set the last block as exit BB
250 // This ensures that each function that has definition must have an exit BB
251 if (svfFun->hasBasicBlock() && svfFun->exitBlock == nullptr)
252 {
253 SVFBasicBlock* retBB = const_cast<SVFBasicBlock*>(svfFun->back());
255 SVFUtil::isa<ReturnInst>(&func->back().back())) &&
256 "last inst must be return inst");
257 svfFun->setExitBlock(retBB);
258 }
259}
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:110
llvm::succ_const_iterator succ_const_iterator
LLVM Iterators.
Definition BasicTypes.h:287
llvm::const_pred_iterator const_pred_iterator
Definition BasicTypes.h:265

◆ llvmModuleSet()

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

Definition at line 623 of file SVFIRBuilder.h.

624 {
626 }

◆ processCE()

void SVFIRBuilder::processCE ( const Value *  val)
protected

Process constant expression.

Handle constant expression, and connect the gep edge

Definition at line 746 of file SVFIRBuilder.cpp.

747{
748 if (const Constant* ref = SVFUtil::dyn_cast<Constant>(val))
749 {
751 {
752 DBOUT(DPAGBuild, outs() << "handle gep constant expression "
753 << LLVMUtil::dumpValue(ref) << "\n");
754 const Constant* opnd = gepce->getOperand(0);
755 // handle recursive constant express case (gep (bitcast (gep X 1)) 1)
757 auto &GEPOp = llvm::cast<llvm::GEPOperator>(*gepce);
758 Type *pType = GEPOp.getSourceElementType();
759 AccessPath ap(0, llvmModuleSet()->getSVFType(pType));
760 bool constGep = computeGepOffset(gepce, ap);
761 // must invoke pag methods here, otherwise it will be a dead recursion cycle
762 const Value* cval = getCurrentValue();
763 const SVFBasicBlock* cbb = getCurrentBB();
765 /*
766 * The gep edge created are like constexpr (same edge may appear at multiple callsites)
767 * so bb/inst of this edge may be rewritten several times, we treat it as global here.
768 */
771 }
772 else if (const ConstantExpr* castce = isCastConstantExpr(ref))
773 {
774 DBOUT(DPAGBuild, outs() << "handle cast constant expression "
775 << LLVMUtil::dumpValue(ref) << "\n");
776 const Constant* opnd = castce->getOperand(0);
778 const Value* cval = getCurrentValue();
779 const SVFBasicBlock* cbb = getCurrentBB();
783 }
785 {
786 DBOUT(DPAGBuild, outs() << "handle select constant expression "
787 << LLVMUtil::dumpValue(ref) << "\n");
788 const Constant* src1 = selectce->getOperand(1);
789 const Constant* src2 = selectce->getOperand(2);
792 const Value* cval = getCurrentValue();
793 const SVFBasicBlock* cbb = getCurrentBB();
795 NodeID cond = llvmModuleSet()->getValueNode(selectce->getOperand(0));
801 }
802 // if we meet a int2ptr, then it points-to black hole
804 {
805 const Constant* opnd = int2Ptrce->getOperand(0);
807 const SVFBasicBlock* cbb = getCurrentBB();
808 const Value* cval = getCurrentValue();
812 }
814 {
815 const Constant* opnd = ptr2Intce->getOperand(0);
817 const SVFBasicBlock* cbb = getCurrentBB();
818 const Value* cval = getCurrentValue();
822 }
824 {
825 // we don't handle trunc and cmp instruction for now
826 const Value* cval = getCurrentValue();
827 const SVFBasicBlock* cbb = getCurrentBB();
832 }
833 else if (isBinaryConstantExpr(ref))
834 {
835 // we don't handle binary constant expression like add(x,y) now
836 const Value* cval = getCurrentValue();
837 const SVFBasicBlock* cbb = getCurrentBB();
842 }
843 else if (isUnaryConstantExpr(ref))
844 {
845 // we don't handle unary constant expression like fneg(x) now
846 const Value* cval = getCurrentValue();
847 const SVFBasicBlock* cbb = getCurrentBB();
852 }
853 else if (SVFUtil::isa<ConstantAggregate>(ref))
854 {
855 // we don't handle constant aggregate like constant vectors
856 }
857 else if (SVFUtil::isa<BlockAddress>(ref))
858 {
859 // blockaddress instruction (e.g. i8* blockaddress(@run_vm, %182))
860 // is treated as constant data object for now, see LLVMUtil.h:397, SymbolTableInfo.cpp:674 and SVFIRBuilder.cpp:183-194
861 const Value* cval = getCurrentValue();
862 const SVFBasicBlock* cbb = getCurrentBB();
867 }
868 else
869 {
870 if(SVFUtil::isa<ConstantExpr>(val))
871 assert(false && "we don't handle all other constant expression for now!");
872 }
873 }
874}
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:310
const ConstantExpr * isInt2PtrConstantExpr(const Value *val)
Definition LLVMUtil.h:245
const ConstantExpr * isSelectConstantExpr(const Value *val)
Definition LLVMUtil.h:275
const ConstantExpr * isTruncConstantExpr(const Value *val)
Definition LLVMUtil.h:285
const ConstantExpr * isPtr2IntConstantExpr(const Value *val)
Definition LLVMUtil.h:255
const ConstantExpr * isUnaryConstantExpr(const Value *val)
Definition LLVMUtil.h:321
const ConstantExpr * isCastConstantExpr(const Value *val)
Definition LLVMUtil.h:265
const ConstantExpr * isGepConstantExpr(const Value *val)
Return corresponding constant expression, otherwise return nullptr.
Definition LLVMUtil.h:235
const ConstantExpr * isCmpConstantExpr(const Value *val)
Definition LLVMUtil.h:299
llvm::ConstantExpr ConstantExpr
Definition BasicTypes.h:124

◆ sanityCheck()

void SVFIRBuilder::sanityCheck ( )

Sanity check for SVFIR.

Definition at line 2267 of file SVFIRBuilder.cpp.

2268{
2269 for (SVFIR::iterator nIter = pag->begin(); nIter != pag->end(); ++nIter)
2270 {
2271 (void) pag->getGNode(nIter->first);
2272 //TODO::
2273 // (1) every source(root) node of a pag tree should be object node
2274 // if a node has no incoming edge, but has outgoing edges
2275 // then it has to be an object node.
2276 // (2) make sure every variable should be initialized
2277 // otherwise it causes the a null pointer, the aliasing relation may not be captured
2278 // when loading a pointer value should make sure
2279 // some value has been store into this pointer before
2280 // q = load p, some value should stored into p first like store w p;
2281 // (3) make sure PAGNode should not have a const expr value (pointer should have unique def)
2282 // (4) look closely into addComplexConsForExt, make sure program locations(e.g.,inst bb)
2283 // are set correctly for dummy gepval node
2284 // (5) reduce unnecessary copy edge (const casts) and ensure correctness.
2285 }
2286}
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

Only the return-value Phi merges at the shared function exit. Aggregate field stores, fallback addresses and a snapshot load before an immediate return belong to the individual return instruction.

CallPE is placed at FunEntryICFGNode (phi-like merging of actual params)

CallPE is phi-like at FunEntryICFGNode. Collect it on each CallCFGEdge whose call site appears as an operand, so the edge knows which params are passed.

Definition at line 2371 of file SVFIRBuilder.cpp.

2372{
2374 return;
2375
2376 assert(curVal && "current Val is nullptr?");
2377 edge->setBB(curBB!=nullptr ? curBB : nullptr);
2379 ICFGNode* icfgNode = pag->getICFG()->getGlobalICFGNode();
2381 if (const Instruction* curInst = SVFUtil::dyn_cast<Instruction>(curVal))
2382 {
2383 const FunObjVar* srcFun = edge->getSrcNode()->getFunction();
2384 const FunObjVar* dstFun = edge->getDstNode()->getFunction();
2385 if(srcFun!=nullptr && !SVFUtil::isa<RetPE>(edge) && !SVFUtil::isa<FunValVar>(edge->getSrcNode()) && !SVFUtil::isa<FunObjVar>(edge->getSrcNode()))
2386 {
2387 assert(srcFun==llvmMS->getFunObjVar(curInst->getFunction()) && "SrcNode of the PAGEdge not in the same function?");
2388 }
2389 if(dstFun!=nullptr && !SVFUtil::isa<CallPE>(edge) && !SVFUtil::isa<RetValPN>(edge->getDstNode()))
2390 {
2391 assert(dstFun==llvmMS->getFunObjVar(curInst->getFunction()) && "DstNode of the PAGEdge not in the same function?");
2392 }
2393
2395 if (!(SVFUtil::isa<GepStmt>(edge) && SVFUtil::isa<GepValVar>(edge->getDstNode())))
2396 assert(curBB && "instruction does not have a basic block??");
2397
2401 if(SVFUtil::isa<ReturnInst>(curInst) && SVFUtil::isa<PhiStmt>(edge))
2402 {
2403 icfgNode = pag->getICFG()->getFunExitICFGNode(llvmMS->getFunObjVar(curInst->getFunction()));
2404 }
2405 else if(const CallPE* callPE = SVFUtil::dyn_cast<CallPE>(edge))
2406 {
2408 icfgNode = const_cast<FunEntryICFGNode*>(callPE->getFunEntryICFGNode());
2409 }
2410 else if(SVFUtil::isa<RetPE>(edge))
2411 {
2412 icfgNode = llvmMS->getRetICFGNode(SVFUtil::cast<Instruction>(curInst));
2413 }
2414 else
2415 {
2416 icfgNode = llvmMS->getICFGNode(SVFUtil::cast<Instruction>(curInst));
2417 }
2418 }
2419 else if (const Argument* arg = SVFUtil::dyn_cast<Argument>(curVal))
2420 {
2422 icfgNode = pag->getICFG()->getFunEntryICFGNode(
2423 llvmModuleSet()->getFunObjVar(SVFUtil::cast<Function>(arg->getParent())));
2424 }
2425 else if (SVFUtil::isa<Constant>(curVal) ||
2426 SVFUtil::isa<Function>(curVal) ||
2427 SVFUtil::isa<MetadataAsValue>(curVal))
2428 {
2429 if (!curBB)
2431 else
2432 {
2433 icfgNode = const_cast<ICFGNode*>(curBB->front());
2434 }
2435 }
2436 else
2437 {
2438 assert(false && "what else value can we have?");
2439 }
2440
2441 pag->addToSVFStmtList(icfgNode,edge);
2442 icfgNode->addSVFStmt(edge);
2443 if(const CallPE* callPE = SVFUtil::dyn_cast<CallPE>(edge))
2444 {
2447 FunEntryICFGNode* entryNode = const_cast<FunEntryICFGNode*>(callPE->getFunEntryICFGNode());
2448 for(u32_t i = 0; i < callPE->getOpVarNum(); i++)
2449 {
2450 CallICFGNode* callNode = const_cast<CallICFGNode*>(callPE->getOpCallICFGNode(i));
2452 SVFUtil::cast<CallCFGEdge>(icfgEdge)->addCallPE(callPE);
2453 }
2454 }
2455 else if(const RetPE* retPE = SVFUtil::dyn_cast<RetPE>(edge))
2456 {
2457 RetICFGNode* retNode = const_cast<RetICFGNode*>(retPE->getCallSite()->getRetICFGNode());
2458 FunExitICFGNode* exitNode = const_cast<FunExitICFGNode*>(retPE->getFunExitICFGNode());
2460 SVFUtil::cast<RetCFGEdge>(edge)->addRetPE(retPE);
2461 }
2462}
const SVFBasicBlock * getEntryBlock() const
void addSVFStmt(const SVFStmt *edge)
Definition ICFGNode.h:111
ICFGEdge * hasInterICFGEdge(ICFGNode *src, ICFGNode *dst, ICFGEdge::ICFGEdgeK kind)
Definition ICFG.cpp:277
const FunObjVar * getParent() const
const ICFGNode * front() const
static bool pagReadFromTXT()
Definition SVFIR.h:281
void addToSVFStmtList(ICFGNode *inst, SVFStmt *edge)
Add a SVFStmt into instruction map.
Definition SVFIR.h:329
void addGlobalPAGEdge(const SVFStmt *edge)
Add global PAGEdges (not in a procedure)
Definition SVFIR.h:865

◆ 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 352 of file SVFIRBuilder.h.

353 {
354 curBB = (bb == nullptr? nullptr : llvmModuleSet()->getSVFBasicBlock(bb));
355 curVal = (val == nullptr ? nullptr: val);
356 }

◆ setCurrentLocation() [2/2]

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

Definition at line 357 of file SVFIRBuilder.h.

358 {
359 curBB = bb;
360 curVal = val;
361 }

◆ updateCallGraph()

void SVFIRBuilder::updateCallGraph ( CallGraph *  callgraph)

connect PAG edges based on callgraph

Definition at line 2232 of file SVFIRBuilder.cpp.

2233{
2234 CallGraph::CallEdgeMap::const_iterator iter = callgraph->getIndCallMap().begin();
2235 CallGraph::CallEdgeMap::const_iterator eiter = callgraph->getIndCallMap().end();
2236 for (; iter != eiter; iter++)
2237 {
2238 const CallICFGNode* callBlock = iter->first;
2239 const CallBase* callbase = SVFUtil::cast<CallBase>(llvmModuleSet()->getLLVMValue(callBlock));
2240 assert(callBlock->isIndirectCall() && "this is not an indirect call?");
2241 const CallGraph::FunctionSet& functions = iter->second;
2242 for (CallGraph::FunctionSet::const_iterator func_iter = functions.begin(); func_iter != functions.end(); func_iter++)
2243 {
2244 const Function* callee = SVFUtil::cast<Function>(llvmModuleSet()->getLLVMValue(*func_iter));
2245
2246 if (isExtCall(*func_iter))
2247 {
2248 setCurrentLocation(callee, callee->empty() ? nullptr : &callee->getEntryBlock());
2250 }
2251 else
2252 {
2253 setCurrentLocation(llvmModuleSet()->getLLVMValue(callBlock), callBlock->getBB());
2254 handleDirectCall(const_cast<CallBase*>(callbase), callee);
2255 }
2256 }
2257 }
2258
2259 // dump SVFIR
2261 pag->dump("svfir_final");
2262}
CallEdgeMap & getIndCallMap()
Get callees from an indirect callsite.
Definition CallGraph.h:331
Set< const FunObjVar * > FunctionSet
Definition CallGraph.h:247
void handleDirectCall(CallBase *cs, const Function *F)
Handle direct call.
virtual void handleExtCall(const CallBase *cs, const Function *callee)

◆ 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 1041 of file SVFIRBuilder.cpp.

1042{
1043
1044 // AllocaInst should always be a pointer type
1045 assert(SVFUtil::isa<PointerType>(inst.getType()));
1046
1048 outs() << "process alloca " << LLVMUtil::dumpValue(&inst) << "\n");
1049 NodeID dst = getValueNode(&inst);
1050
1051 NodeID src = getObjectNode(&inst);
1052
1053 addAddrWithStackArraySz(src, dst, inst);
1054
1055}
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 296 of file SVFIRBuilder.h.

297 {
299 }

◆ visitAtomicRMWInst()

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

Definition at line 300 of file SVFIRBuilder.h.

301 {
303 }

◆ visitBinaryOperator()

void SVFIRBuilder::visitBinaryOperator ( BinaryOperator &  inst)

Visit Binary Operator

Definition at line 1181 of file SVFIRBuilder.cpp.

1182{
1183 NodeID dst = getValueNode(&inst);
1184 assert(inst.getNumOperands() == 2 && "not two operands for BinaryOperator?");
1185 Value* op1 = inst.getOperand(0);
1187 Value* op2 = inst.getOperand(1);
1189 u32_t opcode = inst.getOpcode();
1190 addBinaryOPEdge(op1Node, op2Node, dst, opcode);
1191}
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 1847 of file SVFIRBuilder.cpp.

1848{
1849 NodeID brinst = getValueNode(&inst);
1850 NodeID cond;
1851 if (inst.isConditional())
1852 cond = getValueNode(inst.getCondition());
1853 else
1854 cond = pag->getNullPtr();
1855
1856 assert(inst.getNumSuccessors() <= 2 && "if/else has more than two branches?");
1857
1859 std::vector<const Instruction*> nextInsts;
1861 u32_t branchID = 0;
1862 for (const Instruction* succInst : nextInsts)
1863 {
1864 assert(branchID <= 1 && "if/else has more than two branches?");
1865 const ICFGNode* icfgNode = llvmModuleSet()->getICFGNode(succInst);
1866 successors.push_back(std::make_pair(icfgNode, 1-branchID));
1867 branchID++;
1868 }
1869 addBranchStmt(brinst, cond, successors);
1871 if (inst.isConditional())
1872 {
1873 for (auto& edge : llvmModuleSet()->getICFGNode(&inst)->getOutEdges())
1874 {
1875 if (IntraCFGEdge* intraEdge = SVFUtil::dyn_cast<IntraCFGEdge>(edge))
1876 {
1877 intraEdge->setConditionVar(pag->getGNode(cond));
1878 }
1879 }
1880 }
1881}
std::vector< std::pair< const ICFGNode *, s64_t > > SuccAndCondPairVec
void addBranchStmt(NodeID br, NodeID cond, const BranchStmt::SuccAndCondPairVec &succs)
Add Branch statement.

◆ visitCallBrInst()

void SVFIRBuilder::visitCallBrInst ( CallBrInst &  I)

Definition at line 1249 of file SVFIRBuilder.cpp.

1250{
1251 visitCallSite(&i);
1252}
void visitCallSite(CallBase *cs)

◆ visitCallInst()

void SVFIRBuilder::visitCallInst ( CallInst &  I)

Definition at line 1239 of file SVFIRBuilder.cpp.

1240{
1241 visitCallSite(&i);
1242}

◆ visitCallSite()

void SVFIRBuilder::visitCallSite ( CallBase *  cs)

Collect callsite arguments and returns

Definition at line 1257 of file SVFIRBuilder.cpp.

1258{
1259
1260 // skip llvm intrinsics
1261 if(isIntrinsicInst(cs))
1262 return;
1263
1265 outs() << "process callsite " << LLVMUtil::dumpValue(cs) << "\n");
1266
1267 CallICFGNode* callBlockNode = llvmModuleSet()->getCallICFGNode(cs);
1269
1270 pag->addCallSite(callBlockNode);
1271
1273 for (u32_t i = 0; i < cs->arg_size(); i++)
1275 callBlockNode,
1276 pag->getValVar(getValueNode(cs->getArgOperand(i))));
1277
1278 if(!cs->getType()->isVoidTy())
1280
1281 if (const auto* call = SVFUtil::dyn_cast<CallInst>(cs))
1283
1284 if (callBlockNode->isVirtualCall())
1285 {
1286 const Value* value = cppUtil::getVCallVtblPtr(cs);
1287 callBlockNode->setVtablePtr(pag->getGNode(getValueNode(value)));
1288 }
1289 if (const Function *callee = LLVMUtil::getCallee(cs))
1290 {
1292 {
1293 handleExtCall(cs, callee);
1294 }
1295 else
1296 {
1298 }
1299 }
1300 else
1301 {
1302 //If the callee was not identified as a function (null F), this is indirect.
1303 handleIndCall(cs);
1304 }
1305}
bool isVirtualCall() const
Definition ICFGNode.h:510
void setVtablePtr(SVFVar *v)
Definition ICFGNode.h:515
RetICFGNode * getRetICFGNode(const Instruction *cs)
get a return node
void addAggregateCallFields(const CallInst *call)
void handleIndCall(CallBase *cs)
Handle indirect call.
void addCallSite(const CallICFGNode *call)
Add callsites.
Definition SVFIR.h:870
void addCallSiteRets(RetICFGNode *retBlockNode, const ValVar *arg)
Add callsite returns.
Definition SVFIR.h:648
const Function * getCallee(const CallBase *cs)
Definition LLVMUtil.h:114
const Value * getVCallVtblPtr(const CallBase *cs)
Definition CppUtil.cpp:549

◆ visitCastInst()

void SVFIRBuilder::visitCastInst ( CastInst &  I)

Definition at line 1166 of file SVFIRBuilder.cpp.

1167{
1168
1170 outs() << "process cast " << LLVMUtil::dumpValue(&inst) << "\n");
1171 NodeID dst = getValueNode(&inst);
1172
1173 const Value* opnd = inst.getOperand(0);
1174 NodeID src = getValueNode(opnd);
1175 addCopyEdge(src, dst, getCopyKind(&inst));
1176}
CopyStmt::CopyKind getCopyKind(const Value *val)

◆ visitCmpInst()

void SVFIRBuilder::visitCmpInst ( CmpInst &  inst)

Visit compare instruction

Definition at line 1209 of file SVFIRBuilder.cpp.

1210{
1211 NodeID dst = getValueNode(&inst);
1212 assert(inst.getNumOperands() == 2 && "not two operands for compare instruction?");
1213 Value* op1 = inst.getOperand(0);
1215 Value* op2 = inst.getOperand(1);
1217 u32_t predicate = inst.getPredicate();
1218 addCmpEdge(op1Node, op2Node, dst, predicate);
1219}
void addCmpEdge(NodeID op1, NodeID op2, NodeID dst, u32_t predict)
Add Copy edge.

◆ visitExtractElementInst()

void SVFIRBuilder::visitExtractElementInst ( ExtractElementInst &  inst)

Extract a constant pointer lane using the same field model as extractvalue. For example: a = insertelement <2 x ptr> poison, ptr p, i32 0 b = insertelement <2 x ptr> poison, ptr q, i32 0 s = select i1 cond, <2 x ptr> a, <2 x ptr> b r = extractelement <2 x ptr> s, i32 0

Lane 0 is AggregateField{0}: its copies and conditional SelectStmt are defined at a, b and s, then this visitor copies the lane into r. Dynamic indices, scalable vectors and unsupported lane definitions keep the existing fallback.

Definition at line 1838 of file SVFIRBuilder.cpp.

1839{
1841}
void addExtractedFieldCopy(Instruction &inst)

◆ visitExtractValueInst()

void SVFIRBuilder::visitExtractValueInst ( ExtractValueInst &  inst)

Extract a pointer from a register aggregate using its shared field definition. For example: a = insertvalue {ptr} poison, ptr p, 0 b = insertvalue {ptr} poison, ptr q, 0 s = select i1 cond, {ptr} a, {ptr} b r = extractvalue {ptr} s, 0

getAggregateFieldNode(s, {0}, field) creates field copies at a and b and a SelectStmt with cond at s. This visitor adds one CopyStmt from field to r. Further extracts of s's field 0 reuse that definition. Unsupported fields keep the existing black-hole fallback.

Definition at line 1821 of file SVFIRBuilder.cpp.

1822{
1824}

◆ visitFenceInst()

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

Definition at line 292 of file SVFIRBuilder.h.

293 {
295 }

◆ 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 1988 of file SVFIRBuilder.cpp.

1989{
1990 NodeID dst = getValueNode(&inst);
1991 for (u32_t i = 0; i < inst.getNumOperands(); i++)
1992 {
1993 Value* opnd = inst.getOperand(i);
1994 NodeID src = getValueNode(opnd);
1995 addCopyEdge(src, dst, CopyStmt::COPYVAL);
1996 }
1997}

◆ visitGetElementPtrInst()

void SVFIRBuilder::visitGetElementPtrInst ( GetElementPtrInst &  inst)

Visit getelementptr instructions

Definition at line 1126 of file SVFIRBuilder.cpp.

1127{
1128
1129 NodeID dst = getValueNode(&inst);
1130 // GetElementPtrInst should always be a pointer or a vector contains pointers
1131 // for now we don't handle vector type here
1132 if(SVFUtil::isa<VectorType>(inst.getType()))
1133 {
1135 return;
1136 }
1137
1138 assert(SVFUtil::isa<PointerType>(inst.getType()));
1139
1141 outs() << "process gep " << LLVMUtil::dumpValue(&inst) << "\n");
1142
1143 NodeID src = getValueNode(inst.getPointerOperand());
1144
1145 AccessPath ap(0, llvmModuleSet()->getSVFType(inst.getSourceElementType()));
1146 bool constGep = computeGepOffset(&inst, ap);
1147 if (constGep && ap.getConstantStructFldIdx() == 0 && !Options::ModelArrays())
1148 {
1149 const Type* baseObjType =
1150 LLVMModuleSet::getLLVMModuleSet()->getTypeInference()->inferObjType(inst.getPointerOperand());
1151 if (const auto* arrTy = SVFUtil::dyn_cast<ArrayType>(baseObjType))
1152 {
1153 if (arrTy->getElementType()->isPointerTy())
1154 {
1155 addCopyEdge(src, dst, CopyStmt::COPYVAL);
1156 return;
1157 }
1158 }
1159 }
1160 addGepEdge(src, dst, ap, constGep);
1161}

◆ 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 987 of file SVFIRBuilder.cpp.

988{
989
991 for (Module &M : llvmModuleSet()->getLLVMModules())
992 {
993 for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I)
994 {
995 GlobalVariable *gvar = &*I;
998
1001
1002 if (gvar->hasInitializer())
1003 {
1004 Constant *C = gvar->getInitializer();
1005 DBOUT(DPAGBuild, outs() << "add global var node "
1006 << LLVMUtil::dumpValue(gvar) << "\n");
1007 InitialGlobal(gvar, C, 0);
1008 }
1009 }
1010
1011
1013 for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I)
1014 {
1015 const Function* fun = &*I;
1016 NodeID idx = getValueNode(fun);
1017 NodeID obj = getObjectNode(fun);
1018
1019 DBOUT(DPAGBuild, outs() << "add global function node " << fun->getName().str() << "\n");
1020 setCurrentLocation(fun, (SVFBasicBlock*) nullptr);
1022 }
1023
1024 // 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.
1025 for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); I != E; I++)
1026 {
1027 const GlobalAlias* alias = &*I;
1028 NodeID dst = llvmModuleSet()->getValueNode(alias);
1029 NodeID src = llvmModuleSet()->getValueNode(alias->getAliasee());
1030 processCE(alias->getAliasee());
1031 setCurrentLocation(alias, (SVFBasicBlock*) nullptr);
1032 addCopyEdge(src, dst, CopyStmt::COPYVAL);
1033 }
1034 }
1035}
llvm::GlobalAlias GlobalAlias
Definition BasicTypes.h:135

◆ visitInsertElementInst()

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

Keep the whole vector defined for full-SVFG consumers. getAggregateFieldNode models supported pointer lanes separately; those definitions do not read this fallback.

Definition at line 272 of file SVFIRBuilder.h.

273 {
275 }

◆ visitInsertValueInst()

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

Keep the whole aggregate defined for full-SVFG consumers. getAggregateFieldNode models demanded pointer fields separately; those definitions do not read this fallback.

Definition at line 243 of file SVFIRBuilder.h.

244 {
246 }

◆ visitInstruction()

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

Provide base case for our instruction visit.

Definition at line 306 of file SVFIRBuilder.h.

307 {
308 // If a new instruction is added to LLVM that we don't handle.
309 // TODO: ignore here:
310 }

◆ visitInvokeInst()

void SVFIRBuilder::visitInvokeInst ( InvokeInst &  II)

Definition at line 1244 of file SVFIRBuilder.cpp.

1245{
1246 visitCallSite(&i);
1247}

◆ visitLandingPadInst()

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

Definition at line 280 of file SVFIRBuilder.h.

281 {
283 }

◆ visitLoadInst()

void SVFIRBuilder::visitLoadInst ( LoadInst &  I)

Definition at line 1086 of file SVFIRBuilder.cpp.

1087{
1089 outs() << "process load " << LLVMUtil::dumpValue(&inst) << "\n");
1090
1091 NodeID dst = getValueNode(&inst);
1092
1093 NodeID src = getValueNode(inst.getPointerOperand());
1094 const Type* loadedTy = inst.getType();
1095 if (NodeID fieldZero = getDirectAccessFieldZeroValVar(inst.getPointerOperand(), loadedTy))
1096 src = fieldZero;
1097
1098 addLoadEdge(src, dst);
1099}

◆ visitPHINode()

void SVFIRBuilder::visitPHINode ( PHINode &  inst)

Visit phi instructions

Definition at line 1060 of file SVFIRBuilder.cpp.

1061{
1062
1064 outs() << "process phi " << LLVMUtil::dumpValue(&inst) << "\n");
1065
1066 NodeID dst = getValueNode(&inst);
1067
1068 for (u32_t i = 0; i < inst.getNumIncomingValues(); ++i)
1069 {
1070 const Value* val = inst.getIncomingValue(i);
1071 const Instruction* incomingInst = SVFUtil::dyn_cast<Instruction>(val);
1072 bool matched = (incomingInst == nullptr ||
1073 incomingInst->getFunction() == inst.getFunction());
1074 (void) matched; // Suppress warning of unused variable under release build
1075 assert(matched && "incomingInst's Function incorrect");
1076 const Instruction* predInst = &inst.getIncomingBlock(i)->back();
1077 const ICFGNode* icfgNode = llvmModuleSet()->getICFGNode(predInst);
1078 NodeID src = getValueNode(val);
1079 addPhiStmt(dst,src,icfgNode);
1080 }
1081}

◆ visitResumeInst()

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

Instruction not that often.

Definition at line 286 of file SVFIRBuilder.h.

287 {
288 }

◆ visitReturnInst()

void SVFIRBuilder::visitReturnInst ( ReturnInst &  inst)

Visit return instructions of a function

Definition at line 1310 of file SVFIRBuilder.cpp.

1311{
1312
1313 // ReturnInst itself should always not be a pointer type
1314 assert(!SVFUtil::isa<PointerType>(inst.getType()));
1315
1317 outs() << "process return " << LLVMUtil::dumpValue(&inst) << "\n");
1318
1320
1321 if(Value* src = inst.getReturnValue())
1322 {
1323 const FunObjVar *F = llvmModuleSet()->getFunObjVar(inst.getParent()->getParent());
1324
1326 NodeID vnS = getValueNode(src);
1327 const ICFGNode* icfgNode = llvmModuleSet()->getICFGNode(&inst);
1328 //vnS may be null if src is a null ptr
1329 addPhiStmt(rnF,vnS,icfgNode);
1330 }
1331}
void addAggregateReturnStores(ReturnInst &inst)

◆ visitSelectInst()

void SVFIRBuilder::visitSelectInst ( SelectInst &  inst)

Visit select instructions

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

Definition at line 1225 of file SVFIRBuilder.cpp.

1226{
1227
1229 outs() << "process select " << LLVMUtil::dumpValue(&inst) << "\n");
1230
1231 NodeID dst = getValueNode(&inst);
1232 NodeID src1 = getValueNode(inst.getTrueValue());
1233 NodeID src2 = getValueNode(inst.getFalseValue());
1234 NodeID cond = getValueNode(inst.getCondition());
1236 addSelectStmt(dst,src1,src2, cond);
1237}

◆ visitShuffleVectorInst()

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

Definition at line 276 of file SVFIRBuilder.h.

277 {
279 }

◆ visitStoreInst()

void SVFIRBuilder::visitStoreInst ( StoreInst &  inst)

Visit store instructions

Definition at line 1104 of file SVFIRBuilder.cpp.

1105{
1106 // StoreInst itself should always not be a pointer type
1107 assert(!SVFUtil::isa<PointerType>(inst.getType()));
1108
1110 outs() << "process store " << LLVMUtil::dumpValue(&inst) << "\n");
1111
1112 NodeID dst = getValueNode(inst.getPointerOperand());
1113 const Type* storedTy = inst.getValueOperand()->getType();
1114 if (NodeID fieldZero = getDirectAccessFieldZeroValVar(inst.getPointerOperand(), storedTy))
1115 dst = fieldZero;
1116
1117 NodeID src = getValueNode(inst.getValueOperand());
1118
1119 addStoreEdge(src, dst);
1120
1121}

◆ visitSwitchInst()

void SVFIRBuilder::visitSwitchInst ( SwitchInst &  inst)

Preserve LLVM switch destinations and case values in BranchStmt.

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

set conditional svf var

Definition at line 1926 of file SVFIRBuilder.cpp.

1927{
1928 NodeID brinst = getValueNode(&inst);
1929 NodeID cond = getValueNode(inst.getCondition());
1930
1932 std::vector<const Instruction*> nextInsts;
1933 // Resolve each LLVM successor to its first non-intrinsic instruction.
1935
1936 // Record default first and -1 is the getSuccessorCondValue(default iter, usually 0)
1937 successors.emplace_back(llvmModuleSet()->getICFGNode(nextInsts.front()), -1);
1938
1939 // switch (x) {
1940 // case 1:
1941 // case 2: work(); break;
1942 // default: other(); break;
1943 // }
1944 // Both cases jump to the same call instruction, work(). Keep two records
1945 // for that call's ICFG node: one with case value 1, one with case value 2.
1946 // findCaseDest() returns nullptr for a block shared by multiple cases.
1947 // Read the value from each case, not from its destination block.
1948 for (const auto& switchCase : inst.cases())
1949 {
1950 const ConstantInt* condVal = switchCase.getCaseValue();
1951 s64_t val = -1;
1952 if (condVal->getBitWidth() <= 64)
1954 // In the example, both cases resolve to the same call to work().
1955 const Instruction* succInst = nextInsts[switchCase.getSuccessorIndex()];
1956 const ICFGNode* icfgNode = llvmModuleSet()->getICFGNode(succInst);
1957 successors.push_back(std::make_pair(icfgNode, val));
1958 }
1959 addBranchStmt(brinst, cond, successors);
1961 for (auto& edge : llvmModuleSet()->getICFGNode(&inst)->getOutEdges())
1962 {
1963 if (IntraCFGEdge* intraEdge = SVFUtil::dyn_cast<IntraCFGEdge>(edge))
1964 {
1965 intraEdge->setConditionVar(pag->getGNode(cond));
1966 }
1967 }
1968}
signed long long s64_t
Definition GeneralType.h:70

◆ visitUnaryOperator()

void SVFIRBuilder::visitUnaryOperator ( UnaryOperator &  inst)

Visit Unary Operator

Definition at line 1196 of file SVFIRBuilder.cpp.

1197{
1198 NodeID dst = getValueNode(&inst);
1199 assert(inst.getNumOperands() == 1 && "not one operand for Unary instruction?");
1200 Value* opnd = inst.getOperand(0);
1201 NodeID src = getValueNode(opnd);
1202 u32_t opcode = inst.getOpcode();
1203 addUnaryOPEdge(src, dst, opcode);
1204}
void addUnaryOPEdge(NodeID src, NodeID dst, u32_t opcode)
Add Unary edge.

◆ visitUnreachableInst()

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

Definition at line 289 of file SVFIRBuilder.h.

290 {
291 }

◆ 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 1976 of file SVFIRBuilder.cpp.

1977{
1978 NodeID dst = getValueNode(&inst);
1979 Value* opnd = inst.getPointerOperand();
1980 NodeID src = getValueNode(opnd);
1981 addCopyEdge(src, dst, CopyStmt::COPYVAL);
1982}

◆ visitVACopyInst()

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

Definition at line 258 of file SVFIRBuilder.h.

258{}

◆ visitVAEndInst()

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

Definition at line 259 of file SVFIRBuilder.h.

259{}

◆ visitVAStartInst()

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

Definition at line 260 of file SVFIRBuilder.h.

260{}

Friends And Related Symbol Documentation

◆ GraphDBSVFIRBuilder

friend class GraphDBSVFIRBuilder
friend

Definition at line 51 of file SVFIRBuilder.h.

Member Data Documentation

◆ aggregateCallArgs

Map<const CallInst*, std::map<AggregateField, NodeID> > SVF::SVFIRBuilder::aggregateCallArgs
private

Slot addresses that each call to a modeled callee passes as output arguments, in field-path order, including calls with unused results. visitCallSite appends them after the call's ordinary arguments.

Definition at line 135 of file SVFIRBuilder.h.

◆ aggregateFieldNodes

Map<AggregateFieldKey, NodeID> SVF::SVFIRBuilder::aggregateFieldNodes
private

Reuse the same scalar SVFIR node for repeated requests for a field.

Definition at line 66 of file SVFIRBuilder.h.

◆ aggregateReturnParams

Map<const Function*, std::map<AggregateField, NodeID> > SVF::SVFIRBuilder::aggregateReturnParams
private

Output parameters of each modeled callee, in field-path order.

Carry a pointer field from a returned aggregate to its extraction. C example (Clang 21, x86-64 Linux, -O1; noinline preserves the call): struct Pair { int *first, *second; }; attribute((noinline)) struct Pair make(int *p, int *q) { return (struct Pair){p, q}; } int *first(int *p, int *q) { struct Pair a = make(p, q); return a.first; } Corresponding LLVM IR (names simplified, attributes omitted): define {ptr, ptr} @make(ptr p, ptr q) { r0 = insertvalue {ptr, ptr} poison, ptr p, 0 r1 = insertvalue {ptr, ptr} r0, ptr q, 1 ret {ptr, ptr} r1 } define ptr @first(ptr p, ptr q) { a = tail call {ptr, ptr} @make(ptr p, ptr q) x = extractvalue {ptr, ptr} a, 0 ret ptr x } Only field {0} is extracted. For this call, the field uses three distinct SVFIR nodes: obj: a pointer-sized DummyObjVar, called the return slot. This is synthetic storage, not the Pair object or an LLVM alloca. A: a DummyValVar pointing to obj, passed to make. V: a DummyValVar holding the pointer loaded from obj after the call; later uses read V without reloading obj. Each static callsite has its own obj/A/V for each demanded field. make also gets a synthetic output ArgValVar, named out_obj below. Using symbolic node names, the field transport is shown below; ordinary argument/return edges and whole-aggregate fallback edges are omitted: first's call: A = Addr(obj) make's entry: CallPE(A, out_obj) make's r0: F0 = Copy(p) make's r1: F1 = Copy(F0) make's return: Store(F1, out_obj) first's x: V = Load(A); x = Copy(V) insertvalue creates a new aggregate: r0 = {p, poison}, r1 = {p, q}. The second insertion preserves field {0}. F0 models (r0, {0}) and F1 models (r1, {0}); field {1} is not extracted here, so it needs no separate field node. The snapshot load precedes the extraction copy at the same continuation. aggregateReturnParams[make][{0}] holds out_obj. aggregateCallArgs[a][{0}] holds A, and aggregateFieldNodes[(a, {0})] holds V. obj, Addr(obj) and Load(A) are created before instructions are visited; V is loaded at x, the instruction after the call. All calls to make append their own A to match out_obj, even with unused results. More demanded fields follow field-path order. These additions affect only SVFIR; the LLVM signatures above do not change.

Definition at line 131 of file SVFIRBuilder.h.

◆ curBB

const SVFBasicBlock* SVF::SVFIRBuilder::curBB
private

Current basic block during SVFIR construction when visiting the module.

Definition at line 55 of file SVFIRBuilder.h.

◆ curVal

const Value* SVF::SVFIRBuilder::curVal
private

Current Value during SVFIR construction when visiting the module.

Definition at line 56 of file SVFIRBuilder.h.

◆ pag

SVFIR* SVF::SVFIRBuilder::pag
private

Definition at line 54 of file SVFIRBuilder.h.


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