[ARM] Implement setjmp BTI placement for PACBTI-M

This patch intends to guard indirect branches performed by longjmp
by inserting BTI instructions after calls to setjmp.

Calls with 'returns-twice' are lowered to a new pseudo-instruction
named t2CALL_BTI that is later expanded to a bundle of {tBL,t2BTI}.

This patch is part of a series that adds support for the PACBTI-M extension of
the Armv8.1-M architecture, as detailed here:

https://community.arm.com/arm-community-blogs/b/architectures-and-processors-blog/posts/armv8-1-m-pointer-authentication-and-branch-target-identification-extension

The PACBTI-M specification can be found in the Armv8-M Architecture Reference
Manual:

https://developer.arm.com/documentation/ddi0553/latest

The following people contributed to this patch:

- Alexandros Lamprineas
- Ties Stuij

Reviewed By: labrinea

Differential Revision: https://reviews.llvm.org/D112427

GitOrigin-RevId: 0fbb17458a01a6b388fc67661ffb92969503e977
diff --git a/docs/ClangCommandLineReference.rst b/docs/ClangCommandLineReference.rst
index 8d4ffa6..9780700 100644
--- a/docs/ClangCommandLineReference.rst
+++ b/docs/ClangCommandLineReference.rst
@@ -3260,6 +3260,11 @@
 
 Allow memory accesses to be unaligned (AArch32/AArch64 only)
 
+.. option:: -mno-bti-at-return-twice
+
+Do not add a BTI instruction after a setjmp or other return-twice construct (Arm
+only)
+
 Hexagon
 -------
 .. option:: -mieee-rnd-near
diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td
index 4e6dd20..7c257e4 100644
--- a/include/clang/Driver/Options.td
+++ b/include/clang/Driver/Options.td
@@ -3338,6 +3338,11 @@
 def mmark_bti_property : Flag<["-"], "mmark-bti-property">,
   Group<m_aarch64_Features_Group>,
   HelpText<"Add .note.gnu.property with BTI to assembly files (AArch64 only)">;
+def mno_bti_at_return_twice : Flag<["-"], "mno-bti-at-return-twice">,
+  Group<m_arm_Features_Group>,
+  HelpText<"Do not add a BTI instruction after a setjmp or other"
+           " return-twice construct (Arm only)">;
+
 foreach i = {1-31} in
   def ffixed_x#i : Flag<["-"], "ffixed-x"#i>, Group<m_Group>,
     HelpText<"Reserve the x"#i#" register (AArch64/RISC-V only)">;
diff --git a/lib/Driver/ToolChains/Arch/ARM.cpp b/lib/Driver/ToolChains/Arch/ARM.cpp
index 8d5c64d..e03bed0 100644
--- a/lib/Driver/ToolChains/Arch/ARM.cpp
+++ b/lib/Driver/ToolChains/Arch/ARM.cpp
@@ -875,6 +875,8 @@
     }
   }
 
+  if (Args.getLastArg(options::OPT_mno_bti_at_return_twice))
+    Features.push_back("+no-bti-at-return-twice");
 }
 
 std::string arm::getARMArch(StringRef Arch, const llvm::Triple &Triple) {
diff --git a/test/Driver/arm-bti-return-twice.c b/test/Driver/arm-bti-return-twice.c
new file mode 100644
index 0000000..c5cd385
--- /dev/null
+++ b/test/Driver/arm-bti-return-twice.c
@@ -0,0 +1,7 @@
+// RUN: %clang -target arm-arm-none-eabi -march=armv8-m.main -mbranch-protection=bti \
+// RUN: -mno-bti-at-return-twice -### %s 2>&1 | FileCheck %s --check-prefix=FEAT
+// RUN: %clang -target arm-arm-none-eabi -march=armv8-m.main -mbranch-protection=bti \
+// RUN: -### %s 2>&1 | FileCheck %s --check-prefix=NOFEAT
+
+// FEAT: "+no-bti-at-return-twice"
+// NOFEAT-NOT: "+no-bti-at-return-twice"