[clang] [CIR][NFC] Extract record-rebuilding type converter from CXXABILowering (PR #228599)
Konstantinos Parasyris via cfe-commits
cfe-commits at lists.llvm.org
Fri Oct 2 14:48:27 PDT 2026
https://github.com/koparasy created https://github.com/llvm/llvm-project/pull/228599
CXXABILowering's type converter rebuilds identified records whose member types change. Because identified records cannot be modified in place, each one is recreated under a temporary name, recursive records are resolved with a per-thread conversion stack, and the original names are restored once the conversion is done.
This patch moves the `CIRABITypeConverter` machinery into a reusable base class, `cir::RecordRewritingTypeConverter`.
`CIRABITypeConverter` now derives from it and only adds the C++ ABI specific conversions (data member and method types).
The base class also gets a `shouldConvertRecord(RecordType)` hook, which defaults to `true`. CXXABILowering does not override it, so its behavior is unchanged.
TargetLowering needs the same record rebuilding to convert language address spaces nested in record members. Today the following OpenCL code fails on SPIR-V:
```
struct S { __global int *p; int n; };
kernel void k(__global int *g) {
struct S s;
s.p = g;
*s.p = 1;
}
```
> error: member type mismatch
TargetLowering converts the `get_member` result to `!cir.ptr<!s32i, target_address_space(1)>`, but the field type inside `!rec_S` stays `lang_address_space(offload_global)`, so the verifier rejects the op. The same issue affects SYCL device code.
A follow-up will make TargetLowering's type converter derive from this class and use `shouldConvertRecord` to rebuild only the records that contain language address spaces. Records without them (e.g. all CUDA/HIP records) stay untouched, so the operations using them stay legal.
>From 95063ffc3fee5780cc29761119f709fcec3e678f Mon Sep 17 00:00:00 2001
From: Konstantinos Parasyris <konstantinos.parasyris at intel.com>
Date: Fri, 2 Oct 2026 14:43:39 -0700
Subject: [PATCH] [CIR][NFC] Extract record-rebuilding type converter from
CXXABILowering
CXXABILowering's type converter rebuilds identified records whose member
types change. Because identified records cannot be modified in place, each
one is recreated under a temporary name, recursive records are resolved with
a per-thread conversion stack, and the original names are restored once the
conversion is done.
This patch moves the `CIRABITypeConverter`` machinery into a reusable
base class, `cir::RecordRewritingTypeConverter`.
`CIRABITypeConverter` now derives from it and only adds the C++ ABI specific
conversions (data member and method types).
The base class also gets a `shouldConvertRecord(RecordType)` hook, which
defaults to `true`. CXXABILowering does not override it, so its behavior is
unchanged.
TargetLowering needs the same record rebuilding to convert language address
spaces nested in record members. Today the following OpenCL code fails on
SPIR-V:
```
struct S { __global int *p; int n; };
kernel void k(__global int *g) {
struct S s;
s.p = g;
*s.p = 1;
}
error: member type mismatch
```
TargetLowering converts the `get_member` result to
`!cir.ptr<!s32i, target_address_space(1)>`, but the field type inside `!rec_S`
stays `lang_address_space(offload_global)`, so the verifier rejects the op. The
same issue affects SYCL device code.
A follow-up will make TargetLowering's type converter derive from this class
and use `shouldConvertRecord` to rebuild only the records that contain
language address spaces. Records without them (e.g. all CUDA/HIP records) stay
untouched, so the operations using them stay legal.
---
.../lib/CIR/Dialect/Transforms/CMakeLists.txt | 1 +
.../CIR/Dialect/Transforms/CXXABILowering.cpp | 184 +----------------
.../Transforms/RecordTypeConverter.cpp | 185 ++++++++++++++++++
.../Dialect/Transforms/RecordTypeConverter.h | 76 +++++++
4 files changed, 266 insertions(+), 180 deletions(-)
create mode 100644 clang/lib/CIR/Dialect/Transforms/RecordTypeConverter.cpp
create mode 100644 clang/lib/CIR/Dialect/Transforms/RecordTypeConverter.h
diff --git a/clang/lib/CIR/Dialect/Transforms/CMakeLists.txt b/clang/lib/CIR/Dialect/Transforms/CMakeLists.txt
index 3678fc0b25384..2d6d04fb24abc 100644
--- a/clang/lib/CIR/Dialect/Transforms/CMakeLists.txt
+++ b/clang/lib/CIR/Dialect/Transforms/CMakeLists.txt
@@ -14,6 +14,7 @@ add_clang_library(MLIRCIRTransforms
GotoSolver.cpp
IdiomRecognizer.cpp
LibOpt.cpp
+ RecordTypeConverter.cpp
DEPENDS
MLIRCIRPassIncGen
diff --git a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
index 9a0e40bd4f506..735146b04c64f 100644
--- a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "PassDetail.h"
+#include "RecordTypeConverter.h"
#include "TargetLowering/LowerModule.h"
#include "mlir/Dialect/OpenACC/OpenACCOpsDialect.h.inc"
@@ -24,7 +25,6 @@
#include "clang/CIR/Dialect/Transforms/CIRTransformUtils.h"
#include "clang/CIR/MissingFeatures.h"
-#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/TypeSwitch.h"
using namespace mlir;
@@ -813,159 +813,12 @@ mlir::LogicalResult CIRVTableGetTypeInfoOpABILowering::matchAndRewrite(
namespace {
// A small type to handle type conversion for the the CXXABILoweringPass.
// Even though this is a CIR-to-CIR pass, we are eliminating some CIR types.
-// Most importantly, this pass solves recursive type conversion problems by
-// keeping a call stack.
-class CIRABITypeConverter : public mlir::TypeConverter {
-
- mlir::MLIRContext &context;
-
- // Recursive structure detection.
- // We store one entry per thread here, and rely on locking. This works the
- // same way as the LLVM-IR lowering does it, which has a similar problem.
- DenseMap<uint64_t, std::unique_ptr<SmallVector<cir::RecordType>>>
- conversionCallStack;
- llvm::sys::SmartRWMutex<true> callStackMutex;
-
- // In order to let us 'change the names' back after the fact, we collect them
- // along the way. They should only be added/accessed via the thread-safe
- // functions below.
- llvm::SmallVector<cir::RecordType> convertedRecordTypes;
- llvm::sys::SmartRWMutex<true> recordTypeMutex;
-
- // This provides a stack for the RecordTypes being processed on the current
- // thread, which lets us solve recursive conversions. This implementation is
- // cribbed from the LLVMTypeConverter which solves a similar but not identical
- // problem.
- SmallVector<cir::RecordType> &getCurrentThreadRecursiveStack() {
- {
- // Most of the time, the entry already exists in the map.
- std::shared_lock<decltype(callStackMutex)> lock(callStackMutex,
- std::defer_lock);
- if (context.isMultithreadingEnabled())
- lock.lock();
- auto recursiveStack = conversionCallStack.find(llvm::get_threadid());
- if (recursiveStack != conversionCallStack.end())
- return *recursiveStack->second;
- }
-
- // First time this thread gets here, we have to get an exclusive access to
- // insert in the map
- std::unique_lock<decltype(callStackMutex)> lock(callStackMutex);
- auto recursiveStackInserted = conversionCallStack.insert(
- std::make_pair(llvm::get_threadid(),
- std::make_unique<SmallVector<cir::RecordType>>()));
- return *recursiveStackInserted.first->second;
- }
-
- void addConvertedRecordType(cir::RecordType rt) {
- std::unique_lock<decltype(recordTypeMutex)> lock(recordTypeMutex);
- convertedRecordTypes.push_back(rt);
- }
-
- llvm::SmallVector<mlir::Type> convertRecordMemberTypes(cir::RecordType type) {
- llvm::SmallVector<mlir::Type> loweredMemberTypes;
- loweredMemberTypes.reserve(type.getNumElements());
-
- if (mlir::failed(convertTypes(type.getMembers(), loweredMemberTypes)))
- return {};
-
- return loweredMemberTypes;
- }
-
- cir::RecordType convertRecordType(cir::RecordType type) {
- // Unnamed record types can't be referred to recursively, so we can just
- // convert this one. It also doesn't have uniqueness problems, so we can
- // just do a conversion on it.
- if (!type.getName()) {
- llvm::SmallVector<mlir::Type> converted = convertRecordMemberTypes(type);
- assert(converted.size() == type.getNumElements() &&
- "member conversion must be one type in, one type out for the "
- "kinds to carry over by index");
- if (auto u = mlir::dyn_cast<cir::UnionType>(type)) {
- mlir::Type loweredPadding;
- if (mlir::Type pad = u.getPadding())
- loweredPadding = convertType(pad);
- return cir::UnionType::get(type.getContext(), converted,
- type.getPacked(), loweredPadding,
- u.getMemberKinds());
- }
- auto s = mlir::cast<cir::StructType>(type);
- return cir::StructType::get(type.getContext(), converted,
- type.getPacked(), s.getIsClass(),
- s.getMemberKinds());
- }
-
- assert(!type.isIncomplete() || type.getMembers().empty());
-
- // If the type has already been converted, we can just return, since there
- // is nothing to do. Also, if it is incomplete, it can't have invalid
- // members! So we can skip transforming it.
- if (type.isIncomplete() || type.isABIConvertedRecord())
- return type;
-
- SmallVectorImpl<cir::RecordType> &recursiveStack =
- getCurrentThreadRecursiveStack();
-
- cir::RecordType convertedType;
- if (mlir::isa<cir::UnionType>(type))
- convertedType =
- cir::UnionType::get(type.getContext(), type.getABIConvertedName());
- else
- convertedType =
- cir::StructType::get(type.getContext(), type.getABIConvertedName(),
- mlir::cast<cir::StructType>(type).getIsClass());
-
- // This type has already been converted, just return it.
- if (convertedType.isComplete())
- return convertedType;
-
- // We put the existing 'type' into the vector if we're in the process of
- // converting it (and pop it when we're done). To prevent recursion,
- // just return the 'incomplete' version, and the 'top level' version of this
- // call will call 'complete' on it.
- if (llvm::is_contained(recursiveStack, type))
- return convertedType;
-
- recursiveStack.push_back(type);
- llvm::scope_exit popConvertingType(
- [&recursiveStack]() { recursiveStack.pop_back(); });
-
- SmallVector<mlir::Type> convertedMembers = convertRecordMemberTypes(type);
- assert(convertedMembers.size() == type.getNumElements() &&
- "member conversion must be one type in, one type out for the kinds "
- "to carry over by index");
-
- mlir::Type loweredPadding;
- if (auto u = mlir::dyn_cast<cir::UnionType>(type))
- if (mlir::Type pad = u.getPadding())
- loweredPadding = convertType(pad);
- convertedType.complete(convertedMembers, type.getPacked(), loweredPadding,
- type.getMemberKinds());
- addConvertedRecordType(convertedType);
- return convertedType;
- }
-
+// The records that contain them are rebuilt by RecordRewritingTypeConverter.
+class CIRABITypeConverter : public cir::RecordRewritingTypeConverter {
public:
CIRABITypeConverter(mlir::MLIRContext &ctx, mlir::DataLayout &dataLayout,
cir::LowerModule &lowerModule)
- : context(ctx) {
- addConversion([&](mlir::Type type) -> mlir::Type { return type; });
- // This is necessary in order to convert CIR pointer types that are
- // pointing to CIR types that we are lowering in this pass.
- addConversion([&](cir::PointerType type) -> mlir::Type {
- mlir::Type loweredPointeeType = convertType(type.getPointee());
- if (!loweredPointeeType)
- return {};
- return cir::PointerType::get(type.getContext(), loweredPointeeType,
- type.getAddrSpace());
- });
- addConversion([&](cir::ArrayType type) -> mlir::Type {
- mlir::Type loweredElementType = convertType(type.getElementType());
- if (!loweredElementType)
- return {};
- return cir::ArrayType::get(loweredElementType, type.getSize());
- });
-
+ : RecordRewritingTypeConverter(ctx) {
addConversion([&](cir::DataMemberType type) -> mlir::Type {
mlir::Type abiType =
lowerModule.getCXXABI().lowerDataMemberType(type, *this);
@@ -975,35 +828,6 @@ class CIRABITypeConverter : public mlir::TypeConverter {
mlir::Type abiType = lowerModule.getCXXABI().lowerMethodType(type, *this);
return convertType(abiType);
});
- // This is necessary in order to convert CIR function types that have
- // argument or return types that use CIR types that we are lowering in
- // this pass.
- addConversion([&](cir::FuncType type) -> mlir::Type {
- llvm::SmallVector<mlir::Type> loweredInputTypes;
- loweredInputTypes.reserve(type.getNumInputs());
- if (mlir::failed(convertTypes(type.getInputs(), loweredInputTypes)))
- return {};
-
- mlir::Type loweredReturnType = convertType(type.getReturnType());
- if (!loweredReturnType)
- return {};
-
- return cir::FuncType::get(loweredInputTypes, loweredReturnType,
- /*isVarArg=*/type.getVarArg());
- });
- addConversion([&](cir::StructType type) -> mlir::Type {
- return convertRecordType(type);
- });
- addConversion([&](cir::UnionType type) -> mlir::Type {
- return convertRecordType(type);
- });
- }
-
- void restoreRecordTypeNames() {
- std::unique_lock<decltype(recordTypeMutex)> lock(recordTypeMutex);
-
- for (auto rt : convertedRecordTypes)
- rt.removeABIConversionNamePrefix();
}
};
} // namespace
diff --git a/clang/lib/CIR/Dialect/Transforms/RecordTypeConverter.cpp b/clang/lib/CIR/Dialect/Transforms/RecordTypeConverter.cpp
new file mode 100644
index 0000000000000..529cdccaaa7fa
--- /dev/null
+++ b/clang/lib/CIR/Dialect/Transforms/RecordTypeConverter.cpp
@@ -0,0 +1,185 @@
+//===- RecordTypeConverter.cpp - Record-rebuilding type converter ---------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "RecordTypeConverter.h"
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/ScopeExit.h"
+#include "llvm/Support/Threading.h"
+
+#include <mutex>
+#include <shared_mutex>
+
+using namespace cir;
+
+RecordRewritingTypeConverter::RecordRewritingTypeConverter(
+ mlir::MLIRContext &context)
+ : context(context) {
+ addConversion([&](mlir::Type type) -> mlir::Type { return type; });
+ // This is necessary in order to convert CIR pointer types that are pointing
+ // to CIR types that are being converted.
+ addConversion([&](cir::PointerType type) -> mlir::Type {
+ mlir::Type loweredPointeeType = convertType(type.getPointee());
+ if (!loweredPointeeType)
+ return {};
+ return cir::PointerType::get(type.getContext(), loweredPointeeType,
+ type.getAddrSpace());
+ });
+ addConversion([&](cir::ArrayType type) -> mlir::Type {
+ mlir::Type loweredElementType = convertType(type.getElementType());
+ if (!loweredElementType)
+ return {};
+ return cir::ArrayType::get(loweredElementType, type.getSize());
+ });
+ // This is necessary in order to convert CIR function types that have
+ // argument or return types that use CIR types that are being converted.
+ addConversion([&](cir::FuncType type) -> mlir::Type {
+ llvm::SmallVector<mlir::Type> loweredInputTypes;
+ loweredInputTypes.reserve(type.getNumInputs());
+ if (mlir::failed(convertTypes(type.getInputs(), loweredInputTypes)))
+ return {};
+
+ mlir::Type loweredReturnType = convertType(type.getReturnType());
+ if (!loweredReturnType)
+ return {};
+
+ return cir::FuncType::get(loweredInputTypes, loweredReturnType,
+ /*isVarArg=*/type.getVarArg());
+ });
+ addConversion([&](cir::StructType type) -> mlir::Type {
+ return convertRecordType(type);
+ });
+ addConversion([&](cir::UnionType type) -> mlir::Type {
+ return convertRecordType(type);
+ });
+}
+
+void RecordRewritingTypeConverter::restoreRecordTypeNames() {
+ std::unique_lock<decltype(recordTypeMutex)> lock(recordTypeMutex);
+
+ for (auto rt : convertedRecordTypes)
+ rt.removeABIConversionNamePrefix();
+}
+
+// This provides a stack for the RecordTypes being processed on the current
+// thread, which lets us solve recursive conversions. This implementation is
+// cribbed from the LLVMTypeConverter which solves a similar but not identical
+// problem.
+llvm::SmallVector<cir::RecordType> &
+RecordRewritingTypeConverter::getCurrentThreadRecursiveStack() {
+ {
+ // Most of the time, the entry already exists in the map.
+ std::shared_lock<decltype(callStackMutex)> lock(callStackMutex,
+ std::defer_lock);
+ if (context.isMultithreadingEnabled())
+ lock.lock();
+ auto recursiveStack = conversionCallStack.find(llvm::get_threadid());
+ if (recursiveStack != conversionCallStack.end())
+ return *recursiveStack->second;
+ }
+
+ // First time this thread gets here, we have to get an exclusive access to
+ // insert in the map
+ std::unique_lock<decltype(callStackMutex)> lock(callStackMutex);
+ auto recursiveStackInserted = conversionCallStack.insert(
+ std::make_pair(llvm::get_threadid(),
+ std::make_unique<llvm::SmallVector<cir::RecordType>>()));
+ return *recursiveStackInserted.first->second;
+}
+
+void RecordRewritingTypeConverter::addConvertedRecordType(cir::RecordType rt) {
+ std::unique_lock<decltype(recordTypeMutex)> lock(recordTypeMutex);
+ convertedRecordTypes.push_back(rt);
+}
+
+llvm::SmallVector<mlir::Type>
+RecordRewritingTypeConverter::convertRecordMemberTypes(cir::RecordType type) {
+ llvm::SmallVector<mlir::Type> loweredMemberTypes;
+ loweredMemberTypes.reserve(type.getNumElements());
+
+ if (mlir::failed(convertTypes(type.getMembers(), loweredMemberTypes)))
+ return {};
+
+ return loweredMemberTypes;
+}
+
+cir::RecordType
+RecordRewritingTypeConverter::convertRecordType(cir::RecordType type) {
+ if (!shouldConvertRecord(type))
+ return type;
+
+ // Unnamed record types can't be referred to recursively, so we can just
+ // convert this one. It also doesn't have uniqueness problems, so we can
+ // just do a conversion on it.
+ if (!type.getName()) {
+ llvm::SmallVector<mlir::Type> converted = convertRecordMemberTypes(type);
+ assert(converted.size() == type.getNumElements() &&
+ "member conversion must be one type in, one type out for the "
+ "kinds to carry over by index");
+ if (auto u = mlir::dyn_cast<cir::UnionType>(type)) {
+ mlir::Type loweredPadding;
+ if (mlir::Type pad = u.getPadding())
+ loweredPadding = convertType(pad);
+ return cir::UnionType::get(type.getContext(), converted, type.getPacked(),
+ loweredPadding, u.getMemberKinds());
+ }
+ auto s = mlir::cast<cir::StructType>(type);
+ return cir::StructType::get(type.getContext(), converted, type.getPacked(),
+ s.getIsClass(), s.getMemberKinds());
+ }
+
+ assert(!type.isIncomplete() || type.getMembers().empty());
+
+ // If the type has already been converted, we can just return, since there
+ // is nothing to do. Also, if it is incomplete, it can't have invalid
+ // members! So we can skip transforming it.
+ if (type.isIncomplete() || type.isABIConvertedRecord())
+ return type;
+
+ llvm::SmallVectorImpl<cir::RecordType> &recursiveStack =
+ getCurrentThreadRecursiveStack();
+
+ cir::RecordType convertedType;
+ if (mlir::isa<cir::UnionType>(type))
+ convertedType =
+ cir::UnionType::get(type.getContext(), type.getABIConvertedName());
+ else
+ convertedType =
+ cir::StructType::get(type.getContext(), type.getABIConvertedName(),
+ mlir::cast<cir::StructType>(type).getIsClass());
+
+ // This type has already been converted, just return it.
+ if (convertedType.isComplete())
+ return convertedType;
+
+ // We put the existing 'type' into the vector if we're in the process of
+ // converting it (and pop it when we're done). To prevent recursion,
+ // just return the 'incomplete' version, and the 'top level' version of this
+ // call will call 'complete' on it.
+ if (llvm::is_contained(recursiveStack, type))
+ return convertedType;
+
+ recursiveStack.push_back(type);
+ llvm::scope_exit popConvertingType(
+ [&recursiveStack]() { recursiveStack.pop_back(); });
+
+ llvm::SmallVector<mlir::Type> convertedMembers =
+ convertRecordMemberTypes(type);
+ assert(convertedMembers.size() == type.getNumElements() &&
+ "member conversion must be one type in, one type out for the kinds "
+ "to carry over by index");
+
+ mlir::Type loweredPadding;
+ if (auto u = mlir::dyn_cast<cir::UnionType>(type))
+ if (mlir::Type pad = u.getPadding())
+ loweredPadding = convertType(pad);
+ convertedType.complete(convertedMembers, type.getPacked(), loweredPadding,
+ type.getMemberKinds());
+ addConvertedRecordType(convertedType);
+ return convertedType;
+}
diff --git a/clang/lib/CIR/Dialect/Transforms/RecordTypeConverter.h b/clang/lib/CIR/Dialect/Transforms/RecordTypeConverter.h
new file mode 100644
index 0000000000000..950355c603b89
--- /dev/null
+++ b/clang/lib/CIR/Dialect/Transforms/RecordTypeConverter.h
@@ -0,0 +1,76 @@
+//===- RecordTypeConverter.h - Record-rebuilding type converter -*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// A type converter base for CIR-to-CIR passes that rewrite types nested in
+// records.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_LIB_CIR_DIALECT_TRANSFORMS_RECORDTYPECONVERTER_H
+#define CLANG_LIB_CIR_DIALECT_TRANSFORMS_RECORDTYPECONVERTER_H
+
+#include "mlir/Transforms/DialectConversion.h"
+#include "clang/CIR/Dialect/IR/CIRTypes.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/RWMutex.h"
+
+#include <memory>
+
+namespace cir {
+
+/// A type converter that converts the types nested in pointers, arrays,
+/// functions and records.
+///
+/// Identified records can't be modified in place, so each one is rebuilt under
+/// a temporary name (see RecordType::getABIConvertedName). The conversion keeps
+/// a stack of the records being converted, which resolves recursive records.
+/// Once the conversion is done, restoreRecordTypeNames() gives the rebuilt
+/// records their original names back.
+///
+/// Subclasses add conversions for the types they rewrite. The type converter
+/// tries the most recently added conversion first, so a subclass can also
+/// replace one of the conversions registered here.
+class RecordRewritingTypeConverter : public mlir::TypeConverter {
+public:
+ explicit RecordRewritingTypeConverter(mlir::MLIRContext &context);
+ virtual ~RecordRewritingTypeConverter() = default;
+
+ /// Remove the temporary name of every record rebuilt by this converter.
+ void restoreRecordTypeNames();
+
+protected:
+ /// Whether \p type has to be rebuilt. Rebuilding every record is always
+ /// correct, but makes every operation that uses one illegal.
+ virtual bool shouldConvertRecord(cir::RecordType type) { return true; }
+
+private:
+ cir::RecordType convertRecordType(cir::RecordType type);
+ llvm::SmallVector<mlir::Type> convertRecordMemberTypes(cir::RecordType type);
+ llvm::SmallVector<cir::RecordType> &getCurrentThreadRecursiveStack();
+ void addConvertedRecordType(cir::RecordType rt);
+
+ mlir::MLIRContext &context;
+
+ // Recursive structure detection.
+ // We store one entry per thread here, and rely on locking. This works the
+ // same way as the LLVM-IR lowering does it, which has a similar problem.
+ llvm::DenseMap<uint64_t, std::unique_ptr<llvm::SmallVector<cir::RecordType>>>
+ conversionCallStack;
+ llvm::sys::SmartRWMutex<true> callStackMutex;
+
+ // In order to let us 'change the names' back after the fact, we collect them
+ // along the way. They should only be added/accessed via the thread-safe
+ // functions.
+ llvm::SmallVector<cir::RecordType> convertedRecordTypes;
+ llvm::sys::SmartRWMutex<true> recordTypeMutex;
+};
+
+} // namespace cir
+
+#endif // CLANG_LIB_CIR_DIALECT_TRANSFORMS_RECORDTYPECONVERTER_H
More information about the cfe-commits
mailing list