diff options
Diffstat (limited to 'clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp')
-rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp | 73 |
1 files changed, 64 insertions, 9 deletions
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp index b1e9e76..fe9e210 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp @@ -306,6 +306,7 @@ static mlir::Value emitCXXNewAllocSize(CIRGenFunction &cgf, const CXXNewExpr *e, mlir::cast<cir::IntAttr>(constNumElements).getValue(); unsigned numElementsWidth = count.getBitWidth(); + bool hasAnyOverflow = false; // The equivalent code in CodeGen/CGExprCXX.cpp handles these cases as // overflow, but that should never happen. The size argument is implicitly @@ -336,11 +337,22 @@ static mlir::Value emitCXXNewAllocSize(CIRGenFunction &cgf, const CXXNewExpr *e, // Add in the cookie, and check whether it's overflowed. if (cookieSize != 0) { - cgf.cgm.errorNYI(e->getSourceRange(), - "emitCXXNewAllocSize: array cookie"); + // Save the current size without a cookie. This shouldn't be + // used if there was overflow + sizeWithoutCookie = cgf.getBuilder().getConstInt( + loc, allocationSize.zextOrTrunc(sizeWidth)); + + allocationSize = allocationSize.uadd_ov(cookieSize, overflow); + hasAnyOverflow |= overflow; } - size = cgf.getBuilder().getConstInt(loc, allocationSize); + // On overflow, produce a -1 so operator new will fail + if (hasAnyOverflow) { + size = + cgf.getBuilder().getConstInt(loc, llvm::APInt::getAllOnes(sizeWidth)); + } else { + size = cgf.getBuilder().getConstInt(loc, allocationSize); + } } else { // TODO: Handle the variable size case cgf.cgm.errorNYI(e->getSourceRange(), @@ -390,7 +402,50 @@ void CIRGenFunction::emitNewArrayInitializer( if (!e->hasInitializer()) return; - cgm.errorNYI(e->getSourceRange(), "emitNewArrayInitializer"); + unsigned initListElements = 0; + + const Expr *init = e->getInitializer(); + const InitListExpr *ile = dyn_cast<InitListExpr>(init); + if (ile) { + cgm.errorNYI(ile->getSourceRange(), "emitNewArrayInitializer: init list"); + return; + } + + // If all elements have already been initialized, skip any further + // initialization. + auto constOp = mlir::dyn_cast<cir::ConstantOp>(numElements.getDefiningOp()); + if (constOp) { + auto constIntAttr = mlir::dyn_cast<cir::IntAttr>(constOp.getValue()); + // Just skip out if the constant count is zero. + if (constIntAttr && constIntAttr.getUInt() <= initListElements) + return; + } + + assert(init && "have trailing elements to initialize but no initializer"); + + // If this is a constructor call, try to optimize it out, and failing that + // emit a single loop to initialize all remaining elements. + if (const CXXConstructExpr *cce = dyn_cast<CXXConstructExpr>(init)) { + CXXConstructorDecl *ctor = cce->getConstructor(); + if (ctor->isTrivial()) { + // If new expression did not specify value-initialization, then there + // is no initialization. + if (!cce->requiresZeroInitialization()) + return; + + cgm.errorNYI(cce->getSourceRange(), + "emitNewArrayInitializer: trivial ctor zero-init"); + return; + } + + cgm.errorNYI(cce->getSourceRange(), + "emitNewArrayInitializer: ctor initializer"); + return; + } + + cgm.errorNYI(init->getSourceRange(), + "emitNewArrayInitializer: unsupported initializer"); + return; } static void emitNewInitializer(CIRGenFunction &cgf, const CXXNewExpr *e, @@ -586,9 +641,6 @@ mlir::Value CIRGenFunction::emitCXXNewExpr(const CXXNewExpr *e) { // If there is a brace-initializer, cannot allocate fewer elements than inits. unsigned minElements = 0; - if (e->isArray() && e->hasInitializer()) { - cgm.errorNYI(e->getSourceRange(), "emitCXXNewExpr: array initializer"); - } mlir::Value numElements = nullptr; mlir::Value allocSizeWithoutCookie = nullptr; @@ -667,8 +719,11 @@ mlir::Value CIRGenFunction::emitCXXNewExpr(const CXXNewExpr *e) { !e->getOperatorDelete()->isReservedGlobalPlacementOperator()) cgm.errorNYI(e->getSourceRange(), "emitCXXNewExpr: operator delete"); - if (allocSize != allocSizeWithoutCookie) - cgm.errorNYI(e->getSourceRange(), "emitCXXNewExpr: array with cookies"); + if (allocSize != allocSizeWithoutCookie) { + assert(e->isArray()); + allocation = cgm.getCXXABI().initializeArrayCookie( + *this, allocation, numElements, e, allocType); + } mlir::Type elementTy; if (e->isArray()) { |