MCFixup.h 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. //===-- llvm/MC/MCFixup.h - Instruction Relocation and Patching -*- C++ -*-===//
  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. #ifndef LLVM_MC_MCFIXUP_H
  9. #define LLVM_MC_MCFIXUP_H
  10. #include "llvm/Support/DataTypes.h"
  11. #include "llvm/Support/ErrorHandling.h"
  12. #include "llvm/Support/SMLoc.h"
  13. #include <cassert>
  14. namespace llvm {
  15. class MCExpr;
  16. /// Extensible enumeration to represent the type of a fixup.
  17. enum MCFixupKind {
  18. FK_NONE = 0, ///< A no-op fixup.
  19. FK_Data_1, ///< A one-byte fixup.
  20. FK_Data_2, ///< A two-byte fixup.
  21. FK_Data_4, ///< A four-byte fixup.
  22. FK_Data_8, ///< A eight-byte fixup.
  23. FK_Data_6b, ///< A six-bits fixup.
  24. FK_PCRel_1, ///< A one-byte pc relative fixup.
  25. FK_PCRel_2, ///< A two-byte pc relative fixup.
  26. FK_PCRel_4, ///< A four-byte pc relative fixup.
  27. FK_PCRel_8, ///< A eight-byte pc relative fixup.
  28. FK_GPRel_1, ///< A one-byte gp relative fixup.
  29. FK_GPRel_2, ///< A two-byte gp relative fixup.
  30. FK_GPRel_4, ///< A four-byte gp relative fixup.
  31. FK_GPRel_8, ///< A eight-byte gp relative fixup.
  32. FK_DTPRel_4, ///< A four-byte dtp relative fixup.
  33. FK_DTPRel_8, ///< A eight-byte dtp relative fixup.
  34. FK_TPRel_4, ///< A four-byte tp relative fixup.
  35. FK_TPRel_8, ///< A eight-byte tp relative fixup.
  36. FK_SecRel_1, ///< A one-byte section relative fixup.
  37. FK_SecRel_2, ///< A two-byte section relative fixup.
  38. FK_SecRel_4, ///< A four-byte section relative fixup.
  39. FK_SecRel_8, ///< A eight-byte section relative fixup.
  40. FK_Data_Add_1, ///< A one-byte add fixup.
  41. FK_Data_Add_2, ///< A two-byte add fixup.
  42. FK_Data_Add_4, ///< A four-byte add fixup.
  43. FK_Data_Add_8, ///< A eight-byte add fixup.
  44. FK_Data_Add_6b, ///< A six-bits add fixup.
  45. FK_Data_Sub_1, ///< A one-byte sub fixup.
  46. FK_Data_Sub_2, ///< A two-byte sub fixup.
  47. FK_Data_Sub_4, ///< A four-byte sub fixup.
  48. FK_Data_Sub_8, ///< A eight-byte sub fixup.
  49. FK_Data_Sub_6b, ///< A six-bits sub fixup.
  50. FirstTargetFixupKind = 128,
  51. /// The range [FirstLiteralRelocationKind, MaxTargetFixupKind) is used for
  52. /// relocations coming from .reloc directive. Fixup kind
  53. /// FirstLiteralRelocationKind+V represents the relocation type with number V.
  54. FirstLiteralRelocationKind = 256,
  55. /// Set limit to accommodate the highest reloc type in use for all Targets,
  56. /// currently R_AARCH64_IRELATIVE at 1032, including room for expansion.
  57. MaxFixupKind = FirstLiteralRelocationKind + 1032 + 32,
  58. };
  59. /// Encode information on a single operation to perform on a byte
  60. /// sequence (e.g., an encoded instruction) which requires assemble- or run-
  61. /// time patching.
  62. ///
  63. /// Fixups are used any time the target instruction encoder needs to represent
  64. /// some value in an instruction which is not yet concrete. The encoder will
  65. /// encode the instruction assuming the value is 0, and emit a fixup which
  66. /// communicates to the assembler backend how it should rewrite the encoded
  67. /// value.
  68. ///
  69. /// During the process of relaxation, the assembler will apply fixups as
  70. /// symbolic values become concrete. When relaxation is complete, any remaining
  71. /// fixups become relocations in the object file (or errors, if the fixup cannot
  72. /// be encoded on the target).
  73. class MCFixup {
  74. /// The value to put into the fixup location. The exact interpretation of the
  75. /// expression is target dependent, usually it will be one of the operands to
  76. /// an instruction or an assembler directive.
  77. const MCExpr *Value = nullptr;
  78. /// The byte index of start of the relocation inside the MCFragment.
  79. uint32_t Offset = 0;
  80. /// The target dependent kind of fixup item this is. The kind is used to
  81. /// determine how the operand value should be encoded into the instruction.
  82. MCFixupKind Kind = FK_NONE;
  83. /// The source location which gave rise to the fixup, if any.
  84. SMLoc Loc;
  85. public:
  86. static MCFixup create(uint32_t Offset, const MCExpr *Value,
  87. MCFixupKind Kind, SMLoc Loc = SMLoc()) {
  88. assert(Kind <= MaxFixupKind && "Kind out of range!");
  89. MCFixup FI;
  90. FI.Value = Value;
  91. FI.Offset = Offset;
  92. FI.Kind = Kind;
  93. FI.Loc = Loc;
  94. return FI;
  95. }
  96. /// Return a fixup corresponding to the add half of a add/sub fixup pair for
  97. /// the given Fixup.
  98. static MCFixup createAddFor(const MCFixup &Fixup) {
  99. MCFixup FI;
  100. FI.Value = Fixup.getValue();
  101. FI.Offset = Fixup.getOffset();
  102. FI.Kind = getAddKindForKind(Fixup.getKind());
  103. FI.Loc = Fixup.getLoc();
  104. return FI;
  105. }
  106. /// Return a fixup corresponding to the sub half of a add/sub fixup pair for
  107. /// the given Fixup.
  108. static MCFixup createSubFor(const MCFixup &Fixup) {
  109. MCFixup FI;
  110. FI.Value = Fixup.getValue();
  111. FI.Offset = Fixup.getOffset();
  112. FI.Kind = getSubKindForKind(Fixup.getKind());
  113. FI.Loc = Fixup.getLoc();
  114. return FI;
  115. }
  116. MCFixupKind getKind() const { return Kind; }
  117. unsigned getTargetKind() const { return Kind; }
  118. uint32_t getOffset() const { return Offset; }
  119. void setOffset(uint32_t Value) { Offset = Value; }
  120. const MCExpr *getValue() const { return Value; }
  121. /// Return the generic fixup kind for a value with the given size. It
  122. /// is an error to pass an unsupported size.
  123. static MCFixupKind getKindForSize(unsigned Size, bool IsPCRel) {
  124. switch (Size) {
  125. default: llvm_unreachable("Invalid generic fixup size!");
  126. case 1:
  127. return IsPCRel ? FK_PCRel_1 : FK_Data_1;
  128. case 2:
  129. return IsPCRel ? FK_PCRel_2 : FK_Data_2;
  130. case 4:
  131. return IsPCRel ? FK_PCRel_4 : FK_Data_4;
  132. case 8:
  133. return IsPCRel ? FK_PCRel_8 : FK_Data_8;
  134. }
  135. }
  136. /// Return the generic fixup kind for a value with the given size in bits.
  137. /// It is an error to pass an unsupported size.
  138. static MCFixupKind getKindForSizeInBits(unsigned Size, bool IsPCRel) {
  139. switch (Size) {
  140. default:
  141. llvm_unreachable("Invalid generic fixup size!");
  142. case 6:
  143. assert(!IsPCRel && "Invalid pc-relative fixup size!");
  144. return FK_Data_6b;
  145. case 8:
  146. return IsPCRel ? FK_PCRel_1 : FK_Data_1;
  147. case 16:
  148. return IsPCRel ? FK_PCRel_2 : FK_Data_2;
  149. case 32:
  150. return IsPCRel ? FK_PCRel_4 : FK_Data_4;
  151. case 64:
  152. return IsPCRel ? FK_PCRel_8 : FK_Data_8;
  153. }
  154. }
  155. /// Return the generic fixup kind for an addition with a given size. It
  156. /// is an error to pass an unsupported size.
  157. static MCFixupKind getAddKindForKind(MCFixupKind Kind) {
  158. switch (Kind) {
  159. default: llvm_unreachable("Unknown type to convert!");
  160. case FK_Data_1: return FK_Data_Add_1;
  161. case FK_Data_2: return FK_Data_Add_2;
  162. case FK_Data_4: return FK_Data_Add_4;
  163. case FK_Data_8: return FK_Data_Add_8;
  164. case FK_Data_6b: return FK_Data_Add_6b;
  165. }
  166. }
  167. /// Return the generic fixup kind for an subtraction with a given size. It
  168. /// is an error to pass an unsupported size.
  169. static MCFixupKind getSubKindForKind(MCFixupKind Kind) {
  170. switch (Kind) {
  171. default: llvm_unreachable("Unknown type to convert!");
  172. case FK_Data_1: return FK_Data_Sub_1;
  173. case FK_Data_2: return FK_Data_Sub_2;
  174. case FK_Data_4: return FK_Data_Sub_4;
  175. case FK_Data_8: return FK_Data_Sub_8;
  176. case FK_Data_6b: return FK_Data_Sub_6b;
  177. }
  178. }
  179. SMLoc getLoc() const { return Loc; }
  180. };
  181. } // End llvm namespace
  182. #endif