123 lines · cpp
1//===- RemarkLinker.cpp ---------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file provides an implementation of the remark linker.10//11//===----------------------------------------------------------------------===//12 13#include "llvm/Remarks/RemarkLinker.h"14#include "llvm/ADT/StringRef.h"15#include "llvm/Object/ObjectFile.h"16#include "llvm/Object/SymbolicFile.h"17#include "llvm/Remarks/RemarkParser.h"18#include "llvm/Remarks/RemarkSerializer.h"19#include "llvm/Support/Error.h"20#include <optional>21 22using namespace llvm;23using namespace llvm::remarks;24 25namespace llvm {26class raw_ostream;27}28 29static Expected<StringRef>30getRemarksSectionName(const object::ObjectFile &Obj) {31 if (Obj.isMachO())32 return StringRef("__remarks");33 // ELF -> .remarks, but there is no ELF support at this point.34 return createStringError(std::errc::illegal_byte_sequence,35 "Unsupported file format.");36}37 38Expected<std::optional<StringRef>>39llvm::remarks::getRemarksSectionContents(const object::ObjectFile &Obj) {40 Expected<StringRef> SectionName = getRemarksSectionName(Obj);41 if (!SectionName)42 return SectionName.takeError();43 44 for (const object::SectionRef &Section : Obj.sections()) {45 Expected<StringRef> MaybeName = Section.getName();46 if (!MaybeName)47 return MaybeName.takeError();48 if (*MaybeName != *SectionName)49 continue;50 51 if (Expected<StringRef> Contents = Section.getContents())52 return *Contents;53 else54 return Contents.takeError();55 }56 return std::optional<StringRef>{};57}58 59Remark &RemarkLinker::keep(std::unique_ptr<Remark> Remark) {60 StrTab.internalize(*Remark);61 auto Inserted = Remarks.insert(std::move(Remark));62 return **Inserted.first;63}64 65void RemarkLinker::setExternalFilePrependPath(StringRef PrependPathIn) {66 PrependPath = std::string(PrependPathIn);67}68 69Error RemarkLinker::link(StringRef Buffer, Format RemarkFormat) {70 Expected<std::unique_ptr<RemarkParser>> MaybeParser =71 createRemarkParserFromMeta(72 RemarkFormat, Buffer,73 PrependPath ? std::make_optional<StringRef>(*PrependPath)74 : std::nullopt);75 if (!MaybeParser)76 return MaybeParser.takeError();77 78 RemarkParser &Parser = **MaybeParser;79 80 while (true) {81 Expected<std::unique_ptr<Remark>> Next = Parser.next();82 if (Error E = Next.takeError()) {83 if (E.isA<EndOfFileError>()) {84 consumeError(std::move(E));85 break;86 }87 return E;88 }89 90 assert(*Next != nullptr);91 92 if (shouldKeepRemark(**Next))93 keep(std::move(*Next));94 }95 return Error::success();96}97 98Error RemarkLinker::link(const object::ObjectFile &Obj, Format RemarkFormat) {99 Expected<std::optional<StringRef>> SectionOrErr =100 getRemarksSectionContents(Obj);101 if (!SectionOrErr)102 return SectionOrErr.takeError();103 104 if (std::optional<StringRef> Section = *SectionOrErr)105 return link(*Section, RemarkFormat);106 return Error::success();107}108 109Error RemarkLinker::serialize(raw_ostream &OS, Format RemarksFormat) const {110 Expected<std::unique_ptr<RemarkSerializer>> MaybeSerializer =111 createRemarkSerializer(RemarksFormat, OS,112 std::move(const_cast<StringTable &>(StrTab)));113 if (!MaybeSerializer)114 return MaybeSerializer.takeError();115 116 std::unique_ptr<remarks::RemarkSerializer> Serializer =117 std::move(*MaybeSerializer);118 119 for (const Remark &R : remarks())120 Serializer->emit(R);121 return Error::success();122}123