[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