-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[clang][bytecode] Don't create function frames for builtin calls #137607
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-clang Author: Timm Baeder (tbaederr) ChangesThey don't have local variables etc. so don't create frames for them. Full diff: https://github.com/llvm/llvm-project/pull/137607.diff 7 Files Affected:
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index a9610835c81e6..a1b2d13a15fc6 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -4825,7 +4825,7 @@ bool Compiler<Emitter>::VisitBuiltinCallExpr(const CallExpr *E,
return false;
}
- if (!Func->isUnevaluatedBuiltin()) {
+ if (!Context::isUnevaluatedBuiltin(BuiltinID)) {
// Put arguments on the stack.
for (const auto *Arg : E->arguments()) {
if (!this->visit(Arg))
diff --git a/clang/lib/AST/ByteCode/Context.cpp b/clang/lib/AST/ByteCode/Context.cpp
index 431ccfcc821b1..b35b30cc20d81 100644
--- a/clang/lib/AST/ByteCode/Context.cpp
+++ b/clang/lib/AST/ByteCode/Context.cpp
@@ -450,3 +450,9 @@ unsigned Context::collectBaseOffset(const RecordDecl *BaseDecl,
const Record *Context::getRecord(const RecordDecl *D) const {
return P->getOrCreateRecord(D);
}
+
+bool Context::isUnevaluatedBuiltin(unsigned ID) {
+ return ID == Builtin::BI__builtin_classify_type ||
+ ID == Builtin::BI__builtin_os_log_format_buffer_size ||
+ ID == Builtin::BI__builtin_constant_p || ID == Builtin::BI__noop;
+}
diff --git a/clang/lib/AST/ByteCode/Context.h b/clang/lib/AST/ByteCode/Context.h
index 8b542e6474780..5a39f40ef3f11 100644
--- a/clang/lib/AST/ByteCode/Context.h
+++ b/clang/lib/AST/ByteCode/Context.h
@@ -111,6 +111,13 @@ class Context final {
unsigned getEvalID() const { return EvalID; }
+ /// Unevaluated builtins don't get their arguments put on the stack
+ /// automatically. They instead operate on the AST of their Call
+ /// Expression.
+ /// Similar information is available via ASTContext::BuiltinInfo,
+ /// but that is not correct for our use cases.
+ static bool isUnevaluatedBuiltin(unsigned ID);
+
private:
/// Runs a function.
bool Run(State &Parent, const Function *Func);
diff --git a/clang/lib/AST/ByteCode/Function.cpp b/clang/lib/AST/ByteCode/Function.cpp
index 764aa4a851cf4..17f2caa55f503 100644
--- a/clang/lib/AST/ByteCode/Function.cpp
+++ b/clang/lib/AST/ByteCode/Function.cpp
@@ -62,19 +62,3 @@ SourceInfo Function::getSource(CodePtr PC) const {
return SrcMap.back().second;
return It->second;
}
-
-/// Unevaluated builtins don't get their arguments put on the stack
-/// automatically. They instead operate on the AST of their Call
-/// Expression.
-/// Similar information is available via ASTContext::BuiltinInfo,
-/// but that is not correct for our use cases.
-static bool isUnevaluatedBuiltin(unsigned BuiltinID) {
- return BuiltinID == Builtin::BI__builtin_classify_type ||
- BuiltinID == Builtin::BI__builtin_os_log_format_buffer_size ||
- BuiltinID == Builtin::BI__builtin_constant_p ||
- BuiltinID == Builtin::BI__noop;
-}
-
-bool Function::isUnevaluatedBuiltin() const {
- return ::isUnevaluatedBuiltin(BuiltinID);
-}
diff --git a/clang/lib/AST/ByteCode/Function.h b/clang/lib/AST/ByteCode/Function.h
index c114cfe5ba29a..ea3baf6fca4d6 100644
--- a/clang/lib/AST/ByteCode/Function.h
+++ b/clang/lib/AST/ByteCode/Function.h
@@ -202,8 +202,6 @@ class Function final {
bool isBuiltin() const { return getBuiltinID() != 0; }
- bool isUnevaluatedBuiltin() const;
-
unsigned getNumParams() const { return ParamTypes.size(); }
/// Returns the number of parameter this function takes when it's called,
diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp
index 4f94bb5a85192..af9b3bf92ce55 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -251,22 +251,6 @@ void cleanupAfterFunctionCall(InterpState &S, CodePtr OpPC,
assert(S.Current);
assert(Func);
- if (Func->isUnevaluatedBuiltin())
- return;
-
- // Some builtin functions require us to only look at the call site, since
- // the classified parameter types do not match.
- if (unsigned BID = Func->getBuiltinID();
- BID && S.getASTContext().BuiltinInfo.hasCustomTypechecking(BID)) {
- const auto *CE =
- cast<CallExpr>(S.Current->Caller->getExpr(S.Current->getRetPC()));
- for (int32_t I = CE->getNumArgs() - 1; I >= 0; --I) {
- const Expr *A = CE->getArg(I);
- popArg(S, A);
- }
- return;
- }
-
if (S.Current->Caller && Func->isVariadic()) {
// CallExpr we're look for is at the return PC of the current function, i.e.
// in the caller.
@@ -1630,23 +1614,8 @@ bool CallBI(InterpState &S, CodePtr OpPC, const Function *Func,
if (BuiltinID == Builtin::BI__builtin_operator_new &&
S.checkingPotentialConstantExpression())
return false;
- auto NewFrame = std::make_unique<InterpFrame>(S, Func, OpPC);
-
- InterpFrame *FrameBefore = S.Current;
- S.Current = NewFrame.get();
-
- if (InterpretBuiltin(S, OpPC, Func, CE, BuiltinID)) {
- // Release ownership of NewFrame to prevent it from being deleted.
- NewFrame.release(); // Frame was deleted already.
- // Ensure that S.Current is correctly reset to the previous frame.
- assert(S.Current == FrameBefore);
- return true;
- }
- // Interpreting the function failed somehow. Reset to
- // previous state.
- S.Current = FrameBefore;
- return false;
+ return InterpretBuiltin(S, OpPC, Func, CE, BuiltinID);
}
bool CallPtr(InterpState &S, CodePtr OpPC, uint32_t ArgSize,
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index f2e11670e8fff..1828ea42398ad 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -81,14 +81,41 @@ static void assignInteger(Pointer &Dest, PrimType ValueT, const APSInt &Value) {
ValueT, { Dest.deref<T>() = T::from(static_cast<T>(Value)); });
}
+template <PrimType Name, class V = typename PrimConv<Name>::T>
+static bool retBI(InterpState &S, const CallExpr *Call, unsigned BuiltinID) {
+ // The return value of the function is already on the stack.
+ // Remove it, get rid of all the arguments and add it back.
+ const V &Val = S.Stk.pop<V>();
+ if (!Context::isUnevaluatedBuiltin(BuiltinID)) {
+ for (int32_t I = Call->getNumArgs() - 1; I >= 0; --I) {
+ const Expr *A = Call->getArg(I);
+ PrimType Ty = S.getContext().classify(A).value_or(PT_Ptr);
+ TYPE_SWITCH(Ty, S.Stk.discard<T>());
+ }
+ }
+ S.Stk.push<V>(Val);
+ return true;
+}
+
static bool retPrimValue(InterpState &S, CodePtr OpPC,
- std::optional<PrimType> &T) {
- if (!T)
- return RetVoid(S, OpPC);
+ std::optional<PrimType> &T, const CallExpr *Call,
+ unsigned BuiltinID) {
+
+ if (!T) {
+ if (!Context::isUnevaluatedBuiltin(BuiltinID)) {
+ for (int32_t I = Call->getNumArgs() - 1; I >= 0; --I) {
+ const Expr *A = Call->getArg(I);
+ PrimType Ty = S.getContext().classify(A).value_or(PT_Ptr);
+ TYPE_SWITCH(Ty, S.Stk.discard<T>());
+ }
+ }
+
+ return true;
+ }
#define RET_CASE(X) \
case X: \
- return Ret<X>(S, OpPC);
+ return retBI<X>(S, Call, BuiltinID);
switch (*T) {
RET_CASE(PT_Ptr);
RET_CASE(PT_Float);
@@ -2675,7 +2702,7 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
return false;
}
- return retPrimValue(S, OpPC, ReturnT);
+ return retPrimValue(S, OpPC, ReturnT, Call, BuiltinID);
}
bool InterpretOffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E,
|
They don't have local variables etc. so don't create frames for them.
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/66/builds/13178 Here is the relevant piece of the build log for the reference
|
…m#137607) They don't have local variables etc. so don't create frames for them.
…m#137607) They don't have local variables etc. so don't create frames for them.
…m#137607) They don't have local variables etc. so don't create frames for them.
…m#137607) They don't have local variables etc. so don't create frames for them.
They don't have local variables etc. so don't create frames for them.