Skip to content

Commit 312f3ba

Browse files
ChuanqiXu9AlexisPerry
authored andcommitted
[serialization] No transitive type change (llvm#92511)
Following of llvm#92085. #### motivation The motivation is still cutting of the unnecessary change in the dependency chain. See the above link (recursively) for details. And this will be the last patch of the `no-transitive-*-change` series. If there are any following patches, they might be C++20 Named modules specific to handle special grammars like `ADL` (See the reply in https://discourse.llvm.org/t/rfc-c-20-modules-introduce-thin-bmi-and-decls-hash/74755/53 for example). So they won't affect the whole serialization part as the series patch did. #### example After this patch, finally we are able to cut of unnecessary change of types. For example, ``` //--- m-partA.cppm export module m:partA; //--- m-partA.v1.cppm export module m:partA; namespace NS { class A { public: int getValue() { return 43; } }; } //--- m-partB.cppm export module m:partB; export inline int getB() { return 430; } //--- m.cppm export module m; export import :partA; export import :partB; //--- useBOnly.cppm export module useBOnly; import m; export inline int get() { return getB(); } ``` The BMI of `useBOnly.cppm` is expected to not change if we only add a new class in `m:partA`. This will be pretty useful in practice. #### implementation details The key idea of this patch is similar with the previous patches: extend the 32bits type ID to 64bits so that we can store the module file index in the higher bits. Then the encoding of the type ID is independent on the imported modules. But there are two differences from the previous patches: - TypeID is not completely an index of serialized types. We used the lower 3 bits to store the qualifiers. - TypeID won't take part in any lookup process. So the uses of TypeID is much less than the previous patches. The first difference make we have some more slightly complex bit operations. And the second difference makes the patch much simpler than the previous ones.
1 parent 7542031 commit 312f3ba

11 files changed

+217
-110
lines changed

clang/include/clang/Serialization/ASTBitCodes.h

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "clang/Serialization/SourceLocationEncoding.h"
2727
#include "llvm/ADT/DenseMapInfo.h"
2828
#include "llvm/Bitstream/BitCodes.h"
29+
#include "llvm/Support/MathExtras.h"
2930
#include <cassert>
3031
#include <cstdint>
3132

@@ -70,41 +71,64 @@ using DeclID = DeclIDBase::DeclID;
7071

7172
/// An ID number that refers to a type in an AST file.
7273
///
73-
/// The ID of a type is partitioned into two parts: the lower
74-
/// three bits are used to store the const/volatile/restrict
75-
/// qualifiers (as with QualType) and the upper bits provide a
76-
/// type index. The type index values are partitioned into two
74+
/// The ID of a type is partitioned into three parts:
75+
/// - the lower three bits are used to store the const/volatile/restrict
76+
/// qualifiers (as with QualType).
77+
/// - the next 29 bits provide a type index in the corresponding
78+
/// module file.
79+
/// - the upper 32 bits provide a module file index.
80+
///
81+
/// The type index values are partitioned into two
7782
/// sets. The values below NUM_PREDEF_TYPE_IDs are predefined type
7883
/// IDs (based on the PREDEF_TYPE_*_ID constants), with 0 as a
79-
/// placeholder for "no type". Values from NUM_PREDEF_TYPE_IDs are
80-
/// other types that have serialized representations.
81-
using TypeID = uint32_t;
84+
/// placeholder for "no type". The module file index for predefined
85+
/// types are always 0 since they don't belong to any modules.
86+
/// Values from NUM_PREDEF_TYPE_IDs are other types that have
87+
/// serialized representations.
88+
using TypeID = uint64_t;
89+
/// Same with TypeID except that the LocalTypeID is only meaningful
90+
/// with the corresponding ModuleFile.
91+
///
92+
/// FIXME: Make TypeID and LocalTypeID a class to improve the type
93+
/// safety.
94+
using LocalTypeID = TypeID;
8295

8396
/// A type index; the type ID with the qualifier bits removed.
97+
/// Keep structure alignment 32-bit since the blob is assumed as 32-bit
98+
/// aligned.
8499
class TypeIdx {
100+
uint32_t ModuleFileIndex = 0;
85101
uint32_t Idx = 0;
86102

87103
public:
88104
TypeIdx() = default;
89-
explicit TypeIdx(uint32_t index) : Idx(index) {}
90105

91-
uint32_t getIndex() const { return Idx; }
106+
explicit TypeIdx(uint32_t ModuleFileIdx, uint32_t Idx)
107+
: ModuleFileIndex(ModuleFileIdx), Idx(Idx) {}
108+
109+
uint32_t getModuleFileIndex() const { return ModuleFileIndex; }
110+
111+
uint64_t getValue() const { return ((uint64_t)ModuleFileIndex << 32) | Idx; }
92112

93113
TypeID asTypeID(unsigned FastQuals) const {
94114
if (Idx == uint32_t(-1))
95115
return TypeID(-1);
96116

97-
return (Idx << Qualifiers::FastWidth) | FastQuals;
117+
unsigned Index = (Idx << Qualifiers::FastWidth) | FastQuals;
118+
return ((uint64_t)ModuleFileIndex << 32) | Index;
98119
}
99120

100121
static TypeIdx fromTypeID(TypeID ID) {
101122
if (ID == TypeID(-1))
102-
return TypeIdx(-1);
123+
return TypeIdx(0, -1);
103124

104-
return TypeIdx(ID >> Qualifiers::FastWidth);
125+
return TypeIdx(ID >> 32, (ID & llvm::maskTrailingOnes<TypeID>(32)) >>
126+
Qualifiers::FastWidth);
105127
}
106128
};
107129

130+
static_assert(alignof(TypeIdx) == 4);
131+
108132
/// A structure for putting "fast"-unqualified QualTypes into a
109133
/// DenseMap. This uses the standard pointer hash function.
110134
struct UnsafeQualTypeDenseMapInfo {

clang/include/clang/Serialization/ASTReader.h

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -491,14 +491,6 @@ class ASTReader
491491
/// ID = (I + 1) << FastQual::Width has already been loaded
492492
llvm::PagedVector<QualType> TypesLoaded;
493493

494-
using GlobalTypeMapType =
495-
ContinuousRangeMap<serialization::TypeID, ModuleFile *, 4>;
496-
497-
/// Mapping from global type IDs to the module in which the
498-
/// type resides along with the offset that should be added to the
499-
/// global type ID to produce a local ID.
500-
GlobalTypeMapType GlobalTypeMap;
501-
502494
/// Declarations that have already been loaded from the chain.
503495
///
504496
/// When the pointer at index I is non-NULL, the declaration with ID
@@ -1429,8 +1421,8 @@ class ASTReader
14291421
RecordLocation(ModuleFile *M, uint64_t O) : F(M), Offset(O) {}
14301422
};
14311423

1432-
QualType readTypeRecord(unsigned Index);
1433-
RecordLocation TypeCursorForIndex(unsigned Index);
1424+
QualType readTypeRecord(serialization::TypeID ID);
1425+
RecordLocation TypeCursorForIndex(serialization::TypeID ID);
14341426
void LoadedDecl(unsigned Index, Decl *D);
14351427
Decl *ReadDeclRecord(GlobalDeclID ID);
14361428
void markIncompleteDeclChain(Decl *D);
@@ -1544,6 +1536,11 @@ class ASTReader
15441536
std::pair<ModuleFile *, unsigned>
15451537
translateIdentifierIDToIndex(serialization::IdentifierID ID) const;
15461538

1539+
/// Translate an \param TypeID ID to the index of TypesLoaded
1540+
/// array and the corresponding module file.
1541+
std::pair<ModuleFile *, unsigned>
1542+
translateTypeIDToIndex(serialization::TypeID ID) const;
1543+
15471544
public:
15481545
/// Load the AST file and validate its contents against the given
15491546
/// Preprocessor.
@@ -1892,10 +1889,11 @@ class ASTReader
18921889
QualType GetType(serialization::TypeID ID);
18931890

18941891
/// Resolve a local type ID within a given AST file into a type.
1895-
QualType getLocalType(ModuleFile &F, unsigned LocalID);
1892+
QualType getLocalType(ModuleFile &F, serialization::LocalTypeID LocalID);
18961893

18971894
/// Map a local type ID within a given AST file into a global type ID.
1898-
serialization::TypeID getGlobalTypeID(ModuleFile &F, unsigned LocalID) const;
1895+
serialization::TypeID
1896+
getGlobalTypeID(ModuleFile &F, serialization::LocalTypeID LocalID) const;
18991897

19001898
/// Read a type from the current position in the given record, which
19011899
/// was read from the given AST file.

clang/include/clang/Serialization/ASTRecordReader.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ class ASTRecordReader
163163
void readTypeLoc(TypeLoc TL, LocSeq *Seq = nullptr);
164164

165165
/// Map a local type ID within a given AST file to a global type ID.
166-
serialization::TypeID getGlobalTypeID(unsigned LocalID) const {
166+
serialization::TypeID getGlobalTypeID(serialization::TypeID LocalID) const {
167167
return Reader->getGlobalTypeID(*F, LocalID);
168168
}
169169

clang/include/clang/Serialization/ModuleFile.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -482,9 +482,6 @@ class ModuleFile {
482482
/// the global type ID space.
483483
serialization::TypeID BaseTypeIndex = 0;
484484

485-
/// Remapping table for type IDs in this module.
486-
ContinuousRangeMap<uint32_t, int, 2> TypeRemap;
487-
488485
// === Miscellaneous ===
489486

490487
/// Diagnostic IDs and their mappings that the user changed.

clang/lib/Serialization/ASTCommon.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ serialization::TypeIdxFromBuiltin(const BuiltinType *BT) {
283283
break;
284284
}
285285

286-
return TypeIdx(ID);
286+
return TypeIdx(0, ID);
287287
}
288288

289289
unsigned serialization::ComputeHash(Selector Sel) {

0 commit comments

Comments
 (0)