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@+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@+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 } } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
