1111// ===----------------------------------------------------------------------===//
1212
1313#include " CIRGenCXXABI.h"
14+ #include " CIRGenConstantEmitter.h"
1415#include " CIRGenFunction.h"
1516
1617#include " clang/AST/DeclCXX.h"
@@ -264,6 +265,19 @@ static UsualDeleteParams getUsualDeleteParams(const FunctionDecl *fd) {
264265 return params;
265266}
266267
268+ static CharUnits calculateCookiePadding (CIRGenFunction &cgf,
269+ const CXXNewExpr *e) {
270+ if (!e->isArray ())
271+ return CharUnits::Zero ();
272+
273+ // No cookie is required if the operator new[] being used is the
274+ // reserved placement operator new[].
275+ if (e->getOperatorNew ()->isReservedGlobalPlacementOperator ())
276+ return CharUnits::Zero ();
277+
278+ return cgf.cgm .getCXXABI ().getArrayCookieSize (e);
279+ }
280+
267281static mlir::Value emitCXXNewAllocSize (CIRGenFunction &cgf, const CXXNewExpr *e,
268282 unsigned minElements,
269283 mlir::Value &numElements,
@@ -278,8 +292,98 @@ static mlir::Value emitCXXNewAllocSize(CIRGenFunction &cgf, const CXXNewExpr *e,
278292 return sizeWithoutCookie;
279293 }
280294
281- cgf.cgm .errorNYI (e->getSourceRange (), " emitCXXNewAllocSize: array" );
282- return {};
295+ // The width of size_t.
296+ unsigned sizeWidth = cgf.cgm .getDataLayout ().getTypeSizeInBits (cgf.SizeTy );
297+
298+ // The number of elements can be have an arbitrary integer type;
299+ // essentially, we need to multiply it by a constant factor, add a
300+ // cookie size, and verify that the result is representable as a
301+ // size_t. That's just a gloss, though, and it's wrong in one
302+ // important way: if the count is negative, it's an error even if
303+ // the cookie size would bring the total size >= 0.
304+ //
305+ // If the array size is constant, Sema will have prevented negative
306+ // values and size overflow.
307+
308+ // Compute the constant factor.
309+ llvm::APInt arraySizeMultiplier (sizeWidth, 1 );
310+ while (const ConstantArrayType *cat =
311+ cgf.getContext ().getAsConstantArrayType (type)) {
312+ type = cat->getElementType ();
313+ arraySizeMultiplier *= cat->getSize ();
314+ }
315+
316+ CharUnits typeSize = cgf.getContext ().getTypeSizeInChars (type);
317+ llvm::APInt typeSizeMultiplier (sizeWidth, typeSize.getQuantity ());
318+ typeSizeMultiplier *= arraySizeMultiplier;
319+
320+ // Figure out the cookie size.
321+ llvm::APInt cookieSize (sizeWidth,
322+ calculateCookiePadding (cgf, e).getQuantity ());
323+
324+ // This will be a size_t.
325+ mlir::Value size;
326+
327+ // Emit the array size expression.
328+ // We multiply the size of all dimensions for NumElements.
329+ // e.g for 'int[2][3]', ElemType is 'int' and NumElements is 6.
330+ const Expr *arraySize = *e->getArraySize ();
331+ mlir::Attribute constNumElements =
332+ ConstantEmitter (cgf.cgm , &cgf)
333+ .emitAbstract (arraySize, arraySize->getType ());
334+ if (constNumElements) {
335+ // Get an APInt from the constant
336+ const llvm::APInt &count =
337+ mlir::cast<cir::IntAttr>(constNumElements).getValue ();
338+
339+ unsigned numElementsWidth = count.getBitWidth ();
340+
341+ // The equivalent code in CodeGen/CGExprCXX.cpp handles these cases as
342+ // overflow, but they should never happen. The size argument is implicitly
343+ // cast to a size_t, so it can never be negative and numElementsWidth will
344+ // always equal sizeWidth.
345+ assert (!count.isNegative () && " Expected non-negative array size" );
346+ assert (numElementsWidth == sizeWidth &&
347+ " Expected a size_t array size constant" );
348+
349+ // Okay, compute a count at the right width.
350+ llvm::APInt adjustedCount = count.zextOrTrunc (sizeWidth);
351+
352+ // Scale numElements by that. This might overflow, but we don't
353+ // care because it only overflows if allocationSize does, too, and
354+ // if that overflows then we shouldn't use this.
355+ // This emits a constant that may not be used, but we can't tell here
356+ // whether it will be needed or not.
357+ numElements =
358+ cgf.getBuilder ().getConstInt (loc, adjustedCount * arraySizeMultiplier);
359+
360+ // Compute the size before cookie, and track whether it overflowed.
361+ bool overflow;
362+ llvm::APInt allocationSize =
363+ adjustedCount.umul_ov (typeSizeMultiplier, overflow);
364+
365+ // Sema prevents us from hitting this case
366+ assert (!overflow && " Overflow in array allocation size" );
367+
368+ // Add in the cookie, and check whether it's overflowed.
369+ if (cookieSize != 0 ) {
370+ cgf.cgm .errorNYI (e->getSourceRange (),
371+ " emitCXXNewAllocSize: array cookie" );
372+ }
373+
374+ size = cgf.getBuilder ().getConstInt (loc, allocationSize);
375+ } else {
376+ // TODO: Handle the variable size case
377+ cgf.cgm .errorNYI (e->getSourceRange (),
378+ " emitCXXNewAllocSize: variable array size" );
379+ }
380+
381+ if (cookieSize == 0 )
382+ sizeWithoutCookie = size;
383+ else
384+ assert (sizeWithoutCookie && " didn't set sizeWithoutCookie?" );
385+
386+ return size;
283387}
284388
285389static void storeAnyExprIntoOneUnit (CIRGenFunction &cgf, const Expr *init,
@@ -308,13 +412,26 @@ static void storeAnyExprIntoOneUnit(CIRGenFunction &cgf, const Expr *init,
308412 llvm_unreachable (" bad evaluation kind" );
309413}
310414
415+ void CIRGenFunction::emitNewArrayInitializer (
416+ const CXXNewExpr *e, QualType elementType, mlir::Type elementTy,
417+ Address beginPtr, mlir::Value numElements,
418+ mlir::Value allocSizeWithoutCookie) {
419+ // If we have a type with trivial initialization and no initializer,
420+ // there's nothing to do.
421+ if (!e->hasInitializer ())
422+ return ;
423+
424+ llvm_unreachable (" NYI" );
425+ }
426+
311427static void emitNewInitializer (CIRGenFunction &cgf, const CXXNewExpr *e,
312428 QualType elementType, mlir::Type elementTy,
313429 Address newPtr, mlir::Value numElements,
314430 mlir::Value allocSizeWithoutCookie) {
315431 assert (!cir::MissingFeatures::generateDebugInfo ());
316432 if (e->isArray ()) {
317- cgf.cgm .errorNYI (e->getSourceRange (), " emitNewInitializer: array" );
433+ cgf.emitNewArrayInitializer (e, elementType, elementTy, newPtr, numElements,
434+ allocSizeWithoutCookie);
318435 } else if (const Expr *init = e->getInitializer ()) {
319436 storeAnyExprIntoOneUnit (cgf, init, e->getAllocatedType (), newPtr,
320437 AggValueSlot::DoesNotOverlap);
@@ -583,14 +700,22 @@ mlir::Value CIRGenFunction::emitCXXNewExpr(const CXXNewExpr *e) {
583700
584701 // If there's an operator delete, enter a cleanup to call it if an
585702 // exception is thrown.
586- if (e->getOperatorDelete () &&
587- !e->getOperatorDelete ()->isReservedGlobalPlacementOperator ())
588- cgm.errorNYI (e->getSourceRange (), " emitCXXNewExpr: operator delete" );
703+ // TODO: Handle operator delete cleanup for exception safety
704+ // if (e->getOperatorDelete() &&
705+ // !e->getOperatorDelete()->isReservedGlobalPlacementOperator())
706+ // cgm.errorNYI(e->getSourceRange(), "emitCXXNewExpr: operator delete");
589707
590708 if (allocSize != allocSizeWithoutCookie)
591709 cgm.errorNYI (e->getSourceRange (), " emitCXXNewExpr: array with cookies" );
592710
593- mlir::Type elementTy = convertTypeForMem (allocType);
711+ mlir::Type elementTy;
712+ if (e->isArray ()) {
713+ // For array new, use the allocated type to handle multidimensional arrays
714+ // correctly
715+ elementTy = convertTypeForMem (e->getAllocatedType ());
716+ } else {
717+ elementTy = convertTypeForMem (allocType);
718+ }
594719 Address result = builder.createElementBitCast (getLoc (e->getSourceRange ()),
595720 allocation, elementTy);
596721
0 commit comments