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: "RegisterClass")) {
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 (SubArgDag->getNumArgs() != NumOps) {
147 PrintFatalError(ErrorLoc: R->getLoc(), Msg: "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>(Val: SubArgDag->getArg(Num: j)))
156 PrintFatalError(ErrorLoc: R->getLoc(),
157 Msg: "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(Num: j);
162 if (SubArgName.empty())
163 PrintFatalError(ErrorLoc: R->getLoc(), Msg: "In instruction '" + R->getName() +
164 "', operand #" + Twine(i) +
165 " has no name!");
166 if (!OperandNames.insert(x: SubArgName.str()).second)
167 PrintFatalError(ErrorLoc: R->getLoc(),
168 Msg: "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>(Val: MIOpInfo->getArg(Num: j))
174 ->getDef()
175 ->getValueAsOptionalString(FieldName: "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///
201unsigned CGIOperandList::getOperandNamed(StringRef Name) const {
202 std::optional<unsigned> OpIdx = findOperandNamed(Name);
203 if (OpIdx)
204 return *OpIdx;
205 PrintFatalError(ErrorLoc: TheDef->getLoc(), Msg: "'" + 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.
212std::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(First: OperandList))
215 if (Opnd.Name == Name)
216 return Index;
217 return std::nullopt;
218}
219
220std::optional<std::pair<unsigned, unsigned>>
221CGIOperandList::findSubOperandAlias(StringRef Name) const {
222 assert(!Name.empty() && "Cannot search for operand with no name!");
223 auto SubOpIter = SubOpAliases.find(Key: Name);
224 if (SubOpIter != SubOpAliases.end())
225 return SubOpIter->second;
226 return std::nullopt;
227}
228
229std::pair<unsigned, unsigned>
230CGIOperandList::ParseOperandName(StringRef Op, bool AllowWholeOp) {
231 if (!Op.starts_with(Prefix: "$"))
232 PrintFatalError(ErrorLoc: TheDef->getLoc(),
233 Msg: TheDef->getName() + ": Illegal operand name: '" + Op + "'");
234
235 StringRef OpName = Op.substr(Start: 1);
236 StringRef SubOpName;
237
238 // Check to see if this is $foo.bar.
239 StringRef::size_type DotIdx = OpName.find_first_of(C: '.');
240 if (DotIdx != StringRef::npos) {
241 SubOpName = OpName.substr(Start: DotIdx + 1);
242 if (SubOpName.empty())
243 PrintFatalError(ErrorLoc: TheDef->getLoc(),
244 Msg: TheDef->getName() +
245 ": illegal empty suboperand name in '" + Op + "'");
246 OpName = OpName.substr(Start: 0, N: DotIdx);
247 }
248
249 if (auto SubOp = findSubOperandAlias(Name: OpName)) {
250 // Found a name for a piece of an operand, just return it directly.
251 if (!SubOpName.empty()) {
252 PrintFatalError(
253 ErrorLoc: TheDef->getLoc(),
254 Msg: TheDef->getName() +
255 ": Cannot use dotted suboperand name within suboperand '" +
256 OpName + "'");
257 }
258 return *SubOp;
259 }
260
261 unsigned OpIdx = getOperandNamed(Name: 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(ErrorLoc: TheDef->getLoc(),
268 Msg: 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(ErrorLoc: TheDef->getLoc(), Msg: 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(Num: i) == SubOpName)
287 return {OpIdx, i};
288
289 // Otherwise, didn't find it!
290 PrintFatalError(ErrorLoc: TheDef->getLoc(), Msg: TheDef->getName() +
291 ": unknown suboperand name in '" + Op +
292 "'");
293 return {0U, 0U};
294}
295
296static void ParseConstraint(StringRef CStr, CGIOperandList &Ops,
297 const Record *Rec) {
298 // EARLY_CLOBBER: @early $reg
299 StringRef::size_type wpos = CStr.find_first_of(Chars: " \t");
300 StringRef::size_type start = CStr.find_first_not_of(Chars: " \t");
301 StringRef Tok = CStr.substr(Start: start, N: wpos - start);
302 if (Tok == "@earlyclobber") {
303 StringRef Name = CStr.substr(Start: wpos + 1);
304 wpos = Name.find_first_not_of(Chars: " \t");
305 if (wpos == StringRef::npos)
306 PrintFatalError(ErrorLoc: Rec->getLoc(),
307 Msg: "Illegal format for @earlyclobber constraint in '" +
308 Rec->getName() + "': '" + CStr + "'");
309 Name = Name.substr(Start: wpos);
310 std::pair<unsigned, unsigned> Op = Ops.ParseOperandName(Op: Name, AllowWholeOp: false);
311
312 // Build the string for the operand
313 if (!Ops[Op.first].Constraints[Op.second].isNone())
314 PrintFatalError(ErrorLoc: Rec->getLoc(), Msg: "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(C: '=');
324 if (pos == StringRef::npos || pos == 0 ||
325 CStr.find_first_of(Chars: " \t", From: pos) != (pos + 1) ||
326 CStr.find_last_of(Chars: " \t", From: pos) != (pos - 1))
327 PrintFatalError(ErrorLoc: Rec->getLoc(), Msg: "Unrecognized constraint '" + CStr +
328 "' in '" + Rec->getName() + "'");
329 start = CStr.find_first_not_of(Chars: " \t");
330
331 // TIED_TO: $src1 = $dst
332 wpos = CStr.find_first_of(Chars: " \t", From: start);
333 if (wpos == StringRef::npos || wpos > pos)
334 PrintFatalError(ErrorLoc: Rec->getLoc(),
335 Msg: "Illegal format for tied-to constraint in '" +
336 Rec->getName() + "': '" + CStr + "'");
337 StringRef LHSOpName = CStr.substr(Start: start, N: wpos - start);
338 std::pair<unsigned, unsigned> LHSOp = Ops.ParseOperandName(Op: LHSOpName, AllowWholeOp: false);
339
340 wpos = CStr.find_first_not_of(Chars: " \t", From: pos + 1);
341 if (wpos == StringRef::npos)
342 PrintFatalError(ErrorLoc: Rec->getLoc(),
343 Msg: "Illegal format for tied-to constraint: '" + CStr + "'");
344
345 StringRef RHSOpName = CStr.substr(Start: wpos);
346 std::pair<unsigned, unsigned> RHSOp = Ops.ParseOperandName(Op: RHSOpName, AllowWholeOp: 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(ErrorLoc: Rec->getLoc(), Msg: "Input operands '" + LHSOpName + "' and '" +
359 RHSOpName + "' of '" + Rec->getName() +
360 "' cannot be tied!");
361 if (SrcOp.first < Ops.NumDefs)
362 PrintFatalError(ErrorLoc: Rec->getLoc(), Msg: "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(ErrorLoc: Rec->getLoc(), Msg: "Operand '" + SrcOpName + "' of '" +
371 Rec->getName() +
372 "' cannot have multiple constraints!");
373
374 unsigned DestFlatOpNo = Ops.getFlattenedOperandNumber(Op: DestOp);
375 auto NewConstraint = CGIOperandList::ConstraintInfo::getTied(Op: 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(ErrorLoc: Rec->getLoc(),
383 Msg: "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
390static 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(Chars: delims);
399 while (bidx != StringRef::npos) {
400 eidx = CStr.find_first_of(Chars: delims, From: bidx);
401 if (eidx == StringRef::npos)
402 eidx = CStr.size();
403
404 ParseConstraint(CStr: CStr.substr(Start: bidx, N: eidx - bidx), Ops, Rec);
405 bidx = CStr.find_first_not_of(Chars: delims, From: eidx);
406 }
407}
408
409void CGIOperandList::ProcessDisableEncoding(StringRef DisableEncoding) {
410 while (true) {
411 StringRef OpName;
412 std::tie(args&: OpName, args&: DisableEncoding) = getToken(Source: DisableEncoding, Delimiters: " ,\t");
413 if (OpName.empty())
414 break;
415
416 // Figure out which operand this is.
417 std::pair<unsigned, unsigned> Op = ParseOperandName(Op: OpName, AllowWholeOp: 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
428CodeGenInstruction::CodeGenInstruction(const Record *R)
429 : TheDef(R), Operands(R), InferredFrom(nullptr) {
430 Namespace = R->getValueAsString(FieldName: "Namespace");
431 AsmString = R->getValueAsString(FieldName: "AsmString");
432
433 isPreISelOpcode = R->getValueAsBit(FieldName: "isPreISelOpcode");
434 isReturn = R->getValueAsBit(FieldName: "isReturn");
435 isEHScopeReturn = R->getValueAsBit(FieldName: "isEHScopeReturn");
436 isBranch = R->getValueAsBit(FieldName: "isBranch");
437 isIndirectBranch = R->getValueAsBit(FieldName: "isIndirectBranch");
438 isCompare = R->getValueAsBit(FieldName: "isCompare");
439 isMoveImm = R->getValueAsBit(FieldName: "isMoveImm");
440 isMoveReg = R->getValueAsBit(FieldName: "isMoveReg");
441 isBitcast = R->getValueAsBit(FieldName: "isBitcast");
442 isSelect = R->getValueAsBit(FieldName: "isSelect");
443 isBarrier = R->getValueAsBit(FieldName: "isBarrier");
444 isCall = R->getValueAsBit(FieldName: "isCall");
445 isAdd = R->getValueAsBit(FieldName: "isAdd");
446 isTrap = R->getValueAsBit(FieldName: "isTrap");
447 canFoldAsLoad = R->getValueAsBit(FieldName: "canFoldAsLoad");
448 isPredicable = !R->getValueAsBit(FieldName: "isUnpredicable") &&
449 (Operands.isPredicable || R->getValueAsBit(FieldName: "isPredicable"));
450 isConvertibleToThreeAddress = R->getValueAsBit(FieldName: "isConvertibleToThreeAddress");
451 isCommutable = R->getValueAsBit(FieldName: "isCommutable");
452 isTerminator = R->getValueAsBit(FieldName: "isTerminator");
453 isReMaterializable = R->getValueAsBit(FieldName: "isReMaterializable");
454 hasDelaySlot = R->getValueAsBit(FieldName: "hasDelaySlot");
455 usesCustomInserter = R->getValueAsBit(FieldName: "usesCustomInserter");
456 hasPostISelHook = R->getValueAsBit(FieldName: "hasPostISelHook");
457 hasCtrlDep = R->getValueAsBit(FieldName: "hasCtrlDep");
458 isNotDuplicable = R->getValueAsBit(FieldName: "isNotDuplicable");
459 isRegSequence = R->getValueAsBit(FieldName: "isRegSequence");
460 isExtractSubreg = R->getValueAsBit(FieldName: "isExtractSubreg");
461 isInsertSubreg = R->getValueAsBit(FieldName: "isInsertSubreg");
462 isConvergent = R->getValueAsBit(FieldName: "isConvergent");
463 hasNoSchedulingInfo = R->getValueAsBit(FieldName: "hasNoSchedulingInfo");
464 FastISelShouldIgnore = R->getValueAsBit(FieldName: "FastISelShouldIgnore");
465 variadicOpsAreDefs = R->getValueAsBit(FieldName: "variadicOpsAreDefs");
466 isAuthenticated = R->getValueAsBit(FieldName: "isAuthenticated");
467
468 bool Unset;
469 mayLoad = R->getValueAsBitOrUnset(FieldName: "mayLoad", Unset);
470 mayLoad_Unset = Unset;
471 mayStore = R->getValueAsBitOrUnset(FieldName: "mayStore", Unset);
472 mayStore_Unset = Unset;
473 mayRaiseFPException = R->getValueAsBit(FieldName: "mayRaiseFPException");
474 hasSideEffects = R->getValueAsBitOrUnset(FieldName: "hasSideEffects", Unset);
475 hasSideEffects_Unset = Unset;
476
477 isAsCheapAsAMove = R->getValueAsBit(FieldName: "isAsCheapAsAMove");
478 hasExtraSrcRegAllocReq = R->getValueAsBit(FieldName: "hasExtraSrcRegAllocReq");
479 hasExtraDefRegAllocReq = R->getValueAsBit(FieldName: "hasExtraDefRegAllocReq");
480 isCodeGenOnly = R->getValueAsBit(FieldName: "isCodeGenOnly");
481 isPseudo = R->getValueAsBit(FieldName: "isPseudo");
482 isMeta = R->getValueAsBit(FieldName: "isMeta");
483 ImplicitDefs = R->getValueAsListOfDefs(FieldName: "Defs");
484 ImplicitUses = R->getValueAsListOfDefs(FieldName: "Uses");
485
486 // This flag is only inferred from the pattern.
487 hasChain = false;
488 hasChain_Inferred = false;
489
490 // Parse Constraints.
491 ParseConstraints(CStr: R->getValueAsString(FieldName: "Constraints"), Ops&: Operands, Rec: R);
492
493 // Parse the DisableEncoding field.
494 Operands.ProcessDisableEncoding(DisableEncoding: R->getValueAsString(FieldName: "DisableEncoding"));
495
496 // First check for a ComplexDeprecationPredicate.
497 if (R->getValue(Name: "ComplexDeprecationPredicate")) {
498 HasComplexDeprecationPredicate = true;
499 DeprecatedReason = R->getValueAsString(FieldName: "ComplexDeprecationPredicate").str();
500 } else if (const RecordVal *Dep = R->getValue(Name: "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.
514MVT::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(R: 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.
531std::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(Start: 0, End: 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(Start: VariantsStart, N: VariantsEnd - VariantsStart);
565 for (unsigned i = 0; i != Variant; ++i)
566 Selection = Selection.split(Separator: '|').second;
567 Res += Selection.split(Separator: '|').first;
568
569 assert(VariantsEnd != Cur.size() &&
570 "Unterminated variants in assembly string!");
571 Cur = Cur.substr(Start: VariantsEnd + 1);
572 }
573
574 return Res;
575}
576
577bool CodeGenInstruction::isOperandImpl(StringRef OpListName, unsigned i,
578 StringRef PropertyName) const {
579 const DagInit *ConstraintList = TheDef->getValueAsDag(FieldName: OpListName);
580 if (!ConstraintList || i >= ConstraintList->getNumArgs())
581 return false;
582
583 const DefInit *Constraint = dyn_cast<DefInit>(Val: ConstraintList->getArg(Num: i));
584 if (!Constraint)
585 return false;
586
587 return Constraint->getDef()->isSubClassOf(Name: "TypedOperand") &&
588 Constraint->getDef()->getValueAsBit(FieldName: PropertyName);
589}
590