[llvm] [RISCV][Zicfilp] Codegen LPAD insns by looking at module flags (PR #152121)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 5 04:07:01 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-risc-v
Author: Ming-Yi Lai (mylai-mtk)
<details>
<summary>Changes</summary>
Expected Behavior:
Stop codegening LPAD insns by testing if the target has the Zicfilp extension and instead, codegen LPAD insns if the LLVM module has all of these flags:
+ `cf-protection-branch`: Needs to be a non-zero integer (which means `true`)
+ `cf-branch-label-scheme`: Needs to be `unlabeled`
Context:
In clang, Zicfilp-based control flow integrity (the `unlabeled` scheme) can now be enabled by giving the `-fcf-protection=branch
-mcf-branch-label-scheme=unlabeled` options. With these options, the clang frontend adds the above-mentioned flags to LLVM modules. Here we want to align LPAD insn codegen to be enabled by the semantics of those LLVM module flags, instead of relying on the inaccurate indicator of whether the Zicfilp extension is available, so the toolchain's behavior is more streamlined and expected.
Also, since LPAD insns can be executed regardless of whether Zicfilp is available in target or not (due to LPAD insn being encoded as a standard hint insn), clang accepts the above-mentioned CLI options even if Zicfilp is not enabled and expects backend to still generate LPAD insns. This patch enables LPAD insn generation in such cases.
---
Full diff: https://github.com/llvm/llvm-project/pull/152121.diff
3 Files Affected:
- (modified) llvm/include/llvm/Support/RISCVISAUtils.h (+19)
- (modified) llvm/lib/Target/RISCV/RISCVIndirectBranchTracking.cpp (+20-1)
- (modified) llvm/test/CodeGen/RISCV/lpad.ll (+5)
``````````diff
diff --git a/llvm/include/llvm/Support/RISCVISAUtils.h b/llvm/include/llvm/Support/RISCVISAUtils.h
index 165bb08d66431..e2dd833de74fd 100644
--- a/llvm/include/llvm/Support/RISCVISAUtils.h
+++ b/llvm/include/llvm/Support/RISCVISAUtils.h
@@ -14,7 +14,9 @@
#define LLVM_SUPPORT_RISCVISAUTILS_H
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/Compiler.h"
+#include <cassert>
#include <map>
#include <string>
@@ -43,6 +45,23 @@ struct ExtensionComparator {
typedef std::map<std::string, ExtensionVersion, ExtensionComparator>
OrderedExtensionMap;
+enum class ZicfilpLabelSchemeKind {
+ Invalid,
+ Unlabeled,
+ FuncSig,
+};
+
+// See clang::getCFBranchLabelSchemeFlagVal() for possible CFBranchLabelScheme
+inline ZicfilpLabelSchemeKind
+getZicfilpLabelScheme(const StringRef CFBranchLabelScheme) {
+ const auto Ret = StringSwitch<ZicfilpLabelSchemeKind>(CFBranchLabelScheme)
+ .Case("unlabeled", ZicfilpLabelSchemeKind::Unlabeled)
+ .Case("func-sig", ZicfilpLabelSchemeKind::FuncSig)
+ .Default(ZicfilpLabelSchemeKind::Invalid);
+ assert(Ret != ZicfilpLabelSchemeKind::Invalid);
+ return Ret;
+}
+
} // namespace RISCVISAUtils
} // namespace llvm
diff --git a/llvm/lib/Target/RISCV/RISCVIndirectBranchTracking.cpp b/llvm/lib/Target/RISCV/RISCVIndirectBranchTracking.cpp
index 43621b8f0f33d..554f7d5494731 100644
--- a/llvm/lib/Target/RISCV/RISCVIndirectBranchTracking.cpp
+++ b/llvm/lib/Target/RISCV/RISCVIndirectBranchTracking.cpp
@@ -19,11 +19,14 @@
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/RISCVISAUtils.h"
#define DEBUG_TYPE "riscv-indrect-branch-tracking"
#define PASS_NAME "RISC-V Indirect Branch Tracking"
using namespace llvm;
+using namespace llvm::RISCVISAUtils;
cl::opt<uint32_t> PreferredLandingPadLabel(
"riscv-landing-pad-label", cl::ReallyHidden,
@@ -64,9 +67,25 @@ static void emitLpad(MachineBasicBlock &MBB, const RISCVInstrInfo *TII,
bool RISCVIndirectBranchTracking::runOnMachineFunction(MachineFunction &MF) {
const auto &Subtarget = MF.getSubtarget<RISCVSubtarget>();
const RISCVInstrInfo *TII = Subtarget.getInstrInfo();
- if (!Subtarget.hasStdExtZicfilp())
+
+ const Module *const M = MF.getFunction().getParent();
+ if (!M)
+ return false;
+ if (const Metadata *const Flag = M->getModuleFlag("cf-protection-branch");
+ !Flag || mdconst::extract<ConstantInt>(Flag)->isZero())
return false;
+ StringRef CFBranchLabelScheme;
+ if (const Metadata *const MD = M->getModuleFlag("cf-branch-label-scheme"))
+ CFBranchLabelScheme = cast<MDString>(MD)->getString();
+ else
+ report_fatal_error("missing cf-branch-label-scheme module flag");
+
+ const ZicfilpLabelSchemeKind Scheme =
+ getZicfilpLabelScheme(CFBranchLabelScheme);
+ if (Scheme != ZicfilpLabelSchemeKind::Unlabeled)
+ report_fatal_error("unsupported cf-branch-label-scheme module flag");
+
uint32_t FixedLabel = 0;
if (PreferredLandingPadLabel.getNumOccurrences() > 0) {
if (!isUInt<20>(PreferredLandingPadLabel))
diff --git a/llvm/test/CodeGen/RISCV/lpad.ll b/llvm/test/CodeGen/RISCV/lpad.ll
index 93eda6f10eedb..f69b4dad068b5 100644
--- a/llvm/test/CodeGen/RISCV/lpad.ll
+++ b/llvm/test/CodeGen/RISCV/lpad.ll
@@ -289,3 +289,8 @@ define void @interrupt() "interrupt"="machine" {
; FIXED-ONE-NEXT: mret
ret void
}
+
+!llvm.module.flags = !{!0, !1}
+
+!0 = !{i32 8, !"cf-protection-branch", i32 1}
+!1 = !{i32 1, !"cf-branch-label-scheme", !"unlabeled"}
``````````
</details>
https://github.com/llvm/llvm-project/pull/152121
More information about the llvm-commits
mailing list