CodeGenInstruction.cpp revision 234353
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" 16226633Sdim#include "llvm/TableGen/Error.h" 17226633Sdim#include "llvm/TableGen/Record.h" 18193323Sed#include "llvm/ADT/StringExtras.h" 19218893Sdim#include "llvm/ADT/StringMap.h" 20202375Srdivacky#include "llvm/ADT/STLExtras.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 35205407Srdivacky if (DefInit *Init = dynamic_cast<DefInit*>(OutDI->getOperator())) { 36205407Srdivacky if (Init->getDef()->getName() != "outs") 37205407Srdivacky throw R->getName() + ": invalid def name for output list: use 'outs'"; 38205407Srdivacky } else 39205407Srdivacky throw R->getName() + ": invalid output list: use 'outs'"; 40218893Sdim 41205407Srdivacky NumDefs = OutDI->getNumArgs(); 42218893Sdim 43205407Srdivacky DagInit *InDI = R->getValueAsDag("InOperandList"); 44205407Srdivacky if (DefInit *Init = dynamic_cast<DefInit*>(InDI->getOperator())) { 45205407Srdivacky if (Init->getDef()->getName() != "ins") 46205407Srdivacky throw R->getName() + ": invalid def name for input list: use 'ins'"; 47205407Srdivacky } else 48205407Srdivacky throw 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 63205407Srdivacky DefInit *Arg = dynamic_cast<DefInit*>(ArgInit); 64193323Sed if (!Arg) 65193323Sed throw "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. 83193323Sed if (!dynamic_cast<DefInit*>(MIOpInfo->getOperator()) || 84193323Sed dynamic_cast<DefInit*>(MIOpInfo->getOperator()) 85218893Sdim ->getDef()->getName() != "ops") 86193323Sed throw "Bad value for MIOperandInfo in operand '" + Rec->getName() + 87218893Sdim "'\n"; 88193323Sed 89193323Sed // If we have MIOpInfo, then we have #operands equal to number of entries 90193323Sed // in MIOperandInfo. 91193323Sed if (unsigned NumArgs = MIOpInfo->getNumArgs()) 92193323Sed NumOps = NumArgs; 93193323Sed 94193323Sed if (Rec->isSubClassOf("PredicateOperand")) 95193323Sed isPredicable = true; 96193323Sed else if (Rec->isSubClassOf("OptionalDefOperand")) 97193323Sed hasOptionalDef = true; 98193323Sed } else if (Rec->getName() == "variable_ops") { 99193323Sed isVariadic = true; 100193323Sed continue; 101224145Sdim } else if (Rec->isSubClassOf("RegisterClass")) { 102224145Sdim OperandType = "OPERAND_REGISTER"; 103224145Sdim } else if (!Rec->isSubClassOf("PointerLikeRegClass") && 104218893Sdim Rec->getName() != "unknown") 105193323Sed throw "Unknown operand class '" + Rec->getName() + 106218893Sdim "' in '" + R->getName() + "' instruction!"; 107193323Sed 108193323Sed // Check that the operand has a name and that it's unique. 109205407Srdivacky if (ArgName.empty()) 110193323Sed throw "In instruction '" + R->getName() + "', operand #" + utostr(i) + 111218893Sdim " has no name!"; 112205407Srdivacky if (!OperandNames.insert(ArgName).second) 113193323Sed throw "In instruction '" + R->getName() + "', operand #" + utostr(i) + 114218893Sdim " has the same name as a previous operand!"; 115201360Srdivacky 116218893Sdim OperandList.push_back(OperandInfo(Rec, ArgName, PrintMethod, EncoderMethod, 117224145Sdim OperandType, MIOperandNo, NumOps, 118224145Sdim MIOpInfo)); 119193323Sed MIOperandNo += NumOps; 120193323Sed } 121193323Sed 122201360Srdivacky 123218893Sdim // Make sure the constraints list for each operand is large enough to hold 124218893Sdim // constraint info, even if none is present. 125218893Sdim for (unsigned i = 0, e = OperandList.size(); i != e; ++i) 126218893Sdim OperandList[i].Constraints.resize(OperandList[i].MINumOperands); 127218893Sdim} 128193323Sed 129193323Sed 130193323Sed/// getOperandNamed - Return the index of the operand with the specified 131193323Sed/// non-empty name. If the instruction does not have an operand with the 132193323Sed/// specified name, throw an exception. 133193323Sed/// 134218893Sdimunsigned CGIOperandList::getOperandNamed(StringRef Name) const { 135218893Sdim unsigned OpIdx; 136218893Sdim if (hasOperandNamed(Name, OpIdx)) return OpIdx; 137218893Sdim throw "'" + TheDef->getName() + "' does not have an operand named '$" + 138218893Sdim Name.str() + "'!"; 139218893Sdim} 140218893Sdim 141218893Sdim/// hasOperandNamed - Query whether the instruction has an operand of the 142218893Sdim/// given name. If so, return true and set OpIdx to the index of the 143218893Sdim/// operand. Otherwise, return false. 144218893Sdimbool CGIOperandList::hasOperandNamed(StringRef Name, unsigned &OpIdx) const { 145193323Sed assert(!Name.empty() && "Cannot search for operand with no name!"); 146193323Sed for (unsigned i = 0, e = OperandList.size(); i != e; ++i) 147218893Sdim if (OperandList[i].Name == Name) { 148218893Sdim OpIdx = i; 149218893Sdim return true; 150218893Sdim } 151218893Sdim return false; 152193323Sed} 153193323Sed 154201360Srdivackystd::pair<unsigned,unsigned> 155218893SdimCGIOperandList::ParseOperandName(const std::string &Op, bool AllowWholeOp) { 156193323Sed if (Op.empty() || Op[0] != '$') 157193323Sed throw TheDef->getName() + ": Illegal operand name: '" + Op + "'"; 158201360Srdivacky 159193323Sed std::string OpName = Op.substr(1); 160193323Sed std::string SubOpName; 161201360Srdivacky 162193323Sed // Check to see if this is $foo.bar. 163193323Sed std::string::size_type DotIdx = OpName.find_first_of("."); 164193323Sed if (DotIdx != std::string::npos) { 165193323Sed SubOpName = OpName.substr(DotIdx+1); 166193323Sed if (SubOpName.empty()) 167193323Sed throw TheDef->getName() + ": illegal empty suboperand name in '" +Op +"'"; 168193323Sed OpName = OpName.substr(0, DotIdx); 169193323Sed } 170201360Srdivacky 171193323Sed unsigned OpIdx = getOperandNamed(OpName); 172193323Sed 173193323Sed if (SubOpName.empty()) { // If no suboperand name was specified: 174193323Sed // If one was needed, throw. 175193323Sed if (OperandList[OpIdx].MINumOperands > 1 && !AllowWholeOp && 176193323Sed SubOpName.empty()) 177193323Sed throw TheDef->getName() + ": Illegal to refer to" 178218893Sdim " whole operand part of complex operand '" + Op + "'"; 179201360Srdivacky 180193323Sed // Otherwise, return the operand. 181193323Sed return std::make_pair(OpIdx, 0U); 182193323Sed } 183201360Srdivacky 184193323Sed // Find the suboperand number involved. 185193323Sed DagInit *MIOpInfo = OperandList[OpIdx].MIOperandInfo; 186193323Sed if (MIOpInfo == 0) 187193323Sed throw TheDef->getName() + ": unknown suboperand name in '" + Op + "'"; 188201360Srdivacky 189193323Sed // Find the operand with the right name. 190193323Sed for (unsigned i = 0, e = MIOpInfo->getNumArgs(); i != e; ++i) 191193323Sed if (MIOpInfo->getArgName(i) == SubOpName) 192193323Sed return std::make_pair(OpIdx, i); 193193323Sed 194193323Sed // Otherwise, didn't find it! 195193323Sed throw TheDef->getName() + ": unknown suboperand name in '" + Op + "'"; 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) 207218893Sdim throw "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()) 213218893Sdim throw "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) 228218893Sdim throw "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) 235218893Sdim throw "Illegal format for tied-to constraint: '" + CStr + "'"; 236218893Sdim 237218893Sdim std::pair<unsigned,unsigned> SrcOp = 238218893Sdim Ops.ParseOperandName(Name.substr(wpos), false); 239218893Sdim if (SrcOp > DestOp) 240218893Sdim throw "Illegal tied-to operand constraint '" + CStr + "'"; 241218893Sdim 242218893Sdim 243218893Sdim unsigned FlatOpNo = Ops.getFlattenedOperandNumber(SrcOp); 244218893Sdim 245218893Sdim if (!Ops[DestOp.first].Constraints[DestOp.second].isNone()) 246218893Sdim throw "Operand '" + DestOpName + "' cannot have multiple constraints!"; 247218893Sdim Ops[DestOp.first].Constraints[DestOp.second] = 248234353Sdim CGIOperandList::ConstraintInfo::getTied(FlatOpNo); 249218893Sdim} 250218893Sdim 251218893Sdimstatic void ParseConstraints(const std::string &CStr, CGIOperandList &Ops) { 252218893Sdim if (CStr.empty()) return; 253218893Sdim 254218893Sdim const std::string delims(","); 255218893Sdim std::string::size_type bidx, eidx; 256218893Sdim 257218893Sdim bidx = CStr.find_first_not_of(delims); 258218893Sdim while (bidx != std::string::npos) { 259218893Sdim eidx = CStr.find_first_of(delims, bidx); 260218893Sdim if (eidx == std::string::npos) 261218893Sdim eidx = CStr.length(); 262218893Sdim 263218893Sdim ParseConstraint(CStr.substr(bidx, eidx - bidx), Ops); 264218893Sdim bidx = CStr.find_first_not_of(delims, eidx); 265218893Sdim } 266218893Sdim} 267218893Sdim 268218893Sdimvoid CGIOperandList::ProcessDisableEncoding(std::string DisableEncoding) { 269218893Sdim while (1) { 270226633Sdim std::pair<StringRef, StringRef> P = getToken(DisableEncoding, " ,\t"); 271226633Sdim std::string OpName = P.first; 272226633Sdim DisableEncoding = P.second; 273218893Sdim if (OpName.empty()) break; 274218893Sdim 275218893Sdim // Figure out which operand this is. 276218893Sdim std::pair<unsigned,unsigned> Op = ParseOperandName(OpName, false); 277218893Sdim 278218893Sdim // Mark the operand as not-to-be encoded. 279218893Sdim if (Op.second >= OperandList[Op.first].DoNotEncode.size()) 280218893Sdim OperandList[Op.first].DoNotEncode.resize(Op.second+1); 281218893Sdim OperandList[Op.first].DoNotEncode[Op.second] = true; 282218893Sdim } 283218893Sdim 284218893Sdim} 285218893Sdim 286218893Sdim//===----------------------------------------------------------------------===// 287218893Sdim// CodeGenInstruction Implementation 288218893Sdim//===----------------------------------------------------------------------===// 289218893Sdim 290218893SdimCodeGenInstruction::CodeGenInstruction(Record *R) : TheDef(R), Operands(R) { 291218893Sdim Namespace = R->getValueAsString("Namespace"); 292218893Sdim AsmString = R->getValueAsString("AsmString"); 293218893Sdim 294218893Sdim isReturn = R->getValueAsBit("isReturn"); 295218893Sdim isBranch = R->getValueAsBit("isBranch"); 296218893Sdim isIndirectBranch = R->getValueAsBit("isIndirectBranch"); 297218893Sdim isCompare = R->getValueAsBit("isCompare"); 298218893Sdim isMoveImm = R->getValueAsBit("isMoveImm"); 299221345Sdim isBitcast = R->getValueAsBit("isBitcast"); 300218893Sdim isBarrier = R->getValueAsBit("isBarrier"); 301218893Sdim isCall = R->getValueAsBit("isCall"); 302218893Sdim canFoldAsLoad = R->getValueAsBit("canFoldAsLoad"); 303218893Sdim mayLoad = R->getValueAsBit("mayLoad"); 304218893Sdim mayStore = R->getValueAsBit("mayStore"); 305218893Sdim isPredicable = Operands.isPredicable || R->getValueAsBit("isPredicable"); 306218893Sdim isConvertibleToThreeAddress = R->getValueAsBit("isConvertibleToThreeAddress"); 307218893Sdim isCommutable = R->getValueAsBit("isCommutable"); 308218893Sdim isTerminator = R->getValueAsBit("isTerminator"); 309218893Sdim isReMaterializable = R->getValueAsBit("isReMaterializable"); 310218893Sdim hasDelaySlot = R->getValueAsBit("hasDelaySlot"); 311218893Sdim usesCustomInserter = R->getValueAsBit("usesCustomInserter"); 312226633Sdim hasPostISelHook = R->getValueAsBit("hasPostISelHook"); 313218893Sdim hasCtrlDep = R->getValueAsBit("hasCtrlDep"); 314218893Sdim isNotDuplicable = R->getValueAsBit("isNotDuplicable"); 315218893Sdim hasSideEffects = R->getValueAsBit("hasSideEffects"); 316218893Sdim neverHasSideEffects = R->getValueAsBit("neverHasSideEffects"); 317218893Sdim isAsCheapAsAMove = R->getValueAsBit("isAsCheapAsAMove"); 318218893Sdim hasExtraSrcRegAllocReq = R->getValueAsBit("hasExtraSrcRegAllocReq"); 319218893Sdim hasExtraDefRegAllocReq = R->getValueAsBit("hasExtraDefRegAllocReq"); 320224145Sdim isCodeGenOnly = R->getValueAsBit("isCodeGenOnly"); 321224145Sdim isPseudo = R->getValueAsBit("isPseudo"); 322218893Sdim ImplicitDefs = R->getValueAsListOfDefs("Defs"); 323218893Sdim ImplicitUses = R->getValueAsListOfDefs("Uses"); 324218893Sdim 325218893Sdim if (neverHasSideEffects + hasSideEffects > 1) 326218893Sdim throw R->getName() + ": multiple conflicting side-effect flags set!"; 327218893Sdim 328218893Sdim // Parse Constraints. 329218893Sdim ParseConstraints(R->getValueAsString("Constraints"), Operands); 330218893Sdim 331218893Sdim // Parse the DisableEncoding field. 332218893Sdim Operands.ProcessDisableEncoding(R->getValueAsString("DisableEncoding")); 333218893Sdim} 334218893Sdim 335206083Srdivacky/// HasOneImplicitDefWithKnownVT - If the instruction has at least one 336206083Srdivacky/// implicit def and it has a known VT, return the VT, otherwise return 337206083Srdivacky/// MVT::Other. 338206083SrdivackyMVT::SimpleValueType CodeGenInstruction:: 339206083SrdivackyHasOneImplicitDefWithKnownVT(const CodeGenTarget &TargetInfo) const { 340206083Srdivacky if (ImplicitDefs.empty()) return MVT::Other; 341218893Sdim 342206083Srdivacky // Check to see if the first implicit def has a resolvable type. 343206083Srdivacky Record *FirstImplicitDef = ImplicitDefs[0]; 344206083Srdivacky assert(FirstImplicitDef->isSubClassOf("Register")); 345218893Sdim const std::vector<MVT::SimpleValueType> &RegVTs = 346206083Srdivacky TargetInfo.getRegisterVTs(FirstImplicitDef); 347206083Srdivacky if (RegVTs.size() == 1) 348206083Srdivacky return RegVTs[0]; 349206083Srdivacky return MVT::Other; 350206083Srdivacky} 351206083Srdivacky 352218893Sdim 353218893Sdim/// FlattenAsmStringVariants - Flatten the specified AsmString to only 354218893Sdim/// include text from the specified variant, returning the new string. 355218893Sdimstd::string CodeGenInstruction:: 356218893SdimFlattenAsmStringVariants(StringRef Cur, unsigned Variant) { 357218893Sdim std::string Res = ""; 358218893Sdim 359218893Sdim for (;;) { 360218893Sdim // Find the start of the next variant string. 361218893Sdim size_t VariantsStart = 0; 362218893Sdim for (size_t e = Cur.size(); VariantsStart != e; ++VariantsStart) 363218893Sdim if (Cur[VariantsStart] == '{' && 364218893Sdim (VariantsStart == 0 || (Cur[VariantsStart-1] != '$' && 365218893Sdim Cur[VariantsStart-1] != '\\'))) 366218893Sdim break; 367218893Sdim 368218893Sdim // Add the prefix to the result. 369218893Sdim Res += Cur.slice(0, VariantsStart); 370218893Sdim if (VariantsStart == Cur.size()) 371218893Sdim break; 372218893Sdim 373218893Sdim ++VariantsStart; // Skip the '{'. 374218893Sdim 375218893Sdim // Scan to the end of the variants string. 376218893Sdim size_t VariantsEnd = VariantsStart; 377218893Sdim unsigned NestedBraces = 1; 378218893Sdim for (size_t e = Cur.size(); VariantsEnd != e; ++VariantsEnd) { 379218893Sdim if (Cur[VariantsEnd] == '}' && Cur[VariantsEnd-1] != '\\') { 380218893Sdim if (--NestedBraces == 0) 381218893Sdim break; 382218893Sdim } else if (Cur[VariantsEnd] == '{') 383218893Sdim ++NestedBraces; 384218893Sdim } 385218893Sdim 386218893Sdim // Select the Nth variant (or empty). 387218893Sdim StringRef Selection = Cur.slice(VariantsStart, VariantsEnd); 388218893Sdim for (unsigned i = 0; i != Variant; ++i) 389218893Sdim Selection = Selection.split('|').second; 390218893Sdim Res += Selection.split('|').first; 391218893Sdim 392218893Sdim assert(VariantsEnd != Cur.size() && 393218893Sdim "Unterminated variants in assembly string!"); 394218893Sdim Cur = Cur.substr(VariantsEnd + 1); 395218893Sdim } 396218893Sdim 397218893Sdim return Res; 398218893Sdim} 399218893Sdim 400218893Sdim 401218893Sdim//===----------------------------------------------------------------------===// 402218893Sdim/// CodeGenInstAlias Implementation 403218893Sdim//===----------------------------------------------------------------------===// 404218893Sdim 405218893Sdim/// tryAliasOpMatch - This is a helper function for the CodeGenInstAlias 406218893Sdim/// constructor. It checks if an argument in an InstAlias pattern matches 407218893Sdim/// the corresponding operand of the instruction. It returns true on a 408218893Sdim/// successful match, with ResOp set to the result operand to be used. 409218893Sdimbool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo, 410218893Sdim Record *InstOpRec, bool hasSubOps, 411218893Sdim SMLoc Loc, CodeGenTarget &T, 412218893Sdim ResultOperand &ResOp) { 413218893Sdim Init *Arg = Result->getArg(AliasOpNo); 414218893Sdim DefInit *ADI = dynamic_cast<DefInit*>(Arg); 415218893Sdim 416218893Sdim if (ADI && ADI->getDef() == InstOpRec) { 417218893Sdim // If the operand is a record, it must have a name, and the record type 418218893Sdim // must match up with the instruction's argument type. 419218893Sdim if (Result->getArgName(AliasOpNo).empty()) 420218893Sdim throw TGError(Loc, "result argument #" + utostr(AliasOpNo) + 421218893Sdim " must have a name!"); 422218893Sdim ResOp = ResultOperand(Result->getArgName(AliasOpNo), ADI->getDef()); 423218893Sdim return true; 424218893Sdim } 425218893Sdim 426234353Sdim // For register operands, the source register class can be a subclass 427234353Sdim // of the instruction register class, not just an exact match. 428234353Sdim if (ADI && ADI->getDef()->isSubClassOf("RegisterClass")) { 429234353Sdim if (!InstOpRec->isSubClassOf("RegisterClass")) 430234353Sdim return false; 431234353Sdim if (!T.getRegisterClass(InstOpRec) 432234353Sdim .hasSubClass(&T.getRegisterClass(ADI->getDef()))) 433234353Sdim return false; 434234353Sdim ResOp = ResultOperand(Result->getArgName(AliasOpNo), ADI->getDef()); 435234353Sdim return true; 436234353Sdim } 437234353Sdim 438218893Sdim // Handle explicit registers. 439218893Sdim if (ADI && ADI->getDef()->isSubClassOf("Register")) { 440226633Sdim if (InstOpRec->isSubClassOf("OptionalDefOperand")) { 441226633Sdim DagInit *DI = InstOpRec->getValueAsDag("MIOperandInfo"); 442226633Sdim // The operand info should only have a single (register) entry. We 443226633Sdim // want the register class of it. 444226633Sdim InstOpRec = dynamic_cast<DefInit*>(DI->getArg(0))->getDef(); 445226633Sdim } 446226633Sdim 447224145Sdim if (InstOpRec->isSubClassOf("RegisterOperand")) 448224145Sdim InstOpRec = InstOpRec->getValueAsDef("RegClass"); 449224145Sdim 450218893Sdim if (!InstOpRec->isSubClassOf("RegisterClass")) 451218893Sdim return false; 452218893Sdim 453224145Sdim if (!T.getRegisterClass(InstOpRec) 454224145Sdim .contains(T.getRegBank().getReg(ADI->getDef()))) 455226633Sdim throw TGError(Loc, "fixed register " + ADI->getDef()->getName() + 456226633Sdim " is not a member of the " + InstOpRec->getName() + 457218893Sdim " register class!"); 458218893Sdim 459218893Sdim if (!Result->getArgName(AliasOpNo).empty()) 460218893Sdim throw TGError(Loc, "result fixed register argument must " 461218893Sdim "not have a name!"); 462218893Sdim 463218893Sdim ResOp = ResultOperand(ADI->getDef()); 464218893Sdim return true; 465218893Sdim } 466218893Sdim 467218893Sdim // Handle "zero_reg" for optional def operands. 468218893Sdim if (ADI && ADI->getDef()->getName() == "zero_reg") { 469218893Sdim 470218893Sdim // Check if this is an optional def. 471234353Sdim // Tied operands where the source is a sub-operand of a complex operand 472234353Sdim // need to represent both operands in the alias destination instruction. 473234353Sdim // Allow zero_reg for the tied portion. This can and should go away once 474234353Sdim // the MC representation of things doesn't use tied operands at all. 475234353Sdim //if (!InstOpRec->isSubClassOf("OptionalDefOperand")) 476234353Sdim // throw TGError(Loc, "reg0 used for result that is not an " 477234353Sdim // "OptionalDefOperand!"); 478218893Sdim 479218893Sdim ResOp = ResultOperand(static_cast<Record*>(0)); 480218893Sdim return true; 481218893Sdim } 482218893Sdim 483234353Sdim // Literal integers. 484218893Sdim if (IntInit *II = dynamic_cast<IntInit*>(Arg)) { 485218893Sdim if (hasSubOps || !InstOpRec->isSubClassOf("Operand")) 486218893Sdim return false; 487218893Sdim // Integer arguments can't have names. 488218893Sdim if (!Result->getArgName(AliasOpNo).empty()) 489218893Sdim throw TGError(Loc, "result argument #" + utostr(AliasOpNo) + 490218893Sdim " must not have a name!"); 491218893Sdim ResOp = ResultOperand(II->getValue()); 492218893Sdim return true; 493218893Sdim } 494218893Sdim 495234353Sdim // If both are Operands with the same MVT, allow the conversion. It's 496234353Sdim // up to the user to make sure the values are appropriate, just like 497234353Sdim // for isel Pat's. 498234353Sdim if (InstOpRec->isSubClassOf("Operand") && 499234353Sdim ADI->getDef()->isSubClassOf("Operand")) { 500234353Sdim // FIXME: What other attributes should we check here? Identical 501234353Sdim // MIOperandInfo perhaps? 502234353Sdim if (InstOpRec->getValueInit("Type") != ADI->getDef()->getValueInit("Type")) 503234353Sdim return false; 504234353Sdim ResOp = ResultOperand(Result->getArgName(AliasOpNo), ADI->getDef()); 505234353Sdim return true; 506234353Sdim } 507234353Sdim 508218893Sdim return false; 509218893Sdim} 510218893Sdim 511218893SdimCodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T) : TheDef(R) { 512218893Sdim AsmString = R->getValueAsString("AsmString"); 513218893Sdim Result = R->getValueAsDag("ResultInst"); 514218893Sdim 515218893Sdim // Verify that the root of the result is an instruction. 516218893Sdim DefInit *DI = dynamic_cast<DefInit*>(Result->getOperator()); 517218893Sdim if (DI == 0 || !DI->getDef()->isSubClassOf("Instruction")) 518218893Sdim throw TGError(R->getLoc(), "result of inst alias should be an instruction"); 519218893Sdim 520218893Sdim ResultInst = &T.getInstruction(DI->getDef()); 521218893Sdim 522218893Sdim // NameClass - If argument names are repeated, we need to verify they have 523218893Sdim // the same class. 524218893Sdim StringMap<Record*> NameClass; 525218893Sdim for (unsigned i = 0, e = Result->getNumArgs(); i != e; ++i) { 526218893Sdim DefInit *ADI = dynamic_cast<DefInit*>(Result->getArg(i)); 527218893Sdim if (!ADI || Result->getArgName(i).empty()) 528218893Sdim continue; 529218893Sdim // Verify we don't have something like: (someinst GR16:$foo, GR32:$foo) 530218893Sdim // $foo can exist multiple times in the result list, but it must have the 531218893Sdim // same type. 532218893Sdim Record *&Entry = NameClass[Result->getArgName(i)]; 533218893Sdim if (Entry && Entry != ADI->getDef()) 534218893Sdim throw TGError(R->getLoc(), "result value $" + Result->getArgName(i) + 535218893Sdim " is both " + Entry->getName() + " and " + 536218893Sdim ADI->getDef()->getName() + "!"); 537218893Sdim Entry = ADI->getDef(); 538218893Sdim } 539218893Sdim 540218893Sdim // Decode and validate the arguments of the result. 541218893Sdim unsigned AliasOpNo = 0; 542218893Sdim for (unsigned i = 0, e = ResultInst->Operands.size(); i != e; ++i) { 543218893Sdim 544234353Sdim // Tied registers don't have an entry in the result dag unless they're part 545234353Sdim // of a complex operand, in which case we include them anyways, as we 546234353Sdim // don't have any other way to specify the whole operand. 547234353Sdim if (ResultInst->Operands[i].MINumOperands == 1 && 548234353Sdim ResultInst->Operands[i].getTiedRegister() != -1) 549218893Sdim continue; 550218893Sdim 551218893Sdim if (AliasOpNo >= Result->getNumArgs()) 552218893Sdim throw TGError(R->getLoc(), "not enough arguments for instruction!"); 553218893Sdim 554218893Sdim Record *InstOpRec = ResultInst->Operands[i].Rec; 555218893Sdim unsigned NumSubOps = ResultInst->Operands[i].MINumOperands; 556218893Sdim ResultOperand ResOp(static_cast<int64_t>(0)); 557218893Sdim if (tryAliasOpMatch(Result, AliasOpNo, InstOpRec, (NumSubOps > 1), 558218893Sdim R->getLoc(), T, ResOp)) { 559218893Sdim ResultOperands.push_back(ResOp); 560218893Sdim ResultInstOperandIndex.push_back(std::make_pair(i, -1)); 561218893Sdim ++AliasOpNo; 562218893Sdim continue; 563218893Sdim } 564218893Sdim 565218893Sdim // If the argument did not match the instruction operand, and the operand 566218893Sdim // is composed of multiple suboperands, try matching the suboperands. 567218893Sdim if (NumSubOps > 1) { 568218893Sdim DagInit *MIOI = ResultInst->Operands[i].MIOperandInfo; 569218893Sdim for (unsigned SubOp = 0; SubOp != NumSubOps; ++SubOp) { 570218893Sdim if (AliasOpNo >= Result->getNumArgs()) 571218893Sdim throw TGError(R->getLoc(), "not enough arguments for instruction!"); 572218893Sdim Record *SubRec = dynamic_cast<DefInit*>(MIOI->getArg(SubOp))->getDef(); 573218893Sdim if (tryAliasOpMatch(Result, AliasOpNo, SubRec, false, 574218893Sdim R->getLoc(), T, ResOp)) { 575218893Sdim ResultOperands.push_back(ResOp); 576218893Sdim ResultInstOperandIndex.push_back(std::make_pair(i, SubOp)); 577218893Sdim ++AliasOpNo; 578218893Sdim } else { 579218893Sdim throw TGError(R->getLoc(), "result argument #" + utostr(AliasOpNo) + 580218893Sdim " does not match instruction operand class " + 581218893Sdim (SubOp == 0 ? InstOpRec->getName() :SubRec->getName())); 582218893Sdim } 583218893Sdim } 584218893Sdim continue; 585218893Sdim } 586218893Sdim throw TGError(R->getLoc(), "result argument #" + utostr(AliasOpNo) + 587218893Sdim " does not match instruction operand class " + 588218893Sdim InstOpRec->getName()); 589218893Sdim } 590218893Sdim 591218893Sdim if (AliasOpNo != Result->getNumArgs()) 592218893Sdim throw TGError(R->getLoc(), "too many operands for instruction!"); 593218893Sdim} 594