MCInstPrinter.cpp 7.9 KB

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