Skip to content

Commit befba94

Browse files
committed
[CIR] Add array new cookie support
1 parent 4bf5ab4 commit befba94

File tree

7 files changed

+289
-16
lines changed

7 files changed

+289
-16
lines changed

clang/lib/CIR/CodeGen/CIRGenCXXABI.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,7 @@ CharUnits CIRGenCXXABI::getArrayCookieSize(const CXXNewExpr *e) {
8181
if (!requiresArrayCookie(e))
8282
return CharUnits::Zero();
8383

84-
cgm.errorNYI(e->getSourceRange(), "CIRGenCXXABI::getArrayCookieSize");
85-
return CharUnits::Zero();
84+
return getArrayCookieSizeImpl(e->getAllocatedType());
8685
}
8786

8887
bool CIRGenCXXABI::requiresArrayCookie(const CXXNewExpr *e) {

clang/lib/CIR/CodeGen/CIRGenCXXABI.h

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,8 +290,28 @@ class CIRGenCXXABI {
290290
/// - non-array allocations never need a cookie
291291
/// - calls to \::operator new(size_t, void*) never need a cookie
292292
///
293-
/// \param E - the new-expression being allocated.
293+
/// \param e - the new-expression being allocated.
294294
virtual CharUnits getArrayCookieSize(const CXXNewExpr *e);
295+
296+
/// Initialize the array cookie for the given allocation.
297+
///
298+
/// \param newPtr - a char* which is the presumed-non-null
299+
/// return value of the allocation function
300+
/// \param numElements - the computed number of elements,
301+
/// potentially collapsed from the multidimensional array case;
302+
/// always a size_t
303+
/// \param elementType - the base element allocated type,
304+
/// i.e. the allocated type after stripping all array types
305+
virtual Address initializeArrayCookie(CIRGenFunction &cgf, Address newPtr,
306+
mlir::Value numElements,
307+
const CXXNewExpr *e,
308+
QualType elementType) = 0;
309+
310+
protected:
311+
/// Returns the extra size required in order to store the array
312+
/// cookie for the given type. Assumes that an array cookie is
313+
/// required.
314+
virtual CharUnits getArrayCookieSizeImpl(QualType elementType) = 0;
295315
};
296316

297317
/// Creates and Itanium-family ABI

clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp

Lines changed: 65 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ static mlir::Value emitCXXNewAllocSize(CIRGenFunction &cgf, const CXXNewExpr *e,
283283
mlir::cast<cir::IntAttr>(constNumElements).getValue();
284284

285285
unsigned numElementsWidth = count.getBitWidth();
286+
bool hasAnyOverflow = false;
286287

287288
// The equivalent code in CodeGen/CGExprCXX.cpp handles these cases as
288289
// overflow, but that should never happen. The size argument is implicitly
@@ -313,11 +314,22 @@ static mlir::Value emitCXXNewAllocSize(CIRGenFunction &cgf, const CXXNewExpr *e,
313314

314315
// Add in the cookie, and check whether it's overflowed.
315316
if (cookieSize != 0) {
316-
cgf.cgm.errorNYI(e->getSourceRange(),
317-
"emitCXXNewAllocSize: array cookie");
317+
// Save the current size without a cookie. This shouldn't be
318+
// used if there was overflow
319+
sizeWithoutCookie = cgf.getBuilder().getConstInt(
320+
loc, allocationSize.zextOrTrunc(sizeWidth));
321+
322+
allocationSize = allocationSize.uadd_ov(cookieSize, overflow);
323+
hasAnyOverflow |= overflow;
318324
}
319325

320-
size = cgf.getBuilder().getConstInt(loc, allocationSize);
326+
// On overflow, produce a -1 so operator new will fail
327+
if (hasAnyOverflow) {
328+
size = cgf.getBuilder().getConstInt(
329+
loc, llvm::APInt::getAllOnes(sizeWidth));
330+
} else {
331+
size = cgf.getBuilder().getConstInt(loc, allocationSize);
332+
}
321333
} else {
322334
// TODO: Handle the variable size case
323335
cgf.cgm.errorNYI(e->getSourceRange(),
@@ -367,7 +379,51 @@ void CIRGenFunction::emitNewArrayInitializer(
367379
if (!e->hasInitializer())
368380
return;
369381

370-
cgm.errorNYI(e->getSourceRange(), "emitNewArrayInitializer");
382+
unsigned initListElements = 0;
383+
384+
const Expr *init = e->getInitializer();
385+
const InitListExpr *ile = dyn_cast<InitListExpr>(init);
386+
if (ile) {
387+
cgm.errorNYI(ile->getSourceRange(),
388+
"emitNewArrayInitializer: init list");
389+
return;
390+
}
391+
392+
// If all elements have already been initialized, skip any further
393+
// initialization.
394+
auto constOp = dyn_cast<cir::ConstantOp>(numElements.getDefiningOp());
395+
if (constOp) {
396+
auto constIntAttr = mlir::dyn_cast<cir::IntAttr>(constOp.getValue());
397+
// Just skip out if the constant count is zero.
398+
if (constIntAttr && constIntAttr.getUInt() <= initListElements)
399+
return;
400+
}
401+
402+
assert(init && "have trailing elements to initialize but no initializer");
403+
404+
// If this is a constructor call, try to optimize it out, and failing that
405+
// emit a single loop to initialize all remaining elements.
406+
if (const CXXConstructExpr *cce = dyn_cast<CXXConstructExpr>(init)) {
407+
CXXConstructorDecl *ctor = cce->getConstructor();
408+
if (ctor->isTrivial()) {
409+
// If new expression did not specify value-initialization, then there
410+
// is no initialization.
411+
if (!cce->requiresZeroInitialization())
412+
return;
413+
414+
cgm.errorNYI(cce->getSourceRange(),
415+
"emitNewArrayInitializer: trivial ctor zero-init");
416+
return;
417+
}
418+
419+
cgm.errorNYI(cce->getSourceRange(),
420+
"emitNewArrayInitializer: ctor initializer");
421+
return;
422+
}
423+
424+
cgm.errorNYI(init->getSourceRange(),
425+
"emitNewArrayInitializer: unsupported initializer");
426+
return;
371427
}
372428

373429
static void emitNewInitializer(CIRGenFunction &cgf, const CXXNewExpr *e,
@@ -563,9 +619,6 @@ mlir::Value CIRGenFunction::emitCXXNewExpr(const CXXNewExpr *e) {
563619

564620
// If there is a brace-initializer, cannot allocate fewer elements than inits.
565621
unsigned minElements = 0;
566-
if (e->isArray() && e->hasInitializer()) {
567-
cgm.errorNYI(e->getSourceRange(), "emitCXXNewExpr: array initializer");
568-
}
569622

570623
mlir::Value numElements = nullptr;
571624
mlir::Value allocSizeWithoutCookie = nullptr;
@@ -644,8 +697,11 @@ mlir::Value CIRGenFunction::emitCXXNewExpr(const CXXNewExpr *e) {
644697
!e->getOperatorDelete()->isReservedGlobalPlacementOperator())
645698
cgm.errorNYI(e->getSourceRange(), "emitCXXNewExpr: operator delete");
646699

647-
if (allocSize != allocSizeWithoutCookie)
648-
cgm.errorNYI(e->getSourceRange(), "emitCXXNewExpr: array with cookies");
700+
if (allocSize != allocSizeWithoutCookie) {
701+
assert(e->isArray());
702+
allocation = cgm.getCXXABI().initializeArrayCookie(
703+
*this, allocation, numElements, e, allocType);
704+
}
649705

650706
mlir::Type elementTy;
651707
if (e->isArray()) {

clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,15 @@ class CIRGenItaniumCXXABI : public CIRGenCXXABI {
132132
cir::PointerType destCIRTy, bool isRefCast,
133133
Address src) override;
134134

135-
/**************************** RTTI Uniqueness ******************************/
135+
Address initializeArrayCookie(CIRGenFunction &cgf, Address newPtr,
136+
mlir::Value numElements,
137+
const CXXNewExpr *e,
138+
QualType elementType) override;
139+
136140
protected:
141+
CharUnits getArrayCookieSizeImpl(QualType elementType) override;
142+
143+
/**************************** RTTI Uniqueness ******************************/
137144
/// Returns true if the ABI requires RTTI type_info objects to be unique
138145
/// across a program.
139146
virtual bool shouldRTTIBeUnique() const { return true; }
@@ -1977,3 +1984,69 @@ mlir::Value CIRGenItaniumCXXABI::emitDynamicCast(CIRGenFunction &cgf,
19771984
return cgf.getBuilder().createDynCast(loc, src.getPointer(), destCIRTy,
19781985
isRefCast, castInfo);
19791986
}
1987+
1988+
/************************** Array allocation cookies **************************/
1989+
1990+
CharUnits CIRGenItaniumCXXABI::getArrayCookieSizeImpl(QualType elementType) {
1991+
// The array cookie is a size_t; pad that up to the element alignment.
1992+
// The cookie is actually right-justified in that space.
1993+
return std::max(CharUnits::fromQuantity(cgm.SizeSizeInBytes),
1994+
cgm.getASTContext().getPreferredTypeAlignInChars(
1995+
elementType));
1996+
}
1997+
1998+
Address CIRGenItaniumCXXABI::initializeArrayCookie(CIRGenFunction &cgf,
1999+
Address newPtr,
2000+
mlir::Value numElements,
2001+
const CXXNewExpr *e,
2002+
QualType elementType) {
2003+
assert(requiresArrayCookie(e));
2004+
2005+
// TODO: Get the address space when sanitizer support is implemented.
2006+
2007+
ASTContext &ctx = cgm.getASTContext();
2008+
CharUnits sizeSize = cgf.getSizeSize();
2009+
mlir::Location loc = cgf.getLoc(e->getSourceRange());
2010+
2011+
// The size of the cookie.
2012+
CharUnits cookieSize =
2013+
std::max(sizeSize, ctx.getPreferredTypeAlignInChars(elementType));
2014+
assert(cookieSize == getArrayCookieSizeImpl(elementType));
2015+
2016+
auto u8Ty = cgf.getBuilder().getUIntNTy(8);
2017+
mlir::Value baseBytePtr = cgf.getBuilder().createPtrBitcast(
2018+
newPtr.getPointer(), cgf.getBuilder().getPointerTo(u8Ty));
2019+
2020+
// Compute an offset to the cookie.
2021+
CharUnits cookieOffset = cookieSize - sizeSize;
2022+
mlir::Value cookiePtrValue = baseBytePtr;
2023+
if (!cookieOffset.isZero()) {
2024+
auto offsetOp = cgf.getBuilder().getSignedInt(
2025+
loc, cookieOffset.getQuantity(), /*width=*/32);
2026+
cookiePtrValue =
2027+
cgf.getBuilder().createPtrStride(loc, cookiePtrValue, offsetOp);
2028+
}
2029+
2030+
CharUnits baseAlignment = newPtr.getAlignment();
2031+
CharUnits cookiePtrAlignment = baseAlignment.alignmentAtOffset(cookieOffset);
2032+
Address cookiePtr(cookiePtrValue, u8Ty, cookiePtrAlignment);
2033+
2034+
// Write the number of elements into the appropriate slot.
2035+
Address numElementsPtr =
2036+
cookiePtr.withElementType(cgf.getBuilder(), cgf.SizeTy);
2037+
cgf.getBuilder().createStore(loc, numElements, numElementsPtr);
2038+
2039+
if (cgf.sanOpts.has(SanitizerKind::Address))
2040+
llvm_unreachable("NYI");
2041+
2042+
// Finally, compute a pointer to the actual data buffer by skipping
2043+
// over the cookie completely.
2044+
auto dataOffset = cgf.getBuilder().getSignedInt(
2045+
loc, cookieSize.getQuantity(), /*width=*/32);
2046+
mlir::Value dataPtr =
2047+
cgf.getBuilder().createPtrStride(loc, baseBytePtr, dataOffset);
2048+
mlir::Value finalPtr = cgf.getBuilder().createPtrBitcast(
2049+
dataPtr, newPtr.getElementType());
2050+
CharUnits finalAlignment = baseAlignment.alignmentAtOffset(cookieSize);
2051+
return Address(finalPtr, newPtr.getElementType(), finalAlignment);
2052+
}

clang/lib/CIR/CodeGen/CIRGenModule.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ CIRGenModule::CIRGenModule(mlir::MLIRContext &mlirContext,
100100
// TODO(CIR): Should be updated once TypeSizeInfoAttr is upstreamed
101101
const unsigned sizeTypeSize =
102102
astContext.getTypeSize(astContext.getSignedSizeType());
103-
SizeAlignInBytes = astContext.toCharUnitsFromBits(sizeTypeSize).getQuantity();
103+
SizeSizeInBytes = astContext.toCharUnitsFromBits(sizeTypeSize).getQuantity();
104104
// In CIRGenTypeCache, UIntPtrTy and SizeType are fields of the same union
105105
UIntPtrTy =
106106
cir::IntType::get(&getMLIRContext(), sizeTypeSize, /*isSigned=*/false);

clang/lib/CIR/CodeGen/CIRGenTypeCache.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,17 @@ struct CIRGenTypeCache {
7171
unsigned char PointerSizeInBytes;
7272
};
7373

74-
/// The alignment of size_t.
75-
unsigned char SizeAlignInBytes;
74+
/// The size and alignment of size_t.
75+
union {
76+
unsigned char SizeSizeInBytes; // sizeof(size_t)
77+
unsigned char SizeAlignInBytes;
78+
};
7679

7780
cir::TargetAddressSpaceAttr cirAllocaAddressSpace;
7881

82+
clang::CharUnits getSizeSize() const {
83+
return clang::CharUnits::fromQuantity(SizeSizeInBytes);
84+
}
7985
clang::CharUnits getSizeAlign() const {
8086
return clang::CharUnits::fromQuantity(SizeAlignInBytes);
8187
}

clang/test/CIR/CodeGen/new.cpp

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,125 @@ void t_new_constant_size() {
208208
// OGCG: %[[CALL:.*]] = call noalias noundef nonnull ptr @_Znam(i64 noundef 128)
209209
// OGCG: store ptr %[[CALL]], ptr %[[P_ADDR]], align 8
210210

211+
class C {
212+
public:
213+
~C();
214+
};
215+
216+
void t_constant_size_nontrivial() {
217+
auto p = new C[3];
218+
}
219+
220+
// CHECK: cir.func{{.*}} @_Z26t_constant_size_nontrivialv()
221+
// CHECK: %[[P_ADDR:.*]] = cir.alloca !cir.ptr<!rec_C>, !cir.ptr<!cir.ptr<!rec_C>>, ["p", init] {alignment = 8 : i64}
222+
// CHECK: %[[#NUM_ELEMENTS:]] = cir.const #cir.int<3> : !u64i
223+
// CHECK: %[[#SIZE_WITHOUT_COOKIE:]] = cir.const #cir.int<3> : !u64i
224+
// CHECK: %[[#ALLOCATION_SIZE:]] = cir.const #cir.int<11> : !u64i
225+
// CHECK: %[[RAW_PTR:.*]] = cir.call @_Znam(%[[#ALLOCATION_SIZE]]) : (!u64i) -> !cir.ptr<!void>
226+
// CHECK: %[[COOKIE_PTR_BASE:.*]] = cir.cast bitcast %[[RAW_PTR]] : !cir.ptr<!void> -> !cir.ptr<!cir.ptr<!u8i>>
227+
// CHECK: %[[COOKIE_PTR:.*]] = cir.cast bitcast %[[COOKIE_PTR_BASE]] : !cir.ptr<!cir.ptr<!u8i>> -> !cir.ptr<!u64i>
228+
// CHECK: cir.store align(8) %[[#NUM_ELEMENTS]], %[[COOKIE_PTR]] : !u64i, !cir.ptr<!u64i>
229+
// CHECK: %[[#COOKIE_SIZE:]] = cir.const #cir.int<8> : !s32i
230+
// CHECK: %[[DATA_PTR_RAW:.*]] = cir.ptr_stride %[[COOKIE_PTR_BASE]], %[[#COOKIE_SIZE]] : (!cir.ptr<!cir.ptr<!u8i>>, !s32i) -> !cir.ptr<!cir.ptr<!u8i>>
231+
// CHECK: %[[DATA_PTR_VOID:.*]] = cir.cast bitcast %[[DATA_PTR_RAW]] : !cir.ptr<!cir.ptr<!u8i>> -> !cir.ptr<!void>
232+
// CHECK: %[[DATA_PTR:.*]] = cir.cast bitcast %[[DATA_PTR_VOID]] : !cir.ptr<!void> -> !cir.ptr<!rec_C>
233+
// CHECK: cir.store align(8) %[[DATA_PTR]], %[[P_ADDR]] : !cir.ptr<!rec_C>, !cir.ptr<!cir.ptr<!rec_C>>
234+
// CHECK: cir.return
235+
// CHECK: }
236+
237+
// LLVM: @_Z26t_constant_size_nontrivialv()
238+
// LLVM: %[[ALLOCA:.*]] = alloca ptr, i64 1, align 8
239+
// LLVM: %[[COOKIE_PTR:.*]] = call ptr @_Znam(i64 11)
240+
// LLVM: store i64 3, ptr %[[COOKIE_PTR]], align 8
241+
// LLVM: %[[ALLOCATED_PTR:.*]] = getelementptr ptr, ptr %[[COOKIE_PTR]], i64 8
242+
// LLVM: store ptr %[[ALLOCATED_PTR]], ptr %[[ALLOCA]], align 8
243+
244+
// OGCG: @_Z26t_constant_size_nontrivialv()
245+
// OGCG: %[[ALLOCA:.*]] = alloca ptr, align 8
246+
// OGCG: %[[COOKIE_PTR:.*]] = call noalias noundef nonnull ptr @_Znam(i64 noundef 11)
247+
// OGCG: store i64 3, ptr %[[COOKIE_PTR]], align 8
248+
// OGCG: %[[ALLOCATED_PTR:.*]] = getelementptr inbounds i8, ptr %[[COOKIE_PTR]], i64 8
249+
// OGCG: store ptr %[[ALLOCATED_PTR]], ptr %[[ALLOCA]], align 8
250+
251+
class D {
252+
public:
253+
int x;
254+
~D();
255+
};
256+
257+
void t_constant_size_nontrivial2() {
258+
auto p = new D[3];
259+
}
260+
261+
// In this test SIZE_WITHOUT_COOKIE isn't used, but it would be if there were
262+
// an initializer.
263+
264+
// CHECK: cir.func{{.*}} @_Z27t_constant_size_nontrivial2v()
265+
// CHECK: %[[P_ADDR:.*]] = cir.alloca !cir.ptr<!rec_D>, !cir.ptr<!cir.ptr<!rec_D>>, ["p", init] {alignment = 8 : i64}
266+
// CHECK: %[[#NUM_ELEMENTS:]] = cir.const #cir.int<3> : !u64i
267+
// CHECK: %[[#SIZE_WITHOUT_COOKIE:]] = cir.const #cir.int<12> : !u64i
268+
// CHECK: %[[#ALLOCATION_SIZE:]] = cir.const #cir.int<20> : !u64i
269+
// CHECK: %[[RAW_PTR:.*]] = cir.call @_Znam(%[[#ALLOCATION_SIZE]]) : (!u64i) -> !cir.ptr<!void>
270+
// CHECK: %[[COOKIE_PTR_BASE:.*]] = cir.cast bitcast %[[RAW_PTR]] : !cir.ptr<!void> -> !cir.ptr<!cir.ptr<!u8i>>
271+
// CHECK: %[[COOKIE_PTR:.*]] = cir.cast bitcast %[[COOKIE_PTR_BASE]] : !cir.ptr<!cir.ptr<!u8i>> -> !cir.ptr<!u64i>
272+
// CHECK: cir.store align(8) %[[#NUM_ELEMENTS]], %[[COOKIE_PTR]] : !u64i, !cir.ptr<!u64i>
273+
// CHECK: %[[#COOKIE_SIZE:]] = cir.const #cir.int<8> : !s32i
274+
// CHECK: %[[DATA_PTR_RAW:.*]] = cir.ptr_stride %[[COOKIE_PTR_BASE]], %[[#COOKIE_SIZE]] : (!cir.ptr<!cir.ptr<!u8i>>, !s32i) -> !cir.ptr<!cir.ptr<!u8i>>
275+
// CHECK: %[[DATA_PTR_VOID:.*]] = cir.cast bitcast %[[DATA_PTR_RAW]] : !cir.ptr<!cir.ptr<!u8i>> -> !cir.ptr<!void>
276+
// CHECK: %[[DATA_PTR:.*]] = cir.cast bitcast %[[DATA_PTR_VOID]] : !cir.ptr<!void> -> !cir.ptr<!rec_D>
277+
// CHECK: cir.store align(8) %[[DATA_PTR]], %[[P_ADDR]] : !cir.ptr<!rec_D>, !cir.ptr<!cir.ptr<!rec_D>>
278+
// CHECK: cir.return
279+
// CHECK: }
280+
281+
// LLVM: @_Z27t_constant_size_nontrivial2v()
282+
// LLVM: %[[ALLOCA:.*]] = alloca ptr, i64 1, align 8
283+
// LLVM: %[[COOKIE_PTR:.*]] = call ptr @_Znam(i64 20)
284+
// LLVM: store i64 3, ptr %[[COOKIE_PTR]], align 8
285+
// LLVM: %[[ALLOCATED_PTR:.*]] = getelementptr ptr, ptr %[[COOKIE_PTR]], i64 8
286+
// LLVM: store ptr %[[ALLOCATED_PTR]], ptr %[[ALLOCA]], align 8
287+
288+
struct alignas(16) E {
289+
int x;
290+
~E();
291+
};
292+
293+
void t_align16_nontrivial() {
294+
auto p = new E[2];
295+
}
296+
297+
// CHECK: cir.func{{.*}} @_Z20t_align16_nontrivialv()
298+
// CHECK: %[[P_ADDR:.*]] = cir.alloca !cir.ptr<!rec_E>, !cir.ptr<!cir.ptr<!rec_E>>, ["p", init] {alignment = 8 : i64}
299+
// CHECK: %[[#NUM_ELEMENTS:]] = cir.const #cir.int<2> : !u64i
300+
// CHECK: %[[#SIZE_WITHOUT_COOKIE:]] = cir.const #cir.int<32> : !u64i
301+
// CHECK: %[[#ALLOCATION_SIZE:]] = cir.const #cir.int<48> : !u64i
302+
// CHECK: %[[RAW_PTR:.*]] = cir.call @_Znam(%[[#ALLOCATION_SIZE]]) : (!u64i) -> !cir.ptr<!void>
303+
// CHECK: %[[COOKIE_PTR_BASE:.*]] = cir.cast bitcast %[[RAW_PTR]] : !cir.ptr<!void> -> !cir.ptr<!cir.ptr<!u8i>>
304+
// CHECK: %[[COOKIE_OFFSET:.*]] = cir.const #cir.int<8> : !s32i
305+
// CHECK: %[[COOKIE_PTR_RAW:.*]] = cir.ptr_stride %[[COOKIE_PTR_BASE]], %[[COOKIE_OFFSET]] : (!cir.ptr<!cir.ptr<!u8i>>, !s32i) -> !cir.ptr<!cir.ptr<!u8i>>
306+
// CHECK: %[[COOKIE_PTR:.*]] = cir.cast bitcast %[[COOKIE_PTR_RAW]] : !cir.ptr<!cir.ptr<!u8i>> -> !cir.ptr<!u64i>
307+
// CHECK: cir.store align(8) %[[#NUM_ELEMENTS]], %[[COOKIE_PTR]] : !u64i, !cir.ptr<!u64i>
308+
// CHECK: %[[#COOKIE_SIZE:]] = cir.const #cir.int<16> : !s32i
309+
// CHECK: %[[DATA_PTR_RAW:.*]] = cir.ptr_stride %[[COOKIE_PTR_BASE]], %[[#COOKIE_SIZE]] : (!cir.ptr<!cir.ptr<!u8i>>, !s32i) -> !cir.ptr<!cir.ptr<!u8i>>
310+
// CHECK: %[[DATA_PTR_VOID:.*]] = cir.cast bitcast %[[DATA_PTR_RAW]] : !cir.ptr<!cir.ptr<!u8i>> -> !cir.ptr<!void>
311+
// CHECK: %[[DATA_PTR:.*]] = cir.cast bitcast %[[DATA_PTR_VOID]] : !cir.ptr<!void> -> !cir.ptr<!rec_E>
312+
// CHECK: cir.store align(8) %[[DATA_PTR]], %[[P_ADDR]] : !cir.ptr<!rec_E>, !cir.ptr<!cir.ptr<!rec_E>>
313+
// CHECK: cir.return
314+
// CHECK: }
315+
316+
// LLVM: @_Z20t_align16_nontrivialv()
317+
// LLVM: %[[ALLOCA:.*]] = alloca ptr, i64 1, align 8
318+
// LLVM: %[[RAW_PTR:.*]] = call ptr @_Znam(i64 48)
319+
// LLVM: %[[COOKIE_PTR:.*]] = getelementptr ptr, ptr %[[RAW_PTR]], i64 8
320+
// LLVM: store i64 2, ptr %[[COOKIE_PTR]], align 8
321+
// LLVM: %[[ALLOCATED_PTR:.*]] = getelementptr ptr, ptr %[[RAW_PTR]], i64 16
322+
// LLVM: store ptr %[[ALLOCATED_PTR]], ptr %[[ALLOCA]], align 8
323+
324+
// OGCG: @_Z27t_constant_size_nontrivial2v()
325+
// OGCG: %[[ALLOCA:.*]] = alloca ptr, align 8
326+
// OGCG: %[[COOKIE_PTR:.*]] = call noalias noundef nonnull ptr @_Znam(i64 noundef 20)
327+
// OGCG: store i64 3, ptr %[[COOKIE_PTR]], align 8
328+
// OGCG: %[[ALLOCATED_PTR:.*]] = getelementptr inbounds i8, ptr %[[COOKIE_PTR]], i64 8
329+
// OGCG: store ptr %[[ALLOCATED_PTR]], ptr %[[ALLOCA]], align 8
211330

212331
void t_new_multidim_constant_size() {
213332
auto p = new double[2][3][4];

0 commit comments

Comments
 (0)