MCLinkerOptimizationHint.h 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. //===- MCLinkerOptimizationHint.h - LOH interface ---------------*- C++ -*-===//
  2. //
  3. //
  4. // The LLVM Compiler Infrastructure
  5. //
  6. // This file is distributed under the University of Illinois Open Source
  7. // License. See LICENSE.TXT for details.
  8. //
  9. //===----------------------------------------------------------------------===//
  10. //
  11. // This file declares some helpers classes to handle Linker Optimization Hint
  12. // (LOH).
  13. //
  14. // FIXME: LOH interface supports only MachO format at the moment.
  15. //===----------------------------------------------------------------------===//
  16. #ifndef LLVM_MC_MCLINKEROPTIMIZATIONHINT_H
  17. #define LLVM_MC_MCLINKEROPTIMIZATIONHINT_H
  18. #include "llvm/ADT/SmallVector.h"
  19. #include "llvm/ADT/StringRef.h"
  20. #include "llvm/ADT/StringSwitch.h"
  21. #include "llvm/MC/MCMachObjectWriter.h"
  22. #include "llvm/Support/raw_ostream.h"
  23. namespace llvm {
  24. // Forward declarations.
  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. }
  57. static inline StringRef MCLOHIdToName(MCLOHType Kind) {
  58. #define MCLOHCaseIdToName(Name) case MCLOH_ ## Name: return StringRef(#Name);
  59. switch (Kind) {
  60. MCLOHCaseIdToName(AdrpAdrp);
  61. MCLOHCaseIdToName(AdrpLdr);
  62. MCLOHCaseIdToName(AdrpAddLdr);
  63. MCLOHCaseIdToName(AdrpLdrGotLdr);
  64. MCLOHCaseIdToName(AdrpAddStr);
  65. MCLOHCaseIdToName(AdrpLdrGotStr);
  66. MCLOHCaseIdToName(AdrpAdd);
  67. MCLOHCaseIdToName(AdrpLdrGot);
  68. }
  69. return StringRef();
  70. }
  71. static inline int MCLOHIdToNbArgs(MCLOHType Kind) {
  72. switch (Kind) {
  73. // LOH with two arguments
  74. case MCLOH_AdrpAdrp:
  75. case MCLOH_AdrpLdr:
  76. case MCLOH_AdrpAdd:
  77. case MCLOH_AdrpLdrGot:
  78. return 2;
  79. // LOH with three arguments
  80. case MCLOH_AdrpAddLdr:
  81. case MCLOH_AdrpLdrGotLdr:
  82. case MCLOH_AdrpAddStr:
  83. case MCLOH_AdrpLdrGotStr:
  84. return 3;
  85. }
  86. return -1;
  87. }
  88. /// Store Linker Optimization Hint information (LOH).
  89. class MCLOHDirective {
  90. MCLOHType Kind;
  91. /// Arguments of this directive. Order matters.
  92. SmallVector<MCSymbol *, 3> Args;
  93. /// Emit this directive in \p OutStream using the information available
  94. /// in the given \p ObjWriter and \p Layout to get the address of the
  95. /// arguments within the object file.
  96. void emit_impl(raw_ostream &OutStream, const MachObjectWriter &ObjWriter,
  97. const MCAsmLayout &Layout) const;
  98. public:
  99. typedef SmallVectorImpl<MCSymbol *> LOHArgs;
  100. MCLOHDirective(MCLOHType Kind, const LOHArgs &Args)
  101. : Kind(Kind), Args(Args.begin(), Args.end()) {
  102. assert(isValidMCLOHType(Kind) && "Invalid LOH directive type!");
  103. }
  104. MCLOHType getKind() const { return Kind; }
  105. const LOHArgs &getArgs() const { return Args; }
  106. /// Emit this directive as:
  107. /// <kind, numArgs, addr1, ..., addrN>
  108. void emit(MachObjectWriter &ObjWriter, const MCAsmLayout &Layout) const {
  109. raw_ostream &OutStream = ObjWriter.getStream();
  110. emit_impl(OutStream, ObjWriter, Layout);
  111. }
  112. /// Get the size in bytes of this directive if emitted in \p ObjWriter with
  113. /// the given \p Layout.
  114. uint64_t getEmitSize(const MachObjectWriter &ObjWriter,
  115. const MCAsmLayout &Layout) const {
  116. class raw_counting_ostream : public raw_ostream {
  117. uint64_t Count;
  118. void write_impl(const char *, size_t size) override { Count += size; }
  119. uint64_t current_pos() const override { return Count; }
  120. public:
  121. raw_counting_ostream() : Count(0) {}
  122. ~raw_counting_ostream() override { flush(); }
  123. };
  124. raw_counting_ostream OutStream;
  125. emit_impl(OutStream, ObjWriter, Layout);
  126. return OutStream.tell();
  127. }
  128. };
  129. class MCLOHContainer {
  130. /// Keep track of the emit size of all the LOHs.
  131. mutable uint64_t EmitSize;
  132. /// Keep track of all LOH directives.
  133. SmallVector<MCLOHDirective, 32> Directives;
  134. public:
  135. typedef SmallVectorImpl<MCLOHDirective> LOHDirectives;
  136. MCLOHContainer() : EmitSize(0) {};
  137. /// Const accessor to the directives.
  138. const LOHDirectives &getDirectives() const {
  139. return Directives;
  140. }
  141. /// Add the directive of the given kind \p Kind with the given arguments
  142. /// \p Args to the container.
  143. void addDirective(MCLOHType Kind, const MCLOHDirective::LOHArgs &Args) {
  144. Directives.push_back(MCLOHDirective(Kind, Args));
  145. }
  146. /// Get the size of the directives if emitted.
  147. uint64_t getEmitSize(const MachObjectWriter &ObjWriter,
  148. const MCAsmLayout &Layout) const {
  149. if (!EmitSize) {
  150. for (const MCLOHDirective &D : Directives)
  151. EmitSize += D.getEmitSize(ObjWriter, Layout);
  152. }
  153. return EmitSize;
  154. }
  155. /// Emit all Linker Optimization Hint in one big table.
  156. /// Each line of the table is emitted by LOHDirective::emit.
  157. void emit(MachObjectWriter &ObjWriter, const MCAsmLayout &Layout) const {
  158. for (const MCLOHDirective &D : Directives)
  159. D.emit(ObjWriter, Layout);
  160. }
  161. void reset() {
  162. Directives.clear();
  163. EmitSize = 0;
  164. }
  165. };
  166. // Add types for specialized template using MCSymbol.
  167. typedef MCLOHDirective::LOHArgs MCLOHArgs;
  168. typedef MCLOHContainer::LOHDirectives MCLOHDirectives;
  169. } // end namespace llvm
  170. #endif