Skip to content

Commit 0667a16

Browse files
SC llvm teamSC llvm team
SC llvm team
authored and
SC llvm team
committed
Merged main:2cd19df792056bbac38ed64c028e335d0c7ef05d into amd-gfx:a9792f68f51a
Local branch amd-gfx a9792f6 Merged main:8f68022f8e6e54d1aeae4ed301f5a015963089b7 into amd-gfx:963308497902 Remote branch main 2cd19df [clang][Interp] Allow visiting extern variables
2 parents a9792f6 + 2cd19df commit 0667a16

File tree

177 files changed

+6941
-1788
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

177 files changed

+6941
-1788
lines changed

clang/docs/LanguageExtensions.rst

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3443,6 +3443,21 @@ Query for this feature with ``__has_builtin(__builtin_debugtrap)``.
34433443
34443444
Query for this feature with ``__has_builtin(__builtin_trap)``.
34453445
3446+
``__builtin_arm_trap``
3447+
------------------
3448+
3449+
``__builtin_arm_trap`` is an AArch64 extension to ``__builtin_trap`` which also accepts a compile-time constant value, encoded directly into the trap instruction for later inspection.
3450+
3451+
**Syntax**:
3452+
3453+
.. code-block:: c++
3454+
3455+
__builtin_arm_trap(const unsigned short payload)
3456+
3457+
**Description**
3458+
3459+
``__builtin_arm_trap`` is lowered to the ``llvm.aarch64.break`` builtin, and then to ``brk #payload``.
3460+
34463461
``__builtin_nondeterministic_value``
34473462
------------------------------------
34483463

clang/include/clang/Basic/BuiltinsAArch64.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ BUILTIN(__builtin_arm_wfi, "v", "")
5050
BUILTIN(__builtin_arm_sev, "v", "")
5151
BUILTIN(__builtin_arm_sevl, "v", "")
5252

53+
// Like __builtin_trap but provide an 16-bit immediate reason code (which goes into `brk #N`).
54+
BUILTIN(__builtin_arm_trap, "vUIs", "nr")
55+
5356
// CRC32
5457
TARGET_BUILTIN(__builtin_arm_crc32b, "UiUiUc", "nc", "crc")
5558
TARGET_BUILTIN(__builtin_arm_crc32cb, "UiUiUc", "nc", "crc")

clang/lib/AST/Interp/ByteCodeExprGen.cpp

Lines changed: 32 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -82,15 +82,27 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
8282
if (DiscardResult)
8383
return this->discard(SubExpr);
8484

85-
if (SubExpr->getType()->isAnyComplexType())
86-
return this->delegate(SubExpr);
85+
std::optional<PrimType> SubExprT = classify(SubExpr->getType());
86+
// Prepare storage for the result.
87+
if (!Initializing && !SubExprT) {
88+
std::optional<unsigned> LocalIndex =
89+
allocateLocal(SubExpr, /*IsExtended=*/false);
90+
if (!LocalIndex)
91+
return false;
92+
if (!this->emitGetPtrLocal(*LocalIndex, CE))
93+
return false;
94+
}
8795

8896
if (!this->visit(SubExpr))
8997
return false;
9098

91-
if (std::optional<PrimType> SubExprT = classify(SubExpr->getType()))
99+
if (SubExprT)
92100
return this->emitLoadPop(*SubExprT, CE);
93-
return false;
101+
102+
// If the subexpr type is not primitive, we need to perform a copy here.
103+
// This happens for example in C when dereferencing a pointer of struct
104+
// type.
105+
return this->emitMemcpy(CE);
94106
}
95107

96108
case CK_UncheckedDerivedToBase:
@@ -296,14 +308,11 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
296308
// Location for the SubExpr.
297309
// Since SubExpr is of complex type, visiting it results in a pointer
298310
// anyway, so we just create a temporary pointer variable.
299-
std::optional<unsigned> SubExprOffset = allocateLocalPrimitive(
311+
unsigned SubExprOffset = allocateLocalPrimitive(
300312
SubExpr, PT_Ptr, /*IsConst=*/true, /*IsExtended=*/false);
301-
if (!SubExprOffset)
302-
return false;
303-
304313
if (!this->visit(SubExpr))
305314
return false;
306-
if (!this->emitSetLocal(PT_Ptr, *SubExprOffset, CE))
315+
if (!this->emitSetLocal(PT_Ptr, SubExprOffset, CE))
307316
return false;
308317

309318
PrimType SourceElemT = classifyComplexElementType(SubExpr->getType());
@@ -312,7 +321,7 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
312321
PrimType DestElemT = classifyPrim(DestElemType);
313322
// Cast both elements individually.
314323
for (unsigned I = 0; I != 2; ++I) {
315-
if (!this->emitGetLocal(PT_Ptr, *SubExprOffset, CE))
324+
if (!this->emitGetLocal(PT_Ptr, SubExprOffset, CE))
316325
return false;
317326
if (!this->emitArrayElemPop(SourceElemT, I, CE))
318327
return false;
@@ -1233,22 +1242,19 @@ bool ByteCodeExprGen<Emitter>::VisitOpaqueValueExpr(const OpaqueValueExpr *E) {
12331242
// At this point we either have the evaluated source expression or a pointer
12341243
// to an object on the stack. We want to create a local variable that stores
12351244
// this value.
1236-
std::optional<unsigned> LocalIndex =
1237-
allocateLocalPrimitive(E, SubExprT, /*IsConst=*/true);
1238-
if (!LocalIndex)
1239-
return false;
1240-
if (!this->emitSetLocal(SubExprT, *LocalIndex, E))
1245+
unsigned LocalIndex = allocateLocalPrimitive(E, SubExprT, /*IsConst=*/true);
1246+
if (!this->emitSetLocal(SubExprT, LocalIndex, E))
12411247
return false;
12421248

12431249
// Here the local variable is created but the value is removed from the stack,
12441250
// so we put it back if the caller needs it.
12451251
if (!DiscardResult) {
1246-
if (!this->emitGetLocal(SubExprT, *LocalIndex, E))
1252+
if (!this->emitGetLocal(SubExprT, LocalIndex, E))
12471253
return false;
12481254
}
12491255

12501256
// This is cleaned up when the local variable is destroyed.
1251-
OpaqueExprs.insert({E, *LocalIndex});
1257+
OpaqueExprs.insert({E, LocalIndex});
12521258

12531259
return true;
12541260
}
@@ -1642,14 +1648,13 @@ bool ByteCodeExprGen<Emitter>::VisitMaterializeTemporaryExpr(
16421648

16431649
// For everyhing else, use local variables.
16441650
if (SubExprT) {
1645-
if (std::optional<unsigned> LocalIndex = allocateLocalPrimitive(
1646-
SubExpr, *SubExprT, /*IsConst=*/true, /*IsExtended=*/true)) {
1647-
if (!this->visit(SubExpr))
1648-
return false;
1649-
if (!this->emitSetLocal(*SubExprT, *LocalIndex, E))
1650-
return false;
1651-
return this->emitGetPtrLocal(*LocalIndex, E);
1652-
}
1651+
unsigned LocalIndex = allocateLocalPrimitive(
1652+
SubExpr, *SubExprT, /*IsConst=*/true, /*IsExtended=*/true);
1653+
if (!this->visit(SubExpr))
1654+
return false;
1655+
if (!this->emitSetLocal(*SubExprT, LocalIndex, E))
1656+
return false;
1657+
return this->emitGetPtrLocal(LocalIndex, E);
16531658
} else {
16541659
const Expr *Inner = E->getSubExpr()->skipRValueSubobjectAdjustments();
16551660

@@ -2660,18 +2665,12 @@ bool ByteCodeExprGen<Emitter>::visitVarDecl(const VarDecl *VD) {
26602665
if (P.getGlobal(VD))
26612666
return true;
26622667

2663-
// Ignore external declarations. We will instead emit a dummy
2664-
// pointer when we see a DeclRefExpr for them.
2665-
if (VD->hasExternalStorage())
2666-
return true;
2667-
26682668
std::optional<unsigned> GlobalIndex = P.createGlobal(VD, Init);
26692669

26702670
if (!GlobalIndex)
26712671
return false;
26722672

2673-
assert(Init);
2674-
{
2673+
if (Init) {
26752674
DeclScope<Emitter> LocalScope(this, VD);
26762675

26772676
if (VarT) {
@@ -2681,6 +2680,7 @@ bool ByteCodeExprGen<Emitter>::visitVarDecl(const VarDecl *VD) {
26812680
}
26822681
return this->visitGlobalInitializer(Init, *GlobalIndex);
26832682
}
2683+
return true;
26842684
} else {
26852685
VariableScope<Emitter> LocalScope(this);
26862686
if (VarT) {
@@ -3247,53 +3247,20 @@ bool ByteCodeExprGen<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) {
32473247
// pointer to the actual value) instead of a pointer to the pointer to the
32483248
// value.
32493249
bool IsReference = D->getType()->isReferenceType();
3250-
// Complex values are copied in the AST via a simply assignment or
3251-
// ltor cast. But we represent them as two-element arrays, which means
3252-
// we pass them around as pointers. So, to assignm from them, we will
3253-
// have to copy both (primitive) elements instead.
3254-
bool IsComplex = D->getType()->isAnyComplexType();
32553250

32563251
// Check for local/global variables and parameters.
32573252
if (auto It = Locals.find(D); It != Locals.end()) {
32583253
const unsigned Offset = It->second.Offset;
3259-
// FIXME: Fix the code duplication here with the code in the global case.
3260-
if (Initializing && IsComplex) {
3261-
PrimType ElemT = classifyComplexElementType(D->getType());
3262-
for (unsigned I = 0; I != 2; ++I) {
3263-
if (!this->emitGetPtrLocal(Offset, E))
3264-
return false;
3265-
if (!this->emitArrayElemPop(ElemT, I, E))
3266-
return false;
3267-
if (!this->emitInitElem(ElemT, I, E))
3268-
return false;
3269-
}
3270-
return true;
3271-
}
3272-
32733254
if (IsReference)
32743255
return this->emitGetLocal(PT_Ptr, Offset, E);
32753256
return this->emitGetPtrLocal(Offset, E);
32763257
} else if (auto GlobalIndex = P.getGlobal(D)) {
3277-
if (Initializing && IsComplex) {
3278-
PrimType ElemT = classifyComplexElementType(D->getType());
3279-
for (unsigned I = 0; I != 2; ++I) {
3280-
if (!this->emitGetPtrGlobal(*GlobalIndex, E))
3281-
return false;
3282-
if (!this->emitArrayElemPop(ElemT, I, E))
3283-
return false;
3284-
if (!this->emitInitElem(ElemT, I, E))
3285-
return false;
3286-
}
3287-
return true;
3288-
}
3289-
32903258
if (IsReference)
32913259
return this->emitGetGlobalPtr(*GlobalIndex, E);
32923260

32933261
return this->emitGetPtrGlobal(*GlobalIndex, E);
32943262
} else if (const auto *PVD = dyn_cast<ParmVarDecl>(D)) {
32953263
if (auto It = this->Params.find(PVD); It != this->Params.end()) {
3296-
// FIXME: _Complex initializing case?
32973264
if (IsReference || !It->second.IsPtr)
32983265
return this->emitGetParamPtr(It->second.Offset, E);
32993266

@@ -3322,9 +3289,6 @@ bool ByteCodeExprGen<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) {
33223289
// Retry.
33233290
return this->VisitDeclRefExpr(E);
33243291
}
3325-
3326-
if (VD->hasExternalStorage())
3327-
return this->emitInvalidDeclRef(E, E);
33283292
}
33293293
} else {
33303294
if (const auto *VD = dyn_cast<VarDecl>(D);

clang/lib/AST/Interp/Descriptor.cpp

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -233,9 +233,10 @@ static BlockMoveFn getMoveArrayPrim(PrimType Type) {
233233
Descriptor::Descriptor(const DeclTy &D, PrimType Type, MetadataSize MD,
234234
bool IsConst, bool IsTemporary, bool IsMutable)
235235
: Source(D), ElemSize(primSize(Type)), Size(ElemSize),
236-
MDSize(MD.value_or(0)), AllocSize(align(Size + MDSize)), IsConst(IsConst),
237-
IsMutable(IsMutable), IsTemporary(IsTemporary), CtorFn(getCtorPrim(Type)),
238-
DtorFn(getDtorPrim(Type)), MoveFn(getMovePrim(Type)) {
236+
MDSize(MD.value_or(0)), AllocSize(align(Size + MDSize)), PrimT(Type),
237+
IsConst(IsConst), IsMutable(IsMutable), IsTemporary(IsTemporary),
238+
CtorFn(getCtorPrim(Type)), DtorFn(getDtorPrim(Type)),
239+
MoveFn(getMovePrim(Type)) {
239240
assert(AllocSize >= Size);
240241
assert(Source && "Missing source");
241242
}
@@ -246,7 +247,7 @@ Descriptor::Descriptor(const DeclTy &D, PrimType Type, MetadataSize MD,
246247
bool IsMutable)
247248
: Source(D), ElemSize(primSize(Type)), Size(ElemSize * NumElems),
248249
MDSize(MD.value_or(0)),
249-
AllocSize(align(MDSize) + align(Size) + sizeof(InitMapPtr)),
250+
AllocSize(align(MDSize) + align(Size) + sizeof(InitMapPtr)), PrimT(Type),
250251
IsConst(IsConst), IsMutable(IsMutable), IsTemporary(IsTemporary),
251252
IsArray(true), CtorFn(getCtorArrayPrim(Type)),
252253
DtorFn(getDtorArrayPrim(Type)), MoveFn(getMoveArrayPrim(Type)) {
@@ -300,10 +301,19 @@ Descriptor::Descriptor(const DeclTy &D, const Record *R, MetadataSize MD,
300301
assert(Source && "Missing source");
301302
}
302303

303-
Descriptor::Descriptor(const DeclTy &D, MetadataSize MD)
304-
: Source(D), ElemSize(1), Size(ElemSize), MDSize(MD.value_or(0)),
305-
AllocSize(Size + MDSize), ElemRecord(nullptr), IsConst(true),
306-
IsMutable(false), IsTemporary(false), IsDummy(true) {
304+
/// Dummy.
305+
Descriptor::Descriptor(const DeclTy &D)
306+
: Source(D), ElemSize(1), Size(1), MDSize(0), AllocSize(MDSize),
307+
ElemRecord(nullptr), IsConst(true), IsMutable(false), IsTemporary(false),
308+
IsDummy(true) {
309+
assert(Source && "Missing source");
310+
}
311+
312+
/// Dummy array.
313+
Descriptor::Descriptor(const DeclTy &D, UnknownSize)
314+
: Source(D), ElemSize(1), Size(UnknownSizeMark), MDSize(0),
315+
AllocSize(MDSize), ElemRecord(nullptr), IsConst(true), IsMutable(false),
316+
IsTemporary(false), IsArray(true), IsDummy(true) {
307317
assert(Source && "Missing source");
308318
}
309319

clang/lib/AST/Interp/Descriptor.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,10 @@ struct Descriptor final {
112112
const Record *const ElemRecord = nullptr;
113113
/// Descriptor of the array element.
114114
const Descriptor *const ElemDesc = nullptr;
115+
/// The primitive type this descriptor was created for,
116+
/// or the primitive element type in case this is
117+
/// a primitive array.
118+
const std::optional<PrimType> PrimT = std::nullopt;
115119
/// Flag indicating if the block is mutable.
116120
const bool IsConst = false;
117121
/// Flag indicating if a field is mutable.
@@ -152,7 +156,11 @@ struct Descriptor final {
152156
Descriptor(const DeclTy &D, const Record *R, MetadataSize MD, bool IsConst,
153157
bool IsTemporary, bool IsMutable);
154158

155-
Descriptor(const DeclTy &D, MetadataSize MD);
159+
/// Allocates a dummy descriptor.
160+
Descriptor(const DeclTy &D);
161+
162+
/// Allocates a dummy array descriptor.
163+
Descriptor(const DeclTy &D, UnknownSize);
156164

157165
QualType getType() const;
158166
QualType getElemQualType() const;
@@ -183,6 +191,11 @@ struct Descriptor final {
183191
return Size;
184192
}
185193

194+
PrimType getPrimType() const {
195+
assert(isPrimitiveArray() || isPrimitive());
196+
return *PrimT;
197+
}
198+
186199
/// Returns the allocated size, including metadata.
187200
unsigned getAllocSize() const { return AllocSize; }
188201
/// returns the size of an element when the structure is viewed as an array.

clang/lib/AST/Interp/Disasm.cpp

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,11 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13+
#include "Boolean.h"
1314
#include "Floating.h"
1415
#include "Function.h"
16+
#include "FunctionPointer.h"
17+
#include "Integral.h"
1518
#include "IntegralAP.h"
1619
#include "Opcode.h"
1720
#include "PrimType.h"
@@ -86,6 +89,40 @@ LLVM_DUMP_METHOD void Function::dump(llvm::raw_ostream &OS) const {
8689

8790
LLVM_DUMP_METHOD void Program::dump() const { dump(llvm::errs()); }
8891

92+
static const char *primTypeToString(PrimType T) {
93+
switch (T) {
94+
case PT_Sint8:
95+
return "Sint8";
96+
case PT_Uint8:
97+
return "Uint8";
98+
case PT_Sint16:
99+
return "Sint16";
100+
case PT_Uint16:
101+
return "Uint16";
102+
case PT_Sint32:
103+
return "Sint32";
104+
case PT_Uint32:
105+
return "Uint32";
106+
case PT_Sint64:
107+
return "Sint64";
108+
case PT_Uint64:
109+
return "Uint64";
110+
case PT_IntAP:
111+
return "IntAP";
112+
case PT_IntAPS:
113+
return "IntAPS";
114+
case PT_Bool:
115+
return "Bool";
116+
case PT_Float:
117+
return "Float";
118+
case PT_Ptr:
119+
return "Ptr";
120+
case PT_FnPtr:
121+
return "FnPtr";
122+
}
123+
llvm_unreachable("Unhandled PrimType");
124+
}
125+
89126
LLVM_DUMP_METHOD void Program::dump(llvm::raw_ostream &OS) const {
90127
{
91128
ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_RED, true});
@@ -100,9 +137,10 @@ LLVM_DUMP_METHOD void Program::dump(llvm::raw_ostream &OS) const {
100137
unsigned GI = 0;
101138
for (const Global *G : Globals) {
102139
const Descriptor *Desc = G->block()->getDescriptor();
140+
Pointer GP = getPtrGlobal(GI);
141+
103142
OS << GI << ": " << (void *)G->block() << " ";
104143
{
105-
Pointer GP = getPtrGlobal(GI);
106144
ColorScope SC(OS, true,
107145
GP.isInitialized()
108146
? TerminalColor{llvm::raw_ostream::GREEN, false}
@@ -111,6 +149,15 @@ LLVM_DUMP_METHOD void Program::dump(llvm::raw_ostream &OS) const {
111149
}
112150
Desc->dump(OS);
113151
OS << "\n";
152+
if (Desc->isPrimitive() && !Desc->isDummy()) {
153+
OS << " ";
154+
{
155+
ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_CYAN, false});
156+
OS << primTypeToString(Desc->getPrimType()) << " ";
157+
}
158+
TYPE_SWITCH(Desc->getPrimType(), { GP.deref<T>().print(OS); });
159+
OS << "\n";
160+
}
114161
++GI;
115162
}
116163

0 commit comments

Comments
 (0)