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).