https://github.com/tbaederr created 
https://github.com/llvm/llvm-project/pull/137607

They don't have local variables etc. so don't create frames for them.

>From 9ce67008616c3fc8f59f1071fdaede24227cd678 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbae...@redhat.com>
Date: Mon, 28 Apr 2025 11:40:36 +0200
Subject: [PATCH] [clang][bytecode] Don't create function frames for builtin
 calls

They don't have local variables etc. so don't create frames for them.
---
 clang/lib/AST/ByteCode/Compiler.cpp      |  2 +-
 clang/lib/AST/ByteCode/Context.cpp       |  6 ++++
 clang/lib/AST/ByteCode/Context.h         |  7 +++++
 clang/lib/AST/ByteCode/Function.cpp      | 16 ----------
 clang/lib/AST/ByteCode/Function.h        |  2 --
 clang/lib/AST/ByteCode/Interp.cpp        | 33 +--------------------
 clang/lib/AST/ByteCode/InterpBuiltin.cpp | 37 ++++++++++++++++++++----
 7 files changed, 47 insertions(+), 56 deletions(-)

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,

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to