When adjusting the function prologue for segmented stacks, only update the successor edges of the immediate predecessors of the original prologue.
I encountered a segmentation fault in LLVM while compiling the Rust core targeting armv7em with segmented stack enabled. Below is my attempt to fix it. I am not very certain about the correctness of my patch, because I do not fully understand the code.
Looking at the do-while loop
SmallPtrSet<MachineBasicBlock *, 8> BeforePrologueRegion;
SmallVector<MachineBasicBlock *, 2> WalkList;
WalkList.push_back(&PrologueMBB);
do {
MachineBasicBlock *CurMBB = WalkList.pop_back_val();
for (MachineBasicBlock *PredBB : CurMBB->predecessors()) {
if (BeforePrologueRegion.insert(PredBB).second)
WalkList.push_back(PredBB);
}
} while (!WalkList.empty());it seems BeforePrologueRegion contains non-immediate predecessors of PrologueMBB .
However, in the following while loop, ReplaceUsesOfBlockWith assumes that MBB is an immediate predecessor of PrologueMBB.
for (MachineBasicBlock *MBB : BeforePrologueRegion) {
// Make sure the LiveIns are still sorted and unique.
MBB->sortUniqueLiveIns();
// Replace the edges to PrologueMBB by edges to the sequences
// we are about to add.
MBB->ReplaceUsesOfBlockWith(&PrologueMBB, AddedBlocks[0]);
}The assumption comes from the function call chain
MBB->ReplaceUsesOfBlockWith(&PrologueMBB, AddedBlocks[0]); --> replaceSuccessor(Old, New); ----> Old->removePredecessor(this); ------> assert(I != Predecessors.end()); Predecessors.erase(I);
I ran into this problem when I was compiling Rust core in release mode targeting armv7em with segmented stack enabled. The Predecessors.erase(I); line led to a segmentation fault.
I fixed the problem by adding the if-continue statement. It still passed all of the tests.
I think this would be a bit clearer if rewritten as
i.e. the test and action are both MBB->thing(&PrologueMBB).