Skip to content

Commit 2c1e9f1

Browse files
authored
[clang][bytecode] Explicit composite array descriptor types (llvm#129376)
When creating descriptor for array element types, we only save the original source, e.g. int[2][2][2]. So later calls to getType() of the element descriptors will also return int[2][2][2], instead of e.g. int[2][2] for the second dimension. Fix this by explicitly tracking the array types. The last attached test case used to have an lvalue offset of 32 instead of 24. We should do this for more desriptor types though and not just composite array, but I'm leaving that to a later patch.
1 parent 81a8b5c commit 2c1e9f1

File tree

5 files changed

+80
-6
lines changed

5 files changed

+80
-6
lines changed

clang/lib/AST/ByteCode/Descriptor.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -367,10 +367,12 @@ Descriptor::Descriptor(const DeclTy &D, PrimType Type, MetadataSize MD,
367367
}
368368

369369
/// Arrays of composite elements.
370-
Descriptor::Descriptor(const DeclTy &D, const Descriptor *Elem, MetadataSize MD,
370+
Descriptor::Descriptor(const DeclTy &D, const Type *SourceTy,
371+
const Descriptor *Elem, MetadataSize MD,
371372
unsigned NumElems, bool IsConst, bool IsTemporary,
372373
bool IsMutable)
373-
: Source(D), ElemSize(Elem->getAllocSize() + sizeof(InlineDescriptor)),
374+
: Source(D), SourceType(SourceTy),
375+
ElemSize(Elem->getAllocSize() + sizeof(InlineDescriptor)),
374376
Size(ElemSize * NumElems), MDSize(MD.value_or(0)),
375377
AllocSize(std::max<size_t>(alignof(void *), Size) + MDSize),
376378
ElemDesc(Elem), IsConst(IsConst), IsMutable(IsMutable),
@@ -410,6 +412,8 @@ Descriptor::Descriptor(const DeclTy &D)
410412
}
411413

412414
QualType Descriptor::getType() const {
415+
if (SourceType)
416+
return QualType(SourceType, 0);
413417
if (const auto *D = asValueDecl())
414418
return D->getType();
415419
if (const auto *T = dyn_cast_if_present<TypeDecl>(asDecl()))

clang/lib/AST/ByteCode/Descriptor.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ struct Descriptor final {
124124
private:
125125
/// Original declaration, used to emit the error message.
126126
const DeclTy Source;
127+
const Type *SourceType = nullptr;
127128
/// Size of an element, in host bytes.
128129
const unsigned ElemSize;
129130
/// Size of the storage, in host bytes.
@@ -186,8 +187,9 @@ struct Descriptor final {
186187
bool IsTemporary, UnknownSize);
187188

188189
/// Allocates a descriptor for an array of composites.
189-
Descriptor(const DeclTy &D, const Descriptor *Elem, MetadataSize MD,
190-
unsigned NumElems, bool IsConst, bool IsTemporary, bool IsMutable);
190+
Descriptor(const DeclTy &D, const Type *SourceTy, const Descriptor *Elem,
191+
MetadataSize MD, unsigned NumElems, bool IsConst, bool IsTemporary,
192+
bool IsMutable);
191193

192194
/// Allocates a descriptor for an array of composites of unknown size.
193195
Descriptor(const DeclTy &D, const Descriptor *Elem, MetadataSize MD,

clang/lib/AST/ByteCode/DynamicAllocator.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,10 @@ Block *DynamicAllocator::allocate(const Descriptor *ElementDesc,
5757
assert(ElementDesc->getMetadataSize() == 0);
5858
// Create a new descriptor for an array of the specified size and
5959
// element type.
60+
// FIXME: Pass proper element type.
6061
const Descriptor *D = allocateDescriptor(
61-
ElementDesc->asExpr(), ElementDesc, Descriptor::InlineDescMD, NumElements,
62+
ElementDesc->asExpr(), nullptr, ElementDesc, Descriptor::InlineDescMD,
63+
NumElements,
6264
/*IsConst=*/false, /*IsTemporary=*/false, /*IsMutable=*/false);
6365
return allocate(D, EvalID, AllocForm);
6466
}

clang/lib/AST/ByteCode/Program.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,7 @@ Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty,
419419
unsigned ElemSize = ElemDesc->getAllocSize() + sizeof(InlineDescriptor);
420420
if (std::numeric_limits<unsigned>::max() / ElemSize <= NumElems)
421421
return {};
422-
return allocateDescriptor(D, ElemDesc, MDSize, NumElems, IsConst,
422+
return allocateDescriptor(D, Ty, ElemDesc, MDSize, NumElems, IsConst,
423423
IsTemporary, IsMutable);
424424
}
425425
}

clang/unittests/AST/ByteCode/toAPValue.cpp

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,3 +254,69 @@ TEST(ToAPValue, MemberPointers) {
254254
ASSERT_EQ(A.getKind(), APValue::MemberPointer);
255255
}
256256
}
257+
258+
/// Compare outputs between the two interpreters.
259+
TEST(ToAPValue, Comparison) {
260+
constexpr char Code[] =
261+
"constexpr int GI = 12;\n"
262+
"constexpr const int *PI = &GI;\n"
263+
"struct S{int a; };\n"
264+
"constexpr S GS[] = {{}, {}};\n"
265+
"constexpr const S* OS = GS + 1;\n"
266+
"constexpr S DS = *OS;\n"
267+
"constexpr int IA[2][2][2] = {{{1, 2}, {3, 4}}, {{5, 6}, {7, 8}}};\n"
268+
"constexpr const int *PIA = IA[1][1];\n";
269+
270+
for (const char *Arg : {"", "-fexperimental-new-constant-interpreter"}) {
271+
auto AST = tooling::buildASTFromCodeWithArgs(Code, {Arg});
272+
273+
auto getDecl = [&](const char *Name) -> const VarDecl * {
274+
auto Nodes =
275+
match(valueDecl(hasName(Name)).bind("var"), AST->getASTContext());
276+
assert(Nodes.size() == 1);
277+
const auto *D = Nodes[0].getNodeAs<ValueDecl>("var");
278+
assert(D);
279+
return cast<VarDecl>(D);
280+
};
281+
282+
{
283+
const VarDecl *GIDecl = getDecl("GI");
284+
const APValue *V = GIDecl->evaluateValue();
285+
ASSERT_TRUE(V->isInt());
286+
}
287+
288+
{
289+
const VarDecl *GIDecl = getDecl("GI");
290+
const VarDecl *PIDecl = getDecl("PI");
291+
const APValue *V = PIDecl->evaluateValue();
292+
ASSERT_TRUE(V->isLValue());
293+
ASSERT_TRUE(V->hasLValuePath());
294+
ASSERT_EQ(V->getLValueBase().get<const ValueDecl *>(), GIDecl);
295+
ASSERT_EQ(V->getLValuePath().size(), 0u);
296+
}
297+
298+
{
299+
const APValue *V = getDecl("OS")->evaluateValue();
300+
ASSERT_TRUE(V->isLValue());
301+
ASSERT_EQ(V->getLValueOffset().getQuantity(), (unsigned)sizeof(int));
302+
ASSERT_TRUE(V->hasLValuePath());
303+
ASSERT_EQ(V->getLValuePath().size(), 1u);
304+
ASSERT_EQ(V->getLValuePath()[0].getAsArrayIndex(), 1u);
305+
}
306+
307+
{
308+
const APValue *V = getDecl("DS")->evaluateValue();
309+
ASSERT_TRUE(V->isStruct());
310+
}
311+
{
312+
const APValue *V = getDecl("PIA")->evaluateValue();
313+
ASSERT_TRUE(V->isLValue());
314+
ASSERT_TRUE(V->hasLValuePath());
315+
ASSERT_EQ(V->getLValuePath().size(), 3u);
316+
ASSERT_EQ(V->getLValuePath()[0].getAsArrayIndex(), 1u);
317+
ASSERT_EQ(V->getLValuePath()[1].getAsArrayIndex(), 1u);
318+
ASSERT_EQ(V->getLValuePath()[2].getAsArrayIndex(), 0u);
319+
ASSERT_EQ(V->getLValueOffset().getQuantity(), (unsigned)sizeof(int) * 6);
320+
}
321+
}
322+
}

0 commit comments

Comments
 (0)