Path: blob/main/contrib/llvm-project/llvm/lib/MC/MCInstPrinter.cpp
35233 views
//===- MCInstPrinter.cpp - Convert an MCInst to target assembly syntax ----===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#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>2122using namespace llvm;2324void llvm::dumpBytes(ArrayRef<uint8_t> bytes, raw_ostream &OS) {25static const char hex_rep[] = "0123456789abcdef";26bool First = true;27for (char i: bytes) {28if (First)29First = false;30else31OS << ' ';32OS << hex_rep[(i & 0xF0) >> 4];33OS << hex_rep[i & 0xF];34}35}3637MCInstPrinter::~MCInstPrinter() = default;3839/// getOpcodeName - Return the name of the specified opcode enum (e.g.40/// "MOV32ri") or empty if we can't resolve it.41StringRef MCInstPrinter::getOpcodeName(unsigned Opcode) const {42return MII.getName(Opcode);43}4445void MCInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg) const {46llvm_unreachable("Target should implement this");47}4849void MCInstPrinter::printAnnotation(raw_ostream &OS, StringRef Annot) {50if (!Annot.empty()) {51if (CommentStream) {52(*CommentStream) << Annot;53// By definition (see MCInstPrinter.h), CommentStream must end with54// a newline after each comment.55if (Annot.back() != '\n')56(*CommentStream) << '\n';57} else58OS << " " << MAI.getCommentString() << " " << Annot;59}60}6162static bool matchAliasCondition(const MCInst &MI, const MCSubtargetInfo *STI,63const MCRegisterInfo &MRI, unsigned &OpIdx,64const AliasMatchingData &M,65const AliasPatternCond &C,66bool &OrPredicateResult) {67// Feature tests are special, they don't consume operands.68if (C.Kind == AliasPatternCond::K_Feature)69return STI->getFeatureBits().test(C.Value);70if (C.Kind == AliasPatternCond::K_NegFeature)71return !STI->getFeatureBits().test(C.Value);72// For feature tests where just one feature is required in a list, set the73// predicate result bit to whether the expression will return true, and only74// return the real result at the end of list marker.75if (C.Kind == AliasPatternCond::K_OrFeature) {76OrPredicateResult |= STI->getFeatureBits().test(C.Value);77return true;78}79if (C.Kind == AliasPatternCond::K_OrNegFeature) {80OrPredicateResult |= !(STI->getFeatureBits().test(C.Value));81return true;82}83if (C.Kind == AliasPatternCond::K_EndOrFeatures) {84bool Res = OrPredicateResult;85OrPredicateResult = false;86return Res;87}8889// Get and consume an operand.90const MCOperand &Opnd = MI.getOperand(OpIdx);91++OpIdx;9293// Check the specific condition for the operand.94switch (C.Kind) {95case AliasPatternCond::K_Imm:96// Operand must be a specific immediate.97return Opnd.isImm() && Opnd.getImm() == int32_t(C.Value);98case AliasPatternCond::K_Reg:99// Operand must be a specific register.100return Opnd.isReg() && Opnd.getReg() == C.Value;101case AliasPatternCond::K_TiedReg:102// Operand must match the register of another operand.103return Opnd.isReg() && Opnd.getReg() == MI.getOperand(C.Value).getReg();104case AliasPatternCond::K_RegClass:105// Operand must be a register in this class. Value is a register class id.106return Opnd.isReg() && MRI.getRegClass(C.Value).contains(Opnd.getReg());107case AliasPatternCond::K_Custom:108// Operand must match some custom criteria.109return M.ValidateMCOperand(Opnd, *STI, C.Value);110case AliasPatternCond::K_Ignore:111// Operand can be anything.112return true;113case AliasPatternCond::K_Feature:114case AliasPatternCond::K_NegFeature:115case AliasPatternCond::K_OrFeature:116case AliasPatternCond::K_OrNegFeature:117case AliasPatternCond::K_EndOrFeatures:118llvm_unreachable("handled earlier");119}120llvm_unreachable("invalid kind");121}122123const char *MCInstPrinter::matchAliasPatterns(const MCInst *MI,124const MCSubtargetInfo *STI,125const AliasMatchingData &M) {126// Binary search by opcode. Return false if there are no aliases for this127// opcode.128auto It = lower_bound(M.OpToPatterns, MI->getOpcode(),129[](const PatternsForOpcode &L, unsigned Opcode) {130return L.Opcode < Opcode;131});132if (It == M.OpToPatterns.end() || It->Opcode != MI->getOpcode())133return nullptr;134135// Try all patterns for this opcode.136uint32_t AsmStrOffset = ~0U;137ArrayRef<AliasPattern> Patterns =138M.Patterns.slice(It->PatternStart, It->NumPatterns);139for (const AliasPattern &P : Patterns) {140// Check operand count first.141if (MI->getNumOperands() != P.NumOperands)142return nullptr;143144// Test all conditions for this pattern.145ArrayRef<AliasPatternCond> Conds =146M.PatternConds.slice(P.AliasCondStart, P.NumConds);147unsigned OpIdx = 0;148bool OrPredicateResult = false;149if (llvm::all_of(Conds, [&](const AliasPatternCond &C) {150return matchAliasCondition(*MI, STI, MRI, OpIdx, M, C,151OrPredicateResult);152})) {153// If all conditions matched, use this asm string.154AsmStrOffset = P.AsmStrOffset;155break;156}157}158159// If no alias matched, don't print an alias.160if (AsmStrOffset == ~0U)161return nullptr;162163// Go to offset AsmStrOffset and use the null terminated string there. The164// offset should point to the beginning of an alias string, so it should165// either be zero or be preceded by a null byte.166assert(AsmStrOffset < M.AsmStrings.size() &&167(AsmStrOffset == 0 || M.AsmStrings[AsmStrOffset - 1] == '\0') &&168"bad asm string offset");169return M.AsmStrings.data() + AsmStrOffset;170}171172// For asm-style hex (e.g. 0ffh) the first digit always has to be a number.173static bool needsLeadingZero(uint64_t Value)174{175while (Value)176{177uint64_t digit = (Value >> 60) & 0xf;178if (digit != 0)179return (digit >= 0xa);180Value <<= 4;181}182return false;183}184185format_object<int64_t> MCInstPrinter::formatDec(int64_t Value) const {186return format("%" PRId64, Value);187}188189format_object<int64_t> MCInstPrinter::formatHex(int64_t Value) const {190switch (PrintHexStyle) {191case HexStyle::C:192if (Value < 0) {193if (Value == std::numeric_limits<int64_t>::min())194return format<int64_t>("-0x8000000000000000", Value);195return format("-0x%" PRIx64, -Value);196}197return format("0x%" PRIx64, Value);198case HexStyle::Asm:199if (Value < 0) {200if (Value == std::numeric_limits<int64_t>::min())201return format<int64_t>("-8000000000000000h", Value);202if (needsLeadingZero(-(uint64_t)(Value)))203return format("-0%" PRIx64 "h", -Value);204return format("-%" PRIx64 "h", -Value);205}206if (needsLeadingZero((uint64_t)(Value)))207return format("0%" PRIx64 "h", Value);208return format("%" PRIx64 "h", Value);209}210llvm_unreachable("unsupported print style");211}212213format_object<uint64_t> MCInstPrinter::formatHex(uint64_t Value) const {214switch(PrintHexStyle) {215case HexStyle::C:216return format("0x%" PRIx64, Value);217case HexStyle::Asm:218if (needsLeadingZero(Value))219return format("0%" PRIx64 "h", Value);220else221return format("%" PRIx64 "h", Value);222}223llvm_unreachable("unsupported print style");224}225226MCInstPrinter::WithMarkup MCInstPrinter::markup(raw_ostream &OS,227Markup S) const {228return WithMarkup(OS, S, getUseMarkup(), getUseColor());229}230231MCInstPrinter::WithMarkup::WithMarkup(raw_ostream &OS, Markup M,232bool EnableMarkup, bool EnableColor)233: OS(OS), EnableMarkup(EnableMarkup), EnableColor(EnableColor) {234if (EnableColor) {235switch (M) {236case Markup::Immediate:237OS.changeColor(raw_ostream::RED);238break;239case Markup::Register:240OS.changeColor(raw_ostream::CYAN);241break;242case Markup::Target:243OS.changeColor(raw_ostream::YELLOW);244break;245case Markup::Memory:246OS.changeColor(raw_ostream::GREEN);247break;248}249}250251if (EnableMarkup) {252switch (M) {253case Markup::Immediate:254OS << "<imm:";255break;256case Markup::Register:257OS << "<reg:";258break;259case Markup::Target:260OS << "<target:";261break;262case Markup::Memory:263OS << "<mem:";264break;265}266}267}268269MCInstPrinter::WithMarkup::~WithMarkup() {270if (EnableMarkup)271OS << '>';272if (EnableColor)273OS.resetColor();274}275276277