[clang] [CIR] Add builtin operator new/delete (PR #168578)
Hendrik Hübner via cfe-commits
cfe-commits at lists.llvm.org
Tue Nov 18 09:54:34 PST 2025
https://github.com/HendrikHuebner created https://github.com/llvm/llvm-project/pull/168578
This PR adds `__builtin_operator_new` and `__builtin_operator_delete`. The implementation is taken from clang code gen.
>From 185d4f496ffb5c9299089606213c52cb5b7a60bb Mon Sep 17 00:00:00 2001
From: hhuebner <hendrik.huebner18 at gmail.com>
Date: Tue, 18 Nov 2025 18:50:47 +0100
Subject: [PATCH 1/2] [CIR] builtin operator new/delete
---
clang/include/clang/CIR/MissingFeatures.h | 1 +
clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 9 ++++++++
clang/lib/CIR/CodeGen/CIRGenExpr.cpp | 1 +
clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp | 26 +++++++++++++++++++++++
clang/lib/CIR/CodeGen/CIRGenFunction.h | 3 +++
5 files changed, 40 insertions(+)
diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h
index 567c79a27c07b..477d8046e18c0 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -200,6 +200,7 @@ struct MissingFeatures {
static bool aggValueSlotMayOverlap() { return false; }
static bool aggValueSlotVolatile() { return false; }
static bool alignCXXRecordDecl() { return false; }
+ static bool allocToken() { return false; }
static bool appleKext() { return false; }
static bool armComputeVolatileBitfields() { return false; }
static bool asmGoto() { return false; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index 77f19343653db..c038f0be81137 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -18,6 +18,7 @@
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/Value.h"
#include "mlir/Support/LLVM.h"
+#include "clang/AST/DeclBase.h"
#include "clang/AST/Expr.h"
#include "clang/AST/GlobalDecl.h"
#include "clang/Basic/Builtins.h"
@@ -520,6 +521,13 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
cir::PrefetchOp::create(builder, loc, address, locality, isWrite);
return RValue::get(nullptr);
}
+ case Builtin::BI__builtin_operator_new:
+ return emitNewOrDeleteBuiltinCall(
+ e->getCallee()->getType()->castAs<FunctionProtoType>(), e, false);
+ case Builtin::BI__builtin_operator_delete:
+ emitNewOrDeleteBuiltinCall(
+ e->getCallee()->getType()->castAs<FunctionProtoType>(), e, true);
+ return RValue::get(nullptr);
}
// If this is an alias for a lib function (e.g. __builtin_sin), emit
@@ -559,6 +567,7 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
std::string("unimplemented builtin call: ") +
getContext().BuiltinInfo.getName(builtinID));
return getUndefRValue(e->getType());
+
}
static mlir::Value emitTargetArchBuiltinExpr(CIRGenFunction *cgf,
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index 91a59d60fcb3e..57b49f4640c4c 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -2006,6 +2006,7 @@ RValue CIRGenFunction::emitCallExpr(const clang::CallExpr *e,
return emitCall(e->getCallee()->getType(), callee, e, returnValue);
}
+
/// Emit code to compute the specified expression, ignoring the result.
void CIRGenFunction::emitIgnoredExpr(const Expr *e) {
if (e->isPRValue()) {
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
index 007d873ff5db6..345bb0e6bed9f 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
@@ -610,6 +610,32 @@ static RValue emitNewDeleteCall(CIRGenFunction &cgf,
return rv;
}
+RValue CIRGenFunction::emitNewOrDeleteBuiltinCall(const FunctionProtoType *type,
+ const CallExpr *callExpr,
+ bool isDelete) {
+ CallArgList args;
+ emitCallArgs(args, type, callExpr->arguments());
+ // Find the allocation or deallocation function that we're calling.
+ ASTContext &astContext = getContext();
+ DeclarationName name = astContext.DeclarationNames.getCXXOperatorName(
+ isDelete ? OO_Delete : OO_New);
+
+ clang::DeclContextLookupResult lookupResult = astContext.getTranslationUnitDecl()->lookup(name);
+ for (const auto *decl : lookupResult) {
+ if (const auto *funcDecl = dyn_cast<FunctionDecl>(decl)) {
+ if (astContext.hasSameType(funcDecl->getType(), QualType(type, 0))) {
+ // Used for -fsanitize=alloc-token
+ assert(!cir::MissingFeatures::allocToken());
+
+ // Emit the call to operator new/delete.
+ return emitNewDeleteCall(*this, funcDecl, type, args);
+ }
+ }
+ }
+
+ llvm_unreachable("predeclared global operator new/delete is missing");
+}
+
namespace {
/// Calls the given 'operator delete' on a single object.
struct CallObjectDelete final : EHScopeStack::Cleanup {
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index 00f289bcd1bb2..060a31edea2cf 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -1476,6 +1476,9 @@ class CIRGenFunction : public CIRGenTypeCache {
RValue emitCXXPseudoDestructorExpr(const CXXPseudoDestructorExpr *expr);
+ RValue emitNewOrDeleteBuiltinCall(const FunctionProtoType* type,
+ const CallExpr* call, bool isDelete);
+
void emitCXXTemporary(const CXXTemporary *temporary, QualType tempType,
Address ptr);
>From 948d5e7945bdd19ee4f7f920296aab117c2ccf21 Mon Sep 17 00:00:00 2001
From: hhuebner <hendrik.huebner18 at gmail.com>
Date: Tue, 18 Nov 2025 18:54:20 +0100
Subject: [PATCH 2/2] formatting
---
clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 1 -
clang/lib/CIR/CodeGen/CIRGenExpr.cpp | 1 -
clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp | 7 ++++---
clang/lib/CIR/CodeGen/CIRGenFunction.h | 4 ++--
4 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index c038f0be81137..2fbad2ecce0d3 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -567,7 +567,6 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
std::string("unimplemented builtin call: ") +
getContext().BuiltinInfo.getName(builtinID));
return getUndefRValue(e->getType());
-
}
static mlir::Value emitTargetArchBuiltinExpr(CIRGenFunction *cgf,
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index 57b49f4640c4c..91a59d60fcb3e 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -2006,7 +2006,6 @@ RValue CIRGenFunction::emitCallExpr(const clang::CallExpr *e,
return emitCall(e->getCallee()->getType(), callee, e, returnValue);
}
-
/// Emit code to compute the specified expression, ignoring the result.
void CIRGenFunction::emitIgnoredExpr(const Expr *e) {
if (e->isPRValue()) {
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
index 345bb0e6bed9f..f28887df34212 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
@@ -611,8 +611,8 @@ static RValue emitNewDeleteCall(CIRGenFunction &cgf,
}
RValue CIRGenFunction::emitNewOrDeleteBuiltinCall(const FunctionProtoType *type,
- const CallExpr *callExpr,
- bool isDelete) {
+ const CallExpr *callExpr,
+ bool isDelete) {
CallArgList args;
emitCallArgs(args, type, callExpr->arguments());
// Find the allocation or deallocation function that we're calling.
@@ -620,7 +620,8 @@ RValue CIRGenFunction::emitNewOrDeleteBuiltinCall(const FunctionProtoType *type,
DeclarationName name = astContext.DeclarationNames.getCXXOperatorName(
isDelete ? OO_Delete : OO_New);
- clang::DeclContextLookupResult lookupResult = astContext.getTranslationUnitDecl()->lookup(name);
+ clang::DeclContextLookupResult lookupResult =
+ astContext.getTranslationUnitDecl()->lookup(name);
for (const auto *decl : lookupResult) {
if (const auto *funcDecl = dyn_cast<FunctionDecl>(decl)) {
if (astContext.hasSameType(funcDecl->getType(), QualType(type, 0))) {
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index 060a31edea2cf..0cfcc2be0255e 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -1476,8 +1476,8 @@ class CIRGenFunction : public CIRGenTypeCache {
RValue emitCXXPseudoDestructorExpr(const CXXPseudoDestructorExpr *expr);
- RValue emitNewOrDeleteBuiltinCall(const FunctionProtoType* type,
- const CallExpr* call, bool isDelete);
+ RValue emitNewOrDeleteBuiltinCall(const FunctionProtoType *type,
+ const CallExpr *call, bool isDelete);
void emitCXXTemporary(const CXXTemporary *temporary, QualType tempType,
Address ptr);
More information about the cfe-commits
mailing list