mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-12 02:33:33 +00:00
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:
parent
79b3cddfa2
commit
c240bb0ede
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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()) {
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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)";
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user