MCLinkerOptimizationHint.h 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. //===- MCLinkerOptimizationHint.h - LOH interface ---------------*- C++ -*-===//
  2. //
  3. //
  4. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  5. // See https://llvm.org/LICENSE.txt for license information.
  6. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This file declares some helpers classes to handle Linker Optimization Hint
  11. // (LOH).
  12. //
  13. // FIXME: LOH interface supports only MachO format at the moment.
  14. //===----------------------------------------------------------------------===//
  15. #ifndef LLVM_MC_MCLINKEROPTIMIZATIONHINT_H
  16. #define LLVM_MC_MCLINKEROPTIMIZATIONHINT_H
  17. #include "llvm/ADT/SmallVector.h"
  18. #include "llvm/ADT/StringRef.h"
  19. #include "llvm/ADT/StringSwitch.h"
  20. #include "llvm/Support/raw_ostream.h"
  21. #include <cassert>
  22. #include <cstdint>
  23. namespace llvm {
  24. class MachObjectWriter;
  25. class MCAsmLayout;
  26. class MCSymbol;
  27. /// Linker Optimization Hint Type.
  28. enum MCLOHType {
  29. MCLOH_AdrpAdrp = 0x1u, ///< Adrp xY, _v1@PAGE -> Adrp xY, _v2@PAGE.
  30. MCLOH_AdrpLdr = 0x2u, ///< Adrp _v@PAGE -> Ldr _v@PAGEOFF.
  31. MCLOH_AdrpAddLdr = 0x3u, ///< Adrp _v@PAGE -> Add _v@PAGEOFF -> Ldr.
  32. MCLOH_AdrpLdrGotLdr = 0x4u, ///< Adrp _v@GOTPAGE -> Ldr _v@GOTPAGEOFF -> Ldr.
  33. MCLOH_AdrpAddStr = 0x5u, ///< Adrp _v@PAGE -> Add _v@PAGEOFF -> Str.
  34. MCLOH_AdrpLdrGotStr = 0x6u, ///< Adrp _v@GOTPAGE -> Ldr _v@GOTPAGEOFF -> Str.
  35. MCLOH_AdrpAdd = 0x7u, ///< Adrp _v@PAGE -> Add _v@PAGEOFF.
  36. MCLOH_AdrpLdrGot = 0x8u ///< Adrp _v@GOTPAGE -> Ldr _v@GOTPAGEOFF.
  37. };
  38. static inline StringRef MCLOHDirectiveName() {
  39. return StringRef(".loh");
  40. }
  41. static inline bool isValidMCLOHType(unsigned Kind) {
  42. return Kind >= MCLOH_AdrpAdrp && Kind <= MCLOH_AdrpLdrGot;
  43. }
  44. static inline int MCLOHNameToId(StringRef Name) {
  45. #define MCLOHCaseNameToId(Name) .Case(#Name, MCLOH_ ## Name)
  46. return StringSwitch<int>(Name)
  47. MCLOHCaseNameToId(AdrpAdrp)
  48. MCLOHCaseNameToId(AdrpLdr)
  49. MCLOHCaseNameToId(AdrpAddLdr)
  50. MCLOHCaseNameToId(AdrpLdrGotLdr)
  51. MCLOHCaseNameToId(AdrpAddStr)
  52. MCLOHCaseNameToId(AdrpLdrGotStr)
  53. MCLOHCaseNameToId(AdrpAdd)
  54. MCLOHCaseNameToId(AdrpLdrGot)
  55. .Default(-1);
  56. #undef MCLOHCaseNameToId
  57. }
  58. static inline StringRef MCLOHIdToName(MCLOHType Kind) {
  59. #define MCLOHCaseIdToName(Name) case MCLOH_ ## Name: return StringRef(#Name);
  60. switch (Kind) {
  61. MCLOHCaseIdToName(AdrpAdrp);
  62. MCLOHCaseIdToName(AdrpLdr);
  63. MCLOHCaseIdToName(AdrpAddLdr);
  64. MCLOHCaseIdToName(AdrpLdrGotLdr);
  65. MCLOHCaseIdToName(AdrpAddStr);
  66. MCLOHCaseIdToName(AdrpLdrGotStr);
  67. MCLOHCaseIdToName(AdrpAdd);
  68. MCLOHCaseIdToName(AdrpLdrGot);
  69. }
  70. return StringRef();
  71. #undef MCLOHCaseIdToName
  72. }
  73. static inline int MCLOHIdToNbArgs(MCLOHType Kind) {
  74. switch (Kind) {
  75. // LOH with two arguments
  76. case MCLOH_AdrpAdrp:
  77. case MCLOH_AdrpLdr:
  78. case MCLOH_AdrpAdd:
  79. case MCLOH_AdrpLdrGot:
  80. return 2;
  81. // LOH with three arguments
  82. case MCLOH_AdrpAddLdr:
  83. case MCLOH_AdrpLdrGotLdr:
  84. case MCLOH_AdrpAddStr:
  85. case MCLOH_AdrpLdrGotStr:
  86. return 3;
  87. }
  88. return -1;
  89. }
  90. /// Store Linker Optimization Hint information (LOH).
  91. class MCLOHDirective {
  92. MCLOHType Kind;
  93. /// Arguments of this directive. Order matters.
  94. SmallVector<MCSymbol *, 3> Args;
  95. /// Emit this directive in \p OutStream using the information available
  96. /// in the given \p ObjWriter and \p Layout to get the address of the
  97. /// arguments within the object file.
  98. void emit_impl(raw_ostream &OutStream, const MachObjectWriter &ObjWriter,
  99. const MCAsmLayout &Layout) const;
  100. public:
  101. using LOHArgs = SmallVectorImpl<MCSymbol *>;
  102. MCLOHDirective(MCLOHType Kind, const LOHArgs &Args)
  103. : Kind(Kind), Args(Args.begin(), Args.end()) {
  104. assert(isValidMCLOHType(Kind) && "Invalid LOH directive type!");
  105. }
  106. MCLOHType getKind() const { return Kind; }
  107. const LOHArgs &getArgs() const { return Args; }
  108. /// Emit this directive as:
  109. /// <kind, numArgs, addr1, ..., addrN>
  110. void emit(MachObjectWriter &ObjWriter, const MCAsmLayout &Layout) const;
  111. /// Get the size in bytes of this directive if emitted in \p ObjWriter with
  112. /// the given \p Layout.
  113. uint64_t getEmitSize(const MachObjectWriter &ObjWriter,
  114. const MCAsmLayout &Layout) const;
  115. };
  116. class MCLOHContainer {
  117. /// Keep track of the emit size of all the LOHs.
  118. mutable uint64_t EmitSize = 0;
  119. /// Keep track of all LOH directives.
  120. SmallVector<MCLOHDirective, 32> Directives;
  121. public:
  122. using LOHDirectives = SmallVectorImpl<MCLOHDirective>;
  123. MCLOHContainer() = default;
  124. /// Const accessor to the directives.
  125. const LOHDirectives &getDirectives() const {
  126. return Directives;
  127. }
  128. /// Add the directive of the given kind \p Kind with the given arguments
  129. /// \p Args to the container.
  130. void addDirective(MCLOHType Kind, const MCLOHDirective::LOHArgs &Args) {
  131. Directives.push_back(MCLOHDirective(Kind, Args));
  132. }
  133. /// Get the size of the directives if emitted.
  134. uint64_t getEmitSize(const MachObjectWriter &ObjWriter,
  135. const MCAsmLayout &Layout) const {
  136. if (!EmitSize) {
  137. for (const MCLOHDirective &D : Directives)
  138. EmitSize += D.getEmitSize(ObjWriter, Layout);
  139. }
  140. return EmitSize;
  141. }
  142. /// Emit all Linker Optimization Hint in one big table.
  143. /// Each line of the table is emitted by LOHDirective::emit.
  144. void emit(MachObjectWriter &ObjWriter, const MCAsmLayout &Layout) const {
  145. for (const MCLOHDirective &D : Directives)
  146. D.emit(ObjWriter, Layout);
  147. }
  148. void reset() {
  149. Directives.clear();
  150. EmitSize = 0;
  151. }
  152. };
  153. // Add types for specialized template using MCSymbol.
  154. using MCLOHArgs = MCLOHDirective::LOHArgs;
  155. using MCLOHDirectives = MCLOHContainer::LOHDirectives;
  156. } // end namespace llvm
  157. #endif // LLVM_MC_MCLINKEROPTIMIZATIONHINT_H