Skip to content

Commit 1441f04

Browse files
authored
[CIR] Upstream reserved placement new handling (#169436)
This upstreams the code to support reserved placement new calls.
1 parent 8380a48 commit 1441f04

File tree

3 files changed

+67
-2
lines changed

3 files changed

+67
-2
lines changed

clang/lib/CIR/CodeGen/Address.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,12 @@ class Address {
7777
return Address(newPtr, getElementType(), getAlignment());
7878
}
7979

80+
/// Return address with different alignment, but same pointer and element
81+
/// type.
82+
Address withAlignment(clang::CharUnits newAlignment) const {
83+
return Address(getPointer(), getElementType(), newAlignment);
84+
}
85+
8086
/// Return address with different element type, a bitcast pointer, and
8187
/// the same alignment.
8288
Address withElementType(CIRGenBuilderTy &builder, mlir::Type ElemTy) const;

clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -806,8 +806,27 @@ mlir::Value CIRGenFunction::emitCXXNewExpr(const CXXNewExpr *e) {
806806
Address allocation = Address::invalid();
807807
CallArgList allocatorArgs;
808808
if (allocator->isReservedGlobalPlacementOperator()) {
809-
cgm.errorNYI(e->getSourceRange(),
810-
"emitCXXNewExpr: reserved global placement operator");
809+
// If the allocator is a global placement operator, just
810+
// "inline" it directly.
811+
assert(e->getNumPlacementArgs() == 1);
812+
const Expr *arg = *e->placement_arguments().begin();
813+
814+
LValueBaseInfo baseInfo;
815+
allocation = emitPointerWithAlignment(arg, &baseInfo);
816+
817+
// The pointer expression will, in many cases, be an opaque void*.
818+
// In these cases, discard the computed alignment and use the
819+
// formal alignment of the allocated type.
820+
if (baseInfo.getAlignmentSource() != AlignmentSource::Decl)
821+
allocation = allocation.withAlignment(allocAlign);
822+
823+
// Set up allocatorArgs for the call to operator delete if it's not
824+
// the reserved global operator.
825+
if (e->getOperatorDelete() &&
826+
!e->getOperatorDelete()->isReservedGlobalPlacementOperator()) {
827+
cgm.errorNYI(e->getSourceRange(),
828+
"emitCXXNewExpr: reserved placement new with delete");
829+
}
811830
} else {
812831
const FunctionProtoType *allocatorType =
813832
allocator->getType()->castAs<FunctionProtoType>();
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu %s -fclangir -emit-cir -o %t.cir
2+
// RUN: FileCheck --input-file=%t.cir -check-prefix=CIR %s
3+
// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu %s -fclangir -emit-llvm -o %t-cir.ll
4+
// RUN: FileCheck --input-file=%t-cir.ll -check-prefix=LLVM %s
5+
// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu %s -emit-llvm -o %t.ll
6+
// RUN: FileCheck --input-file=%t.ll -check-prefix=OGCG %s
7+
8+
typedef __typeof__(sizeof(0)) size_t;
9+
10+
// Declare the reserved placement operators.
11+
void *operator new(size_t, void*) throw();
12+
13+
struct A { A(); ~A(); };
14+
15+
void test_reserved_placement_new(void *p) {
16+
new (p) A();
17+
}
18+
19+
// CIR-LABEL: cir.func dso_local @_Z27test_reserved_placement_newPv(
20+
// CIR-SAME: %[[ARG0:.*]]: !cir.ptr<!void>
21+
// CIR: %[[P:.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["p", init]
22+
// CIR: cir.store %[[ARG0]], %[[P]] : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>
23+
// CIR: %[[SIZE:.*]] = cir.const #cir.int<1> : !u64i
24+
// CIR: %[[PTR:.*]] = cir.load{{.*}} %[[P]] : !cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void>
25+
// CIR: %[[PTR_A:.*]] = cir.cast bitcast %[[PTR]] : !cir.ptr<!void> -> !cir.ptr<!rec_A>
26+
// CIR: cir.call @_ZN1AC1Ev(%[[PTR_A]]) : (!cir.ptr<!rec_A>) -> ()
27+
28+
// LLVM-LABEL: define dso_local void @_Z27test_reserved_placement_newPv(
29+
// LLVM-SAME: ptr %[[ARG0:.*]]
30+
// LLVM: %[[P:.*]] = alloca ptr
31+
// LLVM: store ptr %[[ARG0:.*]], ptr %[[P]]
32+
// LLVM: %[[PTR:.*]] = load ptr, ptr %[[P]]
33+
// LLVM: call void @_ZN1AC1Ev(ptr %[[PTR]])
34+
35+
// OGCG-LABEL: define dso_local void @_Z27test_reserved_placement_newPv(
36+
// OGCG-SAME: ptr {{.*}} %[[ARG0:.*]]
37+
// OGCG: %[[P:.*]] = alloca ptr
38+
// OGCG: store ptr %[[ARG0:.*]], ptr %[[P]]
39+
// OGCG: %[[PTR:.*]] = load ptr, ptr %[[P]]
40+
// OGCG: call void @_ZN1AC1Ev(ptr {{.*}} %[[PTR]])

0 commit comments

Comments
 (0)