aboutsummaryrefslogtreecommitdiff
path: root/llvm/include/llvm/MC/MCInstPrinter.h
blob: 8b9ef178e33c1bdbe1ceaaef989b900f305a4b4c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
//===- MCInstPrinter.h - MCInst to target assembly syntax -------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_MC_MCINSTPRINTER_H
#define LLVM_MC_MCINSTPRINTER_H

#include "llvm/Support/Format.h"
#include <cstdint>

namespace llvm {

class MCAsmInfo;
class MCInst;
class MCOperand;
class MCInstrInfo;
class MCInstrAnalysis;
class MCRegisterInfo;
class MCSubtargetInfo;
class raw_ostream;
class StringRef;

/// Convert `Bytes' to a hex string and output to `OS'
void dumpBytes(ArrayRef<uint8_t> Bytes, raw_ostream &OS);

namespace HexStyle {

enum Style {
  C,  ///< 0xff
  Asm ///< 0ffh
};

} // end namespace HexStyle

struct AliasMatchingData;

/// This is an instance of a target assembly language printer that
/// converts an MCInst to valid target assembly syntax.
class MCInstPrinter {
protected:
  /// A stream that comments can be emitted to if desired.  Each comment
  /// must end with a newline.  This will be null if verbose assembly emission
  /// is disabled.
  raw_ostream *CommentStream = nullptr;
  const MCAsmInfo &MAI;
  const MCInstrInfo &MII;
  const MCRegisterInfo &MRI;
  const MCInstrAnalysis *MIA = nullptr;

  /// True if we are printing marked up assembly.
  bool UseMarkup = false;

  /// True if we are printing immediates as hex.
  bool PrintImmHex = false;

  /// Which style to use for printing hexadecimal values.
  HexStyle::Style PrintHexStyle = HexStyle::C;

  /// If true, a branch immediate (e.g. bl 4) will be printed as a hexadecimal
  /// address (e.g. bl 0x20004). This is useful for a stream disassembler
  /// (llvm-objdump -d).
  bool PrintBranchImmAsAddress = false;

  /// If true, symbolize branch target and memory reference operands.
  bool SymbolizeOperands = false;

  /// Utility function for printing annotations.
  void printAnnotation(raw_ostream &OS, StringRef Annot);

  /// Helper for matching MCInsts to alias patterns when printing instructions.
  const char *matchAliasPatterns(const MCInst *MI, const MCSubtargetInfo *STI,
                                 const AliasMatchingData &M);

public:
  MCInstPrinter(const MCAsmInfo &mai, const MCInstrInfo &mii,
                const MCRegisterInfo &mri) : MAI(mai), MII(mii), MRI(mri) {}

  virtual ~MCInstPrinter();

  /// Customize the printer according to a command line option.
  /// @return true if the option is recognized and applied.
  virtual bool applyTargetSpecificCLOption(StringRef Opt) { return false; }

  /// Specify a stream to emit comments to.
  void setCommentStream(raw_ostream &OS) { CommentStream = &OS; }

  /// Returns a pair containing the mnemonic for \p MI and the number of bits
  /// left for further processing by printInstruction (generated by tablegen).
  virtual std::pair<const char *, uint64_t> getMnemonic(const MCInst *MI) = 0;

  /// Print the specified MCInst to the specified raw_ostream.
  ///
  /// \p Address the address of current instruction on most targets, used to
  /// print a PC relative immediate as the target address. On targets where a PC
  /// relative immediate is relative to the next instruction and the length of a
  /// MCInst is difficult to measure (e.g. x86), this is the address of the next
  /// instruction. If Address is 0, the immediate will be printed.
  virtual void printInst(const MCInst *MI, uint64_t Address, StringRef Annot,
                         const MCSubtargetInfo &STI, raw_ostream &OS) = 0;

  /// Return the name of the specified opcode enum (e.g. "MOV32ri") or
  /// empty if we can't resolve it.
  StringRef getOpcodeName(unsigned Opcode) const;

  /// Print the assembler register name.
  virtual void printRegName(raw_ostream &OS, unsigned RegNo) const;

  bool getUseMarkup() const { return UseMarkup; }
  void setUseMarkup(bool Value) { UseMarkup = Value; }

  /// Utility functions to make adding mark ups simpler.
  StringRef markup(StringRef s) const;

  bool getPrintImmHex() const { return PrintImmHex; }
  void setPrintImmHex(bool Value) { PrintImmHex = Value; }

  void setPrintHexStyle(HexStyle::Style Value) { PrintHexStyle = Value; }

  void setPrintBranchImmAsAddress(bool Value) {
    PrintBranchImmAsAddress = Value;
  }

  void setSymbolizeOperands(bool Value) { SymbolizeOperands = Value; }
  void setMCInstrAnalysis(const MCInstrAnalysis *Value) { MIA = Value; }

  /// Utility function to print immediates in decimal or hex.
  format_object<int64_t> formatImm(int64_t Value) const {
    return PrintImmHex ? formatHex(Value) : formatDec(Value);
  }

  /// Utility functions to print decimal/hexadecimal values.
  format_object<int64_t> formatDec(int64_t Value) const;
  format_object<int64_t> formatHex(int64_t Value) const;
  format_object<uint64_t> formatHex(uint64_t Value) const;
};

/// Map from opcode to pattern list by binary search.
struct PatternsForOpcode {
  uint32_t Opcode;
  uint16_t PatternStart;
  uint16_t NumPatterns;
};

/// Data for each alias pattern. Includes feature bits, string, number of
/// operands, and a variadic list of conditions to check.
struct AliasPattern {
  uint32_t AsmStrOffset;
  uint32_t AliasCondStart;
  uint8_t NumOperands;
  uint8_t NumConds;
};

struct AliasPatternCond {
  enum CondKind : uint8_t {
    K_Feature,       // Match only if a feature is enabled.
    K_NegFeature,    // Match only if a feature is disabled.
    K_OrFeature,     // Match only if one of a set of features is enabled.
    K_OrNegFeature,  // Match only if one of a set of features is disabled.
    K_EndOrFeatures, // Note end of list of K_Or(Neg)?Features.
    K_Ignore,        // Match any operand.
    K_Reg,           // Match a specific register.
    K_TiedReg,       // Match another already matched register.
    K_Imm,           // Match a specific immediate.
    K_RegClass,      // Match registers in a class.
    K_Custom,        // Call custom matcher by index.
  };

  CondKind Kind;
  uint32_t Value;
};

/// Tablegenerated data structures needed to match alias patterns.
struct AliasMatchingData {
  ArrayRef<PatternsForOpcode> OpToPatterns;
  ArrayRef<AliasPattern> Patterns;
  ArrayRef<AliasPatternCond> PatternConds;
  StringRef AsmStrings;
  bool (*ValidateMCOperand)(const MCOperand &MCOp, const MCSubtargetInfo &STI,
                            unsigned PredicateIndex);
};

} // end namespace llvm

#endif // LLVM_MC_MCINSTPRINTER_H