@@ -1120,50 +1120,97 @@ adjustFilenameForRelocatableAST(const char *Filename, StringRef BaseDir) {
1120
1120
}
1121
1121
1122
1122
std::pair<ASTFileSignature, ASTFileSignature>
1123
- ASTWriter::createSignature (StringRef AllBytes, StringRef ASTBlockBytes) {
1123
+ ASTWriter::createSignature () const {
1124
+ StringRef AllBytes (Buffer.data (), Buffer.size ());
1125
+
1124
1126
llvm::SHA1 Hasher;
1125
- Hasher.update (ASTBlockBytes );
1127
+ Hasher.update (AllBytes. slice (ASTBlockRange. first , ASTBlockRange. second ) );
1126
1128
ASTFileSignature ASTBlockHash = ASTFileSignature::create (Hasher.result ());
1127
1129
1128
- // Add the remaining bytes (i.e. bytes before the unhashed control block that
1129
- // are not part of the AST block) .
1130
- Hasher.update (
1131
- AllBytes. take_front (ASTBlockBytes. bytes_end () - AllBytes. bytes_begin ()));
1130
+ // Add the remaining bytes:
1131
+ // 1. Before the unhashed control block.
1132
+ Hasher.update (AllBytes. slice ( 0 , UnhashedControlBlockRange. first ));
1133
+ // 2. Between the unhashed control block and the AST block.
1132
1134
Hasher.update (
1133
- AllBytes.take_back (AllBytes.bytes_end () - ASTBlockBytes.bytes_end ()));
1135
+ AllBytes.slice (UnhashedControlBlockRange.second , ASTBlockRange.first ));
1136
+ // 3. After the AST block.
1137
+ Hasher.update (AllBytes.slice (ASTBlockRange.second , StringRef::npos));
1134
1138
ASTFileSignature Signature = ASTFileSignature::create (Hasher.result ());
1135
1139
1136
1140
return std::make_pair (ASTBlockHash, Signature);
1137
1141
}
1138
1142
1139
- ASTFileSignature ASTWriter::writeUnhashedControlBlock (Preprocessor &PP,
1140
- ASTContext &Context) {
1143
+ ASTFileSignature ASTWriter::backpatchSignature () {
1144
+ if (!WritingModule ||
1145
+ !PP->getHeaderSearchInfo ().getHeaderSearchOpts ().ModulesHashContent )
1146
+ return {};
1147
+
1148
+ // For implicit modules, write the hash of the PCM as its signature.
1149
+
1150
+ auto BackpatchSignatureAt = [&](const ASTFileSignature &S, uint64_t BitNo) {
1151
+ using WordT = unsigned ;
1152
+ std::array<WordT, sizeof (ASTFileSignature) / sizeof (WordT)> Words;
1153
+ static_assert (sizeof (Words) == sizeof (S));
1154
+ std::memcpy (Words.data (), S.data (), sizeof (ASTFileSignature));
1155
+ for (WordT Word : Words) {
1156
+ Stream.BackpatchWord (BitNo, Word);
1157
+ BitNo += sizeof (WordT) * 8 ;
1158
+ }
1159
+ };
1160
+
1161
+ ASTFileSignature ASTBlockHash;
1162
+ ASTFileSignature Signature;
1163
+ std::tie (ASTBlockHash, Signature) = createSignature ();
1164
+
1165
+ BackpatchSignatureAt (ASTBlockHash, ASTBlockHashOffset);
1166
+ BackpatchSignatureAt (Signature, SignatureOffset);
1167
+
1168
+ return Signature;
1169
+ }
1170
+
1171
+ void ASTWriter::writeUnhashedControlBlock (Preprocessor &PP,
1172
+ ASTContext &Context) {
1141
1173
using namespace llvm ;
1142
1174
1143
1175
// Flush first to prepare the PCM hash (signature).
1144
1176
Stream.FlushToWord ();
1145
- auto StartOfUnhashedControl = Stream.GetCurrentBitNo () >> 3 ;
1177
+ UnhashedControlBlockRange. first = Stream.GetCurrentBitNo () >> 3 ;
1146
1178
1147
1179
// Enter the block and prepare to write records.
1148
1180
RecordData Record;
1149
1181
Stream.EnterSubblock (UNHASHED_CONTROL_BLOCK_ID, 5 );
1150
1182
1151
1183
// For implicit modules, write the hash of the PCM as its signature.
1152
- ASTFileSignature Signature;
1153
1184
if (WritingModule &&
1154
1185
PP.getHeaderSearchInfo ().getHeaderSearchOpts ().ModulesHashContent ) {
1155
- ASTFileSignature ASTBlockHash;
1156
- auto ASTBlockStartByte = ASTBlockRange.first >> 3 ;
1157
- auto ASTBlockByteLength = (ASTBlockRange.second >> 3 ) - ASTBlockStartByte;
1158
- std::tie (ASTBlockHash, Signature) = createSignature (
1159
- StringRef (Buffer.begin (), StartOfUnhashedControl),
1160
- StringRef (Buffer.begin () + ASTBlockStartByte, ASTBlockByteLength));
1161
-
1162
- Record.append (ASTBlockHash.begin (), ASTBlockHash.end ());
1163
- Stream.EmitRecord (AST_BLOCK_HASH, Record);
1186
+ // At this point, we don't know the actual signature of the file or the AST
1187
+ // block - we're only able to compute those at the end of the serialization
1188
+ // process. Let's store dummy signatures for now, and replace them with the
1189
+ // real ones later on.
1190
+ // The bitstream VBR-encodes record elements, which makes backpatching them
1191
+ // really difficult. Let's store the signatures as blobs instead - they are
1192
+ // guaranteed to be word-aligned, and we control their format/encoding.
1193
+ auto Dummy = ASTFileSignature::createDummy ();
1194
+ SmallString<128 > Blob{Dummy.begin (), Dummy.end ()};
1195
+
1196
+ auto Abbrev = std::make_shared<BitCodeAbbrev>();
1197
+ Abbrev->Add (BitCodeAbbrevOp (AST_BLOCK_HASH));
1198
+ Abbrev->Add (BitCodeAbbrevOp (BitCodeAbbrevOp::Blob));
1199
+ unsigned ASTBlockHashAbbrev = Stream.EmitAbbrev (std::move (Abbrev));
1200
+
1201
+ Abbrev = std::make_shared<BitCodeAbbrev>();
1202
+ Abbrev->Add (BitCodeAbbrevOp (SIGNATURE));
1203
+ Abbrev->Add (BitCodeAbbrevOp (BitCodeAbbrevOp::Blob));
1204
+ unsigned SignatureAbbrev = Stream.EmitAbbrev (std::move (Abbrev));
1205
+
1206
+ Record.push_back (AST_BLOCK_HASH);
1207
+ Stream.EmitRecordWithBlob (ASTBlockHashAbbrev, Record, Blob);
1208
+ ASTBlockHashOffset = Stream.GetCurrentBitNo () - Blob.size () * 8 ;
1164
1209
Record.clear ();
1165
- Record.append (Signature.begin (), Signature.end ());
1166
- Stream.EmitRecord (SIGNATURE, Record);
1210
+
1211
+ Record.push_back (SIGNATURE);
1212
+ Stream.EmitRecordWithBlob (SignatureAbbrev, Record, Blob);
1213
+ SignatureOffset = Stream.GetCurrentBitNo () - Blob.size () * 8 ;
1167
1214
Record.clear ();
1168
1215
}
1169
1216
@@ -1232,7 +1279,7 @@ ASTFileSignature ASTWriter::writeUnhashedControlBlock(Preprocessor &PP,
1232
1279
1233
1280
// Leave the options block.
1234
1281
Stream.ExitBlock ();
1235
- return Signature ;
1282
+ UnhashedControlBlockRange. second = Stream. GetCurrentBitNo () >> 3 ;
1236
1283
}
1237
1284
1238
1285
// / Write the control block.
@@ -4691,8 +4738,12 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
4691
4738
ASTContext &Context = SemaRef.Context ;
4692
4739
Preprocessor &PP = SemaRef.PP ;
4693
4740
4741
+ // This needs to be done very early, since everything that writes
4742
+ // SourceLocations or FileIDs depends on it.
4694
4743
collectNonAffectingInputFiles ();
4695
4744
4745
+ writeUnhashedControlBlock (PP, Context);
4746
+
4696
4747
// Set up predefined declaration IDs.
4697
4748
auto RegisterPredefDecl = [&] (Decl *D, PredefinedDeclIDs ID) {
4698
4749
if (D) {
@@ -4838,7 +4889,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
4838
4889
4839
4890
// Write the remaining AST contents.
4840
4891
Stream.FlushToWord ();
4841
- ASTBlockRange.first = Stream.GetCurrentBitNo ();
4892
+ ASTBlockRange.first = Stream.GetCurrentBitNo () >> 3 ;
4842
4893
Stream.EnterSubblock (AST_BLOCK_ID, 5 );
4843
4894
ASTBlockStartOffset = Stream.GetCurrentBitNo ();
4844
4895
@@ -5191,13 +5242,13 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
5191
5242
Stream.EmitRecord (STATISTICS, Record);
5192
5243
Stream.ExitBlock ();
5193
5244
Stream.FlushToWord ();
5194
- ASTBlockRange.second = Stream.GetCurrentBitNo ();
5245
+ ASTBlockRange.second = Stream.GetCurrentBitNo () >> 3 ;
5195
5246
5196
5247
// Write the module file extension blocks.
5197
5248
for (const auto &ExtWriter : ModuleFileExtensionWriters)
5198
5249
WriteModuleFileExtension (SemaRef, *ExtWriter);
5199
5250
5200
- return writeUnhashedControlBlock (PP, Context );
5251
+ return backpatchSignature ( );
5201
5252
}
5202
5253
5203
5254
void ASTWriter::WriteDeclUpdatesBlocks (RecordDataImpl &OffsetsRecord) {
0 commit comments