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