-
Notifications
You must be signed in to change notification settings - Fork 13.1k
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
[BOLT] Lack of support for noreturn functions results in incorrect CFG generation. #115154
Comments
@kbeyls FYI |
@elhewaty, I believe you're working on a fix for this? |
Yes, I am working on this, Sorry for my late reply. I was thinking of using CallGraph class and CallGraphWalker class to build a pass that mark all no-return functions and cash the results in some Here are some thoughts: 2 - using the call graph and the call graph walker we can start traversing the call graph in any order(I guess), although the the traversal in the walker is topological, but it's suffecient enough for this purpose as it has a worklist that keeps track of the caller function if the callee is later marked as a no-return. 3 - As mentioned, the walker visits every node to ensure some property using the callback function. we can make the callback function a DFS traversal and go from it to see if all it's successors end with a no-return call and mark it as a no-return [I think using this will make updating the worklist unnecessary, as we will visit the leaves of the graph at the first node and cash the results of each node, so when we traverse a visited node from non-visited one the result was cached from before so the traversing stops]. if we go with this we will not need the walker -I guess- the code will be something like this:
So what do you think? |
Some thoughts:
I have also looked at this, and found we can get the BinaryFunction that is used in a call this way: const MCSymbol* TargetSymbol = BC.MIB->getTargetSymbol(Inst); // Inst is a call
BinaryFunction* TargetFunction = BC.SymbolToFunctionMap[TargetSymbol];
So are you saying, if a function only calls noreturn functions then itself is noreturn as well? If so, I agree. But for leaf functions we need to check that they have no returns (obviously), and I think they should end in an instruction that is a terminator. |
BOLT does not have support for noreturn functions. Because of this, BOLT assumes that the call to the noreturn function will return, and execution will continue, and adds the following BasicBlock to the successors list.
Take this example:
Compile it:
(I am compiling for aarch64, but the issue is the same regardless of the architecture).
Looking at the BasicBlocks:
BB containing the call to
my_error
The following BB, which is in the successors list:
This is after the call to
my_error
, but it should not be in the successors list.We can also look at the disassembly of the whole main function:
We can see that the BB starting at
a8c
is the target of a conditional jump, and it is placed under theBL
by the compiler on the assumption, thatmy_error
does not return.The text was updated successfully, but these errors were encountered: