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