Skip to content

Commit dee631b

Browse files
committed
[NFC] Explicitly control alignment of Identifiers
Identifier contains a pointer to character data, and we need to ensure that this pointer has enough spare bits in it for DeclBaseName and DeclName. This currently happens to be true because the StringMap used to intern Identifier pointers happens to place a 32-bit size field in the MapTableEntry object, but it would be better to explicitly force the alignment we want and assert that it’s correct.
1 parent 6a0bc45 commit dee631b

File tree

3 files changed

+45
-25
lines changed

3 files changed

+45
-25
lines changed

include/swift/AST/Identifier.h

Lines changed: 38 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,26 @@ class Identifier {
5656

5757
const char *Pointer;
5858

59+
public:
60+
enum : size_t {
61+
NumLowBitsAvailable = 2,
62+
RequiredAlignment = 1 << NumLowBitsAvailable,
63+
SpareBitMask = ((intptr_t)1 << NumLowBitsAvailable) - 1
64+
};
65+
66+
private:
5967
/// Constructor, only accessible by ASTContext, which handles the uniquing.
60-
explicit Identifier(const char *Ptr) : Pointer(Ptr) {}
68+
explicit Identifier(const char *Ptr) : Pointer(Ptr) {
69+
assert(((uintptr_t)Ptr & SpareBitMask) == 0
70+
&& "Identifier pointer does not use any spare bits");
71+
}
72+
73+
/// A type with the alignment expected of a valid \c Identifier::Pointer .
74+
struct alignas(uint32_t) Aligner {};
75+
76+
static_assert(alignof(Aligner) >= RequiredAlignment,
77+
"Identifier table will provide enough spare bits");
78+
6179
public:
6280
explicit Identifier() : Pointer(nullptr) {}
6381

@@ -153,12 +171,15 @@ class Identifier {
153171
bool operator<(Identifier RHS) const { return Pointer < RHS.Pointer; }
154172

155173
static Identifier getEmptyKey() {
156-
return Identifier((const char*)
157-
llvm::DenseMapInfo<const void*>::getEmptyKey());
174+
uintptr_t Val = static_cast<uintptr_t>(-1);
175+
Val <<= NumLowBitsAvailable;
176+
return Identifier((const char*)Val);
158177
}
178+
159179
static Identifier getTombstoneKey() {
160-
return Identifier((const char*)
161-
llvm::DenseMapInfo<const void*>::getTombstoneKey());
180+
uintptr_t Val = static_cast<uintptr_t>(-2);
181+
Val <<= NumLowBitsAvailable;
182+
return Identifier((const char*)Val);
162183
}
163184

164185
private:
@@ -202,7 +223,7 @@ namespace llvm {
202223
static inline swift::Identifier getFromVoidPointer(void *P) {
203224
return swift::Identifier::getFromOpaquePointer(P);
204225
}
205-
enum { NumLowBitsAvailable = 2 };
226+
enum { NumLowBitsAvailable = swift::Identifier::NumLowBitsAvailable };
206227
};
207228

208229
} // end namespace llvm
@@ -221,15 +242,15 @@ class DeclBaseName {
221242
};
222243

223244
private:
224-
/// In a special DeclName represenenting a subscript, this opaque pointer
245+
/// In a special DeclName representing a subscript, this opaque pointer
225246
/// is used as the data of the base name identifier.
226247
/// This is an implementation detail that should never leak outside of
227248
/// DeclName.
228-
static void *SubscriptIdentifierData;
249+
static const Identifier::Aligner SubscriptIdentifierData;
229250
/// As above, for special constructor DeclNames.
230-
static void *ConstructorIdentifierData;
251+
static const Identifier::Aligner ConstructorIdentifierData;
231252
/// As above, for special destructor DeclNames.
232-
static void *DestructorIdentifierData;
253+
static const Identifier::Aligner DestructorIdentifierData;
233254

234255
Identifier Ident;
235256

@@ -239,23 +260,23 @@ class DeclBaseName {
239260
DeclBaseName(Identifier I) : Ident(I) {}
240261

241262
static DeclBaseName createSubscript() {
242-
return DeclBaseName(Identifier((const char *)SubscriptIdentifierData));
263+
return DeclBaseName(Identifier((const char *)&SubscriptIdentifierData));
243264
}
244265

245266
static DeclBaseName createConstructor() {
246-
return DeclBaseName(Identifier((const char *)ConstructorIdentifierData));
267+
return DeclBaseName(Identifier((const char *)&ConstructorIdentifierData));
247268
}
248269

249270
static DeclBaseName createDestructor() {
250-
return DeclBaseName(Identifier((const char *)DestructorIdentifierData));
271+
return DeclBaseName(Identifier((const char *)&DestructorIdentifierData));
251272
}
252273

253274
Kind getKind() const {
254-
if (Ident.get() == SubscriptIdentifierData) {
275+
if (Ident.get() == (const char *)&SubscriptIdentifierData) {
255276
return Kind::Subscript;
256-
} else if (Ident.get() == ConstructorIdentifierData) {
277+
} else if (Ident.get() == (const char *)&ConstructorIdentifierData) {
257278
return Kind::Constructor;
258-
} else if (Ident.get() == DestructorIdentifierData) {
279+
} else if (Ident.get() == (const char *)&DestructorIdentifierData) {
259280
return Kind::Destructor;
260281
} else {
261282
return Kind::Normal;
@@ -720,7 +741,7 @@ namespace llvm {
720741
static inline swift::DeclName getFromVoidPointer(void *ptr) {
721742
return swift::DeclName::getFromOpaqueValue(ptr);
722743
}
723-
enum { NumLowBitsAvailable = 0 };
744+
enum { NumLowBitsAvailable = PointerLikeTypeTraits<swift::DeclBaseName>::NumLowBitsAvailable - 2 };
724745
};
725746

726747
// DeclNames hash just like pointers.

lib/AST/ASTContext.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,8 @@ struct ASTContext::Implementation {
165165

166166
// FIXME: This is a StringMap rather than a StringSet because StringSet
167167
// doesn't allow passing in a pre-existing allocator.
168-
llvm::StringMap<char, llvm::BumpPtrAllocator&> IdentifierTable;
168+
llvm::StringMap<Identifier::Aligner, llvm::BumpPtrAllocator&>
169+
IdentifierTable;
169170

170171
/// The declaration of Swift.AssignmentPrecedence.
171172
PrecedenceGroupDecl *AssignmentPrecedence = nullptr;
@@ -642,7 +643,8 @@ Identifier ASTContext::getIdentifier(StringRef Str) const {
642643
if (Str.data() == nullptr)
643644
return Identifier(nullptr);
644645

645-
auto I = getImpl().IdentifierTable.insert(std::make_pair(Str, char())).first;
646+
auto pair = std::make_pair(Str, Identifier::Aligner());
647+
auto I = getImpl().IdentifierTable.insert(pair).first;
646648
return Identifier(I->getKeyData());
647649
}
648650

lib/AST/Identifier.cpp

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,9 @@
2121
#include "clang/Basic/CharInfo.h"
2222
using namespace swift;
2323

24-
void *DeclBaseName::SubscriptIdentifierData =
25-
&DeclBaseName::SubscriptIdentifierData;
26-
void *DeclBaseName::ConstructorIdentifierData =
27-
&DeclBaseName::ConstructorIdentifierData;
28-
void *DeclBaseName::DestructorIdentifierData =
29-
&DeclBaseName::DestructorIdentifierData;
24+
constexpr const Identifier::Aligner DeclBaseName::SubscriptIdentifierData{};
25+
constexpr const Identifier::Aligner DeclBaseName::ConstructorIdentifierData{};
26+
constexpr const Identifier::Aligner DeclBaseName::DestructorIdentifierData{};
3027

3128
raw_ostream &llvm::operator<<(raw_ostream &OS, Identifier I) {
3229
if (I.get() == nullptr)

0 commit comments

Comments
 (0)