@@ -1119,50 +1119,97 @@ adjustFilenameForRelocatableAST(const char *Filename, StringRef BaseDir) {
11191119}
11201120
11211121std::pair<ASTFileSignature, ASTFileSignature>
1122- ASTWriter::createSignature (StringRef AllBytes, StringRef ASTBlockBytes) {
1122+ ASTWriter::createSignature () const {
1123+ StringRef AllBytes (Buffer.data (), Buffer.size ());
1124+
11231125 llvm::SHA1 Hasher;
1124- Hasher.update (ASTBlockBytes );
1126+ Hasher.update (AllBytes. slice (ASTBlockRange. first , ASTBlockRange. second ) );
11251127 ASTFileSignature ASTBlockHash = ASTFileSignature::create (Hasher.result ());
11261128
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.
11311133 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));
11331137 ASTFileSignature Signature = ASTFileSignature::create (Hasher.result ());
11341138
11351139 return std::make_pair (ASTBlockHash, Signature);
11361140}
11371141
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) {
11401172 using namespace llvm ;
11411173
11421174 // Flush first to prepare the PCM hash (signature).
11431175 Stream.FlushToWord ();
1144- auto StartOfUnhashedControl = Stream.GetCurrentBitNo () >> 3 ;
1176+ UnhashedControlBlockRange. first = Stream.GetCurrentBitNo () >> 3 ;
11451177
11461178 // Enter the block and prepare to write records.
11471179 RecordData Record;
11481180 Stream.EnterSubblock (UNHASHED_CONTROL_BLOCK_ID, 5 );
11491181
11501182 // For implicit modules, write the hash of the PCM as its signature.
1151- ASTFileSignature Signature;
11521183 if (WritingModule &&
11531184 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 ;
11631208 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 ;
11661213 Record.clear ();
11671214 }
11681215
@@ -1242,7 +1289,7 @@ ASTFileSignature ASTWriter::writeUnhashedControlBlock(Preprocessor &PP,
12421289
12431290 // Leave the options block.
12441291 Stream.ExitBlock ();
1245- return Signature ;
1292+ UnhashedControlBlockRange. second = Stream. GetCurrentBitNo () >> 3 ;
12461293}
12471294
12481295// / Write the control block.
@@ -4656,8 +4703,12 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
46564703 ASTContext &Context = SemaRef.Context ;
46574704 Preprocessor &PP = SemaRef.PP ;
46584705
4706+ // This needs to be done very early, since everything that writes
4707+ // SourceLocations or FileIDs depends on it.
46594708 collectNonAffectingInputFiles ();
46604709
4710+ writeUnhashedControlBlock (PP, Context);
4711+
46614712 // Set up predefined declaration IDs.
46624713 auto RegisterPredefDecl = [&] (Decl *D, PredefinedDeclIDs ID) {
46634714 if (D) {
@@ -4803,7 +4854,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
48034854
48044855 // Write the remaining AST contents.
48054856 Stream.FlushToWord ();
4806- ASTBlockRange.first = Stream.GetCurrentBitNo ();
4857+ ASTBlockRange.first = Stream.GetCurrentBitNo () >> 3 ;
48074858 Stream.EnterSubblock (AST_BLOCK_ID, 5 );
48084859 ASTBlockStartOffset = Stream.GetCurrentBitNo ();
48094860
@@ -5160,13 +5211,13 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
51605211 Stream.EmitRecord (STATISTICS, Record);
51615212 Stream.ExitBlock ();
51625213 Stream.FlushToWord ();
5163- ASTBlockRange.second = Stream.GetCurrentBitNo ();
5214+ ASTBlockRange.second = Stream.GetCurrentBitNo () >> 3 ;
51645215
51655216 // Write the module file extension blocks.
51665217 for (const auto &ExtWriter : ModuleFileExtensionWriters)
51675218 WriteModuleFileExtension (SemaRef, *ExtWriter);
51685219
5169- return writeUnhashedControlBlock (PP, Context );
5220+ return backpatchSignature ( );
51705221}
51715222
51725223void ASTWriter::WriteDeclUpdatesBlocks (RecordDataImpl &OffsetsRecord) {
0 commit comments