diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp index 7d769cdc8b80..a27b0311e8d6 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp @@ -2146,8 +2146,22 @@ static Address createReferenceTemporary(CIRGenFunction &CGF, (Ty->isArrayType() || Ty->isRecordType()) && CGF.CGM.isTypeConstant(Ty, /*ExcludeCtor=*/true, /*ExcludeDtor=*/false)) assert(0 && "NYI"); + + // The temporary memory should be created in the same scope as the extending + // declaration of the temporary materialization expression. + mlir::cir::AllocaOp extDeclAlloca; + if (const clang::ValueDecl *extDecl = M->getExtendingDecl()) { + auto extDeclAddrIter = CGF.LocalDeclMap.find(extDecl); + if (extDeclAddrIter != CGF.LocalDeclMap.end()) { + extDeclAlloca = dyn_cast_if_present( + extDeclAddrIter->second.getDefiningOp()); + } + } + mlir::OpBuilder::InsertPoint ip; + if (extDeclAlloca) + ip = {extDeclAlloca->getBlock(), extDeclAlloca->getIterator()}; return CGF.CreateMemTemp(Ty, CGF.getLoc(M->getSourceRange()), - CGF.getCounterRefTmpAsString(), Alloca); + CGF.getCounterRefTmpAsString(), Alloca, ip); } case SD_Thread: case SD_Static: @@ -2245,7 +2259,7 @@ LValue CIRGenFunction::buildMaterializeTemporaryExpr( } else { switch (M->getStorageDuration()) { case SD_Automatic: - assert(0 && "NYI"); + assert(!MissingFeatures::shouldEmitLifetimeMarkers()); break; case SD_FullExpression: { @@ -2932,18 +2946,20 @@ void CIRGenFunction::buildUnreachable(SourceLocation Loc) { //===----------------------------------------------------------------------===// Address CIRGenFunction::CreateMemTemp(QualType Ty, mlir::Location Loc, - const Twine &Name, Address *Alloca) { + const Twine &Name, Address *Alloca, + mlir::OpBuilder::InsertPoint ip) { // FIXME: Should we prefer the preferred type alignment here? return CreateMemTemp(Ty, getContext().getTypeAlignInChars(Ty), Loc, Name, - Alloca); + Alloca, ip); } Address CIRGenFunction::CreateMemTemp(QualType Ty, CharUnits Align, mlir::Location Loc, const Twine &Name, - Address *Alloca) { + Address *Alloca, + mlir::OpBuilder::InsertPoint ip) { Address Result = CreateTempAlloca(getTypes().convertTypeForMem(Ty), Align, Loc, Name, - /*ArraySize=*/nullptr, Alloca); + /*ArraySize=*/nullptr, Alloca, ip); if (Ty->isConstantMatrixType()) { assert(0 && "NYI"); } diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h index 6a548c9d79bd..67ea4dc389dc 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.h +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h @@ -2215,9 +2215,11 @@ class CIRGenFunction : public CIRGenTypeCache { /// appropriate alignmen and cast it to the default address space. Returns /// the original alloca instruction by \p Alloca if it is not nullptr. Address CreateMemTemp(QualType T, mlir::Location Loc, - const Twine &Name = "tmp", Address *Alloca = nullptr); + const Twine &Name = "tmp", Address *Alloca = nullptr, + mlir::OpBuilder::InsertPoint ip = {}); Address CreateMemTemp(QualType T, CharUnits Align, mlir::Location Loc, - const Twine &Name = "tmp", Address *Alloca = nullptr); + const Twine &Name = "tmp", Address *Alloca = nullptr, + mlir::OpBuilder::InsertPoint ip = {}); /// Create a temporary memory object of the given type, with /// appropriate alignment without casting it to the default address space. diff --git a/clang/test/CIR/CodeGen/temporary-materialization.cpp b/clang/test/CIR/CodeGen/temporary-materialization.cpp new file mode 100644 index 000000000000..3b063db09dc3 --- /dev/null +++ b/clang/test/CIR/CodeGen/temporary-materialization.cpp @@ -0,0 +1,43 @@ +// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --input-file=%t.cir %s + +int make_int(); + +int test() { + const int &x = make_int(); + return x; +} + +// CHECK: cir.func @_Z4testv() +// CHECK-NEXT: %{{.+}} = cir.alloca !s32i, !cir.ptr, ["__retval"] {alignment = 4 : i64} +// CHECK-NEXT: %[[#TEMP_SLOT:]] = cir.alloca !s32i, !cir.ptr, ["ref.tmp0", init] {alignment = 4 : i64} +// CHECK-NEXT: %[[#x:]] = cir.alloca !cir.ptr, !cir.ptr>, ["x", init] {alignment = 8 : i64} +// CHECK-NEXT: cir.scope { +// CHECK-NEXT: %[[#TEMP_VALUE:]] = cir.call @_Z8make_intv() : () -> !s32i +// CHECK-NEXT: cir.store %[[#TEMP_VALUE]], %[[#TEMP_SLOT]] : !s32i, !cir.ptr +// CHECK-NEXT: } +// CHECK-NEXT: cir.store %[[#TEMP_SLOT]], %[[#x]] : !cir.ptr, !cir.ptr> +// CHECK: } + +int test_scoped() { + int x = make_int(); + { + const int &y = make_int(); + x = y; + } + return x; +} + +// CHECK: cir.func @_Z11test_scopedv() +// CHECK-NEXT: %{{.+}} = cir.alloca !s32i, !cir.ptr, ["__retval"] {alignment = 4 : i64} +// CHECK-NEXT: %{{.+}} = cir.alloca !s32i, !cir.ptr, ["x", init] {alignment = 4 : i64} +// CHECK: cir.scope { +// CHECK-NEXT: %[[#TEMP_SLOT:]] = cir.alloca !s32i, !cir.ptr, ["ref.tmp0", init] {alignment = 4 : i64} +// CHECK-NEXT: %[[#y:]] = cir.alloca !cir.ptr, !cir.ptr>, ["y", init] {alignment = 8 : i64} +// CHECK-NEXT: cir.scope { +// CHECK-NEXT: %[[#TEMP_VALUE:]] = cir.call @_Z8make_intv() : () -> !s32i +// CHECK-NEXT: cir.store %[[#TEMP_VALUE]], %[[#TEMP_SLOT]] : !s32i, !cir.ptr +// CHECK-NEXT: } +// CHECK-NEXT: cir.store %[[#TEMP_SLOT]], %[[#y]] : !cir.ptr, !cir.ptr> +// CHECK: } +// CHECK: }