Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -729,6 +729,15 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
return Address(derivedAddr, destType, addr.getAlignment());
}

Address createInBoundsGEP(Address Addr, ArrayRef<llvm::Value *> IdxList,
llvm::Type *ElementType, CharUnits Align,
const Twine &Name = "") {
return RawAddress(CreateInBoundsGEP(Addr.getElementType(),
emitRawPointerFromAddress(Addr),
IdxList, Name),
ElementType, Align, Addr.isKnownNonNull());
}

mlir::Value createVTTAddrPoint(mlir::Location loc, mlir::Type retTy,
mlir::Value addr, uint64_t offset) {
return cir::VTTAddrPointOp::create(*this, loc, retTy,
Expand Down
65 changes: 65 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1280,6 +1280,70 @@ static bool EmitObjectDelete(CIRGenFunction &CGF, const CXXDeleteExpr *DE,
return false;
}

namespace {
/// Calls the given 'operator delete' on an array of objects.
struct CallArrayDelete final : EHScopeStack::Cleanup {
mlir::Value Ptr;
const FunctionDecl *OperatorDelete;
mlir::Value NumElements;
QualType ElementType;
CharUnits CookieSize;

CallArrayDelete(mlir::Value Ptr, const FunctionDecl *OperatorDelete,
mlir::Value NumElements, QualType ElementType,
CharUnits CookieSize)
: Ptr(Ptr), OperatorDelete(OperatorDelete), NumElements(NumElements),
ElementType(ElementType), CookieSize(CookieSize) {}

void Emit(CIRGenFunction &CGF, Flags flags) override {
CGF.emitDeleteCall(OperatorDelete, Ptr, ElementType, NumElements,
CookieSize);
}
};
} // namespace

/// Emit the code for deleting an array of objects.
static void EmitArrayDelete(CIRGenFunction &CGF, const CXXDeleteExpr *E,
Address deletedPtr, QualType elementType) {
llvm::Value *numElements = nullptr;
llvm::Value *allocatedPtr = nullptr;
CharUnits cookieSize;
CGF.CGM.getCXXABI().ReadArrayCookie(CGF, deletedPtr, E, elementType,
numElements, allocatedPtr, cookieSize);

assert(allocatedPtr && "ReadArrayCookie didn't set allocated pointer");

// Make sure that we call delete even if one of the dtors throws.
const FunctionDecl *operatorDelete = E->getOperatorDelete();
CGF.EHStack.pushCleanup<CallArrayDelete>(NormalAndEHCleanup, allocatedPtr,
operatorDelete, numElements,
elementType, cookieSize);

// Destroy the elements.
if (QualType::DestructionKind dtorKind = elementType.isDestructedType()) {
assert(numElements && "no element count for a type with a destructor!");

CharUnits elementSize = CGF.getContext().getTypeSizeInChars(elementType);
CharUnits elementAlign =
deletedPtr.getAlignment().alignmentOfArrayElement(elementSize);

mlir::Value arrayBegin = deletedPtr.emitRawPointer();
mlir::Value arrayEnd = CGF.Builder.createInBoundsGEP(
deletedPtr.getElementType(), arrayBegin, numElements, "delete.end");

// Note that it is legal to allocate a zero-length array, and we
// can never fold the check away because the length should always
// come from a cookie.
CGF.emitArrayDestroy(arrayBegin, arrayEnd, elementType, elementAlign,
CGF.getDestroyer(dtorKind),
/*checkZeroLength*/ true,
CGF.needsEHCleanup(dtorKind));
}

// Pop the cleanup block.
CGF.PopCleanupBlock();
}

void CIRGenFunction::emitCXXDeleteExpr(const CXXDeleteExpr *E) {
const Expr *Arg = E->getArgument();
Address Ptr = emitPointerWithAlignment(Arg);
Expand Down Expand Up @@ -1319,6 +1383,7 @@ void CIRGenFunction::emitCXXDeleteExpr(const CXXDeleteExpr *E) {
assert(convertTypeForMem(DeleteTy) == Ptr.getElementType());

if (E->isArrayForm()) {
EmitArrayDelete(*this, E, Ptr, DeleteTy);
cir::DeleteArrayOp::create(builder, Ptr.getPointer().getLoc(),
Ptr.getPointer());
} else {
Expand Down