https://github.com/HendrikHuebner updated https://github.com/llvm/llvm-project/pull/168578
From 185d4f496ffb5c9299089606213c52cb5b7a60bb Mon Sep 17 00:00:00 2001 From: hhuebner <[email protected]> Date: Tue, 18 Nov 2025 18:50:47 +0100 Subject: [PATCH 1/5] [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 <[email protected]> Date: Tue, 18 Nov 2025 18:54:20 +0100 Subject: [PATCH 2/5] 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); From bd397397a2fbbd3d931051891f075a3cfb73a79e Mon Sep 17 00:00:00 2001 From: hhuebner <[email protected]> Date: Tue, 18 Nov 2025 18:55:48 +0100 Subject: [PATCH 3/5] Add test --- clang/test/CIR/CodeGen/builtin_new_delete.cpp | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 clang/test/CIR/CodeGen/builtin_new_delete.cpp diff --git a/clang/test/CIR/CodeGen/builtin_new_delete.cpp b/clang/test/CIR/CodeGen/builtin_new_delete.cpp new file mode 100644 index 0000000000000..d540bfcf8a36d --- /dev/null +++ b/clang/test/CIR/CodeGen/builtin_new_delete.cpp @@ -0,0 +1,44 @@ +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll +// RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll +// RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s + + +void test_builtins_basic() { + __builtin_operator_delete(__builtin_operator_new(4)); + // CIR-LABEL: test_builtins_basic + // CIR: [[P:%.*]] = cir.call @_Znwm({{%.*}}) : (!u64i) -> !cir.ptr<!void> + // CIR: cir.call @_ZdlPv([[P]]) {{.*}}: (!cir.ptr<!void>) -> () + // CIR: cir.return + + // LLVM-LABEL: test_builtins_basic + // LLVM: [[P:%.*]] = call ptr @_Znwm(i64 4) + // LLVM: call void @_ZdlPv(ptr [[P]]) + // LLVM: ret void + + // OGCG-LABEL: test_builtins_basic + // OGCG: [[P:%.*]] = call {{.*}} ptr @_Znwm(i64 {{.*}} 4) + // OGCG: call void @_ZdlPv(ptr {{.*}} [[P]]) + // OGCG: ret void +} + +void test_sized_delete() { + __builtin_operator_delete(__builtin_operator_new(4), 4); + + // CIR-LABEL: test_sized_delete + // CIR: [[P:%.*]] = cir.call @_Znwm({{%.*}}) : (!u64i) -> !cir.ptr<!void> + // CIR: cir.call @_ZdlPvm([[P]], {{%.*}}) {{.*}}: (!cir.ptr<!void>, !u64i) -> () + // CIR: cir.return + + // LLVM-LABEL: test_sized_delete + // LLVM: [[P:%.*]] = call ptr @_Znwm(i64 4) + // LLVM: call void @_ZdlPvm(ptr [[P]], i64 4) + // LLVM: ret void + + // OGCG-LABEL: test_sized_delete + // OGCG: [[P:%.*]] = call {{.*}} ptr @_Znwm(i64 {{.*}} 4) + // OGCG: call void @_ZdlPvm(ptr {{.*}} [[P]], i64 {{.*}} 4) + // OGCG: ret void +} From b45f8a6558db4d0ae3fcad82b4fa97e6787e40b1 Mon Sep 17 00:00:00 2001 From: hhuebner <[email protected]> Date: Wed, 19 Nov 2025 14:06:12 +0100 Subject: [PATCH 4/5] Feedback --- clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp | 14 +++++++++----- clang/lib/CIR/CodeGen/CIRGenFunction.h | 4 +++- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp index f28887df34212..32e93c9f021f6 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp @@ -16,6 +16,7 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/ExprCXX.h" +#include "clang/Basic/OperatorKinds.h" #include "clang/CIR/MissingFeatures.h" using namespace clang; @@ -612,21 +613,24 @@ static RValue emitNewDeleteCall(CIRGenFunction &cgf, RValue CIRGenFunction::emitNewOrDeleteBuiltinCall(const FunctionProtoType *type, const CallExpr *callExpr, - bool isDelete) { + OverloadedOperatorKind op) { 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); + assert(op == OO_New || op == OO_Delete); + DeclarationName name = astContext.DeclarationNames.getCXXOperatorName(op); 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()); + if (sanOpts.has(SanitizerKind::AllocToken)) { + // TODO: Set !alloc_token metadata. + assert(!cir::MissingFeatures::allocToken()); + cgm.errorNYI("Alloc token sanitizer not yet supported!"); + } // Emit the call to operator new/delete. return emitNewDeleteCall(*this, funcDecl, type, args); diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h index 0cfcc2be0255e..44abc82300d97 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.h +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h @@ -30,6 +30,7 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/Stmt.h" #include "clang/AST/Type.h" +#include "clang/Basic/OperatorKinds.h" #include "clang/CIR/Dialect/IR/CIRDialect.h" #include "clang/CIR/MissingFeatures.h" #include "clang/CIR/TypeEvaluationKind.h" @@ -1477,7 +1478,8 @@ class CIRGenFunction : public CIRGenTypeCache { RValue emitCXXPseudoDestructorExpr(const CXXPseudoDestructorExpr *expr); RValue emitNewOrDeleteBuiltinCall(const FunctionProtoType *type, - const CallExpr *call, bool isDelete); + const CallExpr *callExpr, + OverloadedOperatorKind op); void emitCXXTemporary(const CXXTemporary *temporary, QualType tempType, Address ptr); From 70abb9084a681c5a5f470bcf66b0d6163969c3e4 Mon Sep 17 00:00:00 2001 From: hhuebner <[email protected]> Date: Wed, 19 Nov 2025 14:43:47 +0100 Subject: [PATCH 5/5] Feedback --- clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp index 2fbad2ecce0d3..bcca9181bebfd 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp @@ -22,6 +22,7 @@ #include "clang/AST/Expr.h" #include "clang/AST/GlobalDecl.h" #include "clang/Basic/Builtins.h" +#include "clang/Basic/OperatorKinds.h" #include "clang/CIR/Dialect/IR/CIRTypes.h" #include "clang/CIR/MissingFeatures.h" #include "llvm/Support/ErrorHandling.h" @@ -523,10 +524,10 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID, } case Builtin::BI__builtin_operator_new: return emitNewOrDeleteBuiltinCall( - e->getCallee()->getType()->castAs<FunctionProtoType>(), e, false); + e->getCallee()->getType()->castAs<FunctionProtoType>(), e, OO_New); case Builtin::BI__builtin_operator_delete: emitNewOrDeleteBuiltinCall( - e->getCallee()->getType()->castAs<FunctionProtoType>(), e, true); + e->getCallee()->getType()->castAs<FunctionProtoType>(), e, OO_Delete); return RValue::get(nullptr); } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
