[clang] [Clang][RISCV] Add preprocessor macros for Zicfilp CFI scheme (PR #109600)
Ming-Yi Lai via cfe-commits
cfe-commits at lists.llvm.org
Thu Sep 26 01:34:40 PDT 2024
https://github.com/mylai-mtk updated https://github.com/llvm/llvm-project/pull/109600
>From 1a0aed20421b58114332975ad7d7fff90a21014a Mon Sep 17 00:00:00 2001
From: Ming-Yi Lai <ming-yi.lai at mediatek.com>
Date: Wed, 4 Sep 2024 18:40:48 +0800
Subject: [PATCH 1/2] [clang][RISCV] Introduce command line options for
Zicfilp-backed forward-edge CFI
This patch enables the following command line flags for RISC-V targets:
+ `-fcf-protection=branch` turns on forward-edge control-flow integrity conditioning on RISC-V targets with Zicfilp extension
+ `-mcf-branch-label-scheme=unlabeled|func-sig` selects the label scheme used in the forward-edge CFI conditioning
---
.../clang/Basic/CFProtectionOptions.def | 15 +++
.../include/clang/Basic/CFProtectionOptions.h | 38 ++++++++
clang/include/clang/Basic/CodeGenOptions.def | 2 +
clang/include/clang/Basic/CodeGenOptions.h | 1 +
clang/include/clang/Basic/LangOptions.def | 2 +
clang/include/clang/Basic/LangOptions.h | 2 +
clang/include/clang/Basic/TargetInfo.h | 8 ++
clang/include/clang/Driver/Options.td | 4 +
clang/lib/Basic/TargetInfo.cpp | 15 +++
clang/lib/Basic/Targets/RISCV.h | 22 +++++
clang/lib/CodeGen/CodeGenModule.cpp | 10 ++
clang/lib/Driver/ToolChains/Clang.cpp | 4 +
clang/lib/Frontend/CompilerInvocation.cpp | 40 ++++++++
.../test/CodeGen/RISCV/riscv-cf-protection.c | 94 +++++++++++++++++++
14 files changed, 257 insertions(+)
create mode 100644 clang/include/clang/Basic/CFProtectionOptions.def
create mode 100644 clang/include/clang/Basic/CFProtectionOptions.h
create mode 100644 clang/test/CodeGen/RISCV/riscv-cf-protection.c
diff --git a/clang/include/clang/Basic/CFProtectionOptions.def b/clang/include/clang/Basic/CFProtectionOptions.def
new file mode 100644
index 00000000000000..b9df2de7f7eba0
--- /dev/null
+++ b/clang/include/clang/Basic/CFProtectionOptions.def
@@ -0,0 +1,15 @@
+//===-- CFProtectionOptions.def - cf-protection options ---------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+
+#ifdef CF_BRANCH_LABEL_SCHEME
+CF_BRANCH_LABEL_SCHEME(Unlabeled, unlabeled)
+CF_BRANCH_LABEL_SCHEME(FuncSig, func-sig)
+
+#undef CF_BRANCH_LABEL_SCHEME
+#endif // #ifdef CF_BRANCH_LABEL_SCHEME
diff --git a/clang/include/clang/Basic/CFProtectionOptions.h b/clang/include/clang/Basic/CFProtectionOptions.h
new file mode 100644
index 00000000000000..13f46d4c13e7e7
--- /dev/null
+++ b/clang/include/clang/Basic/CFProtectionOptions.h
@@ -0,0 +1,38 @@
+//===--- CFProtectionOptions.h ----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines constants for -fcf-protection and other related flags.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_CFPROTECTIONOPTIONS_H
+#define LLVM_CLANG_BASIC_CFPROTECTIONOPTIONS_H
+
+#include "llvm/Support/ErrorHandling.h"
+
+namespace clang {
+
+enum class CFBranchLabelSchemeKind {
+ Default,
+#define CF_BRANCH_LABEL_SCHEME(Kind, FlagVal) Kind,
+#include "clang/Basic/CFProtectionOptions.def"
+};
+
+static inline const char *
+getCFBranchLabelSchemeFlagVal(const CFBranchLabelSchemeKind Scheme) {
+#define CF_BRANCH_LABEL_SCHEME(Kind, FlagVal) \
+ if (Scheme == CFBranchLabelSchemeKind::Kind) \
+ return #FlagVal;
+#include "clang/Basic/CFProtectionOptions.def"
+
+ llvm::report_fatal_error("invalid scheme");
+}
+
+} // namespace clang
+
+#endif // #ifndef LLVM_CLANG_BASIC_CFPROTECTIONOPTIONS_H
diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def
index b600198998d85b..de7ae73f8a603b 100644
--- a/clang/include/clang/Basic/CodeGenOptions.def
+++ b/clang/include/clang/Basic/CodeGenOptions.def
@@ -110,6 +110,8 @@ CODEGENOPT(CFProtectionReturn , 1, 0) ///< if -fcf-protection is
///< set to full or return.
CODEGENOPT(CFProtectionBranch , 1, 0) ///< if -fcf-protection is
///< set to full or branch.
+ENUM_CODEGENOPT(CFBranchLabelScheme, CFBranchLabelSchemeKind, 2,
+ CFBranchLabelSchemeKind::Default) ///< if -mcf-branch-label-scheme is set.
CODEGENOPT(FunctionReturnThunks, 1, 0) ///< -mfunction-return={keep|thunk-extern}
CODEGENOPT(IndirectBranchCSPrefix, 1, 0) ///< if -mindirect-branch-cs-prefix
///< is set.
diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h
index f2a707a8ba8d76..a6953c17a447ef 100644
--- a/clang/include/clang/Basic/CodeGenOptions.h
+++ b/clang/include/clang/Basic/CodeGenOptions.h
@@ -13,6 +13,7 @@
#ifndef LLVM_CLANG_BASIC_CODEGENOPTIONS_H
#define LLVM_CLANG_BASIC_CODEGENOPTIONS_H
+#include "clang/Basic/CFProtectionOptions.h"
#include "clang/Basic/PointerAuthOptions.h"
#include "clang/Basic/Sanitizers.h"
#include "clang/Basic/XRayInstr.h"
diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def
index fd3346d29f26a3..68db400c22e6c1 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -364,6 +364,8 @@ BENIGN_LANGOPT(CompatibilityQualifiedIdBlockParamTypeChecking, 1, 0,
LANGOPT(ObjCDisableDirectMethodsForTesting, 1, 0,
"Disable recognition of objc_direct methods")
LANGOPT(CFProtectionBranch , 1, 0, "Control-Flow Branch Protection enabled")
+ENUM_LANGOPT(CFBranchLabelScheme, CFBranchLabelSchemeKind, 2, CFBranchLabelSchemeKind::Default,
+ "Control-Flow Branch Protection Label Scheme")
LANGOPT(FakeAddressSpaceMap , 1, 0, "OpenCL fake address space map")
ENUM_LANGOPT(AddressSpaceMapMangling , AddrSpaceMapMangling, 2, ASMM_Target, "OpenCL address space map mangling mode")
LANGOPT(IncludeDefaultHeader, 1, 0, "Include default header file for OpenCL")
diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h
index 6c186c410e158d..c3d53ca92d450c 100644
--- a/clang/include/clang/Basic/LangOptions.h
+++ b/clang/include/clang/Basic/LangOptions.h
@@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_BASIC_LANGOPTIONS_H
#define LLVM_CLANG_BASIC_LANGOPTIONS_H
+#include "clang/Basic/CFProtectionOptions.h"
#include "clang/Basic/CommentOptions.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangStandard.h"
@@ -73,6 +74,7 @@ class LangOptionsBase {
public:
using Visibility = clang::Visibility;
using RoundingMode = llvm::RoundingMode;
+ using CFBranchLabelSchemeKind = clang::CFBranchLabelSchemeKind;
enum GCMode { NonGC, GCOnly, HybridGC };
enum StackProtectorMode { SSPOff, SSPOn, SSPStrong, SSPReq };
diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h
index f31d88a354ea28..57783850606290 100644
--- a/clang/include/clang/Basic/TargetInfo.h
+++ b/clang/include/clang/Basic/TargetInfo.h
@@ -16,6 +16,7 @@
#include "clang/Basic/AddressSpaces.h"
#include "clang/Basic/BitmaskEnum.h"
+#include "clang/Basic/CFProtectionOptions.h"
#include "clang/Basic/CodeGenOptions.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
@@ -1727,6 +1728,13 @@ class TargetInfo : public TransferrableTargetInfo,
virtual bool
checkCFProtectionBranchSupported(DiagnosticsEngine &Diags) const;
+ /// Get the target default CFBranchLabelScheme scheme
+ virtual CFBranchLabelSchemeKind getDefaultCFBranchLabelScheme() const;
+
+ virtual bool
+ checkCFBranchLabelSchemeSupported(const CFBranchLabelSchemeKind Scheme,
+ DiagnosticsEngine &Diags) const;
+
/// Check if the target supports CFProtection return.
virtual bool
checkCFProtectionReturnSupported(DiagnosticsEngine &Diags) const;
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 002f60350543d9..ccbe302e4937e1 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -2841,6 +2841,10 @@ def fcf_protection : Flag<["-"], "fcf-protection">, Group<f_Group>,
Visibility<[ClangOption, CLOption, CC1Option]>,
Alias<fcf_protection_EQ>, AliasArgs<["full"]>,
HelpText<"Enable cf-protection in 'full' mode">;
+def mcf_branch_label_scheme_EQ : Joined<["-"], "mcf-branch-label-scheme=">,
+ Visibility<[ClangOption, CC1Option]>, Group<m_Group>,
+ HelpText<"Select label scheme for branch control-flow architecture protection">,
+ Values<"unlabeled,func-sig">;
def mfunction_return_EQ : Joined<["-"], "mfunction-return=">,
Group<m_Group>, Visibility<[ClangOption, CLOption, CC1Option]>,
HelpText<"Replace returns with jumps to ``__x86_return_thunk`` (x86 only, error otherwise)">,
diff --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp
index 29f5cd14e46e11..521e417b8a6ea1 100644
--- a/clang/lib/Basic/TargetInfo.cpp
+++ b/clang/lib/Basic/TargetInfo.cpp
@@ -198,6 +198,21 @@ TargetInfo::checkCFProtectionBranchSupported(DiagnosticsEngine &Diags) const {
return false;
}
+CFBranchLabelSchemeKind TargetInfo::getDefaultCFBranchLabelScheme() const {
+ // if this hook is called, the target should override it to return a
+ // non-default scheme
+ llvm::report_fatal_error("not implemented");
+}
+
+bool TargetInfo::checkCFBranchLabelSchemeSupported(
+ const CFBranchLabelSchemeKind Scheme, DiagnosticsEngine &Diags) const {
+ Diags.Report(diag::err_opt_not_valid_on_target)
+ << (Twine("mcf-branch-label-scheme=") +
+ getCFBranchLabelSchemeFlagVal(Scheme))
+ .str();
+ return false;
+}
+
bool
TargetInfo::checkCFProtectionReturnSupported(DiagnosticsEngine &Diags) const {
Diags.Report(diag::err_opt_not_valid_on_target) << "cf-protection=return";
diff --git a/clang/lib/Basic/Targets/RISCV.h b/clang/lib/Basic/Targets/RISCV.h
index 351ef21e197c4d..bf40edb8683b3e 100644
--- a/clang/lib/Basic/Targets/RISCV.h
+++ b/clang/lib/Basic/Targets/RISCV.h
@@ -134,6 +134,28 @@ class RISCVTargetInfo : public TargetInfo {
bool validateGlobalRegisterVariable(StringRef RegName, unsigned RegSize,
bool &HasSizeMismatch) const override;
+
+ bool checkCFProtectionBranchSupported(DiagnosticsEngine &) const override {
+ // Always generate Zicfilp lpad insns
+ // Non-zicfilp CPUs would read them as NOP
+ return true;
+ }
+
+ CFBranchLabelSchemeKind getDefaultCFBranchLabelScheme() const override {
+ return CFBranchLabelSchemeKind::FuncSig;
+ }
+
+ bool
+ checkCFBranchLabelSchemeSupported(const CFBranchLabelSchemeKind Scheme,
+ DiagnosticsEngine &Diags) const override {
+ switch (Scheme) {
+ case CFBranchLabelSchemeKind::Default:
+ case CFBranchLabelSchemeKind::Unlabeled:
+ case CFBranchLabelSchemeKind::FuncSig:
+ return true;
+ }
+ return TargetInfo::checkCFBranchLabelSchemeSupported(Scheme, Diags);
+ }
};
class LLVM_LIBRARY_VISIBILITY RISCV32TargetInfo : public RISCVTargetInfo {
public:
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index d53d47979f29fb..2381fa93e23fea 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -1164,6 +1164,16 @@ void CodeGenModule::Release() {
// Indicate that we want to instrument branch control flow protection.
getModule().addModuleFlag(llvm::Module::Min, "cf-protection-branch",
1);
+
+ auto Scheme = CodeGenOpts.getCFBranchLabelScheme();
+ if (Target.checkCFBranchLabelSchemeSupported(Scheme, getDiags())) {
+ if (Scheme == CFBranchLabelSchemeKind::Default)
+ Scheme = Target.getDefaultCFBranchLabelScheme();
+ getModule().addModuleFlag(
+ llvm::Module::Error, "cf-branch-label-scheme",
+ llvm::MDString::get(getLLVMContext(),
+ getCFBranchLabelSchemeFlagVal(Scheme)));
+ }
}
if (CodeGenOpts.FunctionReturnThunks)
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 0bab48caf1a5e2..d3c5c3d9872ee4 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -7012,6 +7012,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Arg *A = Args.getLastArg(options::OPT_fcf_protection_EQ)) {
CmdArgs.push_back(
Args.MakeArgString(Twine("-fcf-protection=") + A->getValue()));
+
+ if (Arg *SA = Args.getLastArg(options::OPT_mcf_branch_label_scheme_EQ))
+ CmdArgs.push_back(Args.MakeArgString(Twine("-mcf-branch-label-scheme=") +
+ SA->getValue()));
}
if (Arg *A = Args.getLastArg(options::OPT_mfunction_return_EQ))
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index efd852593468aa..6c09843a7146f4 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -1688,6 +1688,18 @@ void CompilerInvocationBase::GenerateCodeGenArgs(const CodeGenOptions &Opts,
else if (Opts.CFProtectionBranch)
GenerateArg(Consumer, OPT_fcf_protection_EQ, "branch");
+ if (Opts.CFProtectionBranch) {
+ switch (Opts.getCFBranchLabelScheme()) {
+ case CFBranchLabelSchemeKind::Default:
+ break;
+#define CF_BRANCH_LABEL_SCHEME(Kind, FlagVal) \
+ case CFBranchLabelSchemeKind::Kind: \
+ GenerateArg(Consumer, OPT_mcf_branch_label_scheme_EQ, #FlagVal); \
+ break;
+#include "clang/Basic/CFProtectionOptions.def"
+ }
+ }
+
if (Opts.FunctionReturnThunks)
GenerateArg(Consumer, OPT_mfunction_return_EQ, "thunk-extern");
@@ -2022,6 +2034,22 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name;
}
+ if (Opts.CFProtectionBranch && T.isRISCV()) {
+ if (const Arg *A = Args.getLastArg(OPT_mcf_branch_label_scheme_EQ)) {
+ const auto Scheme =
+ llvm::StringSwitch<CFBranchLabelSchemeKind>(A->getValue())
+#define CF_BRANCH_LABEL_SCHEME(Kind, FlagVal) \
+ .Case(#FlagVal, CFBranchLabelSchemeKind::Kind)
+#include "clang/Basic/CFProtectionOptions.def"
+ .Default(CFBranchLabelSchemeKind::Default);
+ if (Scheme != CFBranchLabelSchemeKind::Default)
+ Opts.setCFBranchLabelScheme(Scheme);
+ else
+ Diags.Report(diag::err_drv_invalid_value)
+ << A->getAsString(Args) << A->getValue();
+ }
+ }
+
if (const Arg *A = Args.getLastArg(OPT_mfunction_return_EQ)) {
auto Val = llvm::StringSwitch<llvm::FunctionReturnThunksKind>(A->getValue())
.Case("keep", llvm::FunctionReturnThunksKind::Keep)
@@ -3952,6 +3980,18 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args,
}
}
+ if (Opts.CFProtectionBranch) {
+ if (const Arg *A = Args.getLastArg(OPT_mcf_branch_label_scheme_EQ)) {
+ const auto Scheme =
+ llvm::StringSwitch<CFBranchLabelSchemeKind>(A->getValue())
+#define CF_BRANCH_LABEL_SCHEME(Kind, FlagVal) \
+ .Case(#FlagVal, CFBranchLabelSchemeKind::Kind)
+#include "clang/Basic/CFProtectionOptions.def"
+ .Default(CFBranchLabelSchemeKind::Default);
+ Opts.setCFBranchLabelScheme(Scheme);
+ }
+ }
+
if ((Args.hasArg(OPT_fsycl_is_device) || Args.hasArg(OPT_fsycl_is_host)) &&
!Args.hasArg(OPT_sycl_std_EQ)) {
// If the user supplied -fsycl-is-device or -fsycl-is-host, but failed to
diff --git a/clang/test/CodeGen/RISCV/riscv-cf-protection.c b/clang/test/CodeGen/RISCV/riscv-cf-protection.c
new file mode 100644
index 00000000000000..3a9855a3d2f011
--- /dev/null
+++ b/clang/test/CodeGen/RISCV/riscv-cf-protection.c
@@ -0,0 +1,94 @@
+// RUN: %clang --target=riscv32 -menable-experimental-extensions \
+// RUN: -march=rv32i_zicfilp1p0 -fcf-protection=branch \
+// RUN: -mcf-branch-label-scheme=unlabeled -S -emit-llvm %s -o - | FileCheck \
+// RUN: --check-prefixes=BRANCH-PROT-FLAG,UNLABELED-FLAG %s
+
+// RUN: %clang --target=riscv32 -menable-experimental-extensions \
+// RUN: -march=rv32i_zicfilp1p0 -fcf-protection=branch \
+// RUN: -mcf-branch-label-scheme=func-sig -S -emit-llvm %s -o - | FileCheck \
+// RUN: --check-prefixes=BRANCH-PROT-FLAG,FUNC-SIG-FLAG %s
+
+// RUN: %clang --target=riscv32 -menable-experimental-extensions \
+// RUN: -march=rv32i_zicfilp1p0 -mcf-branch-label-scheme=unlabeled -S \
+// RUN: -emit-llvm %s -o - 2>&1 | FileCheck \
+// RUN: --check-prefixes=NO-FLAG,UNLABELED-SCHEME-UNUSED %s
+
+// RUN: %clang --target=riscv32 -menable-experimental-extensions \
+// RUN: -march=rv32i_zicfilp1p0 -mcf-branch-label-scheme=func-sig -S \
+// RUN: -emit-llvm %s -o - 2>&1 | FileCheck \
+// RUN: --check-prefixes=NO-FLAG,FUNC-SIG-SCHEME-UNUSED %s
+
+// RUN: %clang --target=riscv32 -fcf-protection=branch \
+// RUN: -mcf-branch-label-scheme=unlabeled -S -emit-llvm %s -o - | FileCheck \
+// RUN: --check-prefixes=BRANCH-PROT-FLAG,UNLABELED-FLAG %s
+
+// RUN: %clang --target=riscv32 -fcf-protection=branch \
+// RUN: -mcf-branch-label-scheme=func-sig -S -emit-llvm %s -o - | FileCheck \
+// RUN: --check-prefixes=BRANCH-PROT-FLAG,FUNC-SIG-FLAG %s
+
+// RUN: %clang --target=riscv32 -mcf-branch-label-scheme=unlabeled -S \
+// RUN: -emit-llvm %s -o - 2>&1 | FileCheck \
+// RUN: --check-prefixes=NO-FLAG,UNLABELED-SCHEME-UNUSED %s
+
+// RUN: %clang --target=riscv32 -mcf-branch-label-scheme=func-sig -S \
+// RUN: -emit-llvm %s -o - 2>&1 | FileCheck \
+// RUN: --check-prefixes=NO-FLAG,FUNC-SIG-SCHEME-UNUSED %s
+
+// RUN: %clang --target=riscv64 -menable-experimental-extensions \
+// RUN: -march=rv64i_zicfilp1p0 -fcf-protection=branch \
+// RUN: -mcf-branch-label-scheme=unlabeled -S -emit-llvm %s -o - | FileCheck \
+// RUN: --check-prefixes=BRANCH-PROT-FLAG,UNLABELED-FLAG %s
+
+// RUN: %clang --target=riscv64 -menable-experimental-extensions \
+// RUN: -march=rv64i_zicfilp1p0 -fcf-protection=branch \
+// RUN: -mcf-branch-label-scheme=func-sig -S -emit-llvm %s -o - | FileCheck \
+// RUN: --check-prefixes=BRANCH-PROT-FLAG,FUNC-SIG-FLAG %s
+
+// RUN: %clang --target=riscv64 -menable-experimental-extensions \
+// RUN: -march=rv64i_zicfilp1p0 -mcf-branch-label-scheme=unlabeled -S \
+// RUN: -emit-llvm %s -o - 2>&1 | FileCheck \
+// RUN: --check-prefixes=NO-FLAG,UNLABELED-SCHEME-UNUSED %s
+
+// RUN: %clang --target=riscv64 -menable-experimental-extensions \
+// RUN: -march=rv64i_zicfilp1p0 -mcf-branch-label-scheme=func-sig -S \
+// RUN: -emit-llvm %s -o - 2>&1 | FileCheck \
+// RUN: --check-prefixes=NO-FLAG,FUNC-SIG-SCHEME-UNUSED %s
+
+// RUN: %clang --target=riscv64 -fcf-protection=branch \
+// RUN: -mcf-branch-label-scheme=unlabeled -S -emit-llvm %s -o - | FileCheck \
+// RUN: --check-prefixes=BRANCH-PROT-FLAG,UNLABELED-FLAG %s
+
+// RUN: %clang --target=riscv64 -fcf-protection=branch \
+// RUN: -mcf-branch-label-scheme=func-sig -S -emit-llvm %s -o - | FileCheck \
+// RUN: --check-prefixes=BRANCH-PROT-FLAG,FUNC-SIG-FLAG %s
+
+// RUN: %clang --target=riscv64 -mcf-branch-label-scheme=unlabeled -S \
+// RUN: -emit-llvm %s -o - 2>&1 | FileCheck \
+// RUN: --check-prefixes=NO-FLAG,UNLABELED-SCHEME-UNUSED %s
+
+// RUN: %clang --target=riscv64 -mcf-branch-label-scheme=func-sig -S \
+// RUN: -emit-llvm %s -o - 2>&1 | FileCheck \
+// RUN: --check-prefixes=NO-FLAG,FUNC-SIG-SCHEME-UNUSED %s
+
+// Default -mcf-branch-label-scheme is func-sig
+// RUN: %clang --target=riscv32 -fcf-protection=branch -S -emit-llvm %s -o - \
+// RUN: | FileCheck --check-prefixes=BRANCH-PROT-FLAG,FUNC-SIG-FLAG %s
+
+// Default -mcf-branch-label-scheme is func-sig
+// RUN: %clang --target=riscv64 -fcf-protection=branch -S -emit-llvm %s -o - \
+// RUN: | FileCheck --check-prefixes=BRANCH-PROT-FLAG,FUNC-SIG-FLAG %s
+
+// UNLABELED-SCHEME-UNUSED: warning: argument unused during compilation:
+// UNLABELED-SCHEME-UNUSED-SAME: '-mcf-branch-label-scheme=unlabeled'
+// FUNC-SIG-SCHEME-UNUSED: warning: argument unused during compilation:
+// FUNC-SIG-SCHEME-UNUSED-SAME: '-mcf-branch-label-scheme=func-sig'
+
+// BRANCH-PROT-FLAG-DAG: [[P_FLAG:![0-9]+]] = !{i32 8, !"cf-protection-branch", i32 1}
+// UNLABELED-FLAG-DAG: [[S_FLAG:![0-9]+]] = !{i32 1, !"cf-branch-label-scheme", !"unlabeled"}
+// FUNC-SIG-FLAG-DAG: [[S_FLAG:![0-9]+]] = !{i32 1, !"cf-branch-label-scheme", !"func-sig"}
+// BRANCH-PROT-FLAG-DAG: !llvm.module.flags = !{{[{].*}}[[P_FLAG]]{{.*, }}[[S_FLAG]]{{(,.+)?[}]}}
+// NO-FLAG-NOT: !{i32 8, !"cf-protection-branch", i32 1}
+// NO-FLAG-NOT: !{i32 8, !"cf-branch-label-scheme", !"unlabeled"}
+// NO-FLAG-NOT: !{i32 8, !"cf-branch-label-scheme", !"func-sig"}
+
+int main() { return 0; }
>From f87c51a78c976d344360ce769156f7947e95a49b Mon Sep 17 00:00:00 2001
From: Ming-Yi Lai <ming-yi.lai at mediatek.com>
Date: Fri, 10 May 2024 14:16:59 +0800
Subject: [PATCH 2/2] [clang][RISCV] Add Zicfilp CFI scheme preprocessor macros
These macros allow assembly files to know which CFI label to use when the target
has Zicfilp enabled.
---
clang/lib/Basic/Targets/RISCV.cpp | 19 +++++
.../test/CodeGen/RISCV/riscv-cf-protection.c | 79 +++++++++++++++++++
2 files changed, 98 insertions(+)
diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp
index b6ea4440507ea1..b9199e3bc77d34 100644
--- a/clang/lib/Basic/Targets/RISCV.cpp
+++ b/clang/lib/Basic/Targets/RISCV.cpp
@@ -224,6 +224,25 @@ void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts,
else
Builder.defineMacro("__riscv_32e");
}
+
+ if (Opts.CFProtectionBranch) {
+ auto Scheme = Opts.getCFBranchLabelScheme();
+ if (Scheme == CFBranchLabelSchemeKind::Default)
+ Scheme = getDefaultCFBranchLabelScheme();
+
+ Builder.defineMacro("__riscv_landing_pad", "1");
+ switch (Scheme) {
+ case CFBranchLabelSchemeKind::Unlabeled:
+ Builder.defineMacro("__riscv_landing_pad_unlabeled", "1");
+ break;
+ case CFBranchLabelSchemeKind::FuncSig:
+ Builder.defineMacro("__riscv_landing_pad_func_sig", "1");
+ break;
+ case CFBranchLabelSchemeKind::Default:
+ llvm_unreachable("default cf-branch-label scheme should already be "
+ "transformed to other scheme");
+ }
+ }
}
static constexpr Builtin::Info BuiltinInfo[] = {
diff --git a/clang/test/CodeGen/RISCV/riscv-cf-protection.c b/clang/test/CodeGen/RISCV/riscv-cf-protection.c
index 3a9855a3d2f011..db7b65061658c0 100644
--- a/clang/test/CodeGen/RISCV/riscv-cf-protection.c
+++ b/clang/test/CodeGen/RISCV/riscv-cf-protection.c
@@ -1,71 +1,143 @@
+// RUN: %clang --target=riscv32 -menable-experimental-extensions \
+// RUN: -march=rv32i_zicfilp1p0 -fcf-protection=branch \
+// RUN: -mcf-branch-label-scheme=unlabeled -E -dM %s -o - | FileCheck \
+// RUN: --check-prefixes=LPAD-MACRO,UNLABELED-MACRO %s
+
// RUN: %clang --target=riscv32 -menable-experimental-extensions \
// RUN: -march=rv32i_zicfilp1p0 -fcf-protection=branch \
// RUN: -mcf-branch-label-scheme=unlabeled -S -emit-llvm %s -o - | FileCheck \
// RUN: --check-prefixes=BRANCH-PROT-FLAG,UNLABELED-FLAG %s
+// RUN: %clang --target=riscv32 -menable-experimental-extensions \
+// RUN: -march=rv32i_zicfilp1p0 -fcf-protection=branch \
+// RUN: -mcf-branch-label-scheme=func-sig -E -dM %s -o - | FileCheck \
+// RUN: --check-prefixes=LPAD-MACRO,FUNC-SIG-MACRO %s
+
// RUN: %clang --target=riscv32 -menable-experimental-extensions \
// RUN: -march=rv32i_zicfilp1p0 -fcf-protection=branch \
// RUN: -mcf-branch-label-scheme=func-sig -S -emit-llvm %s -o - | FileCheck \
// RUN: --check-prefixes=BRANCH-PROT-FLAG,FUNC-SIG-FLAG %s
+// RUN: %clang --target=riscv32 -menable-experimental-extensions \
+// RUN: -march=rv32i_zicfilp1p0 -mcf-branch-label-scheme=unlabeled -E -dM %s \
+// RUN: -o - 2>&1 | FileCheck \
+// RUN: --check-prefixes=NO-MACRO,UNLABELED-SCHEME-UNUSED %s
+
// RUN: %clang --target=riscv32 -menable-experimental-extensions \
// RUN: -march=rv32i_zicfilp1p0 -mcf-branch-label-scheme=unlabeled -S \
// RUN: -emit-llvm %s -o - 2>&1 | FileCheck \
// RUN: --check-prefixes=NO-FLAG,UNLABELED-SCHEME-UNUSED %s
+// RUN: %clang --target=riscv32 -menable-experimental-extensions \
+// RUN: -march=rv32i_zicfilp1p0 -mcf-branch-label-scheme=func-sig -E -dM %s \
+// RUN: -o - 2>&1 | FileCheck \
+// RUN: --check-prefixes=NO-MACRO,FUNC-SIG-SCHEME-UNUSED %s
+
// RUN: %clang --target=riscv32 -menable-experimental-extensions \
// RUN: -march=rv32i_zicfilp1p0 -mcf-branch-label-scheme=func-sig -S \
// RUN: -emit-llvm %s -o - 2>&1 | FileCheck \
// RUN: --check-prefixes=NO-FLAG,FUNC-SIG-SCHEME-UNUSED %s
+// RUN: %clang --target=riscv32 -fcf-protection=branch \
+// RUN: -mcf-branch-label-scheme=unlabeled -E -dM -emit-llvm %s -o - | \
+// RUN: FileCheck --check-prefixes=LPAD-MACRO,UNLABELED-MACRO %s
+
// RUN: %clang --target=riscv32 -fcf-protection=branch \
// RUN: -mcf-branch-label-scheme=unlabeled -S -emit-llvm %s -o - | FileCheck \
// RUN: --check-prefixes=BRANCH-PROT-FLAG,UNLABELED-FLAG %s
+// RUN: %clang --target=riscv32 -fcf-protection=branch \
+// RUN: -mcf-branch-label-scheme=func-sig -E -dM %s -o - | FileCheck \
+// RUN: --check-prefixes=LPAD-MACRO,FUNC-SIG-MACRO %s
+
// RUN: %clang --target=riscv32 -fcf-protection=branch \
// RUN: -mcf-branch-label-scheme=func-sig -S -emit-llvm %s -o - | FileCheck \
// RUN: --check-prefixes=BRANCH-PROT-FLAG,FUNC-SIG-FLAG %s
+// RUN: %clang --target=riscv32 -mcf-branch-label-scheme=unlabeled -E -dM %s \
+// RUN: -o - 2>&1 | FileCheck \
+// RUN: --check-prefixes=NO-MACRO,UNLABELED-SCHEME-UNUSED %s
+
// RUN: %clang --target=riscv32 -mcf-branch-label-scheme=unlabeled -S \
// RUN: -emit-llvm %s -o - 2>&1 | FileCheck \
// RUN: --check-prefixes=NO-FLAG,UNLABELED-SCHEME-UNUSED %s
+// RUN: %clang --target=riscv32 -mcf-branch-label-scheme=func-sig -E -dM %s \
+// RUN: -o - 2>&1 | FileCheck \
+// RUN: --check-prefixes=NO-MACRO,FUNC-SIG-SCHEME-UNUSED %s
+
// RUN: %clang --target=riscv32 -mcf-branch-label-scheme=func-sig -S \
// RUN: -emit-llvm %s -o - 2>&1 | FileCheck \
// RUN: --check-prefixes=NO-FLAG,FUNC-SIG-SCHEME-UNUSED %s
+// RUN: %clang --target=riscv64 -menable-experimental-extensions \
+// RUN: -march=rv64i_zicfilp1p0 -fcf-protection=branch \
+// RUN: -mcf-branch-label-scheme=unlabeled -E -dM %s -o - | FileCheck \
+// RUN: --check-prefixes=LPAD-MACRO,UNLABELED-MACRO %s
+
// RUN: %clang --target=riscv64 -menable-experimental-extensions \
// RUN: -march=rv64i_zicfilp1p0 -fcf-protection=branch \
// RUN: -mcf-branch-label-scheme=unlabeled -S -emit-llvm %s -o - | FileCheck \
// RUN: --check-prefixes=BRANCH-PROT-FLAG,UNLABELED-FLAG %s
+// RUN: %clang --target=riscv64 -menable-experimental-extensions \
+// RUN: -march=rv64i_zicfilp1p0 -fcf-protection=branch \
+// RUN: -mcf-branch-label-scheme=func-sig -E -dM %s -o - | FileCheck \
+// RUN: --check-prefixes=LPAD-MACRO,FUNC-SIG-MACRO %s
+
// RUN: %clang --target=riscv64 -menable-experimental-extensions \
// RUN: -march=rv64i_zicfilp1p0 -fcf-protection=branch \
// RUN: -mcf-branch-label-scheme=func-sig -S -emit-llvm %s -o - | FileCheck \
// RUN: --check-prefixes=BRANCH-PROT-FLAG,FUNC-SIG-FLAG %s
+// RUN: %clang --target=riscv64 -menable-experimental-extensions \
+// RUN: -march=rv64i_zicfilp1p0 -mcf-branch-label-scheme=unlabeled -E -dM %s \
+// RUN: -o - 2>&1 | FileCheck \
+// RUN: --check-prefixes=NO-MACRO,UNLABELED-SCHEME-UNUSED %s
+
// RUN: %clang --target=riscv64 -menable-experimental-extensions \
// RUN: -march=rv64i_zicfilp1p0 -mcf-branch-label-scheme=unlabeled -S \
// RUN: -emit-llvm %s -o - 2>&1 | FileCheck \
// RUN: --check-prefixes=NO-FLAG,UNLABELED-SCHEME-UNUSED %s
+// RUN: %clang --target=riscv64 -menable-experimental-extensions \
+// RUN: -march=rv64i_zicfilp1p0 -mcf-branch-label-scheme=func-sig -E -dM %s \
+// RUN: -o - 2>&1 | FileCheck \
+// RUN: --check-prefixes=NO-MACRO,FUNC-SIG-SCHEME-UNUSED %s
+
// RUN: %clang --target=riscv64 -menable-experimental-extensions \
// RUN: -march=rv64i_zicfilp1p0 -mcf-branch-label-scheme=func-sig -S \
// RUN: -emit-llvm %s -o - 2>&1 | FileCheck \
// RUN: --check-prefixes=NO-FLAG,FUNC-SIG-SCHEME-UNUSED %s
+// RUN: %clang --target=riscv64 -fcf-protection=branch \
+// RUN: -mcf-branch-label-scheme=unlabeled -E -dM %s -o - | FileCheck \
+// RUN: --check-prefixes=LPAD-MACRO,UNLABELED-MACRO %s
+
// RUN: %clang --target=riscv64 -fcf-protection=branch \
// RUN: -mcf-branch-label-scheme=unlabeled -S -emit-llvm %s -o - | FileCheck \
// RUN: --check-prefixes=BRANCH-PROT-FLAG,UNLABELED-FLAG %s
+// RUN: %clang --target=riscv64 -fcf-protection=branch \
+// RUN: -mcf-branch-label-scheme=func-sig -E -dM %s -o - | FileCheck \
+// RUN: --check-prefixes=LPAD-MACRO,FUNC-SIG-MACRO %s
+
// RUN: %clang --target=riscv64 -fcf-protection=branch \
// RUN: -mcf-branch-label-scheme=func-sig -S -emit-llvm %s -o - | FileCheck \
// RUN: --check-prefixes=BRANCH-PROT-FLAG,FUNC-SIG-FLAG %s
+// RUN: %clang --target=riscv64 -mcf-branch-label-scheme=unlabeled -E -dM %s \
+// RUN: -o - 2>&1 | FileCheck \
+// RUN: --check-prefixes=NO-MACRO,UNLABELED-SCHEME-UNUSED %s
+
// RUN: %clang --target=riscv64 -mcf-branch-label-scheme=unlabeled -S \
// RUN: -emit-llvm %s -o - 2>&1 | FileCheck \
// RUN: --check-prefixes=NO-FLAG,UNLABELED-SCHEME-UNUSED %s
+// RUN: %clang --target=riscv64 -mcf-branch-label-scheme=func-sig -E -dM %s \
+// RUN: -o - 2>&1 | FileCheck \
+// RUN: --check-prefixes=NO-MACRO,FUNC-SIG-SCHEME-UNUSED %s
+
// RUN: %clang --target=riscv64 -mcf-branch-label-scheme=func-sig -S \
// RUN: -emit-llvm %s -o - 2>&1 | FileCheck \
// RUN: --check-prefixes=NO-FLAG,FUNC-SIG-SCHEME-UNUSED %s
@@ -83,6 +155,13 @@
// FUNC-SIG-SCHEME-UNUSED: warning: argument unused during compilation:
// FUNC-SIG-SCHEME-UNUSED-SAME: '-mcf-branch-label-scheme=func-sig'
+// LPAD-MACRO: __riscv_landing_pad 1{{$}}
+// UNLABELED-MACRO: __riscv_landing_pad_unlabeled 1{{$}}
+// FUNC-SIG-MACRO: __riscv_landing_pad_func_sig 1{{$}}
+// NO-MACRO-NOT: __riscv_landing_pad
+// NO-MACRO-NOT: __riscv_landing_pad_unlabeled
+// NO-MACRO-NOT: __riscv_landing_pad_func_sig
+
// BRANCH-PROT-FLAG-DAG: [[P_FLAG:![0-9]+]] = !{i32 8, !"cf-protection-branch", i32 1}
// UNLABELED-FLAG-DAG: [[S_FLAG:![0-9]+]] = !{i32 1, !"cf-branch-label-scheme", !"unlabeled"}
// FUNC-SIG-FLAG-DAG: [[S_FLAG:![0-9]+]] = !{i32 1, !"cf-branch-label-scheme", !"func-sig"}
More information about the cfe-commits
mailing list