//
// Some targets need a custom way to parse operands, some specific instructions
// can contain arguments that can represent processor flags and other kinds of
-// identifiers that need to be mapped to specific valeus in the final encoded
+// identifiers that need to be mapped to specific values in the final encoded
// instructions. The target specific custom operand parsing works in the
// following way:
//
return Kind >= UserClass0;
}
- /// isRelatedTo - Check whether this class is "related" to \arg RHS. Classes
+ /// isRelatedTo - Check whether this class is "related" to \p RHS. Classes
/// are related if they are in the same class hierarchy.
bool isRelatedTo(const ClassInfo &RHS) const {
// Tokens are only related to tokens.
return Root == RHSRoot;
}
- /// isSubsetOf - Test whether this class is a subset of \arg RHS;
+ /// isSubsetOf - Test whether this class is a subset of \p RHS.
bool isSubsetOf(const ClassInfo &RHS) const {
// This is a subset of RHS if it is the same class...
if (this == &RHS)
}
};
+namespace {
+/// Sort ClassInfo pointers independently of pointer value.
+struct LessClassInfoPtr {
+ bool operator()(const ClassInfo *LHS, const ClassInfo *RHS) const {
+ return *LHS < *RHS;
+ }
+};
+}
+
/// MatchableInfo - Helper class for storing the necessary information for an
/// instruction or alias which is capable of being matched.
struct MatchableInfo {
}
/// couldMatchAmbiguouslyWith - Check whether this matchable could
- /// ambiguously match the same set of operands as \arg RHS (without being a
+ /// ambiguously match the same set of operands as \p RHS (without being a
/// strictly superior match).
bool couldMatchAmbiguouslyWith(const MatchableInfo &RHS) {
// The primary comparator is the instruction mnemonic.
std::vector<OperandMatchEntry> OperandMatchInfo;
/// Map of Register records to their class information.
- std::map<Record*, ClassInfo*> RegisterClasses;
+ typedef std::map<Record*, ClassInfo*, LessRecordByID> RegisterClassesTy;
+ RegisterClassesTy RegisterClasses;
/// Map of Predicate records to their subtarget information.
std::map<Record*, SubtargetFeatureInfo*> SubtargetFeatures;
/// Map containing a mask with all operands indices that can be found for
/// that class inside a instruction.
- std::map<ClassInfo*, unsigned> OpClassMask;
+ typedef std::map<ClassInfo*, unsigned, LessClassInfoPtr> OpClassMaskTy;
+ OpClassMaskTy OpClassMask;
for (std::vector<MatchableInfo*>::const_iterator it =
Matchables.begin(), ie = Matchables.end();
}
// Generate operand match info for each mnemonic/operand class pair.
- for (std::map<ClassInfo*, unsigned>::iterator iit = OpClassMask.begin(),
+ for (OpClassMaskTy::iterator iit = OpClassMask.begin(),
iie = OpClassMask.end(); iit != iie; ++iit) {
unsigned OpMask = iit->second;
ClassInfo *CI = iit->first;
<< " const SmallVectorImpl<MCParsedAsmOperand*"
<< "> &Operands) {\n"
<< " assert(Kind < CVT_NUM_SIGNATURES && \"Invalid signature!\");\n"
- << " uint8_t *Converter = ConversionTable[Kind];\n"
+ << " const uint8_t *Converter = ConversionTable[Kind];\n"
<< " Inst.setOpcode(Opcode);\n"
- << " for (uint8_t *p = Converter; *p; p+= 2) {\n"
+ << " for (const uint8_t *p = Converter; *p; p+= 2) {\n"
<< " switch (*p) {\n"
<< " default: llvm_unreachable(\"invalid conversion entry!\");\n"
<< " case CVT_Reg:\n"
<< " assert(Kind < CVT_NUM_SIGNATURES && \"Invalid signature!\");\n"
<< " NumMCOperands = 0;\n"
<< " unsigned MCOperandNum = 0;\n"
- << " uint8_t *Converter = ConversionTable[Kind];\n"
- << " for (uint8_t *p = Converter; *p; p+= 2) {\n"
+ << " const uint8_t *Converter = ConversionTable[Kind];\n"
+ << " for (const uint8_t *p = Converter; *p; p+= 2) {\n"
<< " if (*(p + 1) > OperandNum) continue;\n"
<< " switch (*p) {\n"
<< " default: llvm_unreachable(\"invalid conversion entry!\");\n"
OS << "} // end anonymous namespace\n\n";
// Output the conversion table.
- OS << "static uint8_t ConversionTable[CVT_NUM_SIGNATURES]["
+ OS << "static const uint8_t ConversionTable[CVT_NUM_SIGNATURES]["
<< MaxRowLength << "] = {\n";
for (unsigned Row = 0, ERow = ConversionTable.size(); Row != ERow; ++Row) {
OS << " MatchClassKind OpKind;\n";
OS << " switch (Operand.getReg()) {\n";
OS << " default: OpKind = InvalidMatchClass; break;\n";
- for (std::map<Record*, ClassInfo*>::iterator
+ for (AsmMatcherInfo::RegisterClassesTy::iterator
it = Info.RegisterClasses.begin(), ie = Info.RegisterClasses.end();
it != ie; ++it)
OS << " case " << Info.Target.getName() << "::"
static void emitIsSubclass(CodeGenTarget &Target,
std::vector<ClassInfo*> &Infos,
raw_ostream &OS) {
- OS << "/// isSubclass - Compute whether \\arg A is a subclass of \\arg B.\n";
+ OS << "/// isSubclass - Compute whether \\p A is a subclass of \\p B.\n";
OS << "static bool isSubclass(MatchClassKind A, MatchClassKind B) {\n";
OS << " if (A == B)\n";
OS << " return true;\n\n";
}
static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
- const AsmMatcherInfo &Info, StringRef ClassName) {
+ const AsmMatcherInfo &Info, StringRef ClassName,
+ StringToOffsetTable &StringTable,
+ unsigned MaxMnemonicIndex) {
+ unsigned MaxMask = 0;
+ for (std::vector<OperandMatchEntry>::const_iterator it =
+ Info.OperandMatchInfo.begin(), ie = Info.OperandMatchInfo.end();
+ it != ie; ++it) {
+ MaxMask |= it->OperandMask;
+ }
+
// Emit the static custom operand parsing table;
OS << "namespace {\n";
OS << " struct OperandMatchEntry {\n";
- OS << " static const char *const MnemonicTable;\n";
- OS << " uint32_t OperandMask;\n";
- OS << " uint32_t Mnemonic;\n";
OS << " " << getMinimalTypeForRange(1ULL << Info.SubtargetFeatures.size())
<< " RequiredFeatures;\n";
+ OS << " " << getMinimalTypeForRange(MaxMnemonicIndex)
+ << " Mnemonic;\n";
OS << " " << getMinimalTypeForRange(Info.Classes.size())
- << " Class;\n\n";
+ << " Class;\n";
+ OS << " " << getMinimalTypeForRange(MaxMask)
+ << " OperandMask;\n\n";
OS << " StringRef getMnemonic() const {\n";
OS << " return StringRef(MnemonicTable + Mnemonic + 1,\n";
OS << " MnemonicTable[Mnemonic]);\n";
OS << "} // end anonymous namespace.\n\n";
- StringToOffsetTable StringTable;
-
OS << "static const OperandMatchEntry OperandMatchTable["
<< Info.OperandMatchInfo.size() << "] = {\n";
const OperandMatchEntry &OMI = *it;
const MatchableInfo &II = *OMI.MI;
- OS << " { " << OMI.OperandMask;
+ OS << " { ";
+
+ // Write the required features mask.
+ if (!II.RequiredFeatures.empty()) {
+ for (unsigned i = 0, e = II.RequiredFeatures.size(); i != e; ++i) {
+ if (i) OS << "|";
+ OS << II.RequiredFeatures[i]->getEnumName();
+ }
+ } else
+ OS << "0";
+
+ // Store a pascal-style length byte in the mnemonic.
+ std::string LenMnemonic = char(II.Mnemonic.size()) + II.Mnemonic.str();
+ OS << ", " << StringTable.GetOrAddStringOffset(LenMnemonic, false)
+ << " /* " << II.Mnemonic << " */, ";
+
+ OS << OMI.CI->Name;
+ OS << ", " << OMI.OperandMask;
OS << " /* ";
bool printComma = false;
for (int i = 0, e = 31; i !=e; ++i)
}
OS << " */";
- // Store a pascal-style length byte in the mnemonic.
- std::string LenMnemonic = char(II.Mnemonic.size()) + II.Mnemonic.str();
- OS << ", " << StringTable.GetOrAddStringOffset(LenMnemonic, false)
- << " /* " << II.Mnemonic << " */, ";
-
- // Write the required features mask.
- if (!II.RequiredFeatures.empty()) {
- for (unsigned i = 0, e = II.RequiredFeatures.size(); i != e; ++i) {
- if (i) OS << "|";
- OS << II.RequiredFeatures[i]->getEnumName();
- }
- } else
- OS << "0";
-
- OS << ", " << OMI.CI->Name;
-
OS << " },\n";
}
OS << "};\n\n";
- OS << "const char *const OperandMatchEntry::MnemonicTable =\n";
- StringTable.EmitString(OS);
- OS << ";\n\n";
-
// Emit the operand class switch to call the correct custom parser for
// the found operand class.
OS << Target.getName() << ClassName << "::OperandMatchResultTy "
<< "unsigned Opcode,\n"
<< " const SmallVectorImpl<MCParsedAsmOperand*> "
<< "&Operands);\n";
- OS << " unsigned getMCInstOperandNumImpl(unsigned Kind, MCInst &Inst,\n "
- << " const "
+ OS << " unsigned getMCInstOperandNumImpl(unsigned Kind, MCInst &Inst,\n"
+ << " const "
<< "SmallVectorImpl<MCParsedAsmOperand*> &Operands,\n "
<< " unsigned OperandNum, unsigned &NumMCOperands);\n";
OS << " bool MnemonicIsValid(StringRef Mnemonic);\n";
emitComputeAvailableFeatures(Info, OS);
+ StringToOffsetTable StringTable;
+
size_t MaxNumOperands = 0;
+ unsigned MaxMnemonicIndex = 0;
for (std::vector<MatchableInfo*>::const_iterator it =
Info.Matchables.begin(), ie = Info.Matchables.end();
- it != ie; ++it)
- MaxNumOperands = std::max(MaxNumOperands, (*it)->AsmOperands.size());
+ it != ie; ++it) {
+ MatchableInfo &II = **it;
+ MaxNumOperands = std::max(MaxNumOperands, II.AsmOperands.size());
+
+ // Store a pascal-style length byte in the mnemonic.
+ std::string LenMnemonic = char(II.Mnemonic.size()) + II.Mnemonic.str();
+ MaxMnemonicIndex = std::max(MaxMnemonicIndex,
+ StringTable.GetOrAddStringOffset(LenMnemonic, false));
+ }
+
+ OS << "static const char *const MnemonicTable =\n";
+ StringTable.EmitString(OS);
+ OS << ";\n\n";
// Emit the static match table; unused classes get initalized to 0 which is
// guaranteed to be InvalidMatchClass.
// following the mnemonic.
OS << "namespace {\n";
OS << " struct MatchEntry {\n";
- OS << " static const char *const MnemonicTable;\n";
- OS << " uint32_t Mnemonic;\n";
+ OS << " " << getMinimalTypeForRange(MaxMnemonicIndex)
+ << " Mnemonic;\n";
OS << " uint16_t Opcode;\n";
OS << " " << getMinimalTypeForRange(Info.Matchables.size())
<< " ConvertFn;\n";
OS << "} // end anonymous namespace.\n\n";
- StringToOffsetTable StringTable;
-
OS << "static const MatchEntry MatchTable["
<< Info.Matchables.size() << "] = {\n";
OS << "};\n\n";
- OS << "const char *const MatchEntry::MnemonicTable =\n";
- StringTable.EmitString(OS);
- OS << ";\n\n";
-
// A method to determine if a mnemonic is in the list.
OS << "bool " << Target.getName() << ClassName << "::\n"
<< "MnemonicIsValid(StringRef Mnemonic) {\n";
OS << "}\n\n";
if (Info.OperandMatchInfo.size())
- emitCustomOperandParsing(OS, Target, Info, ClassName);
+ emitCustomOperandParsing(OS, Target, Info, ClassName, StringTable,
+ MaxMnemonicIndex);
OS << "#endif // GET_MATCHER_IMPLEMENTATION\n\n";
}