1480093f4SDimitry Andric //===- RemarkLinker.cpp ---------------------------------------------------===// 2480093f4SDimitry Andric // 3480093f4SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4480093f4SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5480093f4SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6480093f4SDimitry Andric // 7480093f4SDimitry Andric //===----------------------------------------------------------------------===// 8480093f4SDimitry Andric // 9480093f4SDimitry Andric // This file provides an implementation of the remark linker. 10480093f4SDimitry Andric // 11480093f4SDimitry Andric //===----------------------------------------------------------------------===// 12480093f4SDimitry Andric 13480093f4SDimitry Andric #include "llvm/Remarks/RemarkLinker.h" 14480093f4SDimitry Andric #include "llvm/ADT/StringRef.h" 15480093f4SDimitry Andric #include "llvm/Remarks/BitstreamRemarkContainer.h" 16480093f4SDimitry Andric #include "llvm/Remarks/RemarkParser.h" 17480093f4SDimitry Andric #include "llvm/Remarks/RemarkSerializer.h" 18480093f4SDimitry Andric #include "llvm/Support/Error.h" 19480093f4SDimitry Andric 20480093f4SDimitry Andric using namespace llvm; 21480093f4SDimitry Andric using namespace llvm::remarks; 22480093f4SDimitry Andric 23480093f4SDimitry Andric static Expected<StringRef> 24480093f4SDimitry Andric getRemarksSectionName(const object::ObjectFile &Obj) { 25480093f4SDimitry Andric if (Obj.isMachO()) 26480093f4SDimitry Andric return StringRef("__remarks"); 27480093f4SDimitry Andric // ELF -> .remarks, but there is no ELF support at this point. 28480093f4SDimitry Andric return createStringError(std::errc::illegal_byte_sequence, 29480093f4SDimitry Andric "Unsupported file format."); 30480093f4SDimitry Andric } 31480093f4SDimitry Andric 32480093f4SDimitry Andric Expected<Optional<StringRef>> 33480093f4SDimitry Andric llvm::remarks::getRemarksSectionContents(const object::ObjectFile &Obj) { 34480093f4SDimitry Andric Expected<StringRef> SectionName = getRemarksSectionName(Obj); 35480093f4SDimitry Andric if (!SectionName) 36480093f4SDimitry Andric return SectionName.takeError(); 37480093f4SDimitry Andric 38480093f4SDimitry Andric for (const object::SectionRef &Section : Obj.sections()) { 39480093f4SDimitry Andric Expected<StringRef> MaybeName = Section.getName(); 40480093f4SDimitry Andric if (!MaybeName) 41480093f4SDimitry Andric return MaybeName.takeError(); 42480093f4SDimitry Andric if (*MaybeName != *SectionName) 43480093f4SDimitry Andric continue; 44480093f4SDimitry Andric 45480093f4SDimitry Andric if (Expected<StringRef> Contents = Section.getContents()) 46480093f4SDimitry Andric return *Contents; 47480093f4SDimitry Andric else 48480093f4SDimitry Andric return Contents.takeError(); 49480093f4SDimitry Andric } 50480093f4SDimitry Andric return Optional<StringRef>{}; 51480093f4SDimitry Andric } 52480093f4SDimitry Andric 53480093f4SDimitry Andric Remark &RemarkLinker::keep(std::unique_ptr<Remark> Remark) { 54480093f4SDimitry Andric StrTab.internalize(*Remark); 55480093f4SDimitry Andric auto Inserted = Remarks.insert(std::move(Remark)); 56480093f4SDimitry Andric return **Inserted.first; 57480093f4SDimitry Andric } 58480093f4SDimitry Andric 59480093f4SDimitry Andric void RemarkLinker::setExternalFilePrependPath(StringRef PrependPathIn) { 60*5ffd83dbSDimitry Andric PrependPath = std::string(PrependPathIn); 61480093f4SDimitry Andric } 62480093f4SDimitry Andric 63480093f4SDimitry Andric // Discard remarks with no source location. 64480093f4SDimitry Andric static bool shouldKeepRemark(const Remark &R) { return R.Loc.hasValue(); } 65480093f4SDimitry Andric 66480093f4SDimitry Andric Error RemarkLinker::link(StringRef Buffer, Optional<Format> RemarkFormat) { 67480093f4SDimitry Andric if (!RemarkFormat) { 68480093f4SDimitry Andric Expected<Format> ParserFormat = magicToFormat(Buffer); 69480093f4SDimitry Andric if (!ParserFormat) 70480093f4SDimitry Andric return ParserFormat.takeError(); 71480093f4SDimitry Andric RemarkFormat = *ParserFormat; 72480093f4SDimitry Andric } 73480093f4SDimitry Andric 74480093f4SDimitry Andric Expected<std::unique_ptr<RemarkParser>> MaybeParser = 75480093f4SDimitry Andric createRemarkParserFromMeta( 76480093f4SDimitry Andric *RemarkFormat, Buffer, /*StrTab=*/None, 77480093f4SDimitry Andric PrependPath ? Optional<StringRef>(StringRef(*PrependPath)) 78480093f4SDimitry Andric : Optional<StringRef>(None)); 79480093f4SDimitry Andric if (!MaybeParser) 80480093f4SDimitry Andric return MaybeParser.takeError(); 81480093f4SDimitry Andric 82480093f4SDimitry Andric RemarkParser &Parser = **MaybeParser; 83480093f4SDimitry Andric 84480093f4SDimitry Andric while (true) { 85480093f4SDimitry Andric Expected<std::unique_ptr<Remark>> Next = Parser.next(); 86480093f4SDimitry Andric if (Error E = Next.takeError()) { 87480093f4SDimitry Andric if (E.isA<EndOfFileError>()) { 88480093f4SDimitry Andric consumeError(std::move(E)); 89480093f4SDimitry Andric break; 90480093f4SDimitry Andric } 91480093f4SDimitry Andric return E; 92480093f4SDimitry Andric } 93480093f4SDimitry Andric 94480093f4SDimitry Andric assert(*Next != nullptr); 95480093f4SDimitry Andric 96480093f4SDimitry Andric if (shouldKeepRemark(**Next)) 97480093f4SDimitry Andric keep(std::move(*Next)); 98480093f4SDimitry Andric } 99480093f4SDimitry Andric return Error::success(); 100480093f4SDimitry Andric } 101480093f4SDimitry Andric 102480093f4SDimitry Andric Error RemarkLinker::link(const object::ObjectFile &Obj, 103480093f4SDimitry Andric Optional<Format> RemarkFormat) { 104480093f4SDimitry Andric Expected<Optional<StringRef>> SectionOrErr = getRemarksSectionContents(Obj); 105480093f4SDimitry Andric if (!SectionOrErr) 106480093f4SDimitry Andric return SectionOrErr.takeError(); 107480093f4SDimitry Andric 108480093f4SDimitry Andric if (Optional<StringRef> Section = *SectionOrErr) 109480093f4SDimitry Andric return link(*Section, RemarkFormat); 110480093f4SDimitry Andric return Error::success(); 111480093f4SDimitry Andric } 112480093f4SDimitry Andric 113480093f4SDimitry Andric Error RemarkLinker::serialize(raw_ostream &OS, Format RemarksFormat) const { 114480093f4SDimitry Andric Expected<std::unique_ptr<RemarkSerializer>> MaybeSerializer = 115480093f4SDimitry Andric createRemarkSerializer(RemarksFormat, SerializerMode::Standalone, OS, 116480093f4SDimitry Andric std::move(const_cast<StringTable &>(StrTab))); 117480093f4SDimitry Andric if (!MaybeSerializer) 118480093f4SDimitry Andric return MaybeSerializer.takeError(); 119480093f4SDimitry Andric 120480093f4SDimitry Andric std::unique_ptr<remarks::RemarkSerializer> Serializer = 121480093f4SDimitry Andric std::move(*MaybeSerializer); 122480093f4SDimitry Andric 123480093f4SDimitry Andric for (const Remark &R : remarks()) 124480093f4SDimitry Andric Serializer->emit(R); 125480093f4SDimitry Andric return Error::success(); 126480093f4SDimitry Andric } 127