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