https://github.com/andykaylor created https://github.com/llvm/llvm-project/pull/169436
This upstreams the code to support reserved placement new calls. >From 884f4e5a09d6c28ae84eb95764acd61154d69f56 Mon Sep 17 00:00:00 2001 From: Andy Kaylor <[email protected]> Date: Mon, 24 Nov 2025 16:57:55 -0800 Subject: [PATCH] [CIR] Upstream reserved placement new handling This upstreams the code to support reserved placement new calls. --- clang/lib/CIR/CodeGen/Address.h | 6 ++++ clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp | 23 ++++++++++++-- clang/test/CIR/CodeGen/placement-new.cpp | 40 ++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 clang/test/CIR/CodeGen/placement-new.cpp diff --git a/clang/lib/CIR/CodeGen/Address.h b/clang/lib/CIR/CodeGen/Address.h index c8ce530a7b0d3..a425eebe99082 100644 --- a/clang/lib/CIR/CodeGen/Address.h +++ b/clang/lib/CIR/CodeGen/Address.h @@ -77,6 +77,12 @@ class Address { return Address(newPtr, getElementType(), getAlignment()); } + /// Return address with different alignment, but same pointer and element + /// type. + Address withAlignment(clang::CharUnits newAlignment) const { + return Address(getPointer(), getElementType(), newAlignment); + } + /// Return address with different element type, a bitcast pointer, and /// the same alignment. Address withElementType(CIRGenBuilderTy &builder, mlir::Type ElemTy) const; diff --git a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp index dbf20db8bfb8d..81fd8ee106107 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp @@ -806,8 +806,27 @@ mlir::Value CIRGenFunction::emitCXXNewExpr(const CXXNewExpr *e) { Address allocation = Address::invalid(); CallArgList allocatorArgs; if (allocator->isReservedGlobalPlacementOperator()) { - cgm.errorNYI(e->getSourceRange(), - "emitCXXNewExpr: reserved global placement operator"); + // If the allocator is a global placement operator, just + // "inline" it directly. + assert(e->getNumPlacementArgs() == 1); + const Expr *arg = *e->placement_arguments().begin(); + + LValueBaseInfo baseInfo; + allocation = emitPointerWithAlignment(arg, &baseInfo); + + // The pointer expression will, in many cases, be an opaque void*. + // In these cases, discard the computed alignment and use the + // formal alignment of the allocated type. + if (baseInfo.getAlignmentSource() != AlignmentSource::Decl) + allocation = allocation.withAlignment(allocAlign); + + // Set up allocatorArgs for the call to operator delete if it's not + // the reserved global operator. + if (e->getOperatorDelete() && + !e->getOperatorDelete()->isReservedGlobalPlacementOperator()) { + cgm.errorNYI(e->getSourceRange(), + "emitCXXNewExpr: reserved placement new with delete"); + } } else { const FunctionProtoType *allocatorType = allocator->getType()->castAs<FunctionProtoType>(); diff --git a/clang/test/CIR/CodeGen/placement-new.cpp b/clang/test/CIR/CodeGen/placement-new.cpp new file mode 100644 index 0000000000000..7ceaa0a359e1f --- /dev/null +++ b/clang/test/CIR/CodeGen/placement-new.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu %s -fclangir -emit-cir -o %t.cir +// RUN: FileCheck --input-file=%t.cir -check-prefix=CIR %s +// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu %s -fclangir -emit-llvm -o %t-cir.ll +// RUN: FileCheck --input-file=%t-cir.ll -check-prefix=LLVM %s +// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu %s -emit-llvm -o %t.ll +// RUN: FileCheck --input-file=%t.ll -check-prefix=OGCG %s + +typedef __typeof__(sizeof(0)) size_t; + +// Declare the reserved placement operators. +void *operator new(size_t, void*) throw(); + +struct A { A(); ~A(); }; + +void test_reserved_placement_new(void *p) { + new (p) A(); +} + +// CIR-LABEL: cir.func dso_local @_Z27test_reserved_placement_newPv( +// CIR-SAME: %[[ARG0:.*]]: !cir.ptr<!void> +// CIR: %[[P:.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["p", init] +// CIR: cir.store %[[ARG0]], %[[P]] : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>> +// CIR: %[[SIZE:.*]] = cir.const #cir.int<1> : !u64i +// CIR: %[[PTR:.*]] = cir.load{{.*}} %[[P]] : !cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void> +// CIR: %[[PTR_A:.*]] = cir.cast bitcast %[[PTR]] : !cir.ptr<!void> -> !cir.ptr<!rec_A> +// CIR: cir.call @_ZN1AC1Ev(%[[PTR_A]]) : (!cir.ptr<!rec_A>) -> () + +// LLVM-LABEL: define dso_local void @_Z27test_reserved_placement_newPv( +// LLVM-SAME: ptr %[[ARG0:.*]] +// LLVM: %[[P:.*]] = alloca ptr +// LLVM: store ptr %[[ARG0:.*]], ptr %[[P]] +// LLVM: %[[PTR:.*]] = load ptr, ptr %[[P]] +// LLVM: call void @_ZN1AC1Ev(ptr %[[PTR]]) + +// OGCG-LABEL: define dso_local void @_Z27test_reserved_placement_newPv( +// OGCG-SAME: ptr {{.*}} %[[ARG0:.*]] +// OGCG: %[[P:.*]] = alloca ptr +// OGCG: store ptr %[[ARG0:.*]], ptr %[[P]] +// OGCG: %[[PTR:.*]] = load ptr, ptr %[[P]] +// OGCG: call void @_ZN1AC1Ev(ptr {{.*}} %[[PTR]]) _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
