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/CodeGenInstruction.cpp
35290 views
1
//===- CodeGenInstruction.cpp - CodeGen Instruction Class Wrapper ---------===//
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
// This file implements the CodeGenInstruction class.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "CodeGenInstruction.h"
14
#include "CodeGenTarget.h"
15
#include "llvm/ADT/StringExtras.h"
16
#include "llvm/TableGen/Error.h"
17
#include "llvm/TableGen/Record.h"
18
#include <set>
19
using namespace llvm;
20
21
//===----------------------------------------------------------------------===//
22
// CGIOperandList Implementation
23
//===----------------------------------------------------------------------===//
24
25
CGIOperandList::CGIOperandList(Record *R) : TheDef(R) {
26
isPredicable = false;
27
hasOptionalDef = false;
28
isVariadic = false;
29
30
DagInit *OutDI = R->getValueAsDag("OutOperandList");
31
32
if (DefInit *Init = dyn_cast<DefInit>(OutDI->getOperator())) {
33
if (Init->getDef()->getName() != "outs")
34
PrintFatalError(R->getLoc(),
35
R->getName() +
36
": invalid def name for output list: use 'outs'");
37
} else
38
PrintFatalError(R->getLoc(),
39
R->getName() + ": invalid output list: use 'outs'");
40
41
NumDefs = OutDI->getNumArgs();
42
43
DagInit *InDI = R->getValueAsDag("InOperandList");
44
if (DefInit *Init = dyn_cast<DefInit>(InDI->getOperator())) {
45
if (Init->getDef()->getName() != "ins")
46
PrintFatalError(R->getLoc(),
47
R->getName() +
48
": invalid def name for input list: use 'ins'");
49
} else
50
PrintFatalError(R->getLoc(),
51
R->getName() + ": invalid input list: use 'ins'");
52
53
unsigned MIOperandNo = 0;
54
std::set<std::string> OperandNames;
55
unsigned e = InDI->getNumArgs() + OutDI->getNumArgs();
56
OperandList.reserve(e);
57
bool VariadicOuts = false;
58
for (unsigned i = 0; i != e; ++i) {
59
Init *ArgInit;
60
StringRef ArgName;
61
if (i < NumDefs) {
62
ArgInit = OutDI->getArg(i);
63
ArgName = OutDI->getArgNameStr(i);
64
} else {
65
ArgInit = InDI->getArg(i - NumDefs);
66
ArgName = InDI->getArgNameStr(i - NumDefs);
67
}
68
69
DagInit *SubArgDag = dyn_cast<DagInit>(ArgInit);
70
if (SubArgDag)
71
ArgInit = SubArgDag->getOperator();
72
73
DefInit *Arg = dyn_cast<DefInit>(ArgInit);
74
if (!Arg)
75
PrintFatalError(R->getLoc(), "Illegal operand for the '" + R->getName() +
76
"' instruction!");
77
78
Record *Rec = Arg->getDef();
79
std::string PrintMethod = "printOperand";
80
std::string EncoderMethod;
81
std::string OperandType = "OPERAND_UNKNOWN";
82
std::string OperandNamespace = "MCOI";
83
unsigned NumOps = 1;
84
DagInit *MIOpInfo = nullptr;
85
if (Rec->isSubClassOf("RegisterOperand")) {
86
PrintMethod = std::string(Rec->getValueAsString("PrintMethod"));
87
OperandType = std::string(Rec->getValueAsString("OperandType"));
88
OperandNamespace = std::string(Rec->getValueAsString("OperandNamespace"));
89
EncoderMethod = std::string(Rec->getValueAsString("EncoderMethod"));
90
} else if (Rec->isSubClassOf("Operand")) {
91
PrintMethod = std::string(Rec->getValueAsString("PrintMethod"));
92
OperandType = std::string(Rec->getValueAsString("OperandType"));
93
OperandNamespace = std::string(Rec->getValueAsString("OperandNamespace"));
94
// If there is an explicit encoder method, use it.
95
EncoderMethod = std::string(Rec->getValueAsString("EncoderMethod"));
96
MIOpInfo = Rec->getValueAsDag("MIOperandInfo");
97
98
// Verify that MIOpInfo has an 'ops' root value.
99
if (!isa<DefInit>(MIOpInfo->getOperator()) ||
100
cast<DefInit>(MIOpInfo->getOperator())->getDef()->getName() != "ops")
101
PrintFatalError(R->getLoc(),
102
"Bad value for MIOperandInfo in operand '" +
103
Rec->getName() + "'\n");
104
105
// If we have MIOpInfo, then we have #operands equal to number of entries
106
// in MIOperandInfo.
107
if (unsigned NumArgs = MIOpInfo->getNumArgs())
108
NumOps = NumArgs;
109
110
if (Rec->isSubClassOf("PredicateOp"))
111
isPredicable = true;
112
else if (Rec->isSubClassOf("OptionalDefOperand"))
113
hasOptionalDef = true;
114
} else if (Rec->getName() == "variable_ops") {
115
if (i < NumDefs)
116
VariadicOuts = true;
117
isVariadic = true;
118
continue;
119
} else if (Rec->isSubClassOf("RegisterClass")) {
120
OperandType = "OPERAND_REGISTER";
121
} else if (!Rec->isSubClassOf("PointerLikeRegClass") &&
122
!Rec->isSubClassOf("unknown_class")) {
123
PrintFatalError(R->getLoc(), "Unknown operand class '" + Rec->getName() +
124
"' in '" + R->getName() +
125
"' instruction!");
126
}
127
128
// Check that the operand has a name and that it's unique.
129
if (ArgName.empty())
130
PrintFatalError(R->getLoc(), "In instruction '" + R->getName() +
131
"', operand #" + Twine(i) +
132
" has no name!");
133
if (!OperandNames.insert(std::string(ArgName)).second)
134
PrintFatalError(R->getLoc(),
135
"In instruction '" + R->getName() + "', operand #" +
136
Twine(i) +
137
" has the same name as a previous operand!");
138
139
OperandInfo &OpInfo = OperandList.emplace_back(
140
Rec, std::string(ArgName), std::string(PrintMethod),
141
OperandNamespace + "::" + OperandType, MIOperandNo, NumOps, MIOpInfo);
142
143
if (SubArgDag) {
144
if (SubArgDag->getNumArgs() != NumOps) {
145
PrintFatalError(R->getLoc(), "In instruction '" + R->getName() +
146
"', operand #" + Twine(i) + " has " +
147
Twine(SubArgDag->getNumArgs()) +
148
" sub-arg names, expected " +
149
Twine(NumOps) + ".");
150
}
151
152
for (unsigned j = 0; j < NumOps; ++j) {
153
if (!isa<UnsetInit>(SubArgDag->getArg(j)))
154
PrintFatalError(R->getLoc(),
155
"In instruction '" + R->getName() + "', operand #" +
156
Twine(i) + " sub-arg #" + Twine(j) +
157
" has unexpected operand (expected only $name).");
158
159
StringRef SubArgName = SubArgDag->getArgNameStr(j);
160
if (SubArgName.empty())
161
PrintFatalError(R->getLoc(), "In instruction '" + R->getName() +
162
"', operand #" + Twine(i) +
163
" has no name!");
164
if (!OperandNames.insert(std::string(SubArgName)).second)
165
PrintFatalError(R->getLoc(),
166
"In instruction '" + R->getName() + "', operand #" +
167
Twine(i) + " sub-arg #" + Twine(j) +
168
" has the same name as a previous operand!");
169
170
if (auto MaybeEncoderMethod =
171
cast<DefInit>(MIOpInfo->getArg(j))
172
->getDef()
173
->getValueAsOptionalString("EncoderMethod")) {
174
OpInfo.EncoderMethodNames[j] = *MaybeEncoderMethod;
175
}
176
177
OpInfo.SubOpNames[j] = SubArgName;
178
SubOpAliases[SubArgName] = std::pair(i, j);
179
}
180
} else if (!EncoderMethod.empty()) {
181
// If we have no explicit sub-op dag, but have an top-level encoder
182
// method, the single encoder will multiple sub-ops, itself.
183
OpInfo.EncoderMethodNames[0] = EncoderMethod;
184
for (unsigned j = 1; j < NumOps; ++j)
185
OpInfo.DoNotEncode[j] = true;
186
}
187
188
MIOperandNo += NumOps;
189
}
190
191
if (VariadicOuts)
192
--NumDefs;
193
}
194
195
/// getOperandNamed - Return the index of the operand with the specified
196
/// non-empty name. If the instruction does not have an operand with the
197
/// specified name, abort.
198
///
199
unsigned CGIOperandList::getOperandNamed(StringRef Name) const {
200
unsigned OpIdx;
201
if (hasOperandNamed(Name, OpIdx))
202
return OpIdx;
203
PrintFatalError(TheDef->getLoc(), "'" + TheDef->getName() +
204
"' does not have an operand named '$" +
205
Name + "'!");
206
}
207
208
/// hasOperandNamed - Query whether the instruction has an operand of the
209
/// given name. If so, return true and set OpIdx to the index of the
210
/// operand. Otherwise, return false.
211
bool CGIOperandList::hasOperandNamed(StringRef Name, unsigned &OpIdx) const {
212
assert(!Name.empty() && "Cannot search for operand with no name!");
213
for (unsigned i = 0, e = OperandList.size(); i != e; ++i)
214
if (OperandList[i].Name == Name) {
215
OpIdx = i;
216
return true;
217
}
218
return false;
219
}
220
221
bool CGIOperandList::hasSubOperandAlias(
222
StringRef Name, std::pair<unsigned, unsigned> &SubOp) const {
223
assert(!Name.empty() && "Cannot search for operand with no name!");
224
auto SubOpIter = SubOpAliases.find(Name);
225
if (SubOpIter != SubOpAliases.end()) {
226
SubOp = SubOpIter->second;
227
return true;
228
}
229
return false;
230
}
231
232
std::pair<unsigned, unsigned>
233
CGIOperandList::ParseOperandName(StringRef Op, bool AllowWholeOp) {
234
if (!Op.starts_with("$"))
235
PrintFatalError(TheDef->getLoc(),
236
TheDef->getName() + ": Illegal operand name: '" + Op + "'");
237
238
StringRef OpName = Op.substr(1);
239
StringRef SubOpName;
240
241
// Check to see if this is $foo.bar.
242
StringRef::size_type DotIdx = OpName.find_first_of('.');
243
if (DotIdx != StringRef::npos) {
244
SubOpName = OpName.substr(DotIdx + 1);
245
if (SubOpName.empty())
246
PrintFatalError(TheDef->getLoc(),
247
TheDef->getName() +
248
": illegal empty suboperand name in '" + Op + "'");
249
OpName = OpName.substr(0, DotIdx);
250
}
251
252
unsigned OpIdx;
253
254
if (std::pair<unsigned, unsigned> SubOp; hasSubOperandAlias(OpName, SubOp)) {
255
// Found a name for a piece of an operand, just return it directly.
256
if (!SubOpName.empty()) {
257
PrintFatalError(
258
TheDef->getLoc(),
259
TheDef->getName() +
260
": Cannot use dotted suboperand name within suboperand '" +
261
OpName + "'");
262
}
263
return SubOp;
264
}
265
266
OpIdx = getOperandNamed(OpName);
267
268
if (SubOpName.empty()) { // If no suboperand name was specified:
269
// If one was needed, throw.
270
if (OperandList[OpIdx].MINumOperands > 1 && !AllowWholeOp &&
271
SubOpName.empty())
272
PrintFatalError(TheDef->getLoc(),
273
TheDef->getName() +
274
": Illegal to refer to"
275
" whole operand part of complex operand '" +
276
Op + "'");
277
278
// Otherwise, return the operand.
279
return std::pair(OpIdx, 0U);
280
}
281
282
// Find the suboperand number involved.
283
DagInit *MIOpInfo = OperandList[OpIdx].MIOperandInfo;
284
if (!MIOpInfo)
285
PrintFatalError(TheDef->getLoc(), TheDef->getName() +
286
": unknown suboperand name in '" +
287
Op + "'");
288
289
// Find the operand with the right name.
290
for (unsigned i = 0, e = MIOpInfo->getNumArgs(); i != e; ++i)
291
if (MIOpInfo->getArgNameStr(i) == SubOpName)
292
return std::pair(OpIdx, i);
293
294
// Otherwise, didn't find it!
295
PrintFatalError(TheDef->getLoc(), TheDef->getName() +
296
": unknown suboperand name in '" + Op +
297
"'");
298
return std::pair(0U, 0U);
299
}
300
301
static void ParseConstraint(StringRef CStr, CGIOperandList &Ops, Record *Rec) {
302
// EARLY_CLOBBER: @early $reg
303
StringRef::size_type wpos = CStr.find_first_of(" \t");
304
StringRef::size_type start = CStr.find_first_not_of(" \t");
305
StringRef Tok = CStr.substr(start, wpos - start);
306
if (Tok == "@earlyclobber") {
307
StringRef Name = CStr.substr(wpos + 1);
308
wpos = Name.find_first_not_of(" \t");
309
if (wpos == StringRef::npos)
310
PrintFatalError(Rec->getLoc(),
311
"Illegal format for @earlyclobber constraint in '" +
312
Rec->getName() + "': '" + CStr + "'");
313
Name = Name.substr(wpos);
314
std::pair<unsigned, unsigned> Op = Ops.ParseOperandName(Name, false);
315
316
// Build the string for the operand
317
if (!Ops[Op.first].Constraints[Op.second].isNone())
318
PrintFatalError(Rec->getLoc(), "Operand '" + Name + "' of '" +
319
Rec->getName() +
320
"' cannot have multiple constraints!");
321
Ops[Op.first].Constraints[Op.second] =
322
CGIOperandList::ConstraintInfo::getEarlyClobber();
323
return;
324
}
325
326
// Only other constraint is "TIED_TO" for now.
327
StringRef::size_type pos = CStr.find_first_of('=');
328
if (pos == StringRef::npos || pos == 0 ||
329
CStr.find_first_of(" \t", pos) != (pos + 1) ||
330
CStr.find_last_of(" \t", pos) != (pos - 1))
331
PrintFatalError(Rec->getLoc(), "Unrecognized constraint '" + CStr +
332
"' in '" + Rec->getName() + "'");
333
start = CStr.find_first_not_of(" \t");
334
335
// TIED_TO: $src1 = $dst
336
wpos = CStr.find_first_of(" \t", start);
337
if (wpos == StringRef::npos || wpos > pos)
338
PrintFatalError(Rec->getLoc(),
339
"Illegal format for tied-to constraint in '" +
340
Rec->getName() + "': '" + CStr + "'");
341
StringRef LHSOpName = CStr.substr(start, wpos - start);
342
std::pair<unsigned, unsigned> LHSOp = Ops.ParseOperandName(LHSOpName, false);
343
344
wpos = CStr.find_first_not_of(" \t", pos + 1);
345
if (wpos == StringRef::npos)
346
PrintFatalError(Rec->getLoc(),
347
"Illegal format for tied-to constraint: '" + CStr + "'");
348
349
StringRef RHSOpName = CStr.substr(wpos);
350
std::pair<unsigned, unsigned> RHSOp = Ops.ParseOperandName(RHSOpName, false);
351
352
// Sort the operands into order, which should put the output one
353
// first. But keep the original order, for use in diagnostics.
354
bool FirstIsDest = (LHSOp < RHSOp);
355
std::pair<unsigned, unsigned> DestOp = (FirstIsDest ? LHSOp : RHSOp);
356
StringRef DestOpName = (FirstIsDest ? LHSOpName : RHSOpName);
357
std::pair<unsigned, unsigned> SrcOp = (FirstIsDest ? RHSOp : LHSOp);
358
StringRef SrcOpName = (FirstIsDest ? RHSOpName : LHSOpName);
359
360
// Ensure one operand is a def and the other is a use.
361
if (DestOp.first >= Ops.NumDefs)
362
PrintFatalError(Rec->getLoc(), "Input operands '" + LHSOpName + "' and '" +
363
RHSOpName + "' of '" + Rec->getName() +
364
"' cannot be tied!");
365
if (SrcOp.first < Ops.NumDefs)
366
PrintFatalError(Rec->getLoc(), "Output operands '" + LHSOpName + "' and '" +
367
RHSOpName + "' of '" + Rec->getName() +
368
"' cannot be tied!");
369
370
// The constraint has to go on the operand with higher index, i.e.
371
// the source one. Check there isn't another constraint there
372
// already.
373
if (!Ops[SrcOp.first].Constraints[SrcOp.second].isNone())
374
PrintFatalError(Rec->getLoc(), "Operand '" + SrcOpName + "' of '" +
375
Rec->getName() +
376
"' cannot have multiple constraints!");
377
378
unsigned DestFlatOpNo = Ops.getFlattenedOperandNumber(DestOp);
379
auto NewConstraint = CGIOperandList::ConstraintInfo::getTied(DestFlatOpNo);
380
381
// Check that the earlier operand is not the target of another tie
382
// before making it the target of this one.
383
for (const CGIOperandList::OperandInfo &Op : Ops) {
384
for (unsigned i = 0; i < Op.MINumOperands; i++)
385
if (Op.Constraints[i] == NewConstraint)
386
PrintFatalError(Rec->getLoc(),
387
"Operand '" + DestOpName + "' of '" + Rec->getName() +
388
"' cannot have multiple operands tied to it!");
389
}
390
391
Ops[SrcOp.first].Constraints[SrcOp.second] = NewConstraint;
392
}
393
394
static void ParseConstraints(StringRef CStr, CGIOperandList &Ops, Record *Rec) {
395
if (CStr.empty())
396
return;
397
398
StringRef delims(",");
399
StringRef::size_type bidx, eidx;
400
401
bidx = CStr.find_first_not_of(delims);
402
while (bidx != StringRef::npos) {
403
eidx = CStr.find_first_of(delims, bidx);
404
if (eidx == StringRef::npos)
405
eidx = CStr.size();
406
407
ParseConstraint(CStr.substr(bidx, eidx - bidx), Ops, Rec);
408
bidx = CStr.find_first_not_of(delims, eidx);
409
}
410
}
411
412
void CGIOperandList::ProcessDisableEncoding(StringRef DisableEncoding) {
413
while (true) {
414
StringRef OpName;
415
std::tie(OpName, DisableEncoding) = getToken(DisableEncoding, " ,\t");
416
if (OpName.empty())
417
break;
418
419
// Figure out which operand this is.
420
std::pair<unsigned, unsigned> Op = ParseOperandName(OpName, false);
421
422
// Mark the operand as not-to-be encoded.
423
OperandList[Op.first].DoNotEncode[Op.second] = true;
424
}
425
}
426
427
//===----------------------------------------------------------------------===//
428
// CodeGenInstruction Implementation
429
//===----------------------------------------------------------------------===//
430
431
CodeGenInstruction::CodeGenInstruction(Record *R)
432
: TheDef(R), Operands(R), InferredFrom(nullptr) {
433
Namespace = R->getValueAsString("Namespace");
434
AsmString = std::string(R->getValueAsString("AsmString"));
435
436
isPreISelOpcode = R->getValueAsBit("isPreISelOpcode");
437
isReturn = R->getValueAsBit("isReturn");
438
isEHScopeReturn = R->getValueAsBit("isEHScopeReturn");
439
isBranch = R->getValueAsBit("isBranch");
440
isIndirectBranch = R->getValueAsBit("isIndirectBranch");
441
isCompare = R->getValueAsBit("isCompare");
442
isMoveImm = R->getValueAsBit("isMoveImm");
443
isMoveReg = R->getValueAsBit("isMoveReg");
444
isBitcast = R->getValueAsBit("isBitcast");
445
isSelect = R->getValueAsBit("isSelect");
446
isBarrier = R->getValueAsBit("isBarrier");
447
isCall = R->getValueAsBit("isCall");
448
isAdd = R->getValueAsBit("isAdd");
449
isTrap = R->getValueAsBit("isTrap");
450
canFoldAsLoad = R->getValueAsBit("canFoldAsLoad");
451
isPredicable = !R->getValueAsBit("isUnpredicable") &&
452
(Operands.isPredicable || R->getValueAsBit("isPredicable"));
453
isConvertibleToThreeAddress = R->getValueAsBit("isConvertibleToThreeAddress");
454
isCommutable = R->getValueAsBit("isCommutable");
455
isTerminator = R->getValueAsBit("isTerminator");
456
isReMaterializable = R->getValueAsBit("isReMaterializable");
457
hasDelaySlot = R->getValueAsBit("hasDelaySlot");
458
usesCustomInserter = R->getValueAsBit("usesCustomInserter");
459
hasPostISelHook = R->getValueAsBit("hasPostISelHook");
460
hasCtrlDep = R->getValueAsBit("hasCtrlDep");
461
isNotDuplicable = R->getValueAsBit("isNotDuplicable");
462
isRegSequence = R->getValueAsBit("isRegSequence");
463
isExtractSubreg = R->getValueAsBit("isExtractSubreg");
464
isInsertSubreg = R->getValueAsBit("isInsertSubreg");
465
isConvergent = R->getValueAsBit("isConvergent");
466
hasNoSchedulingInfo = R->getValueAsBit("hasNoSchedulingInfo");
467
FastISelShouldIgnore = R->getValueAsBit("FastISelShouldIgnore");
468
variadicOpsAreDefs = R->getValueAsBit("variadicOpsAreDefs");
469
isAuthenticated = R->getValueAsBit("isAuthenticated");
470
471
bool Unset;
472
mayLoad = R->getValueAsBitOrUnset("mayLoad", Unset);
473
mayLoad_Unset = Unset;
474
mayStore = R->getValueAsBitOrUnset("mayStore", Unset);
475
mayStore_Unset = Unset;
476
mayRaiseFPException = R->getValueAsBit("mayRaiseFPException");
477
hasSideEffects = R->getValueAsBitOrUnset("hasSideEffects", Unset);
478
hasSideEffects_Unset = Unset;
479
480
isAsCheapAsAMove = R->getValueAsBit("isAsCheapAsAMove");
481
hasExtraSrcRegAllocReq = R->getValueAsBit("hasExtraSrcRegAllocReq");
482
hasExtraDefRegAllocReq = R->getValueAsBit("hasExtraDefRegAllocReq");
483
isCodeGenOnly = R->getValueAsBit("isCodeGenOnly");
484
isPseudo = R->getValueAsBit("isPseudo");
485
isMeta = R->getValueAsBit("isMeta");
486
ImplicitDefs = R->getValueAsListOfDefs("Defs");
487
ImplicitUses = R->getValueAsListOfDefs("Uses");
488
489
// This flag is only inferred from the pattern.
490
hasChain = false;
491
hasChain_Inferred = false;
492
493
// Parse Constraints.
494
ParseConstraints(R->getValueAsString("Constraints"), Operands, R);
495
496
// Parse the DisableEncoding field.
497
Operands.ProcessDisableEncoding(R->getValueAsString("DisableEncoding"));
498
499
// First check for a ComplexDeprecationPredicate.
500
if (R->getValue("ComplexDeprecationPredicate")) {
501
HasComplexDeprecationPredicate = true;
502
DeprecatedReason =
503
std::string(R->getValueAsString("ComplexDeprecationPredicate"));
504
} else if (RecordVal *Dep = R->getValue("DeprecatedFeatureMask")) {
505
// Check if we have a Subtarget feature mask.
506
HasComplexDeprecationPredicate = false;
507
DeprecatedReason = Dep->getValue()->getAsString();
508
} else {
509
// This instruction isn't deprecated.
510
HasComplexDeprecationPredicate = false;
511
DeprecatedReason = "";
512
}
513
}
514
515
/// HasOneImplicitDefWithKnownVT - If the instruction has at least one
516
/// implicit def and it has a known VT, return the VT, otherwise return
517
/// MVT::Other.
518
MVT::SimpleValueType CodeGenInstruction::HasOneImplicitDefWithKnownVT(
519
const CodeGenTarget &TargetInfo) const {
520
if (ImplicitDefs.empty())
521
return MVT::Other;
522
523
// Check to see if the first implicit def has a resolvable type.
524
Record *FirstImplicitDef = ImplicitDefs[0];
525
assert(FirstImplicitDef->isSubClassOf("Register"));
526
const std::vector<ValueTypeByHwMode> &RegVTs =
527
TargetInfo.getRegisterVTs(FirstImplicitDef);
528
if (RegVTs.size() == 1 && RegVTs[0].isSimple())
529
return RegVTs[0].getSimple().SimpleTy;
530
return MVT::Other;
531
}
532
533
/// FlattenAsmStringVariants - Flatten the specified AsmString to only
534
/// include text from the specified variant, returning the new string.
535
std::string CodeGenInstruction::FlattenAsmStringVariants(StringRef Cur,
536
unsigned Variant) {
537
std::string Res;
538
539
for (;;) {
540
// Find the start of the next variant string.
541
size_t VariantsStart = 0;
542
for (size_t e = Cur.size(); VariantsStart != e; ++VariantsStart)
543
if (Cur[VariantsStart] == '{' &&
544
(VariantsStart == 0 ||
545
(Cur[VariantsStart - 1] != '$' && Cur[VariantsStart - 1] != '\\')))
546
break;
547
548
// Add the prefix to the result.
549
Res += Cur.slice(0, VariantsStart);
550
if (VariantsStart == Cur.size())
551
break;
552
553
++VariantsStart; // Skip the '{'.
554
555
// Scan to the end of the variants string.
556
size_t VariantsEnd = VariantsStart;
557
unsigned NestedBraces = 1;
558
for (size_t e = Cur.size(); VariantsEnd != e; ++VariantsEnd) {
559
if (Cur[VariantsEnd] == '}' && Cur[VariantsEnd - 1] != '\\') {
560
if (--NestedBraces == 0)
561
break;
562
} else if (Cur[VariantsEnd] == '{')
563
++NestedBraces;
564
}
565
566
// Select the Nth variant (or empty).
567
StringRef Selection = Cur.slice(VariantsStart, VariantsEnd);
568
for (unsigned i = 0; i != Variant; ++i)
569
Selection = Selection.split('|').second;
570
Res += Selection.split('|').first;
571
572
assert(VariantsEnd != Cur.size() &&
573
"Unterminated variants in assembly string!");
574
Cur = Cur.substr(VariantsEnd + 1);
575
}
576
577
return Res;
578
}
579
580
bool CodeGenInstruction::isOperandImpl(StringRef OpListName, unsigned i,
581
StringRef PropertyName) const {
582
DagInit *ConstraintList = TheDef->getValueAsDag(OpListName);
583
if (!ConstraintList || i >= ConstraintList->getNumArgs())
584
return false;
585
586
DefInit *Constraint = dyn_cast<DefInit>(ConstraintList->getArg(i));
587
if (!Constraint)
588
return false;
589
590
return Constraint->getDef()->isSubClassOf("TypedOperand") &&
591
Constraint->getDef()->getValueAsBit(PropertyName);
592
}
593
594