[clang] [CIR] Record if c++ ABI was overridden via -fc++-abi flag (PR #229494)
Mariya Podchishchaeva via cfe-commits
cfe-commits at lists.llvm.org
Thu Oct 8 05:14:35 PDT 2026
https://github.com/Fznamznon updated https://github.com/llvm/llvm-project/pull/229494
>From 5e73d15620e1543f8de059c423c4cfb69650b12d Mon Sep 17 00:00:00 2001
From: Mariya Podchishchaeva <Mariya.Podchishchaeva at amd.com>
Date: Tue, 6 Oct 2026 12:11:07 -0500
Subject: [PATCH 1/6] [CIR] Record if c++ ABI was overridden via -fc++-abi flag
Add an optional string module attribute that holds overridden ABI value.
In case it is not present, C++ ABI will be derived from the triple.
---
.../clang/CIR/Dialect/IR/CIRDialect.td | 2 ++
clang/lib/CIR/CodeGen/CIRGenModule.cpp | 7 ++++++
clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 16 +++++++++++++
.../Transforms/TargetLowering/LowerModule.cpp | 6 +++++
.../Transforms/TargetLowering/LowerModule.h | 4 +---
clang/test/CIR/CodeGen/cxx-abi-override.cpp | 24 +++++++++++++++++++
clang/test/CIR/IR/invalid-cxx-abi.cir | 20 ++++++++++++++++
clang/test/CIR/IR/lowering-lang-options.cir | 3 ++-
8 files changed, 78 insertions(+), 4 deletions(-)
create mode 100644 clang/test/CIR/CodeGen/cxx-abi-override.cpp
create mode 100644 clang/test/CIR/IR/invalid-cxx-abi.cir
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRDialect.td b/clang/include/clang/CIR/Dialect/IR/CIRDialect.td
index 70647fa194329..3b950e7f4da1c 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRDialect.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRDialect.td
@@ -43,6 +43,8 @@ def CIR_Dialect : Dialect {
static llvm::StringRef getTripleAttrName() { return "cir.triple"; }
// TargetInfo::getABI(), e.g. "avx512" on x86 or "aapcs" on ARM.
static llvm::StringRef getTargetABIAttrName() { return "cir.target_abi"; }
+ // -fc++-abi override, if not present the target default is used.
+ static llvm::StringRef getCXXABIAttrName() { return "cir.cxx_abi"; }
static llvm::StringRef getSizeTypeWidthAttrName() { return "cir.size_type_width"; }
static llvm::StringRef getIntTypeWidthAttrName() { return "cir.int_type_width"; }
static llvm::StringRef getOptInfoAttrName() { return "cir.opt_info"; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index 5063b6a4cc779..358758f8edd22 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -159,6 +159,13 @@ CIRGenModule::CIRGenModule(mlir::MLIRContext &mlirContext,
builder.getStringAttr(getTriple().str()));
theModule->setAttr(cir::CIRDialect::getTargetABIAttrName(),
builder.getStringAttr(getTarget().getABI()));
+
+ // If cxxabi was overridden via -fc++-abi, record it.
+ if (langOpts.CXXABI)
+ theModule->setAttr(
+ cir::CIRDialect::getCXXABIAttrName(),
+ builder.getStringAttr(TargetCXXABI::getSpelling(*langOpts.CXXABI)));
+
if (llvm::VersionTuple sdkVersion = getTarget().getSDKVersion();
!sdkVersion.empty())
theModule->setAttr(cir::CIRDialect::getSDKVersionAttrName(),
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 15cebd358040e..1496fae50fc18 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -28,6 +28,7 @@
#include "clang/CIR/Dialect/IR/CIROpsDialect.cpp.inc"
#include "clang/CIR/Dialect/IR/CIROpsEnums.cpp.inc"
+#include "clang/Basic/TargetCXXABI.h"
#include "clang/CIR/MissingFeatures.h"
#include "llvm/ADT/SetOperations.h"
#include "llvm/ADT/SmallSet.h"
@@ -257,6 +258,21 @@ cir::CIRDialect::verifyOperationAttribute(mlir::Operation *op,
if (isOpenCLVersionAttrName(attrName))
return verifyOpenCLVersionAttr(op, attr);
+ if (attrName == getCXXABIAttrName()) {
+ if (!mlir::isa<mlir::ModuleOp>(op))
+ return op->emitOpError() << "expects '" << getCXXABIAttrName()
+ << "' attribute to be attached to '"
+ << mlir::ModuleOp::getOperationName() << "'";
+ auto abi = mlir::dyn_cast<mlir::StringAttr>(attr.getValue());
+ if (!abi)
+ return op->emitOpError()
+ << "expects '" << getCXXABIAttrName() << "' to be a string";
+
+ if (!clang::TargetCXXABI::isABI(abi.getValue()))
+ return op->emitOpError() << "unknown C++ ABI '" << abi.getValue() << "'";
+ return success();
+ }
+
if (attrName == getOffloadContainerAttrName()) {
if (!mlir::isa<mlir::UnitAttr>(attr.getValue()))
return op->emitOpError() << "expects '" << getOffloadContainerAttrName()
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
index 03044286e8cf7..be16903f80f4c 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
@@ -114,6 +114,12 @@ std::unique_ptr<LowerModule> createLowerModule(mlir::ModuleOp module) {
langOpts.setClangABICompat(static_cast<clang::LangOptions::ClangABI>(
loweringLangOpts.getClangAbiCompat()));
}
+ // Some langopts are still not lowered.
+ assert(!cir::MissingFeatures::lowerModuleLangOpts());
+
+ if (auto cxxABI = module->getAttrOfType<mlir::StringAttr>(
+ cir::CIRDialect::getCXXABIAttrName()))
+ langOpts.CXXABI = clang::TargetCXXABI::getKind(cxxABI.getValue());
// FIXME(cir): This just uses the default code generation options. We need to
// account for custom options.
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h
index 56fcd0a9b58cd..c0a650d0eb6a0 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h
@@ -21,7 +21,6 @@
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"
-#include "clang/CIR/MissingFeatures.h"
#include <memory>
namespace cir {
@@ -46,8 +45,7 @@ class LowerModule {
const clang::LangOptions &getLangOpts() const { return langOpts; }
clang::TargetCXXABI::Kind getCXXABIKind() const {
- assert(!cir::MissingFeatures::lowerModuleLangOpts());
- return target->getCXXABI().getKind();
+ return langOpts.CXXABI.value_or(target->getCXXABI().getKind());
}
CIRCXXABI &getCXXABI() const { return *abi; }
diff --git a/clang/test/CIR/CodeGen/cxx-abi-override.cpp b/clang/test/CIR/CodeGen/cxx-abi-override.cpp
new file mode 100644
index 0000000000000..199ecb936bc51
--- /dev/null
+++ b/clang/test/CIR/CodeGen/cxx-abi-override.cpp
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -std=c++17 -triple aarch64-unknown-linux-gnu -fc++-abi=itanium \
+// RUN: -fclangir -emit-cir %s -o - | FileCheck %s --check-prefix=CIR-ITANIUM
+// RUN: %clang_cc1 -std=c++17 -triple aarch64-unknown-linux-gnu -fc++-abi=itanium \
+// RUN: -fclangir -emit-llvm %s -o - | FileCheck %s --check-prefix=LLVM-ITANIUM
+// RUN: %clang_cc1 -std=c++17 -triple aarch64-unknown-linux-gnu -fclangir \
+// RUN: -emit-cir %s -o - | FileCheck %s --check-prefix=CIR-ARM
+// RUN: %clang_cc1 -std=c++17 -triple aarch64-unknown-linux-gnu \
+// RUN: -fclangir -emit-llvm %s -o - | FileCheck %s --check-prefix=LLVM-ARM
+
+// Make sure CXXABI can be overridden with a flag. Check that by excersizing
+// pointer to member on arm with itanium cxxabi.
+
+// CIR-ITANIUM: cir.cxx_abi = "itanium"
+// No attribute, C++ ABI is derived from the triple.
+// CIR-ARM-NOT: cir.cxx_abi = "aarch64"
+
+struct S { virtual void v(); };
+void (S::*pv)() = &S::v;
+
+// CIR-ITANIUM: cir.global external @pv = #cir.const_record<{#cir.int<1> : !s64i, #cir.int<0> : !s64i}>
+// CIR-ARM: cir.global external @pv = #cir.const_record<{#cir.int<0> : !s64i, #cir.int<1> : !s64i}>
+
+// LLVM-ITANIUM: @pv = {{.*}}{ i64, i64 } { i64 1, i64 0 }
+// LLVM-ARM: @pv = {{.*}}{ i64, i64 } { i64 0, i64 1 }
diff --git a/clang/test/CIR/IR/invalid-cxx-abi.cir b/clang/test/CIR/IR/invalid-cxx-abi.cir
new file mode 100644
index 0000000000000..bb7d71bffa028
--- /dev/null
+++ b/clang/test/CIR/IR/invalid-cxx-abi.cir
@@ -0,0 +1,20 @@
+// RUN: cir-opt %s -verify-diagnostics -split-input-file
+
+// expected-error at +1 {{unknown C++ ABI 'bla'}}
+module attributes {cir.cxx_abi = "bla"} {
+}
+
+// -----
+
+// expected-error at +1 {{'builtin.module' op expects 'cir.cxx_abi' to be a string}}
+module attributes {cir.cxx_abi = 1 : i32} {
+}
+
+// -----
+
+module {
+ // expected-error at +1 {{'cir.func' op expects 'cir.cxx_abi' attribute to be attached to 'builtin.module'}}
+ cir.func @f() attributes {cir.cxx_abi = "itanium"} {
+ cir.return
+ }
+}
diff --git a/clang/test/CIR/IR/lowering-lang-options.cir b/clang/test/CIR/IR/lowering-lang-options.cir
index 2ef90bd94ed4e..e2bf59783aa55 100644
--- a/clang/test/CIR/IR/lowering-lang-options.cir
+++ b/clang/test/CIR/IR/lowering-lang-options.cir
@@ -7,9 +7,10 @@
module attributes {cir.lowering_lang_options = #cir.lowering_lang_options<
exceptions = true, threadsafe_statics = false, cuda = true,
cuda_is_device = true, hip = true, gpu_rdc = true, openmp = true,
- openmp_is_target_device = true, clang_abi_compat = 9>} {
+ openmp_is_target_device = true, clang_abi_compat = 9>, cir.cxx_abi = "itanium"} {
}
+// CHECK: cir.cxx_abi = "itanium"
// CHECK: cir.lowering_lang_options = #cir.lowering_lang_options<
// CHECK-SAME: exceptions = true, threadsafe_statics = false, cuda = true,
// CHECK-SAME: cuda_is_device = true, hip = true, gpu_rdc = true, openmp = true,
>From 59ef1c7f945a35e866cc60c7afc096b1aaeb93e9 Mon Sep 17 00:00:00 2001
From: Mariya Podchishchaeva <Mariya.Podchishchaeva at amd.com>
Date: Wed, 7 Oct 2026 06:01:35 -0500
Subject: [PATCH 2/6] Format
---
clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 79f9d80f96e8a..1519b93806709 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -26,9 +26,9 @@
#include "mlir/Interfaces/FunctionImplementation.h"
#include "mlir/Support/LLVM.h"
+#include "clang/Basic/TargetCXXABI.h"
#include "clang/CIR/Dialect/IR/CIROpsDialect.cpp.inc"
#include "clang/CIR/Dialect/IR/CIROpsEnums.cpp.inc"
-#include "clang/Basic/TargetCXXABI.h"
#include "clang/CIR/MissingFeatures.h"
#include "llvm/ADT/SetOperations.h"
#include "llvm/ADT/SmallSet.h"
>From 5b156ab360c32555f877b0b43d9cda4f6c329f02 Mon Sep 17 00:00:00 2001
From: Mariya Podchishchaeva <Mariya.Podchishchaeva at amd.com>
Date: Wed, 7 Oct 2026 06:02:30 -0500
Subject: [PATCH 3/6] Typo
---
clang/test/CIR/CodeGen/cxx-abi-override.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/test/CIR/CodeGen/cxx-abi-override.cpp b/clang/test/CIR/CodeGen/cxx-abi-override.cpp
index 199ecb936bc51..d9b483fd1d34d 100644
--- a/clang/test/CIR/CodeGen/cxx-abi-override.cpp
+++ b/clang/test/CIR/CodeGen/cxx-abi-override.cpp
@@ -7,7 +7,7 @@
// RUN: %clang_cc1 -std=c++17 -triple aarch64-unknown-linux-gnu \
// RUN: -fclangir -emit-llvm %s -o - | FileCheck %s --check-prefix=LLVM-ARM
-// Make sure CXXABI can be overridden with a flag. Check that by excersizing
+// Make sure CXXABI can be overridden with a flag. Check that by exercising
// pointer to member on arm with itanium cxxabi.
// CIR-ITANIUM: cir.cxx_abi = "itanium"
>From 40533b33fb2f7358d032dd141cb971d6321c76d2 Mon Sep 17 00:00:00 2001
From: Mariya Podchishchaeva <Mariya.Podchishchaeva at amd.com>
Date: Wed, 7 Oct 2026 06:38:40 -0500
Subject: [PATCH 4/6] Verify specified abi together with the triple and if it
is supported
---
clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 23 ++++++++++++++++++++++-
clang/test/CIR/IR/invalid-cxx-abi.cir | 12 ++++++++++++
2 files changed, 34 insertions(+), 1 deletion(-)
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 1519b93806709..e86d300c292c5 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -268,8 +268,29 @@ cir::CIRDialect::verifyOperationAttribute(mlir::Operation *op,
return op->emitOpError()
<< "expects '" << getCXXABIAttrName() << "' to be a string";
- if (!clang::TargetCXXABI::isABI(abi.getValue()))
+ StringRef abival = abi.getValue();
+ if (!clang::TargetCXXABI::isABI(abival))
return op->emitOpError() << "unknown C++ ABI '" << abi.getValue() << "'";
+
+ clang::TargetCXXABI::Kind kind =
+ clang::TargetCXXABI::getKind(abival);
+ if (auto triple = op->getAttrOfType<mlir::StringAttr>(getTripleAttrName()))
+ if (!clang::TargetCXXABI::isSupportedCXXABI(
+ llvm::Triple(triple.getValue()), kind))
+ return op->emitOpError()
+ << "C++ ABI '" << abi.getValue()
+ << "' is not supported on target '" << triple.getValue() << "'";
+
+ switch (kind) {
+ case clang::TargetCXXABI::GenericItanium:
+ case clang::TargetCXXABI::GenericAArch64:
+ case clang::TargetCXXABI::AppleARM64:
+ case clang::TargetCXXABI::Microsoft:
+ break;
+ default:
+ return op->emitOpError() << "C++ ABI '" << abi.getValue()
+ << "' is not yet supported by CIR";
+ }
return success();
}
diff --git a/clang/test/CIR/IR/invalid-cxx-abi.cir b/clang/test/CIR/IR/invalid-cxx-abi.cir
index bb7d71bffa028..5d9ce74313c4f 100644
--- a/clang/test/CIR/IR/invalid-cxx-abi.cir
+++ b/clang/test/CIR/IR/invalid-cxx-abi.cir
@@ -18,3 +18,15 @@ module {
cir.return
}
}
+
+// -----
+
+// expected-error at +1 {{C++ ABI 'microsoft' is not supported on target 'x86_64-unknown-linux-gnu'}}
+module attributes {cir.triple = "x86_64-unknown-linux-gnu", cir.cxx_abi = "microsoft"} {
+}
+
+// -----
+
+// expected-error at +1 {{C++ ABI 'fuchsia' is not yet supported by CIR}}
+module attributes {cir.triple = "aarch64-unknown-fuchsia", cir.cxx_abi = "fuchsia"} {
+}
>From 82419973a44d3a1b197bfd22fab53be1c639cf49 Mon Sep 17 00:00:00 2001
From: Mariya Podchishchaeva <Mariya.Podchishchaeva at amd.com>
Date: Wed, 7 Oct 2026 06:46:06 -0500
Subject: [PATCH 5/6] Move roundtrip test to a separate file
---
clang/test/CIR/IR/cxx-abi.cir | 9 +++++++++
clang/test/CIR/IR/lowering-lang-options.cir | 3 +--
2 files changed, 10 insertions(+), 2 deletions(-)
create mode 100644 clang/test/CIR/IR/cxx-abi.cir
diff --git a/clang/test/CIR/IR/cxx-abi.cir b/clang/test/CIR/IR/cxx-abi.cir
new file mode 100644
index 0000000000000..953df77d378eb
--- /dev/null
+++ b/clang/test/CIR/IR/cxx-abi.cir
@@ -0,0 +1,9 @@
+// RUN: cir-opt %s --verify-roundtrip | FileCheck %s
+
+// Check that cxx_abi attribute round-trips just fine.
+
+module attributes {cir.cxx_abi = "itanium", cir.triple="aarch64-unknown-linux-gnu"} {
+}
+
+// CHECK: cir.cxx_abi = "itanium"
+// CHECK: cir.triple = "aarch64-unknown-linux-gnu"
diff --git a/clang/test/CIR/IR/lowering-lang-options.cir b/clang/test/CIR/IR/lowering-lang-options.cir
index e2bf59783aa55..2ef90bd94ed4e 100644
--- a/clang/test/CIR/IR/lowering-lang-options.cir
+++ b/clang/test/CIR/IR/lowering-lang-options.cir
@@ -7,10 +7,9 @@
module attributes {cir.lowering_lang_options = #cir.lowering_lang_options<
exceptions = true, threadsafe_statics = false, cuda = true,
cuda_is_device = true, hip = true, gpu_rdc = true, openmp = true,
- openmp_is_target_device = true, clang_abi_compat = 9>, cir.cxx_abi = "itanium"} {
+ openmp_is_target_device = true, clang_abi_compat = 9>} {
}
-// CHECK: cir.cxx_abi = "itanium"
// CHECK: cir.lowering_lang_options = #cir.lowering_lang_options<
// CHECK-SAME: exceptions = true, threadsafe_statics = false, cuda = true,
// CHECK-SAME: cuda_is_device = true, hip = true, gpu_rdc = true, openmp = true,
>From 0ed6e660aaa69b99107355c2202af76dab02ca59 Mon Sep 17 00:00:00 2001
From: Mariya Podchishchaeva <Mariya.Podchishchaeva at amd.com>
Date: Thu, 8 Oct 2026 05:54:22 -0500
Subject: [PATCH 6/6] Format
---
clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index e86d300c292c5..956acf90da6f2 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -272,8 +272,7 @@ cir::CIRDialect::verifyOperationAttribute(mlir::Operation *op,
if (!clang::TargetCXXABI::isABI(abival))
return op->emitOpError() << "unknown C++ ABI '" << abi.getValue() << "'";
- clang::TargetCXXABI::Kind kind =
- clang::TargetCXXABI::getKind(abival);
+ clang::TargetCXXABI::Kind kind = clang::TargetCXXABI::getKind(abival);
if (auto triple = op->getAttrOfType<mlir::StringAttr>(getTripleAttrName()))
if (!clang::TargetCXXABI::isSupportedCXXABI(
llvm::Triple(triple.getValue()), kind))
More information about the cfe-commits
mailing list