Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix a bug: 'getExitBB' of SVFFunction may get incorrect exit block. #1262

Merged
merged 12 commits into from
Dec 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions svf-llvm/include/SVF-LLVM/LLVMUtil.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,9 @@ inline bool isArgOfUncalledFunction (const Value* val)
}
//@}

/// Return true if the function has a return instruction
bool basicBlockHasRetInst(const BasicBlock* bb);

/// Return true if the function has a return instruction reachable from function
/// entry
bool functionDoesNotRet(const Function* fun);
Expand Down
11 changes: 11 additions & 0 deletions svf-llvm/lib/LLVMModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@ void LLVMModuleSet::initSVFFunction()

void LLVMModuleSet::initSVFBasicBlock(const Function* func)
{
SVFFunction *svfFun = getSVFFunction(func);
for (Function::const_iterator bit = func->begin(), ebit = func->end(); bit != ebit; ++bit)
{
const BasicBlock* bb = &*bit;
Expand All @@ -319,6 +320,16 @@ void LLVMModuleSet::initSVFBasicBlock(const Function* func)
const SVFBasicBlock* svf_pred_bb = getSVFBasicBlock(*pred_it);
svfbb->addPredBasicBlock(svf_pred_bb);
}

/// set exit block: exit basic block must have no successors and have a return instruction
if (svfbb->getSuccessors().empty())
{
if (LLVMUtil::basicBlockHasRetInst(bb))
{
svfFun->setExitBlock(svfbb);
}
}

for (BasicBlock::const_iterator iit = bb->begin(), eiit = bb->end(); iit != eiit; ++iit)
{
const Instruction* inst = &*iit;
Expand Down
22 changes: 17 additions & 5 deletions svf-llvm/lib/LLVMUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,24 @@ void LLVMUtil::getFunReachableBBs (const Function* fun, std::vector<const SVFBas
}
}

/**
* Return true if the basic block has a return instruction
*/
bool LLVMUtil::basicBlockHasRetInst(const BasicBlock* bb)
{
for (BasicBlock::const_iterator it = bb->begin(), eit = bb->end();
it != eit; ++it)
{
if(SVFUtil::isa<ReturnInst>(*it))
return true;
}
return false;
}

/*!
* Return true if the function has a return instruction reachable from function entry
*/
bool LLVMUtil::functionDoesNotRet (const Function* fun)
bool LLVMUtil::functionDoesNotRet(const Function* fun)
{
const SVFFunction* svffun = LLVMModuleSet::getLLVMModuleSet()->getSVFFunction(fun);
if (SVFUtil::isExtCall(svffun))
Expand All @@ -115,11 +129,9 @@ bool LLVMUtil::functionDoesNotRet (const Function* fun)
{
const BasicBlock* bb = bbVec.back();
bbVec.pop_back();
for (BasicBlock::const_iterator it = bb->begin(), eit = bb->end();
it != eit; ++it)
if (basicBlockHasRetInst(bb))
{
if(SVFUtil::isa<ReturnInst>(*it))
return false;
return false;
}

for (succ_const_iterator sit = succ_begin(bb), esit = succ_end(bb);
Expand Down
15 changes: 13 additions & 2 deletions svf/include/SVFIR/SVFValue.h
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,7 @@ class SVFFunction : public SVFValue
std::vector<const SVFBasicBlock*> allBBs; /// all BasicBlocks of this function
std::vector<const SVFArgument*> allArgs; /// all formal arguments of this function
std::vector<std::string> annotations; /// annotations of this function
SVFBasicBlock *exitBlock; /// a 'single' basic block having no successors and containing return instruction in a function

protected:
///@{ attributes to be set only through Module builders e.g., LLVMModule
Expand Down Expand Up @@ -412,20 +413,29 @@ class SVFFunction : public SVFValue
return allBBs.front();
}

/// Carefully! when you call getExitBB, you need ensure the function has return instruction
/// more refer to: https://github.com/SVF-tools/SVF/pull/1262
inline const SVFBasicBlock* getExitBB() const
{
assert(hasBasicBlock() && "function does not have any Basicblock, external function?");
return allBBs.back();
assert((!isNotRet && exitBlock) && "ensure the function has a single basic block containing a return instruction!");
return exitBlock;
}

void setExitBlock(SVFBasicBlock *bb);

inline const SVFBasicBlock* front() const
{
return getEntryBlock();
}

inline const SVFBasicBlock* back() const
{
return getExitBB();
assert(hasBasicBlock() && "function does not have any Basicblock, external function?");
/// Carefully! 'back' is just the last basic block of function,
/// but not necessarily a exit basic block
/// more refer to: https://github.com/SVF-tools/SVF/pull/1262
return allBBs.back();
}

inline const_iterator begin() const
Expand Down Expand Up @@ -520,6 +530,7 @@ class SVFBasicBlock : public SVFValue
friend class SVFIRWriter;
friend class SVFIRReader;
friend class SVFIRBuilder;
friend class SVFFunction;

public:
typedef std::vector<const SVFInstruction*>::const_iterator const_iterator;
Expand Down
14 changes: 10 additions & 4 deletions svf/lib/Graphs/ICFG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,11 @@ FunExitICFGNode::FunExitICFGNode(NodeID id, const SVFFunction* f)
// if function is implemented
if (f->begin() != f->end())
{
bb = f->getExitBB();
// ensure the enclosing function has exit basic block
if (!f->isNotRetFunction())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if (f->hasReturn)

Copy link
Contributor Author

@canliture canliture Dec 1, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry for late to commit. 😂 now Is it necessary to commit? I have committed to my forked repository

{
bb = f->getExitBB();
}
}
}

Expand Down Expand Up @@ -112,12 +116,14 @@ const std::string FunEntryICFGNode::toString() const

const std::string FunExitICFGNode::toString() const
{
const SVFFunction *fun = getFun();
std::string str;
std::stringstream rawstr(str);
rawstr << "FunExitICFGNode" << getId();
rawstr << " {fun: " << getFun()->getName();
if (isExtCall(getFun())==false)
rawstr << getFun()->getExitBB()->front()->getSourceLoc();
rawstr << " {fun: " << fun->getName();
// ensure the enclosing function has exit basic block
if (!isExtCall(fun) && !fun->isNotRetFunction())
rawstr << fun->getExitBB()->front()->getSourceLoc();
rawstr << "}";
for (const SVFStmt *stmt : getSVFStmts())
rawstr << "\n" << stmt->toString();
Expand Down
9 changes: 8 additions & 1 deletion svf/lib/SVFIR/SVFValue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,8 @@ SVFFunction::SVFFunction(const SVFType* ty, const SVFFunctionType* ft,
SVFLoopAndDomInfo* ld, std::vector<std::string> annos)
: SVFValue(ty, SVFValue::SVFFunc), isDecl(declare), intrinsic(intrinsic),
addrTaken(adt), isUncalled(false), isNotRet(false), varArg(varg),
funcType(ft), loopAndDom(ld), realDefFun(nullptr), annotations(std::move(annos))
funcType(ft), loopAndDom(ld), realDefFun(nullptr), annotations(std::move(annos)),
exitBlock(nullptr)
{
}

Expand Down Expand Up @@ -189,6 +190,12 @@ bool SVFFunction::isVarArg() const
return varArg;
}

void SVFFunction::setExitBlock(SVFBasicBlock *bb)
{
assert(!exitBlock && "have already set exit Basicblock!");
exitBlock = bb;
}

SVFBasicBlock::SVFBasicBlock(const SVFType* ty, const SVFFunction* f)
: SVFValue(ty, SVFValue::SVFBB), fun(f)
{
Expand Down
Loading