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