|
10 | 10 | #include "llvm/ADT/ArrayRef.h"
|
11 | 11 | #include "llvm/ADT/StringRef.h"
|
12 | 12 | #include "llvm/MC/MCAsmInfo.h"
|
| 13 | +#include "llvm/MC/MCInst.h" |
13 | 14 | #include "llvm/MC/MCInstrInfo.h"
|
| 15 | +#include "llvm/MC/MCSubtargetInfo.h" |
14 | 16 | #include "llvm/Support/ErrorHandling.h"
|
15 | 17 | #include "llvm/Support/Format.h"
|
16 | 18 | #include "llvm/Support/raw_ostream.h"
|
@@ -57,6 +59,94 @@ void MCInstPrinter::printAnnotation(raw_ostream &OS, StringRef Annot) {
|
57 | 59 | }
|
58 | 60 | }
|
59 | 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 | + |
60 | 150 | /// Utility functions to make adding mark ups simpler.
|
61 | 151 | StringRef MCInstPrinter::markup(StringRef s) const {
|
62 | 152 | if (getUseMarkup())
|
|
0 commit comments