diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -3162,6 +3162,8 @@ Group; def mmma: Flag<["-"], "mmma">, Group; def mno_mma: Flag<["-"], "mno-mma">, Group; +def mrop_protection : Flag<["-"], "mrop-protection">, + Group; def maix_struct_return : Flag<["-"], "maix-struct-return">, Group, Flags<[CC1Option]>, HelpText<"Return all structs in memory (PPC32 only)">; diff --git a/clang/lib/Basic/Targets/PPC.h b/clang/lib/Basic/Targets/PPC.h --- a/clang/lib/Basic/Targets/PPC.h +++ b/clang/lib/Basic/Targets/PPC.h @@ -59,6 +59,7 @@ // Target cpu features. bool HasAltivec = false; bool HasMMA = false; + bool HasROPProtection = false; bool HasVSX = false; bool HasP8Vector = false; bool HasP8Crypto = false; diff --git a/clang/lib/Basic/Targets/PPC.cpp b/clang/lib/Basic/Targets/PPC.cpp --- a/clang/lib/Basic/Targets/PPC.cpp +++ b/clang/lib/Basic/Targets/PPC.cpp @@ -66,6 +66,8 @@ PairedVectorMemops = true; } else if (Feature == "+mma") { HasMMA = true; + } else if (Feature == "+rop-protection") { + HasROPProtection = true; } // TODO: Finish this list and add an assert that we've handled them // all. @@ -193,6 +195,8 @@ Builder.defineMacro("__POWER9_VECTOR__"); if (HasMMA) Builder.defineMacro("__MMA__"); + if (HasROPProtection) + Builder.defineMacro("__ROP_PROTECTION__"); if (HasP10Vector) Builder.defineMacro("__POWER10_VECTOR__"); @@ -319,6 +323,9 @@ .Case("pwr8", true) .Default(false); + // ROP Protection is off by default. + Features["rop-protection"] = false; + Features["spe"] = llvm::StringSwitch(CPU) .Case("8548", true) .Case("e500", true) @@ -355,6 +362,13 @@ return false; } + if (!(ArchDefs & ArchDefinePwr8) && + llvm::find(FeaturesVec, "+rop-protection") != FeaturesVec.end()) { + // We can turn on ROP Protection on Power 8 and above. + Diags.Report(diag::err_opt_not_valid_with_opt) << "-mrop-protection" << CPU; + return false; + } + return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec); } @@ -393,6 +407,7 @@ .Case("pcrelative-memops", HasPCRelativeMemops) .Case("spe", HasSPE) .Case("mma", HasMMA) + .Case("rop-protection", HasROPProtection) .Default(false); } diff --git a/clang/test/Driver/ppc-mrop-protection-support-check.c b/clang/test/Driver/ppc-mrop-protection-support-check.c new file mode 100644 --- /dev/null +++ b/clang/test/Driver/ppc-mrop-protection-support-check.c @@ -0,0 +1,26 @@ +// RUN: not %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only \ +// RUN: -mcpu=pwr10 -mrop-protection %s 2>&1 | FileCheck %s --check-prefix=HASROP +// RUN: not %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only \ +// RUN: -mcpu=power10 -mrop-protection %s 2>&1 | FileCheck %s --check-prefix=HASROP +// RUN: not %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only \ +// RUN: -mcpu=pwr9 -mrop-protection %s 2>&1 | FileCheck %s --check-prefix=HASROP +// RUN: not %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only \ +// RUN: -mcpu=power9 -mrop-protection %s 2>&1 | FileCheck %s --check-prefix=HASROP +// RUN: not %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only \ +// RUN: -mcpu=pwr8 -mrop-protection %s 2>&1 | FileCheck %s --check-prefix=HASROP +// RUN: not %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only \ +// RUN: -mcpu=power8 -mrop-protection %s 2>&1 | FileCheck %s --check-prefix=HASROP + +// RUN: not %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only \ +// RUN: -mcpu=pwr7 -mrop-protection %s 2>&1 | FileCheck %s --check-prefix=NOROP +// RUN: not %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only \ +// RUN: -mcpu=power7 -mrop-protection %s 2>&1 | FileCheck %s --check-prefix=NOROP + +#ifdef __ROP_PROTECTION__ +static_assert(false, "ROP Protection enabled"); +#endif + +// HASROP: ROP Protection enabled +// HASROP-NOT: option '-mrop-protection' cannot be specified with +// NOROP: option '-mrop-protection' cannot be specified with + diff --git a/clang/test/Preprocessor/init-ppc64.c b/clang/test/Preprocessor/init-ppc64.c --- a/clang/test/Preprocessor/init-ppc64.c +++ b/clang/test/Preprocessor/init-ppc64.c @@ -566,6 +566,7 @@ // PPCPWR8-NOT:#define _ARCH_PWR6X 1 // PPCPWR8:#define _ARCH_PWR7 1 // PPCPWR8:#define _ARCH_PWR8 1 +// PPCPWR8-NOT:#define __ROP_PROTECTION__ 1 // // RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-none-none -target-cpu power8 -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix PPCPOWER8 %s // @@ -583,6 +584,7 @@ // PPCPOWER8-NOT:#define _ARCH_PWR6X 1 // PPCPOWER8:#define _ARCH_PWR7 1 // PPCPOWER8:#define _ARCH_PWR8 1 +// PPCPOWER8-NOT:#define __ROP_PROTECTION__ 1 // // RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-none-none -target-cpu pwr9 -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix PPCPWR9 %s // @@ -597,6 +599,7 @@ // PPCPWR9-NOT:#define _ARCH_PWR6X 1 // PPCPWR9:#define _ARCH_PWR7 1 // PPCPWR9:#define _ARCH_PWR9 1 +// PPCPWR9-NOT:#define __ROP_PROTECTION__ 1 // // RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-none-none -target-cpu power9 -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix PPCPOWER9 %s // @@ -611,6 +614,7 @@ // PPCPOWER9-NOT:#define _ARCH_PWR6X 1 // PPCPOWER9:#define _ARCH_PWR7 1 // PPCPOWER9:#define _ARCH_PWR9 1 +// PPCPOWER9-NOT:#define __ROP_PROTECTION__ 1 // // RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-none-none -target-cpu pwr10 -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix PPCPOWER10 %s // RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-none-none -target-cpu power10 -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix PPCPOWER10 %s @@ -629,6 +633,7 @@ // PPCPOWER10:#define _ARCH_PWR8 1 // PPCPOWER10:#define _ARCH_PWR9 1 // PPCPOWER10:#define __MMA__ 1 +// PPCPOWER10-NOT:#define __ROP_PROTECTION__ 1 // // RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-none-none -target-cpu future -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix PPCFUTURE %s // @@ -647,10 +652,16 @@ // PPCFUTURE:#define _ARCH_PWR9 1 // PPCFUTURE:#define _ARCH_PWR_FUTURE 1 // PPCFUTURE:#define __MMA__ 1 +// PPCFUTURE-NOT:#define __ROP_PROTECTION__ 1 // // RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-none-none -target-feature +mma -target-cpu power10 -fno-signed-char < /dev/null | FileCheck -check-prefix PPC-MMA %s // PPC-MMA:#define __MMA__ 1 // +// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-none-none -target-feature +rop-protection -target-cpu power10 -fno-signed-char < /dev/null | FileCheck -check-prefix PPC-ROP %s +// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-none-none -target-feature +rop-protection -target-cpu power9 -fno-signed-char < /dev/null | FileCheck -check-prefix PPC-ROP %s +// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-none-none -target-feature +rop-protection -target-cpu power8 -fno-signed-char < /dev/null | FileCheck -check-prefix PPC-ROP %s +// PPC-ROP:#define __ROP_PROTECTION__ 1 +// // RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-none-none -target-feature +float128 -target-cpu power9 -fno-signed-char < /dev/null | FileCheck -check-prefix PPC-FLOAT128 %s // PPC-FLOAT128:#define __FLOAT128__ 1 // diff --git a/llvm/lib/Target/PowerPC/PPC.td b/llvm/lib/Target/PowerPC/PPC.td --- a/llvm/lib/Target/PowerPC/PPC.td +++ b/llvm/lib/Target/PowerPC/PPC.td @@ -252,6 +252,9 @@ "Enable MMA instructions", [FeatureP8Vector, FeatureP9Altivec, FeaturePairedVectorMemops]>; +def FeatureROPProtection : + SubtargetFeature<"rop-protection", "HasROPProtection", "false", + "Add ROP protection">; def FeaturePredictableSelectIsExpensive : SubtargetFeature<"predictable-select-expensive", diff --git a/llvm/lib/Target/PowerPC/PPCSubtarget.h b/llvm/lib/Target/PowerPC/PPCSubtarget.h --- a/llvm/lib/Target/PowerPC/PPCSubtarget.h +++ b/llvm/lib/Target/PowerPC/PPCSubtarget.h @@ -112,6 +112,7 @@ bool HasPrefixInstrs; bool HasPCRelativeMemops; bool HasMMA; + bool HasROPProtection; bool HasFCPSGN; bool HasFSQRT; bool HasFRE, HasFRES, HasFRSQRTE, HasFRSQRTES; @@ -273,6 +274,7 @@ bool hasPrefixInstrs() const { return HasPrefixInstrs; } bool hasPCRelativeMemops() const { return HasPCRelativeMemops; } bool hasMMA() const { return HasMMA; } + bool hasROPProtection() const { return HasROPProtection; } bool pairedVectorMemops() const { return PairedVectorMemops; } bool hasMFOCRF() const { return HasMFOCRF; } bool hasISEL() const { return HasISEL; } diff --git a/llvm/lib/Target/PowerPC/PPCSubtarget.cpp b/llvm/lib/Target/PowerPC/PPCSubtarget.cpp --- a/llvm/lib/Target/PowerPC/PPCSubtarget.cpp +++ b/llvm/lib/Target/PowerPC/PPCSubtarget.cpp @@ -87,6 +87,7 @@ HasP9Vector = false; HasP9Altivec = false; HasMMA = false; + HasROPProtection = false; HasP10Vector = false; HasPrefixInstrs = false; HasPCRelativeMemops = false; diff --git a/llvm/test/CodeGen/PowerPC/future-check-features.ll b/llvm/test/CodeGen/PowerPC/future-check-features.ll --- a/llvm/test/CodeGen/PowerPC/future-check-features.ll +++ b/llvm/test/CodeGen/PowerPC/future-check-features.ll @@ -1,7 +1,7 @@ -; RUN: llc -mattr=pcrelative-memops,prefix-instrs,paired-vector-memops,mma \ +; RUN: llc -mattr=pcrelative-memops,prefix-instrs,paired-vector-memops,mma,rop-protection \ ; RUN: -verify-machineinstrs -mtriple=powerpc64le-unknown-unknown \ ; RUN: -ppc-asm-full-reg-names %s -o - 2>&1 | FileCheck %s -; RUN: llc -mattr=pcrelative-memops,prefix-instrs,paired-vector-memops,mma \ +; RUN: llc -mattr=pcrelative-memops,prefix-instrs,paired-vector-memops,mma,rop-protection \ ; RUN: -verify-machineinstrs -mtriple=powerpc64-unknown-unknown \ ; RUN: -ppc-asm-full-reg-names %s -o - 2>&1 | FileCheck %s