MCLinkerOptimizationHint.h 5.9 KB

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