[clang] [CIR][EH] Preserved exception pointer address spaces in throw calls (PR #227595)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Sep 30 01:03:16 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Kunal Dubey (xakep8)
<details>
<summary>Changes</summary>
CIR previously stored the exception type information and destructor as symbol names. When these were converted into pointers, they could be placed in the wrong address space.
Passed them as typed pointer values intead and preserved their address spaces when creating the __cxa_throw call. Also verified that all throw calls in a module use compatible pointer types and added HIP regression tests.
Fixes #<!-- -->221941
---
Patch is 53.08 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/227595.diff
19 Files Affected:
- (modified) clang/include/clang/CIR/Dialect/IR/CIRDataLayout.h (+9)
- (modified) clang/include/clang/CIR/Dialect/IR/CIROps.td (+28-24)
- (modified) clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp (+20-10)
- (modified) clang/lib/CIR/CodeGen/CIRGenModule.cpp (+2-1)
- (modified) clang/lib/CIR/CodeGen/CIRGenModule.h (+9)
- (modified) clang/lib/CIR/Dialect/IR/CIRDialect.cpp (+59-6)
- (modified) clang/lib/CIR/Dialect/Transforms/CIRTransformUtils.cpp (+2-2)
- (modified) clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp (+34-47)
- (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp (+6-16)
- (modified) clang/test/CIR/CodeGen/cleanup-scope-throw-caught.cpp (+1-1)
- (modified) clang/test/CIR/CodeGen/cleanup-throw-from-cleanup.cpp (+2-2)
- (modified) clang/test/CIR/CodeGen/rtti-member-pointer.cpp (+1-1)
- (modified) clang/test/CIR/CodeGen/rtti-qualfn.cpp (+1-1)
- (modified) clang/test/CIR/CodeGen/ternary-throw.cpp (+19-19)
- (modified) clang/test/CIR/CodeGen/throws.cpp (+14-9)
- (modified) clang/test/CIR/CodeGen/try-catch.cpp (+1-1)
- (added) clang/test/CIR/CodeGenHIP/throw-no-rtti.hip (+83)
- (modified) clang/test/CIR/IR/invalid-throw.cir (+119-3)
- (modified) clang/test/CIR/IR/throw.cir (+12)
``````````diff
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRDataLayout.h b/clang/include/clang/CIR/Dialect/IR/CIRDataLayout.h
index 71214c798afbf..7b19ad1b12e40 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRDataLayout.h
+++ b/clang/include/clang/CIR/Dialect/IR/CIRDataLayout.h
@@ -129,6 +129,15 @@ class CIRDataLayout {
return {};
return cir::TargetAddressSpaceAttr::get(ctx, allocaASAttr.getUInt());
}
+
+ mlir::ptr::MemorySpaceAttrInterface
+ getGlobalAddrSpace(mlir::MLIRContext *ctx) const {
+ auto globalASAttr = mlir::dyn_cast_if_present<mlir::IntegerAttr>(
+ layout.getGlobalMemorySpace());
+ if (!globalASAttr || globalASAttr.getUInt() == 0)
+ return {};
+ return cir::TargetAddressSpaceAttr::get(ctx, globalASAttr.getUInt());
+ }
};
} // namespace cir
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index de805d4c642a2..0f5787f743856 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -8228,20 +8228,23 @@ def CIR_VAArgOp : CIR_Op<"va_arg"> {
//===----------------------------------------------------------------------===//
// Common base class shared by `cir.throw` and its EH counterpart
-// `cir.try_throw`. Both operations carry the same operands and attributes
-// (an optional exception pointer, an optional RTTI symbol and an optional
-// destructor symbol) and use the same verifier logic; subclasses contribute
-// any additional traits, successors and assembly format pieces.
+// `cir.try_throw`. A normal throw carries an exception pointer, an RTTI pointer
+// and a destructor pointer as SSA operands. Null RTTI and destructor pointers
+// are represented by typed null values. The zero-operand form represents a
+// rethrow. Since every normal throw lowers to the same `__cxa_throw` symbol,
+// the address spaces of these three operands must be consistent across the
+// module. Subclasses contribute any additional traits, successors and assembly
+// format pieces.
class CIR_ThrowOpBase<string mnemonic, list<Trait> traits = []>
- : CIR_Op<mnemonic, traits> {
+ : CIR_Op<mnemonic, !listconcat(traits, [AttrSizedOperandSegments])> {
let arguments = (ins
Optional<CIR_PointerType>:$exception_ptr,
- OptionalAttr<FlatSymbolRefAttr>:$type_info,
- OptionalAttr<FlatSymbolRefAttr>:$dtor
+ Optional<CIR_PointerType>:$type_info,
+ Optional<CIR_PointerType>:$dtor
);
let extraClassDeclaration = [{
- bool rethrows() { return getNumOperands() == 0; }
+ bool rethrows() { return !getExceptionPtr(); }
}];
let hasVerifier = 1;
@@ -8257,12 +8260,12 @@ def CIR_ThrowOp : CIR_ThrowOpBase<"throw"> {
This operation is equivalent to either __cxa_throw or __cxa_rethrow,
depending on the arguments.
- The absense of arguments for `cir.throw` means it rethrows.
+ The absence of arguments for `cir.throw` means it rethrows.
- For the no-rethrow version, it must have at least two operands, the RTTI
- information, a pointer to the exception object (likely allocated via
- `cir.alloc_exception`) and finally an optional dtor, which might run as
- part of this operation.
+ For the non-rethrow version, it has three operands: a pointer to the
+ exception object (likely allocated via `cir.alloc_exception`), the RTTI
+ pointer and the destructor pointer. The latter two may be typed null
+ pointers.
Example:
@@ -8281,15 +8284,16 @@ def CIR_ThrowOp : CIR_ThrowOpBase<"throw"> {
// Store string addr for "Division by zero condition!"
cir.store %string_addr, %exception_addr : !cir.ptr<!s8i>,
!cir.ptr<!cir.ptr<!s8i>>
- cir.throw %exception_addr : !cir.ptr<!cir.ptr<!u8i>>,
- @_ZTIPKc
+ %type_info = cir.const #cir.global_view<@_ZTIPKc> : !cir.ptr<!u8i>
+ %dtor = cir.const #cir.ptr<null> : !cir.ptr<!void>
+ cir.throw %exception_addr, %type_info, %dtor :
+ !cir.ptr<!cir.ptr<!u8i>>, !cir.ptr<!u8i>, !cir.ptr<!void>
```
}];
let assemblyFormat = [{
- ($exception_ptr^ `:` type($exception_ptr))?
- (`,` $type_info^)?
- (`,` $dtor^)?
+ ($exception_ptr^ `,` $type_info `,` $dtor `:`
+ type($exception_ptr) `,` type($type_info) `,` type($dtor))?
attr-dict
}];
}
@@ -8309,8 +8313,8 @@ def CIR_TryThrowOp : CIR_ThrowOpBase<"try_throw", [Terminator]> {
analogous to how `cir.try_call` is the EH counterpart of `cir.call`.
Like `cir.throw`, the absence of operands means rethrow. With operands,
- it carries the same exception pointer, type info, and optional
- destructor as `cir.throw`.
+ it carries the same exception pointer, type-info pointer, and destructor
+ pointer as `cir.throw`.
This operation is produced by the FlattenCFG pass for `cir.throw`
operations that appear inside a cleanup scope or try region. It is
@@ -8320,7 +8324,8 @@ def CIR_TryThrowOp : CIR_ThrowOpBase<"try_throw", [Terminator]> {
Example:
```
- cir.try_throw %exception_addr : !cir.ptr<!s32i>, @_ZTIi
+ cir.try_throw %exception_addr, %type_info, %dtor :
+ !cir.ptr<!s32i>, !cir.ptr<!u8i>, !cir.ptr<!void>
^normalDest, ^unwindDest
^normalDest:
cir.unreachable
@@ -8335,9 +8340,8 @@ def CIR_TryThrowOp : CIR_ThrowOpBase<"try_throw", [Terminator]> {
);
let assemblyFormat = [{
- ($exception_ptr^ `:` type($exception_ptr))?
- (`,` $type_info^)?
- (`,` $dtor^)?
+ ($exception_ptr^ `,` $type_info `,` $dtor `:`
+ type($exception_ptr) `,` type($type_info) `,` type($dtor))?
$normalDest `,` $unwindDest
attr-dict
}];
diff --git a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
index 827f000ae573d..4575663ce96fc 100644
--- a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
@@ -1803,8 +1803,8 @@ mlir::Value CIRGenItaniumCXXABI::getCXXDestructorImplicitParam(
// to the throw block and create a block for the remaining operations.
static void insertThrowAndSplit(mlir::OpBuilder &builder, mlir::Location loc,
mlir::Value exceptionPtr = {},
- mlir::FlatSymbolRefAttr typeInfo = {},
- mlir::FlatSymbolRefAttr dtor = {}) {
+ mlir::Value typeInfo = {},
+ mlir::Value dtor = {}) {
mlir::Block *currentBlock = builder.getInsertionBlock();
mlir::Region *region = currentBlock->getParent();
@@ -1861,11 +1861,16 @@ void CIRGenItaniumCXXABI::emitThrow(CIRGenFunction &cgf,
CharUnits exnAlign = cgf.getContext().getExnObjectAlignment();
cgf.emitAnyExprToExn(e->getSubExpr(), Address(exceptionPtr, exnAlign));
- // Get the RTTI symbol address.
- auto typeInfo = mlir::cast<cir::GlobalViewAttr>(
+ // Materialize the RTTI address as an SSA value. Device compilation may
+ // suppress RTTI emission, in which case this is a typed null pointer in the
+ // target's global address space instead of a view of an RTTI global.
+ auto typeInfoAttr = mlir::cast<mlir::TypedAttr>(
cgm.getAddrOfRTTIDescriptor(subExprLoc, clangThrowType,
/*forEH=*/true));
- assert(!typeInfo.getIndices() && "expected no indirection");
+ if (auto globalView = mlir::dyn_cast<cir::GlobalViewAttr>(typeInfoAttr))
+ assert(!globalView.getIndices() && "expected no indirection");
+ mlir::Value typeInfo =
+ cir::ConstantOp::create(builder, subExprLoc, typeInfoAttr);
// The address of the destructor.
//
@@ -1875,21 +1880,26 @@ void CIRGenItaniumCXXABI::emitThrow(CIRGenFunction &cgf,
// Lowering pass to skip passing the trivial function.
//
const auto *cxxrd = clangThrowType->getAsCXXRecordDecl();
- mlir::FlatSymbolRefAttr dtor{};
+ cir::PointerType dtorTy = builder.getVoidPtrTy();
+ mlir::Value dtor = builder.getNullPtr(dtorTy, subExprLoc);
if (cxxrd && !cxxrd->hasTrivialDestructor()) {
// __cxa_throw is declared to take its destructor as void (*)(void *). We
// must match that if function pointers can be authenticated with a
// discriminator based on their type.
assert(!cir::MissingFeatures::pointerAuthentication());
CXXDestructorDecl *dtorD = cxxrd->getDestructor();
- dtor = mlir::FlatSymbolRefAttr::get(
- cgm.getAddrOfCXXStructor(GlobalDecl(dtorD, Dtor_Complete))
- .getSymNameAttr());
+ cir::FuncOp dtorFunc =
+ cgm.getAddrOfCXXStructor(GlobalDecl(dtorD, Dtor_Complete));
+ cir::PointerType dtorFuncPtrTy =
+ builder.getPointerTo(dtorFunc.getFunctionType());
+ dtor = cir::GetGlobalOp::create(builder, subExprLoc, dtorFuncPtrTy,
+ dtorFunc.getSymName());
+ dtor = builder.createBitcast(dtor, dtorTy);
}
// Now throw the exception.
mlir::Location loc = cgf.getLoc(e->getSourceRange());
- insertThrowAndSplit(builder, loc, exceptionPtr, typeInfo.getSymbol(), dtor);
+ insertThrowAndSplit(builder, loc, exceptionPtr, typeInfo, dtor);
}
CIRGenCXXABI *clang::CIRGen::CreateCIRGenItaniumCXXABI(CIRGenModule &cgm) {
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index 007788d7e27c7..6344114eb56b1 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -4154,7 +4154,8 @@ mlir::Attribute CIRGenModule::getAddrOfRTTIDescriptor(mlir::Location loc,
// FIXME: should we even be calling this method if RTTI is disabled
// and it's not for EH?
if (!shouldEmitRTTI(forEh))
- return builder.getConstNullPtrAttr(builder.getUInt8PtrTy());
+ return builder.getConstNullPtrAttr(forEh ? getGlobalsUInt8PtrTy()
+ : builder.getUInt8PtrTy());
if (forEh && ty->isObjCObjectPointerType() &&
langOpts.ObjCRuntime.isGNUFamily()) {
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h b/clang/lib/CIR/CodeGen/CIRGenModule.h
index 3fb95f346536d..31d56304e3d4c 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.h
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.h
@@ -600,6 +600,15 @@ class CIRGenModule : public CIRGenTypeCache {
getTriple().isNVPTX());
}
+ /// Return an i8 pointer in the target's address space for global variables.
+ /// RTTI descriptors use this type, including the null descriptor passed to
+ /// the exception runtime when device compilation suppresses RTTI emission.
+ cir::PointerType getGlobalsUInt8PtrTy() {
+ return builder.getPointerTo(
+ builder.getUInt8Ty(),
+ getDataLayout().getGlobalAddrSpace(&getMLIRContext()));
+ }
+
/// Emit type info if type of an expression is a variably modified
/// type. Also emit proper debug info for cast types.
void emitExplicitCastExprType(const ExplicitCastExpr *e,
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index d5a587ff6d81e..5d98d3b288c10 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -34,6 +34,8 @@
#include "llvm/ADT/TypeSwitch.h"
#include "llvm/Support/LogicalResult.h"
+#include <array>
+
using namespace mlir;
using namespace cir;
@@ -4643,17 +4645,68 @@ ParseResult cir::InlineAsmOp::parse(OpAsmParser &parser,
// ThrowOp / TryThrowOp
//===----------------------------------------------------------------------===//
+using ThrowAddressSpaces = std::array<mlir::ptr::MemorySpaceAttrInterface, 3>;
+
+template <typename ThrowOpTy>
+static std::optional<ThrowAddressSpaces> getThrowAddressSpaces(ThrowOpTy op) {
+ if (!op.getExceptionPtr() || !op.getTypeInfo() || !op.getDtor())
+ return std::nullopt;
+
+ return ThrowAddressSpaces{
+ mlir::cast<cir::PointerType>(op.getExceptionPtr().getType())
+ .getAddrSpace(),
+ mlir::cast<cir::PointerType>(op.getTypeInfo().getType()).getAddrSpace(),
+ mlir::cast<cir::PointerType>(op.getDtor().getType()).getAddrSpace()};
+}
+
+static std::optional<ThrowAddressSpaces>
+getThrowAddressSpaces(mlir::Operation *op) {
+ if (auto throwOp = mlir::dyn_cast<cir::ThrowOp>(op))
+ return getThrowAddressSpaces(throwOp);
+ if (auto tryThrowOp = mlir::dyn_cast<cir::TryThrowOp>(op))
+ return getThrowAddressSpaces(tryThrowOp);
+ return std::nullopt;
+}
+
template <typename ThrowOpTy>
static mlir::LogicalResult verifyThrowOpImpl(ThrowOpTy op) {
- if (op.rethrows())
+ bool hasExceptionPtr = static_cast<bool>(op.getExceptionPtr());
+ bool hasTypeInfo = static_cast<bool>(op.getTypeInfo());
+ bool hasDtor = static_cast<bool>(op.getDtor());
+
+ if (!hasExceptionPtr && !hasTypeInfo && !hasDtor)
return mlir::success();
- if (op.getNumOperands() != 0) {
- if (op.getTypeInfo())
- return mlir::success();
- return op.emitOpError() << "'type_info' symbol attribute missing";
- }
+ if (!hasExceptionPtr || !hasTypeInfo || !hasDtor)
+ return op.emitOpError()
+ << "must have either no operands for a rethrow or exception, "
+ "type_info, and destructor pointer operands for a throw";
+
+ auto module = op->template getParentOfType<mlir::ModuleOp>();
+ if (!module)
+ return op.emitOpError("expects an enclosing module");
+
+ mlir::Operation *firstThrow = nullptr;
+ std::optional<ThrowAddressSpaces> expectedAddressSpaces;
+ module.walk([&](mlir::Operation *candidate) {
+ expectedAddressSpaces = getThrowAddressSpaces(candidate);
+ if (!expectedAddressSpaces)
+ return mlir::WalkResult::advance();
+ firstThrow = candidate;
+ return mlir::WalkResult::interrupt();
+ });
+
+ assert(expectedAddressSpaces && firstThrow &&
+ "the operation being verified provides a throw signature");
+ if (*expectedAddressSpaces == *getThrowAddressSpaces(op))
+ return mlir::success();
+ mlir::InFlightDiagnostic diag = op.emitOpError(
+ "operand address spaces must match the first non-rethrow cir.throw or "
+ "cir.try_throw in the module");
+ diag.attachNote(firstThrow->getLoc())
+ << "the module's __cxa_throw address-space signature is established "
+ "here";
return mlir::failure();
}
diff --git a/clang/lib/CIR/Dialect/Transforms/CIRTransformUtils.cpp b/clang/lib/CIR/Dialect/Transforms/CIRTransformUtils.cpp
index 1c272527603fa..5132100eafede 100644
--- a/clang/lib/CIR/Dialect/Transforms/CIRTransformUtils.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/CIRTransformUtils.cpp
@@ -124,8 +124,8 @@ mlir::Block *cir::replaceThrowWithTryThrow(cir::ThrowOp throwOp,
// Build the try_throw to replace the original throw.
rewriter.setInsertionPoint(throwOp);
auto tryThrowOp = cir::TryThrowOp::create(
- rewriter, loc, throwOp.getExceptionPtr(), throwOp.getTypeInfoAttr(),
- throwOp.getDtorAttr(), normalDest, unwindDest);
+ rewriter, loc, throwOp.getExceptionPtr(), throwOp.getTypeInfo(),
+ throwOp.getDtor(), normalDest, unwindDest);
// The shared inherent state is already set by TryThrowOp::create. Preserve
// only auxiliary metadata here.
diff --git a/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp b/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp
index 77ce7434c8ed3..221168c5eb2d4 100644
--- a/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp
@@ -139,7 +139,9 @@ class ItaniumEHLowering : public EHABILowering {
void ensureRuntimeDecls(mlir::Location loc);
void ensureClangCallTerminate(mlir::Location loc);
- void ensureCxaThrowDecl(mlir::Location loc);
+ void ensureCxaThrowDecl(mlir::Location loc, cir::PointerType exceptionPtrType,
+ cir::PointerType typeInfoPtrType,
+ cir::PointerType dtorPtrType);
void ensureCxaRethrowDecl(mlir::Location loc);
void ensureCxaCallUnexpectedDecl(mlir::Location loc);
mlir::Block *buildTerminateBlock(cir::FuncOp funcOp, mlir::Location loc);
@@ -265,12 +267,20 @@ void ItaniumEHLowering::ensureClangCallTerminate(mlir::Location loc) {
/// Ensure the __cxa_throw runtime function is declared in the module.
///
-/// void __cxa_throw(void *exception, void *type_info, void *dtor);
-void ItaniumEHLowering::ensureCxaThrowDecl(mlir::Location loc) {
+/// void __cxa_throw(void *exception, global void *type_info, void *dtor);
+///
+/// The type-info pointer may use a target-specific global address space, so
+/// derive the declaration from the typed throw operands instead of assuming
+/// that all three pointers use the default address space.
+void ItaniumEHLowering::ensureCxaThrowDecl(mlir::Location loc,
+ cir::PointerType exceptionPtrType,
+ cir::PointerType typeInfoPtrType,
+ cir::PointerType dtorPtrType) {
if (cxaThrowFunc)
return;
- auto throwFuncTy = cir::FuncType::get({voidPtrType, voidPtrType, voidPtrType},
- voidType, /*isVarArg=*/false);
+ auto throwFuncTy = cir::FuncType::get(
+ {exceptionPtrType, typeInfoPtrType, dtorPtrType}, voidType,
+ /*isVarArg=*/false);
cxaThrowFunc =
getOrCreateRuntimeFuncDecl(mod, loc, "__cxa_throw", throwFuncTy);
}
@@ -906,9 +916,9 @@ ItaniumEHLowering::lowerConstructCatchParam(cir::ConstructCatchParamOp op,
}
/// Lower a cir.try_throw to a cir.try_call of __cxa_throw (or
-/// __cxa_rethrow for the no-operand rethrow form). Materializes the
-/// type_info and dtor pointers from their symbol attributes, bitcasting
-/// each to !cir.ptr<!void> as required by the runtime function signature.
+/// __cxa_rethrow for the no-operand rethrow form). Bitcast each typed pointer
+/// operand to a void pointer in the same address space to match the runtime
+/// function signature.
mlir::LogicalResult ItaniumEHLowering::lowerTryThrow(cir::TryThrowOp op) {
mlir::Location loc = op.getLoc();
mlir::Block *normalDest = op.getNormalDest();
@@ -924,45 +934,22 @@ mlir::LogicalResult ItaniumEHLowering::lowerTryThrow(cir::TryThrowOp op) {
return mlir::success();
}
- ensureCxaThrowDecl(loc);
-
- // Bitcast the exception pointer to void* if necessary.
- mlir::Value exnPtr = op.getExceptionPtr();
- if (exnPtr.getType() != voidPtrType)
- exnPtr = cir::CastOp::create(builder, loc, voidPtrType,
- cir::CastKind::bitcast, exnPtr);
-
- // Materialize the type_info pointer, looking up the typed symbol in the
- // module so we get the correct pointer type for cir.get_global, then
- // bitcasting to void* to match the runtime signature.
- mlir::FlatSymbolRefAttr typeInfoAttr = op.getTypeInfoAttr();
- auto typeInfoGlobal = mod.lookupSymbol<cir::GlobalOp>(typeInfoAttr);
- if (!typeInfoGlobal)
- return op.emitError("type_info symbol not found in module");
- auto typeInfoPtrTy = cir::PointerType::get(typeInfoGlobal.getSymType());
- mlir::Value typeInfo = cir::GetGlobalOp::create(builder, loc, typeInfoPtrTy,
- typeInfoAttr.getValue());
- if (typeInfo.getType() != voidPtrType)
- typeInfo = cir::CastOp::create(builder, loc, voidPtrType,
- cir::CastKind::bitcast, typeInfo);
-
- // Materialize the dtor pointer (or null if no dtor).
- mlir::Value dtor;
- if (mlir::FlatSymbolRefAttr dtorAttr = op.getDtorAttr()) {
- auto dtorFunc = mod.lookupSymbol<cir::FuncOp>(dtorAttr);
- if (!dtorFunc)
- return op.emitError("dtor symbol not found in module");
- auto dtorPtrTy = cir::PointerType::get(dtorFunc.getFunctionType());
- dtor =
- cir::GetGlobalOp::create(builder, loc, dtorPtrTy, dtorAttr.getValue());
- if (dtor.getType() != voidPtrType)
- dtor = cir::CastOp::create(builder, loc, voidPtrType,
- cir::CastKind::bitcast, dtor);
- } else {
- dtor = cir::ConstantOp::create(
- builder, loc,
- cir::ConstPtrAttr::get(voidPtrType, builder.getI64IntegerAttr(0)));
- }
+ auto castToVoidPtr = [&](mlir::Value value) -> mlir::Value {
+ auto ptrType = mlir::cast<cir::PointerType>(value.getType());
+ auto targetType = cir::PointerType::get(voidType, ptrType.getAddrSpace());
+ if (value.getType() == targetType)
+ return value;
+ return cir::CastOp::create(builder, loc, targetType, cir::CastKind::bitcast,
+ ...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/227595
More information about the cfe-commits
mailing list