RemarkLinker.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  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-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file provides an implementation of the remark linker.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "llvm/Remarks/RemarkLinker.h"
  13. #include "llvm/ADT/StringRef.h"
  14. #include "llvm/Object/ObjectFile.h"
  15. #include "llvm/Object/SymbolicFile.h"
  16. #include "llvm/Remarks/RemarkParser.h"
  17. #include "llvm/Remarks/RemarkSerializer.h"
  18. #include "llvm/Support/Error.h"
  19. #include <optional>
  20. using namespace llvm;
  21. using namespace llvm::remarks;
  22. namespace llvm {
  23. class raw_ostream;
  24. }
  25. static Expected<StringRef>
  26. getRemarksSectionName(const object::ObjectFile &Obj) {
  27. if (Obj.isMachO())
  28. return StringRef("__remarks");
  29. // ELF -> .remarks, but there is no ELF support at this point.
  30. return createStringError(std::errc::illegal_byte_sequence,
  31. "Unsupported file format.");
  32. }
  33. Expected<std::optional<StringRef>>
  34. llvm::remarks::getRemarksSectionContents(const object::ObjectFile &Obj) {
  35. Expected<StringRef> SectionName = getRemarksSectionName(Obj);
  36. if (!SectionName)
  37. return SectionName.takeError();
  38. for (const object::SectionRef &Section : Obj.sections()) {
  39. Expected<StringRef> MaybeName = Section.getName();
  40. if (!MaybeName)
  41. return MaybeName.takeError();
  42. if (*MaybeName != *SectionName)
  43. continue;
  44. if (Expected<StringRef> Contents = Section.getContents())
  45. return *Contents;
  46. else
  47. return Contents.takeError();
  48. }
  49. return std::optional<StringRef>{};
  50. }
  51. Remark &RemarkLinker::keep(std::unique_ptr<Remark> Remark) {
  52. StrTab.internalize(*Remark);
  53. auto Inserted = Remarks.insert(std::move(Remark));
  54. return **Inserted.first;
  55. }
  56. void RemarkLinker::setExternalFilePrependPath(StringRef PrependPathIn) {
  57. PrependPath = std::string(PrependPathIn);
  58. }
  59. // Discard remarks with no source location.
  60. static bool shouldKeepRemark(const Remark &R) { return R.Loc.has_value(); }
  61. Error RemarkLinker::link(StringRef Buffer, std::optional<Format> RemarkFormat) {
  62. if (!RemarkFormat) {
  63. Expected<Format> ParserFormat = magicToFormat(Buffer);
  64. if (!ParserFormat)
  65. return ParserFormat.takeError();
  66. RemarkFormat = *ParserFormat;
  67. }
  68. Expected<std::unique_ptr<RemarkParser>> MaybeParser =
  69. createRemarkParserFromMeta(
  70. *RemarkFormat, Buffer, /*StrTab=*/std::nullopt,
  71. PrependPath ? std::optional<StringRef>(StringRef(*PrependPath))
  72. : std::optional<StringRef>());
  73. if (!MaybeParser)
  74. return MaybeParser.takeError();
  75. RemarkParser &Parser = **MaybeParser;
  76. while (true) {
  77. Expected<std::unique_ptr<Remark>> Next = Parser.next();
  78. if (Error E = Next.takeError()) {
  79. if (E.isA<EndOfFileError>()) {
  80. consumeError(std::move(E));
  81. break;
  82. }
  83. return E;
  84. }
  85. assert(*Next != nullptr);
  86. if (shouldKeepRemark(**Next))
  87. keep(std::move(*Next));
  88. }
  89. return Error::success();
  90. }
  91. Error RemarkLinker::link(const object::ObjectFile &Obj,
  92. std::optional<Format> RemarkFormat) {
  93. Expected<std::optional<StringRef>> SectionOrErr =
  94. getRemarksSectionContents(Obj);
  95. if (!SectionOrErr)
  96. return SectionOrErr.takeError();
  97. if (std::optional<StringRef> Section = *SectionOrErr)
  98. return link(*Section, RemarkFormat);
  99. return Error::success();
  100. }
  101. Error RemarkLinker::serialize(raw_ostream &OS, Format RemarksFormat) const {
  102. Expected<std::unique_ptr<RemarkSerializer>> MaybeSerializer =
  103. createRemarkSerializer(RemarksFormat, SerializerMode::Standalone, OS,
  104. std::move(const_cast<StringTable &>(StrTab)));
  105. if (!MaybeSerializer)
  106. return MaybeSerializer.takeError();
  107. std::unique_ptr<remarks::RemarkSerializer> Serializer =
  108. std::move(*MaybeSerializer);
  109. for (const Remark &R : remarks())
  110. Serializer->emit(R);
  111. return Error::success();
  112. }