[clang][Interp] Check This pointer without creating InterpFrame
authorTimm Bäder <tbaeder@redhat.com>
Thu, 26 Jan 2023 13:07:46 +0000 (14:07 +0100)
committerTimm Bäder <tbaeder@redhat.com>
Fri, 31 Mar 2023 14:18:15 +0000 (16:18 +0200)
The InterpFrame was only created so early so we could use getThis().
However, we need to know the Function when creating the InterpFrame and
in the case of virtual functions, we need to determine what function to
call at interpretation time.

Get the This pointer ourselves and just create the InterpFrame later.

Differential Revision: https://reviews.llvm.org/D142617

clang/lib/AST/Interp/Interp.h
clang/lib/AST/Interp/InterpStack.cpp
clang/lib/AST/Interp/InterpStack.h

index bb34737..afc5f24 100644 (file)
@@ -1492,10 +1492,11 @@ inline bool CheckGlobalCtor(InterpState &S, CodePtr &PC) {
 }
 
 inline bool Call(InterpState &S, CodePtr &PC, const Function *Func) {
-  auto NewFrame = std::make_unique<InterpFrame>(S, Func, PC);
-  Pointer ThisPtr;
   if (Func->hasThisPointer()) {
-    ThisPtr = NewFrame->getThis();
+    size_t ThisOffset =
+        Func->getArgSize() + (Func->hasRVO() ? primSize(PT_Ptr) : 0);
+    const Pointer &ThisPtr = S.Stk.peek<Pointer>(ThisOffset);
+
     if (!CheckInvoke(S, PC, ThisPtr))
       return false;
 
@@ -1506,6 +1507,7 @@ inline bool Call(InterpState &S, CodePtr &PC, const Function *Func) {
   if (!CheckCallable(S, PC, Func))
     return false;
 
+  auto NewFrame = std::make_unique<InterpFrame>(S, Func, PC);
   InterpFrame *FrameBefore = S.Current;
   S.Current = NewFrame.get();
 
index 7fe678e..63a088b 100644 (file)
@@ -46,7 +46,7 @@ void *InterpStack::grow(size_t Size) {
   return Object;
 }
 
-void *InterpStack::peek(size_t Size) const {
+void *InterpStack::peekData(size_t Size) const {
   assert(Chunk && "Stack is empty!");
 
   StackChunk *Ptr = Chunk;
index e625ffd..435120d 100644 (file)
@@ -64,11 +64,16 @@ public:
 
   /// Returns a reference to the value on the top of the stack.
   template <typename T> T &peek() const {
-    return *reinterpret_cast<T *>(peek(aligned_size<T>()));
+    return *reinterpret_cast<T *>(peekData(aligned_size<T>()));
+  }
+
+  template <typename T> T &peek(size_t Offset) const {
+    assert(aligned(Offset));
+    return *reinterpret_cast<T *>(peekData(Offset));
   }
 
   /// Returns a pointer to the top object.
-  void *top() const { return Chunk ? peek(0) : nullptr; }
+  void *top() const { return Chunk ? peekData(0) : nullptr; }
 
   /// Returns the size of the stack in bytes.
   size_t size() const { return StackSize; }
@@ -90,7 +95,7 @@ private:
   /// Grows the stack to accommodate a value and returns a pointer to it.
   void *grow(size_t Size);
   /// Returns a pointer from the top of the stack.
-  void *peek(size_t Size) const;
+  void *peekData(size_t Size) const;
   /// Shrinks the stack.
   void shrink(size_t Size);