https://github.com/mylai-mtk created 
https://github.com/llvm/llvm-project/pull/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.

>From 0132cefefee074e7ad37946132ac59906b6acd6f Mon Sep 17 00:00:00 2001
From: Ming-Yi Lai <ming-yi....@mediatek.com>
Date: Tue, 5 Aug 2025 16:30:12 +0800
Subject: [PATCH] [clang][RISCV][Zicfilp] Force user to use
 `-mcf-branch-label-scheme=unlabeled`

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.
---
 .../clang/Basic/DiagnosticCommonKinds.td      |  2 +
 clang/lib/Basic/Targets/RISCV.cpp             | 28 ++++++++++++++
 clang/lib/Basic/Targets/RISCV.h               | 10 +----
 .../test/CodeGen/RISCV/riscv-cf-protection.c  | 37 ++++++++++---------
 4 files changed, 51 insertions(+), 26 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td 
b/clang/include/clang/Basic/DiagnosticCommonKinds.td
index 0bd8a423c393e..a8e7a49fcbff4 100644
--- a/clang/include/clang/Basic/DiagnosticCommonKinds.td
+++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td
@@ -356,6 +356,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_sugguest : 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 a6a5ec4b325bc..1120740529eed 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>
@@ -640,3 +641,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_sugguest)
+        << (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 58bfad128ce2c..dc680ea838b12 100644
--- a/clang/lib/Basic/Targets/RISCV.h
+++ b/clang/lib/Basic/Targets/RISCV.h
@@ -158,15 +158,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..17ed4af08da38 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"}

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to