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
CGIOperandList(const Record * R)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 ///
getOperandNamed(StringRef Name) const201 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.
findOperandNamed(StringRef Name) const212 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>>
findSubOperandAlias(StringRef Name) const221 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>
ParseOperandName(StringRef Op,bool AllowWholeOp)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
ParseConstraint(StringRef CStr,CGIOperandList & Ops,const Record * Rec)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
ParseConstraints(StringRef CStr,CGIOperandList & Ops,const Record * Rec)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
ProcessDisableEncoding(StringRef DisableEncoding)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
CodeGenInstruction(const Record * R)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.
HasOneImplicitDefWithKnownVT(const CodeGenTarget & TargetInfo) const514 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.
FlattenAsmStringVariants(StringRef Cur,unsigned Variant)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
isOperandImpl(StringRef OpListName,unsigned i,StringRef PropertyName) const577 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