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
This commit is contained in:
Chris Lattner 2010-11-01 04:03:32 +00:00
parent 79b3cddfa2
commit c240bb0ede
13 changed files with 343 additions and 304 deletions

View File

@ -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;

View File

@ -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<std::pair<unsigned, unsigned>, 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);
}

View File

@ -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,

View File

@ -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<unsigned, unsigned> SO = CGI.getSubOperandNumber(OpIdx);
std::pair<unsigned, unsigned> 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.

View File

@ -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<Record*> 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<TreePatternNode*> ResultNodeOperands;
std::vector<Record*> 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;
}
}

View File

@ -19,134 +19,32 @@
#include <set>
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<unsigned,unsigned> Op =
I->ParseOperandName(Name, false);
//===----------------------------------------------------------------------===//
// CGIOperandList Implementation
//===----------------------------------------------------------------------===//
// 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<unsigned,unsigned> 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<unsigned,unsigned> 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");
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<DefInit*>(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<DefInit*>(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<std::string> 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<DefInit*>(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<DefInit*>(MIOpInfo->getOperator()) ||
dynamic_cast<DefInit*>(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<unsigned,unsigned> 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<unsigned,unsigned>
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<unsigned,unsigned> 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<unsigned,unsigned> 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<unsigned,unsigned> 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<unsigned,unsigned> 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;
}

View File

@ -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,35 +84,113 @@ 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<bool> 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<ConstraintInfo> 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<OperandInfo> OperandList;
// Information gleaned from the operand list.
bool isPredicable;
bool hasOptionalDef;
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
/// true, references to operands with suboperands are allowed, otherwise
/// not.
std::pair<unsigned,unsigned> ParseOperandName(const std::string &Op,
bool AllowWholeOp = true);
/// getFlattenedOperandNumber - Flatten a operand/suboperand pair into a
/// flat machineinstr operand #.
unsigned getFlattenedOperandNumber(std::pair<unsigned,unsigned> Op) const {
return OperandList[Op.first].MIOperandNo + Op.second;
}
/// getSubOperandNumber - Unflatten a operand number into an
/// operand/suboperand pair.
std::pair<unsigned,unsigned> getSubOperandNumber(unsigned Op) const {
for (unsigned i = 0; ; ++i) {
assert(i < OperandList.size() && "Invalid flat operand #");
if (OperandList[i].MIOperandNo+OperandList[i].MINumOperands > Op)
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 {
std::pair<unsigned,unsigned> Op = getSubOperandNumber(FlatOpNo);
if (OperandList[Op.first].DoNotEncode.size() > Op.second)
return OperandList[Op.first].DoNotEncode[Op.second];
return false;
}
void ProcessDisableEncoding(std::string Value);
};
class CodeGenInstruction {
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;
/// 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.
@ -141,62 +212,17 @@ namespace llvm {
bool isReMaterializable;
bool hasDelaySlot;
bool usesCustomInserter;
bool isVariadic;
bool hasCtrlDep;
bool isNotDuplicable;
bool hasOptionalDef;
bool hasSideEffects;
bool neverHasSideEffects;
bool isAsCheapAsAMove;
bool hasExtraSrcRegAllocReq;
bool hasExtraDefRegAllocReq;
/// 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
/// true, references to operands with suboperands are allowed, otherwise
/// not.
std::pair<unsigned,unsigned> ParseOperandName(const std::string &Op,
bool AllowWholeOp = true);
/// getFlattenedOperandNumber - Flatten a operand/suboperand pair into a
/// flat machineinstr operand #.
unsigned getFlattenedOperandNumber(std::pair<unsigned,unsigned> Op) const {
return OperandList[Op.first].MIOperandNo + Op.second;
}
/// getSubOperandNumber - Unflatten a operand number into an
/// operand/suboperand pair.
std::pair<unsigned,unsigned> getSubOperandNumber(unsigned Op) const {
for (unsigned i = 0; ; ++i) {
assert(i < OperandList.size() && "Invalid flat operand #");
if (OperandList[i].MIOperandNo+OperandList[i].MINumOperands > Op)
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 {
std::pair<unsigned,unsigned> Op = getSubOperandNumber(FlatOpNo);
if (OperandList[Op.first].DoNotEncode.size() > Op.second)
return OperandList[Op.first].DoNotEncode[Op.second];
return false;
}
CodeGenInstruction(Record *R);
/// 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;
/// HasOneImplicitDefWithKnownVT - If the instruction has at least one
/// implicit def and it has a known VT, return the VT, otherwise return
/// MVT::Other.
@ -209,6 +235,6 @@ namespace llvm {
static std::string FlattenAsmStringVariants(StringRef AsmString,
unsigned Variant);
};
}
}
#endif

View File

@ -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<unsigned, 8> 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()) {

View File

@ -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;

View File

@ -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);

View File

@ -60,23 +60,23 @@ std::vector<std::string>
InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
std::vector<std::string> 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<CodeGenInstruction::OperandInfo> OperandList;
std::vector<CGIOperandList::OperandInfo> 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<DefInit*>(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<<TOI::Predicate)";
// Optional def operands. Check to see if the original unexpanded operand
// was of type OptionalDefOperand.
if (Inst.OperandList[i].Rec->isSubClassOf("OptionalDefOperand"))
if (Inst.Operands[i].Rec->isSubClassOf("OptionalDefOperand"))
Res += "|(1<<TOI::OptionalDef)";
// Fill in constraint info.
Res += ", ";
const CodeGenInstruction::ConstraintInfo &Constraint =
Inst.OperandList[i].Constraints[j];
const CGIOperandList::ConstraintInfo &Constraint =
Inst.Operands[i].Constraints[j];
if (Constraint.isNone())
Res += "0";
else if (Constraint.isEarlyClobber())
@ -256,14 +256,14 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
const OperandInfoMapTy &OpInfo,
raw_ostream &OS) {
int MinOperands = 0;
if (!Inst.OperandList.empty())
if (!Inst.Operands.size() == 0)
// Each logical operand can be multiple MI operands.
MinOperands = Inst.OperandList.back().MIOperandNo +
Inst.OperandList.back().MINumOperands;
MinOperands = Inst.Operands.back().MIOperandNo +
Inst.Operands.back().MINumOperands;
OS << " { ";
OS << Num << ",\t" << MinOperands << ",\t"
<< Inst.NumDefs << ",\t" << getItinClassNumber(Inst.TheDef)
<< Inst.Operands.NumDefs << ",\t" << getItinClassNumber(Inst.TheDef)
<< ",\t\"" << Inst.TheDef->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<<TID::Terminator)";
if (Inst.isReMaterializable) OS << "|(1<<TID::Rematerializable)";
if (Inst.isNotDuplicable) OS << "|(1<<TID::NotDuplicable)";
if (Inst.hasOptionalDef) OS << "|(1<<TID::HasOptionalDef)";
if (Inst.Operands.hasOptionalDef) OS << "|(1<<TID::HasOptionalDef)";
if (Inst.usesCustomInserter) OS << "|(1<<TID::UsesCustomInserter)";
if (Inst.isVariadic) OS << "|(1<<TID::Variadic)";
if (Inst.Operands.isVariadic)OS << "|(1<<TID::Variadic)";
if (Inst.hasSideEffects) OS << "|(1<<TID::UnmodeledSideEffects)";
if (Inst.isAsCheapAsAMove) OS << "|(1<<TID::CheapAsAMove)";
if (Inst.hasExtraSrcRegAllocReq) OS << "|(1<<TID::ExtraSrcRegAllocReq)";

View File

@ -219,7 +219,7 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables,
Name = Rec->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<CodeGenInstruction::OperandInfo> &OperandList = *Operands;
const std::vector<CGIOperandList::OperandInfo> &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();

View File

@ -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<CodeGenInstruction::OperandInfo>* Operands;
const std::vector<CGIOperandList::OperandInfo>* Operands;
/// The description of the instruction that is emitted into the instruction
/// info table
InstructionSpecifier* Spec;