Skip to content

Commit f8821e8

Browse files
authored
[CIR] Implement partial initialization for array new (#1307)
This implements CIR generation for the case where an array is allocated with array new and a partial initialization list is provided.
1 parent 7c22251 commit f8821e8

File tree

3 files changed

+70
-2
lines changed

3 files changed

+70
-2
lines changed

clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp

+26-2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13+
#include "clang/AST/CharUnits.h"
1314
#include "clang/CIR/Dialect/IR/CIRAttrs.h"
1415
#include "clang/CIR/MissingFeatures.h"
1516
#include <CIRGenCXXABI.h>
@@ -876,6 +877,7 @@ void CIRGenFunction::emitNewArrayInitializer(
876877
unsigned InitListElements = 0;
877878

878879
const Expr *Init = E->getInitializer();
880+
Address EndOfInit = Address::invalid();
879881
QualType::DestructionKind DtorKind = ElementType.isDestructedType();
880882
CleanupDeactivationScope deactivation(*this);
881883

@@ -898,7 +900,13 @@ void CIRGenFunction::emitNewArrayInitializer(
898900
// Subtract out the size of any elements we've already initialized.
899901
auto RemainingSize = AllocSizeWithoutCookie;
900902
if (InitListElements) {
901-
llvm_unreachable("NYI");
903+
// We know this can't overflow; we check this when doing the allocation.
904+
unsigned InitializedSize =
905+
getContext().getTypeSizeInChars(ElementType).getQuantity() *
906+
InitListElements;
907+
auto InitSizeOp =
908+
builder.getConstInt(Loc, RemainingSize.getType(), InitializedSize);
909+
RemainingSize = builder.createSub(RemainingSize, InitSizeOp);
902910
}
903911

904912
// Create the memset.
@@ -946,8 +954,24 @@ void CIRGenFunction::emitNewArrayInitializer(
946954
}
947955

948956
CharUnits StartAlign = CurPtr.getAlignment();
957+
unsigned i = 0;
949958
for (const Expr *IE : InitExprs) {
950-
llvm_unreachable("NYI");
959+
if (EndOfInit.isValid()) {
960+
// This will involve DTor handling.
961+
llvm_unreachable("NYI");
962+
}
963+
// FIXME: If the last initializer is an incomplete initializer list for
964+
// an array, and we have an array filler, we can fold together the two
965+
// initialization loops.
966+
StoreAnyExprIntoOneUnit(*this, IE, IE->getType(), CurPtr,
967+
AggValueSlot::DoesNotOverlap);
968+
auto Loc = getLoc(IE->getExprLoc());
969+
auto CastOp = builder.createPtrBitcast(CurPtr.getPointer(),
970+
convertTypeForMem(AllocType));
971+
auto OffsetOp = builder.getSignedInt(Loc, 1, /*width=*/32);
972+
auto DataPtr = builder.createPtrStride(Loc, CastOp, OffsetOp);
973+
CurPtr = Address(DataPtr, CurPtr.getType(),
974+
StartAlign.alignmentAtOffset((++i) * ElementSize));
951975
}
952976

953977
// The remaining elements are filled with the array filler expression.

clang/test/CIR/CodeGen/new.cpp

+28
Original file line numberDiff line numberDiff line change
@@ -161,3 +161,31 @@ void t_constant_size_memset_init() {
161161
// CHECK: %[[#ZERO:]] = cir.const #cir.int<0> : !u8i
162162
// CHECK: %[[#ZERO_I32:]] = cir.cast(integral, %[[#ZERO]] : !u8i), !s32i
163163
// CHECK: cir.libc.memset %[[#ALLOCATION_SIZE]] bytes from %[[#VOID_PTR]] set to %[[#ZERO_I32]] : !cir.ptr<!void>, !s32i, !u64i
164+
165+
void t_constant_size_partial_init() {
166+
auto p = new int[16] { 1, 2, 3 };
167+
}
168+
169+
// CHECK: cir.func @_Z28t_constant_size_partial_initv()
170+
// CHECK: %[[#NUM_ELEMENTS:]] = cir.const #cir.int<16> : !u64i
171+
// CHECK: %[[#ALLOCATION_SIZE:]] = cir.const #cir.int<64> : !u64i
172+
// CHECK: %[[#ALLOC_PTR:]] = cir.call @_Znam(%[[#ALLOCATION_SIZE]]) : (!u64i) -> !cir.ptr<!void>
173+
// CHECK: %[[#ELEM_0_PTR:]] = cir.cast(bitcast, %[[#ALLOC_PTR]] : !cir.ptr<!void>), !cir.ptr<!s32i>
174+
// CHECK: %[[#CONST_ONE:]] = cir.const #cir.int<1> : !s32i
175+
// CHECK: cir.store %[[#CONST_ONE]], %[[#ELEM_0_PTR]] : !s32i, !cir.ptr<!s32i>
176+
// CHECK: %[[#OFFSET:]] = cir.const #cir.int<1> : !s32i
177+
// CHECK: %[[#ELEM_1_PTR:]] = cir.ptr_stride(%[[#ELEM_0_PTR]] : !cir.ptr<!s32i>, %[[#OFFSET]] : !s32i), !cir.ptr<!s32i>
178+
// CHECK: %[[#CONST_TWO:]] = cir.const #cir.int<2> : !s32i
179+
// CHECK: cir.store %[[#CONST_TWO]], %[[#ELEM_1_PTR]] : !s32i, !cir.ptr<!s32i>
180+
// CHECK: %[[#OFFSET1:]] = cir.const #cir.int<1> : !s32i
181+
// CHECK: %[[#ELEM_2_PTR:]] = cir.ptr_stride(%[[#ELEM_1_PTR]] : !cir.ptr<!s32i>, %[[#OFFSET1]] : !s32i), !cir.ptr<!s32i>
182+
// CHECK: %[[#CONST_THREE:]] = cir.const #cir.int<3> : !s32i
183+
// CHECK: cir.store %[[#CONST_THREE]], %[[#ELEM_2_PTR]] : !s32i, !cir.ptr<!s32i>
184+
// CHECK: %[[#OFFSET2:]] = cir.const #cir.int<1> : !s32i
185+
// CHECK: %[[#ELEM_3_PTR:]] = cir.ptr_stride(%[[#ELEM_2_PTR]] : !cir.ptr<!s32i>, %[[#OFFSET2]] : !s32i), !cir.ptr<!s32i>
186+
// CHECK: %[[#INIT_SIZE:]] = cir.const #cir.int<12> : !u64i
187+
// CHECK: %[[#REMAINING_SIZE:]] = cir.binop(sub, %[[#ALLOCATION_SIZE]], %[[#INIT_SIZE]]) : !u64i
188+
// CHECK: %[[#VOID_PTR:]] = cir.cast(bitcast, %[[#ELEM_3_PTR]] : !cir.ptr<!s32i>), !cir.ptr<!void>
189+
// CHECK: %[[#ZERO:]] = cir.const #cir.int<0> : !u8i
190+
// CHECK: %[[#ZERO_I32:]] = cir.cast(integral, %[[#ZERO]] : !u8i), !s32i
191+
// CHECK: cir.libc.memset %[[#REMAINING_SIZE]] bytes from %[[#VOID_PTR]] set to %[[#ZERO_I32]] : !cir.ptr<!void>, !s32i, !u64i

clang/test/CIR/Lowering/new.cpp

+16
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,19 @@ void t_constant_size_memset_init() {
6767
// LLVM: %[[ADDR:.*]] = call ptr @_Znam(i64 64)
6868
// LLVM: call void @llvm.memset.p0.i64(ptr %[[ADDR]], i8 0, i64 64, i1 false)
6969
// LLVM: store ptr %[[ADDR]], ptr %[[ALLOCA]], align 8
70+
71+
void t_constant_size_partial_init() {
72+
auto p = new int[16] { 1, 2, 3 };
73+
}
74+
75+
// LLVM: @_Z28t_constant_size_partial_initv()
76+
// LLVM: %[[ALLOCA:.*]] = alloca ptr, i64 1, align 8
77+
// LLVM: %[[ADDR:.*]] = call ptr @_Znam(i64 64)
78+
// LLVM: store i32 1, ptr %[[ADDR]], align 4
79+
// LLVM: %[[ELEM_1_PTR:.*]] = getelementptr i32, ptr %[[ADDR]], i64 1
80+
// LLVM: store i32 2, ptr %[[ELEM_1_PTR]], align 4
81+
// LLVM: %[[ELEM_2_PTR:.*]] = getelementptr i32, ptr %[[ELEM_1_PTR]], i64 1
82+
// LLVM: store i32 3, ptr %[[ELEM_2_PTR]], align 4
83+
// LLVM: %[[ELEM_3_PTR:.*]] = getelementptr i32, ptr %[[ELEM_2_PTR]], i64 1
84+
// LLVM: call void @llvm.memset.p0.i64(ptr %[[ELEM_3_PTR]], i8 0, i64 52, i1 false)
85+
// LLVM: store ptr %[[ADDR]], ptr %[[ALLOCA]], align 8

0 commit comments

Comments
 (0)