}
/// operator< - Compare two classes.
+ // FIXME: This ordering seems to be broken. For example:
+ // u64 < i64, i64 < s8, s8 < u64, forming a cycle
+ // u64 is a subset of i64
+ // i64 and s8 are not subsets of each other, so are ordered by name
+ // s8 and u64 are not subsets of each other, so are ordered by name
bool operator<(const ClassInfo &RHS) const {
if (this == &RHS)
return false;
/// The suboperand index within SrcOpName, or -1 for the entire operand.
int SubOpIdx;
+ /// Whether the token is "isolated", i.e., it is preceded and followed
+ /// by separators.
+ bool IsIsolatedToken;
+
/// Register record if this token is singleton register.
Record *SingletonReg;
- explicit AsmOperand(StringRef T) : Token(T), Class(nullptr), SubOpIdx(-1),
- SingletonReg(nullptr) {}
+ explicit AsmOperand(bool IsIsolatedToken, StringRef T)
+ : Token(T), Class(nullptr), SubOpIdx(-1),
+ IsIsolatedToken(IsIsolatedToken), SingletonReg(nullptr) {}
};
/// ResOperand - This represents a single operand in the result instruction
/// AsmVariantID - Target's assembly syntax variant no.
int AsmVariantID;
+ /// AsmString - The assembly string for this instruction (with variants
+ /// removed), e.g. "movsx $src, $dst".
+ std::string AsmString;
+
/// TheDef - This is the definition of the instruction or InstAlias that this
/// matchable came from.
Record *const TheDef;
/// MCInst.
SmallVector<ResOperand, 8> ResOperands;
- /// AsmString - The assembly string for this instruction (with variants
- /// removed), e.g. "movsx $src, $dst".
- std::string AsmString;
-
/// Mnemonic - This is the first token of the matched instruction, its
/// mnemonic.
StringRef Mnemonic;
SmallVector<AsmOperand, 8> AsmOperands;
/// Predicates - The required subtarget features to match this instruction.
- SmallVector<SubtargetFeatureInfo*, 4> RequiredFeatures;
+ SmallVector<const SubtargetFeatureInfo *, 4> RequiredFeatures;
/// ConversionFnKind - The enum value which is passed to the generated
/// convertToMCInst to convert parsed operands into an MCInst for this
/// If this instruction is deprecated in some form.
bool HasDeprecation;
+ /// If this is an alias, this is use to determine whether or not to using
+ /// the conversion function defined by the instruction's AsmMatchConverter
+ /// or to use the function generated by the alias.
+ bool UseInstAsmMatchConverter;
+
MatchableInfo(const CodeGenInstruction &CGI)
- : AsmVariantID(0), TheDef(CGI.TheDef), DefRec(&CGI),
- AsmString(CGI.AsmString) {
+ : AsmVariantID(0), AsmString(CGI.AsmString), TheDef(CGI.TheDef), DefRec(&CGI),
+ UseInstAsmMatchConverter(true) {
+ }
+
+ MatchableInfo(std::unique_ptr<const CodeGenInstAlias> Alias)
+ : AsmVariantID(0), AsmString(Alias->AsmString), TheDef(Alias->TheDef),
+ DefRec(Alias.release()),
+ UseInstAsmMatchConverter(
+ TheDef->getValueAsBit("UseInstAsmMatchConverter")) {
}
- MatchableInfo(const CodeGenInstAlias *Alias)
- : AsmVariantID(0), TheDef(Alias->TheDef), DefRec(Alias),
- AsmString(Alias->AsmString) {
+ // Could remove this and the dtor if PointerUnion supported unique_ptr
+ // elements with a dynamic failure/assertion (like the one below) in the case
+ // where it was copied while being in an owning state.
+ MatchableInfo(const MatchableInfo &RHS)
+ : AsmVariantID(RHS.AsmVariantID), AsmString(RHS.AsmString),
+ TheDef(RHS.TheDef), DefRec(RHS.DefRec), ResOperands(RHS.ResOperands),
+ Mnemonic(RHS.Mnemonic), AsmOperands(RHS.AsmOperands),
+ RequiredFeatures(RHS.RequiredFeatures),
+ ConversionFnKind(RHS.ConversionFnKind),
+ HasDeprecation(RHS.HasDeprecation),
+ UseInstAsmMatchConverter(RHS.UseInstAsmMatchConverter) {
+ assert(!DefRec.is<const CodeGenInstAlias *>());
}
~MatchableInfo() {
- if (DefRec.is<const CodeGenInstAlias*>())
- delete DefRec.get<const CodeGenInstAlias*>();
+ delete DefRec.dyn_cast<const CodeGenInstAlias*>();
}
// Two-operand aliases clone from the main matchable, but mark the second
void initialize(const AsmMatcherInfo &Info,
SmallPtrSetImpl<Record*> &SingletonRegisters,
- int AsmVariantNo, std::string &RegisterPrefix);
+ int AsmVariantNo, StringRef RegisterPrefix);
/// validate - Return true if this matchable is a valid thing to match against
/// and perform a bunch of validity checking.
bool validate(StringRef CommentDelimiter, bool Hack) const;
- /// extractSingletonRegisterForAsmOperand - Extract singleton register,
- /// if present, from specified token.
- void
- extractSingletonRegisterForAsmOperand(unsigned i, const AsmMatcherInfo &Info,
- std::string &RegisterPrefix);
-
/// findAsmOperand - Find the AsmOperand with the specified name and
/// suboperand index.
int findAsmOperand(StringRef N, int SubOpIdx) const {
private:
void tokenizeAsmString(const AsmMatcherInfo &Info);
+ void addAsmOperand(size_t Start, size_t End);
};
/// SubtargetFeatureInfo - Helper class for storing information on a subtarget
RegisterClassesTy RegisterClasses;
/// Map of Predicate records to their subtarget information.
- std::map<Record*, std::unique_ptr<SubtargetFeatureInfo>,
- LessRecordByID> SubtargetFeatures;
+ std::map<Record *, SubtargetFeatureInfo, LessRecordByID> SubtargetFeatures;
/// Map of AsmOperandClass records to their class information.
std::map<Record*, ClassInfo*> AsmOperandClasses;
/// getSubtargetFeature - Lookup or create the subtarget feature info for the
/// given operand.
- SubtargetFeatureInfo *getSubtargetFeature(Record *Def) const {
+ const SubtargetFeatureInfo *getSubtargetFeature(Record *Def) const {
assert(Def->isSubClassOf("Predicate") && "Invalid predicate type!");
const auto &I = SubtargetFeatures.find(Def);
- return I == SubtargetFeatures.end() ? nullptr : I->second.get();
+ return I == SubtargetFeatures.end() ? nullptr : &I->second;
}
RecordKeeper &getRecords() const {
}
}
+/// extractSingletonRegisterForAsmOperand - Extract singleton register,
+/// if present, from specified token.
+static void
+extractSingletonRegisterForAsmOperand(MatchableInfo::AsmOperand &Op,
+ const AsmMatcherInfo &Info,
+ StringRef RegisterPrefix) {
+ StringRef Tok = Op.Token;
+
+ // If this token is not an isolated token, i.e., it isn't separated from
+ // other tokens (e.g. with whitespace), don't interpret it as a register name.
+ if (!Op.IsIsolatedToken)
+ return;
+
+ if (RegisterPrefix.empty()) {
+ std::string LoweredTok = Tok.lower();
+ if (const CodeGenRegister *Reg = Info.Target.getRegisterByName(LoweredTok))
+ Op.SingletonReg = Reg->TheDef;
+ return;
+ }
+
+ if (!Tok.startswith(RegisterPrefix))
+ return;
+
+ StringRef RegName = Tok.substr(RegisterPrefix.size());
+ if (const CodeGenRegister *Reg = Info.Target.getRegisterByName(RegName))
+ Op.SingletonReg = Reg->TheDef;
+
+ // If there is no register prefix (i.e. "%" in "%eax"), then this may
+ // be some random non-register token, just ignore it.
+ return;
+}
+
void MatchableInfo::initialize(const AsmMatcherInfo &Info,
SmallPtrSetImpl<Record*> &SingletonRegisters,
- int AsmVariantNo, std::string &RegisterPrefix) {
+ int AsmVariantNo, StringRef RegisterPrefix) {
AsmVariantID = AsmVariantNo;
AsmString =
CodeGenInstruction::FlattenAsmStringVariants(AsmString, AsmVariantNo);
tokenizeAsmString(Info);
// Compute the require features.
- std::vector<Record*> Predicates =TheDef->getValueAsListOfDefs("Predicates");
- for (unsigned i = 0, e = Predicates.size(); i != e; ++i)
- if (SubtargetFeatureInfo *Feature =
- Info.getSubtargetFeature(Predicates[i]))
+ for (Record *Predicate : TheDef->getValueAsListOfDefs("Predicates"))
+ if (const SubtargetFeatureInfo *Feature =
+ Info.getSubtargetFeature(Predicate))
RequiredFeatures.push_back(Feature);
// Collect singleton registers, if used.
- for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) {
- extractSingletonRegisterForAsmOperand(i, Info, RegisterPrefix);
- if (Record *Reg = AsmOperands[i].SingletonReg)
+ for (MatchableInfo::AsmOperand &Op : AsmOperands) {
+ extractSingletonRegisterForAsmOperand(Op, Info, RegisterPrefix);
+ if (Record *Reg = Op.SingletonReg)
SingletonRegisters.insert(Reg);
}
DepMask ? !DepMask->getValue()->getAsUnquotedString().empty() : false;
}
+/// Append an AsmOperand for the given substring of AsmString.
+void MatchableInfo::addAsmOperand(size_t Start, size_t End) {
+ StringRef String = AsmString;
+ StringRef Separators = "[]*! \t,";
+ // Look for separators before and after to figure out is this token is
+ // isolated. Accept '$$' as that's how we escape '$'.
+ bool IsIsolatedToken =
+ (!Start || Separators.find(String[Start - 1]) != StringRef::npos ||
+ String.substr(Start - 1, 2) == "$$") &&
+ (End >= String.size() || Separators.find(String[End]) != StringRef::npos);
+ AsmOperands.push_back(AsmOperand(IsIsolatedToken, String.slice(Start, End)));
+}
+
/// tokenizeAsmString - Tokenize a simplified assembly string.
void MatchableInfo::tokenizeAsmString(const AsmMatcherInfo &Info) {
StringRef String = AsmString;
- unsigned Prev = 0;
+ size_t Prev = 0;
bool InTok = true;
- for (unsigned i = 0, e = String.size(); i != e; ++i) {
+ for (size_t i = 0, e = String.size(); i != e; ++i) {
switch (String[i]) {
case '[':
case ']':
case '\t':
case ',':
if (InTok) {
- AsmOperands.push_back(AsmOperand(String.slice(Prev, i)));
+ addAsmOperand(Prev, i);
InTok = false;
}
if (!isspace(String[i]) && String[i] != ',')
- AsmOperands.push_back(AsmOperand(String.substr(i, 1)));
+ addAsmOperand(i, i + 1);
Prev = i + 1;
break;
case '\\':
if (InTok) {
- AsmOperands.push_back(AsmOperand(String.slice(Prev, i)));
+ addAsmOperand(Prev, i);
InTok = false;
}
++i;
assert(i != String.size() && "Invalid quoted character");
- AsmOperands.push_back(AsmOperand(String.substr(i, 1)));
+ addAsmOperand(i, i + 1);
Prev = i + 1;
break;
case '$': {
if (InTok) {
- AsmOperands.push_back(AsmOperand(String.slice(Prev, i)));
+ addAsmOperand(Prev, i);
InTok = false;
}
- // If this isn't "${", treat like a normal token.
+ // If this isn't "${", start new identifier looking like "$xxx"
if (i + 1 == String.size() || String[i + 1] != '{') {
Prev = i;
break;
}
- StringRef::iterator End = std::find(String.begin() + i, String.end(),'}');
- assert(End != String.end() && "Missing brace in operand reference!");
- size_t EndPos = End - String.begin();
- AsmOperands.push_back(AsmOperand(String.slice(i, EndPos+1)));
+ // If this is "${" find the next "}" and make an identifier like "${xxx}"
+ size_t EndPos = String.find('}', i);
+ assert(EndPos != StringRef::npos &&
+ "Missing brace in operand reference!");
+ addAsmOperand(i, EndPos+1);
Prev = EndPos + 1;
i = EndPos;
break;
case '.':
if (!Info.AsmParser->getValueAsBit("MnemonicContainsDot")) {
if (InTok)
- AsmOperands.push_back(AsmOperand(String.slice(Prev, i)));
+ addAsmOperand(Prev, i);
Prev = i;
}
InTok = true;
}
}
if (InTok && Prev != String.size())
- AsmOperands.push_back(AsmOperand(String.substr(Prev)));
+ addAsmOperand(Prev, StringRef::npos);
// The first token of the instruction is the mnemonic, which must be a
// simple string, not a $foo variable or a singleton register.
return true;
}
-/// extractSingletonRegisterForAsmOperand - Extract singleton register,
-/// if present, from specified token.
-void MatchableInfo::
-extractSingletonRegisterForAsmOperand(unsigned OperandNo,
- const AsmMatcherInfo &Info,
- std::string &RegisterPrefix) {
- StringRef Tok = AsmOperands[OperandNo].Token;
- if (RegisterPrefix.empty()) {
- std::string LoweredTok = Tok.lower();
- if (const CodeGenRegister *Reg = Info.Target.getRegisterByName(LoweredTok))
- AsmOperands[OperandNo].SingletonReg = Reg->TheDef;
- return;
- }
-
- if (!Tok.startswith(RegisterPrefix))
- return;
-
- StringRef RegName = Tok.substr(RegisterPrefix.size());
- if (const CodeGenRegister *Reg = Info.Target.getRegisterByName(RegName))
- AsmOperands[OperandNo].SingletonReg = Reg->TheDef;
-
- // If there is no register prefix (i.e. "%" in "%eax"), then this may
- // be some random non-register token, just ignore it.
- return;
-}
-
static std::string getEnumNameForToken(StringRef Str) {
std::string Res;
case '.': Res += "_DOT_"; break;
case '<': Res += "_LT_"; break;
case '>': Res += "_GT_"; break;
+ case '-': Res += "_MINUS_"; break;
default:
if ((*it >= 'A' && *it <= 'Z') ||
(*it >= 'a' && *it <= 'z') ||
void AsmMatcherInfo::
buildRegisterClasses(SmallPtrSetImpl<Record*> &SingletonRegisters) {
- const std::vector<CodeGenRegister*> &Registers =
- Target.getRegBank().getRegisters();
- ArrayRef<CodeGenRegisterClass*> RegClassList =
- Target.getRegBank().getRegClasses();
+ const auto &Registers = Target.getRegBank().getRegisters();
+ auto &RegClassList = Target.getRegBank().getRegClasses();
typedef std::set<RegisterSet, LessRegisterSet> RegisterSetSet;
RegisterSetSet RegisterSets;
// Gather the defined sets.
- for (const CodeGenRegisterClass *RC : RegClassList)
- RegisterSets.insert(RegisterSet(RC->getOrder().begin(),
- RC->getOrder().end()));
+ for (const CodeGenRegisterClass &RC : RegClassList)
+ RegisterSets.insert(
+ RegisterSet(RC.getOrder().begin(), RC.getOrder().end()));
// Add any required singleton sets.
for (Record *Rec : SingletonRegisters) {
// a unique register set class), and build the mapping of registers to the set
// they should classify to.
std::map<Record*, RegisterSet> RegisterMap;
- for (const CodeGenRegister *CGR : Registers) {
+ for (const CodeGenRegister &CGR : Registers) {
// Compute the intersection of all sets containing this register.
RegisterSet ContainingSet;
for (const RegisterSet &RS : RegisterSets) {
- if (!RS.count(CGR->TheDef))
+ if (!RS.count(CGR.TheDef))
continue;
if (ContainingSet.empty()) {
if (!ContainingSet.empty()) {
RegisterSets.insert(ContainingSet);
- RegisterMap.insert(std::make_pair(CGR->TheDef, ContainingSet));
+ RegisterMap.insert(std::make_pair(CGR.TheDef, ContainingSet));
}
}
}
// Name the register classes which correspond to a user defined RegisterClass.
- for (const CodeGenRegisterClass *RC : RegClassList) {
+ for (const CodeGenRegisterClass &RC : RegClassList) {
// Def will be NULL for non-user defined register classes.
- Record *Def = RC->getDef();
+ Record *Def = RC.getDef();
if (!Def)
continue;
- ClassInfo *CI = RegisterSetClasses[RegisterSet(RC->getOrder().begin(),
- RC->getOrder().end())];
+ ClassInfo *CI = RegisterSetClasses[RegisterSet(RC.getOrder().begin(),
+ RC.getOrder().end())];
if (CI->ValueName.empty()) {
- CI->ClassName = RC->getName();
- CI->Name = "MCK_" + RC->getName();
- CI->ValueName = RC->getName();
+ CI->ClassName = RC.getName();
+ CI->Name = "MCK_" + RC.getName();
+ CI->ValueName = RC.getName();
} else
- CI->ValueName = CI->ValueName + "," + RC->getName();
+ CI->ValueName = CI->ValueName + "," + RC.getName();
RegisterClassClasses.insert(std::make_pair(Def, CI));
}
CI->Kind = ClassInfo::UserClass0 + Index;
ListInit *Supers = Rec->getValueAsListInit("SuperClasses");
- for (unsigned i = 0, e = Supers->getSize(); i != e; ++i) {
- DefInit *DI = dyn_cast<DefInit>(Supers->getElement(i));
+ for (Init *I : Supers->getValues()) {
+ DefInit *DI = dyn_cast<DefInit>(I);
if (!DI) {
PrintError(Rec->getLoc(), "Invalid super class reference!");
continue;
if (Pred->getName().empty())
PrintFatalError(Pred->getLoc(), "Predicate has no name!");
- uint64_t FeatureNo = SubtargetFeatures.size();
- SubtargetFeatures[Pred] =
- llvm::make_unique<SubtargetFeatureInfo>(Pred, FeatureNo);
- DEBUG(SubtargetFeatures[Pred]->dump());
- assert(FeatureNo < 64 && "Too many subtarget features!");
+ SubtargetFeatures.insert(std::make_pair(
+ Pred, SubtargetFeatureInfo(Pred, SubtargetFeatures.size())));
+ DEBUG(SubtargetFeatures.find(Pred)->second.dump());
+ assert(SubtargetFeatures.size() <= 64 && "Too many subtarget features!");
}
// Parse the instructions; we need to do this first so that we can gather the
if (CGI->TheDef->getValueAsBit("isCodeGenOnly"))
continue;
- std::unique_ptr<MatchableInfo> II(new MatchableInfo(*CGI));
+ auto II = llvm::make_unique<MatchableInfo>(*CGI);
II->initialize(*this, SingletonRegisters, AsmVariantNo, RegisterPrefix);
std::vector<Record*> AllInstAliases =
Records.getAllDerivedDefinitions("InstAlias");
for (unsigned i = 0, e = AllInstAliases.size(); i != e; ++i) {
- CodeGenInstAlias *Alias =
- new CodeGenInstAlias(AllInstAliases[i], AsmVariantNo, Target);
+ auto Alias = llvm::make_unique<CodeGenInstAlias>(AllInstAliases[i],
+ AsmVariantNo, Target);
// If the tblgen -match-prefix option is specified (for tblgen hackers),
// filter the set of instruction aliases we consider, based on the target
.startswith( MatchPrefix))
continue;
- std::unique_ptr<MatchableInfo> II(new MatchableInfo(Alias));
+ auto II = llvm::make_unique<MatchableInfo>(std::move(Alias));
II->initialize(*this, SingletonRegisters, AsmVariantNo, RegisterPrefix);
II->TheDef->getValueAsString("TwoOperandAliasConstraint");
if (Constraint != "") {
// Start by making a copy of the original matchable.
- std::unique_ptr<MatchableInfo> AliasII(new MatchableInfo(*II));
+ auto AliasII = llvm::make_unique<MatchableInfo>(*II);
// Adjust it to be a two-operand alias.
AliasII->formTwoOperandAlias(Constraint);
II->buildAliasResultOperands();
}
if (!NewMatchables.empty())
- std::move(NewMatchables.begin(), NewMatchables.end(),
- std::back_inserter(Matchables));
+ Matchables.insert(Matchables.end(),
+ std::make_move_iterator(NewMatchables.begin()),
+ std::make_move_iterator(NewMatchables.end()));
// Process token alias definitions and set up the associated superclass
// information.
// Insert remaining suboperands after AsmOpIdx in II->AsmOperands.
StringRef Token = Op->Token; // save this in case Op gets moved
for (unsigned SI = 1, SE = Operands[Idx].MINumOperands; SI != SE; ++SI) {
- MatchableInfo::AsmOperand NewAsmOp(Token);
+ MatchableInfo::AsmOperand NewAsmOp(/*IsIsolatedToken=*/true, Token);
NewAsmOp.SubOpIdx = SI;
II->AsmOperands.insert(II->AsmOperands.begin()+AsmOpIdx+SI, NewAsmOp);
}
// Check if we have a custom match function.
std::string AsmMatchConverter =
II->getResultInst()->TheDef->getValueAsString("AsmMatchConverter");
- if (!AsmMatchConverter.empty()) {
+ if (!AsmMatchConverter.empty() && II->UseInstAsmMatchConverter) {
std::string Signature = "ConvertCustom_" + AsmMatchConverter;
II->ConversionFnKind = Signature;
getEnumNameForToken(AsmMatchConverter));
// Add the converter row for this instruction.
- ConversionTable.push_back(std::vector<uint8_t>());
+ ConversionTable.emplace_back();
ConversionTable.back().push_back(KindID);
ConversionTable.back().push_back(CVT_Done);
case MatchableInfo::ResOperand::ImmOperand: {
int64_t Val = OpInfo.ImmVal;
std::string Ty = "imm_" + itostr(Val);
+ Ty = getEnumNameForToken(Ty);
Signature += "__" + Ty;
std::string Name = "CVT_" + Ty;
break;
CvtOS << " case " << Name << ":\n"
- << " Inst.addOperand(MCOperand::CreateImm(" << Val << "));\n"
+ << " Inst.addOperand(MCOperand::createImm(" << Val << "));\n"
<< " break;\n";
OpOS << " case " << Name << ":\n"
if (!IsNewConverter)
break;
CvtOS << " case " << Name << ":\n"
- << " Inst.addOperand(MCOperand::CreateReg(" << Reg << "));\n"
+ << " Inst.addOperand(MCOperand::createReg(" << Reg << "));\n"
<< " break;\n";
OpOS << " case " << Name << ":\n"
continue;
// Add the row to the table.
- ConversionTable.push_back(ConversionRow);
+ ConversionTable.push_back(std::move(ConversionRow));
}
// Finish up the converter driver function.
// Output the instruction conversion kind enum.
OS << "enum InstructionConversionKind {\n";
- for (SetVector<std::string>::const_iterator
- i = InstructionConversionKinds.begin(),
- e = InstructionConversionKinds.end(); i != e; ++i)
- OS << " " << *i << ",\n";
+ for (const std::string &Signature : InstructionConversionKinds)
+ OS << " " << Signature << ",\n";
OS << " CVT_NUM_SIGNATURES\n";
OS << "};\n\n";
std::vector<StringMatcher::StringPair> Matches;
for (const auto &CI : Infos) {
if (CI.Kind == ClassInfo::Token)
- Matches.push_back(
- StringMatcher::StringPair(CI.ValueName, "return " + CI.Name + ";"));
+ Matches.emplace_back(CI.ValueName, "return " + CI.Name + ";");
}
OS << "static MatchClassKind matchTokenString(StringRef Name) {\n";
raw_ostream &OS) {
// Construct the match list.
std::vector<StringMatcher::StringPair> Matches;
- const std::vector<CodeGenRegister*> &Regs =
- Target.getRegBank().getRegisters();
- for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
- const CodeGenRegister *Reg = Regs[i];
- if (Reg->TheDef->getValueAsString("AsmName").empty())
+ const auto &Regs = Target.getRegBank().getRegisters();
+ for (const CodeGenRegister &Reg : Regs) {
+ if (Reg.TheDef->getValueAsString("AsmName").empty())
continue;
- Matches.push_back(StringMatcher::StringPair(
- Reg->TheDef->getValueAsString("AsmName"),
- "return " + utostr(Reg->EnumValue) + ";"));
+ Matches.emplace_back(Reg.TheDef->getValueAsString("AsmName"),
+ "return " + utostr(Reg.EnumValue) + ";");
}
OS << "static unsigned MatchRegisterName(StringRef Name) {\n";
OS << "enum SubtargetFeatureFlag : " << getMinimalRequiredFeaturesType(Info)
<< " {\n";
for (const auto &SF : Info.SubtargetFeatures) {
- SubtargetFeatureInfo &SFI = *SF.second;
+ const SubtargetFeatureInfo &SFI = SF.second;
OS << " " << SFI.getEnumName() << " = (1ULL << " << SFI.Index << "),\n";
}
OS << " Feature_None = 0\n";
if (!Info.SubtargetFeatures.empty()) {
OS << " switch(Val) {\n";
for (const auto &SF : Info.SubtargetFeatures) {
- SubtargetFeatureInfo &SFI = *SF.second;
+ const SubtargetFeatureInfo &SFI = SF.second;
// FIXME: Totally just a placeholder name to get the algorithm working.
OS << " case " << SFI.getEnumName() << ": return \""
<< SFI.TheDef->getValueAsString("PredicateName") << "\";\n";
Info.AsmParser->getValueAsString("AsmParserClassName");
OS << "uint64_t " << Info.Target.getName() << ClassName << "::\n"
- << "ComputeAvailableFeatures(uint64_t FB) const {\n";
+ << "ComputeAvailableFeatures(const FeatureBitset& FB) const {\n";
OS << " uint64_t Features = 0;\n";
for (const auto &SF : Info.SubtargetFeatures) {
- SubtargetFeatureInfo &SFI = *SF.second;
+ const SubtargetFeatureInfo &SFI = SF.second;
OS << " if (";
std::string CondStorage =
Cond = Cond.substr(1);
}
- OS << "((FB & " << Info.Target.getName() << "::" << Cond << ")";
+ OS << "(";
if (Neg)
- OS << " == 0";
- else
- OS << " != 0";
- OS << ")";
+ OS << "!";
+ OS << "FB[" << Info.Target.getName() << "::" << Cond << "])";
if (Comma.second.empty())
break;
std::string Result;
unsigned NumFeatures = 0;
for (unsigned i = 0, e = ReqFeatures.size(); i != e; ++i) {
- SubtargetFeatureInfo *F = Info.getSubtargetFeature(ReqFeatures[i]);
+ const SubtargetFeatureInfo *F = Info.getSubtargetFeature(ReqFeatures[i]);
if (!F)
PrintFatalError(R->getLoc(), "Predicate '" + ReqFeatures[i]->getName() +
// Check for ambiguous matchables.
DEBUG_WITH_TYPE("ambiguous_instrs", {
unsigned NumAmbiguous = 0;
- for (unsigned i = 0, e = Info.Matchables.size(); i != e; ++i) {
- for (unsigned j = i + 1; j != e; ++j) {
- const MatchableInfo &A = *Info.Matchables[i];
- const MatchableInfo &B = *Info.Matchables[j];
+ for (auto I = Info.Matchables.begin(), E = Info.Matchables.end(); I != E;
+ ++I) {
+ for (auto J = std::next(I); J != E; ++J) {
+ const MatchableInfo &A = **I;
+ const MatchableInfo &B = **J;
if (A.couldMatchAmbiguouslyWith(B)) {
errs() << "warning: ambiguous matchables:\n";
OS << "#undef GET_ASSEMBLER_HEADER\n";
OS << " // This should be included into the middle of the declaration of\n";
OS << " // your subclasses implementation of MCTargetAsmParser.\n";
- OS << " uint64_t ComputeAvailableFeatures(uint64_t FeatureBits) const;\n";
+ OS << " uint64_t ComputeAvailableFeatures(const FeatureBitset& FB) const;\n";
OS << " void convertToMCInst(unsigned Kind, MCInst &Inst, "
<< "unsigned Opcode,\n"
<< " const OperandVector "
OS << " void convertToMapAndConstraints(unsigned Kind,\n ";
OS << " const OperandVector &Operands) override;\n";
OS << " bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) override;\n";
- OS << " unsigned MatchInstructionImpl(\n";
- OS.indent(27);
- OS << "const OperandVector &Operands,\n"
+ OS << " unsigned MatchInstructionImpl(const OperandVector &Operands,\n"
<< " MCInst &Inst,\n"
<< " uint64_t &ErrorInfo,"
<< " bool matchingInlineAsm,\n"
<< " unsigned VariantID = 0);\n";
- if (Info.OperandMatchInfo.size()) {
+ if (!Info.OperandMatchInfo.empty()) {
OS << "\n enum OperandMatchResultTy {\n";
OS << " MatchOperand_Success, // operand matched successfully\n";
OS << " MatchOperand_NoMatch, // operand did not match\n";
OS << " // Find the appropriate table for this asm variant.\n";
OS << " const MatchEntry *Start, *End;\n";
OS << " switch (VariantID) {\n";
- OS << " default: // unreachable\n";
+ OS << " default: llvm_unreachable(\"invalid variant!\");\n";
for (unsigned VC = 0; VC != VariantCount; ++VC) {
Record *AsmVariant = Target.getAsmParserVariant(VC);
int AsmVariantNo = AsmVariant->getValueAsInt("Variant");
// Finally, build the match function.
OS << "unsigned " << Target.getName() << ClassName << "::\n"
- << "MatchInstructionImpl(const OperandVector"
- << " &Operands,\n";
- OS << " MCInst &Inst,\n"
- << "uint64_t &ErrorInfo, bool matchingInlineAsm, unsigned VariantID) {\n";
+ << "MatchInstructionImpl(const OperandVector &Operands,\n";
+ OS << " MCInst &Inst, uint64_t &ErrorInfo,\n"
+ << " bool matchingInlineAsm, unsigned VariantID) {\n";
OS << " // Eliminate obvious mismatches.\n";
OS << " if (Operands.size() > " << (MaxNumOperands+1) << ") {\n";
OS << " uint64_t MissingFeatures = ~0ULL;\n";
OS << " // Set ErrorInfo to the operand that mismatches if it is\n";
OS << " // wrong for all instances of the instruction.\n";
- OS << " ErrorInfo = ~0U;\n";
+ OS << " ErrorInfo = ~0ULL;\n";
// Emit code to search the table.
OS << " // Find the appropriate table for this asm variant.\n";
OS << " const MatchEntry *Start, *End;\n";
OS << " switch (VariantID) {\n";
- OS << " default: // unreachable\n";
+ OS << " default: llvm_unreachable(\"invalid variant!\");\n";
for (unsigned VC = 0; VC != VariantCount; ++VC) {
Record *AsmVariant = Target.getAsmParserVariant(VC);
int AsmVariantNo = AsmVariant->getValueAsInt("Variant");
OS << " HadMatchOtherThanFeatures = true;\n";
OS << " uint64_t NewMissingFeatures = it->RequiredFeatures & "
"~AvailableFeatures;\n";
- OS << " if (CountPopulation_64(NewMissingFeatures) <=\n"
- " CountPopulation_64(MissingFeatures))\n";
+ OS << " if (countPopulation(NewMissingFeatures) <=\n"
+ " countPopulation(MissingFeatures))\n";
OS << " MissingFeatures = NewMissingFeatures;\n";
OS << " continue;\n";
OS << " }\n";
OS << "\n";
+ OS << " Inst.clear();\n\n";
OS << " if (matchingInlineAsm) {\n";
OS << " Inst.setOpcode(it->Opcode);\n";
OS << " convertToMapAndConstraints(it->ConvertFn, Operands);\n";
OS << " return Match_MissingFeature;\n";
OS << "}\n\n";
- if (Info.OperandMatchInfo.size())
+ if (!Info.OperandMatchInfo.empty())
emitCustomOperandParsing(OS, Target, Info, ClassName, StringTable,
MaxMnemonicIndex);