13
13
#include " clang/CIR/Dialect/IR/CIRAttrs.h"
14
14
#include " clang/CIR/MissingFeatures.h"
15
15
#include < CIRGenCXXABI.h>
16
+ #include < CIRGenCstEmitter.h>
16
17
#include < CIRGenFunction.h>
17
18
#include < CIRGenModule.h>
18
19
#include < CIRGenValue.h>
@@ -549,11 +550,25 @@ static UsualDeleteParams getUsualDeleteParams(const FunctionDecl *FD) {
549
550
return Params;
550
551
}
551
552
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
+
552
566
static mlir::Value emitCXXNewAllocSize (CIRGenFunction &CGF, const CXXNewExpr *e,
553
567
unsigned minElements,
554
568
mlir::Value &numElements,
555
569
mlir::Value &sizeWithoutCookie) {
556
570
QualType type = e->getAllocatedType ();
571
+ mlir::Location Loc = CGF.getLoc (e->getSourceRange ());
557
572
558
573
if (!e->isArray ()) {
559
574
CharUnits typeSize = CGF.getContext ().getTypeSizeInChars (type);
@@ -563,7 +578,96 @@ static mlir::Value emitCXXNewAllocSize(CIRGenFunction &CGF, const CXXNewExpr *e,
563
578
return sizeWithoutCookie;
564
579
}
565
580
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;
567
671
}
568
672
569
673
namespace {
@@ -745,33 +849,32 @@ static void StoreAnyExprIntoOneUnit(CIRGenFunction &CGF, const Expr *Init,
745
849
llvm_unreachable (" bad evaluation kind" );
746
850
}
747
851
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
+
748
864
static void emitNewInitializer (CIRGenFunction &CGF, const CXXNewExpr *E,
749
865
QualType ElementType, mlir::Type ElementTy,
750
866
Address NewPtr, mlir::Value NumElements,
751
867
mlir::Value AllocSizeWithoutCookie) {
752
868
assert (!cir::MissingFeatures::generateDebugInfo ());
753
869
if (E->isArray ()) {
754
- llvm_unreachable (" NYI" );
870
+ CGF.emitNewArrayInitializer (E, ElementType, ElementTy, NewPtr , NumElements,
871
+ AllocSizeWithoutCookie);
755
872
} else if (const Expr *Init = E->getInitializer ()) {
756
873
StoreAnyExprIntoOneUnit (CGF, Init, E->getAllocatedType (), NewPtr ,
757
874
AggValueSlot::DoesNotOverlap);
758
875
}
759
876
}
760
877
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
-
775
878
namespace {
776
879
// / Calls the given 'operator delete' on a single object.
777
880
struct CallObjectDelete final : EHScopeStack::Cleanup {
@@ -1129,9 +1232,6 @@ mlir::Value CIRGenFunction::emitCXXNewExpr(const CXXNewExpr *E) {
1129
1232
emitNewInitializer (*this , E, allocType, elementTy, result, numElements,
1130
1233
allocSizeWithoutCookie);
1131
1234
auto resultPtr = result.getPointer ();
1132
- if (E->isArray ()) {
1133
- llvm_unreachable (" NYI" );
1134
- }
1135
1235
1136
1236
// Deactivate the 'operator delete' cleanup if we finished
1137
1237
// initialization.
0 commit comments