1 //===- CodeGenInstruction.cpp - CodeGen Instruction Class Wrapper ---------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements the CodeGenInstruction class.
11 //===----------------------------------------------------------------------===//
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"
21 //===----------------------------------------------------------------------===//
22 // CGIOperandList Implementation
23 //===----------------------------------------------------------------------===//
25 CGIOperandList::CGIOperandList(Record
*R
) : TheDef(R
) {
27 hasOptionalDef
= false;
30 DagInit
*OutDI
= R
->getValueAsDag("OutOperandList");
32 if (DefInit
*Init
= dyn_cast
<DefInit
>(OutDI
->getOperator())) {
33 if (Init
->getDef()->getName() != "outs")
34 PrintFatalError(R
->getLoc(),
36 ": invalid def name for output list: use 'outs'");
38 PrintFatalError(R
->getLoc(),
39 R
->getName() + ": invalid output list: use 'outs'");
41 NumDefs
= OutDI
->getNumArgs();
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(),
48 ": invalid def name for input list: use 'ins'");
50 PrintFatalError(R
->getLoc(),
51 R
->getName() + ": invalid input list: use 'ins'");
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
){
62 ArgInit
= OutDI
->getArg(i
);
63 ArgName
= OutDI
->getArgNameStr(i
);
65 ArgInit
= InDI
->getArg(i
-NumDefs
);
66 ArgName
= InDI
->getArgNameStr(i
-NumDefs
);
69 DagInit
*SubArgDag
= dyn_cast
<DagInit
>(ArgInit
);
71 ArgInit
= SubArgDag
->getOperator();
73 DefInit
*Arg
= dyn_cast
<DefInit
>(ArgInit
);
75 PrintFatalError(R
->getLoc(), "Illegal operand for the '" + R
->getName() +
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";
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");
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");
105 // If we have MIOpInfo, then we have #operands equal to number of entries
107 if (unsigned NumArgs
= MIOpInfo
->getNumArgs())
110 if (Rec
->isSubClassOf("PredicateOp"))
112 else if (Rec
->isSubClassOf("OptionalDefOperand"))
113 hasOptionalDef
= true;
114 } else if (Rec
->getName() == "variable_ops") {
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() +
128 // Check that the operand has a name and that it's unique.
130 PrintFatalError(R
->getLoc(), "In instruction '" + R
->getName() +
131 "', operand #" + Twine(i
) +
133 if (!OperandNames
.insert(std::string(ArgName
)).second
)
134 PrintFatalError(R
->getLoc(),
135 "In instruction '" + R
->getName() + "', operand #" +
137 " has the same name as a previous operand!");
139 OperandInfo
&OpInfo
= OperandList
.emplace_back(
140 Rec
, std::string(ArgName
), std::string(PrintMethod
),
141 OperandNamespace
+ "::" + OperandType
, MIOperandNo
, NumOps
, MIOpInfo
);
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
) + ".");
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).");
159 StringRef SubArgName
= SubArgDag
->getArgNameStr(j
);
160 if (SubArgName
.empty())
161 PrintFatalError(R
->getLoc(), "In instruction '" + R
->getName() +
162 "', operand #" + Twine(i
) +
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!");
170 if (auto MaybeEncoderMethod
=
171 cast
<DefInit
>(MIOpInfo
->getArg(j
))
173 ->getValueAsOptionalString("EncoderMethod")) {
174 OpInfo
.EncoderMethodNames
[j
] = *MaybeEncoderMethod
;
177 OpInfo
.SubOpNames
[j
] = SubArgName
;
178 SubOpAliases
[SubArgName
] = std::make_pair(i
, j
);
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;
188 MIOperandNo
+= NumOps
;
196 /// getOperandNamed - Return the index of the operand with the specified
197 /// non-empty name. If the instruction does not have an operand with the
198 /// specified name, abort.
200 unsigned CGIOperandList::getOperandNamed(StringRef Name
) const {
202 if (hasOperandNamed(Name
, OpIdx
))
204 PrintFatalError(TheDef
->getLoc(), "'" + TheDef
->getName() +
205 "' does not have an operand named '$" +
209 /// hasOperandNamed - Query whether the instruction has an operand of the
210 /// given name. If so, return true and set OpIdx to the index of the
211 /// operand. Otherwise, return false.
212 bool CGIOperandList::hasOperandNamed(StringRef Name
, unsigned &OpIdx
) const {
213 assert(!Name
.empty() && "Cannot search for operand with no name!");
214 for (unsigned i
= 0, e
= OperandList
.size(); i
!= e
; ++i
)
215 if (OperandList
[i
].Name
== Name
) {
222 bool CGIOperandList::hasSubOperandAlias(
223 StringRef Name
, std::pair
<unsigned, unsigned> &SubOp
) const {
224 assert(!Name
.empty() && "Cannot search for operand with no name!");
225 auto SubOpIter
= SubOpAliases
.find(Name
);
226 if (SubOpIter
!= SubOpAliases
.end()) {
227 SubOp
= SubOpIter
->second
;
233 std::pair
<unsigned,unsigned>
234 CGIOperandList::ParseOperandName(StringRef Op
, bool AllowWholeOp
) {
235 if (Op
.empty() || Op
[0] != '$')
236 PrintFatalError(TheDef
->getLoc(),
237 TheDef
->getName() + ": Illegal operand name: '" + Op
+ "'");
239 StringRef OpName
= Op
.substr(1);
242 // Check to see if this is $foo.bar.
243 StringRef::size_type DotIdx
= OpName
.find_first_of('.');
244 if (DotIdx
!= StringRef::npos
) {
245 SubOpName
= OpName
.substr(DotIdx
+1);
246 if (SubOpName
.empty())
247 PrintFatalError(TheDef
->getLoc(),
249 ": illegal empty suboperand name in '" + Op
+ "'");
250 OpName
= OpName
.substr(0, DotIdx
);
255 if (std::pair
<unsigned, unsigned> SubOp
; hasSubOperandAlias(OpName
, SubOp
)) {
256 // Found a name for a piece of an operand, just return it directly.
257 if (!SubOpName
.empty()) {
261 ": Cannot use dotted suboperand name within suboperand '" +
267 OpIdx
= getOperandNamed(OpName
);
269 if (SubOpName
.empty()) { // If no suboperand name was specified:
270 // If one was needed, throw.
271 if (OperandList
[OpIdx
].MINumOperands
> 1 && !AllowWholeOp
&&
273 PrintFatalError(TheDef
->getLoc(),
275 ": Illegal to refer to"
276 " whole operand part of complex operand '" +
279 // Otherwise, return the operand.
280 return std::make_pair(OpIdx
, 0U);
283 // Find the suboperand number involved.
284 DagInit
*MIOpInfo
= OperandList
[OpIdx
].MIOperandInfo
;
286 PrintFatalError(TheDef
->getLoc(), TheDef
->getName() +
287 ": unknown suboperand name in '" +
290 // Find the operand with the right name.
291 for (unsigned i
= 0, e
= MIOpInfo
->getNumArgs(); i
!= e
; ++i
)
292 if (MIOpInfo
->getArgNameStr(i
) == SubOpName
)
293 return std::make_pair(OpIdx
, i
);
295 // Otherwise, didn't find it!
296 PrintFatalError(TheDef
->getLoc(), TheDef
->getName() +
297 ": unknown suboperand name in '" + Op
+
299 return std::make_pair(0U, 0U);
302 static void ParseConstraint(StringRef CStr
, CGIOperandList
&Ops
,
304 // EARLY_CLOBBER: @early $reg
305 StringRef::size_type wpos
= CStr
.find_first_of(" \t");
306 StringRef::size_type start
= CStr
.find_first_not_of(" \t");
307 StringRef Tok
= CStr
.substr(start
, wpos
- start
);
308 if (Tok
== "@earlyclobber") {
309 StringRef Name
= CStr
.substr(wpos
+1);
310 wpos
= Name
.find_first_not_of(" \t");
311 if (wpos
== StringRef::npos
)
313 Rec
->getLoc(), "Illegal format for @earlyclobber constraint in '" +
314 Rec
->getName() + "': '" + CStr
+ "'");
315 Name
= Name
.substr(wpos
);
316 std::pair
<unsigned,unsigned> Op
= Ops
.ParseOperandName(Name
, false);
318 // Build the string for the operand
319 if (!Ops
[Op
.first
].Constraints
[Op
.second
].isNone())
321 Rec
->getLoc(), "Operand '" + Name
+ "' of '" + Rec
->getName() +
322 "' cannot have multiple constraints!");
323 Ops
[Op
.first
].Constraints
[Op
.second
] =
324 CGIOperandList::ConstraintInfo::getEarlyClobber();
328 // Only other constraint is "TIED_TO" for now.
329 StringRef::size_type pos
= CStr
.find_first_of('=');
330 if (pos
== StringRef::npos
)
332 Rec
->getLoc(), "Unrecognized constraint '" + CStr
+
333 "' in '" + Rec
->getName() + "'");
334 start
= CStr
.find_first_not_of(" \t");
336 // TIED_TO: $src1 = $dst
337 wpos
= CStr
.find_first_of(" \t", start
);
338 if (wpos
== StringRef::npos
|| wpos
> pos
)
340 Rec
->getLoc(), "Illegal format for tied-to constraint in '" +
341 Rec
->getName() + "': '" + CStr
+ "'");
342 StringRef LHSOpName
= CStr
.substr(start
, wpos
- start
);
343 std::pair
<unsigned,unsigned> LHSOp
= Ops
.ParseOperandName(LHSOpName
, false);
345 wpos
= CStr
.find_first_not_of(" \t", pos
+ 1);
346 if (wpos
== StringRef::npos
)
348 Rec
->getLoc(), "Illegal format for tied-to constraint: '" + CStr
+ "'");
350 StringRef RHSOpName
= CStr
.substr(wpos
);
351 std::pair
<unsigned,unsigned> RHSOp
= Ops
.ParseOperandName(RHSOpName
, false);
353 // Sort the operands into order, which should put the output one
354 // first. But keep the original order, for use in diagnostics.
355 bool FirstIsDest
= (LHSOp
< RHSOp
);
356 std::pair
<unsigned,unsigned> DestOp
= (FirstIsDest
? LHSOp
: RHSOp
);
357 StringRef DestOpName
= (FirstIsDest
? LHSOpName
: RHSOpName
);
358 std::pair
<unsigned,unsigned> SrcOp
= (FirstIsDest
? RHSOp
: LHSOp
);
359 StringRef SrcOpName
= (FirstIsDest
? RHSOpName
: LHSOpName
);
361 // Ensure one operand is a def and the other is a use.
362 if (DestOp
.first
>= Ops
.NumDefs
)
364 Rec
->getLoc(), "Input operands '" + LHSOpName
+ "' and '" + RHSOpName
+
365 "' of '" + Rec
->getName() + "' cannot be tied!");
366 if (SrcOp
.first
< Ops
.NumDefs
)
368 Rec
->getLoc(), "Output operands '" + LHSOpName
+ "' and '" + RHSOpName
+
369 "' of '" + Rec
->getName() + "' cannot be tied!");
371 // The constraint has to go on the operand with higher index, i.e.
372 // the source one. Check there isn't another constraint there
374 if (!Ops
[SrcOp
.first
].Constraints
[SrcOp
.second
].isNone())
376 Rec
->getLoc(), "Operand '" + SrcOpName
+ "' of '" + Rec
->getName() +
377 "' cannot have multiple constraints!");
379 unsigned DestFlatOpNo
= Ops
.getFlattenedOperandNumber(DestOp
);
380 auto NewConstraint
= CGIOperandList::ConstraintInfo::getTied(DestFlatOpNo
);
382 // Check that the earlier operand is not the target of another tie
383 // before making it the target of this one.
384 for (const CGIOperandList::OperandInfo
&Op
: Ops
) {
385 for (unsigned i
= 0; i
< Op
.MINumOperands
; i
++)
386 if (Op
.Constraints
[i
] == NewConstraint
)
388 Rec
->getLoc(), "Operand '" + DestOpName
+ "' of '" + Rec
->getName() +
389 "' cannot have multiple operands tied to it!");
392 Ops
[SrcOp
.first
].Constraints
[SrcOp
.second
] = NewConstraint
;
395 static void ParseConstraints(StringRef CStr
, CGIOperandList
&Ops
, Record
*Rec
) {
396 if (CStr
.empty()) return;
398 StringRef
delims(",");
399 StringRef::size_type bidx
, eidx
;
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
)
407 ParseConstraint(CStr
.substr(bidx
, eidx
- bidx
), Ops
, Rec
);
408 bidx
= CStr
.find_first_not_of(delims
, eidx
);
412 void CGIOperandList::ProcessDisableEncoding(StringRef DisableEncoding
) {
415 std::tie(OpName
, DisableEncoding
) = getToken(DisableEncoding
, " ,\t");
416 if (OpName
.empty()) break;
418 // Figure out which operand this is.
419 std::pair
<unsigned,unsigned> Op
= ParseOperandName(OpName
, false);
421 // Mark the operand as not-to-be encoded.
422 OperandList
[Op
.first
].DoNotEncode
[Op
.second
] = true;
427 //===----------------------------------------------------------------------===//
428 // CodeGenInstruction Implementation
429 //===----------------------------------------------------------------------===//
431 CodeGenInstruction::CodeGenInstruction(Record
*R
)
432 : TheDef(R
), Operands(R
), InferredFrom(nullptr) {
433 Namespace
= R
->getValueAsString("Namespace");
434 AsmString
= std::string(R
->getValueAsString("AsmString"));
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");
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
;
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");
489 // This flag is only inferred from the pattern.
491 hasChain_Inferred
= false;
493 // Parse Constraints.
494 ParseConstraints(R
->getValueAsString("Constraints"), Operands
, R
);
496 // Parse the DisableEncoding field.
497 Operands
.ProcessDisableEncoding(
498 R
->getValueAsString("DisableEncoding"));
500 // First check for a ComplexDeprecationPredicate.
501 if (R
->getValue("ComplexDeprecationPredicate")) {
502 HasComplexDeprecationPredicate
= true;
504 std::string(R
->getValueAsString("ComplexDeprecationPredicate"));
505 } else if (RecordVal
*Dep
= R
->getValue("DeprecatedFeatureMask")) {
506 // Check if we have a Subtarget feature mask.
507 HasComplexDeprecationPredicate
= false;
508 DeprecatedReason
= Dep
->getValue()->getAsString();
510 // This instruction isn't deprecated.
511 HasComplexDeprecationPredicate
= false;
512 DeprecatedReason
= "";
516 /// HasOneImplicitDefWithKnownVT - If the instruction has at least one
517 /// implicit def and it has a known VT, return the VT, otherwise return
519 MVT::SimpleValueType
CodeGenInstruction::
520 HasOneImplicitDefWithKnownVT(const CodeGenTarget
&TargetInfo
) const {
521 if (ImplicitDefs
.empty()) return MVT::Other
;
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
;
534 /// FlattenAsmStringVariants - Flatten the specified AsmString to only
535 /// include text from the specified variant, returning the new string.
536 std::string
CodeGenInstruction::
537 FlattenAsmStringVariants(StringRef Cur
, unsigned Variant
) {
541 // Find the start of the next variant string.
542 size_t VariantsStart
= 0;
543 for (size_t e
= Cur
.size(); VariantsStart
!= e
; ++VariantsStart
)
544 if (Cur
[VariantsStart
] == '{' &&
545 (VariantsStart
== 0 || (Cur
[VariantsStart
-1] != '$' &&
546 Cur
[VariantsStart
-1] != '\\')))
549 // Add the prefix to the result.
550 Res
+= Cur
.slice(0, VariantsStart
);
551 if (VariantsStart
== Cur
.size())
554 ++VariantsStart
; // Skip the '{'.
556 // Scan to the end of the variants string.
557 size_t VariantsEnd
= VariantsStart
;
558 unsigned NestedBraces
= 1;
559 for (size_t e
= Cur
.size(); VariantsEnd
!= e
; ++VariantsEnd
) {
560 if (Cur
[VariantsEnd
] == '}' && Cur
[VariantsEnd
-1] != '\\') {
561 if (--NestedBraces
== 0)
563 } else if (Cur
[VariantsEnd
] == '{')
567 // Select the Nth variant (or empty).
568 StringRef Selection
= Cur
.slice(VariantsStart
, VariantsEnd
);
569 for (unsigned i
= 0; i
!= Variant
; ++i
)
570 Selection
= Selection
.split('|').second
;
571 Res
+= Selection
.split('|').first
;
573 assert(VariantsEnd
!= Cur
.size() &&
574 "Unterminated variants in assembly string!");
575 Cur
= Cur
.substr(VariantsEnd
+ 1);
581 bool CodeGenInstruction::isOperandImpl(StringRef OpListName
, unsigned i
,
582 StringRef PropertyName
) const {
583 DagInit
*ConstraintList
= TheDef
->getValueAsDag(OpListName
);
584 if (!ConstraintList
|| i
>= ConstraintList
->getNumArgs())
587 DefInit
*Constraint
= dyn_cast
<DefInit
>(ConstraintList
->getArg(i
));
591 return Constraint
->getDef()->isSubClassOf("TypedOperand") &&
592 Constraint
->getDef()->getValueAsBit(PropertyName
);