Skip to content

Commit ab2f43c

Browse files
committed
[clang][bytecode] Add AccessFlags to Block
This way, we can check a single uint8_t for != 0 to know whether this block is accessible or not. If not, we still need to figure out why not and diagnose appropriately of course.
1 parent fde9ee1 commit ab2f43c

File tree

12 files changed

+147
-93
lines changed

12 files changed

+147
-93
lines changed

clang/lib/AST/ByteCode/Compiler.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7142,10 +7142,6 @@ bool Compiler<Emitter>::emitDestruction(const Descriptor *Desc,
71427142
assert(!Desc->isPrimitive());
71437143
assert(!Desc->isPrimitiveArray());
71447144

7145-
// Can happen if the decl is invalid.
7146-
if (Desc->isDummy())
7147-
return true;
7148-
71497145
// Arrays.
71507146
if (Desc->isArray()) {
71517147
const Descriptor *ElemDesc = Desc->ElemDesc;

clang/lib/AST/ByteCode/Descriptor.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ Descriptor::Descriptor(const DeclTy &D, const Record *R, MetadataSize MD,
367367
Descriptor::Descriptor(const DeclTy &D, MetadataSize MD)
368368
: Source(D), ElemSize(1), Size(1), MDSize(MD.value_or(0)),
369369
AllocSize(MDSize), ElemRecord(nullptr), IsConst(true), IsMutable(false),
370-
IsTemporary(false), IsDummy(true) {
370+
IsTemporary(false) {
371371
assert(Source && "Missing source");
372372
}
373373

@@ -453,7 +453,7 @@ SourceInfo Descriptor::getLoc() const {
453453
}
454454

455455
bool Descriptor::hasTrivialDtor() const {
456-
if (isPrimitive() || isPrimitiveArray() || isDummy())
456+
if (isPrimitive() || isPrimitiveArray())
457457
return true;
458458

459459
if (isRecord()) {
@@ -462,8 +462,9 @@ bool Descriptor::hasTrivialDtor() const {
462462
return !Dtor || Dtor->isTrivial();
463463
}
464464

465+
if (!ElemDesc)
466+
return true;
465467
// Composite arrays.
466-
assert(ElemDesc);
467468
return ElemDesc->hasTrivialDtor();
468469
}
469470

clang/lib/AST/ByteCode/Descriptor.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,6 @@ struct Descriptor final {
166166
const bool IsVolatile = false;
167167
/// Flag indicating if the block is an array.
168168
const bool IsArray = false;
169-
/// Flag indicating if this is a dummy descriptor.
170-
bool IsDummy = false;
171169
bool IsConstexprUnknown = false;
172170

173171
/// Storage management methods.
@@ -203,9 +201,6 @@ struct Descriptor final {
203201
/// Allocates a dummy descriptor.
204202
Descriptor(const DeclTy &D, MetadataSize MD = std::nullopt);
205203

206-
/// Make this descriptor a dummy descriptor.
207-
void makeDummy() { IsDummy = true; }
208-
209204
QualType getType() const;
210205
QualType getElemQualType() const;
211206
QualType getDataType(const ASTContext &Ctx) const;
@@ -273,8 +268,6 @@ struct Descriptor final {
273268
bool isRecord() const { return !IsArray && ElemRecord; }
274269
/// Checks if the descriptor is of a union.
275270
bool isUnion() const;
276-
/// Checks if this is a dummy descriptor.
277-
bool isDummy() const { return IsDummy; }
278271

279272
/// Whether variables of this descriptor need their destructor called or not.
280273
bool hasTrivialDtor() const;

clang/lib/AST/ByteCode/Disasm.cpp

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ LLVM_DUMP_METHOD void Program::dump(llvm::raw_ostream &OS) const {
338338
}
339339

340340
OS << "\n";
341-
if (GP.isInitialized() && Desc->isPrimitive() && !Desc->isDummy()) {
341+
if (GP.isInitialized() && Desc->isPrimitive() && !G->block()->isDummy()) {
342342
OS << " ";
343343
{
344344
ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_CYAN, false});
@@ -394,8 +394,6 @@ LLVM_DUMP_METHOD void Descriptor::dump(llvm::raw_ostream &OS) const {
394394
else if (isUnknownSizeArray())
395395
OS << " unknown-size-array";
396396

397-
if (isDummy())
398-
OS << " dummy";
399397
if (IsConstexprUnknown)
400398
OS << " constexpr-unknown";
401399
}
@@ -541,11 +539,12 @@ LLVM_DUMP_METHOD void Block::dump(llvm::raw_ostream &OS) const {
541539
else
542540
OS << "-\n";
543541
OS << " Pointers: " << NPointers << "\n";
544-
OS << " Dead: " << IsDead << "\n";
542+
OS << " Dead: " << isDead() << "\n";
545543
OS << " Static: " << IsStatic << "\n";
546-
OS << " Extern: " << IsExtern << "\n";
544+
OS << " Extern: " << isExtern() << "\n";
547545
OS << " Initialized: " << IsInitialized << "\n";
548-
OS << " Weak: " << IsWeak << "\n";
546+
OS << " Weak: " << isWeak() << "\n";
547+
OS << " Dummy: " << isDummy() << '\n';
549548
OS << " Dynamic: " << IsDynamic << "\n";
550549
}
551550

clang/lib/AST/ByteCode/DynamicAllocator.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ void DynamicAllocator::cleanup() {
2424
auto &AllocSite = Iter.second;
2525
for (auto &Alloc : AllocSite.Allocations) {
2626
Block *B = Alloc.block();
27-
assert(!B->IsDead);
27+
assert(!B->isDead());
2828
assert(B->isInitialized());
2929
B->invokeDtor();
3030

@@ -121,15 +121,16 @@ bool DynamicAllocator::deallocate(const Expr *Source,
121121
assert(!Site.empty());
122122

123123
// Find the Block to delete.
124-
auto AllocIt = llvm::find_if(Site.Allocations, [&](const Allocation &A) {
125-
return BlockToDelete == A.block();
126-
});
124+
auto *AllocIt =
125+
llvm::find_if(Site.Allocations, [&](const Allocation &A) {
126+
return BlockToDelete == A.block();
127+
});
127128

128129
assert(AllocIt != Site.Allocations.end());
129130

130131
Block *B = AllocIt->block();
131132
assert(B->isInitialized());
132-
assert(!B->IsDead);
133+
assert(!B->isDead());
133134
B->invokeDtor();
134135

135136
// Almost all our dynamic allocations have a pointer pointing to them
@@ -139,7 +140,7 @@ bool DynamicAllocator::deallocate(const Expr *Source,
139140
// over to a DeadBlock and simply keep the block in a separate DeadAllocations
140141
// list.
141142
if (B->hasPointers()) {
142-
B->IsDead = true;
143+
B->AccessFlags |= Block::DeadFlag;
143144
DeadAllocations.push_back(std::move(*AllocIt));
144145
Site.Allocations.erase(AllocIt);
145146

clang/lib/AST/ByteCode/Interp.cpp

Lines changed: 77 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -738,19 +738,21 @@ static bool CheckWeak(InterpState &S, CodePtr OpPC, const Block *B) {
738738
bool CheckGlobalLoad(InterpState &S, CodePtr OpPC, const Block *B) {
739739
const auto &Desc =
740740
*reinterpret_cast<const GlobalInlineDescriptor *>(B->rawData());
741-
if (!CheckExtern(S, OpPC, Pointer(const_cast<Block *>(B))))
742-
return false;
741+
if (!B->isAccessible()) {
742+
if (!CheckExtern(S, OpPC, Pointer(const_cast<Block *>(B))))
743+
return false;
744+
if (!CheckDummy(S, OpPC, B, AK_Read))
745+
return false;
746+
return CheckWeak(S, OpPC, B);
747+
}
748+
743749
if (!CheckConstant(S, OpPC, B->getDescriptor()))
744750
return false;
745-
if (!CheckDummy(S, OpPC, B, AK_Read))
746-
return false;
747751
if (Desc.InitState != GlobalInitState::Initialized)
748752
return DiagnoseUninitialized(S, OpPC, B->isExtern(), B->getDescriptor(),
749753
AK_Read);
750754
if (!CheckTemporary(S, OpPC, B, AK_Read))
751755
return false;
752-
if (!CheckWeak(S, OpPC, B))
753-
return false;
754756
if (B->getDescriptor()->IsVolatile) {
755757
if (!S.getLangOpts().CPlusPlus)
756758
return Invalid(S, OpPC);
@@ -790,14 +792,32 @@ bool CheckLocalLoad(InterpState &S, CodePtr OpPC, const Block *B) {
790792

791793
bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
792794
AccessKinds AK) {
793-
if (!CheckLive(S, OpPC, Ptr, AK))
794-
return false;
795-
if (!CheckExtern(S, OpPC, Ptr))
795+
if (!Ptr.isBlockPointer()) {
796+
if (Ptr.isZero()) {
797+
const auto &Src = S.Current->getSource(OpPC);
798+
799+
if (Ptr.isField())
800+
S.FFDiag(Src, diag::note_constexpr_null_subobject) << CSK_Field;
801+
else
802+
S.FFDiag(Src, diag::note_constexpr_access_null) << AK;
803+
}
796804
return false;
805+
}
806+
807+
// Block pointers are the only ones we can actually read from.
808+
if (!Ptr.block()->isAccessible()) {
809+
if (!CheckLive(S, OpPC, Ptr, AK))
810+
return false;
811+
if (!CheckExtern(S, OpPC, Ptr))
812+
return false;
813+
if (!CheckDummy(S, OpPC, Ptr.block(), AK))
814+
return false;
815+
if (!CheckWeak(S, OpPC, Ptr.block()))
816+
return false;
817+
}
818+
797819
if (!CheckConstant(S, OpPC, Ptr))
798820
return false;
799-
if (Ptr.isBlockPointer() && !CheckDummy(S, OpPC, Ptr.block(), AK))
800-
return false;
801821
if (!CheckRange(S, OpPC, Ptr, AK))
802822
return false;
803823
if (!CheckActive(S, OpPC, Ptr, AK))
@@ -806,10 +826,9 @@ bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
806826
return false;
807827
if (!Ptr.isInitialized())
808828
return DiagnoseUninitialized(S, OpPC, Ptr, AK);
809-
if (Ptr.isBlockPointer() && !CheckTemporary(S, OpPC, Ptr.block(), AK))
810-
return false;
811-
if (Ptr.isBlockPointer() && !CheckWeak(S, OpPC, Ptr.block()))
829+
if (!CheckTemporary(S, OpPC, Ptr.block(), AK))
812830
return false;
831+
813832
if (!CheckMutable(S, OpPC, Ptr))
814833
return false;
815834
if (!CheckVolatile(S, OpPC, Ptr, AK))
@@ -820,15 +839,32 @@ bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
820839
/// This is not used by any of the opcodes directly. It's used by
821840
/// EvalEmitter to do the final lvalue-to-rvalue conversion.
822841
bool CheckFinalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
823-
if (!CheckLive(S, OpPC, Ptr, AK_Read))
842+
if (!Ptr.isBlockPointer()) {
843+
if (Ptr.isZero()) {
844+
const auto &Src = S.Current->getSource(OpPC);
845+
846+
if (Ptr.isField())
847+
S.FFDiag(Src, diag::note_constexpr_null_subobject) << CSK_Field;
848+
else
849+
S.FFDiag(Src, diag::note_constexpr_access_null) << AK_Read;
850+
}
824851
return false;
852+
}
853+
854+
assert(Ptr.isBlockPointer());
855+
if (!Ptr.block()->isAccessible()) {
856+
if (!CheckLive(S, OpPC, Ptr, AK_Read))
857+
return false;
858+
if (!CheckExtern(S, OpPC, Ptr))
859+
return false;
860+
if (!CheckDummy(S, OpPC, Ptr.block(), AK_Read))
861+
return false;
862+
return CheckWeak(S, OpPC, Ptr.block());
863+
}
864+
825865
if (!CheckConstant(S, OpPC, Ptr))
826866
return false;
827867

828-
if (Ptr.isBlockPointer() && !CheckDummy(S, OpPC, Ptr.block(), AK_Read))
829-
return false;
830-
if (!CheckExtern(S, OpPC, Ptr))
831-
return false;
832868
if (!CheckRange(S, OpPC, Ptr, AK_Read))
833869
return false;
834870
if (!CheckActive(S, OpPC, Ptr, AK_Read))
@@ -837,20 +873,22 @@ bool CheckFinalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
837873
return false;
838874
if (!Ptr.isInitialized())
839875
return DiagnoseUninitialized(S, OpPC, Ptr, AK_Read);
840-
if (Ptr.isBlockPointer() && !CheckTemporary(S, OpPC, Ptr.block(), AK_Read))
841-
return false;
842-
if (Ptr.isBlockPointer() && !CheckWeak(S, OpPC, Ptr.block()))
876+
if (!CheckTemporary(S, OpPC, Ptr.block(), AK_Read))
843877
return false;
844878
if (!CheckMutable(S, OpPC, Ptr))
845879
return false;
846880
return true;
847881
}
848882

849883
bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
850-
if (!CheckLive(S, OpPC, Ptr, AK_Assign))
851-
return false;
852-
if (Ptr.isBlockPointer() && !CheckDummy(S, OpPC, Ptr.block(), AK_Assign))
884+
if (!Ptr.isBlockPointer())
853885
return false;
886+
887+
if (!Ptr.block()->isAccessible()) {
888+
if (!CheckLive(S, OpPC, Ptr, AK_Assign))
889+
return false;
890+
return CheckDummy(S, OpPC, Ptr.block(), AK_Assign);
891+
}
854892
if (!CheckLifetime(S, OpPC, Ptr.getLifetime(), AK_Assign))
855893
return false;
856894
if (!CheckExtern(S, OpPC, Ptr))
@@ -1126,11 +1164,10 @@ bool CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR) {
11261164
}
11271165

11281166
bool CheckDummy(InterpState &S, CodePtr OpPC, const Block *B, AccessKinds AK) {
1129-
const Descriptor *Desc = B->getDescriptor();
1130-
if (!Desc->isDummy())
1167+
if (!B->isDummy())
11311168
return true;
11321169

1133-
const ValueDecl *D = Desc->asValueDecl();
1170+
const ValueDecl *D = B->getDescriptor()->asValueDecl();
11341171
if (!D)
11351172
return false;
11361173

@@ -1837,14 +1874,21 @@ bool CheckNewTypeMismatch(InterpState &S, CodePtr OpPC, const Expr *E,
18371874
if (Ptr.inUnion() && Ptr.getBase().getRecord()->isUnion())
18381875
Ptr.activate();
18391876

1877+
if (!Ptr.isBlockPointer())
1878+
return false;
1879+
18401880
// Similar to CheckStore(), but with the additional CheckTemporary() call and
18411881
// the AccessKinds are different.
1882+
1883+
if (!Ptr.block()->isAccessible()) {
1884+
if (!CheckExtern(S, OpPC, Ptr))
1885+
return false;
1886+
if (!CheckLive(S, OpPC, Ptr, AK_Construct))
1887+
return false;
1888+
return CheckDummy(S, OpPC, Ptr.block(), AK_Construct);
1889+
}
18421890
if (!CheckTemporary(S, OpPC, Ptr.block(), AK_Construct))
18431891
return false;
1844-
if (!CheckLive(S, OpPC, Ptr, AK_Construct))
1845-
return false;
1846-
if (!CheckDummy(S, OpPC, Ptr.block(), AK_Construct))
1847-
return false;
18481892

18491893
// CheckLifetime for this and all base pointers.
18501894
for (Pointer P = Ptr;;) {
@@ -1855,8 +1899,7 @@ bool CheckNewTypeMismatch(InterpState &S, CodePtr OpPC, const Expr *E,
18551899
break;
18561900
P = P.getBase();
18571901
}
1858-
if (!CheckExtern(S, OpPC, Ptr))
1859-
return false;
1902+
18601903
if (!CheckRange(S, OpPC, Ptr, AK_Construct))
18611904
return false;
18621905
if (!CheckGlobal(S, OpPC, Ptr))

clang/lib/AST/ByteCode/InterpBlock.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ void Block::removePointer(Pointer *P) {
6464
}
6565

6666
void Block::cleanup() {
67-
if (Pointers == nullptr && !IsDynamic && IsDead)
67+
if (Pointers == nullptr && !IsDynamic && isDead())
6868
(reinterpret_cast<DeadBlock *>(this + 1) - 1)->free();
6969
}
7070

@@ -113,8 +113,8 @@ bool Block::hasPointer(const Pointer *P) const {
113113
#endif
114114

115115
DeadBlock::DeadBlock(DeadBlock *&Root, Block *Blk)
116-
: Root(Root), B(~0u, Blk->Desc, Blk->IsStatic, Blk->IsExtern, Blk->IsWeak,
117-
/*isDead=*/true) {
116+
: Root(Root), B(~0u, Blk->Desc, Blk->isExtern(), Blk->IsStatic,
117+
Blk->isWeak(), Blk->isDummy(), /*IsDead=*/true) {
118118
// Add the block to the chain of dead blocks.
119119
if (Root)
120120
Root->Prev = this;

0 commit comments

Comments
 (0)