1111// ===----------------------------------------------------------------------===//
1212
1313#include " CIRGenCXXABI.h"
14+ #include " CIRGenConstantEmitter.h"
1415#include " CIRGenFunction.h"
1516
1617#include " clang/AST/DeclCXX.h"
@@ -210,6 +211,19 @@ RValue CIRGenFunction::emitCXXMemberOrOperatorCall(
210211 return emitCall (fnInfo, callee, returnValue, args, nullptr , loc);
211212}
212213
214+ static CharUnits calculateCookiePadding (CIRGenFunction &cgf,
215+ const CXXNewExpr *e) {
216+ if (!e->isArray ())
217+ return CharUnits::Zero ();
218+
219+ // No cookie is required if the operator new[] being used is the
220+ // reserved placement operator new[].
221+ if (e->getOperatorNew ()->isReservedGlobalPlacementOperator ())
222+ return CharUnits::Zero ();
223+
224+ return cgf.cgm .getCXXABI ().getArrayCookieSize (e);
225+ }
226+
213227static mlir::Value emitCXXNewAllocSize (CIRGenFunction &cgf, const CXXNewExpr *e,
214228 unsigned minElements,
215229 mlir::Value &numElements,
@@ -224,8 +238,98 @@ static mlir::Value emitCXXNewAllocSize(CIRGenFunction &cgf, const CXXNewExpr *e,
224238 return sizeWithoutCookie;
225239 }
226240
227- cgf.cgm .errorNYI (e->getSourceRange (), " emitCXXNewAllocSize: array" );
228- return {};
241+ // The width of size_t.
242+ unsigned sizeWidth = cgf.cgm .getDataLayout ().getTypeSizeInBits (cgf.SizeTy );
243+
244+ // The number of elements can be have an arbitrary integer type;
245+ // essentially, we need to multiply it by a constant factor, add a
246+ // cookie size, and verify that the result is representable as a
247+ // size_t. That's just a gloss, though, and it's wrong in one
248+ // important way: if the count is negative, it's an error even if
249+ // the cookie size would bring the total size >= 0.
250+ //
251+ // If the array size is constant, Sema will have prevented negative
252+ // values and size overflow.
253+
254+ // Compute the constant factor.
255+ llvm::APInt arraySizeMultiplier (sizeWidth, 1 );
256+ while (const ConstantArrayType *cat =
257+ cgf.getContext ().getAsConstantArrayType (type)) {
258+ type = cat->getElementType ();
259+ arraySizeMultiplier *= cat->getSize ();
260+ }
261+
262+ CharUnits typeSize = cgf.getContext ().getTypeSizeInChars (type);
263+ llvm::APInt typeSizeMultiplier (sizeWidth, typeSize.getQuantity ());
264+ typeSizeMultiplier *= arraySizeMultiplier;
265+
266+ // Figure out the cookie size.
267+ llvm::APInt cookieSize (sizeWidth,
268+ calculateCookiePadding (cgf, e).getQuantity ());
269+
270+ // This will be a size_t.
271+ mlir::Value size;
272+
273+ // Emit the array size expression.
274+ // We multiply the size of all dimensions for NumElements.
275+ // e.g for 'int[2][3]', ElemType is 'int' and NumElements is 6.
276+ const Expr *arraySize = *e->getArraySize ();
277+ mlir::Attribute constNumElements =
278+ ConstantEmitter (cgf.cgm , &cgf)
279+ .emitAbstract (arraySize, arraySize->getType ());
280+ if (constNumElements) {
281+ // Get an APInt from the constant
282+ const llvm::APInt &count =
283+ mlir::cast<cir::IntAttr>(constNumElements).getValue ();
284+
285+ unsigned numElementsWidth = count.getBitWidth ();
286+
287+ // The equivalent code in CodeGen/CGExprCXX.cpp handles these cases as
288+ // overflow, but that should never happen. The size argument is implicitly
289+ // cast to a size_t, so it can never be negative and numElementsWidth will
290+ // always equal sizeWidth.
291+ assert (!count.isNegative () && " Expected non-negative array size" );
292+ assert (numElementsWidth == sizeWidth &&
293+ " Expected a size_t array size constant" );
294+
295+ // Okay, compute a count at the right width.
296+ llvm::APInt adjustedCount = count.zextOrTrunc (sizeWidth);
297+
298+ // Scale numElements by that. This might overflow, but we don't
299+ // care because it only overflows if allocationSize does too, and
300+ // if that overflows then we shouldn't use this.
301+ // This emits a constant that may not be used, but we can't tell here
302+ // whether it will be needed or not.
303+ numElements =
304+ cgf.getBuilder ().getConstInt (loc, adjustedCount * arraySizeMultiplier);
305+
306+ // Compute the size before cookie, and track whether it overflowed.
307+ bool overflow;
308+ llvm::APInt allocationSize =
309+ adjustedCount.umul_ov (typeSizeMultiplier, overflow);
310+
311+ // Sema prevents us from hitting this case
312+ assert (!overflow && " Overflow in array allocation size" );
313+
314+ // Add in the cookie, and check whether it's overflowed.
315+ if (cookieSize != 0 ) {
316+ cgf.cgm .errorNYI (e->getSourceRange (),
317+ " emitCXXNewAllocSize: array cookie" );
318+ }
319+
320+ size = cgf.getBuilder ().getConstInt (loc, allocationSize);
321+ } else {
322+ // TODO: Handle the variable size case
323+ cgf.cgm .errorNYI (e->getSourceRange (),
324+ " emitCXXNewAllocSize: variable array size" );
325+ }
326+
327+ if (cookieSize == 0 )
328+ sizeWithoutCookie = size;
329+ else
330+ assert (sizeWithoutCookie && " didn't set sizeWithoutCookie?" );
331+
332+ return size;
229333}
230334
231335static void storeAnyExprIntoOneUnit (CIRGenFunction &cgf, const Expr *init,
@@ -254,13 +358,26 @@ static void storeAnyExprIntoOneUnit(CIRGenFunction &cgf, const Expr *init,
254358 llvm_unreachable (" bad evaluation kind" );
255359}
256360
361+ void CIRGenFunction::emitNewArrayInitializer (
362+ const CXXNewExpr *e, QualType elementType, mlir::Type elementTy,
363+ Address beginPtr, mlir::Value numElements,
364+ mlir::Value allocSizeWithoutCookie) {
365+ // If we have a type with trivial initialization and no initializer,
366+ // there's nothing to do.
367+ if (!e->hasInitializer ())
368+ return ;
369+
370+ cgm.errorNYI (e->getSourceRange (), " emitNewArrayInitializer" );
371+ }
372+
257373static void emitNewInitializer (CIRGenFunction &cgf, const CXXNewExpr *e,
258374 QualType elementType, mlir::Type elementTy,
259375 Address newPtr, mlir::Value numElements,
260376 mlir::Value allocSizeWithoutCookie) {
261377 assert (!cir::MissingFeatures::generateDebugInfo ());
262378 if (e->isArray ()) {
263- cgf.cgm .errorNYI (e->getSourceRange (), " emitNewInitializer: array" );
379+ cgf.emitNewArrayInitializer (e, elementType, elementTy, newPtr, numElements,
380+ allocSizeWithoutCookie);
264381 } else if (const Expr *init = e->getInitializer ()) {
265382 storeAnyExprIntoOneUnit (cgf, init, e->getAllocatedType (), newPtr,
266383 AggValueSlot::DoesNotOverlap);
@@ -536,7 +653,14 @@ mlir::Value CIRGenFunction::emitCXXNewExpr(const CXXNewExpr *e) {
536653 if (allocSize != allocSizeWithoutCookie)
537654 cgm.errorNYI (e->getSourceRange (), " emitCXXNewExpr: array with cookies" );
538655
539- mlir::Type elementTy = convertTypeForMem (allocType);
656+ mlir::Type elementTy;
657+ if (e->isArray ()) {
658+ // For array new, use the allocated type to handle multidimensional arrays
659+ // correctly
660+ elementTy = convertTypeForMem (e->getAllocatedType ());
661+ } else {
662+ elementTy = convertTypeForMem (allocType);
663+ }
540664 Address result = builder.createElementBitCast (getLoc (e->getSourceRange ()),
541665 allocation, elementTy);
542666
0 commit comments