Skip to content

Commit 2eaa500

Browse files
authored
[CIR][CIRGen][Builtin] Support BI__builtin_operator_new and BI__builtin_operator_delete (#1035)
The added test cases are from [OG's counterpart](https://github.com/llvm/clangir/blob/f9c5477ee10c9bc005ffbfe698691cc02193ea81/clang/test/CodeGenCXX/builtin-operator-new-delete.cpp#L7). I changed run option to -std=c++17 to support [std::align_val_t](https://en.cppreference.com/w/cpp/memory/new/align_val_t)
1 parent ce2469e commit 2eaa500

File tree

4 files changed

+71
-5
lines changed

4 files changed

+71
-5
lines changed

clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp

+5-2
Original file line numberDiff line numberDiff line change
@@ -1838,9 +1838,12 @@ RValue CIRGenFunction::buildBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
18381838
case Builtin::BI__builtin_function_start:
18391839
llvm_unreachable("BI__builtin_function_start NYI");
18401840
case Builtin::BI__builtin_operator_new:
1841-
llvm_unreachable("BI__builtin_operator_new NYI");
1841+
return buildBuiltinNewDeleteCall(
1842+
E->getCallee()->getType()->castAs<FunctionProtoType>(), E, false);
18421843
case Builtin::BI__builtin_operator_delete:
1843-
llvm_unreachable("BI__builtin_operator_delete NYI");
1844+
buildBuiltinNewDeleteCall(
1845+
E->getCallee()->getType()->castAs<FunctionProtoType>(), E, true);
1846+
return RValue::get(nullptr);
18441847
case Builtin::BI__builtin_is_aligned:
18451848
llvm_unreachable("BI__builtin_is_aligned NYI");
18461849
case Builtin::BI__builtin_align_up:

clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp

+17
Original file line numberDiff line numberDiff line change
@@ -1175,6 +1175,23 @@ static RValue buildNewDeleteCall(CIRGenFunction &CGF,
11751175
return RV;
11761176
}
11771177

1178+
RValue CIRGenFunction::buildBuiltinNewDeleteCall(const FunctionProtoType *type,
1179+
const CallExpr *theCall,
1180+
bool isDelete) {
1181+
CallArgList args;
1182+
buildCallArgs(args, type, theCall->arguments());
1183+
// Find the allocation or deallocation function that we're calling.
1184+
ASTContext &ctx = getContext();
1185+
DeclarationName name =
1186+
ctx.DeclarationNames.getCXXOperatorName(isDelete ? OO_Delete : OO_New);
1187+
1188+
for (auto *decl : ctx.getTranslationUnitDecl()->lookup(name))
1189+
if (auto *fd = dyn_cast<FunctionDecl>(decl))
1190+
if (ctx.hasSameType(fd->getType(), QualType(type, 0)))
1191+
return buildNewDeleteCall(*this, fd, type, args);
1192+
llvm_unreachable("predeclared global operator new/delete is missing");
1193+
}
1194+
11781195
void CIRGenFunction::buildDeleteCall(const FunctionDecl *DeleteFD,
11791196
mlir::Value Ptr, QualType DeleteTy,
11801197
mlir::Value NumElements,

clang/lib/CIR/CodeGen/CIRGenFunction.h

+3
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,9 @@ class CIRGenFunction : public CIRGenTypeCache {
729729
QualType DeleteTy, mlir::Value NumElements = nullptr,
730730
CharUnits CookieSize = CharUnits());
731731

732+
RValue buildBuiltinNewDeleteCall(const FunctionProtoType *type,
733+
const CallExpr *theCallExpr, bool isDelete);
734+
732735
mlir::Value buildDynamicCast(Address ThisAddr, const CXXDynamicCastExpr *DCE);
733736

734737
mlir::Value createLoad(const clang::VarDecl *VD, const char *Name);

clang/test/CIR/CodeGen/new-null.cpp

+46-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-linux-gnu %s -fclangir -emit-cir -o %t.cir
1+
// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu %s -fclangir -emit-cir -o %t.cir
22
// RUN: FileCheck --input-file=%t.cir -check-prefix=CIR %s
3-
// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-linux-gnu %s -fclangir -emit-llvm -o %t.ll
3+
// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu %s -fclangir -emit-llvm -o %t.ll
44
// RUN: FileCheck --input-file=%t.ll -check-prefix=LLVM %s
55

66
// TODO: This file is inspired by clang/test/CodeGenCXX/new.cpp, add all tests from it.
@@ -16,6 +16,8 @@ void *operator new[](size_t);
1616

1717
namespace std {
1818
struct nothrow_t {};
19+
enum class align_val_t : size_t { __zero = 0,
20+
__max = (size_t)-1 };
1921
}
2022
std::nothrow_t nothrow;
2123

@@ -76,4 +78,45 @@ namespace test15 {
7678
void test0b(void *p) {
7779
new (p, true) A();
7880
}
79-
}
81+
}
82+
83+
extern "C" void test_basic() {
84+
__builtin_operator_delete(__builtin_operator_new(4));
85+
// CIR-LABEL: cir.func @test_basic
86+
// CIR: [[P:%.*]] = cir.call @_Znwm({{%.*}}) : (!u64i) -> !cir.ptr<!void>
87+
// CIR: cir.call @_ZdlPv([[P]]) : (!cir.ptr<!void>) -> ()
88+
// CIR: cir.return
89+
90+
// LLVM-LABEL: define{{.*}} void @test_basic()
91+
// LLVM: [[P:%.*]] = call ptr @_Znwm(i64 4)
92+
// LLVM: call void @_ZdlPv(ptr [[P]])
93+
// LLVM: ret void
94+
}
95+
96+
extern "C" void test_aligned_alloc() {
97+
__builtin_operator_delete(__builtin_operator_new(4, std::align_val_t(4)), std::align_val_t(4));
98+
99+
// CIR-LABEL: cir.func @test_aligned_alloc
100+
// CIR: [[P:%.*]] = cir.call @_ZnwmSt11align_val_t({{%.*}}, {{%.*}}) : (!u64i, !u64i) -> !cir.ptr<!void>
101+
// CIR: cir.call @_ZdlPvSt11align_val_t([[P]], {{%.*}}) : (!cir.ptr<!void>, !u64i) -> ()
102+
// CIR: cir.return
103+
104+
// LLVM-LABEL: define{{.*}} void @test_aligned_alloc()
105+
// LLVM: [[P:%.*]] = call ptr @_ZnwmSt11align_val_t(i64 4, i64 4)
106+
// LLVM: call void @_ZdlPvSt11align_val_t(ptr [[P]], i64 4)
107+
// LLVM: ret void
108+
}
109+
110+
extern "C" void test_sized_delete() {
111+
__builtin_operator_delete(__builtin_operator_new(4), 4);
112+
113+
// CIR-LABEL: cir.func @test_sized_delete
114+
// CIR: [[P:%.*]] = cir.call @_Znwm({{%.*}}) : (!u64i) -> !cir.ptr<!void>
115+
// CIR: cir.call @_ZdlPvm([[P]], {{%.*}}) : (!cir.ptr<!void>, !u64i) -> ()
116+
// CIR: cir.return
117+
118+
// LLVM-LABEL: define{{.*}} void @test_sized_delete()
119+
// LLVM: [[P:%.*]] = call ptr @_Znwm(i64 4)
120+
// LLVM: call void @_ZdlPvm(ptr [[P]], i64 4)
121+
// LLVM: ret void
122+
}

0 commit comments

Comments
 (0)