diff options
Diffstat (limited to 'llvm/lib/Remarks')
| -rw-r--r-- | llvm/lib/Remarks/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | llvm/lib/Remarks/RemarkFormat.cpp | 15 | ||||
| -rw-r--r-- | llvm/lib/Remarks/RemarkLinker.cpp | 126 |
3 files changed, 142 insertions, 0 deletions
diff --git a/llvm/lib/Remarks/CMakeLists.txt b/llvm/lib/Remarks/CMakeLists.txt index 9fbb1f06971..db84d631c2c 100644 --- a/llvm/lib/Remarks/CMakeLists.txt +++ b/llvm/lib/Remarks/CMakeLists.txt @@ -3,6 +3,7 @@ add_llvm_library(LLVMRemarks BitstreamRemarkSerializer.cpp Remark.cpp RemarkFormat.cpp + RemarkLinker.cpp RemarkParser.cpp RemarkSerializer.cpp RemarkStringTable.cpp diff --git a/llvm/lib/Remarks/RemarkFormat.cpp b/llvm/lib/Remarks/RemarkFormat.cpp index f2d0331ec6a..c7fce151eff 100644 --- a/llvm/lib/Remarks/RemarkFormat.cpp +++ b/llvm/lib/Remarks/RemarkFormat.cpp @@ -12,6 +12,7 @@ #include "llvm/Remarks/RemarkFormat.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/Remarks/BitstreamRemarkContainer.h" using namespace llvm; using namespace llvm::remarks; @@ -30,3 +31,17 @@ Expected<Format> llvm::remarks::parseFormat(StringRef FormatStr) { return Result; } + +Expected<Format> llvm::remarks::magicToFormat(StringRef Magic) { + auto Result = + StringSwitch<Format>(Magic) + .StartsWith("--- ", Format::YAML) // This is only an assumption. + .StartsWith(remarks::Magic, Format::YAMLStrTab) + .StartsWith(remarks::ContainerMagic, Format::Bitstream) + .Default(Format::Unknown); + + if (Result == Format::Unknown) + return createStringError(std::make_error_code(std::errc::invalid_argument), + "Unknown remark magic: '%s'", Magic.data()); + return Result; +} diff --git a/llvm/lib/Remarks/RemarkLinker.cpp b/llvm/lib/Remarks/RemarkLinker.cpp new file mode 100644 index 00000000000..617ce770af6 --- /dev/null +++ b/llvm/lib/Remarks/RemarkLinker.cpp @@ -0,0 +1,126 @@ +//===- RemarkLinker.cpp ---------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file provides an implementation of the remark linker. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Remarks/RemarkLinker.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Remarks/BitstreamRemarkContainer.h" +#include "llvm/Remarks/RemarkParser.h" +#include "llvm/Remarks/RemarkSerializer.h" +#include "llvm/Support/Error.h" + +using namespace llvm; +using namespace llvm::remarks; + +static Expected<StringRef> +getRemarksSectionName(const object::ObjectFile &Obj) { + if (Obj.isMachO()) + return StringRef("__remarks"); + // ELF -> .remarks, but there is no ELF support at this point. + return createStringError(std::errc::illegal_byte_sequence, + "Unsupported file format."); +} + +Expected<Optional<StringRef>> +llvm::remarks::getRemarksSectionContents(const object::ObjectFile &Obj) { + Expected<StringRef> SectionName = getRemarksSectionName(Obj); + if (!SectionName) + return SectionName.takeError(); + + for (const object::SectionRef &Section : Obj.sections()) { + Expected<StringRef> MaybeName = Section.getName(); + if (!MaybeName) + return MaybeName.takeError(); + if (*MaybeName != *SectionName) + continue; + + if (Expected<StringRef> Contents = Section.getContents()) + return *Contents; + else + return Contents.takeError(); + } + return Optional<StringRef>{}; +} + +Remark &RemarkLinker::keep(std::unique_ptr<Remark> Remark) { + StrTab.internalize(*Remark); + auto Inserted = Remarks.insert(std::move(Remark)); + return **Inserted.first; +} + +void RemarkLinker::setExternalFilePrependPath(StringRef PrependPathIn) { + PrependPath = PrependPathIn; +} + +// Discard remarks with no source location. +static bool shouldKeepRemark(const Remark &R) { return R.Loc.hasValue(); } + +Error RemarkLinker::link(StringRef Buffer, Optional<Format> RemarkFormat) { + if (!RemarkFormat) { + Expected<Format> ParserFormat = magicToFormat(Buffer); + if (!ParserFormat) + return ParserFormat.takeError(); + RemarkFormat = *ParserFormat; + } + + Expected<std::unique_ptr<RemarkParser>> MaybeParser = + createRemarkParserFromMeta( + *RemarkFormat, Buffer, /*StrTab=*/None, + PrependPath ? Optional<StringRef>(StringRef(*PrependPath)) + : Optional<StringRef>(None)); + if (!MaybeParser) + return MaybeParser.takeError(); + + RemarkParser &Parser = **MaybeParser; + + while (true) { + Expected<std::unique_ptr<Remark>> Next = Parser.next(); + if (Error E = Next.takeError()) { + if (E.isA<EndOfFileError>()) { + consumeError(std::move(E)); + break; + } + return E; + } + + assert(*Next != nullptr); + + if (shouldKeepRemark(**Next)) + keep(std::move(*Next)); + } + return Error::success(); +} + +Error RemarkLinker::link(const object::ObjectFile &Obj, + Optional<Format> RemarkFormat) { + Expected<Optional<StringRef>> SectionOrErr = getRemarksSectionContents(Obj); + if (!SectionOrErr) + return SectionOrErr.takeError(); + + if (Optional<StringRef> Section = *SectionOrErr) + return link(*Section, RemarkFormat); + return Error::success(); +} + +Error RemarkLinker::serialize(raw_ostream &OS, Format RemarksFormat) const { + Expected<std::unique_ptr<RemarkSerializer>> MaybeSerializer = + createRemarkSerializer(RemarksFormat, SerializerMode::Standalone, OS, + std::move(const_cast<StringTable &>(StrTab))); + if (!MaybeSerializer) + return MaybeSerializer.takeError(); + + std::unique_ptr<remarks::RemarkSerializer> Serializer = + std::move(*MaybeSerializer); + + for (const Remark &R : remarks()) + Serializer->emit(R); + return Error::success(); +} |

