Author: Andy Kaylor Date: 2026-03-19T08:55:10-07:00 New Revision: b7776ccebe9d97a30160b29623a2d0691572b789
URL: https://github.com/llvm/llvm-project/commit/b7776ccebe9d97a30160b29623a2d0691572b789 DIFF: https://github.com/llvm/llvm-project/commit/b7776ccebe9d97a30160b29623a2d0691572b789.diff LOG: [CIR] Add support for array new with ctor init (#187418) This adds support for array new initialization that requires calling constructors. This diverges a bit from the classic codegen implementation in a couple of ways. First, we use the cir.array_ctor operation to represent all the constructor calls that weren't part of an explicit initializer list. This gets lowered to a loop during the LoweringPrepare pass. Second, because CIR uses more explicit types, we have to insert a bitcast of the array pointer to an explicit array type. Third, when an initializer list is provided and we are calling constructors for the "filler" portion of the list, we attempt to get the array size as a constant and create a "tail array" to initialize that is sized to the number of elements remaining. Added: Modified: clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp clang/test/CIR/CodeGen/new.cpp Removed: ################################################################################ diff --git a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp index e565b029da9df..03298faf79ce3 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp @@ -1046,8 +1046,52 @@ void CIRGenFunction::emitNewArrayInitializer( return; } - cgm.errorNYI(cce->getSourceRange(), - "emitNewArrayInitializer: ctor initializer"); + // Store the new Cleanup position for irregular Cleanups. + // + // FIXME: Share this cleanup with the constructor call emission rather than + // having it create a cleanup of its own. + if (endOfInit.isValid()) + builder.createStore(getLoc(e->getSourceRange()), curPtr.emitRawPointer(), + endOfInit); + + mlir::Type initType = convertType(cce->getType()); + // Emit a constructor call loop to initialize the remaining elements. + if (initListElements) { + // If the number of elements is a constant, we will have already gotten + // the constant op above. Here we use it to get the number of remaining + // elements as a new constant. + if (constOp) { + auto constIntAttr = mlir::cast<cir::IntAttr>(constOp.getValue()); + uint64_t numRemainingElements = + constIntAttr.getUInt() - initListElements; + numElements = + builder.getConstInt(getLoc(e->getSourceRange()), + numElements.getType(), numRemainingElements); + // Currently, the AST gives us a pointer to the element type here + // rather than an array. That's inconsistent with what it does + // without an explicit initializer list, so we need to create an + // array type here. That will decay back to a pointer when we lower + // the cir.array.ctor op, but we need an array type for the initial + // representation. + if (!mlir::isa<cir::ArrayType>(initType)) + initType = cir::ArrayType::get(initType, numRemainingElements); + } else { + cgm.errorNYI(e->getSourceRange(), + "emitNewArrayInitializer: numRemainingElements with " + "non-constant count"); + return; + } + } + + curPtr = curPtr.withElementType(builder, initType); + emitCXXAggrConstructorCall(ctor, numElements, curPtr, cce, + /*newPointerIsChecked=*/true, + cce->requiresZeroInitialization()); + if (getContext().getTargetInfo().emitVectorDeletingDtors( + getContext().getLangOpts())) { + cgm.errorNYI(e->getSourceRange(), + "emitNewArrayInitializer: emitVectorDeletingDtors"); + } return; } diff --git a/clang/test/CIR/CodeGen/new.cpp b/clang/test/CIR/CodeGen/new.cpp index f66e239186fb6..1062b5867d0d6 100644 --- a/clang/test/CIR/CodeGen/new.cpp +++ b/clang/test/CIR/CodeGen/new.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir -mmlir --mlir-print-ir-before=cir-lowering-prepare %s -o %t.cir 2> %t-before.cir +// RUN: FileCheck --check-prefixes=CIR-BEFORE-LPP --input-file=%t-before.cir %s // RUN: FileCheck --input-file=%t.cir %s // RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll // RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s @@ -722,3 +723,192 @@ void t_new_var_size_nontrivial(size_t n) { // OGCG: %[[ELEMENT_SIZE:.*]] = extractvalue { i64, i1 } %[[ADD_OVERFLOW]], 0 // OGCG: %[[ALLOC_SIZE:.*]] = select i1 %[[ANY_OVERFLOW]], i64 -1, i64 %[[ELEMENT_SIZE]] // OGCG: %[[PTR:.*]] = call {{.*}} ptr @_Znam(i64 {{.*}} %[[ALLOC_SIZE]]) + +class F { +public: + F(); +}; + +void test_array_new_with_ctor_init() { + auto p = new F[3]; +} + +// CIR-BEFORE-LPP: cir.func {{.*}} @_Z29test_array_new_with_ctor_initv +// CIR-BEFORE-LPP: %[[P_ADDR:.*]] = cir.alloca !cir.ptr<!rec_F>, !cir.ptr<!cir.ptr<!rec_F>>, ["p", init] +// CIR-BEFORE-LPP: %[[THREE:.*]] = cir.const #cir.int<3> : !u64i +// CIR-BEFORE-LPP: %[[RAW_PTR:.*]] = cir.call @_Znam(%[[THREE]]) {allocsize = array<i32: 0>, builtin} : (!u64i {llvm.noundef}) +// CIR-BEFORE-LPP: %[[BEGIN:.*]] = cir.cast bitcast %[[RAW_PTR]] : !cir.ptr<!void> -> !cir.ptr<!rec_F> +// CIR-BEFORE-LPP: %[[ARRAY_PTR:.*]] = cir.cast bitcast %[[BEGIN]] : !cir.ptr<!rec_F> -> !cir.ptr<!cir.array<!rec_F x 3>> +// CIR-BEFORE-LPP: cir.array.ctor %[[ARRAY_PTR]] : !cir.ptr<!cir.array<!rec_F x 3>> { +// CIR-BEFORE-LPP: ^bb0(%[[ARG:.*]]: !cir.ptr<!rec_F>): +// CIR-BEFORE-LPP: cir.call @_ZN1FC1Ev(%[[ARG]]) : (!cir.ptr<!rec_F> {{.*}}) -> () +// CIR-BEFORE-LPP: cir.yield +// CIR-BEFORE-LPP: } +// CIR-BEFORE-LPP: cir.store{{.*}} %[[BEGIN]], %[[P_ADDR]] : !cir.ptr<!rec_F>, !cir.ptr<!cir.ptr<!rec_F>> +// CIR-BEFORE-LPP: cir.return + +// CHECK: cir.func {{.*}} @_Z29test_array_new_with_ctor_initv +// CHECK: %[[P_ADDR:.*]] = cir.alloca !cir.ptr<!rec_F>, !cir.ptr<!cir.ptr<!rec_F>>, ["p", init] +// CHECK: %[[THREE:.*]] = cir.const #cir.int<3> : !u64i +// CHECK: %[[RAW_PTR:.*]] = cir.call @_Znam(%[[THREE]]) {allocsize = array<i32: 0>, builtin} : (!u64i {llvm.noundef}) +// CHECK: %[[BEGIN:.*]] = cir.cast bitcast %[[RAW_PTR]] : !cir.ptr<!void> -> !cir.ptr<!rec_F> +// CHECK: %[[ARRAY_PTR:.*]] = cir.cast bitcast %[[BEGIN]] : !cir.ptr<!rec_F> -> !cir.ptr<!cir.array<!rec_F x 3>> +// CHECK: %[[THREE_2:.*]] = cir.const #cir.int<3> : !u64i +// CHECK: %[[ARRAY_BEGIN:.*]] = cir.cast array_to_ptrdecay %[[ARRAY_PTR]] : !cir.ptr<!cir.array<!rec_F x 3>> -> !cir.ptr<!rec_F> +// CHECK: %[[ARRAY_END:.*]] = cir.ptr_stride %[[ARRAY_BEGIN]], %[[THREE_2]] : (!cir.ptr<!rec_F>, !u64i) -> !cir.ptr<!rec_F> +// CHECK: %[[IDX_ADDR:.*]] = cir.alloca !cir.ptr<!rec_F>, !cir.ptr<!cir.ptr<!rec_F>>, ["__array_idx"] {alignment = 1 : i64} +// CHECK: cir.store %[[ARRAY_BEGIN]], %[[IDX_ADDR]] : !cir.ptr<!rec_F>, !cir.ptr<!cir.ptr<!rec_F>> +// CHECK: cir.do { +// CHECK: %[[CUR:.*]] = cir.load %[[IDX_ADDR]] : !cir.ptr<!cir.ptr<!rec_F>>, !cir.ptr<!rec_F> +// CHECK: cir.call @_ZN1FC1Ev(%[[CUR]]) : (!cir.ptr<!rec_F> {llvm.align = 1 : i64, llvm.dereferenceable = 1 : i64, llvm.nonnull, llvm.noundef}) -> () +// CHECK: %[[ONE:.*]] = cir.const #cir.int<1> : !u64i +// CHECK: %[[NEXT:.*]] = cir.ptr_stride %[[CUR]], %[[ONE]] : (!cir.ptr<!rec_F>, !u64i) -> !cir.ptr<!rec_F> +// CHECK: cir.store %[[NEXT]], %[[IDX_ADDR]] : !cir.ptr<!rec_F>, !cir.ptr<!cir.ptr<!rec_F>> +// CHECK: cir.yield +// CHECK: } while { +// CHECK: %[[CUR2:.*]] = cir.load %[[IDX_ADDR]] : !cir.ptr<!cir.ptr<!rec_F>>, !cir.ptr<!rec_F> +// CHECK: %[[CMP:.*]] = cir.cmp ne %[[CUR2]], %[[ARRAY_END]] : !cir.ptr<!rec_F> +// CHECK: cir.condition(%[[CMP]]) +// CHECK: } +// CHECK: cir.store{{.*}} %[[BEGIN]], %[[P_ADDR]] +// CHECK: cir.return + +// LLVM: define{{.*}} void @_Z29test_array_new_with_ctor_initv +// LLVM: %[[P_ADDR:.*]] = alloca ptr, i64 1, align 8 +// LLVM: %[[RAW_PTR:.*]] = call noundef ptr @_Znam(i64 noundef 3) +// LLVM: %[[BEGIN:.*]] = getelementptr %class.F, ptr %[[RAW_PTR]], i32 0 +// LLVM: %[[ARRAY_END:.*]] = getelementptr %class.F, ptr %[[BEGIN]], i64 3 +// LLVM: %[[IDX_ADDR:.*]] = alloca ptr, i64 1, align 1 +// LLVM: store ptr %[[BEGIN]], ptr %[[IDX_ADDR]], align 8 +// LLVM: br label +// LLVM: %[[CUR2:.*]] = load ptr, ptr %[[IDX_ADDR]], align 8 +// LLVM: %[[CMP:.*]] = icmp ne ptr %[[CUR2]], %[[ARRAY_END]] +// LLVM: br i1 %[[CMP]], label +// LLVM: %[[CUR:.*]] = load ptr, ptr %[[IDX_ADDR]], align 8 +// LLVM: call void @_ZN1FC1Ev(ptr noundef nonnull align 1 dereferenceable(1) %[[CUR]]) +// LLVM: %[[NEXT:.*]] = getelementptr %class.F, ptr %[[CUR]], i64 1 +// LLVM: store ptr %[[NEXT]], ptr %[[IDX_ADDR]], align 8 +// LLVM: br label +// LLVM: store ptr %[[RAW_PTR]], ptr %[[P_ADDR]], align 8 +// LLVM: ret void + +// OGCG: define{{.*}} void @_Z29test_array_new_with_ctor_initv +// OGCG: %[[P_ADDR:.*]] = alloca ptr, align 8 +// OGCG: %[[RAW_PTR:.*]] = call{{.*}} ptr @_Znam(i64 noundef 3) +// OGCG: %[[ARRAY_END:.*]] = getelementptr inbounds %class.F, ptr %[[RAW_PTR]], i64 3 +// OGCG: br label +// OGCG: %[[CUR:.*]] = phi ptr [ %[[RAW_PTR]], {{.*}} ], [ %[[NEXT:.*]], {{.*}} ] +// OGCG: call void @_ZN1FC1Ev(ptr noundef nonnull align 1 dereferenceable(1) %[[CUR]]) +// OGCG: %[[NEXT]] = getelementptr inbounds %class.F, ptr %[[CUR]], i64 1 +// OGCG: %[[DONE:.*]] = icmp eq ptr %[[NEXT]], %[[ARRAY_END]] +// OGCG: br i1 %[[DONE]], label +// OGCG: store ptr %[[RAW_PTR]], ptr %[[P_ADDR]], align 8 +// OGCG: ret void +// + +class G { +public: + G(); + G(int); +}; + +void test_array_new_with_ctor_partial_init_list() { + auto p = new G[8] {1, 2}; +} + +// CIR-BEFORE-LPP: cir.func {{.*}} @_Z42test_array_new_with_ctor_partial_init_listv +// CIR-BEFORE-LPP: %[[P_ADDR:.*]] = cir.alloca !cir.ptr<!rec_G>, !cir.ptr<!cir.ptr<!rec_G>>, ["p", init] +// CIR-BEFORE-LPP: %[[EIGHT:.*]] = cir.const #cir.int<8> : !u64i +// CIR-BEFORE-LPP: %[[RAW_PTR:.*]] = cir.call @_Znam(%[[EIGHT]]) {allocsize = array<i32: 0>, builtin} : (!u64i {llvm.noundef}) +// CIR-BEFORE-LPP: %[[BEGIN:.*]] = cir.cast bitcast %[[RAW_PTR]] : !cir.ptr<!void> -> !cir.ptr<!rec_G> +// CIR-BEFORE-LPP: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i +// CIR-BEFORE-LPP: cir.call @_ZN1GC1Ei(%[[BEGIN]], %[[ONE]]) : (!cir.ptr<!rec_G> {{.*}}, !s32i {llvm.noundef}) -> () +// CIR-BEFORE-LPP: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i +// CIR-BEFORE-LPP: %[[SECOND:.*]] = cir.ptr_stride %[[BEGIN]], %[[ONE]] : (!cir.ptr<!rec_G>, !s32i) -> !cir.ptr<!rec_G> +// CIR-BEFORE-LPP: %[[TWO:.*]] = cir.const #cir.int<2> : !s32i +// CIR-BEFORE-LPP: cir.call @_ZN1GC1Ei(%[[SECOND]], %[[TWO]]) : (!cir.ptr<!rec_G> {{.*}}, !s32i {llvm.noundef}) -> () +// CIR-BEFORE-LPP: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i +// CIR-BEFORE-LPP: %[[THIRD:.*]] = cir.ptr_stride %[[SECOND]], %[[ONE]] : (!cir.ptr<!rec_G>, !s32i) -> !cir.ptr<!rec_G> +// CIR-BEFORE-LPP: %[[TAIL_ARRAY:.*]] = cir.cast bitcast %[[THIRD]] : !cir.ptr<!rec_G> -> !cir.ptr<!cir.array<!rec_G x 6>> +// CIR-BEFORE-LPP: cir.array.ctor %[[TAIL_ARRAY]] : !cir.ptr<!cir.array<!rec_G x 6>> { +// CIR-BEFORE-LPP: ^bb0(%[[ELEM:.*]]: !cir.ptr<!rec_G>): +// CIR-BEFORE-LPP: cir.call @_ZN1GC1Ev(%[[ELEM]]) : (!cir.ptr<!rec_G> {{.*}}) -> () +// CIR-BEFORE-LPP: cir.yield +// CIR-BEFORE-LPP: } +// CIR-BEFORE-LPP: cir.store{{.*}} %[[BEGIN]], %[[P_ADDR]] +// CIR-BEFORE-LPP: cir.return + +// CHECK: cir.func {{.*}} @_Z42test_array_new_with_ctor_partial_init_listv +// CHECK: %[[P_ADDR:.*]] = cir.alloca !cir.ptr<!rec_G>, !cir.ptr<!cir.ptr<!rec_G>>, ["p", init] +// CHECK: %[[EIGHT:.*]] = cir.const #cir.int<8> : !u64i +// CHECK: %[[RAW_PTR:.*]] = cir.call @_Znam(%[[EIGHT]]) {allocsize = array<i32: 0>, builtin} : (!u64i {llvm.noundef}) +// CHECK: %[[BEGIN:.*]] = cir.cast bitcast %[[RAW_PTR]] : !cir.ptr<!void> -> !cir.ptr<!rec_G> +// CHECK: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i +// CHECK: cir.call @_ZN1GC1Ei(%[[BEGIN]], %[[ONE]]) : (!cir.ptr<!rec_G> {{.*}}, !s32i {llvm.noundef}) -> () +// CHECK: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i +// CHECK: %[[SECOND:.*]] = cir.ptr_stride %[[BEGIN]], %[[ONE]] : (!cir.ptr<!rec_G>, !s32i) -> !cir.ptr<!rec_G> +// CHECK: %[[TWO:.*]] = cir.const #cir.int<2> : !s32i +// CHECK: cir.call @_ZN1GC1Ei(%[[SECOND]], %[[TWO]]) : (!cir.ptr<!rec_G> {{.*}}, !s32i {llvm.noundef}) -> () +// CHECK: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i +// CHECK: %[[THIRD:.*]] = cir.ptr_stride %[[SECOND]], %[[ONE]] : (!cir.ptr<!rec_G>, !s32i) -> !cir.ptr<!rec_G> +// CHECK: %[[TAIL_ARRAY:.*]] = cir.cast bitcast %[[THIRD]] : !cir.ptr<!rec_G> -> !cir.ptr<!cir.array<!rec_G x 6>> +// CHECK: %[[SIX:.*]] = cir.const #cir.int<6> : !u64i +// CHECK: %[[ARRAY_BEGIN:.*]] = cir.cast array_to_ptrdecay %[[TAIL_ARRAY]] : !cir.ptr<!cir.array<!rec_G x 6>> -> !cir.ptr<!rec_G> +// CHECK: %[[ARRAY_END:.*]] = cir.ptr_stride %[[ARRAY_BEGIN]], %[[SIX]] : (!cir.ptr<!rec_G>, !u64i) -> !cir.ptr<!rec_G> +// CHECK: %[[IDX_ADDR:.*]] = cir.alloca !cir.ptr<!rec_G>, !cir.ptr<!cir.ptr<!rec_G>>, ["__array_idx"] {alignment = 1 : i64} +// CHECK: cir.store %[[ARRAY_BEGIN]], %[[IDX_ADDR]] : !cir.ptr<!rec_G>, !cir.ptr<!cir.ptr<!rec_G>> +// CHECK: cir.do { +// CHECK: %[[CUR:.*]] = cir.load %[[IDX_ADDR]] : !cir.ptr<!cir.ptr<!rec_G>>, !cir.ptr<!rec_G> +// CHECK: cir.call @_ZN1GC1Ev(%[[CUR]]) : (!cir.ptr<!rec_G> {{.*}}) -> () +// CHECK: %[[ONE_U64:.*]] = cir.const #cir.int<1> : !u64i +// CHECK: %[[NEXT:.*]] = cir.ptr_stride %[[CUR]], %[[ONE_U64]] : (!cir.ptr<!rec_G>, !u64i) -> !cir.ptr<!rec_G> +// CHECK: cir.store %[[NEXT]], %[[IDX_ADDR]] : !cir.ptr<!rec_G>, !cir.ptr<!cir.ptr<!rec_G>> +// CHECK: cir.yield +// CHECK: } while { +// CHECK: %[[CUR2:.*]] = cir.load %[[IDX_ADDR]] : !cir.ptr<!cir.ptr<!rec_G>>, !cir.ptr<!rec_G> +// CHECK: %[[CMP:.*]] = cir.cmp ne %[[CUR2]], %[[ARRAY_END]] : !cir.ptr<!rec_G> +// CHECK: cir.condition(%[[CMP]]) +// CHECK: } +// CHECK: cir.store{{.*}} %[[BEGIN]], %[[P_ADDR]] +// CHECK: cir.return + +// LLVM: define{{.*}} void @_Z42test_array_new_with_ctor_partial_init_listv +// LLVM: %[[P_ADDR:.*]] = alloca ptr, i64 1, align 8 +// LLVM: %[[RAW_PTR:.*]] = call noundef ptr @_Znam(i64 noundef 8) +// LLVM: call void @_ZN1GC1Ei(ptr noundef nonnull align 1 dereferenceable(1) %[[RAW_PTR]], i32 noundef 1) +// LLVM: %[[SECOND:.*]] = getelementptr %class.G, ptr %[[RAW_PTR]], i64 1 +// LLVM: call void @_ZN1GC1Ei(ptr noundef nonnull align 1 dereferenceable(1) %[[SECOND]], i32 noundef 2) +// LLVM: %[[THIRD:.*]] = getelementptr %class.G, ptr %[[SECOND]], i64 1 +// LLVM: %[[ARRAY_BEGIN:.*]] = getelementptr %class.G, ptr %[[THIRD]], i32 0 +// LLVM: %[[ARRAY_END:.*]] = getelementptr %class.G, ptr %[[ARRAY_BEGIN]], i64 6 +// LLVM: %[[IDX_ADDR:.*]] = alloca ptr, i64 1, align 1 +// LLVM: store ptr %[[ARRAY_BEGIN]], ptr %[[IDX_ADDR]], align 8 +// LLVM: br label +// LLVM: %[[CUR2:.*]] = load ptr, ptr %[[IDX_ADDR]], align 8 +// LLVM: %[[CMP:.*]] = icmp ne ptr %[[CUR2]], %[[ARRAY_END]] +// LLVM: br i1 %[[CMP]], label +// LLVM: %[[CUR:.*]] = load ptr, ptr %[[IDX_ADDR]], align 8 +// LLVM: call void @_ZN1GC1Ev(ptr noundef nonnull align 1 dereferenceable(1) %[[CUR]]) +// LLVM: %[[NEXT:.*]] = getelementptr %class.G, ptr %[[CUR]], i64 1 +// LLVM: store ptr %[[NEXT]], ptr %[[IDX_ADDR]], align 8 +// LLVM: br label +// LLVM: store ptr %[[RAW_PTR]], ptr %[[P_ADDR]], align 8 +// LLVM: ret void + +// OGCG: define{{.*}} void @_Z42test_array_new_with_ctor_partial_init_listv +// OGCG: %[[P_ADDR:.*]] = alloca ptr, align 8 +// OGCG: %[[RAW_PTR:.*]] = call{{.*}} ptr @_Znam(i64 noundef 8) +// OGCG: call void @_ZN1GC1Ei(ptr noundef nonnull align 1 dereferenceable(1) %[[RAW_PTR]], i32 noundef 1) +// OGCG: %[[SECOND:.*]] = getelementptr inbounds %class.G, ptr %[[RAW_PTR]], i64 1 +// OGCG: call void @_ZN1GC1Ei(ptr noundef nonnull align 1 dereferenceable(1) %[[SECOND]], i32 noundef 2) +// OGCG: %[[THIRD:.*]] = getelementptr inbounds %class.G, ptr %[[SECOND]], i64 1 +// OGCG: %[[ARRAY_END:.*]] = getelementptr inbounds %class.G, ptr %[[THIRD]], i64 6 +// OGCG: br label +// OGCG: %[[CUR:.*]] = phi ptr [ %[[THIRD]], {{.*}} ], [ %[[NEXT:.*]], {{.*}} ] +// OGCG: call void @_ZN1GC1Ev(ptr noundef nonnull align 1 dereferenceable(1) %[[CUR]]) +// OGCG: %[[NEXT]] = getelementptr inbounds %class.G, ptr %[[CUR]], i64 1 +// OGCG: %[[DONE:.*]] = icmp eq ptr %[[NEXT]], %[[ARRAY_END]] +// OGCG: br i1 %[[DONE]], label +// OGCG: store ptr %[[RAW_PTR]], ptr %[[P_ADDR]], align 8 +// OGCG: ret void +// _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
