[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
Fri Oct 16 19:09:17 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/27] 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 735146b04c64f6..b57b994bea88c9 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 23fb81e2f706d4..106298629c65e7 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 76ca7114ee5cea..e978acda6cca9f 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 03044286e8cf71..313661ba959f46 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 56fcd0a9b58cda..588bc496bdabaa 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/27] 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 313661ba959f46..afbacbd7987a68 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/27] 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 afbacbd7987a68..4190947e0cb4de 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 6426841e6237f3..d539ad50db866e 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/27] 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 d9018e93628b69..baece7ab02fc71 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 2a5cb9a908a1dc..caa3527a02f118 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 77ce7434c8ed31..e3306227aac5eb 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 4190947e0cb4de..91a6f27ea8b166 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 6e75ce03d14ffd..dc4e3128ca26d4 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 d539ad50db866e..628dc160e251da 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/27] 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 baece7ab02fc71..732d065f81cb3d 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 caa3527a02f118..0136ed1ccd0dc4 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 e3306227aac5eb..72f9c786db08e1 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 91a6f27ea8b166..b6f6031ddaf2da 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 dc4e3128ca26d4..0158c7fe373093 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 628dc160e251da..0903de9c77f202 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/27] 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 fdaf4054410033..0a0c791ae494e3 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/27] 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 732d065f81cb3d..662942fdeda04a 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 0136ed1ccd0dc4..7a208cf4f1b00a 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 b57b994bea88c9..7c7de931fdc70f 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 72f9c786db08e1..668016a432308d 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 106298629c65e7..e35eb52fabda2f 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 e978acda6cca9f..f545fbb6bbecf0 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 b6f6031ddaf2da..a5ee43c544344c 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 588bc496bdabaa..dbd28430c6df34 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 0158c7fe373093..cbc0c515bf2755 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 0903de9c77f202..dc99dd0b439b03 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/27] 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 00000000000000..ed861075a5c36a
--- /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 00000000000000..5d13956c63af4a
--- /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 00000000000000..fc4be2550cb3b0
--- /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 00000000000000..f42bad16d7bc3f
--- /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 00000000000000..36813d4d707a4a
--- /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/27] 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 bebdf3dd57f737..00000000000000
--- 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/27] 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 a74cdbff3d3bdf..8a49790120c5f1 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 ed861075a5c36a..0cf5c4a3327c3f 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/27] 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 662942fdeda04a..764a48787dbd00 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 f7c4955d9ba533..4d62441f26d2c3 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 c7aa0dc68f686b..6f4fa4176890c3 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 5d846af5b64dcd..13d12012423c6e 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 f545fbb6bbecf0..40e956c540471f 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 a5ee43c544344c..f05fe7a1645c06 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 dbd28430c6df34..56fcd0a9b58cda 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/27] 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 4d62441f26d2c3..06c88dfb78d484 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 cbc0c515bf2755..11e8a3ee341f72 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 8a49790120c5f1..0c77affa835ad9 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 1a791d843bb0a4..7b41ca296fefc2 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/27] 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 ed93a419788113..72a8cffc3b0606 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 fc4be2550cb3b0..00000000000000
--- 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/27] 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 52d6afd2c69743..20ccb83694db52 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 00000000000000..a52ae9768689e0
--- /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 5d13956c63af4a..b6ce3bbf0e6c20 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/27] 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 06c88dfb78d484..a80c311d42a937 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/27] 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 0cf5c4a3327c3f..6c208074c1b9fd 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 f42bad16d7bc3f..8ff76ba35e3704 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 36813d4d707a4a..6c507cd2d55975 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/27] 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 a80c311d42a937..ff375bba317d90 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 6f4fa4176890c3..787948cece1494 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 13d12012423c6e..46c1b19d1b0fc7 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 40e956c540471f..8e087a4fbf09ad 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 f05fe7a1645c06..951836d8d58396 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/27] 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 ff375bba317d90..c1952f465de2d7 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 787948cece1494..055874e7dcce1d 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 46c1b19d1b0fc7..4910fff56d7d39 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 8e087a4fbf09ad..5d9e097a259f4f 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 0c77affa835ad9..6780635832ec14 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 6c208074c1b9fd..3cc4ecec41bc70 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 b6ce3bbf0e6c20..67e6b78504f6d0 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 8ff76ba35e3704..43215f72b83385 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 6c507cd2d55975..636aed1ee943d4 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/27] 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 11e8a3ee341f72..84b010efbb2631 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 3cc4ecec41bc70..2133b932c67cf9 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/27] 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 055874e7dcce1d..bb93b4fbb88b8e 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 4910fff56d7d39..659e421c4fa0d8 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 5d9e097a259f4f..a5bef10f659d93 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 84b010efbb2631..97513275dbacaf 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());
>From 31f259f528a8326dd330d827e0b110551b809e24 Mon Sep 17 00:00:00 2001
From: "Li, Ian" <ian.li at intel.com>
Date: Wed, 14 Oct 2026 23:20:28 -0700
Subject: [PATCH 21/27] be more assertive
---
.../CIR/Dialect/Transforms/CXXABILowering.cpp | 15 +++-----
.../Dialect/Transforms/LoweringPrepare.cpp | 13 +++----
.../CIR/Dialect/Transforms/TargetLowering.cpp | 13 +++----
.../Transforms/TargetLowering/LowerModule.cpp | 36 ++++++++++---------
.../Transforms/TargetLowering/LowerModule.h | 18 ++++++++--
.../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 11 +++---
6 files changed, 53 insertions(+), 53 deletions(-)
diff --git a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
index bb93b4fbb88b8e..61e03bae54c80f 100644
--- a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
@@ -898,21 +898,16 @@ 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 (!lowerModule) {
- mod.emitError() << "cannot create a CIR lower module for " << getName()
- << " pass";
+ assert(lowerModule && "LowerModule shouldn't be null");
+ if (!lowerModule->hasTarget()) {
+ mod.emitError() << getArgument() << " requires a module with a '"
+ << cir::CIRDialect::getTripleAttrName() << "' attribute";
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 659e421c4fa0d8..eb2e09baddc3eb 100644
--- a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
@@ -3180,17 +3180,12 @@ 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";
+ assert(lowerModule && "LowerModule shouldn't be null");
+ if (!lowerModule->hasTarget()) {
+ 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 a5bef10f659d93..bbe84e851eaa89 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering.cpp
@@ -296,17 +296,12 @@ 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 (!lowerModule) {
- mod.emitError() << "cannot create a CIR lower module for " << getName()
- << " pass";
+ assert(lowerModule && "LowerModule shouldn't be null");
+ if (!lowerModule->hasTarget()) {
+ mod.emitError() << getArgument() << " requires a module with a '"
+ << cir::CIRDialect::getTripleAttrName() << "' attribute";
return signalPassFailure();
}
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
index 951836d8d58396..505803d1a8cbf2 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
@@ -69,8 +69,10 @@ LowerModule::LowerModule(clang::LangOptions langOpts,
clang::CodeGenOptions codeGenOpts,
mlir::ModuleOp &module,
std::unique_ptr<clang::TargetInfo> target)
- : module(module), langOpts(std::move(langOpts)), target(std::move(target)),
- abi(createCXXABI(*this)) {}
+ : module(module), langOpts(std::move(langOpts)), target(std::move(target)) {
+ if (this->target)
+ abi = createCXXABI(*this);
+}
const TargetLoweringInfo &LowerModule::getTargetLoweringInfo() {
if (!targetLoweringInfo)
@@ -80,19 +82,21 @@ const TargetLoweringInfo &LowerModule::getTargetLoweringInfo() {
// TODO: not to create it every time
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.
+ // If the triple is not present, e.g. CIR modules parsed from text,
+ // LowerModule currently gets created with null target and abi. If triple
+ // becomes a requirement, we should not allow LowerModules to be created with
+ // null target and abi.
assert(!cir::MissingFeatures::makeTripleAlwaysPresent());
// Fetch target information.
- 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)
- return nullptr;
+ std::unique_ptr<clang::TargetInfo> targetInfo;
+ if (std::optional<llvm::Triple> triple = cir::getTripleFromModule(module)) {
+ clang::TargetOptions targetOptions;
+ targetOptions.Triple = triple->str();
+ targetInfo = clang::targets::AllocateTarget(*triple, targetOptions);
+ assert(targetInfo &&
+ "bad cir.triple should have been rejected by the verifier");
+ }
// Populate the lowering-relevant LangOptions from the module's
// #cir.lowering_lang_options attribute so a reloaded .cir lowers the same
@@ -122,10 +126,10 @@ std::unique_ptr<LowerModule> createLowerModule(mlir::ModuleOp module) {
if (auto optAttr = module->getAttr(cir::CIRDialect::getOptInfoAttrName())) {
auto optInfo = mlir::dyn_cast<cir::OptInfoAttr>(optAttr);
- if (!optInfo)
- return nullptr;
- codeGenOpts.OptimizationLevel = optInfo.getLevel();
- codeGenOpts.OptimizeSize = optInfo.getSize();
+ if (optInfo) {
+ codeGenOpts.OptimizationLevel = optInfo.getLevel();
+ codeGenOpts.OptimizeSize = optInfo.getSize();
+ }
}
return std::make_unique<LowerModule>(std::move(langOpts),
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h
index 56fcd0a9b58cda..41c3e121b1ff41 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h
@@ -47,11 +47,25 @@ class LowerModule {
clang::TargetCXXABI::Kind getCXXABIKind() const {
assert(!cir::MissingFeatures::lowerModuleLangOpts());
+ assert(target && "No C++ ABI kind without a target (missing cir.triple)");
return target->getCXXABI().getKind();
}
+ CIRCXXABI &getCXXABI() const {
+ assert(abi && "No C++ ABI without a target (missing cir.triple)");
+ return *abi;
+ }
+
+ bool hasTarget() const {
+ // Null target means module had no cir.triple; but when cir.triple becomes
+ // mandatory this function becomes useless.
+ assert(!cir::MissingFeatures::makeTripleAlwaysPresent());
+ return target != nullptr;
+ }
+ const clang::TargetInfo &getTarget() const {
+ assert(target && "LowerModule has no target (missing cir.triple)");
+ return *target;
+ }
- CIRCXXABI &getCXXABI() const { return *abi; }
- const clang::TargetInfo &getTarget() const { return *target; }
mlir::MLIRContext *getMLIRContext() { return module.getContext(); }
const TargetLoweringInfo &getTargetLoweringInfo();
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 6780635832ec14..348013b79a8ce6 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -5820,13 +5820,10 @@ mlir::LogicalResult CIRToLLVMCpuIdOpLowering::matchAndRewrite(
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();
- }
+ if (!triple)
+ return op.emitOpError() << "requires a '"
+ << cir::CIRDialect::getTripleAttrName()
+ << "' module attribute";
mlir::Type i32Ty = rewriter.getI32Type();
mlir::Type i64Ty = rewriter.getI64Type();
>From ceb7133978e3554713537f0dbb67edb0e47316c0 Mon Sep 17 00:00:00 2001
From: "Li, Ian" <ian.li at intel.com>
Date: Wed, 14 Oct 2026 23:23:00 -0700
Subject: [PATCH 22/27] delete cir-to-llvm-module-attrs test
---
.../CIR/Lowering/cir-to-llvm-module-attrs.cir | 39 -------------------
1 file changed, 39 deletions(-)
delete mode 100644 clang/test/CIR/Lowering/cir-to-llvm-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
deleted file mode 100644
index 2133b932c67cf9..00000000000000
--- a/clang/test/CIR/Lowering/cir-to-llvm-module-attrs.cir
+++ /dev/null
@@ -1,39 +0,0 @@
-// 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 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>
-// 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'}}
- 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
- }
-}
>From 2471db0803b7763a148cbcb2d480c699fdeb24ef Mon Sep 17 00:00:00 2001
From: "Li, Ian" <ian.li at intel.com>
Date: Wed, 14 Oct 2026 23:27:33 -0700
Subject: [PATCH 23/27] clang-format
---
clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 348013b79a8ce6..89230f2ecb2386 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -5821,9 +5821,9 @@ mlir::LogicalResult CIRToLLVMCpuIdOpLowering::matchAndRewrite(
mlir::ModuleOp moduleOp = op->getParentOfType<mlir::ModuleOp>();
std::optional<llvm::Triple> triple = cir::getTripleFromModule(moduleOp);
if (!triple)
- return op.emitOpError() << "requires a '"
- << cir::CIRDialect::getTripleAttrName()
- << "' module attribute";
+ return op.emitOpError()
+ << "requires a '" << cir::CIRDialect::getTripleAttrName()
+ << "' module attribute";
mlir::Type i32Ty = rewriter.getI32Type();
mlir::Type i64Ty = rewriter.getI64Type();
>From d2d42229f1dcb51eb8f95b4393a263f33741a651 Mon Sep 17 00:00:00 2001
From: "Li, Ian" <ian.li at intel.com>
Date: Wed, 14 Oct 2026 23:47:09 -0700
Subject: [PATCH 24/27] fix code style
---
clang/include/clang/CIR/Dialect/IR/CIRDialect.h | 4 ++++
clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 12 ++++--------
.../Transforms/TargetLowering/LowerModule.cpp | 10 ++++------
.../Dialect/Transforms/TargetLowering/LowerModule.h | 2 +-
clang/lib/CIR/Lowering/CIRPasses.cpp | 6 +++---
...d-attrs.cir => cxx-abi-lowering-module-attrs.cir} | 0
6 files changed, 16 insertions(+), 18 deletions(-)
rename clang/test/CIR/Transforms/{cxx-abi-lowering-bad-attrs.cir => cxx-abi-lowering-module-attrs.cir} (100%)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
index 764a48787dbd00..43d31f93c5af77 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
+++ b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
@@ -34,6 +34,10 @@
#include "clang/CIR/Interfaces/CIROpInterfaces.h"
#include "clang/CIR/MissingFeatures.h"
+#include "llvm/TargetParser/Triple.h"
+
+#include <optional>
+
using BuilderCallbackRef =
llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)>;
using BuilderOpStateCallbackRef = llvm::function_ref<void(
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index c1952f465de2d7..4a20798cf4cdf5 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -293,16 +293,15 @@ cir::CIRDialect::verifyOperationAttribute(mlir::Operation *op,
if (!tripleStr)
return op->emitOpError() << "expects '" << getTripleAttrName() << "' to "
<< "be a string";
- llvm::Triple triple = llvm::Triple(tripleStr.getValue());
+ llvm::Triple 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)) {
+ if (!clang::targets::AllocateTarget(triple, targetOptions))
return op->emitOpError()
<< "unknown triple '" << tripleStr.getValue() << "' in '"
<< getTripleAttrName() << "' attribute";
- }
}
if (attrName == getOptInfoAttrName()) {
@@ -431,11 +430,8 @@ static LogicalResult verifyProducedBy(Operation *op, Value operand,
}
std::optional<llvm::Triple> cir::getTripleFromModule(mlir::ModuleOp mod) {
- if (!mod->hasAttr(cir::CIRDialect::getTripleAttrName()))
- return std::nullopt;
-
- auto tripleAttr = mod->getAttrOfType<mlir::StringAttr>(
- cir::CIRDialect::getTripleAttrName());
+ auto tripleAttr =
+ mod->getAttrOfType<mlir::StringAttr>(CIRDialect::getTripleAttrName());
if (!tripleAttr)
return std::nullopt;
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
index 505803d1a8cbf2..8d5e784ae02884 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
@@ -124,12 +124,10 @@ std::unique_ptr<LowerModule> createLowerModule(mlir::ModuleOp module) {
assert(!cir::MissingFeatures::lowerModuleCodeGenOpts());
clang::CodeGenOptions codeGenOpts;
- if (auto optAttr = module->getAttr(cir::CIRDialect::getOptInfoAttrName())) {
- auto optInfo = mlir::dyn_cast<cir::OptInfoAttr>(optAttr);
- if (optInfo) {
- codeGenOpts.OptimizationLevel = optInfo.getLevel();
- codeGenOpts.OptimizeSize = optInfo.getSize();
- }
+ if (auto optInfo = mlir::cast_if_present<cir::OptInfoAttr>(
+ module->getAttr(cir::CIRDialect::getOptInfoAttrName()))) {
+ codeGenOpts.OptimizationLevel = optInfo.getLevel();
+ codeGenOpts.OptimizeSize = optInfo.getSize();
}
return std::make_unique<LowerModule>(std::move(langOpts),
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h
index 41c3e121b1ff41..03e0c3a6679b35 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h
@@ -57,7 +57,7 @@ class LowerModule {
bool hasTarget() const {
// Null target means module had no cir.triple; but when cir.triple becomes
- // mandatory this function becomes useless.
+ // mandatory this function should be removed.
assert(!cir::MissingFeatures::makeTripleAlwaysPresent());
return target != nullptr;
}
diff --git a/clang/lib/CIR/Lowering/CIRPasses.cpp b/clang/lib/CIR/Lowering/CIRPasses.cpp
index 97513275dbacaf..50f179b14738ed 100644
--- a/clang/lib/CIR/Lowering/CIRPasses.cpp
+++ b/clang/lib/CIR/Lowering/CIRPasses.cpp
@@ -126,7 +126,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.value());
+ CallConvTarget target = getCallConvTarget(*triple);
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 +141,8 @@ runCIRToCIRPasses(mlir::ModuleOp theModule, mlir::MLIRContext &mlirContext,
loweringLangOpts.getClangAbiCompat());
pm.addPass(mlir::createCallConvLoweringPass(
target, getX86AVXABILevel(abiAttr.getValue()),
- allowsX86TargetAttrAvx(triple.value(), compat),
- getX86ABICompatInfo(triple.value(), compat)));
+ allowsX86TargetAttrAvx(*triple, compat),
+ getX86ABICompatInfo(*triple, compat)));
}
}
diff --git a/clang/test/CIR/Transforms/cxx-abi-lowering-bad-attrs.cir b/clang/test/CIR/Transforms/cxx-abi-lowering-module-attrs.cir
similarity index 100%
rename from clang/test/CIR/Transforms/cxx-abi-lowering-bad-attrs.cir
rename to clang/test/CIR/Transforms/cxx-abi-lowering-module-attrs.cir
>From 64004de6b86fb38b023c464000ea49f1ecac6690 Mon Sep 17 00:00:00 2001
From: "Li, Ian" <ian.li at intel.com>
Date: Wed, 14 Oct 2026 23:56:54 -0700
Subject: [PATCH 25/27] perpetual clang-format
---
clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 2 +-
clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 4a20798cf4cdf5..e2c0882d1a2a0c 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -431,7 +431,7 @@ static LogicalResult verifyProducedBy(Operation *op, Value operand,
std::optional<llvm::Triple> cir::getTripleFromModule(mlir::ModuleOp mod) {
auto tripleAttr =
- mod->getAttrOfType<mlir::StringAttr>(CIRDialect::getTripleAttrName());
+ mod->getAttrOfType<mlir::StringAttr>(CIRDialect::getTripleAttrName());
if (!tripleAttr)
return std::nullopt;
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
index 8d5e784ae02884..978c5f335c5801 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
@@ -125,7 +125,7 @@ std::unique_ptr<LowerModule> createLowerModule(mlir::ModuleOp module) {
clang::CodeGenOptions codeGenOpts;
if (auto optInfo = mlir::cast_if_present<cir::OptInfoAttr>(
- module->getAttr(cir::CIRDialect::getOptInfoAttrName()))) {
+ module->getAttr(cir::CIRDialect::getOptInfoAttrName()))) {
codeGenOpts.OptimizationLevel = optInfo.getLevel();
codeGenOpts.OptimizeSize = optInfo.getSize();
}
>From 579062c9c7162b8692edcee2f95d91b05b9a4b87 Mon Sep 17 00:00:00 2001
From: "Li, Ian" <ian.li at intel.com>
Date: Thu, 15 Oct 2026 12:32:00 -0700
Subject: [PATCH 26/27] Test looser triple validation
---
clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 9 +++------
.../lib/CIR/Dialect/Transforms/CXXABILowering.cpp | 2 +-
.../CIR/Dialect/Transforms/LoweringPrepare.cpp | 3 ++-
.../lib/CIR/Dialect/Transforms/TargetLowering.cpp | 2 +-
.../Transforms/TargetLowering/LowerModule.cpp | 10 ++++------
.../Transforms/TargetLowering/LowerModule.h | 15 ++++++++++-----
.../Transforms/cxx-abi-lowering-module-attrs.cir | 15 +++++++++++++--
.../Transforms/lowering-prepare-module-attrs.cir | 13 ++++++++++++-
.../Transforms/target-lowering-module-attrs.cir | 13 ++++++++++++-
9 files changed, 58 insertions(+), 24 deletions(-)
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index e2c0882d1a2a0c..005558a5e1ec63 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -12,7 +12,6 @@
#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"
@@ -294,11 +293,9 @@ cir::CIRDialect::verifyOperationAttribute(mlir::Operation *op,
return op->emitOpError() << "expects '" << getTripleAttrName() << "' to "
<< "be a string";
llvm::Triple 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))
+ // "Validate" our triple by checking if it has a known architecture;
+ // although not all triples have a corresponding clang TargetInfo.
+ if (triple.getArch() == llvm::Triple::UnknownArch)
return op->emitOpError()
<< "unknown triple '" << tripleStr.getValue() << "' in '"
<< getTripleAttrName() << "' attribute";
diff --git a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
index 61e03bae54c80f..f6c2ea85019ee3 100644
--- a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
@@ -903,7 +903,7 @@ void CXXABILoweringPass::runOnOperation() {
std::unique_ptr<cir::LowerModule> lowerModule = cir::createLowerModule(mod);
assert(lowerModule && "LowerModule shouldn't be null");
if (!lowerModule->hasTarget()) {
- mod.emitError() << getArgument() << " requires a module with a '"
+ mod.emitError() << getArgument() << " requires a module with a supported '"
<< 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 eb2e09baddc3eb..279bb83474612a 100644
--- a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
@@ -3184,7 +3184,8 @@ void LoweringPreparePass::runOnOperation() {
lowerModule = cir::createLowerModule(mlirModule);
assert(lowerModule && "LowerModule shouldn't be null");
if (!lowerModule->hasTarget()) {
- mlirModule.emitError() << getArgument() << " requires a module with a '"
+ mlirModule.emitError() << getArgument()
+ << " requires a module with a supported '"
<< CIRDialect::getTripleAttrName() << "' attribute";
return signalPassFailure();
}
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering.cpp
index bbe84e851eaa89..c196ff0f02cc07 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering.cpp
@@ -300,7 +300,7 @@ void TargetLoweringPass::runOnOperation() {
std::unique_ptr<cir::LowerModule> lowerModule = cir::createLowerModule(mod);
assert(lowerModule && "LowerModule shouldn't be null");
if (!lowerModule->hasTarget()) {
- mod.emitError() << getArgument() << " requires a module with a '"
+ mod.emitError() << getArgument() << " requires a module with a supported '"
<< cir::CIRDialect::getTripleAttrName() << "' attribute";
return signalPassFailure();
}
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
index 978c5f335c5801..f5415cdbd0d3fe 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
@@ -82,10 +82,10 @@ const TargetLoweringInfo &LowerModule::getTargetLoweringInfo() {
// TODO: not to create it every time
std::unique_ptr<LowerModule> createLowerModule(mlir::ModuleOp module) {
- // If the triple is not present, e.g. CIR modules parsed from text,
- // LowerModule currently gets created with null target and abi. If triple
- // becomes a requirement, we should not allow LowerModules to be created with
- // null target and abi.
+ // If the triple is not present, e.g. CIR modules parsed from text, or clang
+ // has no TargetInfo support for it yet, LowerModule currently gets created
+ // with null target and abi. If triple becomes a requirement, we should not
+ // allow LowerModules to be created with null target and abi.
assert(!cir::MissingFeatures::makeTripleAlwaysPresent());
// Fetch target information.
@@ -94,8 +94,6 @@ std::unique_ptr<LowerModule> createLowerModule(mlir::ModuleOp module) {
clang::TargetOptions targetOptions;
targetOptions.Triple = triple->str();
targetInfo = clang::targets::AllocateTarget(*triple, targetOptions);
- assert(targetInfo &&
- "bad cir.triple should have been rejected by the verifier");
}
// Populate the lowering-relevant LangOptions from the module's
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h
index 03e0c3a6679b35..bc9a2a1d3c8890 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h
@@ -47,22 +47,27 @@ class LowerModule {
clang::TargetCXXABI::Kind getCXXABIKind() const {
assert(!cir::MissingFeatures::lowerModuleLangOpts());
- assert(target && "No C++ ABI kind without a target (missing cir.triple)");
+ assert(target &&
+ "No C++ ABI kind without a target (missing/unsupported cir.triple)");
return target->getCXXABI().getKind();
}
CIRCXXABI &getCXXABI() const {
- assert(abi && "No C++ ABI without a target (missing cir.triple)");
+ assert(abi &&
+ "No C++ ABI without a target (missing/unsupported cir.triple)");
return *abi;
}
bool hasTarget() const {
- // Null target means module had no cir.triple; but when cir.triple becomes
- // mandatory this function should be removed.
+ // Null target means module had no cir.triple, or clang has no TargetInfo
+ // for it; but when cir.triple becomes mandatory we need to figure out how
+ // to handle cir.triple's without a corresponding TargetInfo / potentially
+ // removing this function.
assert(!cir::MissingFeatures::makeTripleAlwaysPresent());
return target != nullptr;
}
const clang::TargetInfo &getTarget() const {
- assert(target && "LowerModule has no target (missing cir.triple)");
+ assert(target &&
+ "LowerModule has no target (missing/unsupported cir.triple)");
return *target;
}
diff --git a/clang/test/CIR/Transforms/cxx-abi-lowering-module-attrs.cir b/clang/test/CIR/Transforms/cxx-abi-lowering-module-attrs.cir
index 67e6b78504f6d0..cefb2196c43f20 100644
--- a/clang/test/CIR/Transforms/cxx-abi-lowering-module-attrs.cir
+++ b/clang/test/CIR/Transforms/cxx-abi-lowering-module-attrs.cir
@@ -12,7 +12,7 @@
// Missing cir.triple.
-// expected-error @below {{cir-cxxabi-lowering requires a module with a 'cir.triple' attribute}}
+// expected-error @below {{cir-cxxabi-lowering requires a module with a supported 'cir.triple' attribute}}
module {
cir.func @missing_triple() {
cir.return
@@ -23,7 +23,7 @@ module {
// Missing cir.triple with a valid cir.opt_info.
-// expected-error @below {{cir-cxxabi-lowering requires a module with a 'cir.triple' attribute}}
+// expected-error @below {{cir-cxxabi-lowering requires a module with a supported 'cir.triple' attribute}}
module attributes {cir.opt_info = #cir.opt_info<level = 0, size = 1>} {
cir.func @missing_triple() {
cir.return
@@ -32,6 +32,17 @@ module attributes {cir.opt_info = #cir.opt_info<level = 0, size = 1>} {
// -----
+// cir.triple with a known architecture that clang has no TargetInfo for.
+
+// expected-error @below {{cir-cxxabi-lowering requires a module with a supported 'cir.triple' attribute}}
+module attributes {cir.triple = "spir-unknown-linux"} {
+ cir.func @unsupported_triple() {
+ cir.return
+ }
+}
+
+// -----
+
// Valid cir.triple without cir.opt_info.
module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
diff --git a/clang/test/CIR/Transforms/lowering-prepare-module-attrs.cir b/clang/test/CIR/Transforms/lowering-prepare-module-attrs.cir
index 43215f72b83385..1207ee1384d84b 100644
--- a/clang/test/CIR/Transforms/lowering-prepare-module-attrs.cir
+++ b/clang/test/CIR/Transforms/lowering-prepare-module-attrs.cir
@@ -12,7 +12,7 @@
// Missing cir.triple.
-// expected-error @below {{cir-lowering-prepare requires a module with a 'cir.triple' attribute}}
+// expected-error @below {{cir-lowering-prepare requires a module with a supported 'cir.triple' attribute}}
module {
cir.func @missing_triple() {
cir.return
@@ -21,6 +21,17 @@ module {
// -----
+// cir.triple with a known architecture that clang has no TargetInfo for.
+
+// expected-error @below {{cir-lowering-prepare requires a module with a supported 'cir.triple' attribute}}
+module attributes {cir.triple = "spir-unknown-linux"} {
+ cir.func @unsupported_triple() {
+ cir.return
+ }
+}
+
+// -----
+
// Valid cir.triple without cir.opt_info.
module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
diff --git a/clang/test/CIR/Transforms/target-lowering-module-attrs.cir b/clang/test/CIR/Transforms/target-lowering-module-attrs.cir
index 636aed1ee943d4..69675f142617a5 100644
--- a/clang/test/CIR/Transforms/target-lowering-module-attrs.cir
+++ b/clang/test/CIR/Transforms/target-lowering-module-attrs.cir
@@ -12,7 +12,7 @@
// Missing cir.triple.
-// expected-error @below {{cir-target-lowering requires a module with a 'cir.triple' attribute}}
+// expected-error @below {{cir-target-lowering requires a module with a supported 'cir.triple' attribute}}
module {
cir.func @missing_triple() {
cir.return
@@ -21,6 +21,17 @@ module {
// -----
+// cir.triple with a known architecture that clang has no TargetInfo for.
+
+// expected-error @below {{cir-target-lowering requires a module with a supported 'cir.triple' attribute}}
+module attributes {cir.triple = "spir-unknown-linux"} {
+ cir.func @unsupported_triple() {
+ cir.return
+ }
+}
+
+// -----
+
// Valid cir.triple without cir.opt_info.
module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
>From 3cf376dd4e7c5943a9963d66615149263bc15c67 Mon Sep 17 00:00:00 2001
From: "Li, Ian" <ian.li at intel.com>
Date: Fri, 16 Oct 2026 19:03:05 -0700
Subject: [PATCH 27/27] enforce that module attrs should be attached to a
module
---
clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 10 ++++++++++
clang/test/CIR/IR/invalid-opt-info.cir | 11 +++++++++++
clang/test/CIR/IR/invalid-triple.cir | 11 +++++++++++
3 files changed, 32 insertions(+)
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 005558a5e1ec63..7d66d4d0c689f4 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -288,6 +288,11 @@ cir::CIRDialect::verifyOperationAttribute(mlir::Operation *op,
}
if (attrName == getTripleAttrName()) {
+ if (!mlir::isa<mlir::ModuleOp>(op))
+ return op->emitOpError()
+ << "expects '" << getTripleAttrName() << "' attribute to be "
+ << "attached to '" << mlir::ModuleOp::getOperationName() << "'";
+
auto tripleStr = mlir::dyn_cast<mlir::StringAttr>(attr.getValue());
if (!tripleStr)
return op->emitOpError() << "expects '" << getTripleAttrName() << "' to "
@@ -302,6 +307,11 @@ cir::CIRDialect::verifyOperationAttribute(mlir::Operation *op,
}
if (attrName == getOptInfoAttrName()) {
+ if (!mlir::isa<mlir::ModuleOp>(op))
+ return op->emitOpError()
+ << "expects '" << getOptInfoAttrName() << "' attribute to be "
+ << "attached to '" << mlir::ModuleOp::getOperationName() << "'";
+
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.
diff --git a/clang/test/CIR/IR/invalid-opt-info.cir b/clang/test/CIR/IR/invalid-opt-info.cir
index 20ccb83694db52..401b32f2a2a487 100644
--- a/clang/test/CIR/IR/invalid-opt-info.cir
+++ b/clang/test/CIR/IR/invalid-opt-info.cir
@@ -32,3 +32,14 @@ module attributes {cir.opt_info = "O2"} {}
// expected-error @below {{'builtin.module' op malformed cir.opt_info attribute}}
module attributes {cir.opt_info = {level = 2 : i32, size = 1 : i32}} {}
+
+// -----
+
+// cir.opt_info attached to something other than a module.
+
+module {
+ // expected-error @below {{'cir.func' op expects 'cir.opt_info' attribute to be attached to 'builtin.module'}}
+ cir.func @not_module_attr() attributes {cir.opt_info = #cir.opt_info<level = 2, size = 0>} {
+ cir.return
+ }
+}
diff --git a/clang/test/CIR/IR/invalid-triple.cir b/clang/test/CIR/IR/invalid-triple.cir
index a52ae9768689e0..c53c83ef0488a0 100644
--- a/clang/test/CIR/IR/invalid-triple.cir
+++ b/clang/test/CIR/IR/invalid-triple.cir
@@ -25,3 +25,14 @@ module attributes {cir.triple = "garbage"} {}
// expected-error @below {{'builtin.module' op unknown triple 'foobar-unknown-unknown' in 'cir.triple' attribute}}
module attributes {cir.triple = "foobar-unknown-unknown"} {}
+
+// -----
+
+// cir.triple attached to something other than a module.
+
+module {
+ // expected-error @below {{'cir.func' op expects 'cir.triple' attribute to be attached to 'builtin.module'}}
+ cir.func @not_module_attr() attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+ cir.return
+ }
+}
More information about the cfe-commits
mailing list