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