mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-04-14 12:22:27 +00:00

Per the comments, `hash_code` values "are not stable to save or persist", so are unsuitable for the module hash, which must persist across compilations for the implicit module hashes to match. Note that in practice, today, `hash_code` are stable. But this is an implementation detail, with a clear `FIXME` indicating we should switch to a per-execution seed. The stability of `MD5` also allows modules cross-compilation use-cases. The `size_t` underlying storage for `hash_code` varying across platforms could cause mismatching hashes when cross-compiling from a 64bit target to a 32bit target. Note that native endianness is still used for the hash computation. So hashes will differ between platforms of different endianness. Reviewed By: jansvoboda11 Differential Revision: https://reviews.llvm.org/D102943
138 lines
4.5 KiB
C++
138 lines
4.5 KiB
C++
//===-- TestModuleFileExtension.cpp - Module Extension Tester -------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
#include "TestModuleFileExtension.h"
|
|
#include "clang/Frontend/FrontendDiagnostic.h"
|
|
#include "clang/Serialization/ASTReader.h"
|
|
#include "llvm/ADT/Hashing.h"
|
|
#include "llvm/Bitstream/BitstreamWriter.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
#include <cstdio>
|
|
using namespace clang;
|
|
using namespace clang::serialization;
|
|
|
|
char TestModuleFileExtension::ID = 0;
|
|
|
|
TestModuleFileExtension::Writer::~Writer() { }
|
|
|
|
void TestModuleFileExtension::Writer::writeExtensionContents(
|
|
Sema &SemaRef,
|
|
llvm::BitstreamWriter &Stream) {
|
|
using namespace llvm;
|
|
|
|
// Write an abbreviation for this record.
|
|
auto Abv = std::make_shared<llvm::BitCodeAbbrev>();
|
|
Abv->Add(BitCodeAbbrevOp(FIRST_EXTENSION_RECORD_ID));
|
|
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # of characters
|
|
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // message
|
|
auto Abbrev = Stream.EmitAbbrev(std::move(Abv));
|
|
|
|
// Write a message into the extension block.
|
|
SmallString<64> Message;
|
|
{
|
|
auto Ext = static_cast<TestModuleFileExtension *>(getExtension());
|
|
raw_svector_ostream OS(Message);
|
|
OS << "Hello from " << Ext->BlockName << " v" << Ext->MajorVersion << "."
|
|
<< Ext->MinorVersion;
|
|
}
|
|
uint64_t Record[] = {FIRST_EXTENSION_RECORD_ID, Message.size()};
|
|
Stream.EmitRecordWithBlob(Abbrev, Record, Message);
|
|
}
|
|
|
|
TestModuleFileExtension::Reader::Reader(ModuleFileExtension *Ext,
|
|
const llvm::BitstreamCursor &InStream)
|
|
: ModuleFileExtensionReader(Ext), Stream(InStream)
|
|
{
|
|
// Read the extension block.
|
|
SmallVector<uint64_t, 4> Record;
|
|
while (true) {
|
|
llvm::Expected<llvm::BitstreamEntry> MaybeEntry =
|
|
Stream.advanceSkippingSubblocks();
|
|
if (!MaybeEntry)
|
|
(void)MaybeEntry.takeError();
|
|
llvm::BitstreamEntry Entry = MaybeEntry.get();
|
|
|
|
switch (Entry.Kind) {
|
|
case llvm::BitstreamEntry::SubBlock:
|
|
case llvm::BitstreamEntry::EndBlock:
|
|
case llvm::BitstreamEntry::Error:
|
|
return;
|
|
|
|
case llvm::BitstreamEntry::Record:
|
|
break;
|
|
}
|
|
|
|
Record.clear();
|
|
StringRef Blob;
|
|
Expected<unsigned> MaybeRecCode =
|
|
Stream.readRecord(Entry.ID, Record, &Blob);
|
|
if (!MaybeRecCode)
|
|
fprintf(stderr, "Failed reading rec code: %s\n",
|
|
toString(MaybeRecCode.takeError()).c_str());
|
|
switch (MaybeRecCode.get()) {
|
|
case FIRST_EXTENSION_RECORD_ID: {
|
|
StringRef Message = Blob.substr(0, Record[0]);
|
|
fprintf(stderr, "Read extension block message: %s\n",
|
|
Message.str().c_str());
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TestModuleFileExtension::Reader::~Reader() { }
|
|
|
|
TestModuleFileExtension::~TestModuleFileExtension() { }
|
|
|
|
ModuleFileExtensionMetadata
|
|
TestModuleFileExtension::getExtensionMetadata() const {
|
|
return { BlockName, MajorVersion, MinorVersion, UserInfo };
|
|
}
|
|
|
|
void TestModuleFileExtension::hashExtension(
|
|
ExtensionHashBuilder &HBuilder) const {
|
|
if (Hashed) {
|
|
HBuilder.add(BlockName);
|
|
HBuilder.add(MajorVersion);
|
|
HBuilder.add(MinorVersion);
|
|
HBuilder.add(UserInfo);
|
|
}
|
|
}
|
|
|
|
std::unique_ptr<ModuleFileExtensionWriter>
|
|
TestModuleFileExtension::createExtensionWriter(ASTWriter &) {
|
|
return std::unique_ptr<ModuleFileExtensionWriter>(new Writer(this));
|
|
}
|
|
|
|
std::unique_ptr<ModuleFileExtensionReader>
|
|
TestModuleFileExtension::createExtensionReader(
|
|
const ModuleFileExtensionMetadata &Metadata,
|
|
ASTReader &Reader, serialization::ModuleFile &Mod,
|
|
const llvm::BitstreamCursor &Stream)
|
|
{
|
|
assert(Metadata.BlockName == BlockName && "Wrong block name");
|
|
if (std::make_pair(Metadata.MajorVersion, Metadata.MinorVersion) !=
|
|
std::make_pair(MajorVersion, MinorVersion)) {
|
|
Reader.getDiags().Report(Mod.ImportLoc,
|
|
diag::err_test_module_file_extension_version)
|
|
<< BlockName << Metadata.MajorVersion << Metadata.MinorVersion
|
|
<< MajorVersion << MinorVersion;
|
|
return nullptr;
|
|
}
|
|
|
|
return std::unique_ptr<ModuleFileExtensionReader>(
|
|
new TestModuleFileExtension::Reader(this, Stream));
|
|
}
|
|
|
|
std::string TestModuleFileExtension::str() const {
|
|
std::string Buffer;
|
|
llvm::raw_string_ostream OS(Buffer);
|
|
OS << BlockName << ":" << MajorVersion << ":" << MinorVersion << ":" << Hashed
|
|
<< ":" << UserInfo;
|
|
return OS.str();
|
|
}
|