1193323Sed//===- CodeGenInstruction.cpp - CodeGen Instruction Class Wrapper ---------===// 2193323Sed// 3193323Sed// The LLVM Compiler Infrastructure 4193323Sed// 5193323Sed// This file is distributed under the University of Illinois Open Source 6193323Sed// License. See LICENSE.TXT for details. 7193323Sed// 8193323Sed//===----------------------------------------------------------------------===// 9193323Sed// 10193323Sed// This file implements the CodeGenInstruction class. 11193323Sed// 12193323Sed//===----------------------------------------------------------------------===// 13193323Sed 14193323Sed#include "CodeGenInstruction.h" 15206083Srdivacky#include "CodeGenTarget.h" 16249423Sdim#include "llvm/ADT/STLExtras.h" 17249423Sdim#include "llvm/ADT/StringExtras.h" 18249423Sdim#include "llvm/ADT/StringMap.h" 19226633Sdim#include "llvm/TableGen/Error.h" 20226633Sdim#include "llvm/TableGen/Record.h" 21193323Sed#include <set> 22193323Sedusing namespace llvm; 23193323Sed 24218893Sdim//===----------------------------------------------------------------------===// 25218893Sdim// CGIOperandList Implementation 26218893Sdim//===----------------------------------------------------------------------===// 27201360Srdivacky 28218893SdimCGIOperandList::CGIOperandList(Record *R) : TheDef(R) { 29218893Sdim isPredicable = false; 30193323Sed hasOptionalDef = false; 31193323Sed isVariadic = false; 32193323Sed 33205407Srdivacky DagInit *OutDI = R->getValueAsDag("OutOperandList"); 34193323Sed 35243830Sdim if (DefInit *Init = dyn_cast<DefInit>(OutDI->getOperator())) { 36205407Srdivacky if (Init->getDef()->getName() != "outs") 37243830Sdim PrintFatalError(R->getName() + ": invalid def name for output list: use 'outs'"); 38205407Srdivacky } else 39243830Sdim PrintFatalError(R->getName() + ": invalid output list: use 'outs'"); 40218893Sdim 41205407Srdivacky NumDefs = OutDI->getNumArgs(); 42218893Sdim 43205407Srdivacky DagInit *InDI = R->getValueAsDag("InOperandList"); 44243830Sdim if (DefInit *Init = dyn_cast<DefInit>(InDI->getOperator())) { 45205407Srdivacky if (Init->getDef()->getName() != "ins") 46243830Sdim PrintFatalError(R->getName() + ": invalid def name for input list: use 'ins'"); 47205407Srdivacky } else 48243830Sdim PrintFatalError(R->getName() + ": invalid input list: use 'ins'"); 49218893Sdim 50193323Sed unsigned MIOperandNo = 0; 51193323Sed std::set<std::string> OperandNames; 52205407Srdivacky for (unsigned i = 0, e = InDI->getNumArgs()+OutDI->getNumArgs(); i != e; ++i){ 53205407Srdivacky Init *ArgInit; 54205407Srdivacky std::string ArgName; 55205407Srdivacky if (i < NumDefs) { 56205407Srdivacky ArgInit = OutDI->getArg(i); 57205407Srdivacky ArgName = OutDI->getArgName(i); 58205407Srdivacky } else { 59205407Srdivacky ArgInit = InDI->getArg(i-NumDefs); 60205407Srdivacky ArgName = InDI->getArgName(i-NumDefs); 61205407Srdivacky } 62218893Sdim 63243830Sdim DefInit *Arg = dyn_cast<DefInit>(ArgInit); 64193323Sed if (!Arg) 65243830Sdim PrintFatalError("Illegal operand for the '" + R->getName() + "' instruction!"); 66193323Sed 67193323Sed Record *Rec = Arg->getDef(); 68193323Sed std::string PrintMethod = "printOperand"; 69218893Sdim std::string EncoderMethod; 70224145Sdim std::string OperandType = "OPERAND_UNKNOWN"; 71193323Sed unsigned NumOps = 1; 72193323Sed DagInit *MIOpInfo = 0; 73224145Sdim if (Rec->isSubClassOf("RegisterOperand")) { 74193323Sed PrintMethod = Rec->getValueAsString("PrintMethod"); 75224145Sdim } else if (Rec->isSubClassOf("Operand")) { 76224145Sdim PrintMethod = Rec->getValueAsString("PrintMethod"); 77224145Sdim OperandType = Rec->getValueAsString("OperandType"); 78218893Sdim // If there is an explicit encoder method, use it. 79218893Sdim EncoderMethod = Rec->getValueAsString("EncoderMethod"); 80193323Sed MIOpInfo = Rec->getValueAsDag("MIOperandInfo"); 81201360Srdivacky 82193323Sed // Verify that MIOpInfo has an 'ops' root value. 83243830Sdim if (!isa<DefInit>(MIOpInfo->getOperator()) || 84243830Sdim cast<DefInit>(MIOpInfo->getOperator())->getDef()->getName() != "ops") 85243830Sdim PrintFatalError("Bad value for MIOperandInfo in operand '" + Rec->getName() + 86243830Sdim "'\n"); 87193323Sed 88193323Sed // If we have MIOpInfo, then we have #operands equal to number of entries 89193323Sed // in MIOperandInfo. 90193323Sed if (unsigned NumArgs = MIOpInfo->getNumArgs()) 91193323Sed NumOps = NumArgs; 92193323Sed 93263508Sdim if (Rec->isSubClassOf("PredicateOp")) 94193323Sed isPredicable = true; 95193323Sed else if (Rec->isSubClassOf("OptionalDefOperand")) 96193323Sed hasOptionalDef = true; 97193323Sed } else if (Rec->getName() == "variable_ops") { 98193323Sed isVariadic = true; 99193323Sed continue; 100224145Sdim } else if (Rec->isSubClassOf("RegisterClass")) { 101224145Sdim OperandType = "OPERAND_REGISTER"; 102224145Sdim } else if (!Rec->isSubClassOf("PointerLikeRegClass") && 103243830Sdim !Rec->isSubClassOf("unknown_class")) 104243830Sdim PrintFatalError("Unknown operand class '" + Rec->getName() + 105243830Sdim "' in '" + R->getName() + "' instruction!"); 106193323Sed 107193323Sed // Check that the operand has a name and that it's unique. 108205407Srdivacky if (ArgName.empty()) 109243830Sdim PrintFatalError("In instruction '" + R->getName() + "', operand #" + utostr(i) + 110243830Sdim " has no name!"); 111205407Srdivacky if (!OperandNames.insert(ArgName).second) 112243830Sdim PrintFatalError("In instruction '" + R->getName() + "', operand #" + utostr(i) + 113243830Sdim " has the same name as a previous operand!"); 114201360Srdivacky 115218893Sdim OperandList.push_back(OperandInfo(Rec, ArgName, PrintMethod, EncoderMethod, 116224145Sdim OperandType, MIOperandNo, NumOps, 117224145Sdim MIOpInfo)); 118193323Sed MIOperandNo += NumOps; 119193323Sed } 120193323Sed 121201360Srdivacky 122218893Sdim // Make sure the constraints list for each operand is large enough to hold 123218893Sdim // constraint info, even if none is present. 124218893Sdim for (unsigned i = 0, e = OperandList.size(); i != e; ++i) 125218893Sdim OperandList[i].Constraints.resize(OperandList[i].MINumOperands); 126218893Sdim} 127193323Sed 128193323Sed 129193323Sed/// getOperandNamed - Return the index of the operand with the specified 130193323Sed/// non-empty name. If the instruction does not have an operand with the 131243830Sdim/// specified name, abort. 132193323Sed/// 133218893Sdimunsigned CGIOperandList::getOperandNamed(StringRef Name) const { 134218893Sdim unsigned OpIdx; 135218893Sdim if (hasOperandNamed(Name, OpIdx)) return OpIdx; 136243830Sdim PrintFatalError("'" + TheDef->getName() + "' does not have an operand named '$" + 137243830Sdim Name.str() + "'!"); 138218893Sdim} 139218893Sdim 140218893Sdim/// hasOperandNamed - Query whether the instruction has an operand of the 141218893Sdim/// given name. If so, return true and set OpIdx to the index of the 142218893Sdim/// operand. Otherwise, return false. 143218893Sdimbool CGIOperandList::hasOperandNamed(StringRef Name, unsigned &OpIdx) const { 144193323Sed assert(!Name.empty() && "Cannot search for operand with no name!"); 145193323Sed for (unsigned i = 0, e = OperandList.size(); i != e; ++i) 146218893Sdim if (OperandList[i].Name == Name) { 147218893Sdim OpIdx = i; 148218893Sdim return true; 149218893Sdim } 150218893Sdim return false; 151193323Sed} 152193323Sed 153201360Srdivackystd::pair<unsigned,unsigned> 154218893SdimCGIOperandList::ParseOperandName(const std::string &Op, bool AllowWholeOp) { 155193323Sed if (Op.empty() || Op[0] != '$') 156243830Sdim PrintFatalError(TheDef->getName() + ": Illegal operand name: '" + Op + "'"); 157201360Srdivacky 158193323Sed std::string OpName = Op.substr(1); 159193323Sed std::string SubOpName; 160201360Srdivacky 161193323Sed // Check to see if this is $foo.bar. 162193323Sed std::string::size_type DotIdx = OpName.find_first_of("."); 163193323Sed if (DotIdx != std::string::npos) { 164193323Sed SubOpName = OpName.substr(DotIdx+1); 165193323Sed if (SubOpName.empty()) 166243830Sdim PrintFatalError(TheDef->getName() + ": illegal empty suboperand name in '" +Op +"'"); 167193323Sed OpName = OpName.substr(0, DotIdx); 168193323Sed } 169201360Srdivacky 170193323Sed unsigned OpIdx = getOperandNamed(OpName); 171193323Sed 172193323Sed if (SubOpName.empty()) { // If no suboperand name was specified: 173193323Sed // If one was needed, throw. 174193323Sed if (OperandList[OpIdx].MINumOperands > 1 && !AllowWholeOp && 175193323Sed SubOpName.empty()) 176243830Sdim PrintFatalError(TheDef->getName() + ": Illegal to refer to" 177243830Sdim " whole operand part of complex operand '" + Op + "'"); 178201360Srdivacky 179193323Sed // Otherwise, return the operand. 180193323Sed return std::make_pair(OpIdx, 0U); 181193323Sed } 182201360Srdivacky 183193323Sed // Find the suboperand number involved. 184193323Sed DagInit *MIOpInfo = OperandList[OpIdx].MIOperandInfo; 185193323Sed if (MIOpInfo == 0) 186243830Sdim PrintFatalError(TheDef->getName() + ": unknown suboperand name in '" + Op + "'"); 187201360Srdivacky 188193323Sed // Find the operand with the right name. 189193323Sed for (unsigned i = 0, e = MIOpInfo->getNumArgs(); i != e; ++i) 190193323Sed if (MIOpInfo->getArgName(i) == SubOpName) 191193323Sed return std::make_pair(OpIdx, i); 192193323Sed 193193323Sed // Otherwise, didn't find it! 194243830Sdim PrintFatalError(TheDef->getName() + ": unknown suboperand name in '" + Op + "'"); 195263508Sdim return std::make_pair(0U, 0U); 196193323Sed} 197206083Srdivacky 198218893Sdimstatic void ParseConstraint(const std::string &CStr, CGIOperandList &Ops) { 199218893Sdim // EARLY_CLOBBER: @early $reg 200218893Sdim std::string::size_type wpos = CStr.find_first_of(" \t"); 201218893Sdim std::string::size_type start = CStr.find_first_not_of(" \t"); 202218893Sdim std::string Tok = CStr.substr(start, wpos - start); 203218893Sdim if (Tok == "@earlyclobber") { 204218893Sdim std::string Name = CStr.substr(wpos+1); 205218893Sdim wpos = Name.find_first_not_of(" \t"); 206218893Sdim if (wpos == std::string::npos) 207243830Sdim PrintFatalError("Illegal format for @earlyclobber constraint: '" + CStr + "'"); 208218893Sdim Name = Name.substr(wpos); 209218893Sdim std::pair<unsigned,unsigned> Op = Ops.ParseOperandName(Name, false); 210206083Srdivacky 211218893Sdim // Build the string for the operand 212218893Sdim if (!Ops[Op.first].Constraints[Op.second].isNone()) 213243830Sdim PrintFatalError("Operand '" + Name + "' cannot have multiple constraints!"); 214218893Sdim Ops[Op.first].Constraints[Op.second] = 215218893Sdim CGIOperandList::ConstraintInfo::getEarlyClobber(); 216218893Sdim return; 217218893Sdim } 218218893Sdim 219218893Sdim // Only other constraint is "TIED_TO" for now. 220218893Sdim std::string::size_type pos = CStr.find_first_of('='); 221218893Sdim assert(pos != std::string::npos && "Unrecognized constraint"); 222218893Sdim start = CStr.find_first_not_of(" \t"); 223218893Sdim std::string Name = CStr.substr(start, pos - start); 224218893Sdim 225218893Sdim // TIED_TO: $src1 = $dst 226218893Sdim wpos = Name.find_first_of(" \t"); 227218893Sdim if (wpos == std::string::npos) 228243830Sdim PrintFatalError("Illegal format for tied-to constraint: '" + CStr + "'"); 229218893Sdim std::string DestOpName = Name.substr(0, wpos); 230218893Sdim std::pair<unsigned,unsigned> DestOp = Ops.ParseOperandName(DestOpName, false); 231218893Sdim 232218893Sdim Name = CStr.substr(pos+1); 233218893Sdim wpos = Name.find_first_not_of(" \t"); 234218893Sdim if (wpos == std::string::npos) 235243830Sdim PrintFatalError("Illegal format for tied-to constraint: '" + CStr + "'"); 236218893Sdim 237243830Sdim std::string SrcOpName = Name.substr(wpos); 238243830Sdim std::pair<unsigned,unsigned> SrcOp = Ops.ParseOperandName(SrcOpName, false); 239243830Sdim if (SrcOp > DestOp) { 240243830Sdim std::swap(SrcOp, DestOp); 241243830Sdim std::swap(SrcOpName, DestOpName); 242243830Sdim } 243218893Sdim 244218893Sdim unsigned FlatOpNo = Ops.getFlattenedOperandNumber(SrcOp); 245218893Sdim 246218893Sdim if (!Ops[DestOp.first].Constraints[DestOp.second].isNone()) 247243830Sdim PrintFatalError("Operand '" + DestOpName + 248243830Sdim "' cannot have multiple constraints!"); 249218893Sdim Ops[DestOp.first].Constraints[DestOp.second] = 250234353Sdim CGIOperandList::ConstraintInfo::getTied(FlatOpNo); 251218893Sdim} 252218893Sdim 253218893Sdimstatic void ParseConstraints(const std::string &CStr, CGIOperandList &Ops) { 254218893Sdim if (CStr.empty()) return; 255218893Sdim 256218893Sdim const std::string delims(","); 257218893Sdim std::string::size_type bidx, eidx; 258218893Sdim 259218893Sdim bidx = CStr.find_first_not_of(delims); 260218893Sdim while (bidx != std::string::npos) { 261218893Sdim eidx = CStr.find_first_of(delims, bidx); 262218893Sdim if (eidx == std::string::npos) 263218893Sdim eidx = CStr.length(); 264218893Sdim 265218893Sdim ParseConstraint(CStr.substr(bidx, eidx - bidx), Ops); 266218893Sdim bidx = CStr.find_first_not_of(delims, eidx); 267218893Sdim } 268218893Sdim} 269218893Sdim 270218893Sdimvoid CGIOperandList::ProcessDisableEncoding(std::string DisableEncoding) { 271218893Sdim while (1) { 272226633Sdim std::pair<StringRef, StringRef> P = getToken(DisableEncoding, " ,\t"); 273226633Sdim std::string OpName = P.first; 274226633Sdim DisableEncoding = P.second; 275218893Sdim if (OpName.empty()) break; 276218893Sdim 277218893Sdim // Figure out which operand this is. 278218893Sdim std::pair<unsigned,unsigned> Op = ParseOperandName(OpName, false); 279218893Sdim 280218893Sdim // Mark the operand as not-to-be encoded. 281218893Sdim if (Op.second >= OperandList[Op.first].DoNotEncode.size()) 282218893Sdim OperandList[Op.first].DoNotEncode.resize(Op.second+1); 283218893Sdim OperandList[Op.first].DoNotEncode[Op.second] = true; 284218893Sdim } 285218893Sdim 286218893Sdim} 287218893Sdim 288218893Sdim//===----------------------------------------------------------------------===// 289218893Sdim// CodeGenInstruction Implementation 290218893Sdim//===----------------------------------------------------------------------===// 291218893Sdim 292243830SdimCodeGenInstruction::CodeGenInstruction(Record *R) 293243830Sdim : TheDef(R), Operands(R), InferredFrom(0) { 294218893Sdim Namespace = R->getValueAsString("Namespace"); 295218893Sdim AsmString = R->getValueAsString("AsmString"); 296218893Sdim 297218893Sdim isReturn = R->getValueAsBit("isReturn"); 298218893Sdim isBranch = R->getValueAsBit("isBranch"); 299218893Sdim isIndirectBranch = R->getValueAsBit("isIndirectBranch"); 300218893Sdim isCompare = R->getValueAsBit("isCompare"); 301218893Sdim isMoveImm = R->getValueAsBit("isMoveImm"); 302221345Sdim isBitcast = R->getValueAsBit("isBitcast"); 303239462Sdim isSelect = R->getValueAsBit("isSelect"); 304218893Sdim isBarrier = R->getValueAsBit("isBarrier"); 305218893Sdim isCall = R->getValueAsBit("isCall"); 306218893Sdim canFoldAsLoad = R->getValueAsBit("canFoldAsLoad"); 307218893Sdim isPredicable = Operands.isPredicable || R->getValueAsBit("isPredicable"); 308218893Sdim isConvertibleToThreeAddress = R->getValueAsBit("isConvertibleToThreeAddress"); 309218893Sdim isCommutable = R->getValueAsBit("isCommutable"); 310218893Sdim isTerminator = R->getValueAsBit("isTerminator"); 311218893Sdim isReMaterializable = R->getValueAsBit("isReMaterializable"); 312218893Sdim hasDelaySlot = R->getValueAsBit("hasDelaySlot"); 313218893Sdim usesCustomInserter = R->getValueAsBit("usesCustomInserter"); 314226633Sdim hasPostISelHook = R->getValueAsBit("hasPostISelHook"); 315218893Sdim hasCtrlDep = R->getValueAsBit("hasCtrlDep"); 316218893Sdim isNotDuplicable = R->getValueAsBit("isNotDuplicable"); 317243830Sdim 318243830Sdim mayLoad = R->getValueAsBitOrUnset("mayLoad", mayLoad_Unset); 319243830Sdim mayStore = R->getValueAsBitOrUnset("mayStore", mayStore_Unset); 320243830Sdim hasSideEffects = R->getValueAsBitOrUnset("hasSideEffects", 321243830Sdim hasSideEffects_Unset); 322218893Sdim neverHasSideEffects = R->getValueAsBit("neverHasSideEffects"); 323243830Sdim 324218893Sdim isAsCheapAsAMove = R->getValueAsBit("isAsCheapAsAMove"); 325218893Sdim hasExtraSrcRegAllocReq = R->getValueAsBit("hasExtraSrcRegAllocReq"); 326218893Sdim hasExtraDefRegAllocReq = R->getValueAsBit("hasExtraDefRegAllocReq"); 327224145Sdim isCodeGenOnly = R->getValueAsBit("isCodeGenOnly"); 328224145Sdim isPseudo = R->getValueAsBit("isPseudo"); 329218893Sdim ImplicitDefs = R->getValueAsListOfDefs("Defs"); 330218893Sdim ImplicitUses = R->getValueAsListOfDefs("Uses"); 331218893Sdim 332218893Sdim if (neverHasSideEffects + hasSideEffects > 1) 333243830Sdim PrintFatalError(R->getName() + ": multiple conflicting side-effect flags set!"); 334218893Sdim 335218893Sdim // Parse Constraints. 336218893Sdim ParseConstraints(R->getValueAsString("Constraints"), Operands); 337218893Sdim 338218893Sdim // Parse the DisableEncoding field. 339218893Sdim Operands.ProcessDisableEncoding(R->getValueAsString("DisableEncoding")); 340263508Sdim 341263508Sdim // First check for a ComplexDeprecationPredicate. 342263508Sdim if (R->getValue("ComplexDeprecationPredicate")) { 343263508Sdim HasComplexDeprecationPredicate = true; 344263508Sdim DeprecatedReason = R->getValueAsString("ComplexDeprecationPredicate"); 345263508Sdim } else if (RecordVal *Dep = R->getValue("DeprecatedFeatureMask")) { 346263508Sdim // Check if we have a Subtarget feature mask. 347263508Sdim HasComplexDeprecationPredicate = false; 348263508Sdim DeprecatedReason = Dep->getValue()->getAsString(); 349263508Sdim } else { 350263508Sdim // This instruction isn't deprecated. 351263508Sdim HasComplexDeprecationPredicate = false; 352263508Sdim DeprecatedReason = ""; 353263508Sdim } 354218893Sdim} 355218893Sdim 356206083Srdivacky/// HasOneImplicitDefWithKnownVT - If the instruction has at least one 357206083Srdivacky/// implicit def and it has a known VT, return the VT, otherwise return 358206083Srdivacky/// MVT::Other. 359206083SrdivackyMVT::SimpleValueType CodeGenInstruction:: 360206083SrdivackyHasOneImplicitDefWithKnownVT(const CodeGenTarget &TargetInfo) const { 361206083Srdivacky if (ImplicitDefs.empty()) return MVT::Other; 362218893Sdim 363206083Srdivacky // Check to see if the first implicit def has a resolvable type. 364206083Srdivacky Record *FirstImplicitDef = ImplicitDefs[0]; 365206083Srdivacky assert(FirstImplicitDef->isSubClassOf("Register")); 366218893Sdim const std::vector<MVT::SimpleValueType> &RegVTs = 367206083Srdivacky TargetInfo.getRegisterVTs(FirstImplicitDef); 368206083Srdivacky if (RegVTs.size() == 1) 369206083Srdivacky return RegVTs[0]; 370206083Srdivacky return MVT::Other; 371206083Srdivacky} 372206083Srdivacky 373218893Sdim 374218893Sdim/// FlattenAsmStringVariants - Flatten the specified AsmString to only 375218893Sdim/// include text from the specified variant, returning the new string. 376218893Sdimstd::string CodeGenInstruction:: 377218893SdimFlattenAsmStringVariants(StringRef Cur, unsigned Variant) { 378218893Sdim std::string Res = ""; 379218893Sdim 380218893Sdim for (;;) { 381218893Sdim // Find the start of the next variant string. 382218893Sdim size_t VariantsStart = 0; 383218893Sdim for (size_t e = Cur.size(); VariantsStart != e; ++VariantsStart) 384218893Sdim if (Cur[VariantsStart] == '{' && 385218893Sdim (VariantsStart == 0 || (Cur[VariantsStart-1] != '$' && 386218893Sdim Cur[VariantsStart-1] != '\\'))) 387218893Sdim break; 388218893Sdim 389218893Sdim // Add the prefix to the result. 390218893Sdim Res += Cur.slice(0, VariantsStart); 391218893Sdim if (VariantsStart == Cur.size()) 392218893Sdim break; 393218893Sdim 394218893Sdim ++VariantsStart; // Skip the '{'. 395218893Sdim 396218893Sdim // Scan to the end of the variants string. 397218893Sdim size_t VariantsEnd = VariantsStart; 398218893Sdim unsigned NestedBraces = 1; 399218893Sdim for (size_t e = Cur.size(); VariantsEnd != e; ++VariantsEnd) { 400218893Sdim if (Cur[VariantsEnd] == '}' && Cur[VariantsEnd-1] != '\\') { 401218893Sdim if (--NestedBraces == 0) 402218893Sdim break; 403218893Sdim } else if (Cur[VariantsEnd] == '{') 404218893Sdim ++NestedBraces; 405218893Sdim } 406218893Sdim 407218893Sdim // Select the Nth variant (or empty). 408218893Sdim StringRef Selection = Cur.slice(VariantsStart, VariantsEnd); 409218893Sdim for (unsigned i = 0; i != Variant; ++i) 410218893Sdim Selection = Selection.split('|').second; 411218893Sdim Res += Selection.split('|').first; 412218893Sdim 413218893Sdim assert(VariantsEnd != Cur.size() && 414218893Sdim "Unterminated variants in assembly string!"); 415218893Sdim Cur = Cur.substr(VariantsEnd + 1); 416218893Sdim } 417218893Sdim 418218893Sdim return Res; 419218893Sdim} 420218893Sdim 421218893Sdim 422218893Sdim//===----------------------------------------------------------------------===// 423218893Sdim/// CodeGenInstAlias Implementation 424218893Sdim//===----------------------------------------------------------------------===// 425218893Sdim 426218893Sdim/// tryAliasOpMatch - This is a helper function for the CodeGenInstAlias 427218893Sdim/// constructor. It checks if an argument in an InstAlias pattern matches 428218893Sdim/// the corresponding operand of the instruction. It returns true on a 429218893Sdim/// successful match, with ResOp set to the result operand to be used. 430218893Sdimbool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo, 431218893Sdim Record *InstOpRec, bool hasSubOps, 432243830Sdim ArrayRef<SMLoc> Loc, CodeGenTarget &T, 433218893Sdim ResultOperand &ResOp) { 434218893Sdim Init *Arg = Result->getArg(AliasOpNo); 435243830Sdim DefInit *ADI = dyn_cast<DefInit>(Arg); 436218893Sdim 437218893Sdim if (ADI && ADI->getDef() == InstOpRec) { 438218893Sdim // If the operand is a record, it must have a name, and the record type 439218893Sdim // must match up with the instruction's argument type. 440218893Sdim if (Result->getArgName(AliasOpNo).empty()) 441243830Sdim PrintFatalError(Loc, "result argument #" + utostr(AliasOpNo) + 442218893Sdim " must have a name!"); 443218893Sdim ResOp = ResultOperand(Result->getArgName(AliasOpNo), ADI->getDef()); 444218893Sdim return true; 445218893Sdim } 446218893Sdim 447234353Sdim // For register operands, the source register class can be a subclass 448234353Sdim // of the instruction register class, not just an exact match. 449234353Sdim if (ADI && ADI->getDef()->isSubClassOf("RegisterClass")) { 450234353Sdim if (!InstOpRec->isSubClassOf("RegisterClass")) 451234353Sdim return false; 452234353Sdim if (!T.getRegisterClass(InstOpRec) 453234353Sdim .hasSubClass(&T.getRegisterClass(ADI->getDef()))) 454234353Sdim return false; 455234353Sdim ResOp = ResultOperand(Result->getArgName(AliasOpNo), ADI->getDef()); 456234353Sdim return true; 457234353Sdim } 458234353Sdim 459218893Sdim // Handle explicit registers. 460218893Sdim if (ADI && ADI->getDef()->isSubClassOf("Register")) { 461226633Sdim if (InstOpRec->isSubClassOf("OptionalDefOperand")) { 462226633Sdim DagInit *DI = InstOpRec->getValueAsDag("MIOperandInfo"); 463226633Sdim // The operand info should only have a single (register) entry. We 464226633Sdim // want the register class of it. 465243830Sdim InstOpRec = cast<DefInit>(DI->getArg(0))->getDef(); 466226633Sdim } 467226633Sdim 468224145Sdim if (InstOpRec->isSubClassOf("RegisterOperand")) 469224145Sdim InstOpRec = InstOpRec->getValueAsDef("RegClass"); 470224145Sdim 471218893Sdim if (!InstOpRec->isSubClassOf("RegisterClass")) 472218893Sdim return false; 473218893Sdim 474224145Sdim if (!T.getRegisterClass(InstOpRec) 475224145Sdim .contains(T.getRegBank().getReg(ADI->getDef()))) 476243830Sdim PrintFatalError(Loc, "fixed register " + ADI->getDef()->getName() + 477243830Sdim " is not a member of the " + InstOpRec->getName() + 478243830Sdim " register class!"); 479218893Sdim 480218893Sdim if (!Result->getArgName(AliasOpNo).empty()) 481243830Sdim PrintFatalError(Loc, "result fixed register argument must " 482243830Sdim "not have a name!"); 483218893Sdim 484218893Sdim ResOp = ResultOperand(ADI->getDef()); 485218893Sdim return true; 486218893Sdim } 487218893Sdim 488218893Sdim // Handle "zero_reg" for optional def operands. 489218893Sdim if (ADI && ADI->getDef()->getName() == "zero_reg") { 490218893Sdim 491218893Sdim // Check if this is an optional def. 492234353Sdim // Tied operands where the source is a sub-operand of a complex operand 493234353Sdim // need to represent both operands in the alias destination instruction. 494234353Sdim // Allow zero_reg for the tied portion. This can and should go away once 495234353Sdim // the MC representation of things doesn't use tied operands at all. 496234353Sdim //if (!InstOpRec->isSubClassOf("OptionalDefOperand")) 497234353Sdim // throw TGError(Loc, "reg0 used for result that is not an " 498234353Sdim // "OptionalDefOperand!"); 499218893Sdim 500218893Sdim ResOp = ResultOperand(static_cast<Record*>(0)); 501218893Sdim return true; 502218893Sdim } 503218893Sdim 504234353Sdim // Literal integers. 505243830Sdim if (IntInit *II = dyn_cast<IntInit>(Arg)) { 506218893Sdim if (hasSubOps || !InstOpRec->isSubClassOf("Operand")) 507218893Sdim return false; 508218893Sdim // Integer arguments can't have names. 509218893Sdim if (!Result->getArgName(AliasOpNo).empty()) 510243830Sdim PrintFatalError(Loc, "result argument #" + utostr(AliasOpNo) + 511243830Sdim " must not have a name!"); 512218893Sdim ResOp = ResultOperand(II->getValue()); 513218893Sdim return true; 514218893Sdim } 515218893Sdim 516234353Sdim // If both are Operands with the same MVT, allow the conversion. It's 517234353Sdim // up to the user to make sure the values are appropriate, just like 518234353Sdim // for isel Pat's. 519234353Sdim if (InstOpRec->isSubClassOf("Operand") && 520234353Sdim ADI->getDef()->isSubClassOf("Operand")) { 521234353Sdim // FIXME: What other attributes should we check here? Identical 522234353Sdim // MIOperandInfo perhaps? 523234353Sdim if (InstOpRec->getValueInit("Type") != ADI->getDef()->getValueInit("Type")) 524234353Sdim return false; 525234353Sdim ResOp = ResultOperand(Result->getArgName(AliasOpNo), ADI->getDef()); 526234353Sdim return true; 527234353Sdim } 528234353Sdim 529218893Sdim return false; 530218893Sdim} 531218893Sdim 532218893SdimCodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T) : TheDef(R) { 533218893Sdim AsmString = R->getValueAsString("AsmString"); 534218893Sdim Result = R->getValueAsDag("ResultInst"); 535218893Sdim 536218893Sdim // Verify that the root of the result is an instruction. 537243830Sdim DefInit *DI = dyn_cast<DefInit>(Result->getOperator()); 538218893Sdim if (DI == 0 || !DI->getDef()->isSubClassOf("Instruction")) 539243830Sdim PrintFatalError(R->getLoc(), 540243830Sdim "result of inst alias should be an instruction"); 541218893Sdim 542218893Sdim ResultInst = &T.getInstruction(DI->getDef()); 543218893Sdim 544218893Sdim // NameClass - If argument names are repeated, we need to verify they have 545218893Sdim // the same class. 546218893Sdim StringMap<Record*> NameClass; 547218893Sdim for (unsigned i = 0, e = Result->getNumArgs(); i != e; ++i) { 548243830Sdim DefInit *ADI = dyn_cast<DefInit>(Result->getArg(i)); 549218893Sdim if (!ADI || Result->getArgName(i).empty()) 550218893Sdim continue; 551218893Sdim // Verify we don't have something like: (someinst GR16:$foo, GR32:$foo) 552218893Sdim // $foo can exist multiple times in the result list, but it must have the 553218893Sdim // same type. 554218893Sdim Record *&Entry = NameClass[Result->getArgName(i)]; 555218893Sdim if (Entry && Entry != ADI->getDef()) 556243830Sdim PrintFatalError(R->getLoc(), "result value $" + Result->getArgName(i) + 557243830Sdim " is both " + Entry->getName() + " and " + 558243830Sdim ADI->getDef()->getName() + "!"); 559218893Sdim Entry = ADI->getDef(); 560218893Sdim } 561218893Sdim 562218893Sdim // Decode and validate the arguments of the result. 563218893Sdim unsigned AliasOpNo = 0; 564218893Sdim for (unsigned i = 0, e = ResultInst->Operands.size(); i != e; ++i) { 565218893Sdim 566234353Sdim // Tied registers don't have an entry in the result dag unless they're part 567234353Sdim // of a complex operand, in which case we include them anyways, as we 568234353Sdim // don't have any other way to specify the whole operand. 569234353Sdim if (ResultInst->Operands[i].MINumOperands == 1 && 570234353Sdim ResultInst->Operands[i].getTiedRegister() != -1) 571218893Sdim continue; 572218893Sdim 573218893Sdim if (AliasOpNo >= Result->getNumArgs()) 574243830Sdim PrintFatalError(R->getLoc(), "not enough arguments for instruction!"); 575218893Sdim 576218893Sdim Record *InstOpRec = ResultInst->Operands[i].Rec; 577218893Sdim unsigned NumSubOps = ResultInst->Operands[i].MINumOperands; 578218893Sdim ResultOperand ResOp(static_cast<int64_t>(0)); 579218893Sdim if (tryAliasOpMatch(Result, AliasOpNo, InstOpRec, (NumSubOps > 1), 580218893Sdim R->getLoc(), T, ResOp)) { 581239462Sdim // If this is a simple operand, or a complex operand with a custom match 582239462Sdim // class, then we can match is verbatim. 583239462Sdim if (NumSubOps == 1 || 584239462Sdim (InstOpRec->getValue("ParserMatchClass") && 585239462Sdim InstOpRec->getValueAsDef("ParserMatchClass") 586239462Sdim ->getValueAsString("Name") != "Imm")) { 587239462Sdim ResultOperands.push_back(ResOp); 588239462Sdim ResultInstOperandIndex.push_back(std::make_pair(i, -1)); 589239462Sdim ++AliasOpNo; 590239462Sdim 591239462Sdim // Otherwise, we need to match each of the suboperands individually. 592239462Sdim } else { 593239462Sdim DagInit *MIOI = ResultInst->Operands[i].MIOperandInfo; 594239462Sdim for (unsigned SubOp = 0; SubOp != NumSubOps; ++SubOp) { 595243830Sdim Record *SubRec = cast<DefInit>(MIOI->getArg(SubOp))->getDef(); 596239462Sdim 597239462Sdim // Take care to instantiate each of the suboperands with the correct 598239462Sdim // nomenclature: $foo.bar 599239462Sdim ResultOperands.push_back( 600239462Sdim ResultOperand(Result->getArgName(AliasOpNo) + "." + 601239462Sdim MIOI->getArgName(SubOp), SubRec)); 602239462Sdim ResultInstOperandIndex.push_back(std::make_pair(i, SubOp)); 603239462Sdim } 604239462Sdim ++AliasOpNo; 605239462Sdim } 606218893Sdim continue; 607218893Sdim } 608218893Sdim 609218893Sdim // If the argument did not match the instruction operand, and the operand 610218893Sdim // is composed of multiple suboperands, try matching the suboperands. 611218893Sdim if (NumSubOps > 1) { 612218893Sdim DagInit *MIOI = ResultInst->Operands[i].MIOperandInfo; 613218893Sdim for (unsigned SubOp = 0; SubOp != NumSubOps; ++SubOp) { 614218893Sdim if (AliasOpNo >= Result->getNumArgs()) 615243830Sdim PrintFatalError(R->getLoc(), "not enough arguments for instruction!"); 616243830Sdim Record *SubRec = cast<DefInit>(MIOI->getArg(SubOp))->getDef(); 617218893Sdim if (tryAliasOpMatch(Result, AliasOpNo, SubRec, false, 618218893Sdim R->getLoc(), T, ResOp)) { 619218893Sdim ResultOperands.push_back(ResOp); 620218893Sdim ResultInstOperandIndex.push_back(std::make_pair(i, SubOp)); 621218893Sdim ++AliasOpNo; 622218893Sdim } else { 623243830Sdim PrintFatalError(R->getLoc(), "result argument #" + utostr(AliasOpNo) + 624218893Sdim " does not match instruction operand class " + 625218893Sdim (SubOp == 0 ? InstOpRec->getName() :SubRec->getName())); 626218893Sdim } 627218893Sdim } 628218893Sdim continue; 629218893Sdim } 630243830Sdim PrintFatalError(R->getLoc(), "result argument #" + utostr(AliasOpNo) + 631243830Sdim " does not match instruction operand class " + 632243830Sdim InstOpRec->getName()); 633218893Sdim } 634218893Sdim 635218893Sdim if (AliasOpNo != Result->getNumArgs()) 636243830Sdim PrintFatalError(R->getLoc(), "too many operands for instruction!"); 637218893Sdim} 638