@@ -1119,50 +1119,97 @@ 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
+ using WordT = unsigned ;
1151
+ std::array<WordT, sizeof (ASTFileSignature) / sizeof (WordT)> Words;
1152
+ static_assert (sizeof (Words) == sizeof (S));
1153
+ std::memcpy (Words.data (), S.data (), sizeof (ASTFileSignature));
1154
+ for (WordT Word : Words) {
1155
+ Stream.BackpatchWord (BitNo, Word);
1156
+ BitNo += sizeof (WordT) * 8 ;
1157
+ }
1158
+ };
1159
+
1160
+ ASTFileSignature ASTBlockHash;
1161
+ ASTFileSignature Signature;
1162
+ std::tie (ASTBlockHash, Signature) = createSignature ();
1163
+
1164
+ BackpatchSignatureAt (ASTBlockHash, ASTBlockHashOffset);
1165
+ BackpatchSignatureAt (Signature, SignatureOffset);
1166
+
1167
+ return Signature;
1168
+ }
1169
+
1170
+ void ASTWriter::writeUnhashedControlBlock (Preprocessor &PP,
1171
+ ASTContext &Context) {
1140
1172
using namespace llvm ;
1141
1173
1142
1174
// Flush first to prepare the PCM hash (signature).
1143
1175
Stream.FlushToWord ();
1144
- auto StartOfUnhashedControl = Stream.GetCurrentBitNo () >> 3 ;
1176
+ UnhashedControlBlockRange. first = Stream.GetCurrentBitNo () >> 3 ;
1145
1177
1146
1178
// Enter the block and prepare to write records.
1147
1179
RecordData Record;
1148
1180
Stream.EnterSubblock (UNHASHED_CONTROL_BLOCK_ID, 5 );
1149
1181
1150
1182
// For implicit modules, write the hash of the PCM as its signature.
1151
- ASTFileSignature Signature;
1152
1183
if (WritingModule &&
1153
1184
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);
1185
+ // At this point, we don't know the actual signature of the file or the AST
1186
+ // block - we're only able to compute those at the end of the serialization
1187
+ // process. Let's store dummy signatures for now, and replace them with the
1188
+ // real ones later on.
1189
+ // The bitstream VBR-encodes record elements, which makes backpatching them
1190
+ // really difficult. Let's store the signatures as blobs instead - they are
1191
+ // guaranteed to be word-aligned, and we control their format/encoding.
1192
+ auto Dummy = ASTFileSignature::createDummy ();
1193
+ SmallString<128 > Blob{Dummy.begin (), Dummy.end ()};
1194
+
1195
+ auto Abbrev = std::make_shared<BitCodeAbbrev>();
1196
+ Abbrev->Add (BitCodeAbbrevOp (AST_BLOCK_HASH));
1197
+ Abbrev->Add (BitCodeAbbrevOp (BitCodeAbbrevOp::Blob));
1198
+ unsigned ASTBlockHashAbbrev = Stream.EmitAbbrev (std::move (Abbrev));
1199
+
1200
+ Abbrev = std::make_shared<BitCodeAbbrev>();
1201
+ Abbrev->Add (BitCodeAbbrevOp (SIGNATURE));
1202
+ Abbrev->Add (BitCodeAbbrevOp (BitCodeAbbrevOp::Blob));
1203
+ unsigned SignatureAbbrev = Stream.EmitAbbrev (std::move (Abbrev));
1204
+
1205
+ Record.push_back (AST_BLOCK_HASH);
1206
+ Stream.EmitRecordWithBlob (ASTBlockHashAbbrev, Record, Blob);
1207
+ ASTBlockHashOffset = Stream.GetCurrentBitNo () - Blob.size () * 8 ;
1163
1208
Record.clear ();
1164
- Record.append (Signature.begin (), Signature.end ());
1165
- Stream.EmitRecord (SIGNATURE, Record);
1209
+
1210
+ Record.push_back (SIGNATURE);
1211
+ Stream.EmitRecordWithBlob (SignatureAbbrev, Record, Blob);
1212
+ SignatureOffset = Stream.GetCurrentBitNo () - Blob.size () * 8 ;
1166
1213
Record.clear ();
1167
1214
}
1168
1215
@@ -1242,7 +1289,7 @@ ASTFileSignature ASTWriter::writeUnhashedControlBlock(Preprocessor &PP,
1242
1289
1243
1290
// Leave the options block.
1244
1291
Stream.ExitBlock ();
1245
- return Signature ;
1292
+ UnhashedControlBlockRange. second = Stream. GetCurrentBitNo () >> 3 ;
1246
1293
}
1247
1294
1248
1295
// / Write the control block.
@@ -4656,8 +4703,12 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
4656
4703
ASTContext &Context = SemaRef.Context ;
4657
4704
Preprocessor &PP = SemaRef.PP ;
4658
4705
4706
+ // This needs to be done very early, since everything that writes
4707
+ // SourceLocations or FileIDs depends on it.
4659
4708
collectNonAffectingInputFiles ();
4660
4709
4710
+ writeUnhashedControlBlock (PP, Context);
4711
+
4661
4712
// Set up predefined declaration IDs.
4662
4713
auto RegisterPredefDecl = [&] (Decl *D, PredefinedDeclIDs ID) {
4663
4714
if (D) {
@@ -4803,7 +4854,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
4803
4854
4804
4855
// Write the remaining AST contents.
4805
4856
Stream.FlushToWord ();
4806
- ASTBlockRange.first = Stream.GetCurrentBitNo ();
4857
+ ASTBlockRange.first = Stream.GetCurrentBitNo () >> 3 ;
4807
4858
Stream.EnterSubblock (AST_BLOCK_ID, 5 );
4808
4859
ASTBlockStartOffset = Stream.GetCurrentBitNo ();
4809
4860
@@ -5160,13 +5211,13 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
5160
5211
Stream.EmitRecord (STATISTICS, Record);
5161
5212
Stream.ExitBlock ();
5162
5213
Stream.FlushToWord ();
5163
- ASTBlockRange.second = Stream.GetCurrentBitNo ();
5214
+ ASTBlockRange.second = Stream.GetCurrentBitNo () >> 3 ;
5164
5215
5165
5216
// Write the module file extension blocks.
5166
5217
for (const auto &ExtWriter : ModuleFileExtensionWriters)
5167
5218
WriteModuleFileExtension (SemaRef, *ExtWriter);
5168
5219
5169
- return writeUnhashedControlBlock (PP, Context );
5220
+ return backpatchSignature ( );
5170
5221
}
5171
5222
5172
5223
void ASTWriter::WriteDeclUpdatesBlocks (RecordDataImpl &OffsetsRecord) {
0 commit comments