summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Remarks/RemarkLinker.cpp
diff options
context:
space:
mode:
authorFrancis Visoiu Mistrih <francisvm@yahoo.com>2019-09-10 15:48:55 -0700
committerFrancis Visoiu Mistrih <francisvm@yahoo.com>2019-10-31 15:26:55 -0700
commite72e59e90287c50539cb2c0afbf197aa0101a023 (patch)
tree0c7481dcc08c20c59d650247175f8d0547790c0c /llvm/lib/Remarks/RemarkLinker.cpp
parentf9061049c1542579f661c3ec25528439ab9d0588 (diff)
downloadbcm5719-llvm-e72e59e90287c50539cb2c0afbf197aa0101a023.tar.gz
bcm5719-llvm-e72e59e90287c50539cb2c0afbf197aa0101a023.zip
[Remarks] Add support for linking remarks
Remarks are usually emitted per-TU, and for generating a standalone remark file that can be shipped with the linked binary we need some kind of tool to merge everything together. The remarks::RemarkLinker class takes care of this and: * Deduplicates remarks * Filters remarks with no debug location * Merges string tables from all the entries As an output, it provides an iterator range that can be used to serialize the remarks to a file. Differential Revision: https://reviews.llvm.org/D69141
Diffstat (limited to 'llvm/lib/Remarks/RemarkLinker.cpp')
-rw-r--r--llvm/lib/Remarks/RemarkLinker.cpp126
1 files changed, 126 insertions, 0 deletions
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();
+}
OpenPOWER on IntegriCloud