diff --git a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp index af0bb71366b9..15dc33f2df64 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp @@ -10,6 +10,7 @@ // //===----------------------------------------------------------------------===// +#include "clang/AST/CharUnits.h" #include "clang/CIR/Dialect/IR/CIRAttrs.h" #include "clang/CIR/MissingFeatures.h" #include @@ -876,6 +877,7 @@ void CIRGenFunction::emitNewArrayInitializer( unsigned InitListElements = 0; const Expr *Init = E->getInitializer(); + Address EndOfInit = Address::invalid(); QualType::DestructionKind DtorKind = ElementType.isDestructedType(); CleanupDeactivationScope deactivation(*this); @@ -898,7 +900,13 @@ void CIRGenFunction::emitNewArrayInitializer( // Subtract out the size of any elements we've already initialized. auto RemainingSize = AllocSizeWithoutCookie; if (InitListElements) { - llvm_unreachable("NYI"); + // We know this can't overflow; we check this when doing the allocation. + unsigned InitializedSize = + getContext().getTypeSizeInChars(ElementType).getQuantity() * + InitListElements; + auto InitSizeOp = + builder.getConstInt(Loc, RemainingSize.getType(), InitializedSize); + RemainingSize = builder.createSub(RemainingSize, InitSizeOp); } // Create the memset. @@ -946,8 +954,24 @@ void CIRGenFunction::emitNewArrayInitializer( } CharUnits StartAlign = CurPtr.getAlignment(); + unsigned i = 0; for (const Expr *IE : InitExprs) { - llvm_unreachable("NYI"); + if (EndOfInit.isValid()) { + // This will involve DTor handling. + llvm_unreachable("NYI"); + } + // FIXME: If the last initializer is an incomplete initializer list for + // an array, and we have an array filler, we can fold together the two + // initialization loops. + StoreAnyExprIntoOneUnit(*this, IE, IE->getType(), CurPtr, + AggValueSlot::DoesNotOverlap); + auto Loc = getLoc(IE->getExprLoc()); + auto CastOp = builder.createPtrBitcast(CurPtr.getPointer(), + convertTypeForMem(AllocType)); + auto OffsetOp = builder.getSignedInt(Loc, 1, /*width=*/32); + auto DataPtr = builder.createPtrStride(Loc, CastOp, OffsetOp); + CurPtr = Address(DataPtr, CurPtr.getType(), + StartAlign.alignmentAtOffset((++i) * ElementSize)); } // The remaining elements are filled with the array filler expression. diff --git a/clang/test/CIR/CodeGen/new.cpp b/clang/test/CIR/CodeGen/new.cpp index 9134018d8673..2750929832e0 100644 --- a/clang/test/CIR/CodeGen/new.cpp +++ b/clang/test/CIR/CodeGen/new.cpp @@ -161,3 +161,31 @@ void t_constant_size_memset_init() { // CHECK: %[[#ZERO:]] = cir.const #cir.int<0> : !u8i // CHECK: %[[#ZERO_I32:]] = cir.cast(integral, %[[#ZERO]] : !u8i), !s32i // CHECK: cir.libc.memset %[[#ALLOCATION_SIZE]] bytes from %[[#VOID_PTR]] set to %[[#ZERO_I32]] : !cir.ptr, !s32i, !u64i + +void t_constant_size_partial_init() { + auto p = new int[16] { 1, 2, 3 }; +} + +// CHECK: cir.func @_Z28t_constant_size_partial_initv() +// CHECK: %[[#NUM_ELEMENTS:]] = cir.const #cir.int<16> : !u64i +// CHECK: %[[#ALLOCATION_SIZE:]] = cir.const #cir.int<64> : !u64i +// CHECK: %[[#ALLOC_PTR:]] = cir.call @_Znam(%[[#ALLOCATION_SIZE]]) : (!u64i) -> !cir.ptr +// CHECK: %[[#ELEM_0_PTR:]] = cir.cast(bitcast, %[[#ALLOC_PTR]] : !cir.ptr), !cir.ptr +// CHECK: %[[#CONST_ONE:]] = cir.const #cir.int<1> : !s32i +// CHECK: cir.store %[[#CONST_ONE]], %[[#ELEM_0_PTR]] : !s32i, !cir.ptr +// CHECK: %[[#OFFSET:]] = cir.const #cir.int<1> : !s32i +// CHECK: %[[#ELEM_1_PTR:]] = cir.ptr_stride(%[[#ELEM_0_PTR]] : !cir.ptr, %[[#OFFSET]] : !s32i), !cir.ptr +// CHECK: %[[#CONST_TWO:]] = cir.const #cir.int<2> : !s32i +// CHECK: cir.store %[[#CONST_TWO]], %[[#ELEM_1_PTR]] : !s32i, !cir.ptr +// CHECK: %[[#OFFSET1:]] = cir.const #cir.int<1> : !s32i +// CHECK: %[[#ELEM_2_PTR:]] = cir.ptr_stride(%[[#ELEM_1_PTR]] : !cir.ptr, %[[#OFFSET1]] : !s32i), !cir.ptr +// CHECK: %[[#CONST_THREE:]] = cir.const #cir.int<3> : !s32i +// CHECK: cir.store %[[#CONST_THREE]], %[[#ELEM_2_PTR]] : !s32i, !cir.ptr +// CHECK: %[[#OFFSET2:]] = cir.const #cir.int<1> : !s32i +// CHECK: %[[#ELEM_3_PTR:]] = cir.ptr_stride(%[[#ELEM_2_PTR]] : !cir.ptr, %[[#OFFSET2]] : !s32i), !cir.ptr +// CHECK: %[[#INIT_SIZE:]] = cir.const #cir.int<12> : !u64i +// CHECK: %[[#REMAINING_SIZE:]] = cir.binop(sub, %[[#ALLOCATION_SIZE]], %[[#INIT_SIZE]]) : !u64i +// CHECK: %[[#VOID_PTR:]] = cir.cast(bitcast, %[[#ELEM_3_PTR]] : !cir.ptr), !cir.ptr +// CHECK: %[[#ZERO:]] = cir.const #cir.int<0> : !u8i +// CHECK: %[[#ZERO_I32:]] = cir.cast(integral, %[[#ZERO]] : !u8i), !s32i +// CHECK: cir.libc.memset %[[#REMAINING_SIZE]] bytes from %[[#VOID_PTR]] set to %[[#ZERO_I32]] : !cir.ptr, !s32i, !u64i diff --git a/clang/test/CIR/Lowering/new.cpp b/clang/test/CIR/Lowering/new.cpp index c4c12531a6b7..bff825323e9e 100644 --- a/clang/test/CIR/Lowering/new.cpp +++ b/clang/test/CIR/Lowering/new.cpp @@ -67,3 +67,19 @@ void t_constant_size_memset_init() { // LLVM: %[[ADDR:.*]] = call ptr @_Znam(i64 64) // LLVM: call void @llvm.memset.p0.i64(ptr %[[ADDR]], i8 0, i64 64, i1 false) // LLVM: store ptr %[[ADDR]], ptr %[[ALLOCA]], align 8 + +void t_constant_size_partial_init() { + auto p = new int[16] { 1, 2, 3 }; +} + +// LLVM: @_Z28t_constant_size_partial_initv() +// LLVM: %[[ALLOCA:.*]] = alloca ptr, i64 1, align 8 +// LLVM: %[[ADDR:.*]] = call ptr @_Znam(i64 64) +// LLVM: store i32 1, ptr %[[ADDR]], align 4 +// LLVM: %[[ELEM_1_PTR:.*]] = getelementptr i32, ptr %[[ADDR]], i64 1 +// LLVM: store i32 2, ptr %[[ELEM_1_PTR]], align 4 +// LLVM: %[[ELEM_2_PTR:.*]] = getelementptr i32, ptr %[[ELEM_1_PTR]], i64 1 +// LLVM: store i32 3, ptr %[[ELEM_2_PTR]], align 4 +// LLVM: %[[ELEM_3_PTR:.*]] = getelementptr i32, ptr %[[ELEM_2_PTR]], i64 1 +// LLVM: call void @llvm.memset.p0.i64(ptr %[[ELEM_3_PTR]], i8 0, i64 52, i1 false) +// LLVM: store ptr %[[ADDR]], ptr %[[ALLOCA]], align 8