Skip to content

Commit e086d7b

Browse files
authored
[clang][bytecode] Don't create function frames for builtin calls (llvm#137607)
They don't have local variables etc. so don't create frames for them.
1 parent 73d90ec commit e086d7b

File tree

7 files changed

+52
-62
lines changed

7 files changed

+52
-62
lines changed

clang/lib/AST/ByteCode/Compiler.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4825,7 +4825,7 @@ bool Compiler<Emitter>::VisitBuiltinCallExpr(const CallExpr *E,
48254825
return false;
48264826
}
48274827

4828-
if (!Func->isUnevaluatedBuiltin()) {
4828+
if (!Context::isUnevaluatedBuiltin(BuiltinID)) {
48294829
// Put arguments on the stack.
48304830
for (const auto *Arg : E->arguments()) {
48314831
if (!this->visit(Arg))

clang/lib/AST/ByteCode/Context.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,3 +450,9 @@ unsigned Context::collectBaseOffset(const RecordDecl *BaseDecl,
450450
const Record *Context::getRecord(const RecordDecl *D) const {
451451
return P->getOrCreateRecord(D);
452452
}
453+
454+
bool Context::isUnevaluatedBuiltin(unsigned ID) {
455+
return ID == Builtin::BI__builtin_classify_type ||
456+
ID == Builtin::BI__builtin_os_log_format_buffer_size ||
457+
ID == Builtin::BI__builtin_constant_p || ID == Builtin::BI__noop;
458+
}

clang/lib/AST/ByteCode/Context.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,13 @@ class Context final {
111111

112112
unsigned getEvalID() const { return EvalID; }
113113

114+
/// Unevaluated builtins don't get their arguments put on the stack
115+
/// automatically. They instead operate on the AST of their Call
116+
/// Expression.
117+
/// Similar information is available via ASTContext::BuiltinInfo,
118+
/// but that is not correct for our use cases.
119+
static bool isUnevaluatedBuiltin(unsigned ID);
120+
114121
private:
115122
/// Runs a function.
116123
bool Run(State &Parent, const Function *Func);

clang/lib/AST/ByteCode/Function.cpp

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -62,19 +62,3 @@ SourceInfo Function::getSource(CodePtr PC) const {
6262
return SrcMap.back().second;
6363
return It->second;
6464
}
65-
66-
/// Unevaluated builtins don't get their arguments put on the stack
67-
/// automatically. They instead operate on the AST of their Call
68-
/// Expression.
69-
/// Similar information is available via ASTContext::BuiltinInfo,
70-
/// but that is not correct for our use cases.
71-
static bool isUnevaluatedBuiltin(unsigned BuiltinID) {
72-
return BuiltinID == Builtin::BI__builtin_classify_type ||
73-
BuiltinID == Builtin::BI__builtin_os_log_format_buffer_size ||
74-
BuiltinID == Builtin::BI__builtin_constant_p ||
75-
BuiltinID == Builtin::BI__noop;
76-
}
77-
78-
bool Function::isUnevaluatedBuiltin() const {
79-
return ::isUnevaluatedBuiltin(BuiltinID);
80-
}

clang/lib/AST/ByteCode/Function.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,8 +202,6 @@ class Function final {
202202

203203
bool isBuiltin() const { return getBuiltinID() != 0; }
204204

205-
bool isUnevaluatedBuiltin() const;
206-
207205
unsigned getNumParams() const { return ParamTypes.size(); }
208206

209207
/// Returns the number of parameter this function takes when it's called,

clang/lib/AST/ByteCode/Interp.cpp

Lines changed: 1 addition & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -251,22 +251,6 @@ void cleanupAfterFunctionCall(InterpState &S, CodePtr OpPC,
251251
assert(S.Current);
252252
assert(Func);
253253

254-
if (Func->isUnevaluatedBuiltin())
255-
return;
256-
257-
// Some builtin functions require us to only look at the call site, since
258-
// the classified parameter types do not match.
259-
if (unsigned BID = Func->getBuiltinID();
260-
BID && S.getASTContext().BuiltinInfo.hasCustomTypechecking(BID)) {
261-
const auto *CE =
262-
cast<CallExpr>(S.Current->Caller->getExpr(S.Current->getRetPC()));
263-
for (int32_t I = CE->getNumArgs() - 1; I >= 0; --I) {
264-
const Expr *A = CE->getArg(I);
265-
popArg(S, A);
266-
}
267-
return;
268-
}
269-
270254
if (S.Current->Caller && Func->isVariadic()) {
271255
// CallExpr we're look for is at the return PC of the current function, i.e.
272256
// in the caller.
@@ -1630,23 +1614,8 @@ bool CallBI(InterpState &S, CodePtr OpPC, const Function *Func,
16301614
if (BuiltinID == Builtin::BI__builtin_operator_new &&
16311615
S.checkingPotentialConstantExpression())
16321616
return false;
1633-
auto NewFrame = std::make_unique<InterpFrame>(S, Func, OpPC);
1634-
1635-
InterpFrame *FrameBefore = S.Current;
1636-
S.Current = NewFrame.get();
1637-
1638-
if (InterpretBuiltin(S, OpPC, Func, CE, BuiltinID)) {
1639-
// Release ownership of NewFrame to prevent it from being deleted.
1640-
NewFrame.release(); // Frame was deleted already.
1641-
// Ensure that S.Current is correctly reset to the previous frame.
1642-
assert(S.Current == FrameBefore);
1643-
return true;
1644-
}
16451617

1646-
// Interpreting the function failed somehow. Reset to
1647-
// previous state.
1648-
S.Current = FrameBefore;
1649-
return false;
1618+
return InterpretBuiltin(S, OpPC, Func, CE, BuiltinID);
16501619
}
16511620

16521621
bool CallPtr(InterpState &S, CodePtr OpPC, uint32_t ArgSize,

clang/lib/AST/ByteCode/InterpBuiltin.cpp

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -81,14 +81,41 @@ static void assignInteger(Pointer &Dest, PrimType ValueT, const APSInt &Value) {
8181
ValueT, { Dest.deref<T>() = T::from(static_cast<T>(Value)); });
8282
}
8383

84+
template <PrimType Name, class V = typename PrimConv<Name>::T>
85+
static bool retBI(InterpState &S, const CallExpr *Call, unsigned BuiltinID) {
86+
// The return value of the function is already on the stack.
87+
// Remove it, get rid of all the arguments and add it back.
88+
const V &Val = S.Stk.pop<V>();
89+
if (!Context::isUnevaluatedBuiltin(BuiltinID)) {
90+
for (int32_t I = Call->getNumArgs() - 1; I >= 0; --I) {
91+
const Expr *A = Call->getArg(I);
92+
PrimType Ty = S.getContext().classify(A).value_or(PT_Ptr);
93+
TYPE_SWITCH(Ty, S.Stk.discard<T>());
94+
}
95+
}
96+
S.Stk.push<V>(Val);
97+
return true;
98+
}
99+
84100
static bool retPrimValue(InterpState &S, CodePtr OpPC,
85-
std::optional<PrimType> &T) {
86-
if (!T)
87-
return RetVoid(S, OpPC);
101+
std::optional<PrimType> &T, const CallExpr *Call,
102+
unsigned BuiltinID) {
103+
104+
if (!T) {
105+
if (!Context::isUnevaluatedBuiltin(BuiltinID)) {
106+
for (int32_t I = Call->getNumArgs() - 1; I >= 0; --I) {
107+
const Expr *A = Call->getArg(I);
108+
PrimType Ty = S.getContext().classify(A).value_or(PT_Ptr);
109+
TYPE_SWITCH(Ty, S.Stk.discard<T>());
110+
}
111+
}
112+
113+
return true;
114+
}
88115

89116
#define RET_CASE(X) \
90117
case X: \
91-
return Ret<X>(S, OpPC);
118+
return retBI<X>(S, Call, BuiltinID);
92119
switch (*T) {
93120
RET_CASE(PT_Ptr);
94121
RET_CASE(PT_Float);
@@ -147,17 +174,16 @@ static bool interp__builtin_is_constant_evaluated(InterpState &S, CodePtr OpPC,
147174
// The one above that, potentially the one for std::is_constant_evaluated().
148175
if (S.inConstantContext() && !S.checkingPotentialConstantExpression() &&
149176
S.getEvalStatus().Diag &&
150-
(Depth == 1 || (Depth == 2 && isStdCall(Caller->getCallee())))) {
151-
if (Caller->Caller && isStdCall(Caller->getCallee())) {
152-
const Expr *E = Caller->Caller->getExpr(Caller->getRetPC());
177+
(Depth == 0 || (Depth == 1 && isStdCall(Frame->getCallee())))) {
178+
if (Caller && isStdCall(Frame->getCallee())) {
179+
const Expr *E = Caller->getExpr(Caller->getRetPC());
153180
S.report(E->getExprLoc(),
154181
diag::warn_is_constant_evaluated_always_true_constexpr)
155182
<< "std::is_constant_evaluated" << E->getSourceRange();
156183
} else {
157-
const Expr *E = Frame->Caller->getExpr(Frame->getRetPC());
158-
S.report(E->getExprLoc(),
184+
S.report(Call->getExprLoc(),
159185
diag::warn_is_constant_evaluated_always_true_constexpr)
160-
<< "__builtin_is_constant_evaluated" << E->getSourceRange();
186+
<< "__builtin_is_constant_evaluated" << Call->getSourceRange();
161187
}
162188
}
163189

@@ -2675,7 +2701,7 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
26752701
return false;
26762702
}
26772703

2678-
return retPrimValue(S, OpPC, ReturnT);
2704+
return retPrimValue(S, OpPC, ReturnT, Call, BuiltinID);
26792705
}
26802706

26812707
bool InterpretOffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E,

0 commit comments

Comments
 (0)