[PATCH] D76848: [CodeGen] Error when writing to reserved registers in inline asm

Victor Campos via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 26 07:33:43 PDT 2020


vhscampos created this revision.
Herald added subscribers: llvm-commits, danielkiss, hiraditya, kristof.beyls.
Herald added a project: LLVM.

No error or warning has been emitted when reserved registers were
written to in inline assembly. Therefore, writes to the program counter
or to the frame pointer, for instance, were permitted, which could have
led to undesirable behaviour.

Example:

  int foo() {
    register int a __asm__("r7"); // r7 = frame-pointer in M-class ARM
    __asm__ __volatile__("mov %0, r1" : "=r"(a) : : );
    return a;
  }

In contrast, GCC issues an error in the same scenario.

This patch detects writes to reserved registers in inline assembly and
emits an error in such case.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D76848

Files:
  llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
  llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
  llvm/test/CodeGen/Generic/inline-asm-reserved-registers.ll


Index: llvm/test/CodeGen/Generic/inline-asm-reserved-registers.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/Generic/inline-asm-reserved-registers.ll
@@ -0,0 +1,15 @@
+; RUN: not llc -mtriple thumbv6m-arm-none-eabi -frame-pointer=all %s 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR
+
+; CHECK-ERROR: error: write to reserved register 'R7'
+define void @test_framepointer_output(i32 %input) {
+entry:
+  %0 = call i32 asm sideeffect "mov $0, r1", "={r7},r"(i32 %input)
+  ret void
+}
+
+; CHECK-ERROR: error: write to reserved register 'R7'
+define void @test_framepointer_input(i32 %input) {
+entry:
+  %0 = call i32 asm sideeffect "mov $0, $1", "=r,{r7}"(i32 %input)
+  ret void
+}
Index: llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
===================================================================
--- llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
+++ llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
@@ -241,6 +241,13 @@
 
 bool AArch64RegisterInfo::isAsmClobberable(const MachineFunction &MF,
                                           unsigned PhysReg) const {
+  // X16/W16 is marked as reserved when Speculative Load Hardening is enabled
+  // to prevent it from being used in register allocation. However, it should
+  // still be clobberable in inline assembly as SLH is capable of handling such
+  // case by implementing a fallback.
+  if (MF.getFunction().hasFnAttribute(Attribute::SpeculativeLoadHardening) &&
+      (PhysReg == AArch64::X16 || PhysReg == AArch64::W16))
+    return true;
   return !isReservedReg(MF, PhysReg);
 }
 
Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
===================================================================
--- llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -8312,6 +8312,21 @@
             : OpInfo;
     GetRegistersForValue(DAG, getCurSDLoc(), OpInfo, RefOpInfo);
 
+    auto detectWriteToReservedRegister = [&]() {
+      const MachineFunction &MF = DAG.getMachineFunction();
+      const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
+      for (unsigned Reg : OpInfo.AssignedRegs.Regs) {
+        if (Register::isPhysicalRegister(Reg) &&
+            !TRI.isAsmClobberable(MF, Reg)) {
+          const char *RegName = TRI.getName(Reg);
+          emitInlineAsmError(CS, "write to reserved register '" +
+                                     Twine(RegName) + "'");
+          return true;
+        }
+      }
+      return false;
+    };
+
     switch (OpInfo.Type) {
     case InlineAsm::isOutput:
       if (OpInfo.ConstraintType == TargetLowering::C_Memory) {
@@ -8337,6 +8352,9 @@
           return;
         }
 
+        if (detectWriteToReservedRegister())
+          return;
+
         // Add information to the INLINEASM node to know that this register is
         // set.
         OpInfo.AssignedRegs.AddInlineAsmOperands(
@@ -8481,6 +8499,9 @@
         return;
       }
 
+      if (detectWriteToReservedRegister())
+        return;
+
       SDLoc dl = getCurSDLoc();
 
       OpInfo.AssignedRegs.getCopyToRegs(InOperandVal, DAG, dl,


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D76848.252843.patch
Type: text/x-patch
Size: 3173 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20200326/b5e00b44/attachment-0001.bin>


More information about the llvm-commits mailing list