[clang] f341dab - [clang][RISCV][Zicfilp] Force user to use `-mcf-branch-label-scheme=unlabeled` (#152122)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Jun 2 03:12:44 PDT 2026
Author: Ming-Yi Lai
Date: 2026-06-02T18:12:39+08:00
New Revision: f341dab9edfa97d7a4a01f9bc0fe981055dc5cc9
URL: https://github.com/llvm/llvm-project/commit/f341dab9edfa97d7a4a01f9bc0fe981055dc5cc9
DIFF: https://github.com/llvm/llvm-project/commit/f341dab9edfa97d7a4a01f9bc0fe981055dc5cc9.diff
LOG: [clang][RISCV][Zicfilp] Force user to use `-mcf-branch-label-scheme=unlabeled` (#152122)
Expected Behavior:
When `-fcf-protection=branch|full` is specified, it's an error to omit
`-mcf-branch-label-scheme=unlabeled`.
Context:
When using forward-edge control flow integrity feature based on the
RISC-V Zicfilp extension, the `-mcf-branch-label-scheme` option selects
the encoding scheme used in the landing pad labels. The spec defines 2
schemes: `func-sig` and `unlabeled`, with the former specified as the
default. However the `func-sig` backend is still under active
development and won't land anytime soon; in the meanwhile, the
`unlabeled` scheme almost has complete support in the toolchain now.
Given that Clang currently accepts and defaults to
`-mcf-branch-label-scheme=func-sig` but doesn't work correctly, we want
to formally forbid the user from using
`-mcf-branch-label-scheme=func-sig` for now until the `func-sig` scheme
is properly supported. We choose to do so by forcing the user to specify
`-mcf-branch-label-scheme=unlabeled` (instead of changing the default to
`unlabeled`) so the default of `func-sig` can be retained according to
the spec and build scripts targeting the current Clang can be
forward-compatible with the Clang that supports the complete `func-sig`
scheme.
Added:
Modified:
clang/include/clang/Basic/DiagnosticCommonKinds.td
clang/lib/Basic/Targets/RISCV.cpp
clang/lib/Basic/Targets/RISCV.h
clang/test/CodeGen/RISCV/riscv-cf-protection.c
Removed:
################################################################################
diff --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td b/clang/include/clang/Basic/DiagnosticCommonKinds.td
index bdbbaffe0a6e1..f2ed2f4698b8d 100644
--- a/clang/include/clang/Basic/DiagnosticCommonKinds.td
+++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td
@@ -363,6 +363,8 @@ def err_opt_not_valid_without_opt : Error<
"option '%0' cannot be specified without '%1'">;
def err_opt_not_valid_on_target : Error<
"option '%0' cannot be specified on this target">;
+def err_opt_unsupported_with_suggest : Error<
+ "option '%0' is unsupported; consider using '%1'">;
def err_invalid_feature_combination : Error<
"invalid feature combination: %0">;
def warn_invalid_feature_combination : Warning<
diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp
index 685925b0773dc..6afef3e2c7c48 100644
--- a/clang/lib/Basic/Targets/RISCV.cpp
+++ b/clang/lib/Basic/Targets/RISCV.cpp
@@ -15,6 +15,7 @@
#include "clang/Basic/MacroBuilder.h"
#include "clang/Basic/TargetBuiltins.h"
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/Twine.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/RISCVTargetParser.h"
#include <optional>
@@ -643,3 +644,30 @@ bool RISCVTargetInfo::validateCpuIs(StringRef CPUName) const {
return llvm::RISCV::hasValidCPUModel(CPUName);
}
+
+bool RISCVTargetInfo::checkCFBranchLabelSchemeSupported(
+ const CFBranchLabelSchemeKind Scheme, DiagnosticsEngine &Diags) const {
+ // TODO: Allow the default func-sig scheme to be selected after backend
+ // implements it
+ switch (Scheme) {
+ case CFBranchLabelSchemeKind::Default:
+ Diags.Report(diag::err_opt_not_valid_without_opt)
+ << "-fcf-protection=branch"
+ << (Twine("-mcf-branch-label-scheme=") +
+ getCFBranchLabelSchemeFlagVal(CFBranchLabelSchemeKind::Unlabeled))
+ .str();
+ return false;
+ case CFBranchLabelSchemeKind::Unlabeled:
+ return true;
+ case CFBranchLabelSchemeKind::FuncSig:
+ Diags.Report(diag::err_opt_unsupported_with_suggest)
+ << (Twine("-mcf-branch-label-scheme=") +
+ getCFBranchLabelSchemeFlagVal(CFBranchLabelSchemeKind::FuncSig))
+ .str()
+ << (Twine("-mcf-branch-label-scheme=") +
+ getCFBranchLabelSchemeFlagVal(CFBranchLabelSchemeKind::Unlabeled))
+ .str();
+ return false;
+ }
+ return TargetInfo::checkCFBranchLabelSchemeSupported(Scheme, Diags);
+}
diff --git a/clang/lib/Basic/Targets/RISCV.h b/clang/lib/Basic/Targets/RISCV.h
index 619d491d379d3..705ee0694038b 100644
--- a/clang/lib/Basic/Targets/RISCV.h
+++ b/clang/lib/Basic/Targets/RISCV.h
@@ -162,15 +162,7 @@ class RISCVTargetInfo : public TargetInfo {
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);
- }
+ DiagnosticsEngine &Diags) const override;
};
class LLVM_LIBRARY_VISIBILITY RISCV32TargetInfo : public RISCVTargetInfo {
public:
diff --git a/clang/test/CodeGen/RISCV/riscv-cf-protection.c b/clang/test/CodeGen/RISCV/riscv-cf-protection.c
index 3a9855a3d2f01..162a50eb0eabd 100644
--- a/clang/test/CodeGen/RISCV/riscv-cf-protection.c
+++ b/clang/test/CodeGen/RISCV/riscv-cf-protection.c
@@ -3,10 +3,10 @@
// 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: not %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: -mcf-branch-label-scheme=func-sig -S -emit-llvm %s 2>&1 | FileCheck \
+// RUN: --check-prefixes=FUNC-SIG-NOSUPPORT %s
// RUN: %clang --target=riscv32 -menable-experimental-extensions \
// RUN: -march=rv32i_zicfilp1p0 -mcf-branch-label-scheme=unlabeled -S \
@@ -22,9 +22,9 @@
// 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: not %clang --target=riscv32 -fcf-protection=branch \
+// RUN: -mcf-branch-label-scheme=func-sig -S -emit-llvm %s 2>&1 | FileCheck \
+// RUN: --check-prefixes=FUNC-SIG-NOSUPPORT %s
// RUN: %clang --target=riscv32 -mcf-branch-label-scheme=unlabeled -S \
// RUN: -emit-llvm %s -o - 2>&1 | FileCheck \
@@ -39,10 +39,10 @@
// 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: not %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: -mcf-branch-label-scheme=func-sig -S -emit-llvm %s 2>&1 | FileCheck \
+// RUN: --check-prefixes=FUNC-SIG-NOSUPPORT %s
// RUN: %clang --target=riscv64 -menable-experimental-extensions \
// RUN: -march=rv64i_zicfilp1p0 -mcf-branch-label-scheme=unlabeled -S \
@@ -58,9 +58,9 @@
// 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: not %clang --target=riscv64 -fcf-protection=branch \
+// RUN: -mcf-branch-label-scheme=func-sig -S -emit-llvm %s 2>&1 | FileCheck \
+// RUN: --check-prefixes=FUNC-SIG-NOSUPPORT %s
// RUN: %clang --target=riscv64 -mcf-branch-label-scheme=unlabeled -S \
// RUN: -emit-llvm %s -o - 2>&1 | FileCheck \
@@ -71,21 +71,24 @@
// 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
+// RUN: not %clang --target=riscv32 -fcf-protection=branch -S -emit-llvm %s 2>&1 \
+// RUN: | FileCheck --check-prefixes=FORCE-UNLABELED %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
+// RUN: not %clang --target=riscv64 -fcf-protection=branch -S -emit-llvm %s 2>&1 \
+// RUN: | FileCheck --check-prefixes=FORCE-UNLABELED %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'
+// FUNC-SIG-NOSUPPORT: error: option '-mcf-branch-label-scheme=func-sig' is
+// FUNC-SIG-NOSUPPORT-SAME: unsupported; consider using '-mcf-branch-label-scheme=unlabeled'
+// FORCE-UNLABELED: error: option '-fcf-protection=branch' cannot be specified
+// FORCE-UNLABELED-SAME: without '-mcf-branch-label-scheme=unlabeled'
// 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"}
More information about the cfe-commits
mailing list