[clang] 5589f29 - [clang][Interp] Merge FunctionPointer into Pointer

Timm Bäder via cfe-commits cfe-commits at lists.llvm.org
Tue Jul 23 07:14:24 PDT 2024


Author: Timm Bäder
Date: 2024-07-23T16:06:04+02:00
New Revision: 5589f2977117ec4685018472ca5f01355424bab9

URL: https://github.com/llvm/llvm-project/commit/5589f2977117ec4685018472ca5f01355424bab9
DIFF: https://github.com/llvm/llvm-project/commit/5589f2977117ec4685018472ca5f01355424bab9.diff

LOG: [clang][Interp] Merge FunctionPointer into Pointer

Back when I introduced the FunctionPointer class, I assumed that we
can always know that a Pointer is not a FunctionPointer. With the
DecayPtr op, that changed somewhat, but the information whether a
Pointer was created through a FunctionPointer was lost.

However, we need this information, especially when we're in the
codegen stage.

Added: 
    

Modified: 
    clang/lib/AST/Interp/FunctionPointer.h
    clang/lib/AST/Interp/Interp.cpp
    clang/lib/AST/Interp/Interp.h
    clang/lib/AST/Interp/Pointer.cpp
    clang/lib/AST/Interp/Pointer.h

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/Interp/FunctionPointer.h b/clang/lib/AST/Interp/FunctionPointer.h
index 0f2c6e571a1d8..d92cd32933fcd 100644
--- a/clang/lib/AST/Interp/FunctionPointer.h
+++ b/clang/lib/AST/Interp/FunctionPointer.h
@@ -23,11 +23,10 @@ class FunctionPointer final {
   bool Valid;
 
 public:
-  FunctionPointer(const Function *Func) : Func(Func), Valid(true) {
-    assert(Func);
-  }
+  FunctionPointer() = default;
+  FunctionPointer(const Function *Func) : Func(Func), Valid(true) {}
 
-  FunctionPointer(uintptr_t IntVal = 0, const Descriptor *Desc = nullptr)
+  FunctionPointer(uintptr_t IntVal, const Descriptor *Desc = nullptr)
       : Func(reinterpret_cast<const Function *>(IntVal)), Valid(false) {}
 
   const Function *getFunction() const { return Func; }

diff  --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp
index 6fcd90e5f5849..bf29b85041d82 100644
--- a/clang/lib/AST/Interp/Interp.cpp
+++ b/clang/lib/AST/Interp/Interp.cpp
@@ -333,7 +333,7 @@ bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc) {
 }
 
 static bool CheckConstant(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
-  if (Ptr.isIntegralPointer())
+  if (!Ptr.isBlockPointer())
     return true;
   return CheckConstant(S, OpPC, Ptr.getDeclDesc());
 }

diff  --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h
index 8e96f78d90568..492802897f013 100644
--- a/clang/lib/AST/Interp/Interp.h
+++ b/clang/lib/AST/Interp/Interp.h
@@ -2811,6 +2811,13 @@ inline bool DecayPtr(InterpState &S, CodePtr OpPC) {
   using ToT = typename PrimConv<TOut>::T;
 
   const FromT &OldPtr = S.Stk.pop<FromT>();
+
+  if constexpr (std::is_same_v<FromT, FunctionPointer> &&
+                std::is_same_v<ToT, Pointer>) {
+    S.Stk.push<Pointer>(OldPtr.getFunction());
+    return true;
+  }
+
   S.Stk.push<ToT>(ToT(OldPtr.getIntegerRepresentation(), nullptr));
   return true;
 }

diff  --git a/clang/lib/AST/Interp/Pointer.cpp b/clang/lib/AST/Interp/Pointer.cpp
index 29579f5db40b6..3ac8bc2b09709 100644
--- a/clang/lib/AST/Interp/Pointer.cpp
+++ b/clang/lib/AST/Interp/Pointer.cpp
@@ -55,7 +55,7 @@ Pointer::Pointer(Pointer &&P)
 }
 
 Pointer::~Pointer() {
-  if (isIntegralPointer())
+  if (!isBlockPointer())
     return;
 
   if (Block *Pointee = PointeeStorage.BS.Pointee) {
@@ -87,6 +87,8 @@ void Pointer::operator=(const Pointer &P) {
       PointeeStorage.BS.Pointee->addPointer(this);
   } else if (P.isIntegralPointer()) {
     PointeeStorage.Int = P.PointeeStorage.Int;
+  } else if (P.isFunctionPointer()) {
+    PointeeStorage.Fn = P.PointeeStorage.Fn;
   } else {
     assert(false && "Unhandled storage kind");
   }
@@ -115,6 +117,8 @@ void Pointer::operator=(Pointer &&P) {
       PointeeStorage.BS.Pointee->addPointer(this);
   } else if (P.isIntegralPointer()) {
     PointeeStorage.Int = P.PointeeStorage.Int;
+  } else if (P.isFunctionPointer()) {
+    PointeeStorage.Fn = P.PointeeStorage.Fn;
   } else {
     assert(false && "Unhandled storage kind");
   }
@@ -131,6 +135,8 @@ APValue Pointer::toAPValue(const ASTContext &ASTCtx) const {
                    CharUnits::fromQuantity(asIntPointer().Value + this->Offset),
                    Path,
                    /*IsOnePastEnd=*/false, /*IsNullPtr=*/false);
+  if (isFunctionPointer())
+    return asFunctionPointer().toAPValue(ASTCtx);
 
   // Build the lvalue base from the block.
   const Descriptor *Desc = getDeclDesc();
@@ -263,7 +269,7 @@ std::string Pointer::toDiagnosticString(const ASTContext &Ctx) const {
 }
 
 bool Pointer::isInitialized() const {
-  if (isIntegralPointer())
+  if (!isBlockPointer())
     return true;
 
   if (isRoot() && PointeeStorage.BS.Base == sizeof(GlobalInlineDescriptor)) {
@@ -299,7 +305,7 @@ bool Pointer::isInitialized() const {
 }
 
 void Pointer::initialize() const {
-  if (isIntegralPointer())
+  if (!isBlockPointer())
     return;
 
   assert(PointeeStorage.BS.Pointee && "Cannot initialize null pointer");
@@ -368,10 +374,15 @@ bool Pointer::hasSameBase(const Pointer &A, const Pointer &B) {
 
   if (A.isIntegralPointer() && B.isIntegralPointer())
     return true;
+  if (A.isFunctionPointer() && B.isFunctionPointer())
+    return true;
 
   if (A.isIntegralPointer() || B.isIntegralPointer())
     return A.getSource() == B.getSource();
 
+  if (A.StorageKind != B.StorageKind)
+    return false;
+
   return A.asBlockPointer().Pointee == B.asBlockPointer().Pointee;
 }
 

diff  --git a/clang/lib/AST/Interp/Pointer.h b/clang/lib/AST/Interp/Pointer.h
index e351699023ba5..6b0c31358159c 100644
--- a/clang/lib/AST/Interp/Pointer.h
+++ b/clang/lib/AST/Interp/Pointer.h
@@ -14,6 +14,7 @@
 #define LLVM_CLANG_AST_INTERP_POINTER_H
 
 #include "Descriptor.h"
+#include "FunctionPointer.h"
 #include "InterpBlock.h"
 #include "clang/AST/ComparisonCategories.h"
 #include "clang/AST/Decl.h"
@@ -45,7 +46,7 @@ struct IntPointer {
   uint64_t Value;
 };
 
-enum class Storage { Block, Int };
+enum class Storage { Block, Int, Fn };
 
 /// A pointer to a memory block, live or dead.
 ///
@@ -96,6 +97,10 @@ class Pointer {
     PointeeStorage.Int.Value = Address;
     PointeeStorage.Int.Desc = Desc;
   }
+  Pointer(const Function *F, uint64_t Offset = 0)
+      : Offset(Offset), StorageKind(Storage::Fn) {
+    PointeeStorage.Fn = FunctionPointer(F);
+  }
   ~Pointer();
 
   void operator=(const Pointer &P);
@@ -126,6 +131,8 @@ class Pointer {
   uint64_t getIntegerRepresentation() const {
     if (isIntegralPointer())
       return asIntPointer().Value + (Offset * elemSize());
+    if (isFunctionPointer())
+      return asFunctionPointer().getIntegerRepresentation();
     return reinterpret_cast<uint64_t>(asBlockPointer().Pointee) + Offset;
   }
 
@@ -137,6 +144,8 @@ class Pointer {
   [[nodiscard]] Pointer atIndex(uint64_t Idx) const {
     if (isIntegralPointer())
       return Pointer(asIntPointer().Value, asIntPointer().Desc, Idx);
+    if (isFunctionPointer())
+      return Pointer(asFunctionPointer().getFunction(), Idx);
 
     if (asBlockPointer().Base == RootPtrMark)
       return Pointer(asBlockPointer().Pointee, RootPtrMark,
@@ -247,18 +256,20 @@ class Pointer {
   bool isZero() const {
     if (isBlockPointer())
       return asBlockPointer().Pointee == nullptr;
+    if (isFunctionPointer())
+      return asFunctionPointer().isZero();
     assert(isIntegralPointer());
     return asIntPointer().Value == 0 && Offset == 0;
   }
   /// Checks if the pointer is live.
   bool isLive() const {
-    if (isIntegralPointer())
+    if (!isBlockPointer())
       return true;
     return asBlockPointer().Pointee && !asBlockPointer().Pointee->IsDead;
   }
   /// Checks if the item is a field in an object.
   bool isField() const {
-    if (isIntegralPointer())
+    if (!isBlockPointer())
       return false;
 
     return !isRoot() && getFieldDesc()->asDecl();
@@ -268,6 +279,8 @@ class Pointer {
   const Descriptor *getDeclDesc() const {
     if (isIntegralPointer())
       return asIntPointer().Desc;
+    if (isFunctionPointer())
+      return nullptr;
 
     assert(isBlockPointer());
     assert(asBlockPointer().Pointee);
@@ -279,7 +292,10 @@ class Pointer {
   DeclTy getSource() const {
     if (isBlockPointer())
       return getDeclDesc()->getSource();
-
+    if (isFunctionPointer()) {
+      const Function *F = asFunctionPointer().getFunction();
+      return F ? F->getDecl() : DeclTy();
+    }
     assert(isIntegralPointer());
     return asIntPointer().Desc ? asIntPointer().Desc->getSource() : DeclTy();
   }
@@ -354,6 +370,7 @@ class Pointer {
   /// Returns the offset into an array.
   unsigned getOffset() const {
     assert(Offset != PastEndMark && "invalid offset");
+    assert(isBlockPointer());
     if (asBlockPointer().Base == RootPtrMark)
       return Offset;
 
@@ -421,8 +438,14 @@ class Pointer {
     assert(isIntegralPointer());
     return PointeeStorage.Int;
   }
+  [[nodiscard]] const FunctionPointer &asFunctionPointer() const {
+    assert(isFunctionPointer());
+    return PointeeStorage.Fn;
+  }
+
   bool isBlockPointer() const { return StorageKind == Storage::Block; }
   bool isIntegralPointer() const { return StorageKind == Storage::Int; }
+  bool isFunctionPointer() const { return StorageKind == Storage::Fn; }
 
   /// Returns the record descriptor of a class.
   const Record *getRecord() const { return getFieldDesc()->ElemRecord; }
@@ -445,7 +468,7 @@ class Pointer {
   }
   /// Checks if the storage is static.
   bool isStatic() const {
-    if (isIntegralPointer())
+    if (!isBlockPointer())
       return true;
     assert(asBlockPointer().Pointee);
     return asBlockPointer().Pointee->isStatic();
@@ -469,7 +492,7 @@ class Pointer {
   }
 
   bool isWeak() const {
-    if (isIntegralPointer())
+    if (!isBlockPointer())
       return false;
 
     assert(isBlockPointer());
@@ -528,8 +551,8 @@ class Pointer {
 
   /// Returns the number of elements.
   unsigned getNumElems() const {
-    if (isIntegralPointer())
-      return ~unsigned(0);
+    if (!isBlockPointer())
+      return ~0u;
     return getSize() / elemSize();
   }
 
@@ -555,7 +578,7 @@ class Pointer {
 
   /// Checks if the index is one past end.
   bool isOnePastEnd() const {
-    if (isIntegralPointer())
+    if (isIntegralPointer() || isFunctionPointer())
       return false;
 
     if (!asBlockPointer().Pointee)
@@ -692,6 +715,7 @@ class Pointer {
   union {
     BlockPointer BS;
     IntPointer Int;
+    FunctionPointer Fn;
   } PointeeStorage;
   Storage StorageKind = Storage::Int;
 };


        


More information about the cfe-commits mailing list