RemarkLinker.cpp 4.0 KB

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