[BOLT] Ensure remember and restore CFIs are in the same list (#144348)
In `addCFIInstruction`, we split the CFI information
between `CFIInstrMapType CIEFrameInstructions` and `CFIInstrMapType
FrameInstructions`. In some cases we can end up with the remember CFI in
`CIEFrameInstructions` and the restore CFI in `FrameInstructions`. This
patch adds a check to make sure we do not split remember and restore
states and fixes https://github.com/llvm/llvm-project/issues/133501.
diff --git a/bolt/include/bolt/Core/BinaryFunction.h b/bolt/include/bolt/Core/BinaryFunction.h
index ca8b786..ae58052 100644
--- a/bolt/include/bolt/Core/BinaryFunction.h
+++ b/bolt/include/bolt/Core/BinaryFunction.h
@@ -1663,7 +1663,11 @@
Offset = I->first;
}
assert(I->first == Offset && "CFI pointing to unknown instruction");
- if (I == Instructions.begin()) {
+ // When dealing with RememberState, we place this CFI in FrameInstructions.
+ // We want to ensure RememberState and RestoreState CFIs are in the same
+ // list in order to properly populate the StateStack.
+ if (I == Instructions.begin() &&
+ Inst.getOperation() != MCCFIInstruction::OpRememberState) {
CIEFrameInstructions.emplace_back(std::forward<MCCFIInstruction>(Inst));
return;
}
diff --git a/bolt/test/AArch64/cfi-state-list.test b/bolt/test/AArch64/cfi-state-list.test
new file mode 100644
index 0000000..2109f91
--- /dev/null
+++ b/bolt/test/AArch64/cfi-state-list.test
@@ -0,0 +1,34 @@
+// This test checks that BOLT does not split remember and restore CFI states
+// into different lists, which would cause an assertion failure.
+
+# RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown %s -o %t.o
+# RUN: %clang %cflags %t.o -o %t.exe -Wl,-q
+# RUN: llvm-bolt %t.exe -o %t.bolt 2>&1 | FileCheck %s
+
+# CHECK: BOLT-INFO: Starting stub-insertion pass
+
+.text
+.global main
+.type main, %function
+
+main:
+.cfi_startproc
+.cfi_remember_state
+ mov w0, wzr
+ b.ne .L1
+.L0:
+ mov w0, wzr
+.L1:
+ cmp x0, #0
+ b.lt .L2
+.L2:
+ nop
+ .cfi_restore_state
+ mov x8, xzr
+ b.ls .L0
+ ret
+.cfi_endproc
+ .size main, .-main
+
+## Force relocation mode.
+ .reloc 0, R_AARCH64_NONE