#include "InstrInfoEmitter.h"
#include "CodeGenTarget.h"
+#include "llvm/Target/TargetInstrInfo.h"
#include "Record.h"
#include <algorithm>
using namespace llvm;
}
if (Namespace.empty()) {
- std::cerr << "No instructions defined!\n";
+ cerr << "No instructions defined!\n";
exit(1);
}
OS << "0 };\n";
}
-static std::vector<std::pair<Record*, unsigned> >
-GetOperandInfo(const CodeGenInstruction &Inst) {
- std::vector<std::pair<Record*, unsigned> > Result;
+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) {
- if (Inst.OperandList[i].Rec->isSubClassOf("RegisterClass")) {
- Result.push_back(std::make_pair(Inst.OperandList[i].Rec,
- Inst.ConstraintsList[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;
+
+ // 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;
+
+ if (!MIOI || MIOI->getNumArgs() == 0) {
+ // Single, anonymous, operand.
+ OperandList.push_back(Inst.OperandList[i]);
} else {
- // This might be a multiple operand thing.
- // Targets like X86 have registers in their multi-operand operands.
- DagInit *MIOI = Inst.OperandList[i].MIOperandInfo;
- unsigned NumDefs = MIOI->getNumArgs();
for (unsigned j = 0, e = Inst.OperandList[i].MINumOperands; j != e; ++j) {
- if (NumDefs <= j) {
- Result.push_back(std::make_pair((Record*)0, Inst.ConstraintsList[i]));
- } else {
- DefInit *Def = dynamic_cast<DefInit*>(MIOI->getArg(j));
- Result.push_back(std::make_pair(Def ? Def->getDef() : 0,
- Inst.ConstraintsList[i]));
- }
+ OperandList.push_back(Inst.OperandList[i]);
+
+ Record *OpR = dynamic_cast<DefInit*>(MIOI->getArg(j))->getDef();
+ OperandList.back().Rec = OpR;
}
}
- }
- // For backward compatibility: isTwoAddress means operand 1 is tied to
- // operand 0.
- if (Inst.isTwoAddress)
- Result[1].second |= 1;
+ for (unsigned j = 0, e = OperandList.size(); j != e; ++j) {
+ Record *OpR = OperandList[j].Rec;
+ std::string Res;
+
+ if (OpR->isSubClassOf("RegisterClass"))
+ Res += getQualifiedName(OpR) + "RegClassID, ";
+ else
+ Res += "0, ";
+ // Fill in applicable flags.
+ Res += "0";
+
+ // Ptr value whose register class is resolved via callback.
+ if (OpR->getName() == "ptr_rc")
+ Res += "|M_LOOK_UP_PTR_REG_CLASS";
+
+ // Predicate operands. Check to see if the original unexpanded operand
+ // was of type PredicateOperand.
+ if (j == 0 && Inst.OperandList[i].Rec->isSubClassOf("PredicateOperand"))
+ Res += "|M_PREDICATE_OPERAND";
+
+ // Fill in constraint info.
+ Res += ", " + Inst.OperandList[i].Constraints[j];
+ Result.push_back(Res);
+ }
+ }
return Result;
}
}
}
- std::map<std::vector<std::pair<Record*, unsigned> >, unsigned>
- OperandInfosEmitted;
+ std::map<std::vector<std::string>, unsigned> OperandInfosEmitted;
unsigned OperandListNum = 0;
- OperandInfosEmitted[std::vector<std::pair<Record*, unsigned> >()] =
- ++OperandListNum;
+ OperandInfosEmitted[std::vector<std::string>()] = ++OperandListNum;
// Emit all of the operand info records.
OS << "\n";
for (CodeGenTarget::inst_iterator II = Target.inst_begin(),
E = Target.inst_end(); II != E; ++II) {
- std::vector<std::pair<Record*, unsigned> > OperandInfo =
- GetOperandInfo(II->second);
+ std::vector<std::string> OperandInfo = GetOperandInfo(II->second);
unsigned &N = OperandInfosEmitted[OperandInfo];
if (N == 0) {
N = ++OperandListNum;
OS << "static const TargetOperandInfo OperandInfo" << N << "[] = { ";
- for (unsigned i = 0, e = OperandInfo.size(); i != e; ++i) {
- Record *RC = OperandInfo[i].first;
- // FIXME: We only care about register operands for now.
- if (RC && RC->isSubClassOf("RegisterClass"))
- OS << "{ " << getQualifiedName(RC) << "RegClassID, 0, ";
- else if (RC && RC->getName() == "ptr_rc")
- // Ptr value whose register class is resolved via callback.
- OS << "{ 0, 1, ";
- else
- OS << "{ 0, 0, ";
- OS << OperandInfo[i].second << " }, ";
- }
+ for (unsigned i = 0, e = OperandInfo.size(); i != e; ++i)
+ OS << "{ " << OperandInfo[i] << " }, ";
OS << "};\n";
}
}
void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
Record *InstrInfo,
std::map<std::vector<Record*>, unsigned> &EmittedLists,
- std::map<std::vector<std::pair<Record*,unsigned> >, unsigned> &OpInfo,
+ std::map<std::vector<std::string>, unsigned> &OpInfo,
std::ostream &OS) {
int MinOperands;
if (!Inst.OperandList.empty())
else
MinOperands = 0;
- OS << " { \"";
+ OS << " { ";
+ OS << Num << ",\t" << MinOperands << ",\t\"";
+
if (Inst.Name.empty())
OS << Inst.TheDef->getName();
else
unsigned ItinClass = !IsItineraries ? 0 :
ItinClassNumber(Inst.TheDef->getValueAsDef("Itinerary")->getName());
- OS << "\",\t" << MinOperands << ", " << ItinClass
- << ", 0";
+ OS << "\",\t" << ItinClass << ", 0";
// Try to determine (from the pattern), if the instruction is a store.
bool isStore = false;
if (Inst.isCall) OS << "|M_CALL_FLAG";
if (Inst.isLoad) OS << "|M_LOAD_FLAG";
if (Inst.isStore || isStore) OS << "|M_STORE_FLAG";
- if (Inst.isTwoAddress) OS << "|M_2_ADDR_FLAG";
+ if (Inst.isPredicated) OS << "|M_PREDICATED";
if (Inst.isConvertibleToThreeAddress) OS << "|M_CONVERTIBLE_TO_3_ADDR";
if (Inst.isCommutable) OS << "|M_COMMUTABLE";
if (Inst.isTerminator) OS << "|M_TERMINATOR_FLAG";
OS << "ImplicitList" << EmittedLists[DefList] << ", ";
// Emit the operand info.
- std::vector<std::pair<Record*,unsigned> > OperandInfo = GetOperandInfo(Inst);
+ std::vector<std::string> OperandInfo = GetOperandInfo(Inst);
if (OperandInfo.empty())
OS << "0";
else
return;
}
- std::cerr << "Unhandled initializer: " << *Val << "\n";
+ cerr << "Unhandled initializer: " << *Val << "\n";
throw "In record '" + R->getName() + "' for TSFlag emission.";
}