[clang] [llvm] [NFC][win] Use an enum for the cfguard module flag (PR #176461)
Daniel Paoliello via cfe-commits
cfe-commits at lists.llvm.org
Fri Jan 16 15:02:53 PST 2026
https://github.com/dpaoliello updated https://github.com/llvm/llvm-project/pull/176461
>From 703680463ae2b52e0738c8c952a7c41c7b91d5dc Mon Sep 17 00:00:00 2001
From: Daniel Paoliello <danpao at microsoft.com>
Date: Fri, 16 Jan 2026 11:15:38 -0800
Subject: [PATCH] [NFC][win] Use an enum for the cfguard module flag
---
clang/lib/CodeGen/CodeGenModule.cpp | 12 ++++++++----
llvm/include/llvm/IR/Module.h | 3 +++
llvm/include/llvm/Support/CodeGen.h | 10 ++++++++++
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 6 +++---
llvm/lib/CodeGen/CFGuardLongjmp.cpp | 3 ++-
llvm/lib/IR/Module.cpp | 7 +++++++
.../Target/AArch64/AArch64Arm64ECCallLowering.cpp | 9 ++++-----
llvm/lib/Transforms/CFGuard/CFGuard.cpp | 12 +++++-------
8 files changed, 42 insertions(+), 20 deletions(-)
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 614bca627e03c..dc8a31b7f7f0d 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -1122,11 +1122,15 @@ void CodeGenModule::Release() {
getModule().addModuleFlag(llvm::Module::Warning, "CodeViewGHash", 1);
}
if (CodeGenOpts.ControlFlowGuard) {
- // Function ID tables and checks for Control Flow Guard (cfguard=2).
- getModule().addModuleFlag(llvm::Module::Warning, "cfguard", 2);
+ // Function ID tables and checks for Control Flow Guard.
+ getModule().addModuleFlag(
+ llvm::Module::Warning, "cfguard",
+ static_cast<unsigned>(llvm::ControlFlowGuardMode::Enabled));
} else if (CodeGenOpts.ControlFlowGuardNoChecks) {
- // Function ID tables for Control Flow Guard (cfguard=1).
- getModule().addModuleFlag(llvm::Module::Warning, "cfguard", 1);
+ // Function ID tables for Control Flow Guard.
+ getModule().addModuleFlag(
+ llvm::Module::Warning, "cfguard",
+ static_cast<unsigned>(llvm::ControlFlowGuardMode::TableOnly));
}
if (CodeGenOpts.EHContGuard) {
// Function ID tables for EH Continuation Guard.
diff --git a/llvm/include/llvm/IR/Module.h b/llvm/include/llvm/IR/Module.h
index ac6c20b81d68c..7156a83c9f3cc 100644
--- a/llvm/include/llvm/IR/Module.h
+++ b/llvm/include/llvm/IR/Module.h
@@ -1056,6 +1056,9 @@ class LLVM_ABI Module {
/// Get how unwind v2 (epilog) information should be generated for x64
/// Windows.
WinX64EHUnwindV2Mode getWinX64EHUnwindV2Mode() const;
+
+ /// Gets the Control Flow Guard mode.
+ ControlFlowGuardMode getControlFlowGuardMode() const;
};
/// Given "llvm.used" or "llvm.compiler.used" as a global name, collect the
diff --git a/llvm/include/llvm/Support/CodeGen.h b/llvm/include/llvm/Support/CodeGen.h
index 848796ef574f8..65d262a087378 100644
--- a/llvm/include/llvm/Support/CodeGen.h
+++ b/llvm/include/llvm/Support/CodeGen.h
@@ -173,6 +173,16 @@ namespace llvm {
Required = 2,
};
+ enum class ControlFlowGuardMode {
+ // Don't enable Control Flow Guard.
+ Disabled = 0,
+ // Emit the Control Flow Guard tables in the binary, but don't emit any
+ // checks.
+ TableOnly = 1,
+ // Enable Control Flow Guard checks and emit the tables.
+ Enabled = 2,
+ };
+
} // namespace llvm
#endif
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index d96294e06d579..3c758ed006bf5 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -664,8 +664,8 @@ bool AsmPrinter::doInitialization(Module &M) {
if (ES)
Handlers.push_back(std::unique_ptr<EHStreamer>(ES));
- // Emit tables for any value of cfguard flag (i.e. cfguard=1 or cfguard=2).
- if (mdconst::extract_or_null<ConstantInt>(M.getModuleFlag("cfguard")))
+ // All CFG modes required the tables emitted.
+ if (M.getControlFlowGuardMode() != ControlFlowGuardMode::Disabled)
EHHandlers.push_back(std::make_unique<WinCFGuard>(this));
for (auto &Handler : Handlers)
@@ -5088,7 +5088,7 @@ void AsmPrinter::emitCOFFFeatureSymbol(Module &M) {
Feat00Value |= COFF::Feat00Flags::SafeSEH;
}
- if (M.getModuleFlag("cfguard")) {
+ if (M.getControlFlowGuardMode() != ControlFlowGuardMode::Disabled) {
// Object is CFG-aware.
Feat00Value |= COFF::Feat00Flags::GuardCF;
}
diff --git a/llvm/lib/CodeGen/CFGuardLongjmp.cpp b/llvm/lib/CodeGen/CFGuardLongjmp.cpp
index 04de011400568..639d0537c2cc1 100644
--- a/llvm/lib/CodeGen/CFGuardLongjmp.cpp
+++ b/llvm/lib/CodeGen/CFGuardLongjmp.cpp
@@ -62,7 +62,8 @@ FunctionPass *llvm::createCFGuardLongjmpPass() { return new CFGuardLongjmp(); }
bool CFGuardLongjmp::runOnMachineFunction(MachineFunction &MF) {
// Skip modules for which the cfguard flag is not set.
- if (!MF.getFunction().getParent()->getModuleFlag("cfguard"))
+ if (MF.getFunction().getParent()->getControlFlowGuardMode() ==
+ ControlFlowGuardMode::Disabled)
return false;
// Skip functions that do not have calls to _setjmp.
diff --git a/llvm/lib/IR/Module.cpp b/llvm/lib/IR/Module.cpp
index 7360d0fa1f86a..11dc68e0e4751 100644
--- a/llvm/lib/IR/Module.cpp
+++ b/llvm/lib/IR/Module.cpp
@@ -940,3 +940,10 @@ WinX64EHUnwindV2Mode Module::getWinX64EHUnwindV2Mode() const {
return static_cast<WinX64EHUnwindV2Mode>(CI->getZExtValue());
return WinX64EHUnwindV2Mode::Disabled;
}
+
+ControlFlowGuardMode Module::getControlFlowGuardMode() const {
+ Metadata *MD = getModuleFlag("cfguard");
+ if (auto *CI = mdconst::dyn_extract_or_null<ConstantInt>(MD))
+ return static_cast<ControlFlowGuardMode>(CI->getZExtValue());
+ return ControlFlowGuardMode::Disabled;
+}
diff --git a/llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp b/llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp
index d0c4b1b9f83fd..c27a693ceecc1 100644
--- a/llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp
@@ -75,7 +75,7 @@ class AArch64Arm64ECCallLowering : public ModulePass {
bool runOnModule(Module &M) override;
private:
- int cfguard_module_flag = 0;
+ ControlFlowGuardMode CFGuardModuleFlag = ControlFlowGuardMode::Disabled;
FunctionType *GuardFnType = nullptr;
FunctionType *DispatchFnType = nullptr;
Constant *GuardFnCFGlobal = nullptr;
@@ -758,7 +758,8 @@ void AArch64Arm64ECCallLowering::lowerCall(CallBase *CB) {
// Load the global symbol as a pointer to the check function.
Value *GuardFn;
- if (cfguard_module_flag == 2 && !CB->hasFnAttr("guard_nocf"))
+ if ((CFGuardModuleFlag == ControlFlowGuardMode::Enabled) &&
+ !CB->hasFnAttr("guard_nocf"))
GuardFn = GuardFnCFGlobal;
else
GuardFn = GuardFnGlobal;
@@ -794,9 +795,7 @@ bool AArch64Arm64ECCallLowering::runOnModule(Module &Mod) {
M = &Mod;
// Check if this module has the cfguard flag and read its value.
- if (auto *MD =
- mdconst::extract_or_null<ConstantInt>(M->getModuleFlag("cfguard")))
- cfguard_module_flag = MD->getZExtValue();
+ CFGuardModuleFlag = M->getControlFlowGuardMode();
PtrTy = PointerType::getUnqual(M->getContext());
I64Ty = Type::getInt64Ty(M->getContext());
diff --git a/llvm/lib/Transforms/CFGuard/CFGuard.cpp b/llvm/lib/Transforms/CFGuard/CFGuard.cpp
index 5c2d9ddaa76db..28d0eddca7ce2 100644
--- a/llvm/lib/Transforms/CFGuard/CFGuard.cpp
+++ b/llvm/lib/Transforms/CFGuard/CFGuard.cpp
@@ -146,8 +146,8 @@ class CFGuardImpl {
bool runOnFunction(Function &F);
private:
- // Only add checks if the module has the cfguard=2 flag.
- int CFGuardModuleFlag = 0;
+ // Only add checks if the module has them enabled.
+ ControlFlowGuardMode CFGuardModuleFlag = ControlFlowGuardMode::Disabled;
StringRef GuardFnName;
Mechanism GuardMechanism = Mechanism::Check;
FunctionType *GuardFnType = nullptr;
@@ -233,12 +233,10 @@ void CFGuardImpl::insertCFGuardDispatch(CallBase *CB) {
bool CFGuardImpl::doInitialization(Module &M) {
// Check if this module has the cfguard flag and read its value.
- if (auto *MD =
- mdconst::extract_or_null<ConstantInt>(M.getModuleFlag("cfguard")))
- CFGuardModuleFlag = MD->getZExtValue();
+ CFGuardModuleFlag = M.getControlFlowGuardMode();
// Skip modules for which CFGuard checks have been disabled.
- if (CFGuardModuleFlag != 2)
+ if (CFGuardModuleFlag != ControlFlowGuardMode::Enabled)
return false;
// Set up prototypes for the guard check and dispatch functions.
@@ -260,7 +258,7 @@ bool CFGuardImpl::doInitialization(Module &M) {
bool CFGuardImpl::runOnFunction(Function &F) {
// Skip modules for which CFGuard checks have been disabled.
- if (CFGuardModuleFlag != 2)
+ if (CFGuardModuleFlag != ControlFlowGuardMode::Enabled)
return false;
SmallVector<CallBase *, 8> IndirectCalls;
More information about the cfe-commits
mailing list