Skip to content

Commit

Permalink
[clang][bytecode] Implement using operator new/operator delete (llvm#…
Browse files Browse the repository at this point in the history
…107679)

Reuse the __builtin_operator_{new,delete} implementations.
  • Loading branch information
tbaederr authored Sep 7, 2024
1 parent 7d4afba commit 78cf9b8
Show file tree
Hide file tree
Showing 7 changed files with 43 additions and 18 deletions.
31 changes: 21 additions & 10 deletions clang/lib/AST/ByteCode/Compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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()) {
Expand All @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/ByteCode/Compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,
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);
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/AST/ByteCode/Interp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1178,15 +1178,15 @@ 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);

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;
}
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/AST/ByteCode/Interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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,
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/AST/ByteCode/InterpBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/ByteCode/Opcodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ def CallVirt : Opcode {
}

def CallBI : Opcode {
let Args = [ArgFunction, ArgCallExpr];
let Args = [ArgFunction, ArgCallExpr, ArgUint32];
}

def CallPtr : Opcode {
Expand Down
14 changes: 14 additions & 0 deletions clang/test/AST/ByteCode/new-delete.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 78cf9b8

Please sign in to comment.