nickdesaulniers updated this revision to Diff 340932.
nickdesaulniers added a comment.

- rebase on D101387 <https://reviews.llvm.org/D101387>


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D100919/new/

https://reviews.llvm.org/D100919

Files:
  clang/include/clang/Basic/CodeGenOptions.h
  clang/lib/CodeGen/BackendUtil.cpp
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/test/Driver/stack-protector-guard.c
  llvm/include/llvm/Target/TargetOptions.h
  llvm/lib/CodeGen/CommandFlags.cpp
  llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
  llvm/test/CodeGen/AArch64/stack-guard-sysreg.ll

Index: llvm/test/CodeGen/AArch64/stack-guard-sysreg.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/AArch64/stack-guard-sysreg.ll
@@ -0,0 +1,73 @@
+; RUN: llc %s --stack-protector-guard=sysreg \
+; RUN:   --stack-protector-guard-reg=sp_el0 \
+; RUN:   --stack-protector-guard-offset=0 -o - | \
+; RUN: FileCheck --check-prefix=CHECK --check-prefix=CHECK-NO-OFFSET %s
+; RUN: llc %s --stack-protector-guard=sysreg \
+; RUN:   --stack-protector-guard-reg=sp_el0 \
+; RUN:   --stack-protector-guard-offset=8 -o - | \
+; RUN: FileCheck --check-prefix=CHECK --check-prefix=CHECK-POSITIVE-OFFSET %s
+; RUN: llc %s --stack-protector-guard=sysreg \
+; RUN:   --stack-protector-guard-reg=sp_el0 \
+; RUN:   --stack-protector-guard-offset=-8 -o - | \
+; RUN: FileCheck --check-prefix=CHECK --check-prefix=CHECK-NEGATIVE-OFFSET %s
+; RUN: llc %s --stack-protector-guard=sysreg \
+; RUN:   --stack-protector-guard-reg=sp_el0 \
+; RUN:   --stack-protector-guard-offset=1 -o - | \
+; RUN: FileCheck --check-prefix=CHECK --check-prefix=CHECK-NPOT-OFFSET %s
+; RUN: llc %s --stack-protector-guard=sysreg \
+; RUN:   --stack-protector-guard-reg=sp_el0 \
+; RUN:   --stack-protector-guard-offset=-1 -o - | \
+; RUN: FileCheck --check-prefix=CHECK --check-prefix=CHECK-NPOT-NEG-OFFSET %s
+
+target triple = "aarch64-unknown-linux-gnu"
+
+; Verify that we `mrs` from `SP_EL0` twice, rather than load from
+; __stack_chk_guard.
+define dso_local void @foo(i64 %t) local_unnamed_addr #0 {
+; CHECK-LABEL:   foo:
+; CHECK:         // %bb.0: // %entry
+; CHECK-NEXT:    stp x29, x30, [sp, #-16]! // 16-byte Folded Spill
+; CHECK-NEXT:    mov x29, sp
+; CHECK-NEXT:    sub sp, sp, #16 // =16
+; CHECK-NEXT:    .cfi_def_cfa w29, 16
+; CHECK-NEXT:    .cfi_offset w30, -8
+; CHECK-NEXT:    .cfi_offset w29, -16
+; CHECK-NEXT:    mrs x8, SP_EL0
+; CHECK-NO-OFFSET:       ldr x8, [x8]
+; CHECK-POSITIVE-OFFSET: ldr x8, [x8, #8]
+; CHECK-NEGATIVE-OFFSET: ldr x8, [x8, #-8]
+; CHECK-NPOT-OFFSET:     ldur x8, [x8, #1]
+; CHECK-NPOT-NEG-OFFSET: ldur x8, [x8, #-1]
+; CHECK-NEXT:    lsl x9, x0, #2
+; CHECK-NEXT:    add x9, x9, #15 // =15
+; CHECK-NEXT:    and x9, x9, #0xfffffffffffffff0
+; CHECK-NEXT:    stur x8, [x29, #-8]
+; CHECK-NEXT:    mov x8, sp
+; CHECK-NEXT:    sub x0, x8, x9
+; CHECK-NEXT:    mov sp, x0
+; CHECK-NEXT:    bl baz
+; CHECK-NEXT:    ldur x8, [x29, #-8]
+; CHECK-NEXT:    mrs x9, SP_EL0
+; CHECK-NO-OFFSET:       ldr x9, [x9]
+; CHECK-POSITIVE-OFFSET: ldr x9, [x9, #8]
+; CHECK-NEGATIVE-OFFSET: ldr x9, [x9, #-8]
+; CHECK-NPOT-OFFSET:     ldur x9, [x9, #1]
+; CHECK-NPOT-NEG-OFFSET: ldur x9, [x9, #-1]
+; CHECK-NEXT:    cmp x9, x8
+; CHECK-NEXT:    b.ne .LBB0_2
+; CHECK-NEXT:  // %bb.1: // %entry
+; CHECK-NEXT:    mov sp, x29
+; CHECK-NEXT:    ldp x29, x30, [sp], #16 // 16-byte Folded Reload
+; CHECK-NEXT:    ret
+; CHECK-NEXT:  .LBB0_2: // %entry
+; CHECK-NEXT:    bl __stack_chk_fail
+; CHECK-NOT: __stack_chk_guard
+entry:
+  %vla = alloca i32, i64 %t, align 4
+  call void @baz(i32* nonnull %vla)
+  ret void
+}
+
+declare dso_local void @baz(i32*) local_unnamed_addr
+
+attributes #0 = { sspstrong }
Index: llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
===================================================================
--- llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
+++ llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
@@ -1901,6 +1901,30 @@
   }
 
   Register Reg = MI.getOperand(0).getReg();
+  if (MI.getOpcode() == AArch64::LOAD_STACK_GUARD) {
+    TargetOptions Options = MI.getParent()->getParent()->getTarget().Options;
+    if (Options.StackProtectorGuard == StackProtectorGuards::SysReg) {
+      const AArch64SysReg::SysReg *SrcReg =
+          AArch64SysReg::lookupSysRegByName(Options.StackProtectorGuardReg);
+      assert(SrcReg && "Unable to encode SysReg");
+      BuildMI(MBB, MI, DL, get(AArch64::MRS))
+          .addReg(Reg, RegState::Define)
+          .addImm(SrcReg->Encoding);
+      if (Options.StackProtectorGuardOffset % 8 == 0)
+        BuildMI(MBB, MI, DL, get(AArch64::LDRXui))
+            .addReg(Reg, getKillRegState(false))
+            .addReg(Reg, RegState::Define)
+            .addImm(Options.StackProtectorGuardOffset >> 3);
+      else
+        BuildMI(MBB, MI, DL, get(AArch64::LDURXi))
+            .addReg(Reg, getKillRegState(false))
+            .addReg(Reg, RegState::Define)
+            .addImm(Options.StackProtectorGuardOffset);
+      MBB.erase(MI);
+      return true;
+    }
+  }
+
   const GlobalValue *GV =
       cast<GlobalValue>((*MI.memoperands_begin())->getValue());
   const TargetMachine &TM = MBB.getParent()->getTarget();
Index: llvm/lib/CodeGen/CommandFlags.cpp
===================================================================
--- llvm/lib/CodeGen/CommandFlags.cpp
+++ llvm/lib/CodeGen/CommandFlags.cpp
@@ -503,6 +503,8 @@
     return StackProtectorGuards::TLS;
   if (getStackProtectorGuard() == "global")
     return StackProtectorGuards::Global;
+  if (getStackProtectorGuard() == "sysreg")
+    return StackProtectorGuards::SysReg;
   if (getStackProtectorGuard() != "none") {
     ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr =
         MemoryBuffer::getFile(getStackProtectorGuard());
Index: llvm/include/llvm/Target/TargetOptions.h
===================================================================
--- llvm/include/llvm/Target/TargetOptions.h
+++ llvm/include/llvm/Target/TargetOptions.h
@@ -73,11 +73,7 @@
     None    // Do not use Basic Block Sections.
   };
 
-  enum class StackProtectorGuards {
-    None,
-    TLS,
-    Global
-  };
+  enum class StackProtectorGuards { None, TLS, Global, SysReg };
 
   enum class EABI {
     Unknown,
@@ -334,7 +330,7 @@
     /// Stack protector guard offset to use.
     int StackProtectorGuardOffset = INT_MAX;
 
-    /// Stack protector guard mode to use, e.g. tls, global.
+    /// Stack protector guard mode to use, e.g. tls, global, sysreg.
     StackProtectorGuards StackProtectorGuard =
                                          StackProtectorGuards::None;
 
Index: clang/test/Driver/stack-protector-guard.c
===================================================================
--- clang/test/Driver/stack-protector-guard.c
+++ clang/test/Driver/stack-protector-guard.c
@@ -23,7 +23,7 @@
 // RUN:   FileCheck -check-prefix=INVALID-ARCH2 %s
 // INVALID-ARCH2: unsupported option '-mstack-protector-guard-reg=fs' for target
 
-// RUN: not %clang -target aarch64-linux-gnu -mstack-protector-guard-offset=10 %s 2>&1 | \
+// RUN: not %clang -target arm-linux-gnueabi -mstack-protector-guard-offset=10 %s 2>&1 | \
 // RUN:   FileCheck -check-prefix=INVALID-ARCH3 %s
 // INVALID-ARCH3: unsupported option '-mstack-protector-guard-offset=10' for target
 
@@ -41,3 +41,19 @@
 // RUN:   FileCheck -check-prefix=CHECK-OFFSET %s
 
 // CHECK-OFFSET: "-cc1" {{.*}}"-mstack-protector-guard-offset=30"
+
+// RUN: %clang -### -target aarch64-linux-gnu -mstack-protector-guard=sysreg \
+// RUN:   -mstack-protector-guard-reg=sp_el0 \
+// RUN:   -mstack-protector-guard-offset=0 %s 2>&1 | \
+// RUN: FileCheck -check-prefix=CHECK-AARCH64 %s
+// RUN: %clang -### -target aarch64-linux-gnu \
+// RUN:   -mstack-protector-guard=tls %s 2>&1 | \
+// RUN:   FileCheck -check-prefix=INVALID-VALUE-AARCH64 %s
+// RUN: %clang -### -target aarch64-linux-gnu -mstack-protector-guard=sysreg \
+// RUN:   -mstack-protector-guard-reg=foo \
+// RUN:   -mstack-protector-guard-offset=0 %s 2>&1 | \
+// RUN: FileCheck -check-prefix=INVALID-REG-AARCH64 %s
+
+// CHECK-AARCH64: "-cc1" {{.*}}"-mstack-protector-guard=sysreg" "-mstack-protector-guard-offset=0" "-mstack-protector-guard-reg=sp_el0"
+// INVALID-VALUE-AARCH64: error: invalid value 'tls' in 'mstack-protector-guard=', valid arguments to '-mstack-protector-guard=' are:sysreg global
+// INVALID-REG-AARCH64: error: invalid value 'foo' in 'mstack-protector-guard-reg='
Index: clang/lib/Driver/ToolChains/Clang.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -3102,18 +3102,22 @@
     }
   }
 
-  // First support "tls" and "global" for X86 target.
-  // TODO: Support "sysreg" for AArch64.
   const std::string &TripleStr = EffectiveTriple.getTriple();
   if (Arg *A = Args.getLastArg(options::OPT_mstack_protector_guard_EQ)) {
     StringRef Value = A->getValue();
     if (!EffectiveTriple.isX86() && !EffectiveTriple.isAArch64())
       D.Diag(diag::err_drv_unsupported_opt_for_target)
           << A->getAsString(Args) << TripleStr;
-    if (Value != "tls" && Value != "global") {
+    if (EffectiveTriple.isX86() && Value != "tls" && Value != "global") {
       D.Diag(diag::err_drv_invalid_value_with_suggestion)
-      << A->getOption().getName() << Value
-      << "valid arguments to '-mstack-protector-guard=' are:tls global";
+          << A->getOption().getName() << Value
+          << "valid arguments to '-mstack-protector-guard=' are:tls global";
+      return;
+    }
+    if (EffectiveTriple.isAArch64() && Value != "sysreg" && Value != "global") {
+      D.Diag(diag::err_drv_invalid_value_with_suggestion)
+          << A->getOption().getName() << Value
+          << "valid arguments to '-mstack-protector-guard=' are:sysreg global";
       return;
     }
     A->render(Args, CmdArgs);
@@ -3121,7 +3125,7 @@
 
   if (Arg *A = Args.getLastArg(options::OPT_mstack_protector_guard_offset_EQ)) {
     StringRef Value = A->getValue();
-    if (!EffectiveTriple.isX86())
+    if (!EffectiveTriple.isX86() && !EffectiveTriple.isAArch64())
       D.Diag(diag::err_drv_unsupported_opt_for_target)
           << A->getAsString(Args) << TripleStr;
     int Offset;
@@ -3134,7 +3138,7 @@
 
   if (Arg *A = Args.getLastArg(options::OPT_mstack_protector_guard_reg_EQ)) {
     StringRef Value = A->getValue();
-    if (!EffectiveTriple.isX86())
+    if (!EffectiveTriple.isX86() && !EffectiveTriple.isAArch64())
       D.Diag(diag::err_drv_unsupported_opt_for_target)
           << A->getAsString(Args) << TripleStr;
     if (EffectiveTriple.isX86() && (Value != "fs" && Value != "gs")) {
@@ -3143,6 +3147,10 @@
       << "for X86, valid arguments to '-mstack-protector-guard-reg=' are:fs gs";
       return;
     }
+    if (EffectiveTriple.isAArch64() && Value != "sp_el0") {
+      D.Diag(diag::err_drv_invalid_value) << A->getOption().getName() << Value;
+      return;
+    }
     A->render(Args, CmdArgs);
   }
 }
Index: clang/lib/CodeGen/BackendUtil.cpp
===================================================================
--- clang/lib/CodeGen/BackendUtil.cpp
+++ clang/lib/CodeGen/BackendUtil.cpp
@@ -555,10 +555,11 @@
   Options.UniqueBasicBlockSectionNames =
       CodeGenOpts.UniqueBasicBlockSectionNames;
   Options.StackProtectorGuard =
-      llvm::StringSwitch<llvm::StackProtectorGuards>(CodeGenOpts
-          .StackProtectorGuard)
+      llvm::StringSwitch<llvm::StackProtectorGuards>(
+          CodeGenOpts.StackProtectorGuard)
           .Case("tls", llvm::StackProtectorGuards::TLS)
           .Case("global", llvm::StackProtectorGuards::Global)
+          .Case("sysreg", llvm::StackProtectorGuards::SysReg)
           .Default(llvm::StackProtectorGuards::None);
   Options.StackProtectorGuardOffset = CodeGenOpts.StackProtectorGuardOffset;
   Options.StackProtectorGuardReg = CodeGenOpts.StackProtectorGuardReg;
Index: clang/include/clang/Basic/CodeGenOptions.h
===================================================================
--- clang/include/clang/Basic/CodeGenOptions.h
+++ clang/include/clang/Basic/CodeGenOptions.h
@@ -382,6 +382,7 @@
 
   /// The TLS base register when StackProtectorGuard is "tls".
   /// On x86 this can be "fs" or "gs".
+  /// On AArch64 this can be any value of llvm::AArch64SysReg::SysReg.
   std::string StackProtectorGuardReg;
 
   /// Path to blocklist file specifying which objects
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to