From 5f47b8342827648b7108d2f3b77b45bd675b7c0a Mon Sep 17 00:00:00 2001 From: Chuanqi Xu Date: Wed, 27 Nov 2024 15:51:55 +0800 Subject: [PATCH] [CIR][CodeGen] Introduce cir.delete.array op --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 15 +++++++++++++++ clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp | 7 +++++-- .../CIR/Dialect/Transforms/LoweringPrepare.cpp | 18 ++++++++++++++++-- .../Dialect/Transforms/LoweringPrepareCXXABI.h | 4 ++++ .../Transforms/LoweringPrepareItaniumCXXABI.h | 12 ++++++++++++ .../TargetLowering/ItaniumCXXABI.cpp | 3 +++ clang/test/CIR/CodeGen/delete-array.cpp | 8 ++++++++ 7 files changed, 63 insertions(+), 4 deletions(-) create mode 100644 clang/test/CIR/CodeGen/delete-array.cpp diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 9c7e2b14ac5a..3ba4a4b5a8a2 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -3497,6 +3497,21 @@ def LLVMIntrinsicCallOp : CIR_Op<"llvm.intrinsic"> { } +//===----------------------------------------------------------------------===// +// DeleteArrayOp +//===----------------------------------------------------------------------===// + +def DeleteArrayOp : CIR_Op<"delete.array">, + Arguments<(ins CIR_PointerType:$address)> { + let summary = "Delete address representing an array"; + let description = [{ + `cir.delete.array` operation deletes an array. For example, `delete[] ptr;` + will be translated to `cir.delete.array %ptr`. + }]; + let assemblyFormat = "$address `:` type($address) attr-dict"; + let hasVerifier = 0; +} + //===----------------------------------------------------------------------===// // CallOp and TryCallOp //===----------------------------------------------------------------------===// diff --git a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp index e336594388ae..38f343512c83 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp @@ -901,17 +901,20 @@ void CIRGenFunction::emitCXXDeleteExpr(const CXXDeleteExpr *E) { return; } + // In CodeGen: // We might be deleting a pointer to array. If so, GEP down to the // first non-array element. // (this assumes that A(*)[3][7] is converted to [3 x [7 x %A]]*) + // In CIRGen: we handle this differently because .... .. .. . . if (DeleteTy->isConstantArrayType()) { - llvm_unreachable("NYI"); + Ptr = Ptr; } assert(convertTypeForMem(DeleteTy) == Ptr.getElementType()); if (E->isArrayForm()) { - llvm_unreachable("NYI"); + builder.create(Ptr.getPointer().getLoc(), + Ptr.getPointer()); } else { (void)EmitObjectDelete(*this, E, Ptr, DeleteTy); } diff --git a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp index b0709e9638ff..002c5253cd2e 100644 --- a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp +++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp @@ -77,6 +77,7 @@ struct LoweringPreparePass : public LoweringPrepareBase { void lowerComplexBinOp(ComplexBinOp op); void lowerThreeWayCmpOp(CmpThreeWayOp op); void lowerVAArgOp(VAArgOp op); + void lowerDeleteArrayOp(DeleteArrayOp op); void lowerGlobalOp(GlobalOp op); void lowerDynamicCastOp(DynamicCastOp op); void lowerStdFindOp(StdFindOp op); @@ -157,6 +158,8 @@ struct LoweringPreparePass : public LoweringPrepareBase { /// Tracks current module. ModuleOp theModule; + std::optional datalayout; + /// Tracks existing dynamic initializers. llvm::StringMap dynamicInitializerNames; llvm::SmallVector dynamicInitializers; @@ -344,9 +347,8 @@ static void canonicalizeIntrinsicThreeWayCmp(CIRBaseBuilderTy &builder, void LoweringPreparePass::lowerVAArgOp(VAArgOp op) { CIRBaseBuilderTy builder(getContext()); builder.setInsertionPoint(op); - cir::CIRDataLayout datalayout(theModule); - auto res = cxxABI->lowerVAArg(builder, op, datalayout); + auto res = cxxABI->lowerVAArg(builder, op, *datalayout); if (res) { op.replaceAllUsesWith(res); op.erase(); @@ -354,6 +356,17 @@ void LoweringPreparePass::lowerVAArgOp(VAArgOp op) { return; } +void LoweringPreparePass::lowerDeleteArrayOp(DeleteArrayOp op) { + CIRBaseBuilderTy builder(getContext()); + builder.setInsertionPoint(op); + + cxxABI->lowerDeleteArray(builder, op, *datalayout); + // DeleteArrayOp won't have a result, so we don't need to replace + // the uses. + op.erase(); + return; +} + void LoweringPreparePass::lowerUnaryOp(UnaryOp op) { auto ty = op.getType(); if (!mlir::isa(ty)) @@ -1188,6 +1201,7 @@ void LoweringPreparePass::runOnOperation() { auto *op = getOperation(); if (isa<::mlir::ModuleOp>(op)) { theModule = cast<::mlir::ModuleOp>(op); + datalayout.emplace(theModule); } llvm::SmallVector opsToTransform; diff --git a/clang/lib/CIR/Dialect/Transforms/LoweringPrepareCXXABI.h b/clang/lib/CIR/Dialect/Transforms/LoweringPrepareCXXABI.h index f3ae48c13574..9824797a31ef 100644 --- a/clang/lib/CIR/Dialect/Transforms/LoweringPrepareCXXABI.h +++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepareCXXABI.h @@ -32,6 +32,10 @@ class LoweringPrepareCXXABI { virtual mlir::Value lowerVAArg(CIRBaseBuilderTy &builder, cir::VAArgOp op, const cir::CIRDataLayout &datalayout) = 0; + + virtual mlir::Value + lowerDeleteArray(cir::CIRBaseBuilderTy &builder, cir::DeleteArrayOp op, + const cir::CIRDataLayout &datalayout) = 0; virtual ~LoweringPrepareCXXABI() {} virtual mlir::Value lowerDynamicCast(CIRBaseBuilderTy &builder, diff --git a/clang/lib/CIR/Dialect/Transforms/LoweringPrepareItaniumCXXABI.h b/clang/lib/CIR/Dialect/Transforms/LoweringPrepareItaniumCXXABI.h index 58b2a5e3915d..4436eb2b851d 100644 --- a/clang/lib/CIR/Dialect/Transforms/LoweringPrepareItaniumCXXABI.h +++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepareItaniumCXXABI.h @@ -21,4 +21,16 @@ class LoweringPrepareItaniumCXXABI : public cir::LoweringPrepareCXXABI { cir::DynamicCastOp op) override; mlir::Value lowerVAArg(cir::CIRBaseBuilderTy &builder, cir::VAArgOp op, const cir::CIRDataLayout &datalayout) override; + + mlir::Value lowerDeleteArray(cir::CIRBaseBuilderTy &builder, + cir::DeleteArrayOp op, + const cir::CIRDataLayout &datalayout) override { + // Note: look at `CIRGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *)` + // in CIRGenExprCXX.cpp. + // In traditional code gen, we need handle ABI related array cookie to + // generate codes to handle the expression to delete array. We need similar + // mechanism here for ItaniumCXXABI. + llvm_unreachable("NYI && Delete Array is not supported to be lowered in " + "Itanium CXX ABI"); + } }; diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/ItaniumCXXABI.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/ItaniumCXXABI.cpp index a87cdc01ea9d..10e8b79cc22d 100644 --- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/ItaniumCXXABI.cpp +++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/ItaniumCXXABI.cpp @@ -164,4 +164,7 @@ class LoweringPrepareItaniumCXXABI : public cir::LoweringPrepareCXXABI { cir::DynamicCastOp op) override; mlir::Value lowerVAArg(cir::CIRBaseBuilderTy &builder, cir::VAArgOp op, const cir::CIRDataLayout &datalayout) override; + mlir::Value lowerDeleteArray(cir::CIRBaseBuilderTy &builder, + cir::DeleteArrayOp op, + const cir::CIRDataLayout &datalayout) override; }; diff --git a/clang/test/CIR/CodeGen/delete-array.cpp b/clang/test/CIR/CodeGen/delete-array.cpp new file mode 100644 index 000000000000..b76d0551f378 --- /dev/null +++ b/clang/test/CIR/CodeGen/delete-array.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --input-file=%t.cir %s + +void test_delete_array(int *ptr) { + delete[] ptr; +} + +// CHECK: cir.delete.array