[clang] [WIP][CIR] Diagnose missing/bad `cir.triple` and `cir.opt_info` attributes in CIR tests instead of asserts/crashes (PR #230003)
Ian Li via cfe-commits
cfe-commits at lists.llvm.org
Wed Oct 7 23:51:29 PDT 2026
https://github.com/ianayl created https://github.com/llvm/llvm-project/pull/230003
This PR addresses crashes from malformed or missing `cir.triple` or `cir.opt_info` and produces diagnosis messages instead if improper attribute values are used via e.g. `cir-opt` (as per in #227917)
I also added a `cir::getTripleFromModule` helper, which tries to standardize parsing `cir.triple` from modules. But do let me know if this is not flexible enough / should consider more edge cases, or if the helper is overbearing and unnecessary in general.
Assisted-by: Claude was only used to generate the tests in this PR
>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 1/8] issue diagnostics on bad cir.triple instead of asserts
---
.../CIR/Dialect/Transforms/CXXABILowering.cpp | 12 ++++----
.../Dialect/Transforms/LoweringPrepare.cpp | 10 +++++--
.../CIR/Dialect/Transforms/TargetLowering.cpp | 12 ++++----
.../Transforms/TargetLowering/LowerModule.cpp | 30 +++++++++++++++----
.../Transforms/TargetLowering/LowerModule.h | 4 ++-
5 files changed, 49 insertions(+), 19 deletions(-)
diff --git a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
index 735146b04c64f..b57b994bea88c 100644
--- a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
@@ -893,13 +893,15 @@ void CXXABILoweringPass::runOnOperation() {
auto mod = mlir::cast<mlir::ModuleOp>(getOperation());
mlir::MLIRContext *ctx = mod.getContext();
- std::unique_ptr<cir::LowerModule> lowerModule = cir::createLowerModule(mod);
+ auto diag = [&] {
+ return mod.emitWarning("cannot create a CIR lower module, skipping the ")
+ << getName() << " pass: ";
+ };
+ std::unique_ptr<cir::LowerModule> lowerModule = cir::createLowerModule(
+ mod, diag);
// If lower module is not available, skip the ABI lowering pass.
- if (!lowerModule) {
- mod.emitWarning("Cannot create a CIR lower module, skipping the ")
- << getName() << " pass";
+ if (!lowerModule)
return;
- }
mlir::DataLayout dataLayout(mod);
CIRABITypeConverter typeConverter(*ctx, dataLayout, *lowerModule);
diff --git a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
index 23fb81e2f706d..106298629c65e 100644
--- a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
@@ -3061,9 +3061,13 @@ void LoweringPreparePass::buildCUDARegisterVars(cir::CIRBaseBuilderTy &builder,
void LoweringPreparePass::runOnOperation() {
mlirModule = getOperation();
- // CIRGen always sets the triple, so this cannot fail.
- lowerModule = cir::createLowerModule(mlirModule);
- assert(lowerModule && "requires a module with a triple");
+ auto diag = [&] {
+ return mlirModule.emitError("cannot create a CIR lower module for ")
+ << getName() << " pass: ";
+ };
+ lowerModule = cir::createLowerModule(mlirModule, diag);
+ if (!lowerModule)
+ return signalPassFailure();
llvm::SmallVector<mlir::Operation *> opsToTransform;
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering.cpp
index 76ca7114ee5ce..e978acda6cca9 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering.cpp
@@ -296,13 +296,15 @@ populateTargetLoweringConversionTarget(mlir::ConversionTarget &target,
void TargetLoweringPass::runOnOperation() {
auto mod = mlir::cast<mlir::ModuleOp>(getOperation());
- std::unique_ptr<cir::LowerModule> lowerModule = cir::createLowerModule(mod);
+ auto diag = [&] {
+ return mod.emitWarning("cannot create a CIR lower module, skipping the ")
+ << getName() << " pass: ";
+ };
+ std::unique_ptr<cir::LowerModule> lowerModule = cir::createLowerModule(
+ mod, diag);
// If lower module is not available, skip the target lowering pass.
- if (!lowerModule) {
- mod.emitWarning("Cannot create a CIR lower module, skipping the ")
- << getName() << " pass";
+ if (!lowerModule)
return;
- }
const auto &targetInfo = lowerModule->getTargetLoweringInfo();
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
index 03044286e8cf7..313661ba959f4 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
@@ -79,20 +79,39 @@ const TargetLoweringInfo &LowerModule::getTargetLoweringInfo() {
}
// TODO: not to create it every time
-std::unique_ptr<LowerModule> createLowerModule(mlir::ModuleOp module) {
+std::unique_ptr<LowerModule>
+createLowerModule(mlir::ModuleOp module,
+ llvm::function_ref<mlir::InFlightDiagnostic()> emitDiag) {
// If the triple is not present, e.g. CIR modules parsed from text, we
// cannot init LowerModule properly.
assert(!cir::MissingFeatures::makeTripleAlwaysPresent());
- if (!module->hasAttr(cir::CIRDialect::getTripleAttrName()))
+ // TODO(triple) what this line do? ^^^
+ if (!module->hasAttr(cir::CIRDialect::getTripleAttrName())) {
+ if (emitDiag)
+ emitDiag() << "module is missing " << cir::CIRDialect::getTripleAttrName()
+ << " attribute";
return nullptr;
+ }
// Fetch target information.
- llvm::Triple triple(mlir::cast<mlir::StringAttr>(
- module->getAttr(cir::CIRDialect::getTripleAttrName()))
- .getValue());
+ auto tripleAttr = module->getAttrOfType<mlir::StringAttr>(
+ cir::CIRDialect::getTripleAttrName());
+ if (!tripleAttr) {
+ if (emitDiag)
+ emitDiag() << "expected module's " << cir::CIRDialect::getTripleAttrName()
+ << " attribute to be a string";
+ return nullptr;
+ }
+ llvm::Triple triple(tripleAttr.getValue());
clang::TargetOptions targetOptions;
targetOptions.Triple = triple.str();
auto targetInfo = clang::targets::AllocateTarget(triple, targetOptions);
+ if (!targetInfo) {
+ if (emitDiag)
+ emitDiag() << "unknown triple '" << tripleAttr.getValue() << "' in "
+ << cir::CIRDialect::getTripleAttrName() << " attribute";
+ return nullptr;
+ }
// Populate the lowering-relevant LangOptions from the module's
// #cir.lowering_lang_options attribute so a reloaded .cir lowers the same
@@ -120,6 +139,7 @@ std::unique_ptr<LowerModule> createLowerModule(mlir::ModuleOp module) {
assert(!cir::MissingFeatures::lowerModuleCodeGenOpts());
clang::CodeGenOptions codeGenOpts;
+ // TODO(optinfo): this cast should be more secure?
if (auto optInfo = mlir::cast_if_present<cir::OptInfoAttr>(
module->getAttr(cir::CIRDialect::getOptInfoAttrName()))) {
codeGenOpts.OptimizationLevel = optInfo.getLevel();
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h
index 56fcd0a9b58cd..588bc496bdaba 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h
@@ -57,7 +57,9 @@ class LowerModule {
const TargetLoweringInfo &getTargetLoweringInfo();
};
-std::unique_ptr<LowerModule> createLowerModule(mlir::ModuleOp module);
+std::unique_ptr<LowerModule>
+createLowerModule(mlir::ModuleOp module,
+ llvm::function_ref<mlir::InFlightDiagnostic()> emitDiag = nullptr);
} // namespace cir
>From 7148a33516414e640d560bff21c033763da991cc Mon Sep 17 00:00:00 2001
From: "Li, Ian" <ian.li at intel.com>
Date: Wed, 7 Oct 2026 17:13:28 -0700
Subject: [PATCH 2/8] issue diagnostics on malformed opt_info attrs
---
.../Dialect/Transforms/TargetLowering/LowerModule.cpp | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
index 313661ba959f4..afbacbd7987a6 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
@@ -139,9 +139,14 @@ createLowerModule(mlir::ModuleOp module,
assert(!cir::MissingFeatures::lowerModuleCodeGenOpts());
clang::CodeGenOptions codeGenOpts;
- // TODO(optinfo): this cast should be more secure?
- if (auto optInfo = mlir::cast_if_present<cir::OptInfoAttr>(
- module->getAttr(cir::CIRDialect::getOptInfoAttrName()))) {
+ if (auto optAttr = module->getAttr(cir::CIRDialect::getOptInfoAttrName())) {
+ auto optInfo = mlir::dyn_cast<cir::OptInfoAttr>(optAttr);
+ if (!optInfo) {
+ if (emitDiag)
+ emitDiag() << "malformed " << cir::CIRDialect::getOptInfoAttrName()
+ << " attribute";
+ return nullptr;
+ }
codeGenOpts.OptimizationLevel = optInfo.getLevel();
codeGenOpts.OptimizeSize = optInfo.getSize();
}
>From 9a939caf75ae9d058a1a5ef55ff8268191096264 Mon Sep 17 00:00:00 2001
From: "Li, Ian" <ian.li at intel.com>
Date: Wed, 7 Oct 2026 18:28:46 -0700
Subject: [PATCH 3/8] patch up reading triples for cpuid op lowering
---
.../Transforms/TargetLowering/LowerModule.cpp | 1 -
.../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 18 ++++++++++++++----
2 files changed, 14 insertions(+), 5 deletions(-)
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
index afbacbd7987a6..4190947e0cb4d 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
@@ -85,7 +85,6 @@ createLowerModule(mlir::ModuleOp module,
// If the triple is not present, e.g. CIR modules parsed from text, we
// cannot init LowerModule properly.
assert(!cir::MissingFeatures::makeTripleAlwaysPresent());
- // TODO(triple) what this line do? ^^^
if (!module->hasAttr(cir::CIRDialect::getTripleAttrName())) {
if (emitDiag)
emitDiag() << "module is missing " << cir::CIRDialect::getTripleAttrName()
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 6426841e6237f..d539ad50db866 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -4508,6 +4508,7 @@ void ConvertCIRToLLVMPass::processCIRAttrs(mlir::ModuleOp module) {
module->getAttr(cir::CIRDialect::getTripleAttrName()))
module->setAttr(mlir::LLVM::LLVMDialect::getTargetTripleAttrName(),
tripleAttr);
+ // TODO(triple) handle triple exception here?
if (mlir::Attribute asmAttr =
module->getAttr(cir::CIRDialect::getModuleLevelAsmAttrName()))
@@ -5819,10 +5820,19 @@ mlir::LogicalResult CIRToLLVMCpuIdOpLowering::matchAndRewrite(
StringRef asmString, constraints;
mlir::ModuleOp moduleOp = op->getParentOfType<mlir::ModuleOp>();
- llvm::Triple triple(
- mlir::cast<mlir::StringAttr>(
- moduleOp->getAttr(cir::CIRDialect::getTripleAttrName()))
- .getValue());
+ auto tripleAttr = moduleOp->getAttr(cir::CIRDialect::getTripleAttrName());
+ if (!tripleAttr) {
+ moduleOp->emitError("module is missing a ")
+ << cir::CIRDialect::getTripleAttrName() << " attribute";
+ return mlir::failure();
+ }
+ mlir::StringAttr tripleStr = mlir::dyn_cast<mlir::StringAttr>(tripleAttr);
+ if (!tripleStr) {
+ moduleOp->emitError("expected string from module ")
+ << cir::CIRDialect::getTripleAttrName() << " attribute";
+ return mlir::failure();
+ }
+ llvm::Triple triple(tripleStr.getValue());
if (triple.getArch() == llvm::Triple::x86) {
asmString = "cpuid";
constraints = "={ax},={bx},={cx},={dx},{ax},{cx}";
>From fd373da1e099dbad33241e2ab7c8afd94ebe7f7b Mon Sep 17 00:00:00 2001
From: "Li, Ian" <ian.li at intel.com>
Date: Wed, 7 Oct 2026 21:04:51 -0700
Subject: [PATCH 4/8] switch to unified helper for triple processing
---
.../include/clang/CIR/Dialect/IR/CIRDialect.h | 6 +++++
clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 22 +++++++++++++++++++
.../CIR/Dialect/Transforms/EHABILowering.cpp | 10 +++------
.../Transforms/TargetLowering/LowerModule.cpp | 22 +++++--------------
clang/lib/CIR/Lowering/CIRPasses.cpp | 12 +++++-----
.../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 18 ++++-----------
6 files changed, 45 insertions(+), 45 deletions(-)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
index d9018e93628b6..baece7ab02fc7 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
+++ b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
@@ -99,6 +99,12 @@ RecordLayoutAttr getRecordLayout(mlir::ModuleOp mod, mlir::StringAttr name);
/// Same lookup as getRecordLayout, but returns a null attribute instead of
/// asserting when the record has no layout entry.
RecordLayoutAttr tryGetRecordLayout(mlir::ModuleOp mod, mlir::StringAttr name);
+
+/// Attempts to construct an llvm::Triple from a module's cir.triple attribute.
+/// If emitDiag is not null, additional diagnostics information is passed into
+/// emitDiag upon failure.
+mlir::FailureOr<llvm::Triple>
+getTripleFromModule(mlir::ModuleOp mod, llvm::function_ref<mlir::InFlightDiagnostic()> emitDiag = nullptr);
} // namespace cir
// TableGen'erated files for MLIR dialects require that a macro be defined when
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 2a5cb9a908a1d..caa3527a02f11 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -402,6 +402,28 @@ static LogicalResult verifyProducedBy(Operation *op, Value operand,
return success();
}
+mlir::FailureOr<llvm::Triple> cir::getTripleFromModule(
+ mlir::ModuleOp mod,
+ llvm::function_ref<mlir::InFlightDiagnostic()> emitDiag) {
+ if (!mod->hasAttr(cir::CIRDialect::getTripleAttrName())) {
+ if (emitDiag)
+ emitDiag() << "module is missing " << cir::CIRDialect::getTripleAttrName()
+ << " attribute";
+ return mlir::failure();
+ }
+
+ auto tripleAttr = mod->getAttrOfType<mlir::StringAttr>(
+ cir::CIRDialect::getTripleAttrName());
+ if (!tripleAttr) {
+ if (emitDiag)
+ emitDiag() << "expected a string from module attribute "
+ << cir::CIRDialect::getTripleAttrName();
+ return mlir::failure();
+ }
+
+ return llvm::Triple{tripleAttr.getValue()};
+}
+
//===----------------------------------------------------------------------===//
// InlineKindAttr (FIXME: remove once FuncOp uses assembly format)
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp b/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp
index 77ce7434c8ed3..e3306227aac5e 100644
--- a/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp
@@ -1088,19 +1088,15 @@ void CIREHABILoweringPass::runOnOperation() {
// The target triple is attached to the module as the "cir.triple"
// attribute. If it is absent (e.g. a CIR module parsed from text without a
// triple) we cannot determine the ABI and must skip the pass.
- auto tripleAttr = mlir::dyn_cast_if_present<mlir::StringAttr>(
- mod->getAttr(cir::CIRDialect::getTripleAttrName()));
- if (!tripleAttr) {
- mod.emitError("Module has no target triple");
+ auto triple = cir::getTripleFromModule(mod, [&] { return mod.emitWarning(); });
+ if (mlir::failed(triple))
return;
- }
// Select the ABI-specific lowering handler from the triple. The Microsoft
// C++ ABI targets a Windows MSVC environment; everything else uses Itanium.
// Extend this when Microsoft ABI lowering is added.
- llvm::Triple triple(tripleAttr.getValue());
std::unique_ptr<EHABILowering> lowering;
- if (triple.isWindowsMSVCEnvironment()) {
+ if (triple->isWindowsMSVCEnvironment()) {
mod.emitError(
"EH ABI lowering is not yet implemented for the Microsoft ABI");
return signalPassFailure();
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
index 4190947e0cb4d..91a6f27ea8b16 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
@@ -85,29 +85,17 @@ createLowerModule(mlir::ModuleOp module,
// If the triple is not present, e.g. CIR modules parsed from text, we
// cannot init LowerModule properly.
assert(!cir::MissingFeatures::makeTripleAlwaysPresent());
- if (!module->hasAttr(cir::CIRDialect::getTripleAttrName())) {
- if (emitDiag)
- emitDiag() << "module is missing " << cir::CIRDialect::getTripleAttrName()
- << " attribute";
- return nullptr;
- }
// Fetch target information.
- auto tripleAttr = module->getAttrOfType<mlir::StringAttr>(
- cir::CIRDialect::getTripleAttrName());
- if (!tripleAttr) {
- if (emitDiag)
- emitDiag() << "expected module's " << cir::CIRDialect::getTripleAttrName()
- << " attribute to be a string";
+ auto triple = cir::getTripleFromModule(module, emitDiag);
+ if (mlir::failed(triple))
return nullptr;
- }
- llvm::Triple triple(tripleAttr.getValue());
clang::TargetOptions targetOptions;
- targetOptions.Triple = triple.str();
- auto targetInfo = clang::targets::AllocateTarget(triple, targetOptions);
+ targetOptions.Triple = triple->str();
+ auto targetInfo = clang::targets::AllocateTarget(*triple, targetOptions);
if (!targetInfo) {
if (emitDiag)
- emitDiag() << "unknown triple '" << tripleAttr.getValue() << "' in "
+ emitDiag() << "unknown triple '" << triple->str() << "' in "
<< cir::CIRDialect::getTripleAttrName() << " attribute";
return nullptr;
}
diff --git a/clang/lib/CIR/Lowering/CIRPasses.cpp b/clang/lib/CIR/Lowering/CIRPasses.cpp
index 6e75ce03d14ff..dc4e3128ca26d 100644
--- a/clang/lib/CIR/Lowering/CIRPasses.cpp
+++ b/clang/lib/CIR/Lowering/CIRPasses.cpp
@@ -78,13 +78,11 @@ runCIRToCIRPasses(mlir::ModuleOp theModule, mlir::MLIRContext &mlirContext,
llvm::TimeTraceScope scope("CIR To CIR Passes");
- auto tripleAttr = theModule->getAttrOfType<mlir::StringAttr>(
- cir::CIRDialect::getTripleAttrName());
- if (!tripleAttr)
- return theModule.emitError()
- << "missing '" << cir::CIRDialect::getTripleAttrName()
- << "' attribute";
- llvm::Triple triple(tripleAttr.getValue());
+ auto maybeTriple = cir::getTripleFromModule(theModule,
+ [&]{ return theModule.emitError(); });
+ if (mlir::failed(maybeTriple))
+ return mlir::LogicalResult::failure();
+ llvm::Triple &triple = *maybeTriple;
auto abiAttr = theModule->getAttrOfType<mlir::StringAttr>(
cir::CIRDialect::getTargetABIAttrName());
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index d539ad50db866..628dc160e251d 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -4508,7 +4508,6 @@ void ConvertCIRToLLVMPass::processCIRAttrs(mlir::ModuleOp module) {
module->getAttr(cir::CIRDialect::getTripleAttrName()))
module->setAttr(mlir::LLVM::LLVMDialect::getTargetTripleAttrName(),
tripleAttr);
- // TODO(triple) handle triple exception here?
if (mlir::Attribute asmAttr =
module->getAttr(cir::CIRDialect::getModuleLevelAsmAttrName()))
@@ -5820,20 +5819,11 @@ mlir::LogicalResult CIRToLLVMCpuIdOpLowering::matchAndRewrite(
StringRef asmString, constraints;
mlir::ModuleOp moduleOp = op->getParentOfType<mlir::ModuleOp>();
- auto tripleAttr = moduleOp->getAttr(cir::CIRDialect::getTripleAttrName());
- if (!tripleAttr) {
- moduleOp->emitError("module is missing a ")
- << cir::CIRDialect::getTripleAttrName() << " attribute";
+ auto triple = cir::getTripleFromModule(moduleOp,
+ [&] { return moduleOp.emitError(); });
+ if (mlir::failed(triple))
return mlir::failure();
- }
- mlir::StringAttr tripleStr = mlir::dyn_cast<mlir::StringAttr>(tripleAttr);
- if (!tripleStr) {
- moduleOp->emitError("expected string from module ")
- << cir::CIRDialect::getTripleAttrName() << " attribute";
- return mlir::failure();
- }
- llvm::Triple triple(tripleStr.getValue());
- if (triple.getArch() == llvm::Triple::x86) {
+ if (triple->getArch() == llvm::Triple::x86) {
asmString = "cpuid";
constraints = "={ax},={bx},={cx},={dx},{ax},{cx}";
} else {
>From 3c65330e55b1a8fc479a554123683a9587b785cb Mon Sep 17 00:00:00 2001
From: "Li, Ian" <ian.li at intel.com>
Date: Wed, 7 Oct 2026 21:16:22 -0700
Subject: [PATCH 5/8] I don't think there were any tangible benefits to using
mlir::FailureOr, and if anything it reads worse than std::optional
---
clang/include/clang/CIR/Dialect/IR/CIRDialect.h | 2 +-
clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 6 +++---
clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp | 4 ++--
.../Dialect/Transforms/TargetLowering/LowerModule.cpp | 4 ++--
clang/lib/CIR/Lowering/CIRPasses.cpp | 11 +++++------
clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 4 ++--
6 files changed, 15 insertions(+), 16 deletions(-)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
index baece7ab02fc7..732d065f81cb3 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
+++ b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
@@ -103,7 +103,7 @@ RecordLayoutAttr tryGetRecordLayout(mlir::ModuleOp mod, mlir::StringAttr name);
/// Attempts to construct an llvm::Triple from a module's cir.triple attribute.
/// If emitDiag is not null, additional diagnostics information is passed into
/// emitDiag upon failure.
-mlir::FailureOr<llvm::Triple>
+std::optional<llvm::Triple>
getTripleFromModule(mlir::ModuleOp mod, llvm::function_ref<mlir::InFlightDiagnostic()> emitDiag = nullptr);
} // namespace cir
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index caa3527a02f11..0136ed1ccd0dc 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -402,14 +402,14 @@ static LogicalResult verifyProducedBy(Operation *op, Value operand,
return success();
}
-mlir::FailureOr<llvm::Triple> cir::getTripleFromModule(
+std::optional<llvm::Triple> cir::getTripleFromModule(
mlir::ModuleOp mod,
llvm::function_ref<mlir::InFlightDiagnostic()> emitDiag) {
if (!mod->hasAttr(cir::CIRDialect::getTripleAttrName())) {
if (emitDiag)
emitDiag() << "module is missing " << cir::CIRDialect::getTripleAttrName()
<< " attribute";
- return mlir::failure();
+ return std::nullopt;
}
auto tripleAttr = mod->getAttrOfType<mlir::StringAttr>(
@@ -418,7 +418,7 @@ mlir::FailureOr<llvm::Triple> cir::getTripleFromModule(
if (emitDiag)
emitDiag() << "expected a string from module attribute "
<< cir::CIRDialect::getTripleAttrName();
- return mlir::failure();
+ return std::nullopt;
}
return llvm::Triple{tripleAttr.getValue()};
diff --git a/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp b/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp
index e3306227aac5e..72f9c786db08e 100644
--- a/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp
@@ -1088,8 +1088,8 @@ void CIREHABILoweringPass::runOnOperation() {
// The target triple is attached to the module as the "cir.triple"
// attribute. If it is absent (e.g. a CIR module parsed from text without a
// triple) we cannot determine the ABI and must skip the pass.
- auto triple = cir::getTripleFromModule(mod, [&] { return mod.emitWarning(); });
- if (mlir::failed(triple))
+ std::optional<llvm::Triple> triple = cir::getTripleFromModule(mod, [&] { return mod.emitWarning(); });
+ if (!triple)
return;
// Select the ABI-specific lowering handler from the triple. The Microsoft
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
index 91a6f27ea8b16..b6f6031ddaf2d 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
@@ -87,8 +87,8 @@ createLowerModule(mlir::ModuleOp module,
assert(!cir::MissingFeatures::makeTripleAlwaysPresent());
// Fetch target information.
- auto triple = cir::getTripleFromModule(module, emitDiag);
- if (mlir::failed(triple))
+ std::optional<llvm::Triple> triple = cir::getTripleFromModule(module, emitDiag);
+ if (!triple)
return nullptr;
clang::TargetOptions targetOptions;
targetOptions.Triple = triple->str();
diff --git a/clang/lib/CIR/Lowering/CIRPasses.cpp b/clang/lib/CIR/Lowering/CIRPasses.cpp
index dc4e3128ca26d..0158c7fe37309 100644
--- a/clang/lib/CIR/Lowering/CIRPasses.cpp
+++ b/clang/lib/CIR/Lowering/CIRPasses.cpp
@@ -78,11 +78,10 @@ runCIRToCIRPasses(mlir::ModuleOp theModule, mlir::MLIRContext &mlirContext,
llvm::TimeTraceScope scope("CIR To CIR Passes");
- auto maybeTriple = cir::getTripleFromModule(theModule,
+ std::optional<llvm::Triple> triple = cir::getTripleFromModule(theModule,
[&]{ return theModule.emitError(); });
- if (mlir::failed(maybeTriple))
+ if (!triple)
return mlir::LogicalResult::failure();
- llvm::Triple &triple = *maybeTriple;
auto abiAttr = theModule->getAttrOfType<mlir::StringAttr>(
cir::CIRDialect::getTargetABIAttrName());
@@ -126,7 +125,7 @@ runCIRToCIRPasses(mlir::ModuleOp theModule, mlir::MLIRContext &mlirContext,
// so it must run after CXXABILowering has lowered C++ ABI types to plain
// records the classifier can handle. Only the x86_64 System V classifier
// is implemented; other targets are left unchanged.
- CallConvTarget target = getCallConvTarget(triple);
+ CallConvTarget target = getCallConvTarget(triple.value());
if (target != CallConvTarget::None) {
// Source the ABI-compatibility version from the module's serialized
// #cir.lowering_lang_options so a reloaded .cir classifies the same way
@@ -141,8 +140,8 @@ runCIRToCIRPasses(mlir::ModuleOp theModule, mlir::MLIRContext &mlirContext,
loweringLangOpts.getClangAbiCompat());
pm.addPass(mlir::createCallConvLoweringPass(
target, getX86AVXABILevel(abiAttr.getValue()),
- allowsX86TargetAttrAvx(triple, compat),
- getX86ABICompatInfo(triple, compat)));
+ allowsX86TargetAttrAvx(triple.value(), compat),
+ getX86ABICompatInfo(triple.value(), compat)));
}
}
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 628dc160e251d..0903de9c77f20 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -5819,9 +5819,9 @@ mlir::LogicalResult CIRToLLVMCpuIdOpLowering::matchAndRewrite(
StringRef asmString, constraints;
mlir::ModuleOp moduleOp = op->getParentOfType<mlir::ModuleOp>();
- auto triple = cir::getTripleFromModule(moduleOp,
+ std::optional<llvm::Triple> triple = cir::getTripleFromModule(moduleOp,
[&] { return moduleOp.emitError(); });
- if (mlir::failed(triple))
+ if (!triple)
return mlir::failure();
if (triple->getArch() == llvm::Triple::x86) {
asmString = "cpuid";
>From 72963ed03bbd69e613943ae2dbdf68a030dcc87a Mon Sep 17 00:00:00 2001
From: "Li, Ian" <ian.li at intel.com>
Date: Wed, 7 Oct 2026 21:21:56 -0700
Subject: [PATCH 6/8] copy cir-opt additions from #229575
---
clang/tools/cir-opt/cir-opt.cpp | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/clang/tools/cir-opt/cir-opt.cpp b/clang/tools/cir-opt/cir-opt.cpp
index fdaf405441003..0a0c791ae494e 100644
--- a/clang/tools/cir-opt/cir-opt.cpp
+++ b/clang/tools/cir-opt/cir-opt.cpp
@@ -82,6 +82,18 @@ int main(int argc, char **argv) {
return mlir::createCXXABILoweringPass();
});
+ ::mlir::registerPass([]() -> std::unique_ptr<::mlir::Pass> {
+ return mlir::createTargetLoweringPass();
+ });
+
+ ::mlir::registerPass([]() -> std::unique_ptr<::mlir::Pass> {
+ return mlir::createLoweringPreparePass();
+ });
+
+ ::mlir::registerPass([]() -> std::unique_ptr<::mlir::Pass> {
+ return mlir::createLibOptPass();
+ });
+
::mlir::registerPass([]() -> std::unique_ptr<::mlir::Pass> {
return mlir::createIdiomRecognizerPass();
});
>From 362290cca48ef863cc0ad67290338d0d85fbca7e Mon Sep 17 00:00:00 2001
From: "Li, Ian" <ian.li at intel.com>
Date: Wed, 7 Oct 2026 21:35:01 -0700
Subject: [PATCH 7/8] clang-format
---
clang/include/clang/CIR/Dialect/IR/CIRDialect.h | 5 +++--
clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 4 ++--
clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp | 6 +++---
clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp | 3 ++-
clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp | 2 +-
clang/lib/CIR/Dialect/Transforms/TargetLowering.cpp | 6 +++---
.../CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp | 3 ++-
.../lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h | 4 ++--
clang/lib/CIR/Lowering/CIRPasses.cpp | 4 ++--
clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 4 ++--
10 files changed, 22 insertions(+), 19 deletions(-)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
index 732d065f81cb3..662942fdeda04 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
+++ b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
@@ -103,8 +103,9 @@ RecordLayoutAttr tryGetRecordLayout(mlir::ModuleOp mod, mlir::StringAttr name);
/// Attempts to construct an llvm::Triple from a module's cir.triple attribute.
/// If emitDiag is not null, additional diagnostics information is passed into
/// emitDiag upon failure.
-std::optional<llvm::Triple>
-getTripleFromModule(mlir::ModuleOp mod, llvm::function_ref<mlir::InFlightDiagnostic()> emitDiag = nullptr);
+std::optional<llvm::Triple> getTripleFromModule(
+ mlir::ModuleOp mod,
+ llvm::function_ref<mlir::InFlightDiagnostic()> emitDiag = nullptr);
} // namespace cir
// TableGen'erated files for MLIR dialects require that a macro be defined when
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 0136ed1ccd0dc..7a208cf4f1b00 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -403,8 +403,8 @@ static LogicalResult verifyProducedBy(Operation *op, Value operand,
}
std::optional<llvm::Triple> cir::getTripleFromModule(
- mlir::ModuleOp mod,
- llvm::function_ref<mlir::InFlightDiagnostic()> emitDiag) {
+ mlir::ModuleOp mod,
+ llvm::function_ref<mlir::InFlightDiagnostic()> emitDiag) {
if (!mod->hasAttr(cir::CIRDialect::getTripleAttrName())) {
if (emitDiag)
emitDiag() << "module is missing " << cir::CIRDialect::getTripleAttrName()
diff --git a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
index b57b994bea88c..7c7de931fdc70 100644
--- a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
@@ -895,10 +895,10 @@ void CXXABILoweringPass::runOnOperation() {
auto diag = [&] {
return mod.emitWarning("cannot create a CIR lower module, skipping the ")
- << getName() << " pass: ";
+ << getName() << " pass: ";
};
- std::unique_ptr<cir::LowerModule> lowerModule = cir::createLowerModule(
- mod, diag);
+ std::unique_ptr<cir::LowerModule> lowerModule =
+ cir::createLowerModule(mod, diag);
// If lower module is not available, skip the ABI lowering pass.
if (!lowerModule)
return;
diff --git a/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp b/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp
index 72f9c786db08e..668016a432308 100644
--- a/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp
@@ -1088,7 +1088,8 @@ void CIREHABILoweringPass::runOnOperation() {
// The target triple is attached to the module as the "cir.triple"
// attribute. If it is absent (e.g. a CIR module parsed from text without a
// triple) we cannot determine the ABI and must skip the pass.
- std::optional<llvm::Triple> triple = cir::getTripleFromModule(mod, [&] { return mod.emitWarning(); });
+ std::optional<llvm::Triple> triple =
+ cir::getTripleFromModule(mod, [&] { return mod.emitWarning(); });
if (!triple)
return;
diff --git a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
index 106298629c65e..e35eb52fabda2 100644
--- a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
@@ -3063,7 +3063,7 @@ void LoweringPreparePass::runOnOperation() {
auto diag = [&] {
return mlirModule.emitError("cannot create a CIR lower module for ")
- << getName() << " pass: ";
+ << getName() << " pass: ";
};
lowerModule = cir::createLowerModule(mlirModule, diag);
if (!lowerModule)
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering.cpp
index e978acda6cca9..f545fbb6bbecf 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering.cpp
@@ -298,10 +298,10 @@ void TargetLoweringPass::runOnOperation() {
auto mod = mlir::cast<mlir::ModuleOp>(getOperation());
auto diag = [&] {
return mod.emitWarning("cannot create a CIR lower module, skipping the ")
- << getName() << " pass: ";
+ << getName() << " pass: ";
};
- std::unique_ptr<cir::LowerModule> lowerModule = cir::createLowerModule(
- mod, diag);
+ std::unique_ptr<cir::LowerModule> lowerModule =
+ cir::createLowerModule(mod, diag);
// If lower module is not available, skip the target lowering pass.
if (!lowerModule)
return;
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
index b6f6031ddaf2d..a5ee43c544344 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
@@ -87,7 +87,8 @@ createLowerModule(mlir::ModuleOp module,
assert(!cir::MissingFeatures::makeTripleAlwaysPresent());
// Fetch target information.
- std::optional<llvm::Triple> triple = cir::getTripleFromModule(module, emitDiag);
+ std::optional<llvm::Triple> triple =
+ cir::getTripleFromModule(module, emitDiag);
if (!triple)
return nullptr;
clang::TargetOptions targetOptions;
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h
index 588bc496bdaba..dbd28430c6df3 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h
@@ -57,8 +57,8 @@ class LowerModule {
const TargetLoweringInfo &getTargetLoweringInfo();
};
-std::unique_ptr<LowerModule>
-createLowerModule(mlir::ModuleOp module,
+std::unique_ptr<LowerModule> createLowerModule(
+ mlir::ModuleOp module,
llvm::function_ref<mlir::InFlightDiagnostic()> emitDiag = nullptr);
} // namespace cir
diff --git a/clang/lib/CIR/Lowering/CIRPasses.cpp b/clang/lib/CIR/Lowering/CIRPasses.cpp
index 0158c7fe37309..cbc0c515bf275 100644
--- a/clang/lib/CIR/Lowering/CIRPasses.cpp
+++ b/clang/lib/CIR/Lowering/CIRPasses.cpp
@@ -78,8 +78,8 @@ runCIRToCIRPasses(mlir::ModuleOp theModule, mlir::MLIRContext &mlirContext,
llvm::TimeTraceScope scope("CIR To CIR Passes");
- std::optional<llvm::Triple> triple = cir::getTripleFromModule(theModule,
- [&]{ return theModule.emitError(); });
+ std::optional<llvm::Triple> triple = cir::getTripleFromModule(
+ theModule, [&] { return theModule.emitError(); });
if (!triple)
return mlir::LogicalResult::failure();
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 0903de9c77f20..dc99dd0b439b0 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -5819,8 +5819,8 @@ mlir::LogicalResult CIRToLLVMCpuIdOpLowering::matchAndRewrite(
StringRef asmString, constraints;
mlir::ModuleOp moduleOp = op->getParentOfType<mlir::ModuleOp>();
- std::optional<llvm::Triple> triple = cir::getTripleFromModule(moduleOp,
- [&] { return moduleOp.emitError(); });
+ std::optional<llvm::Triple> triple =
+ cir::getTripleFromModule(moduleOp, [&] { return moduleOp.emitError(); });
if (!triple)
return mlir::failure();
if (triple->getArch() == llvm::Triple::x86) {
>From 15677e38ac14face59e9174713c7cc2e87596d00 Mon Sep 17 00:00:00 2001
From: "Li, Ian" <ian.li at intel.com>
Date: Wed, 7 Oct 2026 23:36:53 -0700
Subject: [PATCH 8/8] draft up test cases
---
.../CIR/Lowering/cir-to-llvm-module-attrs.cir | 49 +++++++
.../Transforms/cxx-abi-lowering-bad-attrs.cir | 137 ++++++++++++++++++
.../Transforms/eh-abi-lowering-bad-attrs.cir | 41 ++++++
.../lowering-prepare-module-attrs.cir | 130 +++++++++++++++++
.../target-lowering-module-attrs.cir | 137 ++++++++++++++++++
5 files changed, 494 insertions(+)
create mode 100644 clang/test/CIR/Lowering/cir-to-llvm-module-attrs.cir
create mode 100644 clang/test/CIR/Transforms/cxx-abi-lowering-bad-attrs.cir
create mode 100644 clang/test/CIR/Transforms/eh-abi-lowering-bad-attrs.cir
create mode 100644 clang/test/CIR/Transforms/lowering-prepare-module-attrs.cir
create mode 100644 clang/test/CIR/Transforms/target-lowering-module-attrs.cir
diff --git a/clang/test/CIR/Lowering/cir-to-llvm-module-attrs.cir b/clang/test/CIR/Lowering/cir-to-llvm-module-attrs.cir
new file mode 100644
index 0000000000000..ed861075a5c36
--- /dev/null
+++ b/clang/test/CIR/Lowering/cir-to-llvm-module-attrs.cir
@@ -0,0 +1,49 @@
+// RUN: cir-opt %s -cir-to-llvm -verify-diagnostics -split-input-file
+// RUN: not cir-opt %s -cir-to-llvm -split-input-file 2>/dev/null \
+// RUN: | FileCheck %s --implicit-check-not=llvm.func
+
+// -cir-to-llvm relies on cir.triple module attributes: Check that missing or
+// malformed cir.triple attributes read by -cir-to-llvm do not cause asserts or
+// compiler crashes, and are diagnosed properly.
+
+
+// Missing cir.triple.
+
+!s32i = !cir.int<s, 32>
+// expected-warning @below {{module is missing cir.triple attribute}}
+// expected-error @below {{module is missing cir.triple attribute}}
+module {
+ cir.func @missing_triple(%p: !cir.ptr<!s32i>, %a: !s32i, %b: !s32i) {
+ // expected-error @below {{failed to legalize operation 'cir.cpuid'}}
+ cir.cpuid %p, %a, %b : !cir.ptr<!s32i>, !s32i, !s32i
+ cir.return
+ }
+}
+
+// -----
+
+// Non-string cir.triple.
+
+!s32i = !cir.int<s, 32>
+// expected-warning @below {{expected a string from module attribute cir.triple}}
+// expected-error @below {{expected a string from module attribute cir.triple}}
+module attributes {cir.triple = 42 : i32} {
+ cir.func @non_string_triple(%p: !cir.ptr<!s32i>, %a: !s32i, %b: !s32i) {
+ // expected-error @below {{failed to legalize operation 'cir.cpuid'}}
+ cir.cpuid %p, %a, %b : !cir.ptr<!s32i>, !s32i, !s32i
+ cir.return
+ }
+}
+
+// -----
+
+// Valid cir.triple.
+
+!s32i = !cir.int<s, 32>
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+ // CHECK-LABEL: llvm.func @valid_triple(
+ cir.func @valid_triple(%p: !cir.ptr<!s32i>, %a: !s32i, %b: !s32i) {
+ cir.cpuid %p, %a, %b : !cir.ptr<!s32i>, !s32i, !s32i
+ cir.return
+ }
+}
diff --git a/clang/test/CIR/Transforms/cxx-abi-lowering-bad-attrs.cir b/clang/test/CIR/Transforms/cxx-abi-lowering-bad-attrs.cir
new file mode 100644
index 0000000000000..5d13956c63af4
--- /dev/null
+++ b/clang/test/CIR/Transforms/cxx-abi-lowering-bad-attrs.cir
@@ -0,0 +1,137 @@
+// RUN: cir-opt %s -cir-cxxabi-lowering -verify-diagnostics -split-input-file
+// RUN: cir-opt %s -cir-cxxabi-lowering -split-input-file 2>/dev/null | FileCheck %s
+
+// Check that missing or malformed module attributes required/used by
+// -cir-cxxabi-lowering do not cause asserts or compiler crashes, and are
+// diagnosed properly. The pass should warn and skip instead of failing, so
+// every module is still printed.
+
+
+// Missing cir.triple.
+
+// expected-warning @below {{cannot create a CIR lower module, skipping the CXXABILowering pass: module is missing cir.triple attribute}}
+module {
+ // CHECK-LABEL: cir.func @missing_triple(
+ cir.func @missing_triple() {
+ cir.return
+ }
+}
+
+// -----
+
+// Non-string cir.triple.
+
+// expected-warning @below {{cannot create a CIR lower module, skipping the CXXABILowering pass: expected a string from module attribute cir.triple}}
+module attributes {cir.triple = 42 : i32} {
+ // CHECK-LABEL: cir.func @non_string_triple(
+ cir.func @non_string_triple() {
+ cir.return
+ }
+}
+
+// -----
+
+// Empty cir.triple.
+
+// expected-warning @below {{cannot create a CIR lower module, skipping the CXXABILowering pass: unknown triple '' in cir.triple attribute}}
+module attributes {cir.triple = ""} {
+ // CHECK-LABEL: cir.func @empty_triple(
+ cir.func @empty_triple() {
+ cir.return
+ }
+}
+
+// -----
+
+// Malformed cir.triple.
+
+// expected-warning @below {{cannot create a CIR lower module, skipping the CXXABILowering pass: unknown triple 'garbage' in cir.triple attribute}}
+module attributes {cir.triple = "garbage"} {
+ // CHECK-LABEL: cir.func @malformed_triple(
+ cir.func @malformed_triple() {
+ cir.return
+ }
+}
+
+// -----
+
+// Well-formed cir.triple with an unknown target.
+
+// expected-warning @below {{cannot create a CIR lower module, skipping the CXXABILowering pass: unknown triple 'foobar-unknown-unknown' in cir.triple attribute}}
+module attributes {cir.triple = "foobar-unknown-unknown"} {
+ // CHECK-LABEL: cir.func @unknown_triple(
+ cir.func @unknown_triple() {
+ cir.return
+ }
+}
+
+// -----
+
+// Valid cir.triple without cir.opt_info.
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+ // CHECK-LABEL: cir.func @valid_triple(
+ cir.func @valid_triple() {
+ cir.return
+ }
+}
+
+// -----
+
+// Valid cir.triple with a valid cir.opt_info.
+
+module attributes {
+ cir.triple = "x86_64-unknown-linux-gnu",
+ cir.opt_info = #cir.opt_info<level = 2, size = 1>
+} {
+ // CHECK-LABEL: cir.func @valid_opt_info(
+ cir.func @valid_opt_info() {
+ cir.return
+ }
+}
+
+// -----
+
+// Valid cir.triple with a cir.opt_info that is not an OptInfoAttr.
+
+// expected-warning @below {{cannot create a CIR lower module, skipping the CXXABILowering pass: malformed cir.opt_info attribute}}
+module attributes {
+ cir.triple = "x86_64-unknown-linux-gnu",
+ cir.opt_info = 1 : i32
+} {
+ // CHECK-LABEL: cir.func @malformed_opt_info(
+ cir.func @malformed_opt_info() {
+ cir.return
+ }
+}
+
+// -----
+
+// Valid cir.triple with a string cir.opt_info.
+
+// expected-warning @below {{cannot create a CIR lower module, skipping the CXXABILowering pass: malformed cir.opt_info attribute}}
+module attributes {
+ cir.triple = "x86_64-unknown-linux-gnu",
+ cir.opt_info = "O2"
+} {
+ // CHECK-LABEL: cir.func @string_opt_info(
+ cir.func @string_opt_info() {
+ cir.return
+ }
+}
+
+// -----
+
+// Valid cir.triple with a dictionary cir.opt_info that mimics OptInfoAttr's
+// fields.
+
+// expected-warning @below {{cannot create a CIR lower module, skipping the CXXABILowering pass: malformed cir.opt_info attribute}}
+module attributes {
+ cir.triple = "x86_64-unknown-linux-gnu",
+ cir.opt_info = {level = 2 : i32, size = 1 : i32}
+} {
+ // CHECK-LABEL: cir.func @dict_opt_info(
+ cir.func @dict_opt_info() {
+ cir.return
+ }
+}
diff --git a/clang/test/CIR/Transforms/eh-abi-lowering-bad-attrs.cir b/clang/test/CIR/Transforms/eh-abi-lowering-bad-attrs.cir
new file mode 100644
index 0000000000000..fc4be2550cb3b
--- /dev/null
+++ b/clang/test/CIR/Transforms/eh-abi-lowering-bad-attrs.cir
@@ -0,0 +1,41 @@
+// RUN: cir-opt %s -cir-eh-abi-lowering -verify-diagnostics -split-input-file
+// RUN: cir-opt %s -cir-eh-abi-lowering -split-input-file 2>/dev/null | FileCheck %s
+
+// Check that missing or malformed cir.triple attributes required by
+// -cir-eh-abi-lowering do not cause asserts or compiler crashes, and are
+// diagnosed properly. The pass should warn and skip instead of failing, so
+// every module is still printed.
+
+
+// Missing cir.triple.
+
+// expected-warning @below {{module is missing cir.triple attribute}}
+module {
+ // CHECK-LABEL: cir.func @missing_triple(
+ cir.func @missing_triple() {
+ cir.return
+ }
+}
+
+// -----
+
+// Non-string cir.triple.
+
+// expected-warning @below {{expected a string from module attribute cir.triple}}
+module attributes {cir.triple = 42 : i32} {
+ // CHECK-LABEL: cir.func @non_string_triple(
+ cir.func @non_string_triple() {
+ cir.return
+ }
+}
+
+// -----
+
+// Valid cir.triple.
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+ // CHECK-LABEL: cir.func @valid_triple(
+ cir.func @valid_triple() {
+ cir.return
+ }
+}
diff --git a/clang/test/CIR/Transforms/lowering-prepare-module-attrs.cir b/clang/test/CIR/Transforms/lowering-prepare-module-attrs.cir
new file mode 100644
index 0000000000000..f42bad16d7bc3
--- /dev/null
+++ b/clang/test/CIR/Transforms/lowering-prepare-module-attrs.cir
@@ -0,0 +1,130 @@
+// RUN: cir-opt %s -cir-lowering-prepare -verify-diagnostics -split-input-file
+// RUN: not cir-opt %s -cir-lowering-prepare -split-input-file 2>/dev/null \
+// RUN: | FileCheck %s --implicit-check-not=cir.func
+
+// Check that missing or malformed module attributes required/used by
+// -cir-lowering-prepare do not cause asserts or compiler crashes, and are
+// diagnosed properly. The pass should fail on bad attributes, so only modules
+// with valid attributes are printed.
+
+
+// Missing cir.triple.
+
+// expected-error @below {{cannot create a CIR lower module for LoweringPrepare pass: module is missing cir.triple attribute}}
+module {
+ cir.func @missing_triple() {
+ cir.return
+ }
+}
+
+// -----
+
+// Non-string cir.triple.
+
+// expected-error @below {{cannot create a CIR lower module for LoweringPrepare pass: expected a string from module attribute cir.triple}}
+module attributes {cir.triple = 42 : i32} {
+ cir.func @non_string_triple() {
+ cir.return
+ }
+}
+
+// -----
+
+// Empty cir.triple.
+
+// expected-error @below {{cannot create a CIR lower module for LoweringPrepare pass: unknown triple '' in cir.triple attribute}}
+module attributes {cir.triple = ""} {
+ cir.func @empty_triple() {
+ cir.return
+ }
+}
+
+// -----
+
+// Malformed cir.triple.
+
+// expected-error @below {{cannot create a CIR lower module for LoweringPrepare pass: unknown triple 'garbage' in cir.triple attribute}}
+module attributes {cir.triple = "garbage"} {
+ cir.func @malformed_triple() {
+ cir.return
+ }
+}
+
+// -----
+
+// Well-formed cir.triple with an unknown target.
+
+// expected-error @below {{cannot create a CIR lower module for LoweringPrepare pass: unknown triple 'foobar-unknown-unknown' in cir.triple attribute}}
+module attributes {cir.triple = "foobar-unknown-unknown"} {
+ cir.func @unknown_triple() {
+ cir.return
+ }
+}
+
+// -----
+
+// Valid cir.triple without cir.opt_info.
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+ // CHECK-LABEL: cir.func @valid_triple(
+ cir.func @valid_triple() {
+ cir.return
+ }
+}
+
+// -----
+
+// Valid cir.triple with a valid cir.opt_info.
+
+module attributes {
+ cir.triple = "x86_64-unknown-linux-gnu",
+ cir.opt_info = #cir.opt_info<level = 2, size = 1>
+} {
+ // CHECK-LABEL: cir.func @valid_opt_info(
+ cir.func @valid_opt_info() {
+ cir.return
+ }
+}
+
+// -----
+
+// Valid cir.triple with a cir.opt_info that is not an OptInfoAttr.
+
+// expected-error @below {{cannot create a CIR lower module for LoweringPrepare pass: malformed cir.opt_info attribute}}
+module attributes {
+ cir.triple = "x86_64-unknown-linux-gnu",
+ cir.opt_info = 1 : i32
+} {
+ cir.func @malformed_opt_info() {
+ cir.return
+ }
+}
+
+// -----
+
+// Valid cir.triple with a string cir.opt_info.
+
+// expected-error @below {{cannot create a CIR lower module for LoweringPrepare pass: malformed cir.opt_info attribute}}
+module attributes {
+ cir.triple = "x86_64-unknown-linux-gnu",
+ cir.opt_info = "O2"
+} {
+ cir.func @string_opt_info() {
+ cir.return
+ }
+}
+
+// -----
+
+// Valid cir.triple with a dictionary cir.opt_info that mimics OptInfoAttr's
+// fields.
+
+// expected-error @below {{cannot create a CIR lower module for LoweringPrepare pass: malformed cir.opt_info attribute}}
+module attributes {
+ cir.triple = "x86_64-unknown-linux-gnu",
+ cir.opt_info = {level = 2 : i32, size = 1 : i32}
+} {
+ cir.func @dict_opt_info() {
+ cir.return
+ }
+}
diff --git a/clang/test/CIR/Transforms/target-lowering-module-attrs.cir b/clang/test/CIR/Transforms/target-lowering-module-attrs.cir
new file mode 100644
index 0000000000000..36813d4d707a4
--- /dev/null
+++ b/clang/test/CIR/Transforms/target-lowering-module-attrs.cir
@@ -0,0 +1,137 @@
+// RUN: cir-opt %s -cir-target-lowering -verify-diagnostics -split-input-file
+// RUN: cir-opt %s -cir-target-lowering -split-input-file 2>/dev/null | FileCheck %s
+
+// Check that missing or malformed module attributes required/used by
+// -cir-target-lowering do not cause asserts or compiler crashes, and are
+// diagnosed properly. The pass should warn and skip instead of failing, so
+// every module is still printed.
+
+
+// Missing cir.triple.
+
+// expected-warning @below {{cannot create a CIR lower module, skipping the TargetLowering pass: module is missing cir.triple attribute}}
+module {
+ // CHECK-LABEL: cir.func @missing_triple(
+ cir.func @missing_triple() {
+ cir.return
+ }
+}
+
+// -----
+
+// Non-string cir.triple.
+
+// expected-warning @below {{cannot create a CIR lower module, skipping the TargetLowering pass: expected a string from module attribute cir.triple}}
+module attributes {cir.triple = 42 : i32} {
+ // CHECK-LABEL: cir.func @non_string_triple(
+ cir.func @non_string_triple() {
+ cir.return
+ }
+}
+
+// -----
+
+// Empty cir.triple.
+
+// expected-warning @below {{cannot create a CIR lower module, skipping the TargetLowering pass: unknown triple '' in cir.triple attribute}}
+module attributes {cir.triple = ""} {
+ // CHECK-LABEL: cir.func @empty_triple(
+ cir.func @empty_triple() {
+ cir.return
+ }
+}
+
+// -----
+
+// Malformed cir.triple.
+
+// expected-warning @below {{cannot create a CIR lower module, skipping the TargetLowering pass: unknown triple 'garbage' in cir.triple attribute}}
+module attributes {cir.triple = "garbage"} {
+ // CHECK-LABEL: cir.func @malformed_triple(
+ cir.func @malformed_triple() {
+ cir.return
+ }
+}
+
+// -----
+
+// Well-formed cir.triple with an unknown target.
+
+// expected-warning @below {{cannot create a CIR lower module, skipping the TargetLowering pass: unknown triple 'foobar-unknown-unknown' in cir.triple attribute}}
+module attributes {cir.triple = "foobar-unknown-unknown"} {
+ // CHECK-LABEL: cir.func @unknown_triple(
+ cir.func @unknown_triple() {
+ cir.return
+ }
+}
+
+// -----
+
+// Valid cir.triple without cir.opt_info.
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+ // CHECK-LABEL: cir.func @valid_triple(
+ cir.func @valid_triple() {
+ cir.return
+ }
+}
+
+// -----
+
+// Valid cir.triple with a valid cir.opt_info.
+
+module attributes {
+ cir.triple = "x86_64-unknown-linux-gnu",
+ cir.opt_info = #cir.opt_info<level = 2, size = 1>
+} {
+ // CHECK-LABEL: cir.func @valid_opt_info(
+ cir.func @valid_opt_info() {
+ cir.return
+ }
+}
+
+// -----
+
+// Valid cir.triple with a cir.opt_info that is not an OptInfoAttr.
+
+// expected-warning @below {{cannot create a CIR lower module, skipping the TargetLowering pass: malformed cir.opt_info attribute}}
+module attributes {
+ cir.triple = "x86_64-unknown-linux-gnu",
+ cir.opt_info = 1 : i32
+} {
+ // CHECK-LABEL: cir.func @malformed_opt_info(
+ cir.func @malformed_opt_info() {
+ cir.return
+ }
+}
+
+// -----
+
+// Valid cir.triple with a string cir.opt_info.
+
+// expected-warning @below {{cannot create a CIR lower module, skipping the TargetLowering pass: malformed cir.opt_info attribute}}
+module attributes {
+ cir.triple = "x86_64-unknown-linux-gnu",
+ cir.opt_info = "O2"
+} {
+ // CHECK-LABEL: cir.func @string_opt_info(
+ cir.func @string_opt_info() {
+ cir.return
+ }
+}
+
+// -----
+
+// Valid cir.triple with a dictionary cir.opt_info that mimics OptInfoAttr's
+// fields.
+
+// expected-warning @below {{cannot create a CIR lower module, skipping the TargetLowering pass: malformed cir.opt_info attribute}}
+module attributes {
+ cir.triple = "x86_64-unknown-linux-gnu",
+ cir.opt_info = {level = 2 : i32, size = 1 : i32}
+} {
+ // CHECK-LABEL: cir.func @dict_opt_info(
+ cir.func @dict_opt_info() {
+ cir.return
+ }
+}
More information about the cfe-commits
mailing list