Skip to content

Commit d9b34b0

Browse files
tbaederryuxuanchen1997
authored andcommitted
[clang][Interp] Merge FunctionPointer into Pointer
Summary: 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. Test Plan: Reviewers: Subscribers: Tasks: Tags: Differential Revision: https://phabricator.intern.facebook.com/D60251268
1 parent 0040084 commit d9b34b0

File tree

5 files changed

+58
-17
lines changed

5 files changed

+58
-17
lines changed

clang/lib/AST/Interp/FunctionPointer.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,10 @@ class FunctionPointer final {
2323
bool Valid;
2424

2525
public:
26-
FunctionPointer(const Function *Func) : Func(Func), Valid(true) {
27-
assert(Func);
28-
}
26+
FunctionPointer() = default;
27+
FunctionPointer(const Function *Func) : Func(Func), Valid(true) {}
2928

30-
FunctionPointer(uintptr_t IntVal = 0, const Descriptor *Desc = nullptr)
29+
FunctionPointer(uintptr_t IntVal, const Descriptor *Desc = nullptr)
3130
: Func(reinterpret_cast<const Function *>(IntVal)), Valid(false) {}
3231

3332
const Function *getFunction() const { return Func; }

clang/lib/AST/Interp/Interp.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc) {
333333
}
334334

335335
static bool CheckConstant(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
336-
if (Ptr.isIntegralPointer())
336+
if (!Ptr.isBlockPointer())
337337
return true;
338338
return CheckConstant(S, OpPC, Ptr.getDeclDesc());
339339
}

clang/lib/AST/Interp/Interp.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2811,6 +2811,13 @@ inline bool DecayPtr(InterpState &S, CodePtr OpPC) {
28112811
using ToT = typename PrimConv<TOut>::T;
28122812

28132813
const FromT &OldPtr = S.Stk.pop<FromT>();
2814+
2815+
if constexpr (std::is_same_v<FromT, FunctionPointer> &&
2816+
std::is_same_v<ToT, Pointer>) {
2817+
S.Stk.push<Pointer>(OldPtr.getFunction());
2818+
return true;
2819+
}
2820+
28142821
S.Stk.push<ToT>(ToT(OldPtr.getIntegerRepresentation(), nullptr));
28152822
return true;
28162823
}

clang/lib/AST/Interp/Pointer.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ Pointer::Pointer(Pointer &&P)
5555
}
5656

5757
Pointer::~Pointer() {
58-
if (isIntegralPointer())
58+
if (!isBlockPointer())
5959
return;
6060

6161
if (Block *Pointee = PointeeStorage.BS.Pointee) {
@@ -87,6 +87,8 @@ void Pointer::operator=(const Pointer &P) {
8787
PointeeStorage.BS.Pointee->addPointer(this);
8888
} else if (P.isIntegralPointer()) {
8989
PointeeStorage.Int = P.PointeeStorage.Int;
90+
} else if (P.isFunctionPointer()) {
91+
PointeeStorage.Fn = P.PointeeStorage.Fn;
9092
} else {
9193
assert(false && "Unhandled storage kind");
9294
}
@@ -115,6 +117,8 @@ void Pointer::operator=(Pointer &&P) {
115117
PointeeStorage.BS.Pointee->addPointer(this);
116118
} else if (P.isIntegralPointer()) {
117119
PointeeStorage.Int = P.PointeeStorage.Int;
120+
} else if (P.isFunctionPointer()) {
121+
PointeeStorage.Fn = P.PointeeStorage.Fn;
118122
} else {
119123
assert(false && "Unhandled storage kind");
120124
}
@@ -131,6 +135,8 @@ APValue Pointer::toAPValue(const ASTContext &ASTCtx) const {
131135
CharUnits::fromQuantity(asIntPointer().Value + this->Offset),
132136
Path,
133137
/*IsOnePastEnd=*/false, /*IsNullPtr=*/false);
138+
if (isFunctionPointer())
139+
return asFunctionPointer().toAPValue(ASTCtx);
134140

135141
// Build the lvalue base from the block.
136142
const Descriptor *Desc = getDeclDesc();
@@ -263,7 +269,7 @@ std::string Pointer::toDiagnosticString(const ASTContext &Ctx) const {
263269
}
264270

265271
bool Pointer::isInitialized() const {
266-
if (isIntegralPointer())
272+
if (!isBlockPointer())
267273
return true;
268274

269275
if (isRoot() && PointeeStorage.BS.Base == sizeof(GlobalInlineDescriptor)) {
@@ -299,7 +305,7 @@ bool Pointer::isInitialized() const {
299305
}
300306

301307
void Pointer::initialize() const {
302-
if (isIntegralPointer())
308+
if (!isBlockPointer())
303309
return;
304310

305311
assert(PointeeStorage.BS.Pointee && "Cannot initialize null pointer");
@@ -368,10 +374,15 @@ bool Pointer::hasSameBase(const Pointer &A, const Pointer &B) {
368374

369375
if (A.isIntegralPointer() && B.isIntegralPointer())
370376
return true;
377+
if (A.isFunctionPointer() && B.isFunctionPointer())
378+
return true;
371379

372380
if (A.isIntegralPointer() || B.isIntegralPointer())
373381
return A.getSource() == B.getSource();
374382

383+
if (A.StorageKind != B.StorageKind)
384+
return false;
385+
375386
return A.asBlockPointer().Pointee == B.asBlockPointer().Pointee;
376387
}
377388

clang/lib/AST/Interp/Pointer.h

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#define LLVM_CLANG_AST_INTERP_POINTER_H
1515

1616
#include "Descriptor.h"
17+
#include "FunctionPointer.h"
1718
#include "InterpBlock.h"
1819
#include "clang/AST/ComparisonCategories.h"
1920
#include "clang/AST/Decl.h"
@@ -45,7 +46,7 @@ struct IntPointer {
4546
uint64_t Value;
4647
};
4748

48-
enum class Storage { Block, Int };
49+
enum class Storage { Block, Int, Fn };
4950

5051
/// A pointer to a memory block, live or dead.
5152
///
@@ -96,6 +97,10 @@ class Pointer {
9697
PointeeStorage.Int.Value = Address;
9798
PointeeStorage.Int.Desc = Desc;
9899
}
100+
Pointer(const Function *F, uint64_t Offset = 0)
101+
: Offset(Offset), StorageKind(Storage::Fn) {
102+
PointeeStorage.Fn = FunctionPointer(F);
103+
}
99104
~Pointer();
100105

101106
void operator=(const Pointer &P);
@@ -126,6 +131,8 @@ class Pointer {
126131
uint64_t getIntegerRepresentation() const {
127132
if (isIntegralPointer())
128133
return asIntPointer().Value + (Offset * elemSize());
134+
if (isFunctionPointer())
135+
return asFunctionPointer().getIntegerRepresentation();
129136
return reinterpret_cast<uint64_t>(asBlockPointer().Pointee) + Offset;
130137
}
131138

@@ -137,6 +144,8 @@ class Pointer {
137144
[[nodiscard]] Pointer atIndex(uint64_t Idx) const {
138145
if (isIntegralPointer())
139146
return Pointer(asIntPointer().Value, asIntPointer().Desc, Idx);
147+
if (isFunctionPointer())
148+
return Pointer(asFunctionPointer().getFunction(), Idx);
140149

141150
if (asBlockPointer().Base == RootPtrMark)
142151
return Pointer(asBlockPointer().Pointee, RootPtrMark,
@@ -247,18 +256,20 @@ class Pointer {
247256
bool isZero() const {
248257
if (isBlockPointer())
249258
return asBlockPointer().Pointee == nullptr;
259+
if (isFunctionPointer())
260+
return asFunctionPointer().isZero();
250261
assert(isIntegralPointer());
251262
return asIntPointer().Value == 0 && Offset == 0;
252263
}
253264
/// Checks if the pointer is live.
254265
bool isLive() const {
255-
if (isIntegralPointer())
266+
if (!isBlockPointer())
256267
return true;
257268
return asBlockPointer().Pointee && !asBlockPointer().Pointee->IsDead;
258269
}
259270
/// Checks if the item is a field in an object.
260271
bool isField() const {
261-
if (isIntegralPointer())
272+
if (!isBlockPointer())
262273
return false;
263274

264275
return !isRoot() && getFieldDesc()->asDecl();
@@ -268,6 +279,8 @@ class Pointer {
268279
const Descriptor *getDeclDesc() const {
269280
if (isIntegralPointer())
270281
return asIntPointer().Desc;
282+
if (isFunctionPointer())
283+
return nullptr;
271284

272285
assert(isBlockPointer());
273286
assert(asBlockPointer().Pointee);
@@ -279,7 +292,10 @@ class Pointer {
279292
DeclTy getSource() const {
280293
if (isBlockPointer())
281294
return getDeclDesc()->getSource();
282-
295+
if (isFunctionPointer()) {
296+
const Function *F = asFunctionPointer().getFunction();
297+
return F ? F->getDecl() : DeclTy();
298+
}
283299
assert(isIntegralPointer());
284300
return asIntPointer().Desc ? asIntPointer().Desc->getSource() : DeclTy();
285301
}
@@ -354,6 +370,7 @@ class Pointer {
354370
/// Returns the offset into an array.
355371
unsigned getOffset() const {
356372
assert(Offset != PastEndMark && "invalid offset");
373+
assert(isBlockPointer());
357374
if (asBlockPointer().Base == RootPtrMark)
358375
return Offset;
359376

@@ -421,8 +438,14 @@ class Pointer {
421438
assert(isIntegralPointer());
422439
return PointeeStorage.Int;
423440
}
441+
[[nodiscard]] const FunctionPointer &asFunctionPointer() const {
442+
assert(isFunctionPointer());
443+
return PointeeStorage.Fn;
444+
}
445+
424446
bool isBlockPointer() const { return StorageKind == Storage::Block; }
425447
bool isIntegralPointer() const { return StorageKind == Storage::Int; }
448+
bool isFunctionPointer() const { return StorageKind == Storage::Fn; }
426449

427450
/// Returns the record descriptor of a class.
428451
const Record *getRecord() const { return getFieldDesc()->ElemRecord; }
@@ -445,7 +468,7 @@ class Pointer {
445468
}
446469
/// Checks if the storage is static.
447470
bool isStatic() const {
448-
if (isIntegralPointer())
471+
if (!isBlockPointer())
449472
return true;
450473
assert(asBlockPointer().Pointee);
451474
return asBlockPointer().Pointee->isStatic();
@@ -469,7 +492,7 @@ class Pointer {
469492
}
470493

471494
bool isWeak() const {
472-
if (isIntegralPointer())
495+
if (!isBlockPointer())
473496
return false;
474497

475498
assert(isBlockPointer());
@@ -528,8 +551,8 @@ class Pointer {
528551

529552
/// Returns the number of elements.
530553
unsigned getNumElems() const {
531-
if (isIntegralPointer())
532-
return ~unsigned(0);
554+
if (!isBlockPointer())
555+
return ~0u;
533556
return getSize() / elemSize();
534557
}
535558

@@ -555,7 +578,7 @@ class Pointer {
555578

556579
/// Checks if the index is one past end.
557580
bool isOnePastEnd() const {
558-
if (isIntegralPointer())
581+
if (isIntegralPointer() || isFunctionPointer())
559582
return false;
560583

561584
if (!asBlockPointer().Pointee)
@@ -692,6 +715,7 @@ class Pointer {
692715
union {
693716
BlockPointer BS;
694717
IntPointer Int;
718+
FunctionPointer Fn;
695719
} PointeeStorage;
696720
Storage StorageKind = Storage::Int;
697721
};

0 commit comments

Comments
 (0)