[clang] fc1f3ff - [CIR] Fix 'cookie' size of array delete on aligned type (#225806)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Sep 23 13:47:29 PDT 2026
Author: Erich Keane
Date: 2026-09-23T13:47:21-07:00
New Revision: fc1f3ff5a3b3da827cfca31d07a79c036e03b545
URL: https://github.com/llvm/llvm-project/commit/fc1f3ff5a3b3da827cfca31d07a79c036e03b545
DIFF: https://github.com/llvm/llvm-project/commit/fc1f3ff5a3b3da827cfca31d07a79c036e03b545.diff
LOG: [CIR] Fix 'cookie' size of array delete on aligned type (#225806)
This came up in some test suite, the cookie size calcuation of a array
delete with a 'cookie' was incorrect if the type had an alignment. This
patch strings the correct alignment through the 'element_align' tag on
the array-delete operation, and uses that for the final calculation,
matching classic codegen.
Added:
clang/test/CIR/CodeGen/delete-array-overaligned-cookie.cpp
Modified:
clang/include/clang/CIR/Dialect/IR/CIROps.td
clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.cpp
clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.h
clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp
clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerMicrosoftCXXABI.cpp
clang/test/CIR/CodeGen/delete-array-aligned.cpp
clang/test/CIR/CodeGen/delete-array-throwing-dtor.cpp
clang/test/CIR/IR/invalid-delete-array.cir
Removed:
################################################################################
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index f6b524176a655..e3276adef0d1e 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -4547,6 +4547,10 @@ def CIR_DeleteArrayOp : CIR_Op<"delete_array"> {
The `dtor_may_throw` unit property, when present, indicates that the
element destructor may throw exceptions.
+
+ The `element_align` attribute gives the element type's preferred
+ alignment in bytes, which should be the same value the corresponding `new[]`
+ uses to size its array cookie.
}];
let arguments = (ins
@@ -4554,16 +4558,19 @@ def CIR_DeleteArrayOp : CIR_Op<"delete_array"> {
FlatSymbolRefAttr:$delete_fn,
CIR_UsualDeleteParamsAttr:$delete_params,
OptionalAttr<FlatSymbolRefAttr>:$element_dtor,
- UnitProp:$dtor_may_throw
+ UnitProp:$dtor_may_throw,
+ I64Attr:$element_align
);
let builders = [
OpBuilder<(ins "mlir::Value":$address,
"mlir::FlatSymbolRefAttr":$delete_fn,
- "cir::UsualDeleteParamsAttr":$delete_params), [{
+ "cir::UsualDeleteParamsAttr":$delete_params,
+ "uint64_t":$element_align), [{
build($_builder, $_state, address, delete_fn, delete_params,
/*element_dtor=*/mlir::FlatSymbolRefAttr{},
- /*dtor_may_throw=*/false);
+ /*dtor_may_throw=*/false,
+ $_builder.getI64IntegerAttr(element_align));
}]>
];
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
index d0105c96cfd39..56d54a374cf5c 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
@@ -1536,6 +1536,11 @@ void CIRGenFunction::emitCXXDeleteExpr(const CXXDeleteExpr *e) {
builder.getContext(), udp.Size, align,
isTypeAwareAllocation(udp.TypeAwareDelete), udp.DestroyingDelete);
+ // Alignment of the element, used for the 'cookie' later.
+ uint64_t elementAlign = cgm.getASTContext()
+ .getPreferredTypeAlignInChars(deleteTy)
+ .getQuantity();
+
mlir::FlatSymbolRefAttr elementDtor;
bool hasThrowingDtor = false;
if (const auto *rd = deleteTy->getAsCXXRecordDecl()) {
@@ -1552,7 +1557,8 @@ void CIRGenFunction::emitCXXDeleteExpr(const CXXDeleteExpr *e) {
cir::DeleteArrayOp::create(builder, ptr.getPointer().getLoc(),
ptr.getPointer(), deleteFn, deleteParams,
- elementDtor, hasThrowingDtor);
+ elementDtor, hasThrowingDtor,
+ builder.getI64IntegerAttr(elementAlign));
} else {
emitObjectDelete(*this, e, ptr, deleteTy);
}
diff --git a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
index d2774877d11e3..5062b4f231fbb 100644
--- a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
@@ -675,8 +675,10 @@ mlir::LogicalResult CIRDeleteArrayOpABILowering::matchAndRewrite(
if (cookieRequired) {
ptrTy = mlir::cast<cir::PointerType>(loweredAddress.getType());
- cxxABI.readArrayCookie(loc, loweredAddress, dl, cirBuilder, numElements,
- deletePtr, cookieSize);
+ clang::CharUnits elementAlign =
+ clang::CharUnits::fromQuantity(op.getElementAlign());
+ cxxABI.readArrayCookie(loc, loweredAddress, elementAlign, dl, cirBuilder,
+ numElements, deletePtr, cookieSize);
} else {
deletePtr = cir::CastOp::create(rewriter, loc, cirBuilder.getVoidPtrTy(),
cir::CastKind::bitcast, loweredAddress);
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.cpp
index 6046f3f126d98..df8ab49c067ec 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.cpp
@@ -23,6 +23,7 @@ unsigned CIRCXXABI::getPtrSizeInBits() const {
}
void CIRCXXABI::readArrayCookie(mlir::Location loc, mlir::Value elementPtr,
+ clang::CharUnits elementAlign,
const mlir::DataLayout &dataLayout,
CIRBaseBuilderTy &builder,
mlir::Value &numElements, mlir::Value &allocPtr,
@@ -31,8 +32,7 @@ void CIRCXXABI::readArrayCookie(mlir::Location loc, mlir::Value elementPtr,
auto ptrDiffTy = builder.getSIntNTy(getPtrSizeInBits());
auto voidPtrTy = builder.getVoidPtrTy();
- auto ptrTy = mlir::cast<cir::PointerType>(elementPtr.getType());
- cookieSize = getArrayCookieSizeImpl(ptrTy.getPointee(), dataLayout);
+ cookieSize = getArrayCookieSizeImpl(elementAlign);
mlir::Value bytePtr = cir::CastOp::create(builder, loc, u8PtrTy,
cir::CastKind::bitcast, elementPtr);
@@ -45,13 +45,11 @@ void CIRCXXABI::readArrayCookie(mlir::Location loc, mlir::Value elementPtr,
allocPtr = cir::CastOp::create(builder, loc, voidPtrTy,
cir::CastKind::bitcast, allocBytePtr);
- // cookieSize is always a multiple of the element ABI alignment (both are
+ // cookieSize is always a multiple of the element alignment (both are
// powers of 2 and cookieSize >= elementAlign), so subtracting it preserves
// alignment. The cookie alignment therefore equals the element alignment.
- clang::CharUnits cookieAlignment = clang::CharUnits::fromQuantity(
- dataLayout.getTypePreferredAlignment(ptrTy.getPointee()));
- numElements = readArrayCookieImpl(loc, allocBytePtr, cookieSize,
- cookieAlignment, dataLayout, builder);
+ numElements = readArrayCookieImpl(loc, allocBytePtr, cookieSize, elementAlign,
+ dataLayout, builder);
}
} // namespace cir
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.h b/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.h
index 1f65c871d8315..1a2b5bb119cb7 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.h
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.h
@@ -139,11 +139,12 @@ class CIRCXXABI {
mlir::OpBuilder &builder) const = 0;
/// Read the array cookie for a dynamically-allocated array whose first
- /// element is at \p elementPtr. Returns the number of elements, the
- /// original allocation pointer (before the cookie) as a void*, and the
- /// cookie size in bytes. Delegates to getArrayCookieSizeImpl and
- /// readArrayCookieImpl.
+ /// element is at \p elementPtr. \p elementAlign is the element type's
+ /// preferred alignment in bytes. Returns the number of elements, the original
+ /// allocation pointer (before the cookie) as a void*, and the cookie size in
+ /// bytes. Delegates to getArrayCookieSizeImpl and readArrayCookieImpl.
void readArrayCookie(mlir::Location loc, mlir::Value elementPtr,
+ clang::CharUnits elementAlign,
const mlir::DataLayout &dataLayout,
CIRBaseBuilderTy &builder, mlir::Value &numElements,
mlir::Value &allocPtr,
@@ -151,10 +152,10 @@ class CIRCXXABI {
protected:
/// Returns the cookie size in bytes for a dynamically-allocated array of
- /// elements with the given type. Only called when a cookie is required.
+ /// elements with the given preferred alignment. Only called when a cookie
+ /// is required.
virtual clang::CharUnits
- getArrayCookieSizeImpl(mlir::Type elementType,
- const mlir::DataLayout &dataLayout) const = 0;
+ getArrayCookieSizeImpl(clang::CharUnits elementAlign) const = 0;
/// Reads the element count from an array cookie. \p allocPtr is a byte
/// pointer to the start of the allocation (the beginning of the cookie).
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp
index fdfbea028926a..26dbe40c2c93f 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp
@@ -117,8 +117,7 @@ class LowerItaniumCXXABI : public CIRCXXABI {
mlir::OpBuilder &builder) const override;
clang::CharUnits
- getArrayCookieSizeImpl(mlir::Type elementType,
- const mlir::DataLayout &dataLayout) const override;
+ getArrayCookieSizeImpl(clang::CharUnits elementAlign) const override;
mlir::Value readArrayCookieImpl(mlir::Location loc, mlir::Value allocPtr,
clang::CharUnits cookieSize,
@@ -889,14 +888,12 @@ LowerItaniumCXXABI::lowerVTableGetTypeInfo(cir::VTableGetTypeInfoOp op,
}
clang::CharUnits LowerItaniumCXXABI::getArrayCookieSizeImpl(
- mlir::Type elementType, const mlir::DataLayout &dataLayout) const {
+ clang::CharUnits elementAlign) const {
// The array cookie is a size_t; pad that up to the element alignment.
// The cookie is actually right-justified in that space.
clang::CharUnits sizeOfSizeT =
clang::CharUnits::fromQuantity(getPtrSizeInBits() / 8);
- clang::CharUnits eltAlign = clang::CharUnits::fromQuantity(
- dataLayout.getTypePreferredAlignment(elementType));
- return std::max(sizeOfSizeT, eltAlign);
+ return std::max(sizeOfSizeT, elementAlign);
}
mlir::Value LowerItaniumCXXABI::readArrayCookieImpl(
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerMicrosoftCXXABI.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerMicrosoftCXXABI.cpp
index f670981453bed..1cd7306d74dba 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerMicrosoftCXXABI.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerMicrosoftCXXABI.cpp
@@ -135,8 +135,7 @@ class LowerMicrosoftCXXABI : public CIRCXXABI {
}
clang::CharUnits
- getArrayCookieSizeImpl(mlir::Type elementType,
- const mlir::DataLayout &dataLayout) const override {
+ getArrayCookieSizeImpl(clang::CharUnits elementAlign) const override {
llvm_unreachable("Microsoft ABI array cookie lowering NYI");
}
diff --git a/clang/test/CIR/CodeGen/delete-array-aligned.cpp b/clang/test/CIR/CodeGen/delete-array-aligned.cpp
index 41372cb1c1be8..a02476de7da04 100644
--- a/clang/test/CIR/CodeGen/delete-array-aligned.cpp
+++ b/clang/test/CIR/CodeGen/delete-array-aligned.cpp
@@ -15,7 +15,7 @@ struct alignas(128) OverAlignedTy {
};
void test_global_aligned(OverAlignedTy *p) { delete[] p; }
// CIR-LABEL: cir.func no_inline dso_local @_Z19test_global_alignedP13OverAlignedTy(
-// CIR-BEFORE: cir.delete_array %{{.*}} : !cir.ptr<!rec_OverAlignedTy> {delete_fn = @_ZdaPvSt11align_val_t, delete_params = #cir.usual_delete_params<alignment = 128>}
+// CIR-BEFORE: cir.delete_array %{{.*}} : !cir.ptr<!rec_OverAlignedTy> {delete_fn = @_ZdaPvSt11align_val_t, delete_params = #cir.usual_delete_params<alignment = 128>, element_align = 128 : i64}
// CIR-AFTER: %[[PTR:.*]] = cir.cast bitcast %{{.*}} : !cir.ptr<!rec_OverAlignedTy> -> !cir.ptr<!void>
// CIR-AFTER-NEXT: cir.cleanup.scope {
@@ -36,7 +36,7 @@ struct alignas(128) OverAlignedTyClassDelete {
};
void test_class_align_only(OverAlignedTyClassDelete *p) { delete[] p; }
// CIR-LABEL: cir.func no_inline dso_local @_Z21test_class_align_onlyP24OverAlignedTyClassDelete(
-// CIR-BEFORE: cir.delete_array %{{.*}} : !cir.ptr<!rec_OverAlignedTyClassDelete> {delete_fn = @_ZN24OverAlignedTyClassDeletedaEPvSt11align_val_t, delete_params = #cir.usual_delete_params<alignment = 128>}
+// CIR-BEFORE: cir.delete_array %{{.*}} : !cir.ptr<!rec_OverAlignedTyClassDelete> {delete_fn = @_ZN24OverAlignedTyClassDeletedaEPvSt11align_val_t, delete_params = #cir.usual_delete_params<alignment = 128>, element_align = 128 : i64}
// CIR-AFTER: %[[PTR:.*]] = cir.cast bitcast %{{.*}} : !cir.ptr<!rec_OverAlignedTyClassDelete> -> !cir.ptr<!void>
// CIR-AFTER-NEXT: cir.cleanup.scope {
// CIR-AFTER-NEXT: cir.yield
@@ -56,7 +56,7 @@ struct alignas(128) OverAlignedTyClassDeleteCookie {
};
void test_class_size_align(OverAlignedTyClassDeleteCookie *p) { delete[] p; }
// CIR-LABEL: cir.func no_inline dso_local @_Z21test_class_size_alignP30OverAlignedTyClassDeleteCookie(
-// CIR-BEFORE: cir.delete_array %{{.*}} : !cir.ptr<!rec_OverAlignedTyClassDeleteCookie> {delete_fn = @_ZN30OverAlignedTyClassDeleteCookiedaEPvmSt11align_val_t, delete_params = #cir.usual_delete_params<size = true, alignment = 128>}
+// CIR-BEFORE: cir.delete_array %{{.*}} : !cir.ptr<!rec_OverAlignedTyClassDeleteCookie> {delete_fn = @_ZN30OverAlignedTyClassDeleteCookiedaEPvmSt11align_val_t, delete_params = #cir.usual_delete_params<size = true, alignment = 128>, element_align = 128 : i64}
// CIR-AFTER: %[[ORIG_PTR:.*]] = cir.cast bitcast %{{.*}} : !cir.ptr<!rec_OverAlignedTyClassDeleteCookie> -> !cir.ptr<!u8i>
// CIR-AFTER: %[[COOKIE_STRIDE:.*]] = cir.ptr_stride %[[ORIG_PTR]], %{{.*}} : (!cir.ptr<!u8i>, !s64i) -> !cir.ptr<!u8i>
// CIR-AFTER-NEXT: %[[PTR:.*]] = cir.cast bitcast %[[COOKIE_STRIDE]] : !cir.ptr<!u8i> -> !cir.ptr<!void>
@@ -80,7 +80,7 @@ struct alignas(128) OverAlignedTyClassDeleteDtor {
};
void test_class_align_only_dtor(OverAlignedTyClassDeleteDtor *p) { delete[] p; }
// CIR-LABEL: cir.func no_inline dso_local @_Z26test_class_align_only_dtorP28OverAlignedTyClassDeleteDtor(
-// CIR-BEFORE: cir.delete_array %{{.*}} : !cir.ptr<!rec_OverAlignedTyClassDeleteDtor> {delete_fn = @_ZN28OverAlignedTyClassDeleteDtordaEPvSt11align_val_t, delete_params = #cir.usual_delete_params<alignment = 128>, element_dtor = @_ZN28OverAlignedTyClassDeleteDtorD1Ev}
+// CIR-BEFORE: cir.delete_array %{{.*}} : !cir.ptr<!rec_OverAlignedTyClassDeleteDtor> {delete_fn = @_ZN28OverAlignedTyClassDeleteDtordaEPvSt11align_val_t, delete_params = #cir.usual_delete_params<alignment = 128>, element_align = 128 : i64, element_dtor = @_ZN28OverAlignedTyClassDeleteDtorD1Ev}
// CIR-AFTER: %[[ORIG_PTR:.*]] = cir.cast bitcast %{{.*}} : !cir.ptr<!rec_OverAlignedTyClassDeleteDtor> -> !cir.ptr<!u8i>
// CIR-AFTER: %[[COOKIE_STRIDE:.*]] = cir.ptr_stride %[[ORIG_PTR]], %{{.*}} : (!cir.ptr<!u8i>, !s64i) -> !cir.ptr<!u8i>
// CIR-AFTER-NEXT: %[[PTR:.*]] = cir.cast bitcast %[[COOKIE_STRIDE]] : !cir.ptr<!u8i> -> !cir.ptr<!void>
@@ -114,7 +114,7 @@ void test_class_size_align_dtor(OverAlignedTyClassDeleteCookieDtor *p) {
delete[] p;
}
// CIR-LABEL: cir.func no_inline dso_local @_Z26test_class_size_align_dtorP34OverAlignedTyClassDeleteCookieDtor(
-// CIR-BEFORE: cir.delete_array %{{.*}} : !cir.ptr<!rec_OverAlignedTyClassDeleteCookieDtor> {delete_fn = @_ZN34OverAlignedTyClassDeleteCookieDtordaEPvmSt11align_val_t, delete_params = #cir.usual_delete_params<size = true, alignment = 128>, element_dtor = @_ZN34OverAlignedTyClassDeleteCookieDtorD1Ev}
+// CIR-BEFORE: cir.delete_array %{{.*}} : !cir.ptr<!rec_OverAlignedTyClassDeleteCookieDtor> {delete_fn = @_ZN34OverAlignedTyClassDeleteCookieDtordaEPvmSt11align_val_t, delete_params = #cir.usual_delete_params<size = true, alignment = 128>, element_align = 128 : i64, element_dtor = @_ZN34OverAlignedTyClassDeleteCookieDtorD1Ev}
// CIR-AFTER: %[[ORIG_PTR:.*]] = cir.cast bitcast %{{.*}} : !cir.ptr<!rec_OverAlignedTyClassDeleteCookieDtor> -> !cir.ptr<!u8i>
// CIR-AFTER: %[[COOKIE_STRIDE:.*]] = cir.ptr_stride %[[ORIG_PTR]], %{{.*}} : (!cir.ptr<!u8i>, !s64i) -> !cir.ptr<!u8i>
// CIR-AFTER-NEXT: %[[PTR:.*]] = cir.cast bitcast %[[COOKIE_STRIDE]] : !cir.ptr<!u8i> -> !cir.ptr<!void>
diff --git a/clang/test/CIR/CodeGen/delete-array-overaligned-cookie.cpp b/clang/test/CIR/CodeGen/delete-array-overaligned-cookie.cpp
new file mode 100644
index 0000000000000..e9c4a329ac5a1
--- /dev/null
+++ b/clang/test/CIR/CodeGen/delete-array-overaligned-cookie.cpp
@@ -0,0 +1,87 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++17 -fclangir -mconstructor-aliases -emit-cir -mmlir -mlir-print-ir-before=cir-cxxabi-lowering %s -o %t.cir 2> %t-before.cir
+// RUN: FileCheck --input-file=%t-before.cir -check-prefix=CIR,CIR-BEFORE %s
+// RUN: FileCheck --input-file=%t.cir --check-prefix=CIR,CIR-AFTER %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++17 -fclangir -mconstructor-aliases -emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --input-file=%t-cir.ll --check-prefix=LLVM %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++17 -mconstructor-aliases -emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll --check-prefix=LLVM %s
+
+typedef decltype(sizeof(0)) size_t;
+namespace std { enum class align_val_t : size_t {}; }
+
+struct alignas(64) OverAligned {
+ int *p;
+ OverAligned() : p(nullptr) {}
+ ~OverAligned();
+};
+
+void test_delete_array(OverAligned *a) {
+ delete[] a;
+}
+// CIR-LABEL: cir.func {{.*}}@_Z17test_delete_arrayP11OverAligned(
+// CIR-BEFORE: cir.delete_array %{{.*}} : !cir.ptr<!rec_OverAligned> {delete_fn = @_ZdaPvmSt11align_val_t, delete_params = #cir.usual_delete_params<size = true, alignment = 64>, element_align = 64 : i64, element_dtor = @_ZN11OverAlignedD1Ev}
+
+// CIR-AFTER: %[[A:.*]] = cir.alloca "a" align(8) init : !cir.ptr<!cir.ptr<!rec_OverAligned>>
+// CIR-AFTER: %[[LOAD_A:.*]] = cir.load align(8) %[[A]] : !cir.ptr<!cir.ptr<!rec_OverAligned>>, !cir.ptr<!rec_OverAligned>
+// CIR-AFTER: %[[CAST_TO_BYTES:.*]] = cir.cast bitcast %[[LOAD_A]] : !cir.ptr<!rec_OverAligned> -> !cir.ptr<!u8i>
+// CIR-AFTER: %[[COOKIE_OFFSET:.*]] = cir.const #cir.int<-64> : !s64i
+// CIR-AFTER: %[[BEFORE_COOKIE:.*]] = cir.ptr_stride %[[CAST_TO_BYTES]], %[[COOKIE_OFFSET]] : (!cir.ptr<!u8i>, !s64i) -> !cir.ptr<!u8i>
+// CIR-AFTER: %[[COUNT_OFFSET:.*]] = cir.const #cir.int<56> : !s64i
+// CIR-AFTER: %[[AFTER_COUNT:.*]] = cir.ptr_stride %[[BEFORE_COOKIE]], %[[COUNT_OFFSET]] : (!cir.ptr<!u8i>, !s64i) -> !cir.ptr<!u8i>
+// CIR-AFTER: %[[TO_SIZE:.*]] = cir.cast bitcast %[[AFTER_COUNT]] : !cir.ptr<!u8i> -> !cir.ptr<!u64i>
+// CIR-AFTER: %[[LOAD_VAL:.*]] = cir.load align(8) %[[TO_SIZE]] : !cir.ptr<!u64i>, !u64i
+// CIR-AFTER: } cleanup normal {
+// CIR-AFTER: %[[ELT_SIZE:.*]] = cir.const #cir.int<64> : !u64i
+// CIR-AFTER: %[[ELT_OFFSET:.*]] = cir.mul %[[ELT_SIZE]], %[[LOAD_VAL]] : !u64i
+// CIR-AFTER: %[[COOKIE_SIZE:.*]] = cir.const #cir.int<64> : !u64i
+// CIR-AFTER: %[[TOTAL_SIZE:.*]] = cir.add %[[ELT_OFFSET]], %[[COOKIE_SIZE]] : !u64i
+// CIR-AFTER: %[[ALIGN:.*]] = cir.const #cir.int<64> : !u64i
+// CIR-AFTER: cir.call @_ZdaPvmSt11align_val_t(%{{.*}}, %[[TOTAL_SIZE]], %[[ALIGN]]) nothrow : (!cir.ptr<!void>, !u64i, !u64i) -> ()
+
+// LLVM-LABEL: define {{.*}}@_Z17test_delete_arrayP11OverAligned(
+// LLVM: %[[A:.*]] = alloca ptr, align 8
+// LLVM: %[[LOAD_A:.*]] = load ptr, ptr %[[A]], align 8
+// LLVM: %[[BEFORE_COOKIE:.*]] = getelementptr {{.*}}i8, ptr %[[LOAD_A]], i64 -64
+// LLVM: %[[AFTER_COUNT:.*]] = getelementptr {{.*}}i8, ptr %[[BEFORE_COOKIE]], i64 56
+// LLVM: %[[LOAD_VAL:.*]] = load i64, ptr %[[AFTER_COUNT]], align 8
+// LLVM: %[[ELT_OFFSET:.*]] = mul i64 64, %[[LOAD_VAL]]
+// LLVM: %[[TOTAL_SIZE:.*]] = add i64 %[[ELT_OFFSET]], 64
+// LLVM: call void @_ZdaPvmSt11align_val_t(ptr {{.*}}%{{.*}}, i64 {{.*}}%[[TOTAL_SIZE]], i64 {{.*}}64)
+
+
+struct alignas(16) NotAlignedNewButNeedCookie {
+ float x, y, z, a;
+ ~NotAlignedNewButNeedCookie();
+};
+
+void test_not_aligned_new_but_need_cookie(NotAlignedNewButNeedCookie *a) {
+ delete [] a;
+}
+// CIR-LABEL: cir.func {{.*}}@_Z36test_not_aligned_new_but_need_cookieP26NotAlignedNewButNeedCookie(
+// CIR-BEFORE: cir.delete_array %{{.*}} : !cir.ptr<!rec_NotAlignedNewButNeedCookie> {delete_fn = @_ZdaPvm, delete_params = #cir.usual_delete_params<size = true>, element_align = 16 : i64, element_dtor = @_ZN26NotAlignedNewButNeedCookieD1Ev}
+// CIR-AFTER: %[[A:.*]] = cir.alloca "a" align(8) init : !cir.ptr<!cir.ptr<!rec_NotAlignedNewButNeedCookie>>
+
+// CIR-AFTER: %[[LOAD_A:.*]] = cir.load align(8) %[[A]] : !cir.ptr<!cir.ptr<!rec_NotAlignedNewButNeedCookie>>, !cir.ptr<!rec_NotAlignedNewButNeedCookie>
+// CIR-AFTER: %[[CAST_TO_BYTES:.*]] = cir.cast bitcast %[[LOAD_A]] : !cir.ptr<!rec_NotAlignedNewButNeedCookie> -> !cir.ptr<!u8i>
+// CIR-AFTER: %[[COOKIE_OFFSET:.*]] = cir.const #cir.int<-16> : !s64i
+// CIR-AFTER: %[[BEFORE_COOKIE:.*]] = cir.ptr_stride %[[CAST_TO_BYTES]], %[[COOKIE_OFFSET]] : (!cir.ptr<!u8i>, !s64i) -> !cir.ptr<!u8i>
+// CIR-AFTER: %[[COUNT_OFFSET:.*]] = cir.const #cir.int<8> : !s64i
+// CIR-AFTER: %[[AFTER_COUNT:.*]] = cir.ptr_stride %[[BEFORE_COOKIE]], %[[COUNT_OFFSET]] : (!cir.ptr<!u8i>, !s64i) -> !cir.ptr<!u8i>
+// CIR-AFTER: %[[TO_SIZE:.*]] = cir.cast bitcast %[[AFTER_COUNT]] : !cir.ptr<!u8i> -> !cir.ptr<!u64i>
+// CIR-AFTER: %[[LOAD_VAL:.*]] = cir.load align(8) %[[TO_SIZE]] : !cir.ptr<!u64i>, !u64i
+// CIR-AFTER: } cleanup normal {
+// CIR-AFTER: %[[ELT_SIZE:.*]] = cir.const #cir.int<16> : !u64i
+// CIR-AFTER: %[[ELT_OFFSET:.*]] = cir.mul %[[ELT_SIZE]], %[[LOAD_VAL]] : !u64i
+// CIR-AFTER: %[[COOKIE_SIZE:.*]] = cir.const #cir.int<16> : !u64i
+// CIR-AFTER: %[[TOTAL_SIZE:.*]] = cir.add %[[ELT_OFFSET]], %[[COOKIE_SIZE]] : !u64i
+// CIR-AFTER: cir.call @_ZdaPvm(%{{.*}}, %[[TOTAL_SIZE]]) nothrow : (!cir.ptr<!void>, !u64i) -> ()
+
+// LLVM-LABEL: define {{.*}}@_Z36test_not_aligned_new_but_need_cookieP26NotAlignedNewButNeedCookie(
+// LLVM: %[[A:.*]] = alloca ptr, align 8
+// LLVM: %[[LOAD_A:.*]] = load ptr, ptr %[[A]], align 8
+// LLVM: %[[BEFORE_COOKIE:.*]] = getelementptr {{.*}}i8, ptr %[[LOAD_A]], i64 -16
+// LLVM: %[[AFTER_COUNT:.*]] = getelementptr {{.*}}i8, ptr %[[BEFORE_COOKIE]], i64 8
+// LLVM: %[[LOAD_VAL:.*]] = load i64, ptr %[[AFTER_COUNT]], align 8
+// LLVM: %[[ELT_OFFEST:.*]] = mul i64 16, %[[LOAD_VAL]]
+// LLVM: %[[TOTAL_SIZE:.*]] = add i64 %[[ELT_OFFSET]], 16
+// LLVM: call void @_ZdaPvm(ptr {{.*}}%{{.*}}, i64 {{.*}}%[[TOTAL_SIZE]])
diff --git a/clang/test/CIR/CodeGen/delete-array-throwing-dtor.cpp b/clang/test/CIR/CodeGen/delete-array-throwing-dtor.cpp
index 090617bd34375..d5a63bc65edc8 100644
--- a/clang/test/CIR/CodeGen/delete-array-throwing-dtor.cpp
+++ b/clang/test/CIR/CodeGen/delete-array-throwing-dtor.cpp
@@ -23,7 +23,7 @@ void test_delete_array_throwing_dtor(ThrowingDtor *ptr) {
// CIR-BEFORE-CXXABI: %[[NULL:.*]] = cir.const #cir.ptr<null>
// CIR-BEFORE-CXXABI: %[[NOT_NULL:.*]] = cir.cmp ne %[[PTR]], %[[NULL]]
// CIR-BEFORE-CXXABI: cir.if %[[NOT_NULL]] {
-// CIR-BEFORE-CXXABI: cir.delete_array %[[PTR]] : !cir.ptr<!rec_ThrowingDtor> dtor_may_throw {delete_fn = @_ZdaPvm, delete_params = #cir.usual_delete_params<size = true>, element_dtor = @_ZN12ThrowingDtorD1Ev}
+// CIR-BEFORE-CXXABI: cir.delete_array %[[PTR]] : !cir.ptr<!rec_ThrowingDtor> dtor_may_throw {delete_fn = @_ZdaPvm, delete_params = #cir.usual_delete_params<size = true>, element_align = 4 : i64, element_dtor = @_ZN12ThrowingDtorD1Ev}
// CIR-BEFORE-CXXABI: }
// CIR-AFTER-CXXABI: IR Dump After CXXABILowering: cir-cxxabi-lowering
diff --git a/clang/test/CIR/IR/invalid-delete-array.cir b/clang/test/CIR/IR/invalid-delete-array.cir
index 7d6ce8be0951f..a9ac7c6355459 100644
--- a/clang/test/CIR/IR/invalid-delete-array.cir
+++ b/clang/test/CIR/IR/invalid-delete-array.cir
@@ -9,7 +9,13 @@ module {
cir.func @bad_delete_array_throw_without_dtor(%p: !cir.ptr<!rec_S>) {
// expected-error at +1 {{'cir.delete_array' op 'dtor_may_throw' requires an 'element_dtor' to be present}}
- cir.delete_array %p : !cir.ptr<!rec_S> dtor_may_throw {delete_fn = @_ZdaPvm, delete_params = #cir.usual_delete_params<size = true>}
+ cir.delete_array %p : !cir.ptr<!rec_S> dtor_may_throw {delete_fn = @_ZdaPvm, element_align = 1, delete_params = #cir.usual_delete_params<size = true>}
+ cir.return
+ }
+
+ cir.func @bad_delete_array_throw_without_align(%p: !cir.ptr<!rec_S>) {
+ // expected-error at +1 {{'cir.delete_array' op requires attribute 'element_align'}}
+ cir.delete_array %p : !cir.ptr<!rec_S> dtor_may_throw {delete_fn = @_ZdaPvm, dtor_may_throw = true, delete_params = #cir.usual_delete_params<size = true>}
cir.return
}
}
More information about the cfe-commits
mailing list