From: Chris Lattner Date: Mon, 1 Nov 2010 04:03:32 +0000 (+0000) Subject: factor the operand list (and related fields/operations) out of X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=c240bb0ede0541426254d0e0dc81d891beda4b22;p=oota-llvm.git factor the operand list (and related fields/operations) out of CodeGenInstruction into its own helper class. No functionality change. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@117893 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/utils/TableGen/ARMDecoderEmitter.cpp b/utils/TableGen/ARMDecoderEmitter.cpp index 89b3b8354c9..533fca0db0a 100644 --- a/utils/TableGen/ARMDecoderEmitter.cpp +++ b/utils/TableGen/ARMDecoderEmitter.cpp @@ -1763,8 +1763,8 @@ bool ARMDecoderEmitter::ARMDEBackend::populateInstruction( errs() << '\n'; // Dumps the list of operand info. - for (unsigned i = 0, e = CGI.OperandList.size(); i != e; ++i) { - CodeGenInstruction::OperandInfo Info = CGI.OperandList[i]; + for (unsigned i = 0, e = CGI.Operands.size(); i != e; ++i) { + const CGIOperandList::OperandInfo &Info = CGI.Operands[i]; const std::string &OperandName = Info.Name; const Record &OperandDef = *Info.Rec; diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp index 3f4594c4e3e..254a719959f 100644 --- a/utils/TableGen/AsmMatcherEmitter.cpp +++ b/utils/TableGen/AsmMatcherEmitter.cpp @@ -386,7 +386,7 @@ struct InstructionInfo { ClassInfo *Class; /// The original operand this corresponds to, if any. - const CodeGenInstruction::OperandInfo *OperandInfo; + const CGIOperandList::OperandInfo *OperandInfo; }; /// InstrName - The target name for this instruction. @@ -536,7 +536,7 @@ private: /// getOperandClass - Lookup or create the class for the given operand. ClassInfo *getOperandClass(StringRef Token, - const CodeGenInstruction::OperandInfo &OI); + const CGIOperandList::OperandInfo &OI); /// BuildRegisterClasses - Build the ClassInfo* instances for register /// classes. @@ -587,7 +587,7 @@ void InstructionInfo::dump() { continue; } - const CodeGenInstruction::OperandInfo &OI = *Op.OperandInfo; + const CGIOperandList::OperandInfo &OI = *Op.OperandInfo; errs() << OI.Name << " " << OI.Rec->getName() << " (" << OI.MIOperandNo << ", " << OI.MINumOperands << ")\n"; } @@ -665,7 +665,7 @@ ClassInfo *AsmMatcherInfo::getTokenClass(StringRef Token) { ClassInfo * AsmMatcherInfo::getOperandClass(StringRef Token, - const CodeGenInstruction::OperandInfo &OI) { + const CGIOperandList::OperandInfo &OI) { if (OI.Rec->isSubClassOf("RegisterClass")) { ClassInfo *CI = RegisterClassClasses[OI.Rec]; @@ -945,7 +945,8 @@ void AsmMatcherInfo::BuildInfo() { Instructions.push_back(II.take()); } - + + // Build info for the register classes. BuildRegisterClasses(SingletonRegisters); @@ -998,7 +999,7 @@ void AsmMatcherInfo::BuildInfo() { // Map this token to an operand. FIXME: Move elsewhere. unsigned Idx; - if (!II->Instr->hasOperandNamed(OperandName, Idx)) + if (!II->Instr->Operands.hasOperandNamed(OperandName, Idx)) throw std::string("error: unable to find operand: '" + OperandName.str() + "'"); @@ -1006,15 +1007,15 @@ void AsmMatcherInfo::BuildInfo() { // XCHG8rm). What we want is the untied operand, which we now have to // grovel for. Only worry about this for single entry operands, we have to // clean this up anyway. - const CodeGenInstruction::OperandInfo *OI = &II->Instr->OperandList[Idx]; + const CGIOperandList::OperandInfo *OI = &II->Instr->Operands[Idx]; if (OI->Constraints[0].isTied()) { unsigned TiedOp = OI->Constraints[0].getTiedOperand(); // The tied operand index is an MIOperand index, find the operand that // contains it. - for (unsigned i = 0, e = II->Instr->OperandList.size(); i != e; ++i) { - if (II->Instr->OperandList[i].MIOperandNo == TiedOp) { - OI = &II->Instr->OperandList[i]; + for (unsigned i = 0, e = II->Instr->Operands.size(); i != e; ++i) { + if (II->Instr->Operands[i].MIOperandNo == TiedOp) { + OI = &II->Instr->Operands[i]; break; } } @@ -1086,10 +1087,10 @@ static void EmitConvertToMCInst(CodeGenTarget &Target, // Find any tied operands. SmallVector, 4> TiedOperands; - for (unsigned i = 0, e = II.Instr->OperandList.size(); i != e; ++i) { - const CodeGenInstruction::OperandInfo &OpInfo = II.Instr->OperandList[i]; + for (unsigned i = 0, e = II.Instr->Operands.size(); i != e; ++i) { + const CGIOperandList::OperandInfo &OpInfo = II.Instr->Operands[i]; for (unsigned j = 0, e = OpInfo.Constraints.size(); j != e; ++j) { - const CodeGenInstruction::ConstraintInfo &CI = OpInfo.Constraints[j]; + const CGIOperandList::ConstraintInfo &CI = OpInfo.Constraints[j]; if (CI.isTied()) TiedOperands.push_back(std::make_pair(OpInfo.MIOperandNo + j, CI.getTiedOperand())); @@ -1100,8 +1101,8 @@ static void EmitConvertToMCInst(CodeGenTarget &Target, // Compute the total number of operands. unsigned NumMIOperands = 0; - for (unsigned i = 0, e = II.Instr->OperandList.size(); i != e; ++i) { - const CodeGenInstruction::OperandInfo &OI = II.Instr->OperandList[i]; + for (unsigned i = 0, e = II.Instr->Operands.size(); i != e; ++i) { + const CGIOperandList::OperandInfo &OI = II.Instr->Operands[i]; NumMIOperands = std::max(NumMIOperands, OI.MIOperandNo + OI.MINumOperands); } diff --git a/utils/TableGen/AsmWriterInst.cpp b/utils/TableGen/AsmWriterInst.cpp index 7989406d6fa..fdf447f2aaf 100644 --- a/utils/TableGen/AsmWriterInst.cpp +++ b/utils/TableGen/AsmWriterInst.cpp @@ -198,8 +198,8 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, Modifier)); } else { // Otherwise, normal operand. - unsigned OpNo = CGI.getOperandNamed(VarName); - CodeGenInstruction::OperandInfo OpInfo = CGI.OperandList[OpNo]; + unsigned OpNo = CGI.Operands.getOperandNamed(VarName); + CGIOperandList::OperandInfo OpInfo = CGI.Operands[OpNo]; unsigned MIOp = OpInfo.MIOperandNo; Operands.push_back(AsmWriterOperand(OpInfo.PrinterMethodName, diff --git a/utils/TableGen/CodeEmitterGen.cpp b/utils/TableGen/CodeEmitterGen.cpp index b7b62d502b0..631075263e4 100644 --- a/utils/TableGen/CodeEmitterGen.cpp +++ b/utils/TableGen/CodeEmitterGen.cpp @@ -158,21 +158,22 @@ void CodeEmitterGen::run(raw_ostream &o) { // operand number. Non-matching operands are assumed to be in // order. unsigned OpIdx; - if (CGI.hasOperandNamed(VarName, OpIdx)) { + if (CGI.Operands.hasOperandNamed(VarName, OpIdx)) { // Get the machine operand number for the indicated operand. - OpIdx = CGI.OperandList[OpIdx].MIOperandNo; - assert (!CGI.isFlatOperandNotEmitted(OpIdx) && + OpIdx = CGI.Operands[OpIdx].MIOperandNo; + assert (!CGI.Operands.isFlatOperandNotEmitted(OpIdx) && "Explicitly used operand also marked as not emitted!"); } else { /// If this operand is not supposed to be emitted by the /// generated emitter, skip it. - while (CGI.isFlatOperandNotEmitted(NumberedOp)) + while (CGI.Operands.isFlatOperandNotEmitted(NumberedOp)) ++NumberedOp; OpIdx = NumberedOp++; } - std::pair SO = CGI.getSubOperandNumber(OpIdx); + std::pair SO = + CGI.Operands.getSubOperandNumber(OpIdx); std::string &EncoderMethodName = - CGI.OperandList[SO.first].EncoderMethodName; + CGI.Operands[SO.first].EncoderMethodName; // If the source operand has a custom encoder, use it. This will // get the encoding for all of the suboperands. diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp index 6f541914981..6c89453ce4c 100644 --- a/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/utils/TableGen/CodeGenDAGPatterns.cpp @@ -829,7 +829,7 @@ static unsigned GetNumNodeResults(Record *Operator, CodeGenDAGPatterns &CDP) { CodeGenInstruction &InstInfo = CDP.getTargetInfo().getInstruction(Operator); // FIXME: Should allow access to all the results here. - unsigned NumDefsToAdd = InstInfo.NumDefs ? 1 : 0; + unsigned NumDefsToAdd = InstInfo.Operands.NumDefs ? 1 : 0; // Add on one implicit def if it has a resolvable type. if (InstInfo.HasOneImplicitDefWithKnownVT(CDP.getTargetInfo()) !=MVT::Other) @@ -1314,7 +1314,7 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { // Apply the result types to the node, these come from the things in the // (outs) list of the instruction. // FIXME: Cap at one result so far. - unsigned NumResultsToAdd = InstInfo.NumDefs ? 1 : 0; + unsigned NumResultsToAdd = InstInfo.Operands.NumDefs ? 1 : 0; for (unsigned ResNo = 0; ResNo != NumResultsToAdd; ++ResNo) { Record *ResultNode = Inst.getResult(ResNo); @@ -2258,7 +2258,7 @@ static void InferFromPattern(const CodeGenInstruction &Inst, HasSideEffects = true; } - if (Inst.isVariadic) + if (Inst.Operands.isVariadic) IsVariadic = true; // Can warn if we want. } @@ -2283,18 +2283,18 @@ void CodeGenDAGPatterns::ParseInstructions() { CodeGenInstruction &InstInfo = Target.getInstruction(Instrs[i]); - if (InstInfo.OperandList.size() != 0) { - if (InstInfo.NumDefs == 0) { + if (InstInfo.Operands.size() != 0) { + if (InstInfo.Operands.NumDefs == 0) { // These produce no results - for (unsigned j = 0, e = InstInfo.OperandList.size(); j < e; ++j) - Operands.push_back(InstInfo.OperandList[j].Rec); + for (unsigned j = 0, e = InstInfo.Operands.size(); j < e; ++j) + Operands.push_back(InstInfo.Operands[j].Rec); } else { // Assume the first operand is the result. - Results.push_back(InstInfo.OperandList[0].Rec); + Results.push_back(InstInfo.Operands[0].Rec); // The rest are inputs. - for (unsigned j = 1, e = InstInfo.OperandList.size(); j < e; ++j) - Operands.push_back(InstInfo.OperandList[j].Rec); + for (unsigned j = 1, e = InstInfo.Operands.size(); j < e; ++j) + Operands.push_back(InstInfo.Operands[j].Rec); } } @@ -2351,10 +2351,10 @@ void CodeGenDAGPatterns::ParseInstructions() { std::vector Results; TreePatternNode *Res0Node = 0; for (unsigned i = 0; i != NumResults; ++i) { - if (i == CGI.OperandList.size()) + if (i == CGI.Operands.size()) I->error("'" + InstResults.begin()->first + "' set but does not appear in operand list!"); - const std::string &OpName = CGI.OperandList[i].Name; + const std::string &OpName = CGI.Operands[i].Name; // Check that it exists in InstResults. TreePatternNode *RNode = InstResults[OpName]; @@ -2368,11 +2368,11 @@ void CodeGenDAGPatterns::ParseInstructions() { I->error("Operand $" + OpName + " should be a set destination: all " "outputs must occur before inputs in operand list!"); - if (CGI.OperandList[i].Rec != R) + if (CGI.Operands[i].Rec != R) I->error("Operand $" + OpName + " class mismatch!"); // Remember the return type. - Results.push_back(CGI.OperandList[i].Rec); + Results.push_back(CGI.Operands[i].Rec); // Okay, this one checks out. InstResults.erase(OpName); @@ -2384,8 +2384,8 @@ void CodeGenDAGPatterns::ParseInstructions() { std::vector ResultNodeOperands; std::vector Operands; - for (unsigned i = NumResults, e = CGI.OperandList.size(); i != e; ++i) { - CodeGenInstruction::OperandInfo &Op = CGI.OperandList[i]; + for (unsigned i = NumResults, e = CGI.Operands.size(); i != e; ++i) { + CGIOperandList::OperandInfo &Op = CGI.Operands[i]; const std::string &OpName = Op.Name; if (OpName.empty()) I->error("Operand #" + utostr(i) + " in operands list has no name!"); @@ -2569,7 +2569,7 @@ void CodeGenDAGPatterns::InferInstructionFlags() { InstInfo.mayStore = MayStore; InstInfo.mayLoad = MayLoad; InstInfo.hasSideEffects = HasSideEffects; - InstInfo.isVariadic = IsVariadic; + InstInfo.Operands.isVariadic = IsVariadic; } } diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp index 259e7c36a4c..5eceaeb015c 100644 --- a/utils/TableGen/CodeGenInstruction.cpp +++ b/utils/TableGen/CodeGenInstruction.cpp @@ -19,134 +19,32 @@ #include using namespace llvm; -static void ParseConstraint(const std::string &CStr, CodeGenInstruction *I) { - // EARLY_CLOBBER: @early $reg - std::string::size_type wpos = CStr.find_first_of(" \t"); - std::string::size_type start = CStr.find_first_not_of(" \t"); - std::string Tok = CStr.substr(start, wpos - start); - if (Tok == "@earlyclobber") { - std::string Name = CStr.substr(wpos+1); - wpos = Name.find_first_not_of(" \t"); - if (wpos == std::string::npos) - throw "Illegal format for @earlyclobber constraint: '" + CStr + "'"; - Name = Name.substr(wpos); - std::pair Op = - I->ParseOperandName(Name, false); - - // Build the string for the operand - if (!I->OperandList[Op.first].Constraints[Op.second].isNone()) - throw "Operand '" + Name + "' cannot have multiple constraints!"; - I->OperandList[Op.first].Constraints[Op.second] = - CodeGenInstruction::ConstraintInfo::getEarlyClobber(); - return; - } - - // Only other constraint is "TIED_TO" for now. - std::string::size_type pos = CStr.find_first_of('='); - assert(pos != std::string::npos && "Unrecognized constraint"); - start = CStr.find_first_not_of(" \t"); - std::string Name = CStr.substr(start, pos - start); - - // TIED_TO: $src1 = $dst - wpos = Name.find_first_of(" \t"); - if (wpos == std::string::npos) - throw "Illegal format for tied-to constraint: '" + CStr + "'"; - std::string DestOpName = Name.substr(0, wpos); - std::pair DestOp = I->ParseOperandName(DestOpName, false); - - Name = CStr.substr(pos+1); - wpos = Name.find_first_not_of(" \t"); - if (wpos == std::string::npos) - throw "Illegal format for tied-to constraint: '" + CStr + "'"; - - std::pair SrcOp = - I->ParseOperandName(Name.substr(wpos), false); - if (SrcOp > DestOp) - throw "Illegal tied-to operand constraint '" + CStr + "'"; - - - unsigned FlatOpNo = I->getFlattenedOperandNumber(SrcOp); - - if (!I->OperandList[DestOp.first].Constraints[DestOp.second].isNone()) - throw "Operand '" + DestOpName + "' cannot have multiple constraints!"; - I->OperandList[DestOp.first].Constraints[DestOp.second] = - CodeGenInstruction::ConstraintInfo::getTied(FlatOpNo); -} - -static void ParseConstraints(const std::string &CStr, CodeGenInstruction *I) { - // Make sure the constraints list for each operand is large enough to hold - // constraint info, even if none is present. - for (unsigned i = 0, e = I->OperandList.size(); i != e; ++i) - I->OperandList[i].Constraints.resize(I->OperandList[i].MINumOperands); - - if (CStr.empty()) return; - - const std::string delims(","); - std::string::size_type bidx, eidx; - - bidx = CStr.find_first_not_of(delims); - while (bidx != std::string::npos) { - eidx = CStr.find_first_of(delims, bidx); - if (eidx == std::string::npos) - eidx = CStr.length(); - - ParseConstraint(CStr.substr(bidx, eidx - bidx), I); - bidx = CStr.find_first_not_of(delims, eidx); - } -} - -CodeGenInstruction::CodeGenInstruction(Record *R) : TheDef(R) { - Namespace = R->getValueAsString("Namespace"); - AsmString = R->getValueAsString("AsmString"); +//===----------------------------------------------------------------------===// +// CGIOperandList Implementation +//===----------------------------------------------------------------------===// - isReturn = R->getValueAsBit("isReturn"); - isBranch = R->getValueAsBit("isBranch"); - isIndirectBranch = R->getValueAsBit("isIndirectBranch"); - isCompare = R->getValueAsBit("isCompare"); - isBarrier = R->getValueAsBit("isBarrier"); - isCall = R->getValueAsBit("isCall"); - canFoldAsLoad = R->getValueAsBit("canFoldAsLoad"); - mayLoad = R->getValueAsBit("mayLoad"); - mayStore = R->getValueAsBit("mayStore"); - isPredicable = R->getValueAsBit("isPredicable"); - isConvertibleToThreeAddress = R->getValueAsBit("isConvertibleToThreeAddress"); - isCommutable = R->getValueAsBit("isCommutable"); - isTerminator = R->getValueAsBit("isTerminator"); - isReMaterializable = R->getValueAsBit("isReMaterializable"); - hasDelaySlot = R->getValueAsBit("hasDelaySlot"); - usesCustomInserter = R->getValueAsBit("usesCustomInserter"); - hasCtrlDep = R->getValueAsBit("hasCtrlDep"); - isNotDuplicable = R->getValueAsBit("isNotDuplicable"); - hasSideEffects = R->getValueAsBit("hasSideEffects"); - neverHasSideEffects = R->getValueAsBit("neverHasSideEffects"); - isAsCheapAsAMove = R->getValueAsBit("isAsCheapAsAMove"); - hasExtraSrcRegAllocReq = R->getValueAsBit("hasExtraSrcRegAllocReq"); - hasExtraDefRegAllocReq = R->getValueAsBit("hasExtraDefRegAllocReq"); +CGIOperandList::CGIOperandList(Record *R) : TheDef(R) { + isPredicable = false; hasOptionalDef = false; isVariadic = false; - ImplicitDefs = R->getValueAsListOfDefs("Defs"); - ImplicitUses = R->getValueAsListOfDefs("Uses"); - - if (neverHasSideEffects + hasSideEffects > 1) - throw R->getName() + ": multiple conflicting side-effect flags set!"; - + DagInit *OutDI = R->getValueAsDag("OutOperandList"); - + if (DefInit *Init = dynamic_cast(OutDI->getOperator())) { if (Init->getDef()->getName() != "outs") throw R->getName() + ": invalid def name for output list: use 'outs'"; } else throw R->getName() + ": invalid output list: use 'outs'"; - + NumDefs = OutDI->getNumArgs(); - + DagInit *InDI = R->getValueAsDag("InOperandList"); if (DefInit *Init = dynamic_cast(InDI->getOperator())) { if (Init->getDef()->getName() != "ins") throw R->getName() + ": invalid def name for input list: use 'ins'"; } else throw R->getName() + ": invalid input list: use 'ins'"; - + unsigned MIOperandNo = 0; std::set OperandNames; for (unsigned i = 0, e = InDI->getNumArgs()+OutDI->getNumArgs(); i != e; ++i){ @@ -163,7 +61,7 @@ CodeGenInstruction::CodeGenInstruction(Record *R) : TheDef(R) { DefInit *Arg = dynamic_cast(ArgInit); if (!Arg) throw "Illegal operand for the '" + R->getName() + "' instruction!"; - + Record *Rec = Arg->getDef(); std::string PrintMethod = "printOperand"; std::string EncoderMethod; @@ -175,19 +73,19 @@ CodeGenInstruction::CodeGenInstruction(Record *R) : TheDef(R) { if (Rec->getValue("EncoderMethod")) EncoderMethod = Rec->getValueAsString("EncoderMethod"); MIOpInfo = Rec->getValueAsDag("MIOperandInfo"); - + // Verify that MIOpInfo has an 'ops' root value. if (!dynamic_cast(MIOpInfo->getOperator()) || dynamic_cast(MIOpInfo->getOperator()) - ->getDef()->getName() != "ops") + ->getDef()->getName() != "ops") throw "Bad value for MIOperandInfo in operand '" + Rec->getName() + - "'\n"; - + "'\n"; + // If we have MIOpInfo, then we have #operands equal to number of entries // in MIOperandInfo. if (unsigned NumArgs = MIOpInfo->getNumArgs()) NumOps = NumArgs; - + if (Rec->isSubClassOf("PredicateOperand")) isPredicable = true; else if (Rec->isSubClassOf("OptionalDefOperand")) @@ -198,57 +96,38 @@ CodeGenInstruction::CodeGenInstruction(Record *R) : TheDef(R) { } else if (!Rec->isSubClassOf("RegisterClass") && Rec->getName() != "ptr_rc" && Rec->getName() != "unknown") throw "Unknown operand class '" + Rec->getName() + - "' in '" + R->getName() + "' instruction!"; - + "' in '" + R->getName() + "' instruction!"; + // Check that the operand has a name and that it's unique. if (ArgName.empty()) throw "In instruction '" + R->getName() + "', operand #" + utostr(i) + - " has no name!"; + " has no name!"; if (!OperandNames.insert(ArgName).second) throw "In instruction '" + R->getName() + "', operand #" + utostr(i) + - " has the same name as a previous operand!"; - + " has the same name as a previous operand!"; + OperandList.push_back(OperandInfo(Rec, ArgName, PrintMethod, EncoderMethod, MIOperandNo, NumOps, MIOpInfo)); MIOperandNo += NumOps; } - - // Parse Constraints. - ParseConstraints(R->getValueAsString("Constraints"), this); - - // Parse the DisableEncoding field. - std::string DisableEncoding = R->getValueAsString("DisableEncoding"); - while (1) { - std::string OpName; - tie(OpName, DisableEncoding) = getToken(DisableEncoding, " ,\t"); - if (OpName.empty()) break; - - // Figure out which operand this is. - std::pair Op = ParseOperandName(OpName, false); - - // Mark the operand as not-to-be encoded. - if (Op.second >= OperandList[Op.first].DoNotEncode.size()) - OperandList[Op.first].DoNotEncode.resize(Op.second+1); - OperandList[Op.first].DoNotEncode[Op.second] = true; - } } + /// getOperandNamed - Return the index of the operand with the specified /// non-empty name. If the instruction does not have an operand with the /// specified name, throw an exception. /// -unsigned CodeGenInstruction::getOperandNamed(StringRef Name) const { +unsigned CGIOperandList::getOperandNamed(StringRef Name) const { unsigned OpIdx; if (hasOperandNamed(Name, OpIdx)) return OpIdx; - throw "Instruction '" + TheDef->getName() + - "' does not have an operand named '$" + Name.str() + "'!"; + throw "'" + TheDef->getName() + "' does not have an operand named '$" + + Name.str() + "'!"; } /// hasOperandNamed - Query whether the instruction has an operand of the /// given name. If so, return true and set OpIdx to the index of the /// operand. Otherwise, return false. -bool CodeGenInstruction::hasOperandNamed(StringRef Name, - unsigned &OpIdx) const { +bool CGIOperandList::hasOperandNamed(StringRef Name, unsigned &OpIdx) const { assert(!Name.empty() && "Cannot search for operand with no name!"); for (unsigned i = 0, e = OperandList.size(); i != e; ++i) if (OperandList[i].Name == Name) { @@ -259,14 +138,13 @@ bool CodeGenInstruction::hasOperandNamed(StringRef Name, } std::pair -CodeGenInstruction::ParseOperandName(const std::string &Op, - bool AllowWholeOp) { +CGIOperandList::ParseOperandName(const std::string &Op, bool AllowWholeOp) { if (Op.empty() || Op[0] != '$') throw TheDef->getName() + ": Illegal operand name: '" + Op + "'"; - + std::string OpName = Op.substr(1); std::string SubOpName; - + // Check to see if this is $foo.bar. std::string::size_type DotIdx = OpName.find_first_of("."); if (DotIdx != std::string::npos) { @@ -275,34 +153,169 @@ CodeGenInstruction::ParseOperandName(const std::string &Op, throw TheDef->getName() + ": illegal empty suboperand name in '" +Op +"'"; OpName = OpName.substr(0, DotIdx); } - + unsigned OpIdx = getOperandNamed(OpName); - + if (SubOpName.empty()) { // If no suboperand name was specified: // If one was needed, throw. if (OperandList[OpIdx].MINumOperands > 1 && !AllowWholeOp && SubOpName.empty()) throw TheDef->getName() + ": Illegal to refer to" - " whole operand part of complex operand '" + Op + "'"; - + " whole operand part of complex operand '" + Op + "'"; + // Otherwise, return the operand. return std::make_pair(OpIdx, 0U); } - + // Find the suboperand number involved. DagInit *MIOpInfo = OperandList[OpIdx].MIOperandInfo; if (MIOpInfo == 0) throw TheDef->getName() + ": unknown suboperand name in '" + Op + "'"; - + // Find the operand with the right name. for (unsigned i = 0, e = MIOpInfo->getNumArgs(); i != e; ++i) if (MIOpInfo->getArgName(i) == SubOpName) return std::make_pair(OpIdx, i); - + // Otherwise, didn't find it! throw TheDef->getName() + ": unknown suboperand name in '" + Op + "'"; } +static void ParseConstraint(const std::string &CStr, CGIOperandList &Ops) { + // EARLY_CLOBBER: @early $reg + std::string::size_type wpos = CStr.find_first_of(" \t"); + std::string::size_type start = CStr.find_first_not_of(" \t"); + std::string Tok = CStr.substr(start, wpos - start); + if (Tok == "@earlyclobber") { + std::string Name = CStr.substr(wpos+1); + wpos = Name.find_first_not_of(" \t"); + if (wpos == std::string::npos) + throw "Illegal format for @earlyclobber constraint: '" + CStr + "'"; + Name = Name.substr(wpos); + std::pair Op = Ops.ParseOperandName(Name, false); + + // Build the string for the operand + if (!Ops[Op.first].Constraints[Op.second].isNone()) + throw "Operand '" + Name + "' cannot have multiple constraints!"; + Ops[Op.first].Constraints[Op.second] = + CGIOperandList::ConstraintInfo::getEarlyClobber(); + return; + } + + // Only other constraint is "TIED_TO" for now. + std::string::size_type pos = CStr.find_first_of('='); + assert(pos != std::string::npos && "Unrecognized constraint"); + start = CStr.find_first_not_of(" \t"); + std::string Name = CStr.substr(start, pos - start); + + // TIED_TO: $src1 = $dst + wpos = Name.find_first_of(" \t"); + if (wpos == std::string::npos) + throw "Illegal format for tied-to constraint: '" + CStr + "'"; + std::string DestOpName = Name.substr(0, wpos); + std::pair DestOp = Ops.ParseOperandName(DestOpName, false); + + Name = CStr.substr(pos+1); + wpos = Name.find_first_not_of(" \t"); + if (wpos == std::string::npos) + throw "Illegal format for tied-to constraint: '" + CStr + "'"; + + std::pair SrcOp = + Ops.ParseOperandName(Name.substr(wpos), false); + if (SrcOp > DestOp) + throw "Illegal tied-to operand constraint '" + CStr + "'"; + + + unsigned FlatOpNo = Ops.getFlattenedOperandNumber(SrcOp); + + if (!Ops[DestOp.first].Constraints[DestOp.second].isNone()) + throw "Operand '" + DestOpName + "' cannot have multiple constraints!"; + Ops[DestOp.first].Constraints[DestOp.second] = + CGIOperandList::ConstraintInfo::getTied(FlatOpNo); +} + +static void ParseConstraints(const std::string &CStr, CGIOperandList &Ops) { + // Make sure the constraints list for each operand is large enough to hold + // constraint info, even if none is present. + for (unsigned i = 0, e = Ops.size(); i != e; ++i) + Ops[i].Constraints.resize(Ops[i].MINumOperands); + + if (CStr.empty()) return; + + const std::string delims(","); + std::string::size_type bidx, eidx; + + bidx = CStr.find_first_not_of(delims); + while (bidx != std::string::npos) { + eidx = CStr.find_first_of(delims, bidx); + if (eidx == std::string::npos) + eidx = CStr.length(); + + ParseConstraint(CStr.substr(bidx, eidx - bidx), Ops); + bidx = CStr.find_first_not_of(delims, eidx); + } +} + +void CGIOperandList::ProcessDisableEncoding(std::string DisableEncoding) { + while (1) { + std::string OpName; + tie(OpName, DisableEncoding) = getToken(DisableEncoding, " ,\t"); + if (OpName.empty()) break; + + // Figure out which operand this is. + std::pair Op = ParseOperandName(OpName, false); + + // Mark the operand as not-to-be encoded. + if (Op.second >= OperandList[Op.first].DoNotEncode.size()) + OperandList[Op.first].DoNotEncode.resize(Op.second+1); + OperandList[Op.first].DoNotEncode[Op.second] = true; + } + +} + +//===----------------------------------------------------------------------===// +// CodeGenInstruction Implementation +//===----------------------------------------------------------------------===// + +CodeGenInstruction::CodeGenInstruction(Record *R) : TheDef(R), Operands(R) { + Namespace = R->getValueAsString("Namespace"); + AsmString = R->getValueAsString("AsmString"); + + isReturn = R->getValueAsBit("isReturn"); + isBranch = R->getValueAsBit("isBranch"); + isIndirectBranch = R->getValueAsBit("isIndirectBranch"); + isCompare = R->getValueAsBit("isCompare"); + isBarrier = R->getValueAsBit("isBarrier"); + isCall = R->getValueAsBit("isCall"); + canFoldAsLoad = R->getValueAsBit("canFoldAsLoad"); + mayLoad = R->getValueAsBit("mayLoad"); + mayStore = R->getValueAsBit("mayStore"); + isPredicable = Operands.isPredicable || R->getValueAsBit("isPredicable"); + isConvertibleToThreeAddress = R->getValueAsBit("isConvertibleToThreeAddress"); + isCommutable = R->getValueAsBit("isCommutable"); + isTerminator = R->getValueAsBit("isTerminator"); + isReMaterializable = R->getValueAsBit("isReMaterializable"); + hasDelaySlot = R->getValueAsBit("hasDelaySlot"); + usesCustomInserter = R->getValueAsBit("usesCustomInserter"); + hasCtrlDep = R->getValueAsBit("hasCtrlDep"); + isNotDuplicable = R->getValueAsBit("isNotDuplicable"); + hasSideEffects = R->getValueAsBit("hasSideEffects"); + neverHasSideEffects = R->getValueAsBit("neverHasSideEffects"); + isAsCheapAsAMove = R->getValueAsBit("isAsCheapAsAMove"); + hasExtraSrcRegAllocReq = R->getValueAsBit("hasExtraSrcRegAllocReq"); + hasExtraDefRegAllocReq = R->getValueAsBit("hasExtraDefRegAllocReq"); + ImplicitDefs = R->getValueAsListOfDefs("Defs"); + ImplicitUses = R->getValueAsListOfDefs("Uses"); + + if (neverHasSideEffects + hasSideEffects > 1) + throw R->getName() + ": multiple conflicting side-effect flags set!"; + + // Parse Constraints. + ParseConstraints(R->getValueAsString("Constraints"), Operands); + + // Parse the DisableEncoding field. + Operands.ProcessDisableEncoding(R->getValueAsString("DisableEncoding")); +} /// HasOneImplicitDefWithKnownVT - If the instruction has at least one /// implicit def and it has a known VT, return the VT, otherwise return @@ -369,4 +382,3 @@ FlattenAsmStringVariants(StringRef Cur, unsigned Variant) { return Res; } - diff --git a/utils/TableGen/CodeGenInstruction.h b/utils/TableGen/CodeGenInstruction.h index 7f9d24925cc..93bec14ff5f 100644 --- a/utils/TableGen/CodeGenInstruction.h +++ b/utils/TableGen/CodeGenInstruction.h @@ -24,40 +24,33 @@ namespace llvm { class DagInit; class CodeGenTarget; class StringRef; - - class CodeGenInstruction { + + class CGIOperandList { public: - Record *TheDef; // The actual record defining this instruction. - std::string Namespace; // The namespace the instruction is in. - - /// AsmString - The format string used to emit a .s file for the - /// instruction. - std::string AsmString; - class ConstraintInfo { enum { None, EarlyClobber, Tied } Kind; unsigned OtherTiedOperand; public: ConstraintInfo() : Kind(None) {} - + static ConstraintInfo getEarlyClobber() { ConstraintInfo I; I.Kind = EarlyClobber; I.OtherTiedOperand = 0; return I; } - + static ConstraintInfo getTied(unsigned Op) { ConstraintInfo I; I.Kind = Tied; I.OtherTiedOperand = Op; return I; } - + bool isNone() const { return Kind == None; } bool isEarlyClobber() const { return Kind == EarlyClobber; } bool isTied() const { return Kind == Tied; } - + unsigned getTiedOperand() const { assert(isTied()); return OtherTiedOperand; @@ -70,19 +63,19 @@ namespace llvm { /// Rec - The definition this operand is declared as. /// Record *Rec; - + /// Name - If this operand was assigned a symbolic name, this is it, /// otherwise, it's empty. std::string Name; - + /// PrinterMethodName - The method used to print operands of this type in /// the asmprinter. std::string PrinterMethodName; - + /// EncoderMethodName - The method used to get the machine operand value /// for binary encoding. "getMachineOpValue" by default. std::string EncoderMethodName; - + /// MIOperandNo - Currently (this is meant to be phased out), some logical /// operands correspond to multiple MachineInstr operands. In the X86 /// target for example, one address operand is represented as 4 @@ -91,66 +84,63 @@ namespace llvm { /// does, this contains the MI operand index of this operand. unsigned MIOperandNo; unsigned MINumOperands; // The number of operands. - + /// DoNotEncode - Bools are set to true in this vector for each operand in /// the DisableEncoding list. These should not be emitted by the code /// emitter. std::vector DoNotEncode; - + /// MIOperandInfo - Default MI operand type. Note an operand may be made /// up of multiple MI operands. DagInit *MIOperandInfo; - + /// Constraint info for this operand. This operand can have pieces, so we /// track constraint info for each. std::vector Constraints; - + OperandInfo(Record *R, const std::string &N, const std::string &PMN, const std::string &EMN, unsigned MION, unsigned MINO, DagInit *MIOI) - : Rec(R), Name(N), PrinterMethodName(PMN), EncoderMethodName(EMN), - MIOperandNo(MION), MINumOperands(MINO), MIOperandInfo(MIOI) {} + : Rec(R), Name(N), PrinterMethodName(PMN), EncoderMethodName(EMN), + MIOperandNo(MION), MINumOperands(MINO), MIOperandInfo(MIOI) {} }; + + CGIOperandList(Record *D); + + Record *TheDef; // The actual record containing this OperandList. /// NumDefs - Number of def operands declared, this is the number of /// elements in the instruction's (outs) list. /// unsigned NumDefs; - + /// OperandList - The list of declared operands, along with their declared /// type (which is a record). std::vector OperandList; - - /// ImplicitDefs/ImplicitUses - These are lists of registers that are - /// implicitly defined and used by the instruction. - std::vector ImplicitDefs, ImplicitUses; - - // Various boolean values we track for the instruction. - bool isReturn; - bool isBranch; - bool isIndirectBranch; - bool isCompare; - bool isBarrier; - bool isCall; - bool canFoldAsLoad; - bool mayLoad, mayStore; + + // Information gleaned from the operand list. bool isPredicable; - bool isConvertibleToThreeAddress; - bool isCommutable; - bool isTerminator; - bool isReMaterializable; - bool hasDelaySlot; - bool usesCustomInserter; - bool isVariadic; - bool hasCtrlDep; - bool isNotDuplicable; bool hasOptionalDef; - bool hasSideEffects; - bool neverHasSideEffects; - bool isAsCheapAsAMove; - bool hasExtraSrcRegAllocReq; - bool hasExtraDefRegAllocReq; - + bool isVariadic; + + // Provide transparent accessors to the operand list. + unsigned size() const { return OperandList.size(); } + const OperandInfo &operator[](unsigned i) const { return OperandList[i]; } + OperandInfo &operator[](unsigned i) { return OperandList[i]; } + OperandInfo &back() { return OperandList.back(); } + const OperandInfo &back() const { return OperandList.back(); } + + + /// getOperandNamed - Return the index of the operand with the specified + /// non-empty name. If the instruction does not have an operand with the + /// specified name, throw an exception. + unsigned getOperandNamed(StringRef Name) const; + + /// hasOperandNamed - Query whether the instruction has an operand of the + /// given name. If so, return true and set OpIdx to the index of the + /// operand. Otherwise, return false. + bool hasOperandNamed(StringRef Name, unsigned &OpIdx) const; + /// ParseOperandName - Parse an operand name like "$foo" or "$foo.bar", /// where $foo is a whole operand and $foo.bar refers to a suboperand. /// This throws an exception if the name is invalid. If AllowWholeOp is @@ -158,13 +148,13 @@ namespace llvm { /// not. std::pair ParseOperandName(const std::string &Op, bool AllowWholeOp = true); - + /// getFlattenedOperandNumber - Flatten a operand/suboperand pair into a /// flat machineinstr operand #. unsigned getFlattenedOperandNumber(std::pair Op) const { return OperandList[Op.first].MIOperandNo + Op.second; } - + /// getSubOperandNumber - Unflatten a operand number into an /// operand/suboperand pair. std::pair getSubOperandNumber(unsigned Op) const { @@ -174,8 +164,8 @@ namespace llvm { return std::make_pair(i, Op-OperandList[i].MIOperandNo); } } - - + + /// isFlatOperandNotEmitted - Return true if the specified flat operand # /// should not be emitted with the code emitter. bool isFlatOperandNotEmitted(unsigned FlatOpNo) const { @@ -184,18 +174,54 @@ namespace llvm { return OperandList[Op.first].DoNotEncode[Op.second]; return false; } + + void ProcessDisableEncoding(std::string Value); + }; + - CodeGenInstruction(Record *R); + class CodeGenInstruction { + public: + Record *TheDef; // The actual record defining this instruction. + std::string Namespace; // The namespace the instruction is in. - /// getOperandNamed - Return the index of the operand with the specified - /// non-empty name. If the instruction does not have an operand with the - /// specified name, throw an exception. - unsigned getOperandNamed(StringRef Name) const; + /// AsmString - The format string used to emit a .s file for the + /// instruction. + std::string AsmString; - /// hasOperandNamed - Query whether the instruction has an operand of the - /// given name. If so, return true and set OpIdx to the index of the - /// operand. Otherwise, return false. - bool hasOperandNamed(StringRef Name, unsigned &OpIdx) const; + /// Operands - This is information about the (ins) and (outs) list specified + /// to the instruction. + CGIOperandList Operands; + + /// ImplicitDefs/ImplicitUses - These are lists of registers that are + /// implicitly defined and used by the instruction. + std::vector ImplicitDefs, ImplicitUses; + + // Various boolean values we track for the instruction. + bool isReturn; + bool isBranch; + bool isIndirectBranch; + bool isCompare; + bool isBarrier; + bool isCall; + bool canFoldAsLoad; + bool mayLoad, mayStore; + bool isPredicable; + bool isConvertibleToThreeAddress; + bool isCommutable; + bool isTerminator; + bool isReMaterializable; + bool hasDelaySlot; + bool usesCustomInserter; + bool hasCtrlDep; + bool isNotDuplicable; + bool hasSideEffects; + bool neverHasSideEffects; + bool isAsCheapAsAMove; + bool hasExtraSrcRegAllocReq; + bool hasExtraDefRegAllocReq; + + + CodeGenInstruction(Record *R); /// HasOneImplicitDefWithKnownVT - If the instruction has at least one /// implicit def and it has a known VT, return the VT, otherwise return @@ -209,6 +235,6 @@ namespace llvm { static std::string FlattenAsmStringVariants(StringRef AsmString, unsigned Variant); }; -} + } #endif diff --git a/utils/TableGen/DAGISelMatcherGen.cpp b/utils/TableGen/DAGISelMatcherGen.cpp index 57c0b155788..c1e3212e81c 100644 --- a/utils/TableGen/DAGISelMatcherGen.cpp +++ b/utils/TableGen/DAGISelMatcherGen.cpp @@ -678,11 +678,11 @@ EmitResultInstructionAsOperand(const TreePatternNode *N, // in the 'execute always' values. Match up the node operands to the // instruction operands to do this. SmallVector InstOps; - for (unsigned ChildNo = 0, InstOpNo = NumResults, e = II.OperandList.size(); + for (unsigned ChildNo = 0, InstOpNo = NumResults, e = II.Operands.size(); InstOpNo != e; ++InstOpNo) { // Determine what to emit for this operand. - Record *OperandNode = II.OperandList[InstOpNo].Rec; + Record *OperandNode = II.Operands[InstOpNo].Rec; if ((OperandNode->isSubClassOf("PredicateOperand") || OperandNode->isSubClassOf("OptionalDefOperand")) && !CGP.getDefaultOperand(OperandNode).DefaultOps.empty()) { diff --git a/utils/TableGen/EDEmitter.cpp b/utils/TableGen/EDEmitter.cpp index 8b1b890538e..1d5e1e170ba 100644 --- a/utils/TableGen/EDEmitter.cpp +++ b/utils/TableGen/EDEmitter.cpp @@ -346,11 +346,10 @@ static void X86PopulateOperands( return; unsigned int index; - unsigned int numOperands = inst.OperandList.size(); + unsigned int numOperands = inst.Operands.size(); for (index = 0; index < numOperands; ++index) { - const CodeGenInstruction::OperandInfo &operandInfo = - inst.OperandList[index]; + const CGIOperandList::OperandInfo &operandInfo = inst.Operands[index]; Record &rec = *operandInfo.Rec; if (X86TypeFromOpName(operandTypes[index], rec.getName())) { @@ -376,7 +375,7 @@ static inline void decorate1( const char *opFlag) { unsigned opIndex; - opIndex = inst.getOperandNamed(std::string(opName)); + opIndex = inst.Operands.getOperandNamed(std::string(opName)); operandFlags[opIndex]->addEntry(opFlag); } @@ -648,7 +647,7 @@ static void ARMPopulateOperands( return; unsigned int index; - unsigned int numOperands = inst.OperandList.size(); + unsigned int numOperands = inst.Operands.size(); if (numOperands > EDIS_MAX_OPERANDS) { errs() << "numOperands == " << numOperands << " > " << @@ -657,8 +656,7 @@ static void ARMPopulateOperands( } for (index = 0; index < numOperands; ++index) { - const CodeGenInstruction::OperandInfo &operandInfo = - inst.OperandList[index]; + const CGIOperandList::OperandInfo &operandInfo = inst.Operands[index]; Record &rec = *operandInfo.Rec; if (ARMFlagFromOpName(operandTypes[index], rec.getName())) { @@ -709,7 +707,7 @@ static void ARMExtractSemantics( BRANCH("func"); unsigned opIndex; - opIndex = inst.getOperandNamed("func"); + opIndex = inst.Operands.getOperandNamed("func"); if (operandTypes[opIndex]->is("kOperandTypeImmediate")) operandTypes[opIndex]->set("kOperandTypeARMBranchTarget"); } @@ -740,7 +738,7 @@ static void populateInstInfo(CompoundConstantEmitter &infoArray, infoStruct->addEntry(instType); LiteralConstantEmitter *numOperandsEmitter = - new LiteralConstantEmitter(inst.OperandList.size()); + new LiteralConstantEmitter(inst.Operands.size()); infoStruct->addEntry(numOperandsEmitter); CompoundConstantEmitter *operandTypeArray = new CompoundConstantEmitter; diff --git a/utils/TableGen/FastISelEmitter.cpp b/utils/TableGen/FastISelEmitter.cpp index 6c16fcfaa8a..0039506f621 100644 --- a/utils/TableGen/FastISelEmitter.cpp +++ b/utils/TableGen/FastISelEmitter.cpp @@ -263,7 +263,7 @@ void FastISelMap::CollectPatterns(CodeGenDAGPatterns &CGP) { if (!Op->isSubClassOf("Instruction")) continue; CodeGenInstruction &II = CGP.getTargetInfo().getInstruction(Op); - if (II.OperandList.empty()) + if (II.Operands.size() == 0) continue; // For now, ignore multi-instruction patterns. @@ -285,7 +285,7 @@ void FastISelMap::CollectPatterns(CodeGenDAGPatterns &CGP) { const CodeGenRegisterClass *DstRC = 0; std::string SubRegNo; if (Op->getName() != "EXTRACT_SUBREG") { - Record *Op0Rec = II.OperandList[0].Rec; + Record *Op0Rec = II.Operands[0].Rec; if (!Op0Rec->isSubClassOf("RegisterClass")) continue; DstRC = &Target.getRegisterClass(Op0Rec); diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp index 4d3aa5e621c..e04ab6c4ef9 100644 --- a/utils/TableGen/InstrInfoEmitter.cpp +++ b/utils/TableGen/InstrInfoEmitter.cpp @@ -60,23 +60,23 @@ std::vector InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) { std::vector Result; - for (unsigned i = 0, e = Inst.OperandList.size(); i != e; ++i) { + for (unsigned i = 0, e = Inst.Operands.size(); i != e; ++i) { // Handle aggregate operands and normal operands the same way by expanding // either case into a list of operands for this op. - std::vector OperandList; + std::vector OperandList; // This might be a multiple operand thing. Targets like X86 have // registers in their multi-operand operands. It may also be an anonymous // operand, which has a single operand, but no declared class for the // operand. - DagInit *MIOI = Inst.OperandList[i].MIOperandInfo; + DagInit *MIOI = Inst.Operands[i].MIOperandInfo; if (!MIOI || MIOI->getNumArgs() == 0) { // Single, anonymous, operand. - OperandList.push_back(Inst.OperandList[i]); + OperandList.push_back(Inst.Operands[i]); } else { - for (unsigned j = 0, e = Inst.OperandList[i].MINumOperands; j != e; ++j) { - OperandList.push_back(Inst.OperandList[i]); + for (unsigned j = 0, e = Inst.Operands[i].MINumOperands; j != e; ++j) { + OperandList.push_back(Inst.Operands[i]); Record *OpR = dynamic_cast(MIOI->getArg(j))->getDef(); OperandList.back().Rec = OpR; @@ -104,19 +104,19 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) { // Predicate operands. Check to see if the original unexpanded operand // was of type PredicateOperand. - if (Inst.OperandList[i].Rec->isSubClassOf("PredicateOperand")) + if (Inst.Operands[i].Rec->isSubClassOf("PredicateOperand")) Res += "|(1<isSubClassOf("OptionalDefOperand")) + if (Inst.Operands[i].Rec->isSubClassOf("OptionalDefOperand")) Res += "|(1<getName() << "\", 0"; // Emit all of the target indepedent flags... @@ -283,9 +283,9 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, if (Inst.isTerminator) OS << "|(1<getName(); AsmString = Rec->getValueAsString("AsmString"); - Operands = &insn.OperandList; + Operands = &insn.Operands.OperandList; IsSSE = HasOpSizePrefix && (Name.find("16") == Name.npos); HasFROperands = false; @@ -424,7 +424,7 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { Spec->insnContext = insnContext(); - const std::vector &OperandList = *Operands; + const std::vector &OperandList = *Operands; unsigned operandIndex; unsigned numOperands = OperandList.size(); @@ -440,7 +440,7 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { for (operandIndex = 0; operandIndex < numOperands; ++operandIndex) { if (OperandList[operandIndex].Constraints.size()) { - const CodeGenInstruction::ConstraintInfo &Constraint = + const CGIOperandList::ConstraintInfo &Constraint = OperandList[operandIndex].Constraints[0]; if (Constraint.isTied()) { operandMapping[operandIndex] = Constraint.getTiedOperand(); diff --git a/utils/TableGen/X86RecognizableInstr.h b/utils/TableGen/X86RecognizableInstr.h index db4d96dda03..113b3bdb37c 100644 --- a/utils/TableGen/X86RecognizableInstr.h +++ b/utils/TableGen/X86RecognizableInstr.h @@ -76,7 +76,8 @@ private: /// The operands of the instruction, as listed in the CodeGenInstruction. /// They are not one-to-one with operands listed in the MCInst; for example, /// memory operands expand to 5 operands in the MCInst - const std::vector* Operands; + const std::vector* Operands; + /// The description of the instruction that is emitted into the instruction /// info table InstructionSpecifier* Spec;