MCInstPrinter.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. //===- MCInstPrinter.cpp - Convert an MCInst to target assembly syntax ----===//
  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. #include "llvm/MC/MCInstPrinter.h"
  9. #include "llvm/ADT/ArrayRef.h"
  10. #include "llvm/ADT/StringRef.h"
  11. #include "llvm/MC/MCAsmInfo.h"
  12. #include "llvm/MC/MCInst.h"
  13. #include "llvm/MC/MCInstrInfo.h"
  14. #include "llvm/MC/MCSubtargetInfo.h"
  15. #include "llvm/Support/ErrorHandling.h"
  16. #include "llvm/Support/Format.h"
  17. #include "llvm/Support/raw_ostream.h"
  18. #include <cinttypes>
  19. #include <cstdint>
  20. using namespace llvm;
  21. void llvm::dumpBytes(ArrayRef<uint8_t> bytes, raw_ostream &OS) {
  22. static const char hex_rep[] = "0123456789abcdef";
  23. bool First = true;
  24. for (char i: bytes) {
  25. if (First)
  26. First = false;
  27. else
  28. OS << ' ';
  29. OS << hex_rep[(i & 0xF0) >> 4];
  30. OS << hex_rep[i & 0xF];
  31. }
  32. }
  33. MCInstPrinter::~MCInstPrinter() = default;
  34. /// getOpcodeName - Return the name of the specified opcode enum (e.g.
  35. /// "MOV32ri") or empty if we can't resolve it.
  36. StringRef MCInstPrinter::getOpcodeName(unsigned Opcode) const {
  37. return MII.getName(Opcode);
  38. }
  39. void MCInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
  40. llvm_unreachable("Target should implement this");
  41. }
  42. void MCInstPrinter::printAnnotation(raw_ostream &OS, StringRef Annot) {
  43. if (!Annot.empty()) {
  44. if (CommentStream) {
  45. (*CommentStream) << Annot;
  46. // By definition (see MCInstPrinter.h), CommentStream must end with
  47. // a newline after each comment.
  48. if (Annot.back() != '\n')
  49. (*CommentStream) << '\n';
  50. } else
  51. OS << " " << MAI.getCommentString() << " " << Annot;
  52. }
  53. }
  54. static bool matchAliasCondition(const MCInst &MI, const MCSubtargetInfo *STI,
  55. const MCRegisterInfo &MRI, unsigned &OpIdx,
  56. const AliasMatchingData &M,
  57. const AliasPatternCond &C,
  58. bool &OrPredicateResult) {
  59. // Feature tests are special, they don't consume operands.
  60. if (C.Kind == AliasPatternCond::K_Feature)
  61. return STI->getFeatureBits().test(C.Value);
  62. if (C.Kind == AliasPatternCond::K_NegFeature)
  63. return !STI->getFeatureBits().test(C.Value);
  64. // For feature tests where just one feature is required in a list, set the
  65. // predicate result bit to whether the expression will return true, and only
  66. // return the real result at the end of list marker.
  67. if (C.Kind == AliasPatternCond::K_OrFeature) {
  68. OrPredicateResult |= STI->getFeatureBits().test(C.Value);
  69. return true;
  70. }
  71. if (C.Kind == AliasPatternCond::K_OrNegFeature) {
  72. OrPredicateResult |= !(STI->getFeatureBits().test(C.Value));
  73. return true;
  74. }
  75. if (C.Kind == AliasPatternCond::K_EndOrFeatures) {
  76. bool Res = OrPredicateResult;
  77. OrPredicateResult = false;
  78. return Res;
  79. }
  80. // Get and consume an operand.
  81. const MCOperand &Opnd = MI.getOperand(OpIdx);
  82. ++OpIdx;
  83. // Check the specific condition for the operand.
  84. switch (C.Kind) {
  85. case AliasPatternCond::K_Imm:
  86. // Operand must be a specific immediate.
  87. return Opnd.isImm() && Opnd.getImm() == int32_t(C.Value);
  88. case AliasPatternCond::K_Reg:
  89. // Operand must be a specific register.
  90. return Opnd.isReg() && Opnd.getReg() == C.Value;
  91. case AliasPatternCond::K_TiedReg:
  92. // Operand must match the register of another operand.
  93. return Opnd.isReg() && Opnd.getReg() == MI.getOperand(C.Value).getReg();
  94. case AliasPatternCond::K_RegClass:
  95. // Operand must be a register in this class. Value is a register class id.
  96. return Opnd.isReg() && MRI.getRegClass(C.Value).contains(Opnd.getReg());
  97. case AliasPatternCond::K_Custom:
  98. // Operand must match some custom criteria.
  99. return M.ValidateMCOperand(Opnd, *STI, C.Value);
  100. case AliasPatternCond::K_Ignore:
  101. // Operand can be anything.
  102. return true;
  103. case AliasPatternCond::K_Feature:
  104. case AliasPatternCond::K_NegFeature:
  105. case AliasPatternCond::K_OrFeature:
  106. case AliasPatternCond::K_OrNegFeature:
  107. case AliasPatternCond::K_EndOrFeatures:
  108. llvm_unreachable("handled earlier");
  109. }
  110. llvm_unreachable("invalid kind");
  111. }
  112. const char *MCInstPrinter::matchAliasPatterns(const MCInst *MI,
  113. const MCSubtargetInfo *STI,
  114. const AliasMatchingData &M) {
  115. // Binary search by opcode. Return false if there are no aliases for this
  116. // opcode.
  117. auto It = lower_bound(M.OpToPatterns, MI->getOpcode(),
  118. [](const PatternsForOpcode &L, unsigned Opcode) {
  119. return L.Opcode < Opcode;
  120. });
  121. if (It == M.OpToPatterns.end() || It->Opcode != MI->getOpcode())
  122. return nullptr;
  123. // Try all patterns for this opcode.
  124. uint32_t AsmStrOffset = ~0U;
  125. ArrayRef<AliasPattern> Patterns =
  126. M.Patterns.slice(It->PatternStart, It->NumPatterns);
  127. for (const AliasPattern &P : Patterns) {
  128. // Check operand count first.
  129. if (MI->getNumOperands() != P.NumOperands)
  130. return nullptr;
  131. // Test all conditions for this pattern.
  132. ArrayRef<AliasPatternCond> Conds =
  133. M.PatternConds.slice(P.AliasCondStart, P.NumConds);
  134. unsigned OpIdx = 0;
  135. bool OrPredicateResult = false;
  136. if (llvm::all_of(Conds, [&](const AliasPatternCond &C) {
  137. return matchAliasCondition(*MI, STI, MRI, OpIdx, M, C,
  138. OrPredicateResult);
  139. })) {
  140. // If all conditions matched, use this asm string.
  141. AsmStrOffset = P.AsmStrOffset;
  142. break;
  143. }
  144. }
  145. // If no alias matched, don't print an alias.
  146. if (AsmStrOffset == ~0U)
  147. return nullptr;
  148. // Go to offset AsmStrOffset and use the null terminated string there. The
  149. // offset should point to the beginning of an alias string, so it should
  150. // either be zero or be preceded by a null byte.
  151. assert(AsmStrOffset < M.AsmStrings.size() &&
  152. (AsmStrOffset == 0 || M.AsmStrings[AsmStrOffset - 1] == '\0') &&
  153. "bad asm string offset");
  154. return M.AsmStrings.data() + AsmStrOffset;
  155. }
  156. /// Utility functions to make adding mark ups simpler.
  157. StringRef MCInstPrinter::markup(StringRef s) const {
  158. if (getUseMarkup())
  159. return s;
  160. else
  161. return "";
  162. }
  163. // For asm-style hex (e.g. 0ffh) the first digit always has to be a number.
  164. static bool needsLeadingZero(uint64_t Value)
  165. {
  166. while (Value)
  167. {
  168. uint64_t digit = (Value >> 60) & 0xf;
  169. if (digit != 0)
  170. return (digit >= 0xa);
  171. Value <<= 4;
  172. }
  173. return false;
  174. }
  175. format_object<int64_t> MCInstPrinter::formatDec(int64_t Value) const {
  176. return format("%" PRId64, Value);
  177. }
  178. format_object<int64_t> MCInstPrinter::formatHex(int64_t Value) const {
  179. switch (PrintHexStyle) {
  180. case HexStyle::C:
  181. if (Value < 0) {
  182. if (Value == std::numeric_limits<int64_t>::min())
  183. return format<int64_t>("-0x8000000000000000", Value);
  184. return format("-0x%" PRIx64, -Value);
  185. }
  186. return format("0x%" PRIx64, Value);
  187. case HexStyle::Asm:
  188. if (Value < 0) {
  189. if (Value == std::numeric_limits<int64_t>::min())
  190. return format<int64_t>("-8000000000000000h", Value);
  191. if (needsLeadingZero(-(uint64_t)(Value)))
  192. return format("-0%" PRIx64 "h", -Value);
  193. return format("-%" PRIx64 "h", -Value);
  194. }
  195. if (needsLeadingZero((uint64_t)(Value)))
  196. return format("0%" PRIx64 "h", Value);
  197. return format("%" PRIx64 "h", Value);
  198. }
  199. llvm_unreachable("unsupported print style");
  200. }
  201. format_object<uint64_t> MCInstPrinter::formatHex(uint64_t Value) const {
  202. switch(PrintHexStyle) {
  203. case HexStyle::C:
  204. return format("0x%" PRIx64, Value);
  205. case HexStyle::Asm:
  206. if (needsLeadingZero(Value))
  207. return format("0%" PRIx64 "h", Value);
  208. else
  209. return format("%" PRIx64 "h", Value);
  210. }
  211. llvm_unreachable("unsupported print style");
  212. }