[clang] [llvm] [PowerPC][ISelLowering] Support -mstack-protector-guard=tls (PR #110928)
Keith Packard via cfe-commits
cfe-commits at lists.llvm.org
Mon Oct 7 18:10:05 PDT 2024
https://github.com/keith-packard updated https://github.com/llvm/llvm-project/pull/110928
>From ad3d5b03886aa7939d67aef10e31734db7c43834 Mon Sep 17 00:00:00 2001
From: Keith Packard <keithp at keithp.com>
Date: Sun, 6 Oct 2024 23:19:30 -0700
Subject: [PATCH 1/5] [CodeGen] Provide Module to useLoadStackGuardNode
Use of LOAD_STACK_GUARD may depend upon compilation parameters; the
Module has access to all of the stack guard parameter methods.
Signed-off-by: Keith Packard <keithp at keithp.com>
---
llvm/include/llvm/CodeGen/TargetLowering.h | 4 +---
llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | 4 ++--
llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 7 ++++---
llvm/lib/Target/AArch64/AArch64ISelLowering.cpp | 4 ++--
llvm/lib/Target/AArch64/AArch64ISelLowering.h | 2 +-
llvm/lib/Target/ARM/ARMISelLowering.cpp | 2 +-
llvm/lib/Target/ARM/ARMISelLowering.h | 2 +-
llvm/lib/Target/Sparc/SparcISelLowering.cpp | 4 ++--
llvm/lib/Target/Sparc/SparcISelLowering.h | 2 +-
llvm/lib/Target/SystemZ/SystemZISelLowering.h | 4 +---
llvm/lib/Target/X86/X86ISelLowering.cpp | 2 +-
llvm/lib/Target/X86/X86ISelLowering.h | 2 +-
12 files changed, 18 insertions(+), 21 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h
index 3842af56e6b3d7..54054ed38050ea 100644
--- a/llvm/include/llvm/CodeGen/TargetLowering.h
+++ b/llvm/include/llvm/CodeGen/TargetLowering.h
@@ -5586,9 +5586,7 @@ class TargetLowering : public TargetLoweringBase {
/// If this function returns true, SelectionDAGBuilder emits a
/// LOAD_STACK_GUARD node when it is lowering Intrinsic::stackprotector.
- virtual bool useLoadStackGuardNode() const {
- return false;
- }
+ virtual bool useLoadStackGuardNode(const Module &M) const { return false; }
virtual SDValue emitStackGuardXorFP(SelectionDAG &DAG, SDValue Val,
const SDLoc &DL) const {
diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index 40360b0b0f1d86..7b57db1222249a 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -2377,7 +2377,7 @@ bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID,
case Intrinsic::stackprotector: {
LLT PtrTy = getLLTForType(*CI.getArgOperand(0)->getType(), *DL);
Register GuardVal;
- if (TLI->useLoadStackGuardNode()) {
+ if (TLI->useLoadStackGuardNode(*CI.getModule())) {
GuardVal = MRI->createGenericVirtualRegister(PtrTy);
getStackGuard(GuardVal, MIRBuilder);
} else
@@ -3868,7 +3868,7 @@ bool IRTranslator::emitSPDescriptorParent(StackProtectorDescriptor &SPD,
// If useLoadStackGuardNode returns true, generate LOAD_STACK_GUARD.
// Otherwise, emit a volatile load to retrieve the stack guard value.
- if (TLI->useLoadStackGuardNode()) {
+ if (TLI->useLoadStackGuardNode(*ParentBB->getBasicBlock()->getModule())) {
Guard =
MRI->createGenericVirtualRegister(LLT::scalar(PtrTy.getSizeInBits()));
getStackGuard(Guard, *CurBuilder);
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 25213f587116d5..138058ce192470 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -3138,7 +3138,7 @@ void SelectionDAGBuilder::visitSPDescriptorParent(StackProtectorDescriptor &SPD,
// If useLoadStackGuardNode returns true, generate LOAD_STACK_GUARD.
// Otherwise, emit a volatile load to retrieve the stack guard value.
SDValue Chain = DAG.getEntryNode();
- if (TLI.useLoadStackGuardNode()) {
+ if (TLI.useLoadStackGuardNode(M)) {
Guard = getLoadStackGuard(DAG, dl, Chain);
} else {
const Value *IRGuard = TLI.getSDagStackGuard(M);
@@ -7331,7 +7331,7 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
const Module &M = *MF.getFunction().getParent();
EVT PtrTy = TLI.getValueType(DAG.getDataLayout(), I.getType());
SDValue Chain = getRoot();
- if (TLI.useLoadStackGuardNode()) {
+ if (TLI.useLoadStackGuardNode(M)) {
Res = getLoadStackGuard(DAG, sdl, Chain);
Res = DAG.getPtrExtOrTrunc(Res, sdl, PtrTy);
} else {
@@ -7351,9 +7351,10 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
// Emit code into the DAG to store the stack guard onto the stack.
MachineFunction &MF = DAG.getMachineFunction();
MachineFrameInfo &MFI = MF.getFrameInfo();
+ const Module &M = *MF.getFunction().getParent();
SDValue Src, Chain = getRoot();
- if (TLI.useLoadStackGuardNode())
+ if (TLI.useLoadStackGuardNode(M))
Src = getLoadStackGuard(DAG, sdl, Chain);
else
Src = getValue(I.getArgOperand(0)); // The guard's value.
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index e55e9989e6565c..9c42ea98a2469f 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -27316,9 +27316,9 @@ void AArch64TargetLowering::ReplaceNodeResults(
}
}
-bool AArch64TargetLowering::useLoadStackGuardNode() const {
+bool AArch64TargetLowering::useLoadStackGuardNode(const Module &M) const {
if (Subtarget->isTargetAndroid() || Subtarget->isTargetFuchsia())
- return TargetLowering::useLoadStackGuardNode();
+ return TargetLowering::useLoadStackGuardNode(M);
return true;
}
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.h b/llvm/lib/Target/AArch64/AArch64ISelLowering.h
index 480bf60360bf55..87bd40aa49405c 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.h
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.h
@@ -813,7 +813,7 @@ class AArch64TargetLowering : public TargetLowering {
TargetLoweringBase::AtomicExpansionKind
shouldExpandAtomicCmpXchgInIR(AtomicCmpXchgInst *AI) const override;
- bool useLoadStackGuardNode() const override;
+ bool useLoadStackGuardNode(const Module &M) const override;
TargetLoweringBase::LegalizeTypeAction
getPreferredVectorAction(MVT VT) const override;
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index 1733424a8b669f..db9f2c873f64e9 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -21452,7 +21452,7 @@ bool ARMTargetLowering::shouldInsertFencesForAtomic(
return InsertFencesForAtomic;
}
-bool ARMTargetLowering::useLoadStackGuardNode() const {
+bool ARMTargetLowering::useLoadStackGuardNode(const Module &M) const {
// ROPI/RWPI are not supported currently.
return !Subtarget->isROPI() && !Subtarget->isRWPI();
}
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.h b/llvm/lib/Target/ARM/ARMISelLowering.h
index a255e9b6fc365f..e70616293860df 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.h
+++ b/llvm/lib/Target/ARM/ARMISelLowering.h
@@ -677,7 +677,7 @@ class VectorType;
TargetLoweringBase::AtomicExpansionKind
shouldExpandAtomicCmpXchgInIR(AtomicCmpXchgInst *AI) const override;
- bool useLoadStackGuardNode() const override;
+ bool useLoadStackGuardNode(const Module &M) const override;
void insertSSPDeclarations(Module &M) const override;
Value *getSDagStackGuard(const Module &M) const override;
diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
index 42b8248006d1fd..de4986ef1e89e4 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
@@ -3548,9 +3548,9 @@ void SparcTargetLowering::ReplaceNodeResults(SDNode *N,
}
// Override to enable LOAD_STACK_GUARD lowering on Linux.
-bool SparcTargetLowering::useLoadStackGuardNode() const {
+bool SparcTargetLowering::useLoadStackGuardNode(const Module &M) const {
if (!Subtarget->isTargetLinux())
- return TargetLowering::useLoadStackGuardNode();
+ return TargetLowering::useLoadStackGuardNode(M);
return true;
}
diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.h b/llvm/lib/Target/Sparc/SparcISelLowering.h
index 15d09bc9309754..cc672074a4be80 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.h
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.h
@@ -119,7 +119,7 @@ namespace llvm {
}
/// Override to support customized stack guard loading.
- bool useLoadStackGuardNode() const override;
+ bool useLoadStackGuardNode(const Module &M) const override;
void insertSSPDeclarations(Module &M) const override;
/// getSetCCResultType - Return the ISD::SETCC ValueType
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.h b/llvm/lib/Target/SystemZ/SystemZISelLowering.h
index 2b065245c16f20..3c06c1fdf2b1bc 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.h
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.h
@@ -570,9 +570,7 @@ class SystemZTargetLowering : public TargetLowering {
getExceptionSelectorRegister(const Constant *PersonalityFn) const override;
/// Override to support customized stack guard loading.
- bool useLoadStackGuardNode() const override {
- return true;
- }
+ bool useLoadStackGuardNode(const Module &M) const override { return true; }
void insertSSPDeclarations(Module &M) const override {
}
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 73f7f52846f625..dde0768d3ecc7e 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -2680,7 +2680,7 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM,
}
// This has so far only been implemented for 64-bit MachO.
-bool X86TargetLowering::useLoadStackGuardNode() const {
+bool X86TargetLowering::useLoadStackGuardNode(const Module &M) const {
return Subtarget.isTargetMachO() && Subtarget.is64Bit();
}
diff --git a/llvm/lib/Target/X86/X86ISelLowering.h b/llvm/lib/Target/X86/X86ISelLowering.h
index 0ab42f032c3ea6..a9cb8db5c4a8a2 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.h
+++ b/llvm/lib/Target/X86/X86ISelLowering.h
@@ -1570,7 +1570,7 @@ namespace llvm {
/// returns the address of that location. Otherwise, returns nullptr.
Value *getIRStackGuard(IRBuilderBase &IRB) const override;
- bool useLoadStackGuardNode() const override;
+ bool useLoadStackGuardNode(const Module &M) const override;
bool useStackGuardXorFP() const override;
void insertSSPDeclarations(Module &M) const override;
Value *getSDagStackGuard(const Module &M) const override;
>From fc346dc1754d55ea05e11e51dae792a648a61766 Mon Sep 17 00:00:00 2001
From: Keith Packard <keithp at keithp.com>
Date: Mon, 16 Sep 2024 15:41:38 +0200
Subject: [PATCH 2/5] [PowerPC][ISelLowering] Support
-mstack-protector-guard=tls
Add support for using a thread-local variable with a specified offset
for holding the stack guard canary value.
Signed-off-by: Keith Packard <keithp at keithp.com>
---
clang/lib/Driver/ToolChains/Clang.cpp | 18 ++++++++++++++----
llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 8 ++++----
llvm/lib/Target/PowerPC/PPCISelLowering.h | 2 +-
llvm/lib/Target/PowerPC/PPCInstrInfo.cpp | 14 +++++++++++---
4 files changed, 30 insertions(+), 12 deletions(-)
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index c9baca00ec6f3b..2b465915054a0c 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -3605,7 +3605,7 @@ static void RenderSSPOptions(const Driver &D, const ToolChain &TC,
StringRef Value = A->getValue();
if (!EffectiveTriple.isX86() && !EffectiveTriple.isAArch64() &&
!EffectiveTriple.isARM() && !EffectiveTriple.isThumb() &&
- !EffectiveTriple.isRISCV())
+ !EffectiveTriple.isRISCV() && !EffectiveTriple.isPPC())
D.Diag(diag::err_drv_unsupported_opt_for_target)
<< A->getAsString(Args) << TripleStr;
if ((EffectiveTriple.isX86() || EffectiveTriple.isARM() ||
@@ -3645,7 +3645,7 @@ static void RenderSSPOptions(const Driver &D, const ToolChain &TC,
<< A->getOption().getName() << Value << "sysreg global";
return;
}
- if (EffectiveTriple.isRISCV()) {
+ if (EffectiveTriple.isRISCV() || EffectiveTriple.isPPC()) {
if (Value != "tls" && Value != "global") {
D.Diag(diag::err_drv_invalid_value_with_suggestion)
<< A->getOption().getName() << Value << "tls global";
@@ -3666,7 +3666,7 @@ static void RenderSSPOptions(const Driver &D, const ToolChain &TC,
StringRef Value = A->getValue();
if (!EffectiveTriple.isX86() && !EffectiveTriple.isAArch64() &&
!EffectiveTriple.isARM() && !EffectiveTriple.isThumb() &&
- !EffectiveTriple.isRISCV())
+ !EffectiveTriple.isRISCV() && !EffectiveTriple.isPPC())
D.Diag(diag::err_drv_unsupported_opt_for_target)
<< A->getAsString(Args) << TripleStr;
int Offset;
@@ -3686,7 +3686,7 @@ 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() &&
- !EffectiveTriple.isRISCV())
+ !EffectiveTriple.isRISCV() && !EffectiveTriple.isPPC())
D.Diag(diag::err_drv_unsupported_opt_for_target)
<< A->getAsString(Args) << TripleStr;
if (EffectiveTriple.isX86() && (Value != "fs" && Value != "gs")) {
@@ -3703,6 +3703,16 @@ static void RenderSSPOptions(const Driver &D, const ToolChain &TC,
<< 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/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index d9847a21489e63..acebb47d41a45b 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -17889,10 +17889,10 @@ SDValue PPCTargetLowering::getNegatedExpression(SDValue Op, SelectionDAG &DAG,
}
// Override to enable LOAD_STACK_GUARD lowering on Linux.
-bool PPCTargetLowering::useLoadStackGuardNode() const {
- if (!Subtarget.isTargetLinux())
- return TargetLowering::useLoadStackGuardNode();
- return true;
+bool PPCTargetLowering::useLoadStackGuardNode(const Module &M) const {
+ if (M.getStackProtectorGuard() == "tls" || Subtarget.isTargetLinux())
+ return true;
+ return TargetLowering::useLoadStackGuardNode(M);
}
// Override to disable global variable loading on Linux and insert AIX canary
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.h b/llvm/lib/Target/PowerPC/PPCISelLowering.h
index 8907c3c5a81c3c..8c7961e641c354 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.h
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.h
@@ -1137,7 +1137,7 @@ namespace llvm {
getExceptionSelectorRegister(const Constant *PersonalityFn) const override;
/// Override to support customized stack guard loading.
- bool useLoadStackGuardNode() const override;
+ bool useLoadStackGuardNode(const Module &M) const override;
void insertSSPDeclarations(Module &M) const override;
Value *getSDagStackGuard(const Module &M) const override;
diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp
index 48833e8f88066c..bc2a1b295b4333 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp
+++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp
@@ -35,6 +35,7 @@
#include "llvm/CodeGen/ScheduleDAG.h"
#include "llvm/CodeGen/SlotIndexes.h"
#include "llvm/CodeGen/StackMaps.h"
+#include "llvm/IR/Module.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/TargetRegistry.h"
@@ -3107,9 +3108,16 @@ bool PPCInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
return true;
}
case TargetOpcode::LOAD_STACK_GUARD: {
- assert(Subtarget.isTargetLinux() &&
- "Only Linux target is expected to contain LOAD_STACK_GUARD");
- const int64_t Offset = Subtarget.isPPC64() ? -0x7010 : -0x7008;
+ auto M = MBB.getParent()->getFunction().getParent();
+ assert(
+ (Subtarget.isTargetLinux() || M->getStackProtectorGuard() == "tls") &&
+ "Only Linux target or tls mode are expected to contain "
+ "LOAD_STACK_GUARD");
+ int64_t Offset;
+ if (M->getStackProtectorGuard() == "tls")
+ Offset = M->getStackProtectorGuardOffset();
+ else
+ Offset = Subtarget.isPPC64() ? -0x7010 : -0x7008;
const unsigned Reg = Subtarget.isPPC64() ? PPC::X13 : PPC::R2;
MI.setDesc(get(Subtarget.isPPC64() ? PPC::LD : PPC::LWZ));
MachineInstrBuilder(*MI.getParent()->getParent(), MI)
>From 93329008fe070c4b110276adcb74f3093a6b4a0f Mon Sep 17 00:00:00 2001
From: Keith Packard <keithp at keithp.com>
Date: Mon, 16 Sep 2024 11:27:19 -0700
Subject: [PATCH 3/5] [clang][PowerPC] Add stack protector tests
Add tests ensuring that the driver correctly handles stack protector
guard options.
Signed-off-by: Keith Packard <keithp at keithp.com>
---
clang/test/CodeGen/stack-protector-guard.c | 16 ++++++
clang/test/Driver/stack-protector-guard.c | 57 ++++++++++++++++++++--
2 files changed, 70 insertions(+), 3 deletions(-)
diff --git a/clang/test/CodeGen/stack-protector-guard.c b/clang/test/CodeGen/stack-protector-guard.c
index 4777367c94e733..82616ae800c426 100644
--- a/clang/test/CodeGen/stack-protector-guard.c
+++ b/clang/test/CodeGen/stack-protector-guard.c
@@ -12,6 +12,12 @@
// 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
+// RUN: %clang_cc1 -mstack-protector-guard=tls -triple ppc32-unknown-elf \
+// RUN: -mstack-protector-guard-offset=16 -mstack-protector-guard-reg=r2 \
+// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=POWERPC32
void foo(int*);
void bar(int x) {
int baz[x];
@@ -31,3 +37,13 @@ void bar(int x) {
// 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: [[ATTR2]] = !{i32 1, !"stack-protector-guard", !"tls"}
+// POWERPC64: [[ATTR3]] = !{i32 1, !"stack-protector-guard-reg", !"r13"}
+// POWERPC64: [[ATTR4]] = !{i32 1, !"stack-protector-guard-offset", i32 52}
+
+// POWERPC32: !llvm.module.flags = !{{{.*}}[[ATTR1:![0-9]+]], [[ATTR2:![0-9]+]], [[ATTR3:![0-9]+]], [[ATTR4:![0-9]+]]}
+// POWERPC32: [[ATTR2]] = !{i32 1, !"stack-protector-guard", !"tls"}
+// POWERPC32: [[ATTR3]] = !{i32 1, !"stack-protector-guard-reg", !"r2"}
+// POWERPC32: [[ATTR4]] = !{i32 1, !"stack-protector-guard-offset", i32 16}
diff --git a/clang/test/Driver/stack-protector-guard.c b/clang/test/Driver/stack-protector-guard.c
index d8475a70e3709f..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
@@ -104,3 +104,54 @@
// 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
>From c4aacbf763eadea801db327f71a51c6a4cdeb0eb Mon Sep 17 00:00:00 2001
From: Keith Packard <keithp at keithp.com>
Date: Mon, 16 Sep 2024 12:36:06 -0700
Subject: [PATCH 4/5] [CodeGen][PowerPC] Add codegen test for TLS stack canary
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 <keithp at keithp.com>
---
llvm/test/CodeGen/PowerPC/stack-guard-tls.ll | 114 +++++++++++++++++++
1 file changed, 114 insertions(+)
create mode 100644 llvm/test/CodeGen/PowerPC/stack-guard-tls.ll
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..de0becc037309f
--- /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: ld 4, 500(13)
+; BE64-NEXT: sldi 3, 3, 2
+; BE64-NEXT: mr 31, 1
+; BE64-NEXT: addi 3, 3, 15
+; BE64-NEXT: rldicr 3, 3, 0, 59
+; BE64-NEXT: std 0, 160(1)
+; 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, 128(31)
+; BE64-NEXT: ld 4, 500(13)
+; BE64-NEXT: cmpld 4, 3
+; BE64-NEXT: bne 0, .LBB0_2
+; BE64-NEXT: # %bb.1:
+; 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: sldi 3, 3, 2
+; LE64-NEXT: ld 4, 500(13)
+; LE64-NEXT: std 0, 80(1)
+; LE64-NEXT: addi 3, 3, 15
+; LE64-NEXT: mr 31, 1
+; LE64-NEXT: std 4, 48(31)
+; LE64-NEXT: addi 4, 31, 64
+; LE64-NEXT: rldicr 3, 3, 0, 59
+; LE64-NEXT: neg 3, 3
+; LE64-NEXT: stdux 4, 1, 3
+; LE64-NEXT: addi 3, 1, 32
+; LE64-NEXT: bl baz
+; LE64-NEXT: nop
+; LE64-NEXT: ld 3, 48(31)
+; LE64-NEXT: ld 4, 500(13)
+; LE64-NEXT: cmpld 4, 3
+; LE64-NEXT: bne 0, .LBB0_2
+; LE64-NEXT: # %bb.1:
+; 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: lwz 3, 500(2)
+; LE32-NEXT: slwi 4, 4, 2
+; LE32-NEXT: addi 4, 4, 15
+; LE32-NEXT: stw 31, 28(1)
+; LE32-NEXT: mr 31, 1
+; LE32-NEXT: rlwinm 4, 4, 0, 0, 27
+; LE32-NEXT: stw 0, 36(1)
+; LE32-NEXT: neg 4, 4
+; LE32-NEXT: stw 3, 24(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, 24(31)
+; LE32-NEXT: lwz 4, 500(2)
+; LE32-NEXT: cmplw 4, 3
+; LE32-NEXT: bne 0, .LBB0_2
+; LE32-NEXT: # %bb.1:
+; 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, !2}
+!1 = !{i32 2, !"stack-protector-guard", !"tls"}
+!2 = !{i32 2, !"stack-protector-guard-offset", i32 500}
>From ef8f4685be71221a1d075ffdb2e063cc2529489b Mon Sep 17 00:00:00 2001
From: Keith Packard <keithp at keithp.com>
Date: Mon, 23 Sep 2024 11:34:21 -0700
Subject: [PATCH 5/5] [CodeGen][PowerPC] Add codegen test for global stack
canary
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 <keithp at keithp.com>
---
.../CodeGen/PowerPC/stack-guard-global.ll | 122 ++++++++++++++++++
1 file changed, 122 insertions(+)
create mode 100644 llvm/test/CodeGen/PowerPC/stack-guard-global.ll
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 at toc@ha
+; BE64-NEXT: sldi 3, 3, 2
+; BE64-NEXT: ld 4, __stack_chk_guard at 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 at 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 at toc@ha
+; LE64-NEXT: addi 3, 3, 15
+; LE64-NEXT: ld 4, __stack_chk_guard at 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 at 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 at ha
+; LE32-NEXT: lwz 3, __stack_chk_guard at 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 at 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"}
More information about the cfe-commits
mailing list