Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PowerPC][ISelLowering] Support -mstack-protector-guard=tls #110928

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

keith-packard
Copy link
Contributor

Add support for using a thread-local variable with a specified offset for holding the stack guard canary value. This supports both 32- and 64- bit PowerPC targets.

This mirrors changes from #108942 but targeting PowerPC instead of RISCV. Because both of these PRs modify the same driver functions, this series is stack on top of the RISC-V one.

Copy link

github-actions bot commented Oct 2, 2024

Thank you for submitting a Pull Request (PR) to the LLVM Project!

This PR will be automatically labeled and the relevant teams will be notified.

If you wish to, you can add reviewers by using the "Reviewers" section on this page.

If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using @ followed by their GitHub username.

If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers.

If you have further questions, they may be answered by the LLVM GitHub User Guide.

You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums.

@llvmbot llvmbot added clang Clang issues not falling into any other category backend:RISC-V backend:PowerPC clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' labels Oct 2, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented Oct 2, 2024

@llvm/pr-subscribers-clang-driver
@llvm/pr-subscribers-backend-risc-v
@llvm/pr-subscribers-backend-powerpc

@llvm/pr-subscribers-clang

Author: Keith Packard (keith-packard)

Changes

Add support for using a thread-local variable with a specified offset for holding the stack guard canary value. This supports both 32- and 64- bit PowerPC targets.

This mirrors changes from #108942 but targeting PowerPC instead of RISCV. Because both of these PRs modify the same driver functions, this series is stack on top of the RISC-V one.


Patch is 25.26 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/110928.diff

10 Files Affected:

  • (modified) clang/lib/Driver/ToolChains/Clang.cpp (+39-3)
  • (modified) clang/test/CodeGen/stack-protector-guard.c (+16)
  • (modified) clang/test/Driver/stack-protector-guard.c (+73-3)
  • (modified) llvm/lib/Target/PowerPC/PPCISelLowering.cpp (+21)
  • (modified) llvm/lib/Target/PowerPC/PPCISelLowering.h (+1)
  • (modified) llvm/lib/Target/RISCV/RISCVISelLowering.cpp (+9-1)
  • (added) llvm/test/CodeGen/PowerPC/stack-guard-global.ll (+122)
  • (added) llvm/test/CodeGen/PowerPC/stack-guard-tls.ll (+114)
  • (added) llvm/test/CodeGen/RISCV/stack-guard-global.ll (+42)
  • (added) llvm/test/CodeGen/RISCV/stack-guard-tls.ll (+41)
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index b9987288d82d10..183820e5d7f187 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -3604,7 +3604,9 @@ static void RenderSSPOptions(const Driver &D, const ToolChain &TC,
   if (Arg *A = Args.getLastArg(options::OPT_mstack_protector_guard_EQ)) {
     StringRef Value = A->getValue();
     if (!EffectiveTriple.isX86() && !EffectiveTriple.isAArch64() &&
-        !EffectiveTriple.isARM() && !EffectiveTriple.isThumb())
+        !EffectiveTriple.isARM() && !EffectiveTriple.isThumb() &&
+        !EffectiveTriple.isRISCV() && !EffectiveTriple.isPPC64() &&
+        !EffectiveTriple.isPPC32())
       D.Diag(diag::err_drv_unsupported_opt_for_target)
           << A->getAsString(Args) << TripleStr;
     if ((EffectiveTriple.isX86() || EffectiveTriple.isARM() ||
@@ -3644,13 +3646,30 @@ static void RenderSSPOptions(const Driver &D, const ToolChain &TC,
           << A->getOption().getName() << Value << "sysreg global";
       return;
     }
+    if (EffectiveTriple.isRISCV() || EffectiveTriple.isPPC64() ||
+        EffectiveTriple.isPPC32()) {
+      if (Value != "tls" && Value != "global") {
+        D.Diag(diag::err_drv_invalid_value_with_suggestion)
+            << A->getOption().getName() << Value << "tls global";
+        return;
+      }
+      if (Value == "tls") {
+        if (!Args.hasArg(options::OPT_mstack_protector_guard_offset_EQ)) {
+          D.Diag(diag::err_drv_ssp_missing_offset_argument)
+              << A->getAsString(Args);
+          return;
+        }
+      }
+    }
     A->render(Args, CmdArgs);
   }
 
   if (Arg *A = Args.getLastArg(options::OPT_mstack_protector_guard_offset_EQ)) {
     StringRef Value = A->getValue();
     if (!EffectiveTriple.isX86() && !EffectiveTriple.isAArch64() &&
-        !EffectiveTriple.isARM() && !EffectiveTriple.isThumb())
+        !EffectiveTriple.isARM() && !EffectiveTriple.isThumb() &&
+        !EffectiveTriple.isRISCV() && !EffectiveTriple.isPPC64() &&
+        !EffectiveTriple.isPPC32())
       D.Diag(diag::err_drv_unsupported_opt_for_target)
           << A->getAsString(Args) << TripleStr;
     int Offset;
@@ -3669,7 +3688,9 @@ static void RenderSSPOptions(const Driver &D, const ToolChain &TC,
 
   if (Arg *A = Args.getLastArg(options::OPT_mstack_protector_guard_reg_EQ)) {
     StringRef Value = A->getValue();
-    if (!EffectiveTriple.isX86() && !EffectiveTriple.isAArch64())
+    if (!EffectiveTriple.isX86() && !EffectiveTriple.isAArch64() &&
+        !EffectiveTriple.isRISCV() && !EffectiveTriple.isPPC64() &&
+        !EffectiveTriple.isPPC32())
       D.Diag(diag::err_drv_unsupported_opt_for_target)
           << A->getAsString(Args) << TripleStr;
     if (EffectiveTriple.isX86() && (Value != "fs" && Value != "gs")) {
@@ -3681,6 +3702,21 @@ static void RenderSSPOptions(const Driver &D, const ToolChain &TC,
       D.Diag(diag::err_drv_invalid_value) << A->getOption().getName() << Value;
       return;
     }
+    if (EffectiveTriple.isRISCV() && Value != "tp") {
+      D.Diag(diag::err_drv_invalid_value_with_suggestion)
+          << A->getOption().getName() << Value << "tp";
+      return;
+    }
+    if (EffectiveTriple.isPPC64() && Value != "r13") {
+      D.Diag(diag::err_drv_invalid_value_with_suggestion)
+          << A->getOption().getName() << Value << "r13";
+      return;
+    }
+    if (EffectiveTriple.isPPC32() && Value != "r2") {
+      D.Diag(diag::err_drv_invalid_value_with_suggestion)
+          << A->getOption().getName() << Value << "r2";
+      return;
+    }
     A->render(Args, CmdArgs);
   }
 
diff --git a/clang/test/CodeGen/stack-protector-guard.c b/clang/test/CodeGen/stack-protector-guard.c
index 5839ab06033a15..51af6fb6311be8 100644
--- a/clang/test/CodeGen/stack-protector-guard.c
+++ b/clang/test/CodeGen/stack-protector-guard.c
@@ -9,6 +9,12 @@
 // RUN: %clang_cc1 -mstack-protector-guard=sysreg -triple aarch64-linux-gnu \
 // RUN:   -mstack-protector-guard-offset=1024 -mstack-protector-guard-reg=sp_el0 \
 // RUN:   -emit-llvm %s -o - | FileCheck %s --check-prefix=AARCH64
+// RUN: %clang_cc1 -mstack-protector-guard=tls -triple riscv64-unknown-elf \
+// RUN:   -mstack-protector-guard-offset=44 -mstack-protector-guard-reg=tp \
+// RUN:   -emit-llvm %s -o - | FileCheck %s --check-prefix=RISCV
+// RUN: %clang_cc1 -mstack-protector-guard=tls -triple powerpc64-unknown-elf \
+// RUN:   -mstack-protector-guard-offset=52 -mstack-protector-guard-reg=r13 \
+// RUN:   -emit-llvm %s -o - | FileCheck %s --check-prefix=POWERPC64
 void foo(int*);
 void bar(int x) {
   int baz[x];
@@ -23,3 +29,13 @@ void bar(int x) {
 // AARCH64: [[ATTR1]] = !{i32 1, !"stack-protector-guard", !"sysreg"}
 // AARCH64: [[ATTR2]] = !{i32 1, !"stack-protector-guard-reg", !"sp_el0"}
 // AARCH64: [[ATTR3]] = !{i32 1, !"stack-protector-guard-offset", i32 1024}
+
+// RISCV: !llvm.module.flags = !{{{.*}}[[ATTR1:![0-9]+]], [[ATTR2:![0-9]+]], [[ATTR3:![0-9]+]], [[ATTR4:![0-9]+]]}
+// RISCV: [[ATTR1]] = !{i32 1, !"stack-protector-guard", !"tls"}
+// RISCV: [[ATTR2]] = !{i32 1, !"stack-protector-guard-reg", !"tp"}
+// RISCV: [[ATTR3]] = !{i32 1, !"stack-protector-guard-offset", i32 44}
+
+// POWERPC64: !llvm.module.flags = !{{{.*}}[[ATTR1:![0-9]+]], [[ATTR2:![0-9]+]], [[ATTR3:![0-9]+]], [[ATTR4:![0-9]+]]}
+// POWERPC64: [[ATTR1]] = !{i32 1, !"stack-protector-guard", !"tls"}
+// POWERPC64: [[ATTR2]] = !{i32 1, !"stack-protector-guard-reg", !"r13"}
+// POWERPC64: [[ATTR3]] = !{i32 1, !"stack-protector-guard-offset", i32 52}
diff --git a/clang/test/Driver/stack-protector-guard.c b/clang/test/Driver/stack-protector-guard.c
index af4e11f8eaabce..666c83079e5191 100644
--- a/clang/test/Driver/stack-protector-guard.c
+++ b/clang/test/Driver/stack-protector-guard.c
@@ -17,15 +17,15 @@
 // RUN:   FileCheck -check-prefix=CHECK-SYM %s
 
 // Invalid arch
-// RUN: not %clang -target powerpc64le-linux-gnu -mstack-protector-guard=tls %s 2>&1 | \
+// RUN: not %clang -target mipsel-linux-gnu -mstack-protector-guard=tls %s 2>&1 | \
 // RUN:   FileCheck -check-prefix=INVALID-ARCH %s
 // INVALID-ARCH: unsupported option '-mstack-protector-guard=tls' for target
 
-// RUN: not %clang -target powerpc64le-linux-gnu -mstack-protector-guard-reg=fs %s 2>&1 | \
+// RUN: not %clang -target mipsel-linux-gnu -mstack-protector-guard-reg=fs %s 2>&1 | \
 // RUN:   FileCheck -check-prefix=INVALID-ARCH2 %s
 // INVALID-ARCH2: unsupported option '-mstack-protector-guard-reg=fs' for target
 
-// RUN: not %clang -target powerpc64le-linux-gnu -mstack-protector-guard-offset=10 %s 2>&1 | \
+// RUN: not %clang -target mipsel-linux-gnu -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
 
@@ -85,3 +85,73 @@
 // 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=', expected one of: sysreg global
 // INVALID-REG-AARCH64: error: invalid value 'foo' in 'mstack-protector-guard-reg='
+
+// RUN: %clang -### -target riscv64-unknown-elf -mstack-protector-guard=tls -mstack-protector-guard-offset=24 -mstack-protector-guard-reg=tp %s 2>&1 | \
+// RUN:   FileCheck -v -check-prefix=CHECK-TLS-RISCV %s
+// RUN: %clang -### -target riscv64-unknown-elf -mstack-protector-guard=global %s 2>&1 | \
+// RUN:   FileCheck -check-prefix=CHECK-GLOBAL %s
+
+// CHECK-TLS-RISCV: "-cc1" {{.*}}"-mstack-protector-guard=tls" "-mstack-protector-guard-offset=24" "-mstack-protector-guard-reg=tp"
+
+// RUN: not %clang -target riscv64-unknown-elf -mstack-protector-guard=tls %s 2>&1 | \
+// RUN:   FileCheck -check-prefix=MISSING-OFFSET %s
+
+// RUN: not %clang -target riscv64-unknown-elf -mstack-protector-guard=sysreg %s 2>&1 | \
+// RUN:   FileCheck -check-prefix=INVALID-VALUE2 %s
+
+// RUN: not %clang -target riscv64-unknown-elf -mstack-protector-guard=tls \
+// RUN: -mstack-protector-guard-offset=20 -mstack-protector-guard-reg=sp %s 2>&1 | \
+// RUN:   FileCheck -check-prefix=INVALID-REG-RISCV %s
+
+// INVALID-REG-RISCV: error: invalid value 'sp' in 'mstack-protector-guard-reg=', expected one of: tp
+
+// RUN: %clang -### -target powerpc64-unknown-elf -mstack-protector-guard=tls -mstack-protector-guard-offset=24 -mstack-protector-guard-reg=r13 %s 2>&1 | \
+// RUN:   FileCheck -v -check-prefix=CHECK-TLS-POWERPC64 %s
+// RUN: %clang -### -target powerpc64-unknown-linux-gnu -mstack-protector-guard=global %s 2>&1 | \
+// RUN:   FileCheck -check-prefix=CHECK-GLOBAL %s
+
+// RUN: not %clang -target powerpc64-unknown-linux-gnu -mstack-protector-guard=tls %s 2>&1 | \
+// RUN:   FileCheck -check-prefix=MISSING-OFFSET %s
+
+// RUN: not %clang -target powerpc64-unknown-elf -mstack-protector-guard=sysreg %s 2>&1 | \
+// RUN:   FileCheck -check-prefix=INVALID-VALUE2 %s
+
+// RUN: not %clang -target powerpc64-unknown-elf -mstack-protector-guard=tls \
+// RUN: -mstack-protector-guard-offset=20 -mstack-protector-guard-reg=r12 %s 2>&1 | \
+// RUN:   FileCheck -check-prefix=INVALID-REG-POWERPC64 %s
+
+// CHECK-TLS-POWERPC64: "-cc1" {{.*}}"-mstack-protector-guard=tls" "-mstack-protector-guard-offset=24" "-mstack-protector-guard-reg=r13"
+// INVALID-REG-POWERPC64: error: invalid value 'r12' in 'mstack-protector-guard-reg=', expected one of: r13
+
+// RUN: %clang -### -target powerpc64le-unknown-elf -mstack-protector-guard=tls -mstack-protector-guard-offset=24 -mstack-protector-guard-reg=r13 %s 2>&1 | \
+// RUN:   FileCheck -v -check-prefix=CHECK-TLS-POWERPC64 %s
+// RUN: %clang -### -target powerpc64le-unknown-elf -mstack-protector-guard=global %s 2>&1 | \
+// RUN:   FileCheck -check-prefix=CHECK-GLOBAL %s
+
+// RUN: not %clang -target powerpc64le-unknown-elf -mstack-protector-guard=tls %s 2>&1 | \
+// RUN:   FileCheck -check-prefix=MISSING-OFFSET %s
+
+// RUN: not %clang -target powerpc64le-unknown-elf -mstack-protector-guard=sysreg %s 2>&1 | \
+// RUN:   FileCheck -check-prefix=INVALID-VALUE2 %s
+
+// RUN: not %clang -target powerpc64le-unknown-elf -mstack-protector-guard=tls \
+// RUN: -mstack-protector-guard-offset=20 -mstack-protector-guard-reg=r12 %s 2>&1 | \
+// RUN:   FileCheck -check-prefix=INVALID-REG-POWERPC64 %s
+
+// RUN: %clang -### -target ppc32-unknown-elf -mstack-protector-guard=tls -mstack-protector-guard-offset=24 -mstack-protector-guard-reg=r2 %s 2>&1 | \
+// RUN:   FileCheck -v -check-prefix=CHECK-TLS-POWERPC32 %s
+// RUN: %clang -### -target ppc32-unknown-elf -mstack-protector-guard=global %s 2>&1 | \
+// RUN:   FileCheck -check-prefix=CHECK-GLOBAL %s
+
+// RUN: not %clang -target ppc32-unknown-elf -mstack-protector-guard=tls %s 2>&1 | \
+// RUN:   FileCheck -check-prefix=MISSING-OFFSET %s
+
+// RUN: not %clang -target ppc32-unknown-elf -mstack-protector-guard=sysreg %s 2>&1 | \
+// RUN:   FileCheck -check-prefix=INVALID-VALUE2 %s
+
+// RUN: not %clang -target ppc32-unknown-elf -mstack-protector-guard=tls \
+// RUN: -mstack-protector-guard-offset=20 -mstack-protector-guard-reg=r3 %s 2>&1 | \
+// RUN:   FileCheck -check-prefix=INVALID-REG-POWERPC32 %s
+
+// CHECK-TLS-POWERPC32: "-cc1" {{.*}}"-mstack-protector-guard=tls" "-mstack-protector-guard-offset=24" "-mstack-protector-guard-reg=r2"
+// INVALID-REG-POWERPC32: error: invalid value 'r3' in 'mstack-protector-guard-reg=', expected one of: r2
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index d9847a21489e63..455b62aed4c027 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -17913,6 +17913,27 @@ Value *PPCTargetLowering::getSDagStackGuard(const Module &M) const {
   return TargetLowering::getSDagStackGuard(M);
 }
 
+static Value *useTpOffset(IRBuilderBase &IRB, unsigned Offset) {
+  Module *M = IRB.GetInsertBlock()->getModule();
+  Function *ThreadPointerFunc =
+      Intrinsic::getDeclaration(M, Intrinsic::thread_pointer);
+  return IRB.CreateConstGEP1_32(IRB.getInt8Ty(),
+                                IRB.CreateCall(ThreadPointerFunc), Offset);
+}
+
+Value *PPCTargetLowering::getIRStackGuard(IRBuilderBase &IRB) const {
+  Module *M = IRB.GetInsertBlock()->getModule();
+
+  if (M->getStackProtectorGuard() == "tls") {
+    // Specially, some users may customize the base reg and offset.
+    int Offset = M->getStackProtectorGuardOffset();
+    return useTpOffset(IRB, Offset);
+  }
+
+  return TargetLowering::getIRStackGuard(IRB);
+}
+
+
 bool PPCTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT,
                                      bool ForCodeSize) const {
   if (!VT.isSimple() || !Subtarget.hasVSX())
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.h b/llvm/lib/Target/PowerPC/PPCISelLowering.h
index 8907c3c5a81c3c..8d993d467f2b00 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.h
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.h
@@ -1140,6 +1140,7 @@ namespace llvm {
     bool useLoadStackGuardNode() const override;
     void insertSSPDeclarations(Module &M) const override;
     Value *getSDagStackGuard(const Module &M) const override;
+    Value *getIRStackGuard(IRBuilderBase &IRB) const override;
 
     bool isFPImmLegal(const APFloat &Imm, EVT VT,
                       bool ForCodeSize) const override;
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 4f77bba2968988..a0f885695c2051 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -21304,7 +21304,7 @@ bool RISCVTargetLowering::preferScalarizeSplat(SDNode *N) const {
 }
 
 static Value *useTpOffset(IRBuilderBase &IRB, unsigned Offset) {
-  Module *M = IRB.GetInsertBlock()->getParent()->getParent();
+  Module *M = IRB.GetInsertBlock()->getModule();
   Function *ThreadPointerFunc =
       Intrinsic::getDeclaration(M, Intrinsic::thread_pointer);
   return IRB.CreateConstGEP1_32(IRB.getInt8Ty(),
@@ -21323,6 +21323,14 @@ Value *RISCVTargetLowering::getIRStackGuard(IRBuilderBase &IRB) const {
   if (Subtarget.isTargetAndroid())
     return useTpOffset(IRB, -0x18);
 
+  Module *M = IRB.GetInsertBlock()->getModule();
+
+  if (M->getStackProtectorGuard() == "tls") {
+    // Users must specify the offset explicitly
+    int Offset = M->getStackProtectorGuardOffset();
+    return useTpOffset(IRB, Offset);
+  }
+
   return TargetLowering::getIRStackGuard(IRB);
 }
 
diff --git a/llvm/test/CodeGen/PowerPC/stack-guard-global.ll b/llvm/test/CodeGen/PowerPC/stack-guard-global.ll
new file mode 100644
index 00000000000000..022a62a4b0918d
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/stack-guard-global.ll
@@ -0,0 +1,122 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc -mtriple=powerpc64 -verify-machineinstrs < %s \
+; RUN:     | FileCheck %s --check-prefixes=BE64
+; RUN: llc -mtriple=powerpc64le -verify-machineinstrs < %s \
+; RUN:     | FileCheck %s --check-prefixes=LE64
+; RUN: llc -mtriple=ppc32 -verify-machineinstrs < %s \
+; RUN:     | FileCheck %s --check-prefixes=LE32
+
+define void @foo(i64 %t) sspstrong nounwind {
+; BE64-LABEL: foo:
+; BE64:       # %bb.0:
+; BE64-NEXT:    mflr 0
+; BE64-NEXT:    std 31, -8(1)
+; BE64-NEXT:    stdu 1, -144(1)
+; BE64-NEXT:    mr 31, 1
+; BE64-NEXT:    std 0, 160(1)
+; BE64-NEXT:    std 30, 128(31) # 8-byte Folded Spill
+; BE64-NEXT:    addis 30, 2, __stack_chk_guard@toc@ha
+; BE64-NEXT:    sldi 3, 3, 2
+; BE64-NEXT:    ld 4, __stack_chk_guard@toc@l(30)
+; BE64-NEXT:    addi 3, 3, 15
+; BE64-NEXT:    rldicr 3, 3, 0, 59
+; BE64-NEXT:    neg 3, 3
+; BE64-NEXT:    std 4, 120(31)
+; BE64-NEXT:    addi 4, 31, 144
+; BE64-NEXT:    stdux 4, 1, 3
+; BE64-NEXT:    addi 3, 1, 112
+; BE64-NEXT:    bl baz
+; BE64-NEXT:    nop
+; BE64-NEXT:    ld 3, __stack_chk_guard@toc@l(30)
+; BE64-NEXT:    ld 4, 120(31)
+; BE64-NEXT:    cmpld 3, 4
+; BE64-NEXT:    bne 0, .LBB0_2
+; BE64-NEXT:  # %bb.1:
+; BE64-NEXT:    ld 30, 128(31) # 8-byte Folded Reload
+; BE64-NEXT:    ld 1, 0(1)
+; BE64-NEXT:    ld 0, 16(1)
+; BE64-NEXT:    ld 31, -8(1)
+; BE64-NEXT:    mtlr 0
+; BE64-NEXT:    blr
+; BE64-NEXT:  .LBB0_2:
+; BE64-NEXT:    bl __stack_chk_fail
+; BE64-NEXT:    nop
+;
+; LE64-LABEL: foo:
+; LE64:       # %bb.0:
+; LE64-NEXT:    mflr 0
+; LE64-NEXT:    std 31, -8(1)
+; LE64-NEXT:    stdu 1, -64(1)
+; LE64-NEXT:    mr 31, 1
+; LE64-NEXT:    sldi 3, 3, 2
+; LE64-NEXT:    std 0, 80(1)
+; LE64-NEXT:    std 30, 48(31) # 8-byte Folded Spill
+; LE64-NEXT:    addis 30, 2, __stack_chk_guard@toc@ha
+; LE64-NEXT:    addi 3, 3, 15
+; LE64-NEXT:    ld 4, __stack_chk_guard@toc@l(30)
+; LE64-NEXT:    rldicr 3, 3, 0, 59
+; LE64-NEXT:    neg 3, 3
+; LE64-NEXT:    std 4, 40(31)
+; LE64-NEXT:    addi 4, 31, 64
+; LE64-NEXT:    stdux 4, 1, 3
+; LE64-NEXT:    addi 3, 1, 32
+; LE64-NEXT:    bl baz
+; LE64-NEXT:    nop
+; LE64-NEXT:    ld 3, __stack_chk_guard@toc@l(30)
+; LE64-NEXT:    ld 4, 40(31)
+; LE64-NEXT:    cmpld 3, 4
+; LE64-NEXT:    bne 0, .LBB0_2
+; LE64-NEXT:  # %bb.1:
+; LE64-NEXT:    ld 30, 48(31) # 8-byte Folded Reload
+; LE64-NEXT:    ld 1, 0(1)
+; LE64-NEXT:    ld 0, 16(1)
+; LE64-NEXT:    ld 31, -8(1)
+; LE64-NEXT:    mtlr 0
+; LE64-NEXT:    blr
+; LE64-NEXT:  .LBB0_2:
+; LE64-NEXT:    bl __stack_chk_fail
+; LE64-NEXT:    nop
+;
+; LE32-LABEL: foo:
+; LE32:       # %bb.0:
+; LE32-NEXT:    mflr 0
+; LE32-NEXT:    stwu 1, -32(1)
+; LE32-NEXT:    stw 31, 28(1)
+; LE32-NEXT:    mr 31, 1
+; LE32-NEXT:    stw 0, 36(1)
+; LE32-NEXT:    slwi 4, 4, 2
+; LE32-NEXT:    stw 30, 24(31) # 4-byte Folded Spill
+; LE32-NEXT:    lis 30, __stack_chk_guard@ha
+; LE32-NEXT:    lwz 3, __stack_chk_guard@l(30)
+; LE32-NEXT:    addi 4, 4, 15
+; LE32-NEXT:    rlwinm 4, 4, 0, 0, 27
+; LE32-NEXT:    neg 4, 4
+; LE32-NEXT:    stw 3, 20(31)
+; LE32-NEXT:    addi 3, 31, 32
+; LE32-NEXT:    stwux 3, 1, 4
+; LE32-NEXT:    addi 3, 1, 16
+; LE32-NEXT:    bl baz
+; LE32-NEXT:    lwz 3, __stack_chk_guard@l(30)
+; LE32-NEXT:    lwz 4, 20(31)
+; LE32-NEXT:    cmplw 3, 4
+; LE32-NEXT:    bne 0, .LBB0_2
+; LE32-NEXT:  # %bb.1:
+; LE32-NEXT:    lwz 30, 24(31) # 4-byte Folded Reload
+; LE32-NEXT:    lwz 31, 0(1)
+; LE32-NEXT:    lwz 0, -4(31)
+; LE32-NEXT:    mr 1, 31
+; LE32-NEXT:    mr 31, 0
+; LE32-NEXT:    lwz 0, 4(1)
+; LE32-NEXT:    mtlr 0
+; LE32-NEXT:    blr
+; LE32-NEXT:  .LBB0_2:
+; LE32-NEXT:    bl __stack_chk_fail
+  %vla = alloca i32, i64 %t, align 4
+  call void @baz(ptr %vla)
+  ret void
+}
+
+declare void @baz(ptr)
+
+!llvm.module.flags = !{!1}
+!1 = !{i32 2, !"stack-protector-guard", !"global"}
diff --git a/llvm/test/CodeGen/PowerPC/stack-guard-tls.ll b/llvm/test/CodeGen/PowerPC/stack-guard-tls.ll
new file mode 100644
index 00000000000000..fa50db0607f9aa
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/stack-guard-tls.ll
@@ -0,0 +1,114 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc -mtriple=powerpc64 -verify-machineinstrs < %s \
+; RUN:     | FileCheck %s --check-prefixes=BE64
+; RUN: llc -mtriple=powerpc64le -verify-machineinstrs < %s \
+; RUN:     | FileCheck %s --check-prefixes=LE64
+; RUN: llc -mtriple=ppc32 -verify-machineinstrs < %s \
+; RUN:     | FileCheck %s --check-prefixes=LE32
+
+define void @foo(i64 %t) sspstrong nounwind {
+; BE64-LABEL: foo:
+; BE64:       # %bb.0:
+; BE64-NEXT:    mflr 0
+; BE64-NEXT:    std 31, -8(1)
+; BE64-NEXT:    stdu 1, -144(1)
+; BE64-NEXT:    std 0, 160(1)
+; BE64-NEXT:    sldi 3, 3, 2
+; BE64-NEXT:    mr 31, 1
+; BE64-NEXT:    ld 4, 500(13)
+; BE64-NEXT:    addi 3, 3, 15
+; BE64-NEXT:    rldicr 3, 3, 0, 59
+; BE64-NEXT:    neg 3, 3
+; BE64-NEXT:    std 4, 128(31)
+; BE64-NEXT:    addi 4, 31, 144
+; BE64-NEXT:    stdux 4, 1, 3
+; BE64-NEXT:    addi 3, 1, 112
+; BE64-NEXT:    bl baz
+; BE64-NEXT:    nop
+; BE64-NEXT:    ld 3, 500(13)
+; BE64-NEXT:    ld 4, 128(31)
+; BE64-NEXT:    cmpld 3, 4
+; BE64-NEXT:    bne- 0, .LBB0_2
+; BE64-NEXT:  # %bb.1: # %SP_return
+; BE64-NEXT:    ld 1, 0(1)
+; BE64-NEXT:    ld 0, 16(1)
+; BE64-NEXT:    ld 31, -8(1)
+; BE64-NEXT:    mtlr 0
+; BE64-NEXT:    blr
+; BE64-NEXT:  .LBB0_2: # %CallStackCheckFailBlk
+; BE64-NEXT:    bl __stack_chk_fail
+; BE64-NEXT:    nop
+;
+; LE64-LABEL: foo:
+; LE64:       # %bb.0:
+; LE64-NEXT:    mflr 0
+; LE64-NEXT:    std 31, -8(1)
+; LE64-NEXT:    stdu 1, -64(1)
...
[truncated]

Comment on lines 3608 to 3609
!EffectiveTriple.isRISCV() && !EffectiveTriple.isPPC64() &&
!EffectiveTriple.isPPC32())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason not to use EffectiveTriple.isPPC() instead of both EffectiveTriple.isPPC32() and EffectiveTriple.isPPC64()?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

None at all -- I started adding just PPC64 support and realized that it would be easy to just do both 32 and 64 in the same series, but didn't go back and re-factor. Thanks for catching this. I've rebased on top of main so that the RISC-V changes aren't mixed into this PR.

Copy link

github-actions bot commented Oct 3, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

Add support for using a thread-local variable with a specified offset
for holding the stack guard canary value.

Signed-off-by: Keith Packard <[email protected]>
Add tests ensuring that the driver correctly handles stack protector
guard options.

Signed-off-by: Keith Packard <[email protected]>
Make sure the code generated for a TLS-relative stack guard canary
references the right location before and after intervening function
code.

Signed-off-by: Keith Packard <[email protected]>
Make sure the code generated for a global stack guard canary
references __stack_chk_guard before and after intervening function
code.

Signed-off-by: Keith Packard <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:PowerPC backend:RISC-V clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants