RemarkLinker.cpp 4.0 KB

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