1313#include " clang/CIR/Dialect/IR/CIRAttrs.h"
1414#include " clang/CIR/MissingFeatures.h"
1515#include < CIRGenCXXABI.h>
16+ #include < CIRGenCstEmitter.h>
1617#include < CIRGenFunction.h>
1718#include < CIRGenModule.h>
1819#include < CIRGenValue.h>
@@ -549,11 +550,25 @@ static UsualDeleteParams getUsualDeleteParams(const FunctionDecl *FD) {
549550 return Params;
550551}
551552
553+ static CharUnits CalculateCookiePadding (CIRGenFunction &CGF,
554+ const CXXNewExpr *E) {
555+ if (!E->isArray ())
556+ return CharUnits::Zero ();
557+
558+ // No cookie is required if the operator new[] being used is the
559+ // reserved placement operator new[].
560+ if (E->getOperatorNew ()->isReservedGlobalPlacementOperator ())
561+ return CharUnits::Zero ();
562+
563+ return CGF.CGM .getCXXABI ().getArrayCookieSize (E);
564+ }
565+
552566static mlir::Value emitCXXNewAllocSize (CIRGenFunction &CGF, const CXXNewExpr *e,
553567 unsigned minElements,
554568 mlir::Value &numElements,
555569 mlir::Value &sizeWithoutCookie) {
556570 QualType type = e->getAllocatedType ();
571+ mlir::Location Loc = CGF.getLoc (e->getSourceRange ());
557572
558573 if (!e->isArray ()) {
559574 CharUnits typeSize = CGF.getContext ().getTypeSizeInChars (type);
@@ -563,7 +578,96 @@ static mlir::Value emitCXXNewAllocSize(CIRGenFunction &CGF, const CXXNewExpr *e,
563578 return sizeWithoutCookie;
564579 }
565580
566- llvm_unreachable (" NYI" );
581+ // The width of size_t.
582+ unsigned sizeWidth = CGF.CGM .getDataLayout ().getTypeSizeInBits (CGF.SizeTy );
583+
584+ // The number of elements can be have an arbitrary integer type;
585+ // essentially, we need to multiply it by a constant factor, add a
586+ // cookie size, and verify that the result is representable as a
587+ // size_t. That's just a gloss, though, and it's wrong in one
588+ // important way: if the count is negative, it's an error even if
589+ // the cookie size would bring the total size >= 0.
590+ //
591+ // If the array size is constant, Sema will have prevented negative
592+ // values and size overflow.
593+
594+ // Compute the constant factor.
595+ llvm::APInt arraySizeMultiplier (sizeWidth, 1 );
596+ while (const ConstantArrayType *CAT =
597+ CGF.getContext ().getAsConstantArrayType (type)) {
598+ type = CAT->getElementType ();
599+ arraySizeMultiplier *= CAT->getSize ();
600+ }
601+
602+ CharUnits typeSize = CGF.getContext ().getTypeSizeInChars (type);
603+ llvm::APInt typeSizeMultiplier (sizeWidth, typeSize.getQuantity ());
604+ typeSizeMultiplier *= arraySizeMultiplier;
605+
606+ // Figure out the cookie size.
607+ llvm::APInt cookieSize (sizeWidth,
608+ CalculateCookiePadding (CGF, e).getQuantity ());
609+
610+ // This will be a size_t.
611+ mlir::Value size;
612+
613+ // Emit the array size expression.
614+ // We multiply the size of all dimensions for NumElements.
615+ // e.g for 'int[2][3]', ElemType is 'int' and NumElements is 6.
616+ const Expr *arraySize = *e->getArraySize ();
617+ mlir::Attribute constNumElements =
618+ ConstantEmitter (CGF.CGM , &CGF)
619+ .tryEmitAbstract (arraySize, arraySize->getType ());
620+ if (constNumElements) {
621+ // Get an APInt from the constant
622+ const llvm::APInt &count =
623+ mlir::cast<cir::IntAttr>(constNumElements).getValue ();
624+
625+ unsigned numElementsWidth = count.getBitWidth ();
626+
627+ // The equivalent code in CodeGen/CGExprCXX.cpp handles these cases as
628+ // overflow, but they should never happen. The size argument is implicitly
629+ // cast to a size_t, so it can never be negative and numElementsWidth will
630+ // always equal sizeWidth.
631+ assert (!count.isNegative () && " Expected non-negative array size" );
632+ assert (numElementsWidth == sizeWidth &&
633+ " Expected a size_t array size constant" );
634+
635+ // Okay, compute a count at the right width.
636+ llvm::APInt adjustedCount = count.zextOrTrunc (sizeWidth);
637+
638+ // Scale numElements by that. This might overflow, but we don't
639+ // care because it only overflows if allocationSize does, too, and
640+ // if that overflows then we shouldn't use this.
641+ // This emits a constant that may not be used, but we can't tell here
642+ // whether it will be needed or not.
643+ numElements =
644+ CGF.getBuilder ().getConstInt (Loc, adjustedCount * arraySizeMultiplier);
645+
646+ // Compute the size before cookie, and track whether it overflowed.
647+ bool overflow;
648+ llvm::APInt allocationSize =
649+ adjustedCount.umul_ov (typeSizeMultiplier, overflow);
650+
651+ // Sema prevents us from hitting this case
652+ assert (!overflow && " Overflow in array allocation size" );
653+
654+ // Add in the cookie, and check whether it's overflowed.
655+ if (cookieSize != 0 ) {
656+ llvm_unreachable (" NYI" );
657+ }
658+
659+ size = CGF.getBuilder ().getConstInt (Loc, allocationSize);
660+ } else {
661+ // TODO: Handle the variable size case
662+ llvm_unreachable (" NYI" );
663+ }
664+
665+ if (cookieSize == 0 )
666+ sizeWithoutCookie = size;
667+ else
668+ assert (sizeWithoutCookie && " didn't set sizeWithoutCookie?" );
669+
670+ return size;
567671}
568672
569673namespace {
@@ -745,33 +849,32 @@ static void StoreAnyExprIntoOneUnit(CIRGenFunction &CGF, const Expr *Init,
745849 llvm_unreachable (" bad evaluation kind" );
746850}
747851
852+ void CIRGenFunction::emitNewArrayInitializer (
853+ const CXXNewExpr *E, QualType ElementType, mlir::Type ElementTy,
854+ Address BeginPtr, mlir::Value NumElements,
855+ mlir::Value AllocSizeWithoutCookie) {
856+ // If we have a type with trivial initialization and no initializer,
857+ // there's nothing to do.
858+ if (!E->hasInitializer ())
859+ return ;
860+
861+ llvm_unreachable (" NYI" );
862+ }
863+
748864static void emitNewInitializer (CIRGenFunction &CGF, const CXXNewExpr *E,
749865 QualType ElementType, mlir::Type ElementTy,
750866 Address NewPtr, mlir::Value NumElements,
751867 mlir::Value AllocSizeWithoutCookie) {
752868 assert (!cir::MissingFeatures::generateDebugInfo ());
753869 if (E->isArray ()) {
754- llvm_unreachable (" NYI" );
870+ CGF.emitNewArrayInitializer (E, ElementType, ElementTy, NewPtr, NumElements,
871+ AllocSizeWithoutCookie);
755872 } else if (const Expr *Init = E->getInitializer ()) {
756873 StoreAnyExprIntoOneUnit (CGF, Init, E->getAllocatedType (), NewPtr,
757874 AggValueSlot::DoesNotOverlap);
758875 }
759876}
760877
761- static CharUnits CalculateCookiePadding (CIRGenFunction &CGF,
762- const CXXNewExpr *E) {
763- if (!E->isArray ())
764- return CharUnits::Zero ();
765-
766- // No cookie is required if the operator new[] being used is the
767- // reserved placement operator new[].
768- if (E->getOperatorNew ()->isReservedGlobalPlacementOperator ())
769- return CharUnits::Zero ();
770-
771- llvm_unreachable (" NYI" );
772- // return CGF.CGM.getCXXABI().GetArrayCookieSize(E);
773- }
774-
775878namespace {
776879// / Calls the given 'operator delete' on a single object.
777880struct CallObjectDelete final : EHScopeStack::Cleanup {
@@ -1129,9 +1232,6 @@ mlir::Value CIRGenFunction::emitCXXNewExpr(const CXXNewExpr *E) {
11291232 emitNewInitializer (*this , E, allocType, elementTy, result, numElements,
11301233 allocSizeWithoutCookie);
11311234 auto resultPtr = result.getPointer ();
1132- if (E->isArray ()) {
1133- llvm_unreachable (" NYI" );
1134- }
11351235
11361236 // Deactivate the 'operator delete' cleanup if we finished
11371237 // initialization.
0 commit comments