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