LLVM 20.0.0git
|
Encapsulates all of the information needed to generate a stack protector check, and signals to isel when initialized that one needs to be generated. More...
#include "llvm/CodeGen/CodeGenCommonISel.h"
Public Member Functions | |
StackProtectorDescriptor ()=default | |
bool | shouldEmitStackProtector () const |
Returns true if all fields of the stack protector descriptor are initialized implying that we should/are ready to emit a stack protector. | |
bool | shouldEmitFunctionBasedCheckStackProtector () const |
void | initialize (const BasicBlock *BB, MachineBasicBlock *MBB, bool FunctionBasedInstrumentation) |
Initialize the stack protector descriptor structure for a new basic block. | |
void | resetPerBBState () |
Reset state that changes when we handle different basic blocks. | |
void | resetPerFunctionState () |
Reset state that only changes when we switch functions. | |
MachineBasicBlock * | getParentMBB () |
MachineBasicBlock * | getSuccessMBB () |
MachineBasicBlock * | getFailureMBB () |
Encapsulates all of the information needed to generate a stack protector check, and signals to isel when initialized that one needs to be generated.
NOTE The following is a high level documentation of SelectionDAG Stack Protector Generation. This is now also ported be shared with GlobalISel, but without any significant changes.
High Level Overview of ISel Stack Protector Generation:
Previously, the "stack protector" IR pass handled stack protector generation. This necessitated splitting basic blocks at the IR level to create the success/failure basic blocks in the tail of the basic block in question. As a result of this, calls that would have qualified for the sibling call optimization were no longer eligible for optimization since said calls were no longer right in the "tail position" (i.e. the immediate predecessor of a ReturnInst instruction).
Since the sibling call optimization causes the callee to reuse the caller's stack, if we could delay the generation of the stack protector check until later in CodeGen after the sibling call decision was made, we get both the tail call optimization and the stack protector check!
A few goals in solving this problem were:
The main problem that guided the present solution is that one can not solve this problem in an architecture independent manner at the IR level only. This is because:
To get around this problem:
Given the aforementioned constraints, the following solution was devised:
On platforms that do support ISel stack protector check generation:
a. Use the IR level stack protector pass to decide if a stack protector is required/which BB we insert the stack protector check in by reusing the logic already therein.
b. After we finish selecting the basic block, we produce the validation code with one of these techniques: 1) with a call to a guard check function 2) with inlined instrumentation
1) We insert a call to the check function before the terminator.
2) We first find a splice point in the parent basic block before the terminator and then splice the terminator of said basic block into the success basic block. Then we code-gen a new tail for the parent basic block consisting of the two loads, the comparison, and finally two branches to the success/failure basic blocks. We conclude by code-gening the failure basic block if we have not code-gened it already (all stack protector checks we generate in the same function, use the same failure basic block).
Definition at line 116 of file CodeGenCommonISel.h.
|
default |
|
inline |
Definition at line 172 of file CodeGenCommonISel.h.
Referenced by llvm::SelectionDAGBuilder::visitSPDescriptorParent().
|
inline |
Definition at line 170 of file CodeGenCommonISel.h.
|
inline |
Definition at line 171 of file CodeGenCommonISel.h.
Referenced by llvm::SelectionDAGBuilder::visitSPDescriptorParent().
|
inline |
Initialize the stack protector descriptor structure for a new basic block.
Definition at line 132 of file CodeGenCommonISel.h.
References assert(), MBB, and shouldEmitStackProtector().
|
inline |
Reset state that changes when we handle different basic blocks.
This currently includes:
Definition at line 154 of file CodeGenCommonISel.h.
|
inline |
Reset state that only changes when we switch functions.
This currently includes:
2.The guard variable since the guard variable we are checking against is always the same.
Definition at line 168 of file CodeGenCommonISel.h.
|
inline |
Definition at line 126 of file CodeGenCommonISel.h.
|
inline |
Returns true if all fields of the stack protector descriptor are initialized implying that we should/are ready to emit a stack protector.
Definition at line 122 of file CodeGenCommonISel.h.
Referenced by initialize().