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