-
Notifications
You must be signed in to change notification settings - Fork 436
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
Conversation
maybe multi exit blocks leads to assert crashes |
Could you help fix this? |
Yes, I currently work on this. |
…and connect all exit basic blocks to it.
Hi @canliture , which LLVM version are you using to compile this case? |
svf/include/SVFIR/SVFValue.h
Outdated
@@ -320,6 +320,15 @@ 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 *entryBlock; /// entry BasicBlock of this function |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we don't need an entryBlock because it is always the first block in allBBs. This is consistent with LLVM's API called getEntryBlock(), which simply returns the front of its basic blocks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for your review. Yeah, here is redundant.
svf-llvm/lib/LLVMModule.cpp
Outdated
} | ||
if (svfbb->getSuccessors().empty()) | ||
{ | ||
svfFun->setExitBlock(svfbb); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should consider the unreachable blocks introduced by instructions such as exit(0). These blocks are not function exit blocks and cannot be connected to the unique exit block. A valid function exit should end with a return instruction.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To my knowledge, each llvm function can only have one return instruction. This means there should be only one function exit block? In that way, no extra unique function exit block is needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, we do not need an extra unique exit block theoretically
.
I would like to improve robustness of SVF: when someone generate a valid
bitcode file like above, we should handle it correctly.
And I have a question, why my first pr can't pass the testcases. I guess the following assert leads to fail to pass the testcase (maybe multi exit basic block
)
inline void setExitBlock(SVFBasicBlock *bb)
{
assert(!exitBlock && "function already has a exit Basicblock.");
exitBlock = bb;
}
Because I have no testcases, so I can only guess the reason...
I use opt command of llvm 13
|
Thank you for your time. That's a good catch! It is not rigorous to return the last block as the exit block. It seems that some cases fail the CI because of no return instructions residing in the function (e.g., https://github.com/SVF-tools/Test-Suite/blob/ac3865cafc6f5ab3af86e5e923aa4f1462704583/test_cases_bc/basic_cpp_tests/deque-1.cpp.bc#L981). |
Confirming that all 27 failed cases are caused by the Assertion `exitBlock && "have not yet set exit Basicblock?"'. This happens when analyzing the following functions: define linkonce_odr hidden void @__clang_call_terminate(i8* %0) #6 comdat { I think there should be no exit BBs for this function. Also, there should be no return edge from the callee back to the caller. Therefore, I suppose that the assertion in getExitBB() for checking null for exitBB can be removed. |
Need to revise the assert to be: assert((function.hasReturn() && exitBlock) && "have not yet set exit Basicblock?"); |
…e function must have return instruction
svf-llvm/lib/LLVMModule.cpp
Outdated
@@ -319,6 +320,17 @@ void LLVMModuleSet::initSVFBasicBlock(const Function* func) | |||
const SVFBasicBlock* svf_pred_bb = getSVFBasicBlock(*pred_it); | |||
svfbb->addPredBasicBlock(svf_pred_bb); | |||
} | |||
|
|||
// set exit block | |||
if (svfbb->getSuccessors().empty() && !bb->getInstList().empty()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you sure this will be the exit bb? Better to add assertions in your code to make it more robust.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for review.
Yeah, an exit basic block is a 'single' basic block in a function:
- having no successors
- containing return instruction in a function, and
- ret instruction is not neccessarily the last instruction in the basic block
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks to me the crests are failed. Please help fix them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks to me the crests are failed. Please help fix them.
Yes, I have fixed all the test failures.
…nction has ret instruction
Codecov Report
Additional details and impacted files@@ Coverage Diff @@
## master #1262 +/- ##
=======================================
Coverage 64.50% 64.51%
=======================================
Files 223 223
Lines 23767 23781 +14
=======================================
+ Hits 15331 15342 +11
- Misses 8436 8439 +3
|
I think maybe there are some potential crashes of all callers of getExitBB(). But we have guard assert in getExitBB(), these crashes may be left for more real projects test, but currently, It's very nice.😄 |
svf-llvm/lib/LLVMModule.cpp
Outdated
/// set exit block | ||
if (svfbb->getSuccessors().empty()) | ||
{ | ||
if (LLVMUtil::basicBlockHasRet(bb)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
basicBlockHasRet=>basicBlockHasRetInst
svf-llvm/lib/LLVMModule.cpp
Outdated
{ | ||
if (LLVMUtil::basicBlockHasRet(bb)) | ||
{ | ||
// exit basic block must have no successors and have a return instruction |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
move this comment to lin324
svf/include/SVFIR/SVFValue.h
Outdated
@@ -458,6 +468,11 @@ class SVFFunction : public SVFValue | |||
return isNotRet; | |||
} | |||
|
|||
inline bool hasReturn() const |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can hasReturn() and isNotRetFunction() be merged into one? hasReturn() seems redundant to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could you keep hasReturn and remove the other one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for reviewing. Yeah, I think so.
@@ -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()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (f->hasReturn)
There was a problem hiding this comment.
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
reproduce the bug:
given the code in file bb.c:
compile and optimize the code with the following commands:
we get the final optimized bitcode file
bb.ll.ll
and get the code of test function:so, the
basic block vector
is:in the code above, we know:
for.end
basic block is the exit basic block of the function test, so I think we can't get exit basic block by simply retrievingthe last element
of thebasic block vector
by pulling request, I unify to set entry and exit basic block according to the definition of the entry/exit basic block of a function: no preds/succs.