Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/utils/TableGen/Common/AsmWriterInst.cpp
35290 views
1
//===- AsmWriterInst.h - Classes encapsulating a printable inst -----------===//
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
// These classes implement a parser for assembly strings.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "AsmWriterInst.h"
14
#include "CodeGenInstruction.h"
15
#include "llvm/ADT/StringExtras.h"
16
#include "llvm/TableGen/Error.h"
17
#include "llvm/TableGen/Record.h"
18
19
using namespace llvm;
20
21
static bool isIdentChar(char C) { return isAlnum(C) || C == '_'; }
22
23
std::string AsmWriterOperand::getCode(bool PassSubtarget) const {
24
if (OperandType == isLiteralTextOperand) {
25
if (Str.size() == 1)
26
return "O << '" + Str + "';";
27
return "O << \"" + Str + "\";";
28
}
29
30
if (OperandType == isLiteralStatementOperand)
31
return Str;
32
33
std::string Result = Str + "(MI";
34
if (PCRel)
35
Result += ", Address";
36
if (MIOpNo != ~0U)
37
Result += ", " + utostr(MIOpNo);
38
if (PassSubtarget)
39
Result += ", STI";
40
Result += ", O";
41
if (!MiModifier.empty())
42
Result += ", \"" + MiModifier + '"';
43
return Result + ");";
44
}
45
46
/// ParseAsmString - Parse the specified Instruction's AsmString into this
47
/// AsmWriterInst.
48
///
49
AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned CGIIndex,
50
unsigned Variant)
51
: CGI(&CGI), CGIIndex(CGIIndex) {
52
53
// NOTE: Any extensions to this code need to be mirrored in the
54
// AsmPrinter::printInlineAsm code that executes as compile time (assuming
55
// that inline asm strings should also get the new feature)!
56
std::string AsmString = CGI.FlattenAsmStringVariants(CGI.AsmString, Variant);
57
std::string::size_type LastEmitted = 0;
58
while (LastEmitted != AsmString.size()) {
59
std::string::size_type DollarPos =
60
AsmString.find_first_of("$\\", LastEmitted);
61
if (DollarPos == std::string::npos)
62
DollarPos = AsmString.size();
63
64
// Emit a constant string fragment.
65
if (DollarPos != LastEmitted) {
66
for (; LastEmitted != DollarPos; ++LastEmitted)
67
switch (AsmString[LastEmitted]) {
68
case '\n':
69
AddLiteralString("\\n");
70
break;
71
case '\t':
72
AddLiteralString("\\t");
73
break;
74
case '"':
75
AddLiteralString("\\\"");
76
break;
77
case '\\':
78
AddLiteralString("\\\\");
79
break;
80
default:
81
AddLiteralString(std::string(1, AsmString[LastEmitted]));
82
break;
83
}
84
} else if (AsmString[DollarPos] == '\\') {
85
if (DollarPos + 1 != AsmString.size()) {
86
if (AsmString[DollarPos + 1] == 'n') {
87
AddLiteralString("\\n");
88
} else if (AsmString[DollarPos + 1] == 't') {
89
AddLiteralString("\\t");
90
} else if (std::string("${|}\\").find(AsmString[DollarPos + 1]) !=
91
std::string::npos) {
92
AddLiteralString(std::string(1, AsmString[DollarPos + 1]));
93
} else {
94
PrintFatalError(
95
CGI.TheDef->getLoc(),
96
"Non-supported escaped character found in instruction '" +
97
CGI.TheDef->getName() + "'!");
98
}
99
LastEmitted = DollarPos + 2;
100
continue;
101
}
102
} else if (DollarPos + 1 != AsmString.size() &&
103
AsmString[DollarPos + 1] == '$') {
104
AddLiteralString("$"); // "$$" -> $
105
LastEmitted = DollarPos + 2;
106
} else {
107
// Get the name of the variable.
108
std::string::size_type VarEnd = DollarPos + 1;
109
110
// handle ${foo}bar as $foo by detecting whether the character following
111
// the dollar sign is a curly brace. If so, advance VarEnd and DollarPos
112
// so the variable name does not contain the leading curly brace.
113
bool hasCurlyBraces = false;
114
if (VarEnd < AsmString.size() && '{' == AsmString[VarEnd]) {
115
hasCurlyBraces = true;
116
++DollarPos;
117
++VarEnd;
118
}
119
120
while (VarEnd < AsmString.size() && isIdentChar(AsmString[VarEnd]))
121
++VarEnd;
122
StringRef VarName(AsmString.data() + DollarPos + 1,
123
VarEnd - DollarPos - 1);
124
125
// Modifier - Support ${foo:modifier} syntax, where "modifier" is passed
126
// into printOperand. Also support ${:feature}, which is passed into
127
// PrintSpecial.
128
std::string Modifier;
129
130
// In order to avoid starting the next string at the terminating curly
131
// brace, advance the end position past it if we found an opening curly
132
// brace.
133
if (hasCurlyBraces) {
134
if (VarEnd >= AsmString.size())
135
PrintFatalError(
136
CGI.TheDef->getLoc(),
137
"Reached end of string before terminating curly brace in '" +
138
CGI.TheDef->getName() + "'");
139
140
// Look for a modifier string.
141
if (AsmString[VarEnd] == ':') {
142
++VarEnd;
143
if (VarEnd >= AsmString.size())
144
PrintFatalError(
145
CGI.TheDef->getLoc(),
146
"Reached end of string before terminating curly brace in '" +
147
CGI.TheDef->getName() + "'");
148
149
std::string::size_type ModifierStart = VarEnd;
150
while (VarEnd < AsmString.size() && isIdentChar(AsmString[VarEnd]))
151
++VarEnd;
152
Modifier = AsmString.substr(ModifierStart, VarEnd - ModifierStart);
153
if (Modifier.empty())
154
PrintFatalError(CGI.TheDef->getLoc(),
155
"Bad operand modifier name in '" +
156
CGI.TheDef->getName() + "'");
157
}
158
159
if (AsmString[VarEnd] != '}')
160
PrintFatalError(
161
CGI.TheDef->getLoc(),
162
"Variable name beginning with '{' did not end with '}' in '" +
163
CGI.TheDef->getName() + "'");
164
++VarEnd;
165
}
166
if (VarName.empty() && Modifier.empty())
167
PrintFatalError(CGI.TheDef->getLoc(),
168
"Stray '$' in '" + CGI.TheDef->getName() +
169
"' asm string, maybe you want $$?");
170
171
if (VarName.empty()) {
172
// Just a modifier, pass this into PrintSpecial.
173
Operands.emplace_back("PrintSpecial", ~0U, Modifier);
174
} else {
175
// Otherwise, normal operand.
176
unsigned OpNo = CGI.Operands.getOperandNamed(VarName);
177
CGIOperandList::OperandInfo OpInfo = CGI.Operands[OpNo];
178
179
unsigned MIOp = OpInfo.MIOperandNo;
180
Operands.emplace_back(OpInfo.PrinterMethodName, MIOp, Modifier,
181
AsmWriterOperand::isMachineInstrOperand,
182
OpInfo.OperandType == "MCOI::OPERAND_PCREL");
183
}
184
LastEmitted = VarEnd;
185
}
186
}
187
188
Operands.emplace_back("return;", AsmWriterOperand::isLiteralStatementOperand);
189
}
190
191
/// MatchesAllButOneOp - If this instruction is exactly identical to the
192
/// specified instruction except for one differing operand, return the differing
193
/// operand number. If more than one operand mismatches, return ~1, otherwise
194
/// if the instructions are identical return ~0.
195
unsigned AsmWriterInst::MatchesAllButOneOp(const AsmWriterInst &Other) const {
196
if (Operands.size() != Other.Operands.size())
197
return ~1;
198
199
unsigned MismatchOperand = ~0U;
200
for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
201
if (Operands[i] != Other.Operands[i]) {
202
if (MismatchOperand != ~0U) // Already have one mismatch?
203
return ~1U;
204
MismatchOperand = i;
205
}
206
}
207
return MismatchOperand;
208
}
209
210