[clang] [CIR] Diagnose missing/bad `cir.triple` and `cir.opt_info` attributes in CIR tests instead of asserts/crashes (PR #230003)
Ian Li via cfe-commits
cfe-commits at lists.llvm.org
Wed Oct 14 01:21:00 PDT 2026
https://github.com/ianayl updated https://github.com/llvm/llvm-project/pull/230003
>From 3d967e6f36629898ecef72528512b269f163eddb Mon Sep 17 00:00:00 2001
From: "Li, Ian" <ian.li at intel.com>
Date: Wed, 7 Oct 2026 16:41:26 -0700
Subject: [PATCH 01/20] issue diagnostics on bad cir.triple instead of asserts
---
.../CIR/Dialect/Transforms/CXXABILowering.cpp | 12 ++++----
.../Dialect/Transforms/LoweringPrepare.cpp | 10 +++++--
.../CIR/Dialect/Transforms/TargetLowering.cpp | 12 ++++----
.../Transforms/TargetLowering/LowerModule.cpp | 30 +++++++++++++++----
.../Transforms/TargetLowering/LowerModule.h | 4 ++-
5 files changed, 49 insertions(+), 19 deletions(-)
diff --git a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
index 735146b04c64f..b57b994bea88c 100644
--- a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
@@ -893,13 +893,15 @@ void CXXABILoweringPass::runOnOperation() {
auto mod = mlir::cast<mlir::ModuleOp>(getOperation());
mlir::MLIRContext *ctx = mod.getContext();
- std::unique_ptr<cir::LowerModule> lowerModule = cir::createLowerModule(mod);
+ auto diag = [&] {
+ return mod.emitWarning("cannot create a CIR lower module, skipping the ")
+ << getName() << " pass: ";
+ };
+ std::unique_ptr<cir::LowerModule> lowerModule = cir::createLowerModule(
+ mod, diag);
// If lower module is not available, skip the ABI lowering pass.
- if (!lowerModule) {
- mod.emitWarning("Cannot create a CIR lower module, skipping the ")
- << getName() << " pass";
+ if (!lowerModule)
return;
- }
mlir::DataLayout dataLayout(mod);
CIRABITypeConverter typeConverter(*ctx, dataLayout, *lowerModule);
diff --git a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
index 23fb81e2f706d..106298629c65e 100644
--- a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
@@ -3061,9 +3061,13 @@ void LoweringPreparePass::buildCUDARegisterVars(cir::CIRBaseBuilderTy &builder,
void LoweringPreparePass::runOnOperation() {
mlirModule = getOperation();
- // CIRGen always sets the triple, so this cannot fail.
- lowerModule = cir::createLowerModule(mlirModule);
- assert(lowerModule && "requires a module with a triple");
+ auto diag = [&] {
+ return mlirModule.emitError("cannot create a CIR lower module for ")
+ << getName() << " pass: ";
+ };
+ lowerModule = cir::createLowerModule(mlirModule, diag);
+ if (!lowerModule)
+ return signalPassFailure();
llvm::SmallVector<mlir::Operation *> opsToTransform;
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering.cpp
index 76ca7114ee5ce..e978acda6cca9 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering.cpp
@@ -296,13 +296,15 @@ populateTargetLoweringConversionTarget(mlir::ConversionTarget &target,
void TargetLoweringPass::runOnOperation() {
auto mod = mlir::cast<mlir::ModuleOp>(getOperation());
- std::unique_ptr<cir::LowerModule> lowerModule = cir::createLowerModule(mod);
+ auto diag = [&] {
+ return mod.emitWarning("cannot create a CIR lower module, skipping the ")
+ << getName() << " pass: ";
+ };
+ std::unique_ptr<cir::LowerModule> lowerModule = cir::createLowerModule(
+ mod, diag);
// If lower module is not available, skip the target lowering pass.
- if (!lowerModule) {
- mod.emitWarning("Cannot create a CIR lower module, skipping the ")
- << getName() << " pass";
+ if (!lowerModule)
return;
- }
const auto &targetInfo = lowerModule->getTargetLoweringInfo();
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
index 03044286e8cf7..313661ba959f4 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
@@ -79,20 +79,39 @@ const TargetLoweringInfo &LowerModule::getTargetLoweringInfo() {
}
// TODO: not to create it every time
-std::unique_ptr<LowerModule> createLowerModule(mlir::ModuleOp module) {
+std::unique_ptr<LowerModule>
+createLowerModule(mlir::ModuleOp module,
+ llvm::function_ref<mlir::InFlightDiagnostic()> emitDiag) {
// If the triple is not present, e.g. CIR modules parsed from text, we
// cannot init LowerModule properly.
assert(!cir::MissingFeatures::makeTripleAlwaysPresent());
- if (!module->hasAttr(cir::CIRDialect::getTripleAttrName()))
+ // TODO(triple) what this line do? ^^^
+ if (!module->hasAttr(cir::CIRDialect::getTripleAttrName())) {
+ if (emitDiag)
+ emitDiag() << "module is missing " << cir::CIRDialect::getTripleAttrName()
+ << " attribute";
return nullptr;
+ }
// Fetch target information.
- llvm::Triple triple(mlir::cast<mlir::StringAttr>(
- module->getAttr(cir::CIRDialect::getTripleAttrName()))
- .getValue());
+ auto tripleAttr = module->getAttrOfType<mlir::StringAttr>(
+ cir::CIRDialect::getTripleAttrName());
+ if (!tripleAttr) {
+ if (emitDiag)
+ emitDiag() << "expected module's " << cir::CIRDialect::getTripleAttrName()
+ << " attribute to be a string";
+ return nullptr;
+ }
+ llvm::Triple triple(tripleAttr.getValue());
clang::TargetOptions targetOptions;
targetOptions.Triple = triple.str();
auto targetInfo = clang::targets::AllocateTarget(triple, targetOptions);
+ if (!targetInfo) {
+ if (emitDiag)
+ emitDiag() << "unknown triple '" << tripleAttr.getValue() << "' in "
+ << cir::CIRDialect::getTripleAttrName() << " attribute";
+ return nullptr;
+ }
// Populate the lowering-relevant LangOptions from the module's
// #cir.lowering_lang_options attribute so a reloaded .cir lowers the same
@@ -120,6 +139,7 @@ std::unique_ptr<LowerModule> createLowerModule(mlir::ModuleOp module) {
assert(!cir::MissingFeatures::lowerModuleCodeGenOpts());
clang::CodeGenOptions codeGenOpts;
+ // TODO(optinfo): this cast should be more secure?
if (auto optInfo = mlir::cast_if_present<cir::OptInfoAttr>(
module->getAttr(cir::CIRDialect::getOptInfoAttrName()))) {
codeGenOpts.OptimizationLevel = optInfo.getLevel();
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h
index 56fcd0a9b58cd..588bc496bdaba 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h
@@ -57,7 +57,9 @@ class LowerModule {
const TargetLoweringInfo &getTargetLoweringInfo();
};
-std::unique_ptr<LowerModule> createLowerModule(mlir::ModuleOp module);
+std::unique_ptr<LowerModule>
+createLowerModule(mlir::ModuleOp module,
+ llvm::function_ref<mlir::InFlightDiagnostic()> emitDiag = nullptr);
} // namespace cir
>From 7148a33516414e640d560bff21c033763da991cc Mon Sep 17 00:00:00 2001
From: "Li, Ian" <ian.li at intel.com>
Date: Wed, 7 Oct 2026 17:13:28 -0700
Subject: [PATCH 02/20] issue diagnostics on malformed opt_info attrs
---
.../Dialect/Transforms/TargetLowering/LowerModule.cpp | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
index 313661ba959f4..afbacbd7987a6 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
@@ -139,9 +139,14 @@ createLowerModule(mlir::ModuleOp module,
assert(!cir::MissingFeatures::lowerModuleCodeGenOpts());
clang::CodeGenOptions codeGenOpts;
- // TODO(optinfo): this cast should be more secure?
- if (auto optInfo = mlir::cast_if_present<cir::OptInfoAttr>(
- module->getAttr(cir::CIRDialect::getOptInfoAttrName()))) {
+ if (auto optAttr = module->getAttr(cir::CIRDialect::getOptInfoAttrName())) {
+ auto optInfo = mlir::dyn_cast<cir::OptInfoAttr>(optAttr);
+ if (!optInfo) {
+ if (emitDiag)
+ emitDiag() << "malformed " << cir::CIRDialect::getOptInfoAttrName()
+ << " attribute";
+ return nullptr;
+ }
codeGenOpts.OptimizationLevel = optInfo.getLevel();
codeGenOpts.OptimizeSize = optInfo.getSize();
}
>From 9a939caf75ae9d058a1a5ef55ff8268191096264 Mon Sep 17 00:00:00 2001
From: "Li, Ian" <ian.li at intel.com>
Date: Wed, 7 Oct 2026 18:28:46 -0700
Subject: [PATCH 03/20] patch up reading triples for cpuid op lowering
---
.../Transforms/TargetLowering/LowerModule.cpp | 1 -
.../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 18 ++++++++++++++----
2 files changed, 14 insertions(+), 5 deletions(-)
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
index afbacbd7987a6..4190947e0cb4d 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
@@ -85,7 +85,6 @@ createLowerModule(mlir::ModuleOp module,
// If the triple is not present, e.g. CIR modules parsed from text, we
// cannot init LowerModule properly.
assert(!cir::MissingFeatures::makeTripleAlwaysPresent());
- // TODO(triple) what this line do? ^^^
if (!module->hasAttr(cir::CIRDialect::getTripleAttrName())) {
if (emitDiag)
emitDiag() << "module is missing " << cir::CIRDialect::getTripleAttrName()
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 6426841e6237f..d539ad50db866 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -4508,6 +4508,7 @@ void ConvertCIRToLLVMPass::processCIRAttrs(mlir::ModuleOp module) {
module->getAttr(cir::CIRDialect::getTripleAttrName()))
module->setAttr(mlir::LLVM::LLVMDialect::getTargetTripleAttrName(),
tripleAttr);
+ // TODO(triple) handle triple exception here?
if (mlir::Attribute asmAttr =
module->getAttr(cir::CIRDialect::getModuleLevelAsmAttrName()))
@@ -5819,10 +5820,19 @@ mlir::LogicalResult CIRToLLVMCpuIdOpLowering::matchAndRewrite(
StringRef asmString, constraints;
mlir::ModuleOp moduleOp = op->getParentOfType<mlir::ModuleOp>();
- llvm::Triple triple(
- mlir::cast<mlir::StringAttr>(
- moduleOp->getAttr(cir::CIRDialect::getTripleAttrName()))
- .getValue());
+ auto tripleAttr = moduleOp->getAttr(cir::CIRDialect::getTripleAttrName());
+ if (!tripleAttr) {
+ moduleOp->emitError("module is missing a ")
+ << cir::CIRDialect::getTripleAttrName() << " attribute";
+ return mlir::failure();
+ }
+ mlir::StringAttr tripleStr = mlir::dyn_cast<mlir::StringAttr>(tripleAttr);
+ if (!tripleStr) {
+ moduleOp->emitError("expected string from module ")
+ << cir::CIRDialect::getTripleAttrName() << " attribute";
+ return mlir::failure();
+ }
+ llvm::Triple triple(tripleStr.getValue());
if (triple.getArch() == llvm::Triple::x86) {
asmString = "cpuid";
constraints = "={ax},={bx},={cx},={dx},{ax},{cx}";
>From fd373da1e099dbad33241e2ab7c8afd94ebe7f7b Mon Sep 17 00:00:00 2001
From: "Li, Ian" <ian.li at intel.com>
Date: Wed, 7 Oct 2026 21:04:51 -0700
Subject: [PATCH 04/20] switch to unified helper for triple processing
---
.../include/clang/CIR/Dialect/IR/CIRDialect.h | 6 +++++
clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 22 +++++++++++++++++++
.../CIR/Dialect/Transforms/EHABILowering.cpp | 10 +++------
.../Transforms/TargetLowering/LowerModule.cpp | 22 +++++--------------
clang/lib/CIR/Lowering/CIRPasses.cpp | 12 +++++-----
.../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 18 ++++-----------
6 files changed, 45 insertions(+), 45 deletions(-)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
index d9018e93628b6..baece7ab02fc7 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
+++ b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
@@ -99,6 +99,12 @@ RecordLayoutAttr getRecordLayout(mlir::ModuleOp mod, mlir::StringAttr name);
/// Same lookup as getRecordLayout, but returns a null attribute instead of
/// asserting when the record has no layout entry.
RecordLayoutAttr tryGetRecordLayout(mlir::ModuleOp mod, mlir::StringAttr name);
+
+/// Attempts to construct an llvm::Triple from a module's cir.triple attribute.
+/// If emitDiag is not null, additional diagnostics information is passed into
+/// emitDiag upon failure.
+mlir::FailureOr<llvm::Triple>
+getTripleFromModule(mlir::ModuleOp mod, llvm::function_ref<mlir::InFlightDiagnostic()> emitDiag = nullptr);
} // namespace cir
// TableGen'erated files for MLIR dialects require that a macro be defined when
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 2a5cb9a908a1d..caa3527a02f11 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -402,6 +402,28 @@ static LogicalResult verifyProducedBy(Operation *op, Value operand,
return success();
}
+mlir::FailureOr<llvm::Triple> cir::getTripleFromModule(
+ mlir::ModuleOp mod,
+ llvm::function_ref<mlir::InFlightDiagnostic()> emitDiag) {
+ if (!mod->hasAttr(cir::CIRDialect::getTripleAttrName())) {
+ if (emitDiag)
+ emitDiag() << "module is missing " << cir::CIRDialect::getTripleAttrName()
+ << " attribute";
+ return mlir::failure();
+ }
+
+ auto tripleAttr = mod->getAttrOfType<mlir::StringAttr>(
+ cir::CIRDialect::getTripleAttrName());
+ if (!tripleAttr) {
+ if (emitDiag)
+ emitDiag() << "expected a string from module attribute "
+ << cir::CIRDialect::getTripleAttrName();
+ return mlir::failure();
+ }
+
+ return llvm::Triple{tripleAttr.getValue()};
+}
+
//===----------------------------------------------------------------------===//
// InlineKindAttr (FIXME: remove once FuncOp uses assembly format)
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp b/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp
index 77ce7434c8ed3..e3306227aac5e 100644
--- a/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp
@@ -1088,19 +1088,15 @@ void CIREHABILoweringPass::runOnOperation() {
// The target triple is attached to the module as the "cir.triple"
// attribute. If it is absent (e.g. a CIR module parsed from text without a
// triple) we cannot determine the ABI and must skip the pass.
- auto tripleAttr = mlir::dyn_cast_if_present<mlir::StringAttr>(
- mod->getAttr(cir::CIRDialect::getTripleAttrName()));
- if (!tripleAttr) {
- mod.emitError("Module has no target triple");
+ auto triple = cir::getTripleFromModule(mod, [&] { return mod.emitWarning(); });
+ if (mlir::failed(triple))
return;
- }
// Select the ABI-specific lowering handler from the triple. The Microsoft
// C++ ABI targets a Windows MSVC environment; everything else uses Itanium.
// Extend this when Microsoft ABI lowering is added.
- llvm::Triple triple(tripleAttr.getValue());
std::unique_ptr<EHABILowering> lowering;
- if (triple.isWindowsMSVCEnvironment()) {
+ if (triple->isWindowsMSVCEnvironment()) {
mod.emitError(
"EH ABI lowering is not yet implemented for the Microsoft ABI");
return signalPassFailure();
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
index 4190947e0cb4d..91a6f27ea8b16 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
@@ -85,29 +85,17 @@ createLowerModule(mlir::ModuleOp module,
// If the triple is not present, e.g. CIR modules parsed from text, we
// cannot init LowerModule properly.
assert(!cir::MissingFeatures::makeTripleAlwaysPresent());
- if (!module->hasAttr(cir::CIRDialect::getTripleAttrName())) {
- if (emitDiag)
- emitDiag() << "module is missing " << cir::CIRDialect::getTripleAttrName()
- << " attribute";
- return nullptr;
- }
// Fetch target information.
- auto tripleAttr = module->getAttrOfType<mlir::StringAttr>(
- cir::CIRDialect::getTripleAttrName());
- if (!tripleAttr) {
- if (emitDiag)
- emitDiag() << "expected module's " << cir::CIRDialect::getTripleAttrName()
- << " attribute to be a string";
+ auto triple = cir::getTripleFromModule(module, emitDiag);
+ if (mlir::failed(triple))
return nullptr;
- }
- llvm::Triple triple(tripleAttr.getValue());
clang::TargetOptions targetOptions;
- targetOptions.Triple = triple.str();
- auto targetInfo = clang::targets::AllocateTarget(triple, targetOptions);
+ targetOptions.Triple = triple->str();
+ auto targetInfo = clang::targets::AllocateTarget(*triple, targetOptions);
if (!targetInfo) {
if (emitDiag)
- emitDiag() << "unknown triple '" << tripleAttr.getValue() << "' in "
+ emitDiag() << "unknown triple '" << triple->str() << "' in "
<< cir::CIRDialect::getTripleAttrName() << " attribute";
return nullptr;
}
diff --git a/clang/lib/CIR/Lowering/CIRPasses.cpp b/clang/lib/CIR/Lowering/CIRPasses.cpp
index 6e75ce03d14ff..dc4e3128ca26d 100644
--- a/clang/lib/CIR/Lowering/CIRPasses.cpp
+++ b/clang/lib/CIR/Lowering/CIRPasses.cpp
@@ -78,13 +78,11 @@ runCIRToCIRPasses(mlir::ModuleOp theModule, mlir::MLIRContext &mlirContext,
llvm::TimeTraceScope scope("CIR To CIR Passes");
- auto tripleAttr = theModule->getAttrOfType<mlir::StringAttr>(
- cir::CIRDialect::getTripleAttrName());
- if (!tripleAttr)
- return theModule.emitError()
- << "missing '" << cir::CIRDialect::getTripleAttrName()
- << "' attribute";
- llvm::Triple triple(tripleAttr.getValue());
+ auto maybeTriple = cir::getTripleFromModule(theModule,
+ [&]{ return theModule.emitError(); });
+ if (mlir::failed(maybeTriple))
+ return mlir::LogicalResult::failure();
+ llvm::Triple &triple = *maybeTriple;
auto abiAttr = theModule->getAttrOfType<mlir::StringAttr>(
cir::CIRDialect::getTargetABIAttrName());
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index d539ad50db866..628dc160e251d 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -4508,7 +4508,6 @@ void ConvertCIRToLLVMPass::processCIRAttrs(mlir::ModuleOp module) {
module->getAttr(cir::CIRDialect::getTripleAttrName()))
module->setAttr(mlir::LLVM::LLVMDialect::getTargetTripleAttrName(),
tripleAttr);
- // TODO(triple) handle triple exception here?
if (mlir::Attribute asmAttr =
module->getAttr(cir::CIRDialect::getModuleLevelAsmAttrName()))
@@ -5820,20 +5819,11 @@ mlir::LogicalResult CIRToLLVMCpuIdOpLowering::matchAndRewrite(
StringRef asmString, constraints;
mlir::ModuleOp moduleOp = op->getParentOfType<mlir::ModuleOp>();
- auto tripleAttr = moduleOp->getAttr(cir::CIRDialect::getTripleAttrName());
- if (!tripleAttr) {
- moduleOp->emitError("module is missing a ")
- << cir::CIRDialect::getTripleAttrName() << " attribute";
+ auto triple = cir::getTripleFromModule(moduleOp,
+ [&] { return moduleOp.emitError(); });
+ if (mlir::failed(triple))
return mlir::failure();
- }
- mlir::StringAttr tripleStr = mlir::dyn_cast<mlir::StringAttr>(tripleAttr);
- if (!tripleStr) {
- moduleOp->emitError("expected string from module ")
- << cir::CIRDialect::getTripleAttrName() << " attribute";
- return mlir::failure();
- }
- llvm::Triple triple(tripleStr.getValue());
- if (triple.getArch() == llvm::Triple::x86) {
+ if (triple->getArch() == llvm::Triple::x86) {
asmString = "cpuid";
constraints = "={ax},={bx},={cx},={dx},{ax},{cx}";
} else {
>From 3c65330e55b1a8fc479a554123683a9587b785cb Mon Sep 17 00:00:00 2001
From: "Li, Ian" <ian.li at intel.com>
Date: Wed, 7 Oct 2026 21:16:22 -0700
Subject: [PATCH 05/20] I don't think there were any tangible benefits to using
mlir::FailureOr, and if anything it reads worse than std::optional
---
clang/include/clang/CIR/Dialect/IR/CIRDialect.h | 2 +-
clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 6 +++---
clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp | 4 ++--
.../Dialect/Transforms/TargetLowering/LowerModule.cpp | 4 ++--
clang/lib/CIR/Lowering/CIRPasses.cpp | 11 +++++------
clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 4 ++--
6 files changed, 15 insertions(+), 16 deletions(-)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
index baece7ab02fc7..732d065f81cb3 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
+++ b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
@@ -103,7 +103,7 @@ RecordLayoutAttr tryGetRecordLayout(mlir::ModuleOp mod, mlir::StringAttr name);
/// Attempts to construct an llvm::Triple from a module's cir.triple attribute.
/// If emitDiag is not null, additional diagnostics information is passed into
/// emitDiag upon failure.
-mlir::FailureOr<llvm::Triple>
+std::optional<llvm::Triple>
getTripleFromModule(mlir::ModuleOp mod, llvm::function_ref<mlir::InFlightDiagnostic()> emitDiag = nullptr);
} // namespace cir
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index caa3527a02f11..0136ed1ccd0dc 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -402,14 +402,14 @@ static LogicalResult verifyProducedBy(Operation *op, Value operand,
return success();
}
-mlir::FailureOr<llvm::Triple> cir::getTripleFromModule(
+std::optional<llvm::Triple> cir::getTripleFromModule(
mlir::ModuleOp mod,
llvm::function_ref<mlir::InFlightDiagnostic()> emitDiag) {
if (!mod->hasAttr(cir::CIRDialect::getTripleAttrName())) {
if (emitDiag)
emitDiag() << "module is missing " << cir::CIRDialect::getTripleAttrName()
<< " attribute";
- return mlir::failure();
+ return std::nullopt;
}
auto tripleAttr = mod->getAttrOfType<mlir::StringAttr>(
@@ -418,7 +418,7 @@ mlir::FailureOr<llvm::Triple> cir::getTripleFromModule(
if (emitDiag)
emitDiag() << "expected a string from module attribute "
<< cir::CIRDialect::getTripleAttrName();
- return mlir::failure();
+ return std::nullopt;
}
return llvm::Triple{tripleAttr.getValue()};
diff --git a/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp b/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp
index e3306227aac5e..72f9c786db08e 100644
--- a/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp
@@ -1088,8 +1088,8 @@ void CIREHABILoweringPass::runOnOperation() {
// The target triple is attached to the module as the "cir.triple"
// attribute. If it is absent (e.g. a CIR module parsed from text without a
// triple) we cannot determine the ABI and must skip the pass.
- auto triple = cir::getTripleFromModule(mod, [&] { return mod.emitWarning(); });
- if (mlir::failed(triple))
+ std::optional<llvm::Triple> triple = cir::getTripleFromModule(mod, [&] { return mod.emitWarning(); });
+ if (!triple)
return;
// Select the ABI-specific lowering handler from the triple. The Microsoft
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
index 91a6f27ea8b16..b6f6031ddaf2d 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
@@ -87,8 +87,8 @@ createLowerModule(mlir::ModuleOp module,
assert(!cir::MissingFeatures::makeTripleAlwaysPresent());
// Fetch target information.
- auto triple = cir::getTripleFromModule(module, emitDiag);
- if (mlir::failed(triple))
+ std::optional<llvm::Triple> triple = cir::getTripleFromModule(module, emitDiag);
+ if (!triple)
return nullptr;
clang::TargetOptions targetOptions;
targetOptions.Triple = triple->str();
diff --git a/clang/lib/CIR/Lowering/CIRPasses.cpp b/clang/lib/CIR/Lowering/CIRPasses.cpp
index dc4e3128ca26d..0158c7fe37309 100644
--- a/clang/lib/CIR/Lowering/CIRPasses.cpp
+++ b/clang/lib/CIR/Lowering/CIRPasses.cpp
@@ -78,11 +78,10 @@ runCIRToCIRPasses(mlir::ModuleOp theModule, mlir::MLIRContext &mlirContext,
llvm::TimeTraceScope scope("CIR To CIR Passes");
- auto maybeTriple = cir::getTripleFromModule(theModule,
+ std::optional<llvm::Triple> triple = cir::getTripleFromModule(theModule,
[&]{ return theModule.emitError(); });
- if (mlir::failed(maybeTriple))
+ if (!triple)
return mlir::LogicalResult::failure();
- llvm::Triple &triple = *maybeTriple;
auto abiAttr = theModule->getAttrOfType<mlir::StringAttr>(
cir::CIRDialect::getTargetABIAttrName());
@@ -126,7 +125,7 @@ runCIRToCIRPasses(mlir::ModuleOp theModule, mlir::MLIRContext &mlirContext,
// so it must run after CXXABILowering has lowered C++ ABI types to plain
// records the classifier can handle. Only the x86_64 System V classifier
// is implemented; other targets are left unchanged.
- CallConvTarget target = getCallConvTarget(triple);
+ CallConvTarget target = getCallConvTarget(triple.value());
if (target != CallConvTarget::None) {
// Source the ABI-compatibility version from the module's serialized
// #cir.lowering_lang_options so a reloaded .cir classifies the same way
@@ -141,8 +140,8 @@ runCIRToCIRPasses(mlir::ModuleOp theModule, mlir::MLIRContext &mlirContext,
loweringLangOpts.getClangAbiCompat());
pm.addPass(mlir::createCallConvLoweringPass(
target, getX86AVXABILevel(abiAttr.getValue()),
- allowsX86TargetAttrAvx(triple, compat),
- getX86ABICompatInfo(triple, compat)));
+ allowsX86TargetAttrAvx(triple.value(), compat),
+ getX86ABICompatInfo(triple.value(), compat)));
}
}
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 628dc160e251d..0903de9c77f20 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -5819,9 +5819,9 @@ mlir::LogicalResult CIRToLLVMCpuIdOpLowering::matchAndRewrite(
StringRef asmString, constraints;
mlir::ModuleOp moduleOp = op->getParentOfType<mlir::ModuleOp>();
- auto triple = cir::getTripleFromModule(moduleOp,
+ std::optional<llvm::Triple> triple = cir::getTripleFromModule(moduleOp,
[&] { return moduleOp.emitError(); });
- if (mlir::failed(triple))
+ if (!triple)
return mlir::failure();
if (triple->getArch() == llvm::Triple::x86) {
asmString = "cpuid";
>From 72963ed03bbd69e613943ae2dbdf68a030dcc87a Mon Sep 17 00:00:00 2001
From: "Li, Ian" <ian.li at intel.com>
Date: Wed, 7 Oct 2026 21:21:56 -0700
Subject: [PATCH 06/20] copy cir-opt additions from #229575
---
clang/tools/cir-opt/cir-opt.cpp | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/clang/tools/cir-opt/cir-opt.cpp b/clang/tools/cir-opt/cir-opt.cpp
index fdaf405441003..0a0c791ae494e 100644
--- a/clang/tools/cir-opt/cir-opt.cpp
+++ b/clang/tools/cir-opt/cir-opt.cpp
@@ -82,6 +82,18 @@ int main(int argc, char **argv) {
return mlir::createCXXABILoweringPass();
});
+ ::mlir::registerPass([]() -> std::unique_ptr<::mlir::Pass> {
+ return mlir::createTargetLoweringPass();
+ });
+
+ ::mlir::registerPass([]() -> std::unique_ptr<::mlir::Pass> {
+ return mlir::createLoweringPreparePass();
+ });
+
+ ::mlir::registerPass([]() -> std::unique_ptr<::mlir::Pass> {
+ return mlir::createLibOptPass();
+ });
+
::mlir::registerPass([]() -> std::unique_ptr<::mlir::Pass> {
return mlir::createIdiomRecognizerPass();
});
>From 362290cca48ef863cc0ad67290338d0d85fbca7e Mon Sep 17 00:00:00 2001
From: "Li, Ian" <ian.li at intel.com>
Date: Wed, 7 Oct 2026 21:35:01 -0700
Subject: [PATCH 07/20] clang-format
---
clang/include/clang/CIR/Dialect/IR/CIRDialect.h | 5 +++--
clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 4 ++--
clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp | 6 +++---
clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp | 3 ++-
clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp | 2 +-
clang/lib/CIR/Dialect/Transforms/TargetLowering.cpp | 6 +++---
.../CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp | 3 ++-
.../lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h | 4 ++--
clang/lib/CIR/Lowering/CIRPasses.cpp | 4 ++--
clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 4 ++--
10 files changed, 22 insertions(+), 19 deletions(-)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
index 732d065f81cb3..662942fdeda04 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
+++ b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
@@ -103,8 +103,9 @@ RecordLayoutAttr tryGetRecordLayout(mlir::ModuleOp mod, mlir::StringAttr name);
/// Attempts to construct an llvm::Triple from a module's cir.triple attribute.
/// If emitDiag is not null, additional diagnostics information is passed into
/// emitDiag upon failure.
-std::optional<llvm::Triple>
-getTripleFromModule(mlir::ModuleOp mod, llvm::function_ref<mlir::InFlightDiagnostic()> emitDiag = nullptr);
+std::optional<llvm::Triple> getTripleFromModule(
+ mlir::ModuleOp mod,
+ llvm::function_ref<mlir::InFlightDiagnostic()> emitDiag = nullptr);
} // namespace cir
// TableGen'erated files for MLIR dialects require that a macro be defined when
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 0136ed1ccd0dc..7a208cf4f1b00 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -403,8 +403,8 @@ static LogicalResult verifyProducedBy(Operation *op, Value operand,
}
std::optional<llvm::Triple> cir::getTripleFromModule(
- mlir::ModuleOp mod,
- llvm::function_ref<mlir::InFlightDiagnostic()> emitDiag) {
+ mlir::ModuleOp mod,
+ llvm::function_ref<mlir::InFlightDiagnostic()> emitDiag) {
if (!mod->hasAttr(cir::CIRDialect::getTripleAttrName())) {
if (emitDiag)
emitDiag() << "module is missing " << cir::CIRDialect::getTripleAttrName()
diff --git a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
index b57b994bea88c..7c7de931fdc70 100644
--- a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
@@ -895,10 +895,10 @@ void CXXABILoweringPass::runOnOperation() {
auto diag = [&] {
return mod.emitWarning("cannot create a CIR lower module, skipping the ")
- << getName() << " pass: ";
+ << getName() << " pass: ";
};
- std::unique_ptr<cir::LowerModule> lowerModule = cir::createLowerModule(
- mod, diag);
+ std::unique_ptr<cir::LowerModule> lowerModule =
+ cir::createLowerModule(mod, diag);
// If lower module is not available, skip the ABI lowering pass.
if (!lowerModule)
return;
diff --git a/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp b/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp
index 72f9c786db08e..668016a432308 100644
--- a/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp
@@ -1088,7 +1088,8 @@ void CIREHABILoweringPass::runOnOperation() {
// The target triple is attached to the module as the "cir.triple"
// attribute. If it is absent (e.g. a CIR module parsed from text without a
// triple) we cannot determine the ABI and must skip the pass.
- std::optional<llvm::Triple> triple = cir::getTripleFromModule(mod, [&] { return mod.emitWarning(); });
+ std::optional<llvm::Triple> triple =
+ cir::getTripleFromModule(mod, [&] { return mod.emitWarning(); });
if (!triple)
return;
diff --git a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
index 106298629c65e..e35eb52fabda2 100644
--- a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
@@ -3063,7 +3063,7 @@ void LoweringPreparePass::runOnOperation() {
auto diag = [&] {
return mlirModule.emitError("cannot create a CIR lower module for ")
- << getName() << " pass: ";
+ << getName() << " pass: ";
};
lowerModule = cir::createLowerModule(mlirModule, diag);
if (!lowerModule)
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering.cpp
index e978acda6cca9..f545fbb6bbecf 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering.cpp
@@ -298,10 +298,10 @@ void TargetLoweringPass::runOnOperation() {
auto mod = mlir::cast<mlir::ModuleOp>(getOperation());
auto diag = [&] {
return mod.emitWarning("cannot create a CIR lower module, skipping the ")
- << getName() << " pass: ";
+ << getName() << " pass: ";
};
- std::unique_ptr<cir::LowerModule> lowerModule = cir::createLowerModule(
- mod, diag);
+ std::unique_ptr<cir::LowerModule> lowerModule =
+ cir::createLowerModule(mod, diag);
// If lower module is not available, skip the target lowering pass.
if (!lowerModule)
return;
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
index b6f6031ddaf2d..a5ee43c544344 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
@@ -87,7 +87,8 @@ createLowerModule(mlir::ModuleOp module,
assert(!cir::MissingFeatures::makeTripleAlwaysPresent());
// Fetch target information.
- std::optional<llvm::Triple> triple = cir::getTripleFromModule(module, emitDiag);
+ std::optional<llvm::Triple> triple =
+ cir::getTripleFromModule(module, emitDiag);
if (!triple)
return nullptr;
clang::TargetOptions targetOptions;
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h
index 588bc496bdaba..dbd28430c6df3 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h
@@ -57,8 +57,8 @@ class LowerModule {
const TargetLoweringInfo &getTargetLoweringInfo();
};
-std::unique_ptr<LowerModule>
-createLowerModule(mlir::ModuleOp module,
+std::unique_ptr<LowerModule> createLowerModule(
+ mlir::ModuleOp module,
llvm::function_ref<mlir::InFlightDiagnostic()> emitDiag = nullptr);
} // namespace cir
diff --git a/clang/lib/CIR/Lowering/CIRPasses.cpp b/clang/lib/CIR/Lowering/CIRPasses.cpp
index 0158c7fe37309..cbc0c515bf275 100644
--- a/clang/lib/CIR/Lowering/CIRPasses.cpp
+++ b/clang/lib/CIR/Lowering/CIRPasses.cpp
@@ -78,8 +78,8 @@ runCIRToCIRPasses(mlir::ModuleOp theModule, mlir::MLIRContext &mlirContext,
llvm::TimeTraceScope scope("CIR To CIR Passes");
- std::optional<llvm::Triple> triple = cir::getTripleFromModule(theModule,
- [&]{ return theModule.emitError(); });
+ std::optional<llvm::Triple> triple = cir::getTripleFromModule(
+ theModule, [&] { return theModule.emitError(); });
if (!triple)
return mlir::LogicalResult::failure();
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 0903de9c77f20..dc99dd0b439b0 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -5819,8 +5819,8 @@ mlir::LogicalResult CIRToLLVMCpuIdOpLowering::matchAndRewrite(
StringRef asmString, constraints;
mlir::ModuleOp moduleOp = op->getParentOfType<mlir::ModuleOp>();
- std::optional<llvm::Triple> triple = cir::getTripleFromModule(moduleOp,
- [&] { return moduleOp.emitError(); });
+ std::optional<llvm::Triple> triple =
+ cir::getTripleFromModule(moduleOp, [&] { return moduleOp.emitError(); });
if (!triple)
return mlir::failure();
if (triple->getArch() == llvm::Triple::x86) {
>From 15677e38ac14face59e9174713c7cc2e87596d00 Mon Sep 17 00:00:00 2001
From: "Li, Ian" <ian.li at intel.com>
Date: Wed, 7 Oct 2026 23:36:53 -0700
Subject: [PATCH 08/20] draft up test cases
---
.../CIR/Lowering/cir-to-llvm-module-attrs.cir | 49 +++++++
.../Transforms/cxx-abi-lowering-bad-attrs.cir | 137 ++++++++++++++++++
.../Transforms/eh-abi-lowering-bad-attrs.cir | 41 ++++++
.../lowering-prepare-module-attrs.cir | 130 +++++++++++++++++
.../target-lowering-module-attrs.cir | 137 ++++++++++++++++++
5 files changed, 494 insertions(+)
create mode 100644 clang/test/CIR/Lowering/cir-to-llvm-module-attrs.cir
create mode 100644 clang/test/CIR/Transforms/cxx-abi-lowering-bad-attrs.cir
create mode 100644 clang/test/CIR/Transforms/eh-abi-lowering-bad-attrs.cir
create mode 100644 clang/test/CIR/Transforms/lowering-prepare-module-attrs.cir
create mode 100644 clang/test/CIR/Transforms/target-lowering-module-attrs.cir
diff --git a/clang/test/CIR/Lowering/cir-to-llvm-module-attrs.cir b/clang/test/CIR/Lowering/cir-to-llvm-module-attrs.cir
new file mode 100644
index 0000000000000..ed861075a5c36
--- /dev/null
+++ b/clang/test/CIR/Lowering/cir-to-llvm-module-attrs.cir
@@ -0,0 +1,49 @@
+// RUN: cir-opt %s -cir-to-llvm -verify-diagnostics -split-input-file
+// RUN: not cir-opt %s -cir-to-llvm -split-input-file 2>/dev/null \
+// RUN: | FileCheck %s --implicit-check-not=llvm.func
+
+// -cir-to-llvm relies on cir.triple module attributes: Check that missing or
+// malformed cir.triple attributes read by -cir-to-llvm do not cause asserts or
+// compiler crashes, and are diagnosed properly.
+
+
+// Missing cir.triple.
+
+!s32i = !cir.int<s, 32>
+// expected-warning @below {{module is missing cir.triple attribute}}
+// expected-error @below {{module is missing cir.triple attribute}}
+module {
+ cir.func @missing_triple(%p: !cir.ptr<!s32i>, %a: !s32i, %b: !s32i) {
+ // expected-error @below {{failed to legalize operation 'cir.cpuid'}}
+ cir.cpuid %p, %a, %b : !cir.ptr<!s32i>, !s32i, !s32i
+ cir.return
+ }
+}
+
+// -----
+
+// Non-string cir.triple.
+
+!s32i = !cir.int<s, 32>
+// expected-warning @below {{expected a string from module attribute cir.triple}}
+// expected-error @below {{expected a string from module attribute cir.triple}}
+module attributes {cir.triple = 42 : i32} {
+ cir.func @non_string_triple(%p: !cir.ptr<!s32i>, %a: !s32i, %b: !s32i) {
+ // expected-error @below {{failed to legalize operation 'cir.cpuid'}}
+ cir.cpuid %p, %a, %b : !cir.ptr<!s32i>, !s32i, !s32i
+ cir.return
+ }
+}
+
+// -----
+
+// Valid cir.triple.
+
+!s32i = !cir.int<s, 32>
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+ // CHECK-LABEL: llvm.func @valid_triple(
+ cir.func @valid_triple(%p: !cir.ptr<!s32i>, %a: !s32i, %b: !s32i) {
+ cir.cpuid %p, %a, %b : !cir.ptr<!s32i>, !s32i, !s32i
+ cir.return
+ }
+}
diff --git a/clang/test/CIR/Transforms/cxx-abi-lowering-bad-attrs.cir b/clang/test/CIR/Transforms/cxx-abi-lowering-bad-attrs.cir
new file mode 100644
index 0000000000000..5d13956c63af4
--- /dev/null
+++ b/clang/test/CIR/Transforms/cxx-abi-lowering-bad-attrs.cir
@@ -0,0 +1,137 @@
+// RUN: cir-opt %s -cir-cxxabi-lowering -verify-diagnostics -split-input-file
+// RUN: cir-opt %s -cir-cxxabi-lowering -split-input-file 2>/dev/null | FileCheck %s
+
+// Check that missing or malformed module attributes required/used by
+// -cir-cxxabi-lowering do not cause asserts or compiler crashes, and are
+// diagnosed properly. The pass should warn and skip instead of failing, so
+// every module is still printed.
+
+
+// Missing cir.triple.
+
+// expected-warning @below {{cannot create a CIR lower module, skipping the CXXABILowering pass: module is missing cir.triple attribute}}
+module {
+ // CHECK-LABEL: cir.func @missing_triple(
+ cir.func @missing_triple() {
+ cir.return
+ }
+}
+
+// -----
+
+// Non-string cir.triple.
+
+// expected-warning @below {{cannot create a CIR lower module, skipping the CXXABILowering pass: expected a string from module attribute cir.triple}}
+module attributes {cir.triple = 42 : i32} {
+ // CHECK-LABEL: cir.func @non_string_triple(
+ cir.func @non_string_triple() {
+ cir.return
+ }
+}
+
+// -----
+
+// Empty cir.triple.
+
+// expected-warning @below {{cannot create a CIR lower module, skipping the CXXABILowering pass: unknown triple '' in cir.triple attribute}}
+module attributes {cir.triple = ""} {
+ // CHECK-LABEL: cir.func @empty_triple(
+ cir.func @empty_triple() {
+ cir.return
+ }
+}
+
+// -----
+
+// Malformed cir.triple.
+
+// expected-warning @below {{cannot create a CIR lower module, skipping the CXXABILowering pass: unknown triple 'garbage' in cir.triple attribute}}
+module attributes {cir.triple = "garbage"} {
+ // CHECK-LABEL: cir.func @malformed_triple(
+ cir.func @malformed_triple() {
+ cir.return
+ }
+}
+
+// -----
+
+// Well-formed cir.triple with an unknown target.
+
+// expected-warning @below {{cannot create a CIR lower module, skipping the CXXABILowering pass: unknown triple 'foobar-unknown-unknown' in cir.triple attribute}}
+module attributes {cir.triple = "foobar-unknown-unknown"} {
+ // CHECK-LABEL: cir.func @unknown_triple(
+ cir.func @unknown_triple() {
+ cir.return
+ }
+}
+
+// -----
+
+// Valid cir.triple without cir.opt_info.
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+ // CHECK-LABEL: cir.func @valid_triple(
+ cir.func @valid_triple() {
+ cir.return
+ }
+}
+
+// -----
+
+// Valid cir.triple with a valid cir.opt_info.
+
+module attributes {
+ cir.triple = "x86_64-unknown-linux-gnu",
+ cir.opt_info = #cir.opt_info<level = 2, size = 1>
+} {
+ // CHECK-LABEL: cir.func @valid_opt_info(
+ cir.func @valid_opt_info() {
+ cir.return
+ }
+}
+
+// -----
+
+// Valid cir.triple with a cir.opt_info that is not an OptInfoAttr.
+
+// expected-warning @below {{cannot create a CIR lower module, skipping the CXXABILowering pass: malformed cir.opt_info attribute}}
+module attributes {
+ cir.triple = "x86_64-unknown-linux-gnu",
+ cir.opt_info = 1 : i32
+} {
+ // CHECK-LABEL: cir.func @malformed_opt_info(
+ cir.func @malformed_opt_info() {
+ cir.return
+ }
+}
+
+// -----
+
+// Valid cir.triple with a string cir.opt_info.
+
+// expected-warning @below {{cannot create a CIR lower module, skipping the CXXABILowering pass: malformed cir.opt_info attribute}}
+module attributes {
+ cir.triple = "x86_64-unknown-linux-gnu",
+ cir.opt_info = "O2"
+} {
+ // CHECK-LABEL: cir.func @string_opt_info(
+ cir.func @string_opt_info() {
+ cir.return
+ }
+}
+
+// -----
+
+// Valid cir.triple with a dictionary cir.opt_info that mimics OptInfoAttr's
+// fields.
+
+// expected-warning @below {{cannot create a CIR lower module, skipping the CXXABILowering pass: malformed cir.opt_info attribute}}
+module attributes {
+ cir.triple = "x86_64-unknown-linux-gnu",
+ cir.opt_info = {level = 2 : i32, size = 1 : i32}
+} {
+ // CHECK-LABEL: cir.func @dict_opt_info(
+ cir.func @dict_opt_info() {
+ cir.return
+ }
+}
diff --git a/clang/test/CIR/Transforms/eh-abi-lowering-bad-attrs.cir b/clang/test/CIR/Transforms/eh-abi-lowering-bad-attrs.cir
new file mode 100644
index 0000000000000..fc4be2550cb3b
--- /dev/null
+++ b/clang/test/CIR/Transforms/eh-abi-lowering-bad-attrs.cir
@@ -0,0 +1,41 @@
+// RUN: cir-opt %s -cir-eh-abi-lowering -verify-diagnostics -split-input-file
+// RUN: cir-opt %s -cir-eh-abi-lowering -split-input-file 2>/dev/null | FileCheck %s
+
+// Check that missing or malformed cir.triple attributes required by
+// -cir-eh-abi-lowering do not cause asserts or compiler crashes, and are
+// diagnosed properly. The pass should warn and skip instead of failing, so
+// every module is still printed.
+
+
+// Missing cir.triple.
+
+// expected-warning @below {{module is missing cir.triple attribute}}
+module {
+ // CHECK-LABEL: cir.func @missing_triple(
+ cir.func @missing_triple() {
+ cir.return
+ }
+}
+
+// -----
+
+// Non-string cir.triple.
+
+// expected-warning @below {{expected a string from module attribute cir.triple}}
+module attributes {cir.triple = 42 : i32} {
+ // CHECK-LABEL: cir.func @non_string_triple(
+ cir.func @non_string_triple() {
+ cir.return
+ }
+}
+
+// -----
+
+// Valid cir.triple.
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+ // CHECK-LABEL: cir.func @valid_triple(
+ cir.func @valid_triple() {
+ cir.return
+ }
+}
diff --git a/clang/test/CIR/Transforms/lowering-prepare-module-attrs.cir b/clang/test/CIR/Transforms/lowering-prepare-module-attrs.cir
new file mode 100644
index 0000000000000..f42bad16d7bc3
--- /dev/null
+++ b/clang/test/CIR/Transforms/lowering-prepare-module-attrs.cir
@@ -0,0 +1,130 @@
+// RUN: cir-opt %s -cir-lowering-prepare -verify-diagnostics -split-input-file
+// RUN: not cir-opt %s -cir-lowering-prepare -split-input-file 2>/dev/null \
+// RUN: | FileCheck %s --implicit-check-not=cir.func
+
+// Check that missing or malformed module attributes required/used by
+// -cir-lowering-prepare do not cause asserts or compiler crashes, and are
+// diagnosed properly. The pass should fail on bad attributes, so only modules
+// with valid attributes are printed.
+
+
+// Missing cir.triple.
+
+// expected-error @below {{cannot create a CIR lower module for LoweringPrepare pass: module is missing cir.triple attribute}}
+module {
+ cir.func @missing_triple() {
+ cir.return
+ }
+}
+
+// -----
+
+// Non-string cir.triple.
+
+// expected-error @below {{cannot create a CIR lower module for LoweringPrepare pass: expected a string from module attribute cir.triple}}
+module attributes {cir.triple = 42 : i32} {
+ cir.func @non_string_triple() {
+ cir.return
+ }
+}
+
+// -----
+
+// Empty cir.triple.
+
+// expected-error @below {{cannot create a CIR lower module for LoweringPrepare pass: unknown triple '' in cir.triple attribute}}
+module attributes {cir.triple = ""} {
+ cir.func @empty_triple() {
+ cir.return
+ }
+}
+
+// -----
+
+// Malformed cir.triple.
+
+// expected-error @below {{cannot create a CIR lower module for LoweringPrepare pass: unknown triple 'garbage' in cir.triple attribute}}
+module attributes {cir.triple = "garbage"} {
+ cir.func @malformed_triple() {
+ cir.return
+ }
+}
+
+// -----
+
+// Well-formed cir.triple with an unknown target.
+
+// expected-error @below {{cannot create a CIR lower module for LoweringPrepare pass: unknown triple 'foobar-unknown-unknown' in cir.triple attribute}}
+module attributes {cir.triple = "foobar-unknown-unknown"} {
+ cir.func @unknown_triple() {
+ cir.return
+ }
+}
+
+// -----
+
+// Valid cir.triple without cir.opt_info.
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+ // CHECK-LABEL: cir.func @valid_triple(
+ cir.func @valid_triple() {
+ cir.return
+ }
+}
+
+// -----
+
+// Valid cir.triple with a valid cir.opt_info.
+
+module attributes {
+ cir.triple = "x86_64-unknown-linux-gnu",
+ cir.opt_info = #cir.opt_info<level = 2, size = 1>
+} {
+ // CHECK-LABEL: cir.func @valid_opt_info(
+ cir.func @valid_opt_info() {
+ cir.return
+ }
+}
+
+// -----
+
+// Valid cir.triple with a cir.opt_info that is not an OptInfoAttr.
+
+// expected-error @below {{cannot create a CIR lower module for LoweringPrepare pass: malformed cir.opt_info attribute}}
+module attributes {
+ cir.triple = "x86_64-unknown-linux-gnu",
+ cir.opt_info = 1 : i32
+} {
+ cir.func @malformed_opt_info() {
+ cir.return
+ }
+}
+
+// -----
+
+// Valid cir.triple with a string cir.opt_info.
+
+// expected-error @below {{cannot create a CIR lower module for LoweringPrepare pass: malformed cir.opt_info attribute}}
+module attributes {
+ cir.triple = "x86_64-unknown-linux-gnu",
+ cir.opt_info = "O2"
+} {
+ cir.func @string_opt_info() {
+ cir.return
+ }
+}
+
+// -----
+
+// Valid cir.triple with a dictionary cir.opt_info that mimics OptInfoAttr's
+// fields.
+
+// expected-error @below {{cannot create a CIR lower module for LoweringPrepare pass: malformed cir.opt_info attribute}}
+module attributes {
+ cir.triple = "x86_64-unknown-linux-gnu",
+ cir.opt_info = {level = 2 : i32, size = 1 : i32}
+} {
+ cir.func @dict_opt_info() {
+ cir.return
+ }
+}
diff --git a/clang/test/CIR/Transforms/target-lowering-module-attrs.cir b/clang/test/CIR/Transforms/target-lowering-module-attrs.cir
new file mode 100644
index 0000000000000..36813d4d707a4
--- /dev/null
+++ b/clang/test/CIR/Transforms/target-lowering-module-attrs.cir
@@ -0,0 +1,137 @@
+// RUN: cir-opt %s -cir-target-lowering -verify-diagnostics -split-input-file
+// RUN: cir-opt %s -cir-target-lowering -split-input-file 2>/dev/null | FileCheck %s
+
+// Check that missing or malformed module attributes required/used by
+// -cir-target-lowering do not cause asserts or compiler crashes, and are
+// diagnosed properly. The pass should warn and skip instead of failing, so
+// every module is still printed.
+
+
+// Missing cir.triple.
+
+// expected-warning @below {{cannot create a CIR lower module, skipping the TargetLowering pass: module is missing cir.triple attribute}}
+module {
+ // CHECK-LABEL: cir.func @missing_triple(
+ cir.func @missing_triple() {
+ cir.return
+ }
+}
+
+// -----
+
+// Non-string cir.triple.
+
+// expected-warning @below {{cannot create a CIR lower module, skipping the TargetLowering pass: expected a string from module attribute cir.triple}}
+module attributes {cir.triple = 42 : i32} {
+ // CHECK-LABEL: cir.func @non_string_triple(
+ cir.func @non_string_triple() {
+ cir.return
+ }
+}
+
+// -----
+
+// Empty cir.triple.
+
+// expected-warning @below {{cannot create a CIR lower module, skipping the TargetLowering pass: unknown triple '' in cir.triple attribute}}
+module attributes {cir.triple = ""} {
+ // CHECK-LABEL: cir.func @empty_triple(
+ cir.func @empty_triple() {
+ cir.return
+ }
+}
+
+// -----
+
+// Malformed cir.triple.
+
+// expected-warning @below {{cannot create a CIR lower module, skipping the TargetLowering pass: unknown triple 'garbage' in cir.triple attribute}}
+module attributes {cir.triple = "garbage"} {
+ // CHECK-LABEL: cir.func @malformed_triple(
+ cir.func @malformed_triple() {
+ cir.return
+ }
+}
+
+// -----
+
+// Well-formed cir.triple with an unknown target.
+
+// expected-warning @below {{cannot create a CIR lower module, skipping the TargetLowering pass: unknown triple 'foobar-unknown-unknown' in cir.triple attribute}}
+module attributes {cir.triple = "foobar-unknown-unknown"} {
+ // CHECK-LABEL: cir.func @unknown_triple(
+ cir.func @unknown_triple() {
+ cir.return
+ }
+}
+
+// -----
+
+// Valid cir.triple without cir.opt_info.
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+ // CHECK-LABEL: cir.func @valid_triple(
+ cir.func @valid_triple() {
+ cir.return
+ }
+}
+
+// -----
+
+// Valid cir.triple with a valid cir.opt_info.
+
+module attributes {
+ cir.triple = "x86_64-unknown-linux-gnu",
+ cir.opt_info = #cir.opt_info<level = 2, size = 1>
+} {
+ // CHECK-LABEL: cir.func @valid_opt_info(
+ cir.func @valid_opt_info() {
+ cir.return
+ }
+}
+
+// -----
+
+// Valid cir.triple with a cir.opt_info that is not an OptInfoAttr.
+
+// expected-warning @below {{cannot create a CIR lower module, skipping the TargetLowering pass: malformed cir.opt_info attribute}}
+module attributes {
+ cir.triple = "x86_64-unknown-linux-gnu",
+ cir.opt_info = 1 : i32
+} {
+ // CHECK-LABEL: cir.func @malformed_opt_info(
+ cir.func @malformed_opt_info() {
+ cir.return
+ }
+}
+
+// -----
+
+// Valid cir.triple with a string cir.opt_info.
+
+// expected-warning @below {{cannot create a CIR lower module, skipping the TargetLowering pass: malformed cir.opt_info attribute}}
+module attributes {
+ cir.triple = "x86_64-unknown-linux-gnu",
+ cir.opt_info = "O2"
+} {
+ // CHECK-LABEL: cir.func @string_opt_info(
+ cir.func @string_opt_info() {
+ cir.return
+ }
+}
+
+// -----
+
+// Valid cir.triple with a dictionary cir.opt_info that mimics OptInfoAttr's
+// fields.
+
+// expected-warning @below {{cannot create a CIR lower module, skipping the TargetLowering pass: malformed cir.opt_info attribute}}
+module attributes {
+ cir.triple = "x86_64-unknown-linux-gnu",
+ cir.opt_info = {level = 2 : i32, size = 1 : i32}
+} {
+ // CHECK-LABEL: cir.func @dict_opt_info(
+ cir.func @dict_opt_info() {
+ cir.return
+ }
+}
>From aeaa75c8a3307620b83229d3d6a8b2ad12815926 Mon Sep 17 00:00:00 2001
From: "Li, Ian" <ian.li at intel.com>
Date: Thu, 8 Oct 2026 00:28:43 -0700
Subject: [PATCH 09/20] this test case is already covered in
lowering-prepare-module-attrs.cir
---
clang/test/CIR/Transforms/lowering-prepare-no-triple.cir | 5 -----
1 file changed, 5 deletions(-)
delete mode 100644 clang/test/CIR/Transforms/lowering-prepare-no-triple.cir
diff --git a/clang/test/CIR/Transforms/lowering-prepare-no-triple.cir b/clang/test/CIR/Transforms/lowering-prepare-no-triple.cir
deleted file mode 100644
index bebdf3dd57f73..0000000000000
--- a/clang/test/CIR/Transforms/lowering-prepare-no-triple.cir
+++ /dev/null
@@ -1,5 +0,0 @@
-// RUN: cir-opt %s --cir-lowering-prepare -verify-diagnostics
-
-// expected-error @below {{cir-lowering-prepare requires a module with a triple}}
-module {
-}
>From 12140d978c541100c9fbad75c5a79a12ae5d839e Mon Sep 17 00:00:00 2001
From: "Li, Ian" <ian.li at intel.com>
Date: Thu, 8 Oct 2026 18:53:32 -0700
Subject: [PATCH 10/20] update cir.cpuid op lowering diagnostics to provide
more info
---
clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 7 +++++--
clang/test/CIR/Lowering/cir-to-llvm-module-attrs.cir | 10 +++++-----
2 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index a74cdbff3d3bd..8a49790120c5f 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -5830,8 +5830,11 @@ mlir::LogicalResult CIRToLLVMCpuIdOpLowering::matchAndRewrite(
StringRef asmString, constraints;
mlir::ModuleOp moduleOp = op->getParentOfType<mlir::ModuleOp>();
- std::optional<llvm::Triple> triple =
- cir::getTripleFromModule(moduleOp, [&] { return moduleOp.emitError(); });
+ auto diag = [&] {
+ return moduleOp.emitError("cannot lower ")
+ << op.getOperationName() << " op: ";
+ };
+ std::optional<llvm::Triple> triple = cir::getTripleFromModule(moduleOp, diag);
if (!triple)
return mlir::failure();
if (triple->getArch() == llvm::Triple::x86) {
diff --git a/clang/test/CIR/Lowering/cir-to-llvm-module-attrs.cir b/clang/test/CIR/Lowering/cir-to-llvm-module-attrs.cir
index ed861075a5c36..0cf5c4a3327c3 100644
--- a/clang/test/CIR/Lowering/cir-to-llvm-module-attrs.cir
+++ b/clang/test/CIR/Lowering/cir-to-llvm-module-attrs.cir
@@ -2,16 +2,16 @@
// RUN: not cir-opt %s -cir-to-llvm -split-input-file 2>/dev/null \
// RUN: | FileCheck %s --implicit-check-not=llvm.func
-// -cir-to-llvm relies on cir.triple module attributes: Check that missing or
-// malformed cir.triple attributes read by -cir-to-llvm do not cause asserts or
-// compiler crashes, and are diagnosed properly.
+// -cir-to-llvm relies on cir.triple module attributes to handle cir.cpuid ops:
+// Check that missing or malformed cir.triple attributes read by -cir-to-llvm do
+// not cause asserts or compiler crashes, and are diagnosed properly.
// Missing cir.triple.
!s32i = !cir.int<s, 32>
// expected-warning @below {{module is missing cir.triple attribute}}
-// expected-error @below {{module is missing cir.triple attribute}}
+// expected-error @below {{cannot lower cir.cpuid op: module is missing cir.triple attribute}}
module {
cir.func @missing_triple(%p: !cir.ptr<!s32i>, %a: !s32i, %b: !s32i) {
// expected-error @below {{failed to legalize operation 'cir.cpuid'}}
@@ -26,7 +26,7 @@ module {
!s32i = !cir.int<s, 32>
// expected-warning @below {{expected a string from module attribute cir.triple}}
-// expected-error @below {{expected a string from module attribute cir.triple}}
+// expected-error @below {{cannot lower cir.cpuid op: expected a string from module attribute cir.triple}}
module attributes {cir.triple = 42 : i32} {
cir.func @non_string_triple(%p: !cir.ptr<!s32i>, %a: !s32i, %b: !s32i) {
// expected-error @below {{failed to legalize operation 'cir.cpuid'}}
>From 9f08e15b96a4302654f397cd5302e788c0b282ff Mon Sep 17 00:00:00 2001
From: "Li, Ian" <ian.li at intel.com>
Date: Tue, 13 Oct 2026 13:05:35 -0700
Subject: [PATCH 11/20] WIP: remove diagnostics from createLowerModule and move
checking and validation to verifyOperationAttrs
---
.../include/clang/CIR/Dialect/IR/CIRDialect.h | 6 +--
clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 45 +++++++++++++------
.../CIR/Dialect/Transforms/CXXABILowering.cpp | 12 +++--
.../Dialect/Transforms/LoweringPrepare.cpp | 9 ++--
.../CIR/Dialect/Transforms/TargetLowering.cpp | 12 +++--
.../Transforms/TargetLowering/LowerModule.cpp | 18 ++------
.../Transforms/TargetLowering/LowerModule.h | 4 +-
7 files changed, 52 insertions(+), 54 deletions(-)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
index 662942fdeda04..764a48787dbd0 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
+++ b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
@@ -101,11 +101,7 @@ RecordLayoutAttr getRecordLayout(mlir::ModuleOp mod, mlir::StringAttr name);
RecordLayoutAttr tryGetRecordLayout(mlir::ModuleOp mod, mlir::StringAttr name);
/// Attempts to construct an llvm::Triple from a module's cir.triple attribute.
-/// If emitDiag is not null, additional diagnostics information is passed into
-/// emitDiag upon failure.
-std::optional<llvm::Triple> getTripleFromModule(
- mlir::ModuleOp mod,
- llvm::function_ref<mlir::InFlightDiagnostic()> emitDiag = nullptr);
+std::optional<llvm::Triple> getTripleFromModule(mlir::ModuleOp mod);
} // namespace cir
// TableGen'erated files for MLIR dialects require that a macro be defined when
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index f7c4955d9ba53..4d62441f26d2c 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -12,6 +12,7 @@
#include "clang/CIR/Dialect/IR/CIRDialect.h"
+#include "clang/Basic/TargetInfo.h"
#include "clang/CIR/Dialect/IR/CIRAttrs.h"
#include "clang/CIR/Dialect/IR/CIROpsEnums.h"
#include "clang/CIR/Dialect/IR/CIRTypes.h"
@@ -287,6 +288,31 @@ cir::CIRDialect::verifyOperationAttribute(mlir::Operation *op,
/*trailingZerosNum=*/0);
}
+ if (attrName == getTripleAttrName()) {
+ auto tripleStr = mlir::dyn_cast<mlir::StringAttr>(attr.getValue());
+ if (!tripleStr)
+ return op->emitOpError() << "expects '" << getTripleAttrName() << "' to "
+ << " be a string";
+ llvm::Triple triple = llvm::Triple(tripleStr.getValue());
+ clang::TargetOptions targetOptions;
+ targetOptions.Triple = tripleStr.getValue();
+ // "Validate" our triple by checking if it can successfully initialize into
+ // a TargetInfo:
+ if (!clang::targets::AllocateTarget(triple, targetOptions)) {
+ return op->emitOpError() << "unknown triple '" << tripleStr.getValue()
+ << "' in '" << getTripleAttrName()
+ << "' attribute";
+ }
+ }
+
+ if (attrName == getOptInfoAttrName()) {
+ auto optInfo = mlir::dyn_cast<cir::OptInfoAttr>(attr.getValue());
+ if (!optInfo)
+ return op->emitOpError() << "malformed "
+ << cir::CIRDialect::getOptInfoAttrName()
+ << " attribute";
+ }
+
return success();
}
@@ -402,24 +428,17 @@ static LogicalResult verifyProducedBy(Operation *op, Value operand,
return success();
}
-std::optional<llvm::Triple> cir::getTripleFromModule(
- mlir::ModuleOp mod,
- llvm::function_ref<mlir::InFlightDiagnostic()> emitDiag) {
- if (!mod->hasAttr(cir::CIRDialect::getTripleAttrName())) {
- if (emitDiag)
- emitDiag() << "module is missing " << cir::CIRDialect::getTripleAttrName()
- << " attribute";
+std::optional<llvm::Triple> cir::getTripleFromModule(mlir::ModuleOp mod) {
+ // Verifying the validity of the triple attribute happens in
+ // cir::CIRDialect::verifyOperationAttribute; verifyOperationAttribute
+ // should error first if we have an invalid attribute.
+ if (!mod->hasAttr(cir::CIRDialect::getTripleAttrName()))
return std::nullopt;
- }
auto tripleAttr = mod->getAttrOfType<mlir::StringAttr>(
cir::CIRDialect::getTripleAttrName());
- if (!tripleAttr) {
- if (emitDiag)
- emitDiag() << "expected a string from module attribute "
- << cir::CIRDialect::getTripleAttrName();
+ if (!tripleAttr)
return std::nullopt;
- }
return llvm::Triple{tripleAttr.getValue()};
}
diff --git a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
index c7aa0dc68f686..6f4fa4176890c 100644
--- a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
@@ -900,15 +900,13 @@ void CXXABILoweringPass::runOnOperation() {
auto mod = mlir::cast<mlir::ModuleOp>(getOperation());
mlir::MLIRContext *ctx = mod.getContext();
- auto diag = [&] {
- return mod.emitWarning("cannot create a CIR lower module, skipping the ")
- << getName() << " pass: ";
- };
- std::unique_ptr<cir::LowerModule> lowerModule =
- cir::createLowerModule(mod, diag);
+ std::unique_ptr<cir::LowerModule> lowerModule = cir::createLowerModule(mod);
// If lower module is not available, skip the ABI lowering pass.
- if (!lowerModule)
+ if (!lowerModule) {
+ mod.emitWarning("cannot create a CIR lower module, skipping the ")
+ << getName() << " pass: ";
return;
+ }
mlir::DataLayout dataLayout(mod);
CIRABITypeConverter typeConverter(*ctx, dataLayout, *lowerModule);
diff --git a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
index 5d846af5b64dc..13d12012423c6 100644
--- a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
@@ -3181,13 +3181,12 @@ void LoweringPreparePass::buildCUDARegisterVars(cir::CIRBaseBuilderTy &builder,
void LoweringPreparePass::runOnOperation() {
mlirModule = getOperation();
- auto diag = [&] {
- return mlirModule.emitError("cannot create a CIR lower module for ")
+ lowerModule = cir::createLowerModule(mlirModule);
+ if (!lowerModule) {
+ mlirModule.emitError("cannot create a CIR lower module for ")
<< getName() << " pass: ";
- };
- lowerModule = cir::createLowerModule(mlirModule, diag);
- if (!lowerModule)
return signalPassFailure();
+ }
llvm::SmallVector<mlir::Operation *> opsToTransform;
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering.cpp
index f545fbb6bbecf..40e956c540471 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering.cpp
@@ -296,15 +296,13 @@ populateTargetLoweringConversionTarget(mlir::ConversionTarget &target,
void TargetLoweringPass::runOnOperation() {
auto mod = mlir::cast<mlir::ModuleOp>(getOperation());
- auto diag = [&] {
- return mod.emitWarning("cannot create a CIR lower module, skipping the ")
- << getName() << " pass: ";
- };
- std::unique_ptr<cir::LowerModule> lowerModule =
- cir::createLowerModule(mod, diag);
+ std::unique_ptr<cir::LowerModule> lowerModule = cir::createLowerModule(mod);
// If lower module is not available, skip the target lowering pass.
- if (!lowerModule)
+ if (!lowerModule) {
+ mod.emitWarning("cannot create a CIR lower module, skipping the ")
+ << getName() << " pass: ";
return;
+ }
const auto &targetInfo = lowerModule->getTargetLoweringInfo();
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
index a5ee43c544344..f05fe7a1645c0 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
@@ -80,26 +80,20 @@ const TargetLoweringInfo &LowerModule::getTargetLoweringInfo() {
// TODO: not to create it every time
std::unique_ptr<LowerModule>
-createLowerModule(mlir::ModuleOp module,
- llvm::function_ref<mlir::InFlightDiagnostic()> emitDiag) {
+createLowerModule(mlir::ModuleOp module) {
// If the triple is not present, e.g. CIR modules parsed from text, we
// cannot init LowerModule properly.
assert(!cir::MissingFeatures::makeTripleAlwaysPresent());
// Fetch target information.
- std::optional<llvm::Triple> triple =
- cir::getTripleFromModule(module, emitDiag);
+ std::optional<llvm::Triple> triple = cir::getTripleFromModule(module);
if (!triple)
return nullptr;
clang::TargetOptions targetOptions;
targetOptions.Triple = triple->str();
auto targetInfo = clang::targets::AllocateTarget(*triple, targetOptions);
- if (!targetInfo) {
- if (emitDiag)
- emitDiag() << "unknown triple '" << triple->str() << "' in "
- << cir::CIRDialect::getTripleAttrName() << " attribute";
+ if (!targetInfo)
return nullptr;
- }
// Populate the lowering-relevant LangOptions from the module's
// #cir.lowering_lang_options attribute so a reloaded .cir lowers the same
@@ -129,12 +123,8 @@ createLowerModule(mlir::ModuleOp module,
if (auto optAttr = module->getAttr(cir::CIRDialect::getOptInfoAttrName())) {
auto optInfo = mlir::dyn_cast<cir::OptInfoAttr>(optAttr);
- if (!optInfo) {
- if (emitDiag)
- emitDiag() << "malformed " << cir::CIRDialect::getOptInfoAttrName()
- << " attribute";
+ if (!optInfo)
return nullptr;
- }
codeGenOpts.OptimizationLevel = optInfo.getLevel();
codeGenOpts.OptimizeSize = optInfo.getSize();
}
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h
index dbd28430c6df3..56fcd0a9b58cd 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h
@@ -57,9 +57,7 @@ class LowerModule {
const TargetLoweringInfo &getTargetLoweringInfo();
};
-std::unique_ptr<LowerModule> createLowerModule(
- mlir::ModuleOp module,
- llvm::function_ref<mlir::InFlightDiagnostic()> emitDiag = nullptr);
+std::unique_ptr<LowerModule> createLowerModule(mlir::ModuleOp module);
} // namespace cir
>From 7cac1228b6ec312044ba83075e68ff5ea33c94a4 Mon Sep 17 00:00:00 2001
From: "Li, Ian" <ian.li at intel.com>
Date: Tue, 13 Oct 2026 21:16:31 -0700
Subject: [PATCH 12/20] complete removing diags and moving validation to
verifyOperationAttrs
---
clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 2 +-
clang/lib/CIR/Lowering/CIRPasses.cpp | 3 +--
clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 6 +-----
clang/test/CIR/Input/cir-input-invalid.cir | 5 +++--
4 files changed, 6 insertions(+), 10 deletions(-)
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 4d62441f26d2c..06c88dfb78d48 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -292,7 +292,7 @@ cir::CIRDialect::verifyOperationAttribute(mlir::Operation *op,
auto tripleStr = mlir::dyn_cast<mlir::StringAttr>(attr.getValue());
if (!tripleStr)
return op->emitOpError() << "expects '" << getTripleAttrName() << "' to "
- << " be a string";
+ << "be a string";
llvm::Triple triple = llvm::Triple(tripleStr.getValue());
clang::TargetOptions targetOptions;
targetOptions.Triple = tripleStr.getValue();
diff --git a/clang/lib/CIR/Lowering/CIRPasses.cpp b/clang/lib/CIR/Lowering/CIRPasses.cpp
index cbc0c515bf275..11e8a3ee341f7 100644
--- a/clang/lib/CIR/Lowering/CIRPasses.cpp
+++ b/clang/lib/CIR/Lowering/CIRPasses.cpp
@@ -78,8 +78,7 @@ runCIRToCIRPasses(mlir::ModuleOp theModule, mlir::MLIRContext &mlirContext,
llvm::TimeTraceScope scope("CIR To CIR Passes");
- std::optional<llvm::Triple> triple = cir::getTripleFromModule(
- theModule, [&] { return theModule.emitError(); });
+ std::optional<llvm::Triple> triple = cir::getTripleFromModule(theModule);
if (!triple)
return mlir::LogicalResult::failure();
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 8a49790120c5f..0c77affa835ad 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -5830,11 +5830,7 @@ mlir::LogicalResult CIRToLLVMCpuIdOpLowering::matchAndRewrite(
StringRef asmString, constraints;
mlir::ModuleOp moduleOp = op->getParentOfType<mlir::ModuleOp>();
- auto diag = [&] {
- return moduleOp.emitError("cannot lower ")
- << op.getOperationName() << " op: ";
- };
- std::optional<llvm::Triple> triple = cir::getTripleFromModule(moduleOp, diag);
+ std::optional<llvm::Triple> triple = cir::getTripleFromModule(moduleOp);
if (!triple)
return mlir::failure();
if (triple->getArch() == llvm::Triple::x86) {
diff --git a/clang/test/CIR/Input/cir-input-invalid.cir b/clang/test/CIR/Input/cir-input-invalid.cir
index 1a791d843bb0a..7b41ca296fefc 100644
--- a/clang/test/CIR/Input/cir-input-invalid.cir
+++ b/clang/test/CIR/Input/cir-input-invalid.cir
@@ -25,11 +25,12 @@
// RUN: not %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-cir %t/no-triple.cir -o - 2>&1 \
// RUN: | FileCheck %s --check-prefix=NO-TRIPLE --implicit-check-not=error:
-// RUN: not %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-cir %t/int-triple.cir -o - 2>&1 \
-// RUN: | FileCheck %s --check-prefix=NO-TRIPLE --implicit-check-not=error:
// RUN: not %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-obj %t/no-triple.cir -o /dev/null 2>&1 \
// RUN: | FileCheck %s --check-prefix=NO-TRIPLE --implicit-check-not=error:
// NO-TRIPLE: error: missing target triple in ClangIR input
+// RUN: not %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-cir %t/int-triple.cir -o - 2>&1 \
+// RUN: | FileCheck %s --check-prefix=BAD-TRIPLE --implicit-check-not=error:
+// BAD-TRIPLE: error: 'builtin.module' op expects 'cir.triple' to be a string
// RUN: not %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-cir %t/mismatch.cir -o - 2>&1 \
// RUN: | FileCheck %s --check-prefix=MISMATCH --implicit-check-not=error:
>From 66d12d03046af3dfb3909ee672afb4dcf116262a Mon Sep 17 00:00:00 2001
From: "Li, Ian" <ian.li at intel.com>
Date: Tue, 13 Oct 2026 21:17:13 -0700
Subject: [PATCH 13/20] Delete changes to EHABILowering; should be another PR
---
.../CIR/Dialect/Transforms/EHABILowering.cpp | 11 +++--
.../Transforms/eh-abi-lowering-bad-attrs.cir | 41 -------------------
2 files changed, 7 insertions(+), 45 deletions(-)
delete mode 100644 clang/test/CIR/Transforms/eh-abi-lowering-bad-attrs.cir
diff --git a/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp b/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp
index ed93a41978811..72a8cffc3b060 100644
--- a/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp
@@ -1113,16 +1113,19 @@ void CIREHABILoweringPass::runOnOperation() {
// The target triple is attached to the module as the "cir.triple"
// attribute. If it is absent (e.g. a CIR module parsed from text without a
// triple) we cannot determine the ABI and must skip the pass.
- std::optional<llvm::Triple> triple =
- cir::getTripleFromModule(mod, [&] { return mod.emitWarning(); });
- if (!triple)
+ auto tripleAttr = mlir::dyn_cast_if_present<mlir::StringAttr>(
+ mod->getAttr(cir::CIRDialect::getTripleAttrName()));
+ if (!tripleAttr) {
+ mod.emitError("Module has no target triple");
return;
+ }
// Select the ABI-specific lowering handler from the triple. The Microsoft
// C++ ABI targets a Windows MSVC environment; everything else uses Itanium.
// Extend this when Microsoft ABI lowering is added.
+ llvm::Triple triple(tripleAttr.getValue());
std::unique_ptr<EHABILowering> lowering;
- if (triple->isWindowsMSVCEnvironment()) {
+ if (triple.isWindowsMSVCEnvironment()) {
mod.emitError(
"EH ABI lowering is not yet implemented for the Microsoft ABI");
return signalPassFailure();
diff --git a/clang/test/CIR/Transforms/eh-abi-lowering-bad-attrs.cir b/clang/test/CIR/Transforms/eh-abi-lowering-bad-attrs.cir
deleted file mode 100644
index fc4be2550cb3b..0000000000000
--- a/clang/test/CIR/Transforms/eh-abi-lowering-bad-attrs.cir
+++ /dev/null
@@ -1,41 +0,0 @@
-// RUN: cir-opt %s -cir-eh-abi-lowering -verify-diagnostics -split-input-file
-// RUN: cir-opt %s -cir-eh-abi-lowering -split-input-file 2>/dev/null | FileCheck %s
-
-// Check that missing or malformed cir.triple attributes required by
-// -cir-eh-abi-lowering do not cause asserts or compiler crashes, and are
-// diagnosed properly. The pass should warn and skip instead of failing, so
-// every module is still printed.
-
-
-// Missing cir.triple.
-
-// expected-warning @below {{module is missing cir.triple attribute}}
-module {
- // CHECK-LABEL: cir.func @missing_triple(
- cir.func @missing_triple() {
- cir.return
- }
-}
-
-// -----
-
-// Non-string cir.triple.
-
-// expected-warning @below {{expected a string from module attribute cir.triple}}
-module attributes {cir.triple = 42 : i32} {
- // CHECK-LABEL: cir.func @non_string_triple(
- cir.func @non_string_triple() {
- cir.return
- }
-}
-
-// -----
-
-// Valid cir.triple.
-
-module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
- // CHECK-LABEL: cir.func @valid_triple(
- cir.func @valid_triple() {
- cir.return
- }
-}
>From b273d9ffd00b492b517e330c96e5abb6b0625b84 Mon Sep 17 00:00:00 2001
From: "Li, Ian" <ian.li at intel.com>
Date: Tue, 13 Oct 2026 21:30:52 -0700
Subject: [PATCH 14/20] add tests for new CIR dialect verifier behavior
---
clang/test/CIR/IR/invalid-opt-info.cir | 21 ++++
clang/test/CIR/IR/invalid-triple.cir | 27 +++++
.../Transforms/cxx-abi-lowering-bad-attrs.cir | 104 ++----------------
3 files changed, 59 insertions(+), 93 deletions(-)
create mode 100644 clang/test/CIR/IR/invalid-triple.cir
diff --git a/clang/test/CIR/IR/invalid-opt-info.cir b/clang/test/CIR/IR/invalid-opt-info.cir
index 52d6afd2c6974..20ccb83694db5 100644
--- a/clang/test/CIR/IR/invalid-opt-info.cir
+++ b/clang/test/CIR/IR/invalid-opt-info.cir
@@ -11,3 +11,24 @@ module attributes {
// expected-error @below {{size optimization level must be between 0 and 2 inclusive}}
cir.opt_info = #cir.opt_info<level = 0, size = 3>
} {}
+
+// -----
+
+// cir.opt_info that is not an OptInfoAttr.
+
+// expected-error @below {{'builtin.module' op malformed cir.opt_info attribute}}
+module attributes {cir.opt_info = 1 : i32} {}
+
+// -----
+
+// String cir.opt_info.
+
+// expected-error @below {{'builtin.module' op malformed cir.opt_info attribute}}
+module attributes {cir.opt_info = "O2"} {}
+
+// -----
+
+// Dictionary cir.opt_info that mimics OptInfoAttr's fields.
+
+// expected-error @below {{'builtin.module' op malformed cir.opt_info attribute}}
+module attributes {cir.opt_info = {level = 2 : i32, size = 1 : i32}} {}
diff --git a/clang/test/CIR/IR/invalid-triple.cir b/clang/test/CIR/IR/invalid-triple.cir
new file mode 100644
index 0000000000000..a52ae9768689e
--- /dev/null
+++ b/clang/test/CIR/IR/invalid-triple.cir
@@ -0,0 +1,27 @@
+// RUN: cir-opt %s -verify-diagnostics -split-input-file
+
+// Non-string cir.triple.
+
+// expected-error @below {{'builtin.module' op expects 'cir.triple' to be a string}}
+module attributes {cir.triple = 42 : i32} {}
+
+// -----
+
+// Empty cir.triple.
+
+// expected-error @below {{'builtin.module' op unknown triple '' in 'cir.triple' attribute}}
+module attributes {cir.triple = ""} {}
+
+// -----
+
+// Malformed cir.triple.
+
+// expected-error @below {{'builtin.module' op unknown triple 'garbage' in 'cir.triple' attribute}}
+module attributes {cir.triple = "garbage"} {}
+
+// -----
+
+// Well-formed cir.triple with an unknown target.
+
+// expected-error @below {{'builtin.module' op unknown triple 'foobar-unknown-unknown' in 'cir.triple' attribute}}
+module attributes {cir.triple = "foobar-unknown-unknown"} {}
diff --git a/clang/test/CIR/Transforms/cxx-abi-lowering-bad-attrs.cir b/clang/test/CIR/Transforms/cxx-abi-lowering-bad-attrs.cir
index 5d13956c63af4..b6ce3bbf0e6c2 100644
--- a/clang/test/CIR/Transforms/cxx-abi-lowering-bad-attrs.cir
+++ b/clang/test/CIR/Transforms/cxx-abi-lowering-bad-attrs.cir
@@ -1,15 +1,17 @@
// RUN: cir-opt %s -cir-cxxabi-lowering -verify-diagnostics -split-input-file
// RUN: cir-opt %s -cir-cxxabi-lowering -split-input-file 2>/dev/null | FileCheck %s
-// Check that missing or malformed module attributes required/used by
-// -cir-cxxabi-lowering do not cause asserts or compiler crashes, and are
-// diagnosed properly. The pass should warn and skip instead of failing, so
-// every module is still printed.
+// Check that missing cir.triple module attribute does not cause asserts or
+// compiler crashes in -cir-cxxabi-lowering, and is diagnosed properly. The pass
+// should warn and skip instead of failing. so every module is still printed.
+//
+// Malformed cir.triple and cir.opt_info attributes are rejected by the CIR
+// dialect verifier; see IR/invalid-triple.cir and IR/invalid-opt-info.cir.
// Missing cir.triple.
-// expected-warning @below {{cannot create a CIR lower module, skipping the CXXABILowering pass: module is missing cir.triple attribute}}
+// expected-warning @below {{cannot create a CIR lower module, skipping the CXXABILowering pass}}
module {
// CHECK-LABEL: cir.func @missing_triple(
cir.func @missing_triple() {
@@ -19,48 +21,10 @@ module {
// -----
-// Non-string cir.triple.
-
-// expected-warning @below {{cannot create a CIR lower module, skipping the CXXABILowering pass: expected a string from module attribute cir.triple}}
-module attributes {cir.triple = 42 : i32} {
- // CHECK-LABEL: cir.func @non_string_triple(
- cir.func @non_string_triple() {
- cir.return
- }
-}
-
-// -----
-
-// Empty cir.triple.
-
-// expected-warning @below {{cannot create a CIR lower module, skipping the CXXABILowering pass: unknown triple '' in cir.triple attribute}}
-module attributes {cir.triple = ""} {
- // CHECK-LABEL: cir.func @empty_triple(
- cir.func @empty_triple() {
- cir.return
- }
-}
-
-// -----
-
-// Malformed cir.triple.
-
-// expected-warning @below {{cannot create a CIR lower module, skipping the CXXABILowering pass: unknown triple 'garbage' in cir.triple attribute}}
-module attributes {cir.triple = "garbage"} {
- // CHECK-LABEL: cir.func @malformed_triple(
- cir.func @malformed_triple() {
- cir.return
- }
-}
-
-// -----
-
-// Well-formed cir.triple with an unknown target.
-
-// expected-warning @below {{cannot create a CIR lower module, skipping the CXXABILowering pass: unknown triple 'foobar-unknown-unknown' in cir.triple attribute}}
-module attributes {cir.triple = "foobar-unknown-unknown"} {
- // CHECK-LABEL: cir.func @unknown_triple(
- cir.func @unknown_triple() {
+// expected-warning @below {{cannot create a CIR lower module, skipping the CXXABILowering pass}}
+module attributes {cir.opt_info = #cir.opt_info<level = 0, size = 1>} {
+ // CHECK-LABEL: cir.func @missing_triple(
+ cir.func @missing_triple() {
cir.return
}
}
@@ -89,49 +53,3 @@ module attributes {
cir.return
}
}
-
-// -----
-
-// Valid cir.triple with a cir.opt_info that is not an OptInfoAttr.
-
-// expected-warning @below {{cannot create a CIR lower module, skipping the CXXABILowering pass: malformed cir.opt_info attribute}}
-module attributes {
- cir.triple = "x86_64-unknown-linux-gnu",
- cir.opt_info = 1 : i32
-} {
- // CHECK-LABEL: cir.func @malformed_opt_info(
- cir.func @malformed_opt_info() {
- cir.return
- }
-}
-
-// -----
-
-// Valid cir.triple with a string cir.opt_info.
-
-// expected-warning @below {{cannot create a CIR lower module, skipping the CXXABILowering pass: malformed cir.opt_info attribute}}
-module attributes {
- cir.triple = "x86_64-unknown-linux-gnu",
- cir.opt_info = "O2"
-} {
- // CHECK-LABEL: cir.func @string_opt_info(
- cir.func @string_opt_info() {
- cir.return
- }
-}
-
-// -----
-
-// Valid cir.triple with a dictionary cir.opt_info that mimics OptInfoAttr's
-// fields.
-
-// expected-warning @below {{cannot create a CIR lower module, skipping the CXXABILowering pass: malformed cir.opt_info attribute}}
-module attributes {
- cir.triple = "x86_64-unknown-linux-gnu",
- cir.opt_info = {level = 2 : i32, size = 1 : i32}
-} {
- // CHECK-LABEL: cir.func @dict_opt_info(
- cir.func @dict_opt_info() {
- cir.return
- }
-}
>From 58a6435d2db545602ec6dc9ef5fb2a3508d3403e Mon Sep 17 00:00:00 2001
From: "Li, Ian" <ian.li at intel.com>
Date: Tue, 13 Oct 2026 21:33:20 -0700
Subject: [PATCH 15/20] add comment
---
clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 2 ++
1 file changed, 2 insertions(+)
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 06c88dfb78d48..a80c311d42a93 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -307,6 +307,8 @@ cir::CIRDialect::verifyOperationAttribute(mlir::Operation *op,
if (attrName == getOptInfoAttrName()) {
auto optInfo = mlir::dyn_cast<cir::OptInfoAttr>(attr.getValue());
+ // Checks whether or not OptInfoAttr is even parseable; opt info range
+ // sanity checks are done in OptInfoAttr::verify.
if (!optInfo)
return op->emitOpError() << "malformed "
<< cir::CIRDialect::getOptInfoAttrName()
>From 6928e7efbe589945a0bb85052e4658a89cb28463 Mon Sep 17 00:00:00 2001
From: "Li, Ian" <ian.li at intel.com>
Date: Tue, 13 Oct 2026 21:52:44 -0700
Subject: [PATCH 16/20] delete a crap ton of test code; this feels good but
I'll get rid of the rest later
---
.../CIR/Lowering/cir-to-llvm-module-attrs.cir | 21 +---
.../lowering-prepare-module-attrs.cir | 92 +----------------
.../target-lowering-module-attrs.cir | 99 +------------------
3 files changed, 12 insertions(+), 200 deletions(-)
diff --git a/clang/test/CIR/Lowering/cir-to-llvm-module-attrs.cir b/clang/test/CIR/Lowering/cir-to-llvm-module-attrs.cir
index 0cf5c4a3327c3..6c208074c1b9f 100644
--- a/clang/test/CIR/Lowering/cir-to-llvm-module-attrs.cir
+++ b/clang/test/CIR/Lowering/cir-to-llvm-module-attrs.cir
@@ -5,13 +5,15 @@
// -cir-to-llvm relies on cir.triple module attributes to handle cir.cpuid ops:
// Check that missing or malformed cir.triple attributes read by -cir-to-llvm do
// not cause asserts or compiler crashes, and are diagnosed properly.
+//
+// Malformed cir.triple attributes are rejected by the CIR dialect verifier; see
+// IR/invalid-triple.cir.
// Missing cir.triple.
!s32i = !cir.int<s, 32>
-// expected-warning @below {{module is missing cir.triple attribute}}
-// expected-error @below {{cannot lower cir.cpuid op: module is missing cir.triple attribute}}
+// expected-error @below {{Module has no target triple}}
module {
cir.func @missing_triple(%p: !cir.ptr<!s32i>, %a: !s32i, %b: !s32i) {
// expected-error @below {{failed to legalize operation 'cir.cpuid'}}
@@ -22,21 +24,6 @@ module {
// -----
-// Non-string cir.triple.
-
-!s32i = !cir.int<s, 32>
-// expected-warning @below {{expected a string from module attribute cir.triple}}
-// expected-error @below {{cannot lower cir.cpuid op: expected a string from module attribute cir.triple}}
-module attributes {cir.triple = 42 : i32} {
- cir.func @non_string_triple(%p: !cir.ptr<!s32i>, %a: !s32i, %b: !s32i) {
- // expected-error @below {{failed to legalize operation 'cir.cpuid'}}
- cir.cpuid %p, %a, %b : !cir.ptr<!s32i>, !s32i, !s32i
- cir.return
- }
-}
-
-// -----
-
// Valid cir.triple.
!s32i = !cir.int<s, 32>
diff --git a/clang/test/CIR/Transforms/lowering-prepare-module-attrs.cir b/clang/test/CIR/Transforms/lowering-prepare-module-attrs.cir
index f42bad16d7bc3..8ff76ba35e370 100644
--- a/clang/test/CIR/Transforms/lowering-prepare-module-attrs.cir
+++ b/clang/test/CIR/Transforms/lowering-prepare-module-attrs.cir
@@ -6,11 +6,14 @@
// -cir-lowering-prepare do not cause asserts or compiler crashes, and are
// diagnosed properly. The pass should fail on bad attributes, so only modules
// with valid attributes are printed.
+//
+// Malformed cir.triple and cir.opt_info attributes are rejected by the CIR
+// dialect verifier; see IR/invalid-triple.cir and IR/invalid-opt-info.cir.
// Missing cir.triple.
-// expected-error @below {{cannot create a CIR lower module for LoweringPrepare pass: module is missing cir.triple attribute}}
+// expected-error @below {{cannot create a CIR lower module for LoweringPrepare pass}}
module {
cir.func @missing_triple() {
cir.return
@@ -19,50 +22,6 @@ module {
// -----
-// Non-string cir.triple.
-
-// expected-error @below {{cannot create a CIR lower module for LoweringPrepare pass: expected a string from module attribute cir.triple}}
-module attributes {cir.triple = 42 : i32} {
- cir.func @non_string_triple() {
- cir.return
- }
-}
-
-// -----
-
-// Empty cir.triple.
-
-// expected-error @below {{cannot create a CIR lower module for LoweringPrepare pass: unknown triple '' in cir.triple attribute}}
-module attributes {cir.triple = ""} {
- cir.func @empty_triple() {
- cir.return
- }
-}
-
-// -----
-
-// Malformed cir.triple.
-
-// expected-error @below {{cannot create a CIR lower module for LoweringPrepare pass: unknown triple 'garbage' in cir.triple attribute}}
-module attributes {cir.triple = "garbage"} {
- cir.func @malformed_triple() {
- cir.return
- }
-}
-
-// -----
-
-// Well-formed cir.triple with an unknown target.
-
-// expected-error @below {{cannot create a CIR lower module for LoweringPrepare pass: unknown triple 'foobar-unknown-unknown' in cir.triple attribute}}
-module attributes {cir.triple = "foobar-unknown-unknown"} {
- cir.func @unknown_triple() {
- cir.return
- }
-}
-
-// -----
-
// Valid cir.triple without cir.opt_info.
module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
@@ -85,46 +44,3 @@ module attributes {
cir.return
}
}
-
-// -----
-
-// Valid cir.triple with a cir.opt_info that is not an OptInfoAttr.
-
-// expected-error @below {{cannot create a CIR lower module for LoweringPrepare pass: malformed cir.opt_info attribute}}
-module attributes {
- cir.triple = "x86_64-unknown-linux-gnu",
- cir.opt_info = 1 : i32
-} {
- cir.func @malformed_opt_info() {
- cir.return
- }
-}
-
-// -----
-
-// Valid cir.triple with a string cir.opt_info.
-
-// expected-error @below {{cannot create a CIR lower module for LoweringPrepare pass: malformed cir.opt_info attribute}}
-module attributes {
- cir.triple = "x86_64-unknown-linux-gnu",
- cir.opt_info = "O2"
-} {
- cir.func @string_opt_info() {
- cir.return
- }
-}
-
-// -----
-
-// Valid cir.triple with a dictionary cir.opt_info that mimics OptInfoAttr's
-// fields.
-
-// expected-error @below {{cannot create a CIR lower module for LoweringPrepare pass: malformed cir.opt_info attribute}}
-module attributes {
- cir.triple = "x86_64-unknown-linux-gnu",
- cir.opt_info = {level = 2 : i32, size = 1 : i32}
-} {
- cir.func @dict_opt_info() {
- cir.return
- }
-}
diff --git a/clang/test/CIR/Transforms/target-lowering-module-attrs.cir b/clang/test/CIR/Transforms/target-lowering-module-attrs.cir
index 36813d4d707a4..6c507cd2d5597 100644
--- a/clang/test/CIR/Transforms/target-lowering-module-attrs.cir
+++ b/clang/test/CIR/Transforms/target-lowering-module-attrs.cir
@@ -5,11 +5,14 @@
// -cir-target-lowering do not cause asserts or compiler crashes, and are
// diagnosed properly. The pass should warn and skip instead of failing, so
// every module is still printed.
+//
+// Malformed cir.triple and cir.opt_info attributes are rejected by the CIR
+// dialect verifier; see IR/invalid-triple.cir and IR/invalid-opt-info.cir.
// Missing cir.triple.
-// expected-warning @below {{cannot create a CIR lower module, skipping the TargetLowering pass: module is missing cir.triple attribute}}
+// expected-warning @below {{cannot create a CIR lower module, skipping the TargetLowering pass}}
module {
// CHECK-LABEL: cir.func @missing_triple(
cir.func @missing_triple() {
@@ -19,54 +22,6 @@ module {
// -----
-// Non-string cir.triple.
-
-// expected-warning @below {{cannot create a CIR lower module, skipping the TargetLowering pass: expected a string from module attribute cir.triple}}
-module attributes {cir.triple = 42 : i32} {
- // CHECK-LABEL: cir.func @non_string_triple(
- cir.func @non_string_triple() {
- cir.return
- }
-}
-
-// -----
-
-// Empty cir.triple.
-
-// expected-warning @below {{cannot create a CIR lower module, skipping the TargetLowering pass: unknown triple '' in cir.triple attribute}}
-module attributes {cir.triple = ""} {
- // CHECK-LABEL: cir.func @empty_triple(
- cir.func @empty_triple() {
- cir.return
- }
-}
-
-// -----
-
-// Malformed cir.triple.
-
-// expected-warning @below {{cannot create a CIR lower module, skipping the TargetLowering pass: unknown triple 'garbage' in cir.triple attribute}}
-module attributes {cir.triple = "garbage"} {
- // CHECK-LABEL: cir.func @malformed_triple(
- cir.func @malformed_triple() {
- cir.return
- }
-}
-
-// -----
-
-// Well-formed cir.triple with an unknown target.
-
-// expected-warning @below {{cannot create a CIR lower module, skipping the TargetLowering pass: unknown triple 'foobar-unknown-unknown' in cir.triple attribute}}
-module attributes {cir.triple = "foobar-unknown-unknown"} {
- // CHECK-LABEL: cir.func @unknown_triple(
- cir.func @unknown_triple() {
- cir.return
- }
-}
-
-// -----
-
// Valid cir.triple without cir.opt_info.
module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
@@ -89,49 +44,3 @@ module attributes {
cir.return
}
}
-
-// -----
-
-// Valid cir.triple with a cir.opt_info that is not an OptInfoAttr.
-
-// expected-warning @below {{cannot create a CIR lower module, skipping the TargetLowering pass: malformed cir.opt_info attribute}}
-module attributes {
- cir.triple = "x86_64-unknown-linux-gnu",
- cir.opt_info = 1 : i32
-} {
- // CHECK-LABEL: cir.func @malformed_opt_info(
- cir.func @malformed_opt_info() {
- cir.return
- }
-}
-
-// -----
-
-// Valid cir.triple with a string cir.opt_info.
-
-// expected-warning @below {{cannot create a CIR lower module, skipping the TargetLowering pass: malformed cir.opt_info attribute}}
-module attributes {
- cir.triple = "x86_64-unknown-linux-gnu",
- cir.opt_info = "O2"
-} {
- // CHECK-LABEL: cir.func @string_opt_info(
- cir.func @string_opt_info() {
- cir.return
- }
-}
-
-// -----
-
-// Valid cir.triple with a dictionary cir.opt_info that mimics OptInfoAttr's
-// fields.
-
-// expected-warning @below {{cannot create a CIR lower module, skipping the TargetLowering pass: malformed cir.opt_info attribute}}
-module attributes {
- cir.triple = "x86_64-unknown-linux-gnu",
- cir.opt_info = {level = 2 : i32, size = 1 : i32}
-} {
- // CHECK-LABEL: cir.func @dict_opt_info(
- cir.func @dict_opt_info() {
- cir.return
- }
-}
>From 2ac4c32b68aa944fb02895b9cfa1db1f9802ccdd Mon Sep 17 00:00:00 2001
From: "Li, Ian" <ian.li at intel.com>
Date: Tue, 13 Oct 2026 22:05:33 -0700
Subject: [PATCH 17/20] clang-format
---
clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 14 +++++++-------
.../lib/CIR/Dialect/Transforms/CXXABILowering.cpp | 2 +-
.../lib/CIR/Dialect/Transforms/LoweringPrepare.cpp | 2 +-
.../lib/CIR/Dialect/Transforms/TargetLowering.cpp | 2 +-
.../Transforms/TargetLowering/LowerModule.cpp | 3 +--
5 files changed, 11 insertions(+), 12 deletions(-)
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index a80c311d42a93..ff375bba317d9 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -299,9 +299,9 @@ cir::CIRDialect::verifyOperationAttribute(mlir::Operation *op,
// "Validate" our triple by checking if it can successfully initialize into
// a TargetInfo:
if (!clang::targets::AllocateTarget(triple, targetOptions)) {
- return op->emitOpError() << "unknown triple '" << tripleStr.getValue()
- << "' in '" << getTripleAttrName()
- << "' attribute";
+ return op->emitOpError()
+ << "unknown triple '" << tripleStr.getValue() << "' in '"
+ << getTripleAttrName() << "' attribute";
}
}
@@ -310,9 +310,9 @@ cir::CIRDialect::verifyOperationAttribute(mlir::Operation *op,
// Checks whether or not OptInfoAttr is even parseable; opt info range
// sanity checks are done in OptInfoAttr::verify.
if (!optInfo)
- return op->emitOpError() << "malformed "
- << cir::CIRDialect::getOptInfoAttrName()
- << " attribute";
+ return op->emitOpError()
+ << "malformed " << cir::CIRDialect::getOptInfoAttrName()
+ << " attribute";
}
return success();
@@ -433,7 +433,7 @@ static LogicalResult verifyProducedBy(Operation *op, Value operand,
std::optional<llvm::Triple> cir::getTripleFromModule(mlir::ModuleOp mod) {
// Verifying the validity of the triple attribute happens in
// cir::CIRDialect::verifyOperationAttribute; verifyOperationAttribute
- // should error first if we have an invalid attribute.
+ // should error first if we have an invalid attribute.
if (!mod->hasAttr(cir::CIRDialect::getTripleAttrName()))
return std::nullopt;
diff --git a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
index 6f4fa4176890c..787948cece149 100644
--- a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
@@ -904,7 +904,7 @@ void CXXABILoweringPass::runOnOperation() {
// If lower module is not available, skip the ABI lowering pass.
if (!lowerModule) {
mod.emitWarning("cannot create a CIR lower module, skipping the ")
- << getName() << " pass: ";
+ << getName() << " pass: ";
return;
}
diff --git a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
index 13d12012423c6..46c1b19d1b0fc 100644
--- a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
@@ -3184,7 +3184,7 @@ void LoweringPreparePass::runOnOperation() {
lowerModule = cir::createLowerModule(mlirModule);
if (!lowerModule) {
mlirModule.emitError("cannot create a CIR lower module for ")
- << getName() << " pass: ";
+ << getName() << " pass: ";
return signalPassFailure();
}
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering.cpp
index 40e956c540471..8e087a4fbf09a 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering.cpp
@@ -300,7 +300,7 @@ void TargetLoweringPass::runOnOperation() {
// If lower module is not available, skip the target lowering pass.
if (!lowerModule) {
mod.emitWarning("cannot create a CIR lower module, skipping the ")
- << getName() << " pass: ";
+ << getName() << " pass: ";
return;
}
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
index f05fe7a1645c0..951836d8d5839 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
@@ -79,8 +79,7 @@ const TargetLoweringInfo &LowerModule::getTargetLoweringInfo() {
}
// TODO: not to create it every time
-std::unique_ptr<LowerModule>
-createLowerModule(mlir::ModuleOp module) {
+std::unique_ptr<LowerModule> createLowerModule(mlir::ModuleOp module) {
// If the triple is not present, e.g. CIR modules parsed from text, we
// cannot init LowerModule properly.
assert(!cir::MissingFeatures::makeTripleAlwaysPresent());
>From eb0f96ee80c38c09444bb73dc6518966cb67e15a Mon Sep 17 00:00:00 2001
From: "Li, Ian" <ian.li at intel.com>
Date: Wed, 14 Oct 2026 00:51:01 -0700
Subject: [PATCH 18/20] throw missing triple diagnosis again after removing
diagnostics from createLowerModule
---
clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 6 +++---
.../CIR/Dialect/Transforms/CXXABILowering.cpp | 16 +++++++++++-----
.../CIR/Dialect/Transforms/LoweringPrepare.cpp | 9 ++++++++-
.../CIR/Dialect/Transforms/TargetLowering.cpp | 14 ++++++++++----
.../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 14 ++++++++++----
.../CIR/Lowering/cir-to-llvm-module-attrs.cir | 2 +-
.../Transforms/cxx-abi-lowering-bad-attrs.cir | 17 +++++++++--------
.../lowering-prepare-module-attrs.cir | 5 ++---
.../Transforms/target-lowering-module-attrs.cir | 9 ++++-----
9 files changed, 58 insertions(+), 34 deletions(-)
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index ff375bba317d9..c1952f465de2d 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -431,9 +431,6 @@ static LogicalResult verifyProducedBy(Operation *op, Value operand,
}
std::optional<llvm::Triple> cir::getTripleFromModule(mlir::ModuleOp mod) {
- // Verifying the validity of the triple attribute happens in
- // cir::CIRDialect::verifyOperationAttribute; verifyOperationAttribute
- // should error first if we have an invalid attribute.
if (!mod->hasAttr(cir::CIRDialect::getTripleAttrName()))
return std::nullopt;
@@ -442,6 +439,9 @@ std::optional<llvm::Triple> cir::getTripleFromModule(mlir::ModuleOp mod) {
if (!tripleAttr)
return std::nullopt;
+ // Verifying the validity of the triple attribute happens in
+ // cir::CIRDialect::verifyOperationAttribute; verifyOperationAttribute
+ // should error first if we have an invalid attribute.
return llvm::Triple{tripleAttr.getValue()};
}
diff --git a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
index 787948cece149..055874e7dcce1 100644
--- a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
@@ -898,16 +898,22 @@ populateCXXABIConversionTarget(mlir::ConversionTarget &target,
void CXXABILoweringPass::runOnOperation() {
auto mod = mlir::cast<mlir::ModuleOp>(getOperation());
+ // Triple attribute is required by createLowerModule:
+ if (!mod->hasAttr(cir::CIRDialect::getTripleAttrName())) {
+ mod.emitError() << getArgument()
+ << " requires a module with a '"
+ << cir::CIRDialect::getTripleAttrName() << "' attribute";
+ return signalPassFailure();
+ }
+
mlir::MLIRContext *ctx = mod.getContext();
std::unique_ptr<cir::LowerModule> lowerModule = cir::createLowerModule(mod);
- // If lower module is not available, skip the ABI lowering pass.
if (!lowerModule) {
- mod.emitWarning("cannot create a CIR lower module, skipping the ")
- << getName() << " pass: ";
- return;
+ mod.emitError() << "cannot create a CIR lower module for " << getName()
+ << " pass";
+ return signalPassFailure();
}
-
mlir::DataLayout dataLayout(mod);
CIRABITypeConverter typeConverter(*ctx, dataLayout, *lowerModule);
diff --git a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
index 46c1b19d1b0fc..4910fff56d7d3 100644
--- a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
@@ -3180,11 +3180,18 @@ void LoweringPreparePass::buildCUDARegisterVars(cir::CIRBaseBuilderTy &builder,
void LoweringPreparePass::runOnOperation() {
mlirModule = getOperation();
+ // Triple attribute is required by createLowerModule:
+ if (!mlirModule->hasAttr(CIRDialect::getTripleAttrName())) {
+ mlirModule.emitError() << getArgument()
+ << " requires a module with a '"
+ << CIRDialect::getTripleAttrName() << "' attribute";
+ return signalPassFailure();
+ }
lowerModule = cir::createLowerModule(mlirModule);
if (!lowerModule) {
mlirModule.emitError("cannot create a CIR lower module for ")
- << getName() << " pass: ";
+ << getName() << " pass";
return signalPassFailure();
}
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering.cpp
index 8e087a4fbf09a..5d9e097a259f4 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering.cpp
@@ -296,12 +296,18 @@ populateTargetLoweringConversionTarget(mlir::ConversionTarget &target,
void TargetLoweringPass::runOnOperation() {
auto mod = mlir::cast<mlir::ModuleOp>(getOperation());
+ // Triple attribute is required by createLowerModule:
+ if (!mod->hasAttr(CIRDialect::getTripleAttrName())) {
+ mod.emitError() << getArgument() << " requires a module with a '"
+ << CIRDialect::getTripleAttrName() << "' attribute";
+ return signalPassFailure();
+ }
+
std::unique_ptr<cir::LowerModule> lowerModule = cir::createLowerModule(mod);
- // If lower module is not available, skip the target lowering pass.
if (!lowerModule) {
- mod.emitWarning("cannot create a CIR lower module, skipping the ")
- << getName() << " pass: ";
- return;
+ mod.emitError() << "cannot create a CIR lower module for " << getName()
+ << " pass";
+ return signalPassFailure();
}
const auto &targetInfo = lowerModule->getTargetLoweringInfo();
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 0c77affa835ad..6780635832ec1 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -5818,6 +5818,16 @@ mlir::LogicalResult CIRToLLVMTokenNoneOpLowering::matchAndRewrite(
mlir::LogicalResult CIRToLLVMCpuIdOpLowering::matchAndRewrite(
cir::CpuIdOp op, OpAdaptor adaptor,
mlir::ConversionPatternRewriter &rewriter) const {
+ mlir::ModuleOp moduleOp = op->getParentOfType<mlir::ModuleOp>();
+ std::optional<llvm::Triple> triple = cir::getTripleFromModule(moduleOp);
+ if (!triple) {
+ moduleOp.emitError() << "cannot lower " << op.getOperationName() << " "
+ << "without a '"
+ << cir::CIRDialect::getTripleAttrName() << "' "
+ << "attribute";
+ return mlir::failure();
+ }
+
mlir::Type i32Ty = rewriter.getI32Type();
mlir::Type i64Ty = rewriter.getI64Type();
mlir::Type i32PtrTy = mlir::LLVM::LLVMPointerType::get(i32Ty.getContext(), 0);
@@ -5829,10 +5839,6 @@ mlir::LogicalResult CIRToLLVMCpuIdOpLowering::matchAndRewrite(
mlir::Value subFunctionId = adaptor.getSubFunctionId();
StringRef asmString, constraints;
- mlir::ModuleOp moduleOp = op->getParentOfType<mlir::ModuleOp>();
- std::optional<llvm::Triple> triple = cir::getTripleFromModule(moduleOp);
- if (!triple)
- return mlir::failure();
if (triple->getArch() == llvm::Triple::x86) {
asmString = "cpuid";
constraints = "={ax},={bx},={cx},={dx},{ax},{cx}";
diff --git a/clang/test/CIR/Lowering/cir-to-llvm-module-attrs.cir b/clang/test/CIR/Lowering/cir-to-llvm-module-attrs.cir
index 6c208074c1b9f..3cc4ecec41bc7 100644
--- a/clang/test/CIR/Lowering/cir-to-llvm-module-attrs.cir
+++ b/clang/test/CIR/Lowering/cir-to-llvm-module-attrs.cir
@@ -13,7 +13,7 @@
// Missing cir.triple.
!s32i = !cir.int<s, 32>
-// expected-error @below {{Module has no target triple}}
+// expected-error @below {{cannot lower cir.cpuid without a 'cir.triple' attribute}}
module {
cir.func @missing_triple(%p: !cir.ptr<!s32i>, %a: !s32i, %b: !s32i) {
// expected-error @below {{failed to legalize operation 'cir.cpuid'}}
diff --git a/clang/test/CIR/Transforms/cxx-abi-lowering-bad-attrs.cir b/clang/test/CIR/Transforms/cxx-abi-lowering-bad-attrs.cir
index b6ce3bbf0e6c2..67e6b78504f6d 100644
--- a/clang/test/CIR/Transforms/cxx-abi-lowering-bad-attrs.cir
+++ b/clang/test/CIR/Transforms/cxx-abi-lowering-bad-attrs.cir
@@ -1,9 +1,10 @@
// RUN: cir-opt %s -cir-cxxabi-lowering -verify-diagnostics -split-input-file
-// RUN: cir-opt %s -cir-cxxabi-lowering -split-input-file 2>/dev/null | FileCheck %s
+// RUN: not cir-opt %s -cir-cxxabi-lowering -split-input-file 2>/dev/null \
+// RUN: | FileCheck %s --implicit-check-not=cir.func
-// Check that missing cir.triple module attribute does not cause asserts or
-// compiler crashes in -cir-cxxabi-lowering, and is diagnosed properly. The pass
-// should warn and skip instead of failing. so every module is still printed.
+// Check that a missing cir.triple module attribute required by -cir-cxxabi-
+// lowering does not cause asserts or compiler crashes, and is diagnosed
+// properly.
//
// Malformed cir.triple and cir.opt_info attributes are rejected by the CIR
// dialect verifier; see IR/invalid-triple.cir and IR/invalid-opt-info.cir.
@@ -11,9 +12,8 @@
// Missing cir.triple.
-// expected-warning @below {{cannot create a CIR lower module, skipping the CXXABILowering pass}}
+// expected-error @below {{cir-cxxabi-lowering requires a module with a 'cir.triple' attribute}}
module {
- // CHECK-LABEL: cir.func @missing_triple(
cir.func @missing_triple() {
cir.return
}
@@ -21,9 +21,10 @@ module {
// -----
-// expected-warning @below {{cannot create a CIR lower module, skipping the CXXABILowering pass}}
+// Missing cir.triple with a valid cir.opt_info.
+
+// expected-error @below {{cir-cxxabi-lowering requires a module with a 'cir.triple' attribute}}
module attributes {cir.opt_info = #cir.opt_info<level = 0, size = 1>} {
- // CHECK-LABEL: cir.func @missing_triple(
cir.func @missing_triple() {
cir.return
}
diff --git a/clang/test/CIR/Transforms/lowering-prepare-module-attrs.cir b/clang/test/CIR/Transforms/lowering-prepare-module-attrs.cir
index 8ff76ba35e370..43215f72b8338 100644
--- a/clang/test/CIR/Transforms/lowering-prepare-module-attrs.cir
+++ b/clang/test/CIR/Transforms/lowering-prepare-module-attrs.cir
@@ -4,8 +4,7 @@
// Check that missing or malformed module attributes required/used by
// -cir-lowering-prepare do not cause asserts or compiler crashes, and are
-// diagnosed properly. The pass should fail on bad attributes, so only modules
-// with valid attributes are printed.
+// diagnosed properly.
//
// Malformed cir.triple and cir.opt_info attributes are rejected by the CIR
// dialect verifier; see IR/invalid-triple.cir and IR/invalid-opt-info.cir.
@@ -13,7 +12,7 @@
// Missing cir.triple.
-// expected-error @below {{cannot create a CIR lower module for LoweringPrepare pass}}
+// expected-error @below {{cir-lowering-prepare requires a module with a 'cir.triple' attribute}}
module {
cir.func @missing_triple() {
cir.return
diff --git a/clang/test/CIR/Transforms/target-lowering-module-attrs.cir b/clang/test/CIR/Transforms/target-lowering-module-attrs.cir
index 6c507cd2d5597..636aed1ee943d 100644
--- a/clang/test/CIR/Transforms/target-lowering-module-attrs.cir
+++ b/clang/test/CIR/Transforms/target-lowering-module-attrs.cir
@@ -1,10 +1,10 @@
// RUN: cir-opt %s -cir-target-lowering -verify-diagnostics -split-input-file
-// RUN: cir-opt %s -cir-target-lowering -split-input-file 2>/dev/null | FileCheck %s
+// RUN: not cir-opt %s -cir-target-lowering -split-input-file 2>/dev/null \
+// RUN: | FileCheck %s --implicit-check-not=cir.func
// Check that missing or malformed module attributes required/used by
// -cir-target-lowering do not cause asserts or compiler crashes, and are
-// diagnosed properly. The pass should warn and skip instead of failing, so
-// every module is still printed.
+// diagnosed properly.
//
// Malformed cir.triple and cir.opt_info attributes are rejected by the CIR
// dialect verifier; see IR/invalid-triple.cir and IR/invalid-opt-info.cir.
@@ -12,9 +12,8 @@
// Missing cir.triple.
-// expected-warning @below {{cannot create a CIR lower module, skipping the TargetLowering pass}}
+// expected-error @below {{cir-target-lowering requires a module with a 'cir.triple' attribute}}
module {
- // CHECK-LABEL: cir.func @missing_triple(
cir.func @missing_triple() {
cir.return
}
>From f61b88bd42c33eee3f6bd054f35b1d6123e92a4e Mon Sep 17 00:00:00 2001
From: "Li, Ian" <ian.li at intel.com>
Date: Wed, 14 Oct 2026 01:16:34 -0700
Subject: [PATCH 19/20] Patch up errors related to current EH ABI Lowering
behavior
---
clang/lib/CIR/Lowering/CIRPasses.cpp | 4 +++-
clang/test/CIR/Lowering/cir-to-llvm-module-attrs.cir | 3 +++
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/clang/lib/CIR/Lowering/CIRPasses.cpp b/clang/lib/CIR/Lowering/CIRPasses.cpp
index 11e8a3ee341f7..84b010efbb263 100644
--- a/clang/lib/CIR/Lowering/CIRPasses.cpp
+++ b/clang/lib/CIR/Lowering/CIRPasses.cpp
@@ -80,7 +80,9 @@ runCIRToCIRPasses(mlir::ModuleOp theModule, mlir::MLIRContext &mlirContext,
std::optional<llvm::Triple> triple = cir::getTripleFromModule(theModule);
if (!triple)
- return mlir::LogicalResult::failure();
+ return theModule.emitError()
+ << "missing '" << cir::CIRDialect::getTripleAttrName()
+ << "' attribute";
auto abiAttr = theModule->getAttrOfType<mlir::StringAttr>(
cir::CIRDialect::getTargetABIAttrName());
diff --git a/clang/test/CIR/Lowering/cir-to-llvm-module-attrs.cir b/clang/test/CIR/Lowering/cir-to-llvm-module-attrs.cir
index 3cc4ecec41bc7..2133b932c67cf 100644
--- a/clang/test/CIR/Lowering/cir-to-llvm-module-attrs.cir
+++ b/clang/test/CIR/Lowering/cir-to-llvm-module-attrs.cir
@@ -13,7 +13,10 @@
// Missing cir.triple.
!s32i = !cir.int<s, 32>
+// FIXME: CIREHABILoweringPass emits an error diagnostic, but returns normally.
+// Make CIREHABILoweringPass return error too, and delete this line:
// expected-error @below {{cannot lower cir.cpuid without a 'cir.triple' attribute}}
+// expected-error @below {{Module has no target triple}}
module {
cir.func @missing_triple(%p: !cir.ptr<!s32i>, %a: !s32i, %b: !s32i) {
// expected-error @below {{failed to legalize operation 'cir.cpuid'}}
>From 5ea820d689cc0c63944de0863a76980a4a00ac6e Mon Sep 17 00:00:00 2001
From: "Li, Ian" <ian.li at intel.com>
Date: Wed, 14 Oct 2026 01:20:31 -0700
Subject: [PATCH 20/20] clang-format
---
clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp | 3 +--
clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp | 5 ++---
clang/lib/CIR/Dialect/Transforms/TargetLowering.cpp | 2 +-
clang/lib/CIR/Lowering/CIRPasses.cpp | 4 ++--
4 files changed, 6 insertions(+), 8 deletions(-)
diff --git a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
index 055874e7dcce1..bb93b4fbb88b8 100644
--- a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
@@ -900,8 +900,7 @@ void CXXABILoweringPass::runOnOperation() {
auto mod = mlir::cast<mlir::ModuleOp>(getOperation());
// Triple attribute is required by createLowerModule:
if (!mod->hasAttr(cir::CIRDialect::getTripleAttrName())) {
- mod.emitError() << getArgument()
- << " requires a module with a '"
+ mod.emitError() << getArgument() << " requires a module with a '"
<< cir::CIRDialect::getTripleAttrName() << "' attribute";
return signalPassFailure();
}
diff --git a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
index 4910fff56d7d3..659e421c4fa0d 100644
--- a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
@@ -3182,9 +3182,8 @@ void LoweringPreparePass::runOnOperation() {
mlirModule = getOperation();
// Triple attribute is required by createLowerModule:
if (!mlirModule->hasAttr(CIRDialect::getTripleAttrName())) {
- mlirModule.emitError() << getArgument()
- << " requires a module with a '"
- << CIRDialect::getTripleAttrName() << "' attribute";
+ mlirModule.emitError() << getArgument() << " requires a module with a '"
+ << CIRDialect::getTripleAttrName() << "' attribute";
return signalPassFailure();
}
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering.cpp
index 5d9e097a259f4..a5bef10f659d9 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering.cpp
@@ -299,7 +299,7 @@ void TargetLoweringPass::runOnOperation() {
// Triple attribute is required by createLowerModule:
if (!mod->hasAttr(CIRDialect::getTripleAttrName())) {
mod.emitError() << getArgument() << " requires a module with a '"
- << CIRDialect::getTripleAttrName() << "' attribute";
+ << CIRDialect::getTripleAttrName() << "' attribute";
return signalPassFailure();
}
diff --git a/clang/lib/CIR/Lowering/CIRPasses.cpp b/clang/lib/CIR/Lowering/CIRPasses.cpp
index 84b010efbb263..97513275dbaca 100644
--- a/clang/lib/CIR/Lowering/CIRPasses.cpp
+++ b/clang/lib/CIR/Lowering/CIRPasses.cpp
@@ -81,8 +81,8 @@ runCIRToCIRPasses(mlir::ModuleOp theModule, mlir::MLIRContext &mlirContext,
std::optional<llvm::Triple> triple = cir::getTripleFromModule(theModule);
if (!triple)
return theModule.emitError()
- << "missing '" << cir::CIRDialect::getTripleAttrName()
- << "' attribute";
+ << "missing '" << cir::CIRDialect::getTripleAttrName()
+ << "' attribute";
auto abiAttr = theModule->getAttrOfType<mlir::StringAttr>(
cir::CIRDialect::getTargetABIAttrName());
More information about the cfe-commits
mailing list