@@ -1119,50 +1119,93 @@ adjustFilenameForRelocatableAST(const char *Filename, StringRef BaseDir) {
1119
1119
}
1120
1120
1121
1121
std::pair<ASTFileSignature, ASTFileSignature>
1122
- ASTWriter::createSignature (StringRef AllBytes, StringRef ASTBlockBytes) {
1122
+ ASTWriter::createSignature () const {
1123
+ StringRef AllBytes (Buffer.data (), Buffer.size ());
1124
+
1123
1125
llvm::SHA1 Hasher;
1124
- Hasher.update (ASTBlockBytes );
1126
+ Hasher.update (AllBytes. slice (ASTBlockRange. first , ASTBlockRange. second ) );
1125
1127
ASTFileSignature ASTBlockHash = ASTFileSignature::create (Hasher.result ());
1126
1128
1127
- // Add the remaining bytes (i.e. bytes before the unhashed control block that
1128
- // are not part of the AST block) .
1129
- Hasher.update (
1130
- AllBytes. take_front (ASTBlockBytes. bytes_end () - AllBytes. bytes_begin ()));
1129
+ // Add the remaining bytes:
1130
+ // 1. Before the unhashed control block.
1131
+ Hasher.update (AllBytes. slice ( 0 , UnhashedControlBlockRange. first ));
1132
+ // 2. Between the unhashed control block and the AST block.
1131
1133
Hasher.update (
1132
- AllBytes.take_back (AllBytes.bytes_end () - ASTBlockBytes.bytes_end ()));
1134
+ AllBytes.slice (UnhashedControlBlockRange.second , ASTBlockRange.first ));
1135
+ // 3. After the AST block.
1136
+ Hasher.update (AllBytes.slice (ASTBlockRange.second , StringRef::npos));
1133
1137
ASTFileSignature Signature = ASTFileSignature::create (Hasher.result ());
1134
1138
1135
1139
return std::make_pair (ASTBlockHash, Signature);
1136
1140
}
1137
1141
1138
- ASTFileSignature ASTWriter::writeUnhashedControlBlock (Preprocessor &PP,
1139
- ASTContext &Context) {
1142
+ ASTFileSignature ASTWriter::backpatchSignature () {
1143
+ if (!WritingModule ||
1144
+ !PP->getHeaderSearchInfo ().getHeaderSearchOpts ().ModulesHashContent )
1145
+ return {};
1146
+
1147
+ // For implicit modules, write the hash of the PCM as its signature.
1148
+
1149
+ auto BackpatchSignatureAt = [&](const ASTFileSignature &S, uint64_t BitNo) {
1150
+ for (uint8_t Byte : S) {
1151
+ Stream.BackpatchByte (BitNo, Byte);
1152
+ BitNo += 8 ;
1153
+ }
1154
+ };
1155
+
1156
+ ASTFileSignature ASTBlockHash;
1157
+ ASTFileSignature Signature;
1158
+ std::tie (ASTBlockHash, Signature) = createSignature ();
1159
+
1160
+ BackpatchSignatureAt (ASTBlockHash, ASTBlockHashOffset);
1161
+ BackpatchSignatureAt (Signature, SignatureOffset);
1162
+
1163
+ return Signature;
1164
+ }
1165
+
1166
+ void ASTWriter::writeUnhashedControlBlock (Preprocessor &PP,
1167
+ ASTContext &Context) {
1140
1168
using namespace llvm ;
1141
1169
1142
1170
// Flush first to prepare the PCM hash (signature).
1143
1171
Stream.FlushToWord ();
1144
- auto StartOfUnhashedControl = Stream.GetCurrentBitNo () >> 3 ;
1172
+ UnhashedControlBlockRange. first = Stream.GetCurrentBitNo () >> 3 ;
1145
1173
1146
1174
// Enter the block and prepare to write records.
1147
1175
RecordData Record;
1148
1176
Stream.EnterSubblock (UNHASHED_CONTROL_BLOCK_ID, 5 );
1149
1177
1150
1178
// For implicit modules, write the hash of the PCM as its signature.
1151
- ASTFileSignature Signature;
1152
1179
if (WritingModule &&
1153
1180
PP.getHeaderSearchInfo ().getHeaderSearchOpts ().ModulesHashContent ) {
1154
- ASTFileSignature ASTBlockHash;
1155
- auto ASTBlockStartByte = ASTBlockRange.first >> 3 ;
1156
- auto ASTBlockByteLength = (ASTBlockRange.second >> 3 ) - ASTBlockStartByte;
1157
- std::tie (ASTBlockHash, Signature) = createSignature (
1158
- StringRef (Buffer.begin (), StartOfUnhashedControl),
1159
- StringRef (Buffer.begin () + ASTBlockStartByte, ASTBlockByteLength));
1160
-
1161
- Record.append (ASTBlockHash.begin (), ASTBlockHash.end ());
1162
- Stream.EmitRecord (AST_BLOCK_HASH, Record);
1181
+ // At this point, we don't know the actual signature of the file or the AST
1182
+ // block - we're only able to compute those at the end of the serialization
1183
+ // process. Let's store dummy signatures for now, and replace them with the
1184
+ // real ones later on.
1185
+ // The bitstream VBR-encodes record elements, which makes backpatching them
1186
+ // really difficult. Let's store the signatures as blobs instead - they are
1187
+ // guaranteed to be word-aligned, and we control their format/encoding.
1188
+ auto Dummy = ASTFileSignature::createDummy ();
1189
+ SmallString<128 > Blob{Dummy.begin (), Dummy.end ()};
1190
+
1191
+ auto Abbrev = std::make_shared<BitCodeAbbrev>();
1192
+ Abbrev->Add (BitCodeAbbrevOp (AST_BLOCK_HASH));
1193
+ Abbrev->Add (BitCodeAbbrevOp (BitCodeAbbrevOp::Blob));
1194
+ unsigned ASTBlockHashAbbrev = Stream.EmitAbbrev (std::move (Abbrev));
1195
+
1196
+ Abbrev = std::make_shared<BitCodeAbbrev>();
1197
+ Abbrev->Add (BitCodeAbbrevOp (SIGNATURE));
1198
+ Abbrev->Add (BitCodeAbbrevOp (BitCodeAbbrevOp::Blob));
1199
+ unsigned SignatureAbbrev = Stream.EmitAbbrev (std::move (Abbrev));
1200
+
1201
+ Record.push_back (AST_BLOCK_HASH);
1202
+ Stream.EmitRecordWithBlob (ASTBlockHashAbbrev, Record, Blob);
1203
+ ASTBlockHashOffset = Stream.GetCurrentBitNo () - Blob.size () * 8 ;
1163
1204
Record.clear ();
1164
- Record.append (Signature.begin (), Signature.end ());
1165
- Stream.EmitRecord (SIGNATURE, Record);
1205
+
1206
+ Record.push_back (SIGNATURE);
1207
+ Stream.EmitRecordWithBlob (SignatureAbbrev, Record, Blob);
1208
+ SignatureOffset = Stream.GetCurrentBitNo () - Blob.size () * 8 ;
1166
1209
Record.clear ();
1167
1210
}
1168
1211
@@ -1242,7 +1285,7 @@ ASTFileSignature ASTWriter::writeUnhashedControlBlock(Preprocessor &PP,
1242
1285
1243
1286
// Leave the options block.
1244
1287
Stream.ExitBlock ();
1245
- return Signature ;
1288
+ UnhashedControlBlockRange. second = Stream. GetCurrentBitNo () >> 3 ;
1246
1289
}
1247
1290
1248
1291
// / Write the control block.
@@ -1600,6 +1643,8 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr,
1600
1643
IFHAbbrev->Add (BitCodeAbbrevOp (BitCodeAbbrevOp::Fixed, 32 ));
1601
1644
unsigned IFHAbbrevCode = Stream.EmitAbbrev (std::move (IFHAbbrev));
1602
1645
1646
+ uint64_t InputFilesOffsetBase = Stream.GetCurrentBitNo ();
1647
+
1603
1648
// Get all ContentCache objects for files.
1604
1649
std::vector<InputFileEntry> UserFiles;
1605
1650
std::vector<InputFileEntry> SystemFiles;
@@ -1663,7 +1708,7 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr,
1663
1708
continue ; // already recorded this file.
1664
1709
1665
1710
// Record this entry's offset.
1666
- InputFileOffsets.push_back (Stream.GetCurrentBitNo ());
1711
+ InputFileOffsets.push_back (Stream.GetCurrentBitNo () - InputFilesOffsetBase );
1667
1712
1668
1713
InputFileID = InputFileOffsets.size ();
1669
1714
@@ -4654,8 +4699,12 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
4654
4699
ASTContext &Context = SemaRef.Context ;
4655
4700
Preprocessor &PP = SemaRef.PP ;
4656
4701
4702
+ // This needs to be done very early, since everything that writes
4703
+ // SourceLocations or FileIDs depends on it.
4657
4704
collectNonAffectingInputFiles ();
4658
4705
4706
+ writeUnhashedControlBlock (PP, Context);
4707
+
4659
4708
// Set up predefined declaration IDs.
4660
4709
auto RegisterPredefDecl = [&] (Decl *D, PredefinedDeclIDs ID) {
4661
4710
if (D) {
@@ -4801,7 +4850,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
4801
4850
4802
4851
// Write the remaining AST contents.
4803
4852
Stream.FlushToWord ();
4804
- ASTBlockRange.first = Stream.GetCurrentBitNo ();
4853
+ ASTBlockRange.first = Stream.GetCurrentBitNo () >> 3 ;
4805
4854
Stream.EnterSubblock (AST_BLOCK_ID, 5 );
4806
4855
ASTBlockStartOffset = Stream.GetCurrentBitNo ();
4807
4856
@@ -5158,13 +5207,13 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
5158
5207
Stream.EmitRecord (STATISTICS, Record);
5159
5208
Stream.ExitBlock ();
5160
5209
Stream.FlushToWord ();
5161
- ASTBlockRange.second = Stream.GetCurrentBitNo ();
5210
+ ASTBlockRange.second = Stream.GetCurrentBitNo () >> 3 ;
5162
5211
5163
5212
// Write the module file extension blocks.
5164
5213
for (const auto &ExtWriter : ModuleFileExtensionWriters)
5165
5214
WriteModuleFileExtension (SemaRef, *ExtWriter);
5166
5215
5167
- return writeUnhashedControlBlock (PP, Context );
5216
+ return backpatchSignature ( );
5168
5217
}
5169
5218
5170
5219
void ASTWriter::WriteDeclUpdatesBlocks (RecordDataImpl &OffsetsRecord) {
0 commit comments