summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimm Baeder <tbaeder@redhat.com>2024-09-07 12:17:54 +0200
committerGitHub <noreply@github.com>2024-09-07 12:17:54 +0200
commit78cf9b830c78daa5aed51b5ca77bb7db9974d1ec (patch)
tree3064b1ae3065c84aba38b10117664010b4544d8d
parent7d4afba831bcf9b3e50ee7b6a3fbc9c0a7c61597 (diff)
[clang][bytecode] Implement using operator new/operator delete (#107679)
Reuse the __builtin_operator_{new,delete} implementations.
-rw-r--r--clang/lib/AST/ByteCode/Compiler.cpp31
-rw-r--r--clang/lib/AST/ByteCode/Compiler.h2
-rw-r--r--clang/lib/AST/ByteCode/Interp.cpp4
-rw-r--r--clang/lib/AST/ByteCode/Interp.h4
-rw-r--r--clang/lib/AST/ByteCode/InterpBuiltin.cpp4
-rw-r--r--clang/lib/AST/ByteCode/Opcodes.td2
-rw-r--r--clang/test/AST/ByteCode/new-delete.cpp14
7 files changed, 43 insertions, 18 deletions
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index bada8621b968..115b0aa7dd29 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -4070,18 +4070,18 @@ bool Compiler<Emitter>::visitAPValueInitializer(const APValue &Val,
}
template <class Emitter>
-bool Compiler<Emitter>::VisitBuiltinCallExpr(const CallExpr *E) {
+bool Compiler<Emitter>::VisitBuiltinCallExpr(const CallExpr *E,
+ unsigned BuiltinID) {
const Function *Func = getFunction(E->getDirectCallee());
if (!Func)
return false;
// For these, we're expected to ultimately return an APValue pointing
// to the CallExpr. This is needed to get the correct codegen.
- unsigned Builtin = E->getBuiltinCallee();
- if (Builtin == Builtin::BI__builtin___CFStringMakeConstantString ||
- Builtin == Builtin::BI__builtin___NSStringMakeConstantString ||
- Builtin == Builtin::BI__builtin_ptrauth_sign_constant ||
- Builtin == Builtin::BI__builtin_function_start) {
+ if (BuiltinID == Builtin::BI__builtin___CFStringMakeConstantString ||
+ BuiltinID == Builtin::BI__builtin___NSStringMakeConstantString ||
+ BuiltinID == Builtin::BI__builtin_ptrauth_sign_constant ||
+ BuiltinID == Builtin::BI__builtin_function_start) {
if (std::optional<unsigned> GlobalOffset = P.createGlobal(E)) {
if (!this->emitGetPtrGlobal(*GlobalOffset, E))
return false;
@@ -4113,7 +4113,7 @@ bool Compiler<Emitter>::VisitBuiltinCallExpr(const CallExpr *E) {
}
}
- if (!this->emitCallBI(Func, E, E))
+ if (!this->emitCallBI(Func, E, BuiltinID, E))
return false;
if (DiscardResult && !ReturnType->isVoidType()) {
@@ -4126,13 +4126,24 @@ bool Compiler<Emitter>::VisitBuiltinCallExpr(const CallExpr *E) {
template <class Emitter>
bool Compiler<Emitter>::VisitCallExpr(const CallExpr *E) {
- if (E->getBuiltinCallee())
- return VisitBuiltinCallExpr(E);
+ if (unsigned BuiltinID = E->getBuiltinCallee())
+ return VisitBuiltinCallExpr(E, BuiltinID);
+
+ const FunctionDecl *FuncDecl = E->getDirectCallee();
+ // Calls to replaceable operator new/operator delete.
+ if (FuncDecl && FuncDecl->isReplaceableGlobalAllocationFunction()) {
+ if (FuncDecl->getDeclName().getCXXOverloadedOperator() == OO_New ||
+ FuncDecl->getDeclName().getCXXOverloadedOperator() == OO_Array_New) {
+ return VisitBuiltinCallExpr(E, Builtin::BI__builtin_operator_new);
+ } else {
+ assert(FuncDecl->getDeclName().getCXXOverloadedOperator() == OO_Delete);
+ return VisitBuiltinCallExpr(E, Builtin::BI__builtin_operator_delete);
+ }
+ }
QualType ReturnType = E->getCallReturnType(Ctx.getASTContext());
std::optional<PrimType> T = classify(ReturnType);
bool HasRVO = !ReturnType->isVoidType() && !T;
- const FunctionDecl *FuncDecl = E->getDirectCallee();
if (HasRVO) {
if (DiscardResult) {
diff --git a/clang/lib/AST/ByteCode/Compiler.h b/clang/lib/AST/ByteCode/Compiler.h
index eb1252fec054..39c0736cb4e2 100644
--- a/clang/lib/AST/ByteCode/Compiler.h
+++ b/clang/lib/AST/ByteCode/Compiler.h
@@ -133,7 +133,7 @@ public:
bool VisitVectorBinOp(const BinaryOperator *E);
bool VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E);
bool VisitCallExpr(const CallExpr *E);
- bool VisitBuiltinCallExpr(const CallExpr *E);
+ bool VisitBuiltinCallExpr(const CallExpr *E, unsigned BuiltinID);
bool VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E);
bool VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E);
bool VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E);
diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp
index 99d01ca52645..ac02bd6d0334 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -1178,7 +1178,7 @@ bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func,
}
bool CallBI(InterpState &S, CodePtr &PC, const Function *Func,
- const CallExpr *CE) {
+ const CallExpr *CE, uint32_t BuiltinID) {
if (S.checkingPotentialConstantExpression())
return false;
auto NewFrame = std::make_unique<InterpFrame>(S, Func, PC);
@@ -1186,7 +1186,7 @@ bool CallBI(InterpState &S, CodePtr &PC, const Function *Func,
InterpFrame *FrameBefore = S.Current;
S.Current = NewFrame.get();
- if (InterpretBuiltin(S, PC, Func, CE)) {
+ if (InterpretBuiltin(S, PC, Func, CE, BuiltinID)) {
NewFrame.release();
return true;
}
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index 4ca0e05d67c7..7a0011b96069 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -155,7 +155,7 @@ bool Call(InterpState &S, CodePtr OpPC, const Function *Func,
bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func,
uint32_t VarArgSize);
bool CallBI(InterpState &S, CodePtr &PC, const Function *Func,
- const CallExpr *CE);
+ const CallExpr *CE, uint32_t BuiltinID);
bool CallPtr(InterpState &S, CodePtr OpPC, uint32_t ArgSize,
const CallExpr *CE);
@@ -268,7 +268,7 @@ bool Interpret(InterpState &S, APValue &Result);
/// Interpret a builtin function.
bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
- const CallExpr *Call);
+ const CallExpr *Call, uint32_t BuiltinID);
/// Interpret an offsetof operation.
bool InterpretOffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E,
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index 49fbaa3cbcb3..51c77b7da1a6 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -1395,13 +1395,13 @@ static bool interp__builtin_operator_delete(InterpState &S, CodePtr OpPC,
}
bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
- const CallExpr *Call) {
+ const CallExpr *Call, uint32_t BuiltinID) {
const InterpFrame *Frame = S.Current;
APValue Dummy;
std::optional<PrimType> ReturnT = S.getContext().classify(Call);
- switch (F->getBuiltinID()) {
+ switch (BuiltinID) {
case Builtin::BI__builtin_is_constant_evaluated:
if (!interp__builtin_is_constant_evaluated(S, OpPC, Frame, Call))
return false;
diff --git a/clang/lib/AST/ByteCode/Opcodes.td b/clang/lib/AST/ByteCode/Opcodes.td
index 5d7a6e94f6e2..e3a88c069847 100644
--- a/clang/lib/AST/ByteCode/Opcodes.td
+++ b/clang/lib/AST/ByteCode/Opcodes.td
@@ -202,7 +202,7 @@ def CallVirt : Opcode {
}
def CallBI : Opcode {
- let Args = [ArgFunction, ArgCallExpr];
+ let Args = [ArgFunction, ArgCallExpr, ArgUint32];
}
def CallPtr : Opcode {
diff --git a/clang/test/AST/ByteCode/new-delete.cpp b/clang/test/AST/ByteCode/new-delete.cpp
index 556efa65ae11..902ab4aab10f 100644
--- a/clang/test/AST/ByteCode/new-delete.cpp
+++ b/clang/test/AST/ByteCode/new-delete.cpp
@@ -601,6 +601,19 @@ namespace std {
};
}
+/// Specialization for float, using operator new/delete.
+namespace std {
+ using size_t = decltype(sizeof(0));
+ template<> struct allocator<float> {
+ constexpr float *allocate(size_t N) {
+ return (float*)operator new (sizeof(float) * N);
+ }
+ constexpr void deallocate(void *p) {
+ operator delete(p);
+ }
+ };
+}
+
namespace OperatorNewDelete {
constexpr bool mismatched(int alloc_kind, int dealloc_kind) {
@@ -696,6 +709,7 @@ namespace OperatorNewDelete {
constexpr int no_deallocate_nullptr = (std::allocator<int>().deallocate(nullptr), 1); // both-error {{constant expression}} \
// both-note {{in call}}
+ static_assert((std::allocator<float>().deallocate(std::allocator<float>().allocate(10)), 1) == 1);
}
#else