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 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 /// 201 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. 212 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>> 221 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> 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 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 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 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 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. 514 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. 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 577 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