1fa3d789dSPierre van Houtryve //===- CodeGenInstruction.cpp - CodeGen Instruction Class Wrapper ---------===// 2fa3d789dSPierre van Houtryve // 3fa3d789dSPierre van Houtryve // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4fa3d789dSPierre van Houtryve // See https://llvm.org/LICENSE.txt for license information. 5fa3d789dSPierre van Houtryve // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6fa3d789dSPierre van Houtryve // 7fa3d789dSPierre van Houtryve //===----------------------------------------------------------------------===// 8fa3d789dSPierre van Houtryve // 9fa3d789dSPierre van Houtryve // This file implements the CodeGenInstruction class. 10fa3d789dSPierre van Houtryve // 11fa3d789dSPierre van Houtryve //===----------------------------------------------------------------------===// 12fa3d789dSPierre van Houtryve 13fa3d789dSPierre van Houtryve #include "CodeGenInstruction.h" 14fa3d789dSPierre van Houtryve #include "CodeGenTarget.h" 15fa3d789dSPierre van Houtryve #include "llvm/ADT/StringExtras.h" 16fa3d789dSPierre van Houtryve #include "llvm/TableGen/Error.h" 17fa3d789dSPierre van Houtryve #include "llvm/TableGen/Record.h" 18fa3d789dSPierre van Houtryve #include <set> 19fa3d789dSPierre van Houtryve using namespace llvm; 20fa3d789dSPierre van Houtryve 21fa3d789dSPierre van Houtryve //===----------------------------------------------------------------------===// 22fa3d789dSPierre van Houtryve // CGIOperandList Implementation 23fa3d789dSPierre van Houtryve //===----------------------------------------------------------------------===// 24fa3d789dSPierre van Houtryve 25bdf02249SRahul Joshi CGIOperandList::CGIOperandList(const Record *R) : TheDef(R) { 26fa3d789dSPierre van Houtryve isPredicable = false; 27fa3d789dSPierre van Houtryve hasOptionalDef = false; 28fa3d789dSPierre van Houtryve isVariadic = false; 29fa3d789dSPierre van Houtryve 3062e2c7fbSRahul Joshi const DagInit *OutDI = R->getValueAsDag("OutOperandList"); 31fa3d789dSPierre van Houtryve 3262e2c7fbSRahul Joshi if (const DefInit *Init = dyn_cast<DefInit>(OutDI->getOperator())) { 33fa3d789dSPierre van Houtryve if (Init->getDef()->getName() != "outs") 34fa3d789dSPierre van Houtryve PrintFatalError(R->getLoc(), 35fa3d789dSPierre van Houtryve R->getName() + 36fa3d789dSPierre van Houtryve ": invalid def name for output list: use 'outs'"); 37fa3d789dSPierre van Houtryve } else 38fa3d789dSPierre van Houtryve PrintFatalError(R->getLoc(), 39fa3d789dSPierre van Houtryve R->getName() + ": invalid output list: use 'outs'"); 40fa3d789dSPierre van Houtryve 41fa3d789dSPierre van Houtryve NumDefs = OutDI->getNumArgs(); 42fa3d789dSPierre van Houtryve 4362e2c7fbSRahul Joshi const DagInit *InDI = R->getValueAsDag("InOperandList"); 4462e2c7fbSRahul Joshi if (const DefInit *Init = dyn_cast<DefInit>(InDI->getOperator())) { 45fa3d789dSPierre van Houtryve if (Init->getDef()->getName() != "ins") 46fa3d789dSPierre van Houtryve PrintFatalError(R->getLoc(), 47fa3d789dSPierre van Houtryve R->getName() + 48fa3d789dSPierre van Houtryve ": invalid def name for input list: use 'ins'"); 49fa3d789dSPierre van Houtryve } else 50fa3d789dSPierre van Houtryve PrintFatalError(R->getLoc(), 51fa3d789dSPierre van Houtryve R->getName() + ": invalid input list: use 'ins'"); 52fa3d789dSPierre van Houtryve 53fa3d789dSPierre van Houtryve unsigned MIOperandNo = 0; 54fa3d789dSPierre van Houtryve std::set<std::string> OperandNames; 55fa3d789dSPierre van Houtryve unsigned e = InDI->getNumArgs() + OutDI->getNumArgs(); 56fa3d789dSPierre van Houtryve OperandList.reserve(e); 57fa3d789dSPierre van Houtryve bool VariadicOuts = false; 58fa3d789dSPierre van Houtryve for (unsigned i = 0; i != e; ++i) { 5962e2c7fbSRahul Joshi const Init *ArgInit; 60fa3d789dSPierre van Houtryve StringRef ArgName; 61fa3d789dSPierre van Houtryve if (i < NumDefs) { 62fa3d789dSPierre van Houtryve ArgInit = OutDI->getArg(i); 63fa3d789dSPierre van Houtryve ArgName = OutDI->getArgNameStr(i); 64fa3d789dSPierre van Houtryve } else { 65fa3d789dSPierre van Houtryve ArgInit = InDI->getArg(i - NumDefs); 66fa3d789dSPierre van Houtryve ArgName = InDI->getArgNameStr(i - NumDefs); 67fa3d789dSPierre van Houtryve } 68fa3d789dSPierre van Houtryve 6962e2c7fbSRahul Joshi const DagInit *SubArgDag = dyn_cast<DagInit>(ArgInit); 70fa3d789dSPierre van Houtryve if (SubArgDag) 71fa3d789dSPierre van Houtryve ArgInit = SubArgDag->getOperator(); 72fa3d789dSPierre van Houtryve 7362e2c7fbSRahul Joshi const DefInit *Arg = dyn_cast<DefInit>(ArgInit); 74fa3d789dSPierre van Houtryve if (!Arg) 75fa3d789dSPierre van Houtryve PrintFatalError(R->getLoc(), "Illegal operand for the '" + R->getName() + 76fa3d789dSPierre van Houtryve "' instruction!"); 77fa3d789dSPierre van Houtryve 78bdf02249SRahul Joshi const Record *Rec = Arg->getDef(); 79fa3d789dSPierre van Houtryve std::string PrintMethod = "printOperand"; 80fa3d789dSPierre van Houtryve std::string EncoderMethod; 81fa3d789dSPierre van Houtryve std::string OperandType = "OPERAND_UNKNOWN"; 82fa3d789dSPierre van Houtryve std::string OperandNamespace = "MCOI"; 83fa3d789dSPierre van Houtryve unsigned NumOps = 1; 8462e2c7fbSRahul Joshi const DagInit *MIOpInfo = nullptr; 85fa3d789dSPierre van Houtryve if (Rec->isSubClassOf("RegisterOperand")) { 86fa3d789dSPierre van Houtryve PrintMethod = std::string(Rec->getValueAsString("PrintMethod")); 87fa3d789dSPierre van Houtryve OperandType = std::string(Rec->getValueAsString("OperandType")); 88fa3d789dSPierre van Houtryve OperandNamespace = std::string(Rec->getValueAsString("OperandNamespace")); 89fa3d789dSPierre van Houtryve EncoderMethod = std::string(Rec->getValueAsString("EncoderMethod")); 90fa3d789dSPierre van Houtryve } else if (Rec->isSubClassOf("Operand")) { 91fa3d789dSPierre van Houtryve PrintMethod = std::string(Rec->getValueAsString("PrintMethod")); 92fa3d789dSPierre van Houtryve OperandType = std::string(Rec->getValueAsString("OperandType")); 93fa3d789dSPierre van Houtryve OperandNamespace = std::string(Rec->getValueAsString("OperandNamespace")); 94fa3d789dSPierre van Houtryve // If there is an explicit encoder method, use it. 95fa3d789dSPierre van Houtryve EncoderMethod = std::string(Rec->getValueAsString("EncoderMethod")); 96fa3d789dSPierre van Houtryve MIOpInfo = Rec->getValueAsDag("MIOperandInfo"); 97fa3d789dSPierre van Houtryve 98fa3d789dSPierre van Houtryve // Verify that MIOpInfo has an 'ops' root value. 99fa3d789dSPierre van Houtryve if (!isa<DefInit>(MIOpInfo->getOperator()) || 100fa3d789dSPierre van Houtryve cast<DefInit>(MIOpInfo->getOperator())->getDef()->getName() != "ops") 101fa3d789dSPierre van Houtryve PrintFatalError(R->getLoc(), 102fa3d789dSPierre van Houtryve "Bad value for MIOperandInfo in operand '" + 103fa3d789dSPierre van Houtryve Rec->getName() + "'\n"); 104fa3d789dSPierre van Houtryve 105fa3d789dSPierre van Houtryve // If we have MIOpInfo, then we have #operands equal to number of entries 106fa3d789dSPierre van Houtryve // in MIOperandInfo. 107fa3d789dSPierre van Houtryve if (unsigned NumArgs = MIOpInfo->getNumArgs()) 108fa3d789dSPierre van Houtryve NumOps = NumArgs; 109fa3d789dSPierre van Houtryve 110fa3d789dSPierre van Houtryve if (Rec->isSubClassOf("PredicateOp")) 111fa3d789dSPierre van Houtryve isPredicable = true; 112fa3d789dSPierre van Houtryve else if (Rec->isSubClassOf("OptionalDefOperand")) 113fa3d789dSPierre van Houtryve hasOptionalDef = true; 114fa3d789dSPierre van Houtryve } else if (Rec->getName() == "variable_ops") { 115fa3d789dSPierre van Houtryve if (i < NumDefs) 116fa3d789dSPierre van Houtryve VariadicOuts = true; 117fa3d789dSPierre van Houtryve isVariadic = true; 118fa3d789dSPierre van Houtryve continue; 119fa3d789dSPierre van Houtryve } else if (Rec->isSubClassOf("RegisterClass")) { 120fa3d789dSPierre van Houtryve OperandType = "OPERAND_REGISTER"; 121fa3d789dSPierre van Houtryve } else if (!Rec->isSubClassOf("PointerLikeRegClass") && 122fa3d789dSPierre van Houtryve !Rec->isSubClassOf("unknown_class")) { 123fa3d789dSPierre van Houtryve PrintFatalError(R->getLoc(), "Unknown operand class '" + Rec->getName() + 124fa3d789dSPierre van Houtryve "' in '" + R->getName() + 125fa3d789dSPierre van Houtryve "' instruction!"); 126fa3d789dSPierre van Houtryve } 127fa3d789dSPierre van Houtryve 128fa3d789dSPierre van Houtryve // Check that the operand has a name and that it's unique. 129fa3d789dSPierre van Houtryve if (ArgName.empty()) 130fa3d789dSPierre van Houtryve PrintFatalError(R->getLoc(), "In instruction '" + R->getName() + 131fa3d789dSPierre van Houtryve "', operand #" + Twine(i) + 132fa3d789dSPierre van Houtryve " has no name!"); 133fa3d789dSPierre van Houtryve if (!OperandNames.insert(std::string(ArgName)).second) 134fa3d789dSPierre van Houtryve PrintFatalError(R->getLoc(), 135fa3d789dSPierre van Houtryve "In instruction '" + R->getName() + "', operand #" + 136fa3d789dSPierre van Houtryve Twine(i) + 137fa3d789dSPierre van Houtryve " has the same name as a previous operand!"); 138fa3d789dSPierre van Houtryve 139fa3d789dSPierre van Houtryve OperandInfo &OpInfo = OperandList.emplace_back( 14031ce47b5Sabhishek-kaushik22 Rec, std::string(ArgName), std::string(std::move(PrintMethod)), 141fa3d789dSPierre van Houtryve OperandNamespace + "::" + OperandType, MIOperandNo, NumOps, MIOpInfo); 142fa3d789dSPierre van Houtryve 143fa3d789dSPierre van Houtryve if (SubArgDag) { 144fa3d789dSPierre van Houtryve if (SubArgDag->getNumArgs() != NumOps) { 145fa3d789dSPierre van Houtryve PrintFatalError(R->getLoc(), "In instruction '" + R->getName() + 146fa3d789dSPierre van Houtryve "', operand #" + Twine(i) + " has " + 147fa3d789dSPierre van Houtryve Twine(SubArgDag->getNumArgs()) + 148fa3d789dSPierre van Houtryve " sub-arg names, expected " + 149fa3d789dSPierre van Houtryve Twine(NumOps) + "."); 150fa3d789dSPierre van Houtryve } 151fa3d789dSPierre van Houtryve 152fa3d789dSPierre van Houtryve for (unsigned j = 0; j < NumOps; ++j) { 153fa3d789dSPierre van Houtryve if (!isa<UnsetInit>(SubArgDag->getArg(j))) 154fa3d789dSPierre van Houtryve PrintFatalError(R->getLoc(), 155fa3d789dSPierre van Houtryve "In instruction '" + R->getName() + "', operand #" + 156fa3d789dSPierre van Houtryve Twine(i) + " sub-arg #" + Twine(j) + 157fa3d789dSPierre van Houtryve " has unexpected operand (expected only $name)."); 158fa3d789dSPierre van Houtryve 159fa3d789dSPierre van Houtryve StringRef SubArgName = SubArgDag->getArgNameStr(j); 160fa3d789dSPierre van Houtryve if (SubArgName.empty()) 161fa3d789dSPierre van Houtryve PrintFatalError(R->getLoc(), "In instruction '" + R->getName() + 162fa3d789dSPierre van Houtryve "', operand #" + Twine(i) + 163fa3d789dSPierre van Houtryve " has no name!"); 164fa3d789dSPierre van Houtryve if (!OperandNames.insert(std::string(SubArgName)).second) 165fa3d789dSPierre van Houtryve PrintFatalError(R->getLoc(), 166fa3d789dSPierre van Houtryve "In instruction '" + R->getName() + "', operand #" + 167fa3d789dSPierre van Houtryve Twine(i) + " sub-arg #" + Twine(j) + 168fa3d789dSPierre van Houtryve " has the same name as a previous operand!"); 169fa3d789dSPierre van Houtryve 170fa3d789dSPierre van Houtryve if (auto MaybeEncoderMethod = 171fa3d789dSPierre van Houtryve cast<DefInit>(MIOpInfo->getArg(j)) 172fa3d789dSPierre van Houtryve ->getDef() 173fa3d789dSPierre van Houtryve ->getValueAsOptionalString("EncoderMethod")) { 174fa3d789dSPierre van Houtryve OpInfo.EncoderMethodNames[j] = *MaybeEncoderMethod; 175fa3d789dSPierre van Houtryve } 176fa3d789dSPierre van Houtryve 177fa3d789dSPierre van Houtryve OpInfo.SubOpNames[j] = SubArgName; 178*4e8c9d28SJay Foad SubOpAliases[SubArgName] = {i, j}; 179fa3d789dSPierre van Houtryve } 180fa3d789dSPierre van Houtryve } else if (!EncoderMethod.empty()) { 181fa3d789dSPierre van Houtryve // If we have no explicit sub-op dag, but have an top-level encoder 182fa3d789dSPierre van Houtryve // method, the single encoder will multiple sub-ops, itself. 18331ce47b5Sabhishek-kaushik22 OpInfo.EncoderMethodNames[0] = std::move(EncoderMethod); 184fa3d789dSPierre van Houtryve for (unsigned j = 1; j < NumOps; ++j) 185fa3d789dSPierre van Houtryve OpInfo.DoNotEncode[j] = true; 186fa3d789dSPierre van Houtryve } 187fa3d789dSPierre van Houtryve 188fa3d789dSPierre van Houtryve MIOperandNo += NumOps; 189fa3d789dSPierre van Houtryve } 190fa3d789dSPierre van Houtryve 191fa3d789dSPierre van Houtryve if (VariadicOuts) 192fa3d789dSPierre van Houtryve --NumDefs; 193fa3d789dSPierre van Houtryve } 194fa3d789dSPierre van Houtryve 195fa3d789dSPierre van Houtryve /// getOperandNamed - Return the index of the operand with the specified 196fa3d789dSPierre van Houtryve /// non-empty name. If the instruction does not have an operand with the 197fa3d789dSPierre van Houtryve /// specified name, abort. 198fa3d789dSPierre van Houtryve /// 199fa3d789dSPierre van Houtryve unsigned CGIOperandList::getOperandNamed(StringRef Name) const { 200fa3d789dSPierre van Houtryve unsigned OpIdx; 201fa3d789dSPierre van Houtryve if (hasOperandNamed(Name, OpIdx)) 202fa3d789dSPierre van Houtryve return OpIdx; 203fa3d789dSPierre van Houtryve PrintFatalError(TheDef->getLoc(), "'" + TheDef->getName() + 204fa3d789dSPierre van Houtryve "' does not have an operand named '$" + 205fa3d789dSPierre van Houtryve Name + "'!"); 206fa3d789dSPierre van Houtryve } 207fa3d789dSPierre van Houtryve 208fa3d789dSPierre van Houtryve /// hasOperandNamed - Query whether the instruction has an operand of the 209fa3d789dSPierre van Houtryve /// given name. If so, return true and set OpIdx to the index of the 210fa3d789dSPierre van Houtryve /// operand. Otherwise, return false. 211fa3d789dSPierre van Houtryve bool CGIOperandList::hasOperandNamed(StringRef Name, unsigned &OpIdx) const { 212fa3d789dSPierre van Houtryve assert(!Name.empty() && "Cannot search for operand with no name!"); 213fa3d789dSPierre van Houtryve for (unsigned i = 0, e = OperandList.size(); i != e; ++i) 214fa3d789dSPierre van Houtryve if (OperandList[i].Name == Name) { 215fa3d789dSPierre van Houtryve OpIdx = i; 216fa3d789dSPierre van Houtryve return true; 217fa3d789dSPierre van Houtryve } 218fa3d789dSPierre van Houtryve return false; 219fa3d789dSPierre van Houtryve } 220fa3d789dSPierre van Houtryve 221fa3d789dSPierre van Houtryve bool CGIOperandList::hasSubOperandAlias( 222fa3d789dSPierre van Houtryve StringRef Name, std::pair<unsigned, unsigned> &SubOp) const { 223fa3d789dSPierre van Houtryve assert(!Name.empty() && "Cannot search for operand with no name!"); 224fa3d789dSPierre van Houtryve auto SubOpIter = SubOpAliases.find(Name); 225fa3d789dSPierre van Houtryve if (SubOpIter != SubOpAliases.end()) { 226fa3d789dSPierre van Houtryve SubOp = SubOpIter->second; 227fa3d789dSPierre van Houtryve return true; 228fa3d789dSPierre van Houtryve } 229fa3d789dSPierre van Houtryve return false; 230fa3d789dSPierre van Houtryve } 231fa3d789dSPierre van Houtryve 232fa3d789dSPierre van Houtryve std::pair<unsigned, unsigned> 233fa3d789dSPierre van Houtryve CGIOperandList::ParseOperandName(StringRef Op, bool AllowWholeOp) { 234fa3d789dSPierre van Houtryve if (!Op.starts_with("$")) 235fa3d789dSPierre van Houtryve PrintFatalError(TheDef->getLoc(), 236fa3d789dSPierre van Houtryve TheDef->getName() + ": Illegal operand name: '" + Op + "'"); 237fa3d789dSPierre van Houtryve 238fa3d789dSPierre van Houtryve StringRef OpName = Op.substr(1); 239fa3d789dSPierre van Houtryve StringRef SubOpName; 240fa3d789dSPierre van Houtryve 241fa3d789dSPierre van Houtryve // Check to see if this is $foo.bar. 242fa3d789dSPierre van Houtryve StringRef::size_type DotIdx = OpName.find_first_of('.'); 243fa3d789dSPierre van Houtryve if (DotIdx != StringRef::npos) { 244fa3d789dSPierre van Houtryve SubOpName = OpName.substr(DotIdx + 1); 245fa3d789dSPierre van Houtryve if (SubOpName.empty()) 246fa3d789dSPierre van Houtryve PrintFatalError(TheDef->getLoc(), 247fa3d789dSPierre van Houtryve TheDef->getName() + 248fa3d789dSPierre van Houtryve ": illegal empty suboperand name in '" + Op + "'"); 249fa3d789dSPierre van Houtryve OpName = OpName.substr(0, DotIdx); 250fa3d789dSPierre van Houtryve } 251fa3d789dSPierre van Houtryve 252fa3d789dSPierre van Houtryve unsigned OpIdx; 253fa3d789dSPierre van Houtryve 254fa3d789dSPierre van Houtryve if (std::pair<unsigned, unsigned> SubOp; hasSubOperandAlias(OpName, SubOp)) { 255fa3d789dSPierre van Houtryve // Found a name for a piece of an operand, just return it directly. 256fa3d789dSPierre van Houtryve if (!SubOpName.empty()) { 257fa3d789dSPierre van Houtryve PrintFatalError( 258fa3d789dSPierre van Houtryve TheDef->getLoc(), 259fa3d789dSPierre van Houtryve TheDef->getName() + 260fa3d789dSPierre van Houtryve ": Cannot use dotted suboperand name within suboperand '" + 261fa3d789dSPierre van Houtryve OpName + "'"); 262fa3d789dSPierre van Houtryve } 263fa3d789dSPierre van Houtryve return SubOp; 264fa3d789dSPierre van Houtryve } 265fa3d789dSPierre van Houtryve 266fa3d789dSPierre van Houtryve OpIdx = getOperandNamed(OpName); 267fa3d789dSPierre van Houtryve 268fa3d789dSPierre van Houtryve if (SubOpName.empty()) { // If no suboperand name was specified: 269fa3d789dSPierre van Houtryve // If one was needed, throw. 270fa3d789dSPierre van Houtryve if (OperandList[OpIdx].MINumOperands > 1 && !AllowWholeOp && 271fa3d789dSPierre van Houtryve SubOpName.empty()) 272fa3d789dSPierre van Houtryve PrintFatalError(TheDef->getLoc(), 273fa3d789dSPierre van Houtryve TheDef->getName() + 274fa3d789dSPierre van Houtryve ": Illegal to refer to" 275fa3d789dSPierre van Houtryve " whole operand part of complex operand '" + 276fa3d789dSPierre van Houtryve Op + "'"); 277fa3d789dSPierre van Houtryve 278fa3d789dSPierre van Houtryve // Otherwise, return the operand. 279*4e8c9d28SJay Foad return {OpIdx, 0U}; 280fa3d789dSPierre van Houtryve } 281fa3d789dSPierre van Houtryve 282fa3d789dSPierre van Houtryve // Find the suboperand number involved. 28362e2c7fbSRahul Joshi const DagInit *MIOpInfo = OperandList[OpIdx].MIOperandInfo; 284fa3d789dSPierre van Houtryve if (!MIOpInfo) 285fa3d789dSPierre van Houtryve PrintFatalError(TheDef->getLoc(), TheDef->getName() + 286fa3d789dSPierre van Houtryve ": unknown suboperand name in '" + 287fa3d789dSPierre van Houtryve Op + "'"); 288fa3d789dSPierre van Houtryve 289fa3d789dSPierre van Houtryve // Find the operand with the right name. 290fa3d789dSPierre van Houtryve for (unsigned i = 0, e = MIOpInfo->getNumArgs(); i != e; ++i) 291fa3d789dSPierre van Houtryve if (MIOpInfo->getArgNameStr(i) == SubOpName) 292*4e8c9d28SJay Foad return {OpIdx, i}; 293fa3d789dSPierre van Houtryve 294fa3d789dSPierre van Houtryve // Otherwise, didn't find it! 295fa3d789dSPierre van Houtryve PrintFatalError(TheDef->getLoc(), TheDef->getName() + 296fa3d789dSPierre van Houtryve ": unknown suboperand name in '" + Op + 297fa3d789dSPierre van Houtryve "'"); 298*4e8c9d28SJay Foad return {0U, 0U}; 299fa3d789dSPierre van Houtryve } 300fa3d789dSPierre van Houtryve 30137865681SRahul Joshi static void ParseConstraint(StringRef CStr, CGIOperandList &Ops, 30237865681SRahul Joshi const Record *Rec) { 303fa3d789dSPierre van Houtryve // EARLY_CLOBBER: @early $reg 304fa3d789dSPierre van Houtryve StringRef::size_type wpos = CStr.find_first_of(" \t"); 305fa3d789dSPierre van Houtryve StringRef::size_type start = CStr.find_first_not_of(" \t"); 306fa3d789dSPierre van Houtryve StringRef Tok = CStr.substr(start, wpos - start); 307fa3d789dSPierre van Houtryve if (Tok == "@earlyclobber") { 308fa3d789dSPierre van Houtryve StringRef Name = CStr.substr(wpos + 1); 309fa3d789dSPierre van Houtryve wpos = Name.find_first_not_of(" \t"); 310fa3d789dSPierre van Houtryve if (wpos == StringRef::npos) 311fa3d789dSPierre van Houtryve PrintFatalError(Rec->getLoc(), 312fa3d789dSPierre van Houtryve "Illegal format for @earlyclobber constraint in '" + 313fa3d789dSPierre van Houtryve Rec->getName() + "': '" + CStr + "'"); 314fa3d789dSPierre van Houtryve Name = Name.substr(wpos); 315fa3d789dSPierre van Houtryve std::pair<unsigned, unsigned> Op = Ops.ParseOperandName(Name, false); 316fa3d789dSPierre van Houtryve 317fa3d789dSPierre van Houtryve // Build the string for the operand 318fa3d789dSPierre van Houtryve if (!Ops[Op.first].Constraints[Op.second].isNone()) 319fa3d789dSPierre van Houtryve PrintFatalError(Rec->getLoc(), "Operand '" + Name + "' of '" + 320fa3d789dSPierre van Houtryve Rec->getName() + 321fa3d789dSPierre van Houtryve "' cannot have multiple constraints!"); 322fa3d789dSPierre van Houtryve Ops[Op.first].Constraints[Op.second] = 323fa3d789dSPierre van Houtryve CGIOperandList::ConstraintInfo::getEarlyClobber(); 324fa3d789dSPierre van Houtryve return; 325fa3d789dSPierre van Houtryve } 326fa3d789dSPierre van Houtryve 327fa3d789dSPierre van Houtryve // Only other constraint is "TIED_TO" for now. 328fa3d789dSPierre van Houtryve StringRef::size_type pos = CStr.find_first_of('='); 329fa3d789dSPierre van Houtryve if (pos == StringRef::npos || pos == 0 || 330fa3d789dSPierre van Houtryve CStr.find_first_of(" \t", pos) != (pos + 1) || 331fa3d789dSPierre van Houtryve CStr.find_last_of(" \t", pos) != (pos - 1)) 332fa3d789dSPierre van Houtryve PrintFatalError(Rec->getLoc(), "Unrecognized constraint '" + CStr + 333fa3d789dSPierre van Houtryve "' in '" + Rec->getName() + "'"); 334fa3d789dSPierre van Houtryve start = CStr.find_first_not_of(" \t"); 335fa3d789dSPierre van Houtryve 336fa3d789dSPierre van Houtryve // TIED_TO: $src1 = $dst 337fa3d789dSPierre van Houtryve wpos = CStr.find_first_of(" \t", start); 338fa3d789dSPierre van Houtryve if (wpos == StringRef::npos || wpos > pos) 339fa3d789dSPierre van Houtryve PrintFatalError(Rec->getLoc(), 340fa3d789dSPierre van Houtryve "Illegal format for tied-to constraint in '" + 341fa3d789dSPierre van Houtryve Rec->getName() + "': '" + CStr + "'"); 342fa3d789dSPierre van Houtryve StringRef LHSOpName = CStr.substr(start, wpos - start); 343fa3d789dSPierre van Houtryve std::pair<unsigned, unsigned> LHSOp = Ops.ParseOperandName(LHSOpName, false); 344fa3d789dSPierre van Houtryve 345fa3d789dSPierre van Houtryve wpos = CStr.find_first_not_of(" \t", pos + 1); 346fa3d789dSPierre van Houtryve if (wpos == StringRef::npos) 347fa3d789dSPierre van Houtryve PrintFatalError(Rec->getLoc(), 348fa3d789dSPierre van Houtryve "Illegal format for tied-to constraint: '" + CStr + "'"); 349fa3d789dSPierre van Houtryve 350fa3d789dSPierre van Houtryve StringRef RHSOpName = CStr.substr(wpos); 351fa3d789dSPierre van Houtryve std::pair<unsigned, unsigned> RHSOp = Ops.ParseOperandName(RHSOpName, false); 352fa3d789dSPierre van Houtryve 353fa3d789dSPierre van Houtryve // Sort the operands into order, which should put the output one 354fa3d789dSPierre van Houtryve // first. But keep the original order, for use in diagnostics. 355fa3d789dSPierre van Houtryve bool FirstIsDest = (LHSOp < RHSOp); 356fa3d789dSPierre van Houtryve std::pair<unsigned, unsigned> DestOp = (FirstIsDest ? LHSOp : RHSOp); 357fa3d789dSPierre van Houtryve StringRef DestOpName = (FirstIsDest ? LHSOpName : RHSOpName); 358fa3d789dSPierre van Houtryve std::pair<unsigned, unsigned> SrcOp = (FirstIsDest ? RHSOp : LHSOp); 359fa3d789dSPierre van Houtryve StringRef SrcOpName = (FirstIsDest ? RHSOpName : LHSOpName); 360fa3d789dSPierre van Houtryve 361fa3d789dSPierre van Houtryve // Ensure one operand is a def and the other is a use. 362fa3d789dSPierre van Houtryve if (DestOp.first >= Ops.NumDefs) 363fa3d789dSPierre van Houtryve PrintFatalError(Rec->getLoc(), "Input operands '" + LHSOpName + "' and '" + 364fa3d789dSPierre van Houtryve RHSOpName + "' of '" + Rec->getName() + 365fa3d789dSPierre van Houtryve "' cannot be tied!"); 366fa3d789dSPierre van Houtryve if (SrcOp.first < Ops.NumDefs) 367fa3d789dSPierre van Houtryve PrintFatalError(Rec->getLoc(), "Output operands '" + LHSOpName + "' and '" + 368fa3d789dSPierre van Houtryve RHSOpName + "' of '" + Rec->getName() + 369fa3d789dSPierre van Houtryve "' cannot be tied!"); 370fa3d789dSPierre van Houtryve 371fa3d789dSPierre van Houtryve // The constraint has to go on the operand with higher index, i.e. 372fa3d789dSPierre van Houtryve // the source one. Check there isn't another constraint there 373fa3d789dSPierre van Houtryve // already. 374fa3d789dSPierre van Houtryve if (!Ops[SrcOp.first].Constraints[SrcOp.second].isNone()) 375fa3d789dSPierre van Houtryve PrintFatalError(Rec->getLoc(), "Operand '" + SrcOpName + "' of '" + 376fa3d789dSPierre van Houtryve Rec->getName() + 377fa3d789dSPierre van Houtryve "' cannot have multiple constraints!"); 378fa3d789dSPierre van Houtryve 379fa3d789dSPierre van Houtryve unsigned DestFlatOpNo = Ops.getFlattenedOperandNumber(DestOp); 380fa3d789dSPierre van Houtryve auto NewConstraint = CGIOperandList::ConstraintInfo::getTied(DestFlatOpNo); 381fa3d789dSPierre van Houtryve 382fa3d789dSPierre van Houtryve // Check that the earlier operand is not the target of another tie 383fa3d789dSPierre van Houtryve // before making it the target of this one. 384fa3d789dSPierre van Houtryve for (const CGIOperandList::OperandInfo &Op : Ops) { 385fa3d789dSPierre van Houtryve for (unsigned i = 0; i < Op.MINumOperands; i++) 386fa3d789dSPierre van Houtryve if (Op.Constraints[i] == NewConstraint) 387fa3d789dSPierre van Houtryve PrintFatalError(Rec->getLoc(), 388fa3d789dSPierre van Houtryve "Operand '" + DestOpName + "' of '" + Rec->getName() + 389fa3d789dSPierre van Houtryve "' cannot have multiple operands tied to it!"); 390fa3d789dSPierre van Houtryve } 391fa3d789dSPierre van Houtryve 392fa3d789dSPierre van Houtryve Ops[SrcOp.first].Constraints[SrcOp.second] = NewConstraint; 393fa3d789dSPierre van Houtryve } 394fa3d789dSPierre van Houtryve 39537865681SRahul Joshi static void ParseConstraints(StringRef CStr, CGIOperandList &Ops, 39637865681SRahul Joshi const Record *Rec) { 397fa3d789dSPierre van Houtryve if (CStr.empty()) 398fa3d789dSPierre van Houtryve return; 399fa3d789dSPierre van Houtryve 400fa3d789dSPierre van Houtryve StringRef delims(","); 401fa3d789dSPierre van Houtryve StringRef::size_type bidx, eidx; 402fa3d789dSPierre van Houtryve 403fa3d789dSPierre van Houtryve bidx = CStr.find_first_not_of(delims); 404fa3d789dSPierre van Houtryve while (bidx != StringRef::npos) { 405fa3d789dSPierre van Houtryve eidx = CStr.find_first_of(delims, bidx); 406fa3d789dSPierre van Houtryve if (eidx == StringRef::npos) 407fa3d789dSPierre van Houtryve eidx = CStr.size(); 408fa3d789dSPierre van Houtryve 409fa3d789dSPierre van Houtryve ParseConstraint(CStr.substr(bidx, eidx - bidx), Ops, Rec); 410fa3d789dSPierre van Houtryve bidx = CStr.find_first_not_of(delims, eidx); 411fa3d789dSPierre van Houtryve } 412fa3d789dSPierre van Houtryve } 413fa3d789dSPierre van Houtryve 414fa3d789dSPierre van Houtryve void CGIOperandList::ProcessDisableEncoding(StringRef DisableEncoding) { 415fa3d789dSPierre van Houtryve while (true) { 416fa3d789dSPierre van Houtryve StringRef OpName; 417fa3d789dSPierre van Houtryve std::tie(OpName, DisableEncoding) = getToken(DisableEncoding, " ,\t"); 418fa3d789dSPierre van Houtryve if (OpName.empty()) 419fa3d789dSPierre van Houtryve break; 420fa3d789dSPierre van Houtryve 421fa3d789dSPierre van Houtryve // Figure out which operand this is. 422fa3d789dSPierre van Houtryve std::pair<unsigned, unsigned> Op = ParseOperandName(OpName, false); 423fa3d789dSPierre van Houtryve 424fa3d789dSPierre van Houtryve // Mark the operand as not-to-be encoded. 425fa3d789dSPierre van Houtryve OperandList[Op.first].DoNotEncode[Op.second] = true; 426fa3d789dSPierre van Houtryve } 427fa3d789dSPierre van Houtryve } 428fa3d789dSPierre van Houtryve 429fa3d789dSPierre van Houtryve //===----------------------------------------------------------------------===// 430fa3d789dSPierre van Houtryve // CodeGenInstruction Implementation 431fa3d789dSPierre van Houtryve //===----------------------------------------------------------------------===// 432fa3d789dSPierre van Houtryve 43337865681SRahul Joshi CodeGenInstruction::CodeGenInstruction(const Record *R) 434fa3d789dSPierre van Houtryve : TheDef(R), Operands(R), InferredFrom(nullptr) { 435fa3d789dSPierre van Houtryve Namespace = R->getValueAsString("Namespace"); 436fa3d789dSPierre van Houtryve AsmString = std::string(R->getValueAsString("AsmString")); 437fa3d789dSPierre van Houtryve 438fa3d789dSPierre van Houtryve isPreISelOpcode = R->getValueAsBit("isPreISelOpcode"); 439fa3d789dSPierre van Houtryve isReturn = R->getValueAsBit("isReturn"); 440fa3d789dSPierre van Houtryve isEHScopeReturn = R->getValueAsBit("isEHScopeReturn"); 441fa3d789dSPierre van Houtryve isBranch = R->getValueAsBit("isBranch"); 442fa3d789dSPierre van Houtryve isIndirectBranch = R->getValueAsBit("isIndirectBranch"); 443fa3d789dSPierre van Houtryve isCompare = R->getValueAsBit("isCompare"); 444fa3d789dSPierre van Houtryve isMoveImm = R->getValueAsBit("isMoveImm"); 445fa3d789dSPierre van Houtryve isMoveReg = R->getValueAsBit("isMoveReg"); 446fa3d789dSPierre van Houtryve isBitcast = R->getValueAsBit("isBitcast"); 447fa3d789dSPierre van Houtryve isSelect = R->getValueAsBit("isSelect"); 448fa3d789dSPierre van Houtryve isBarrier = R->getValueAsBit("isBarrier"); 449fa3d789dSPierre van Houtryve isCall = R->getValueAsBit("isCall"); 450fa3d789dSPierre van Houtryve isAdd = R->getValueAsBit("isAdd"); 451fa3d789dSPierre van Houtryve isTrap = R->getValueAsBit("isTrap"); 452fa3d789dSPierre van Houtryve canFoldAsLoad = R->getValueAsBit("canFoldAsLoad"); 453fa3d789dSPierre van Houtryve isPredicable = !R->getValueAsBit("isUnpredicable") && 454fa3d789dSPierre van Houtryve (Operands.isPredicable || R->getValueAsBit("isPredicable")); 455fa3d789dSPierre van Houtryve isConvertibleToThreeAddress = R->getValueAsBit("isConvertibleToThreeAddress"); 456fa3d789dSPierre van Houtryve isCommutable = R->getValueAsBit("isCommutable"); 457fa3d789dSPierre van Houtryve isTerminator = R->getValueAsBit("isTerminator"); 458fa3d789dSPierre van Houtryve isReMaterializable = R->getValueAsBit("isReMaterializable"); 459fa3d789dSPierre van Houtryve hasDelaySlot = R->getValueAsBit("hasDelaySlot"); 460fa3d789dSPierre van Houtryve usesCustomInserter = R->getValueAsBit("usesCustomInserter"); 461fa3d789dSPierre van Houtryve hasPostISelHook = R->getValueAsBit("hasPostISelHook"); 462fa3d789dSPierre van Houtryve hasCtrlDep = R->getValueAsBit("hasCtrlDep"); 463fa3d789dSPierre van Houtryve isNotDuplicable = R->getValueAsBit("isNotDuplicable"); 464fa3d789dSPierre van Houtryve isRegSequence = R->getValueAsBit("isRegSequence"); 465fa3d789dSPierre van Houtryve isExtractSubreg = R->getValueAsBit("isExtractSubreg"); 466fa3d789dSPierre van Houtryve isInsertSubreg = R->getValueAsBit("isInsertSubreg"); 467fa3d789dSPierre van Houtryve isConvergent = R->getValueAsBit("isConvergent"); 468fa3d789dSPierre van Houtryve hasNoSchedulingInfo = R->getValueAsBit("hasNoSchedulingInfo"); 469fa3d789dSPierre van Houtryve FastISelShouldIgnore = R->getValueAsBit("FastISelShouldIgnore"); 470fa3d789dSPierre van Houtryve variadicOpsAreDefs = R->getValueAsBit("variadicOpsAreDefs"); 471fa3d789dSPierre van Houtryve isAuthenticated = R->getValueAsBit("isAuthenticated"); 472fa3d789dSPierre van Houtryve 473fa3d789dSPierre van Houtryve bool Unset; 474fa3d789dSPierre van Houtryve mayLoad = R->getValueAsBitOrUnset("mayLoad", Unset); 475fa3d789dSPierre van Houtryve mayLoad_Unset = Unset; 476fa3d789dSPierre van Houtryve mayStore = R->getValueAsBitOrUnset("mayStore", Unset); 477fa3d789dSPierre van Houtryve mayStore_Unset = Unset; 478fa3d789dSPierre van Houtryve mayRaiseFPException = R->getValueAsBit("mayRaiseFPException"); 479fa3d789dSPierre van Houtryve hasSideEffects = R->getValueAsBitOrUnset("hasSideEffects", Unset); 480fa3d789dSPierre van Houtryve hasSideEffects_Unset = Unset; 481fa3d789dSPierre van Houtryve 482fa3d789dSPierre van Houtryve isAsCheapAsAMove = R->getValueAsBit("isAsCheapAsAMove"); 483fa3d789dSPierre van Houtryve hasExtraSrcRegAllocReq = R->getValueAsBit("hasExtraSrcRegAllocReq"); 484fa3d789dSPierre van Houtryve hasExtraDefRegAllocReq = R->getValueAsBit("hasExtraDefRegAllocReq"); 485fa3d789dSPierre van Houtryve isCodeGenOnly = R->getValueAsBit("isCodeGenOnly"); 486fa3d789dSPierre van Houtryve isPseudo = R->getValueAsBit("isPseudo"); 487fa3d789dSPierre van Houtryve isMeta = R->getValueAsBit("isMeta"); 488a140931bSRahul Joshi ImplicitDefs = R->getValueAsListOfDefs("Defs"); 489a140931bSRahul Joshi ImplicitUses = R->getValueAsListOfDefs("Uses"); 490fa3d789dSPierre van Houtryve 491fa3d789dSPierre van Houtryve // This flag is only inferred from the pattern. 492fa3d789dSPierre van Houtryve hasChain = false; 493fa3d789dSPierre van Houtryve hasChain_Inferred = false; 494fa3d789dSPierre van Houtryve 495fa3d789dSPierre van Houtryve // Parse Constraints. 496fa3d789dSPierre van Houtryve ParseConstraints(R->getValueAsString("Constraints"), Operands, R); 497fa3d789dSPierre van Houtryve 498fa3d789dSPierre van Houtryve // Parse the DisableEncoding field. 499fa3d789dSPierre van Houtryve Operands.ProcessDisableEncoding(R->getValueAsString("DisableEncoding")); 500fa3d789dSPierre van Houtryve 501fa3d789dSPierre van Houtryve // First check for a ComplexDeprecationPredicate. 502fa3d789dSPierre van Houtryve if (R->getValue("ComplexDeprecationPredicate")) { 503fa3d789dSPierre van Houtryve HasComplexDeprecationPredicate = true; 504fa3d789dSPierre van Houtryve DeprecatedReason = 505fa3d789dSPierre van Houtryve std::string(R->getValueAsString("ComplexDeprecationPredicate")); 50637865681SRahul Joshi } else if (const RecordVal *Dep = R->getValue("DeprecatedFeatureMask")) { 507fa3d789dSPierre van Houtryve // Check if we have a Subtarget feature mask. 508fa3d789dSPierre van Houtryve HasComplexDeprecationPredicate = false; 509fa3d789dSPierre van Houtryve DeprecatedReason = Dep->getValue()->getAsString(); 510fa3d789dSPierre van Houtryve } else { 511fa3d789dSPierre van Houtryve // This instruction isn't deprecated. 512fa3d789dSPierre van Houtryve HasComplexDeprecationPredicate = false; 513fa3d789dSPierre van Houtryve DeprecatedReason = ""; 514fa3d789dSPierre van Houtryve } 515fa3d789dSPierre van Houtryve } 516fa3d789dSPierre van Houtryve 517fa3d789dSPierre van Houtryve /// HasOneImplicitDefWithKnownVT - If the instruction has at least one 518fa3d789dSPierre van Houtryve /// implicit def and it has a known VT, return the VT, otherwise return 519fa3d789dSPierre van Houtryve /// MVT::Other. 520fa3d789dSPierre van Houtryve MVT::SimpleValueType CodeGenInstruction::HasOneImplicitDefWithKnownVT( 521fa3d789dSPierre van Houtryve const CodeGenTarget &TargetInfo) const { 522fa3d789dSPierre van Houtryve if (ImplicitDefs.empty()) 523fa3d789dSPierre van Houtryve return MVT::Other; 524fa3d789dSPierre van Houtryve 525fa3d789dSPierre van Houtryve // Check to see if the first implicit def has a resolvable type. 52623123aa4SRahul Joshi const Record *FirstImplicitDef = ImplicitDefs[0]; 527fa3d789dSPierre van Houtryve assert(FirstImplicitDef->isSubClassOf("Register")); 528fa3d789dSPierre van Houtryve const std::vector<ValueTypeByHwMode> &RegVTs = 529fa3d789dSPierre van Houtryve TargetInfo.getRegisterVTs(FirstImplicitDef); 530fa3d789dSPierre van Houtryve if (RegVTs.size() == 1 && RegVTs[0].isSimple()) 531fa3d789dSPierre van Houtryve return RegVTs[0].getSimple().SimpleTy; 532fa3d789dSPierre van Houtryve return MVT::Other; 533fa3d789dSPierre van Houtryve } 534fa3d789dSPierre van Houtryve 535fa3d789dSPierre van Houtryve /// FlattenAsmStringVariants - Flatten the specified AsmString to only 536fa3d789dSPierre van Houtryve /// include text from the specified variant, returning the new string. 537fa3d789dSPierre van Houtryve std::string CodeGenInstruction::FlattenAsmStringVariants(StringRef Cur, 538fa3d789dSPierre van Houtryve unsigned Variant) { 539fa3d789dSPierre van Houtryve std::string Res; 540fa3d789dSPierre van Houtryve 541fa3d789dSPierre van Houtryve for (;;) { 542fa3d789dSPierre van Houtryve // Find the start of the next variant string. 543fa3d789dSPierre van Houtryve size_t VariantsStart = 0; 544fa3d789dSPierre van Houtryve for (size_t e = Cur.size(); VariantsStart != e; ++VariantsStart) 545fa3d789dSPierre van Houtryve if (Cur[VariantsStart] == '{' && 546fa3d789dSPierre van Houtryve (VariantsStart == 0 || 547fa3d789dSPierre van Houtryve (Cur[VariantsStart - 1] != '$' && Cur[VariantsStart - 1] != '\\'))) 548fa3d789dSPierre van Houtryve break; 549fa3d789dSPierre van Houtryve 550fa3d789dSPierre van Houtryve // Add the prefix to the result. 551fa3d789dSPierre van Houtryve Res += Cur.slice(0, VariantsStart); 552fa3d789dSPierre van Houtryve if (VariantsStart == Cur.size()) 553fa3d789dSPierre van Houtryve break; 554fa3d789dSPierre van Houtryve 555fa3d789dSPierre van Houtryve ++VariantsStart; // Skip the '{'. 556fa3d789dSPierre van Houtryve 557fa3d789dSPierre van Houtryve // Scan to the end of the variants string. 558fa3d789dSPierre van Houtryve size_t VariantsEnd = VariantsStart; 559fa3d789dSPierre van Houtryve unsigned NestedBraces = 1; 560fa3d789dSPierre van Houtryve for (size_t e = Cur.size(); VariantsEnd != e; ++VariantsEnd) { 561fa3d789dSPierre van Houtryve if (Cur[VariantsEnd] == '}' && Cur[VariantsEnd - 1] != '\\') { 562fa3d789dSPierre van Houtryve if (--NestedBraces == 0) 563fa3d789dSPierre van Houtryve break; 564fa3d789dSPierre van Houtryve } else if (Cur[VariantsEnd] == '{') 565fa3d789dSPierre van Houtryve ++NestedBraces; 566fa3d789dSPierre van Houtryve } 567fa3d789dSPierre van Houtryve 568fa3d789dSPierre van Houtryve // Select the Nth variant (or empty). 5699bb5af8aSFangrui Song StringRef Selection = 5709bb5af8aSFangrui Song Cur.substr(VariantsStart, VariantsEnd - VariantsStart); 571fa3d789dSPierre van Houtryve for (unsigned i = 0; i != Variant; ++i) 572fa3d789dSPierre van Houtryve Selection = Selection.split('|').second; 573fa3d789dSPierre van Houtryve Res += Selection.split('|').first; 574fa3d789dSPierre van Houtryve 575fa3d789dSPierre van Houtryve assert(VariantsEnd != Cur.size() && 576fa3d789dSPierre van Houtryve "Unterminated variants in assembly string!"); 577fa3d789dSPierre van Houtryve Cur = Cur.substr(VariantsEnd + 1); 578fa3d789dSPierre van Houtryve } 579fa3d789dSPierre van Houtryve 580fa3d789dSPierre van Houtryve return Res; 581fa3d789dSPierre van Houtryve } 582fa3d789dSPierre van Houtryve 583fa3d789dSPierre van Houtryve bool CodeGenInstruction::isOperandImpl(StringRef OpListName, unsigned i, 584fa3d789dSPierre van Houtryve StringRef PropertyName) const { 58562e2c7fbSRahul Joshi const DagInit *ConstraintList = TheDef->getValueAsDag(OpListName); 586fa3d789dSPierre van Houtryve if (!ConstraintList || i >= ConstraintList->getNumArgs()) 587fa3d789dSPierre van Houtryve return false; 588fa3d789dSPierre van Houtryve 58962e2c7fbSRahul Joshi const DefInit *Constraint = dyn_cast<DefInit>(ConstraintList->getArg(i)); 590fa3d789dSPierre van Houtryve if (!Constraint) 591fa3d789dSPierre van Houtryve return false; 592fa3d789dSPierre van Houtryve 593fa3d789dSPierre van Houtryve return Constraint->getDef()->isSubClassOf("TypedOperand") && 594fa3d789dSPierre van Houtryve Constraint->getDef()->getValueAsBit(PropertyName); 595fa3d789dSPierre van Houtryve } 596