aboutsummaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
Diffstat (limited to 'utils')
-rw-r--r--utils/FileCheck/FileCheck.cpp6
-rw-r--r--utils/TableGen/AsmMatcherEmitter.cpp348
-rw-r--r--utils/TableGen/CodeEmitterGen.cpp2
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.cpp412
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.h5
-rw-r--r--utils/TableGen/CodeGenInstruction.cpp14
-rw-r--r--utils/TableGen/CodeGenInstruction.h16
-rw-r--r--utils/TableGen/CodeGenRegisters.cpp4
-rw-r--r--utils/TableGen/CodeGenTarget.cpp11
-rw-r--r--utils/TableGen/CodeGenTarget.h4
-rw-r--r--utils/TableGen/DAGISelMatcherGen.cpp3
-rw-r--r--utils/TableGen/FixedLenDecoderEmitter.cpp2
-rw-r--r--utils/TableGen/PseudoLoweringEmitter.cpp2
-rw-r--r--utils/TableGen/SequenceToOffsetTable.h4
-rw-r--r--utils/TableGen/SubtargetEmitter.cpp2
-rw-r--r--utils/TableGen/X86RecognizableInstr.cpp2
-rw-r--r--utils/TableGen/X86RecognizableInstr.h2
-rwxr-xr-xutils/llvm-lit/llvm-lit.in13
-rw-r--r--utils/llvm.grm1
-rw-r--r--utils/unittest/googletest/include/gtest/internal/gtest-port.h2
20 files changed, 606 insertions, 249 deletions
diff --git a/utils/FileCheck/FileCheck.cpp b/utils/FileCheck/FileCheck.cpp
index 33f04ce647..0805504ad1 100644
--- a/utils/FileCheck/FileCheck.cpp
+++ b/utils/FileCheck/FileCheck.cpp
@@ -45,6 +45,10 @@ static cl::opt<bool>
NoCanonicalizeWhiteSpace("strict-whitespace",
cl::desc("Do not treat all horizontal whitespace as equivalent"));
+static cl::opt<bool>
+NoRegex("exact-match",
+ cl::desc("Look for exact matches without using regular expressions"));
+
//===----------------------------------------------------------------------===//
// Pattern Handling Code.
//===----------------------------------------------------------------------===//
@@ -124,7 +128,7 @@ bool Pattern::ParsePattern(StringRef PatternStr, SourceMgr &SM) {
}
// Check to see if this is a fixed string, or if it has regex pieces.
- if (PatternStr.size() < 2 ||
+ if (PatternStr.size() < 2 || NoRegex ||
(PatternStr.find("{{") == StringRef::npos &&
PatternStr.find("[[") == StringRef::npos)) {
FixedStr = PatternStr;
diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp
index abcec8fe94..78eb641899 100644
--- a/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/utils/TableGen/AsmMatcherEmitter.cpp
@@ -416,7 +416,7 @@ struct MatchableInfo {
SmallVector<SubtargetFeatureInfo*, 4> RequiredFeatures;
/// ConversionFnKind - The enum value which is passed to the generated
- /// ConvertToMCInst to convert parsed operands into an MCInst for this
+ /// convertToMCInst to convert parsed operands into an MCInst for this
/// function.
std::string ConversionFnKind;
@@ -488,6 +488,15 @@ struct MatchableInfo {
return false;
}
+ // Give matches that require more features higher precedence. This is useful
+ // because we cannot define AssemblerPredicates with the negation of
+ // processor features. For example, ARM v6 "nop" may be either a HINT or
+ // MOV. With v6, we want to match HINT. The assembler has no way to
+ // predicate MOV under "NoV6", but HINT will always match first because it
+ // requires V6 while MOV does not.
+ if (RequiredFeatures.size() != RHS.RequiredFeatures.size())
+ return RequiredFeatures.size() > RHS.RequiredFeatures.size();
+
return false;
}
@@ -666,7 +675,7 @@ void MatchableInfo::dump() {
}
static std::pair<StringRef, StringRef>
-parseTwoOperandConstraint(StringRef S, SMLoc Loc) {
+parseTwoOperandConstraint(StringRef S, ArrayRef<SMLoc> Loc) {
// Split via the '='.
std::pair<StringRef, StringRef> Ops = S.split('=');
if (Ops.second == "")
@@ -1638,34 +1647,90 @@ void MatchableInfo::buildAliasResultOperands() {
}
}
+static unsigned getConverterOperandID(const std::string &Name,
+ SetVector<std::string> &Table,
+ bool &IsNew) {
+ IsNew = Table.insert(Name);
+
+ unsigned ID = IsNew ? Table.size() - 1 :
+ std::find(Table.begin(), Table.end(), Name) - Table.begin();
+
+ assert(ID < Table.size());
+
+ return ID;
+}
+
+
static void emitConvertToMCInst(CodeGenTarget &Target, StringRef ClassName,
std::vector<MatchableInfo*> &Infos,
raw_ostream &OS) {
+ SetVector<std::string> OperandConversionKinds;
+ SetVector<std::string> InstructionConversionKinds;
+ std::vector<std::vector<uint8_t> > ConversionTable;
+ size_t MaxRowLength = 2; // minimum is custom converter plus terminator.
+
+ // TargetOperandClass - This is the target's operand class, like X86Operand.
+ std::string TargetOperandClass = Target.getName() + "Operand";
+
// Write the convert function to a separate stream, so we can drop it after
- // the enum.
+ // the enum. We'll build up the conversion handlers for the individual
+ // operand types opportunistically as we encounter them.
std::string ConvertFnBody;
raw_string_ostream CvtOS(ConvertFnBody);
-
- // Function we have already generated.
- std::set<std::string> GeneratedFns;
-
// Start the unified conversion function.
- CvtOS << "bool " << Target.getName() << ClassName << "::\n";
- CvtOS << "ConvertToMCInst(unsigned Kind, MCInst &Inst, "
+ CvtOS << "void " << Target.getName() << ClassName << "::\n"
+ << "convertToMCInst(unsigned Kind, MCInst &Inst, "
<< "unsigned Opcode,\n"
- << " const SmallVectorImpl<MCParsedAsmOperand*"
- << "> &Operands) {\n";
- CvtOS << " Inst.setOpcode(Opcode);\n";
- CvtOS << " switch (Kind) {\n";
- CvtOS << " default:\n";
-
- // Start the enum, which we will generate inline.
-
- OS << "// Unified function for converting operands to MCInst instances.\n\n";
- OS << "enum ConversionKind {\n";
-
- // TargetOperandClass - This is the target's operand class, like X86Operand.
- std::string TargetOperandClass = Target.getName() + "Operand";
+ << " const SmallVectorImpl<MCParsedAsmOperand*"
+ << "> &Operands) {\n"
+ << " assert(Kind < CVT_NUM_SIGNATURES && \"Invalid signature!\");\n"
+ << " uint8_t *Converter = ConversionTable[Kind];\n"
+ << " Inst.setOpcode(Opcode);\n"
+ << " for (uint8_t *p = Converter; *p; p+= 2) {\n"
+ << " switch (*p) {\n"
+ << " default: llvm_unreachable(\"invalid conversion entry!\");\n"
+ << " case CVT_Reg:\n"
+ << " static_cast<" << TargetOperandClass
+ << "*>(Operands[*(p + 1)])->addRegOperands(Inst, 1);\n"
+ << " break;\n"
+ << " case CVT_Tied:\n"
+ << " Inst.addOperand(Inst.getOperand(*(p + 1)));\n"
+ << " break;\n";
+
+ std::string OperandFnBody;
+ raw_string_ostream OpOS(OperandFnBody);
+ // Start the operand number lookup function.
+ OpOS << "unsigned " << Target.getName() << ClassName << "::\n"
+ << "getMCInstOperandNumImpl(unsigned Kind, MCInst &Inst,\n"
+ << " const SmallVectorImpl<MCParsedAsmOperand*> "
+ << "&Operands,\n unsigned OperandNum, unsigned "
+ << "&NumMCOperands) {\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"
+ << " if (*(p + 1) > OperandNum) continue;\n"
+ << " switch (*p) {\n"
+ << " default: llvm_unreachable(\"invalid conversion entry!\");\n"
+ << " case CVT_Reg:\n"
+ << " if (*(p + 1) == OperandNum) {\n"
+ << " NumMCOperands = 1;\n"
+ << " break;\n"
+ << " }\n"
+ << " ++MCOperandNum;\n"
+ << " break;\n"
+ << " case CVT_Tied:\n"
+ << " // FIXME: Tied operand calculation not supported.\n"
+ << " assert (0 && \"getMCInstOperandNumImpl() doesn't support tied operands, yet!\");\n"
+ << " break;\n";
+
+ // Pre-populate the operand conversion kinds with the standard always
+ // available entries.
+ OperandConversionKinds.insert("CVT_Done");
+ OperandConversionKinds.insert("CVT_Reg");
+ OperandConversionKinds.insert("CVT_Tied");
+ enum { CVT_Done, CVT_Reg, CVT_Tied };
for (std::vector<MatchableInfo*>::const_iterator it = Infos.begin(),
ie = Infos.end(); it != ie; ++it) {
@@ -1679,24 +1744,35 @@ static void emitConvertToMCInst(CodeGenTarget &Target, StringRef ClassName,
II.ConversionFnKind = Signature;
// Check if we have already generated this signature.
- if (!GeneratedFns.insert(Signature).second)
+ if (!InstructionConversionKinds.insert(Signature))
continue;
- // If not, emit it now. Add to the enum list.
- OS << " " << Signature << ",\n";
+ // Remember this converter for the kind enum.
+ unsigned KindID = OperandConversionKinds.size();
+ OperandConversionKinds.insert("CVT_" + AsmMatchConverter);
- CvtOS << " case " << Signature << ":\n";
- CvtOS << " return " << AsmMatchConverter
- << "(Inst, Opcode, Operands);\n";
+ // Add the converter row for this instruction.
+ ConversionTable.push_back(std::vector<uint8_t>());
+ ConversionTable.back().push_back(KindID);
+ ConversionTable.back().push_back(CVT_Done);
+
+ // Add the handler to the conversion driver function.
+ CvtOS << " case CVT_" << AsmMatchConverter << ":\n"
+ << " " << AsmMatchConverter << "(Inst, Operands);\n"
+ << " break;\n";
+
+ // FIXME: Handle the operand number lookup for custom match functions.
continue;
}
// Build the conversion function signature.
std::string Signature = "Convert";
- std::string CaseBody;
- raw_string_ostream CaseOS(CaseBody);
+
+ std::vector<uint8_t> ConversionRow;
// Compute the convert enum and the case body.
+ MaxRowLength = std::max(MaxRowLength, II.ResOperands.size()*2 + 1 );
+
for (unsigned i = 0, e = II.ResOperands.size(); i != e; ++i) {
const MatchableInfo::ResOperand &OpInfo = II.ResOperands[i];
@@ -1709,74 +1785,186 @@ static void emitConvertToMCInst(CodeGenTarget &Target, StringRef ClassName,
// Registers are always converted the same, don't duplicate the
// conversion function based on them.
Signature += "__";
- if (Op.Class->isRegisterClass())
- Signature += "Reg";
- else
- Signature += Op.Class->ClassName;
+ std::string Class;
+ Class = Op.Class->isRegisterClass() ? "Reg" : Op.Class->ClassName;
+ Signature += Class;
Signature += utostr(OpInfo.MINumOperands);
Signature += "_" + itostr(OpInfo.AsmOperandNum);
- CaseOS << " ((" << TargetOperandClass << "*)Operands["
- << (OpInfo.AsmOperandNum+1) << "])->" << Op.Class->RenderMethod
- << "(Inst, " << OpInfo.MINumOperands << ");\n";
+ // Add the conversion kind, if necessary, and get the associated ID
+ // the index of its entry in the vector).
+ std::string Name = "CVT_" + (Op.Class->isRegisterClass() ? "Reg" :
+ Op.Class->RenderMethod);
+
+ bool IsNewConverter = false;
+ unsigned ID = getConverterOperandID(Name, OperandConversionKinds,
+ IsNewConverter);
+
+ // Add the operand entry to the instruction kind conversion row.
+ ConversionRow.push_back(ID);
+ ConversionRow.push_back(OpInfo.AsmOperandNum + 1);
+
+ if (!IsNewConverter)
+ break;
+
+ // This is a new operand kind. Add a handler for it to the
+ // converter driver.
+ CvtOS << " case " << Name << ":\n"
+ << " static_cast<" << TargetOperandClass
+ << "*>(Operands[*(p + 1)])->"
+ << Op.Class->RenderMethod << "(Inst, " << OpInfo.MINumOperands
+ << ");\n"
+ << " break;\n";
+
+ // Add a handler for the operand number lookup.
+ OpOS << " case " << Name << ":\n"
+ << " if (*(p + 1) == OperandNum) {\n"
+ << " NumMCOperands = " << OpInfo.MINumOperands << ";\n"
+ << " break;\n"
+ << " }\n"
+ << " MCOperandNum += " << OpInfo.MINumOperands << ";\n"
+ << " break;\n";
break;
}
-
case MatchableInfo::ResOperand::TiedOperand: {
// If this operand is tied to a previous one, just copy the MCInst
// operand from the earlier one.We can only tie single MCOperand values.
//assert(OpInfo.MINumOperands == 1 && "Not a singular MCOperand");
unsigned TiedOp = OpInfo.TiedOperandNum;
assert(i > TiedOp && "Tied operand precedes its target!");
- CaseOS << " Inst.addOperand(Inst.getOperand(" << TiedOp << "));\n";
Signature += "__Tie" + utostr(TiedOp);
+ ConversionRow.push_back(CVT_Tied);
+ ConversionRow.push_back(TiedOp);
+ // FIXME: Handle the operand number lookup for tied operands.
break;
}
case MatchableInfo::ResOperand::ImmOperand: {
int64_t Val = OpInfo.ImmVal;
- CaseOS << " Inst.addOperand(MCOperand::CreateImm(" << Val << "));\n";
- Signature += "__imm" + itostr(Val);
+ std::string Ty = "imm_" + itostr(Val);
+ Signature += "__" + Ty;
+
+ std::string Name = "CVT_" + Ty;
+ bool IsNewConverter = false;
+ unsigned ID = getConverterOperandID(Name, OperandConversionKinds,
+ IsNewConverter);
+ // Add the operand entry to the instruction kind conversion row.
+ ConversionRow.push_back(ID);
+ ConversionRow.push_back(0);
+
+ if (!IsNewConverter)
+ break;
+
+ CvtOS << " case " << Name << ":\n"
+ << " Inst.addOperand(MCOperand::CreateImm(" << Val << "));\n"
+ << " break;\n";
+
+ OpOS << " case " << Name << ":\n"
+ << " if (*(p + 1) == OperandNum) {\n"
+ << " NumMCOperands = 1;\n"
+ << " break;\n"
+ << " }\n"
+ << " ++MCOperandNum;\n"
+ << " break;\n";
break;
}
case MatchableInfo::ResOperand::RegOperand: {
+ std::string Reg, Name;
if (OpInfo.Register == 0) {
- CaseOS << " Inst.addOperand(MCOperand::CreateReg(0));\n";
- Signature += "__reg0";
+ Name = "reg0";
+ Reg = "0";
} else {
- std::string N = getQualifiedName(OpInfo.Register);
- CaseOS << " Inst.addOperand(MCOperand::CreateReg(" << N << "));\n";
- Signature += "__reg" + OpInfo.Register->getName();
+ Reg = getQualifiedName(OpInfo.Register);
+ Name = "reg" + OpInfo.Register->getName();
}
+ Signature += "__" + Name;
+ Name = "CVT_" + Name;
+ bool IsNewConverter = false;
+ unsigned ID = getConverterOperandID(Name, OperandConversionKinds,
+ IsNewConverter);
+ // Add the operand entry to the instruction kind conversion row.
+ ConversionRow.push_back(ID);
+ ConversionRow.push_back(0);
+
+ if (!IsNewConverter)
+ break;
+ CvtOS << " case " << Name << ":\n"
+ << " Inst.addOperand(MCOperand::CreateReg(" << Reg << "));\n"
+ << " break;\n";
+
+ OpOS << " case " << Name << ":\n"
+ << " if (*(p + 1) == OperandNum) {\n"
+ << " NumMCOperands = 1;\n"
+ << " break;\n"
+ << " }\n"
+ << " ++MCOperandNum;\n"
+ << " break;\n";
}
}
}
+ // If there were no operands, add to the signature to that effect
+ if (Signature == "Convert")
+ Signature += "_NoOperands";
+
II.ConversionFnKind = Signature;
- // Check if we have already generated this signature.
- if (!GeneratedFns.insert(Signature).second)
+ // Save the signature. If we already have it, don't add a new row
+ // to the table.
+ if (!InstructionConversionKinds.insert(Signature))
continue;
- // If not, emit it now. Add to the enum list.
- OS << " " << Signature << ",\n";
-
- CvtOS << " case " << Signature << ":\n";
- CvtOS << CaseOS.str();
- CvtOS << " return true;\n";
+ // Add the row to the table.
+ ConversionTable.push_back(ConversionRow);
}
- // Finish the convert function.
+ // Finish up the converter driver function.
+ CvtOS << " }\n }\n}\n\n";
+
+ // Finish up the operand number lookup function.
+ OpOS << " }\n }\n return MCOperandNum;\n}\n\n";
+
+ OS << "namespace {\n";
+
+ // Output the operand conversion kind enum.
+ OS << "enum OperatorConversionKind {\n";
+ for (unsigned i = 0, e = OperandConversionKinds.size(); i != e; ++i)
+ OS << " " << OperandConversionKinds[i] << ",\n";
+ OS << " CVT_NUM_CONVERTERS\n";
+ OS << "};\n\n";
+
+ // 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";
+ OS << " CVT_NUM_SIGNATURES\n";
+ OS << "};\n\n";
+
- CvtOS << " }\n";
- CvtOS << " return false;\n";
- CvtOS << "}\n\n";
+ OS << "} // end anonymous namespace\n\n";
- // Finish the enum, and drop the convert function after it.
+ // Output the conversion table.
+ OS << "static uint8_t ConversionTable[CVT_NUM_SIGNATURES]["
+ << MaxRowLength << "] = {\n";
+
+ for (unsigned Row = 0, ERow = ConversionTable.size(); Row != ERow; ++Row) {
+ assert(ConversionTable[Row].size() % 2 == 0 && "bad conversion row!");
+ OS << " // " << InstructionConversionKinds[Row] << "\n";
+ OS << " { ";
+ for (unsigned i = 0, e = ConversionTable[Row].size(); i != e; i += 2)
+ OS << OperandConversionKinds[ConversionTable[Row][i]] << ", "
+ << (unsigned)(ConversionTable[Row][i + 1]) << ", ";
+ OS << "CVT_Done },\n";
+ }
- OS << " NumConversionVariants\n";
OS << "};\n\n";
+ // Spit out the conversion driver function.
OS << CvtOS.str();
+
+ // Spit out the operand number lookup function.
+ OS << OpOS.str();
}
/// emitMatchClassEnumeration - Emit the enumeration for match class kinds.
@@ -2407,14 +2595,19 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " // This should be included into the middle of the declaration of\n";
OS << " // your subclasses implementation of MCTargetAsmParser.\n";
OS << " unsigned ComputeAvailableFeatures(uint64_t FeatureBits) const;\n";
- OS << " bool ConvertToMCInst(unsigned Kind, MCInst &Inst, "
+ OS << " void convertToMCInst(unsigned Kind, MCInst &Inst, "
<< "unsigned Opcode,\n"
- << " const SmallVectorImpl<MCParsedAsmOperand*> "
+ << " const SmallVectorImpl<MCParsedAsmOperand*> "
<< "&Operands);\n";
+ OS << " unsigned getMCInstOperandNumImpl(unsigned Kind, MCInst &Inst,\n "
+ << " const "
+ << "SmallVectorImpl<MCParsedAsmOperand*> &Operands,\n "
+ << " unsigned OperandNum, unsigned &NumMCOperands);\n";
OS << " bool MnemonicIsValid(StringRef Mnemonic);\n";
- OS << " unsigned MatchInstructionImpl(\n";
- OS << " const SmallVectorImpl<MCParsedAsmOperand*> &Operands,\n";
- OS << " MCInst &Inst, unsigned &ErrorInfo, unsigned VariantID = 0);\n";
+ OS << " unsigned MatchInstructionImpl(\n"
+ << " const SmallVectorImpl<MCParsedAsmOperand*> &Operands,\n"
+ << " unsigned &Kind, MCInst &Inst, "
+ << "unsigned &ErrorInfo,\n unsigned VariantID = 0);\n";
if (Info.OperandMatchInfo.size()) {
OS << "\n enum OperandMatchResultTy {\n";
@@ -2594,8 +2787,14 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
<< Target.getName() << ClassName << "::\n"
<< "MatchInstructionImpl(const SmallVectorImpl<MCParsedAsmOperand*>"
<< " &Operands,\n";
- OS << " MCInst &Inst, unsigned &ErrorInfo, ";
- OS << "unsigned VariantID) {\n";
+ OS << " unsigned &Kind, MCInst &Inst, unsigned ";
+ OS << "&ErrorInfo,\n unsigned VariantID) {\n";
+
+ OS << " // Eliminate obvious mismatches.\n";
+ OS << " if (Operands.size() > " << (MaxNumOperands+1) << ") {\n";
+ OS << " ErrorInfo = " << (MaxNumOperands+1) << ";\n";
+ OS << " return Match_InvalidOperand;\n";
+ OS << " }\n\n";
// Emit code to get the available features.
OS << " // Get the current feature set.\n";
@@ -2613,12 +2812,6 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
}
// Emit code to compute the class list for this operand vector.
- OS << " // Eliminate obvious mismatches.\n";
- OS << " if (Operands.size() > " << (MaxNumOperands+1) << ") {\n";
- OS << " ErrorInfo = " << (MaxNumOperands+1) << ";\n";
- OS << " return Match_InvalidOperand;\n";
- OS << " }\n\n";
-
OS << " // Some state to try to produce better error messages.\n";
OS << " bool HadMatchOtherThanFeatures = false;\n";
OS << " bool HadMatchOtherThanPredicate = false;\n";
@@ -2683,17 +2876,15 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " HadMatchOtherThanFeatures = true;\n";
OS << " unsigned NewMissingFeatures = it->RequiredFeatures & "
"~AvailableFeatures;\n";
- OS << " if (CountPopulation_32(NewMissingFeatures) <= "
- "CountPopulation_32(MissingFeatures))\n";
+ OS << " if (CountPopulation_32(NewMissingFeatures) <=\n"
+ " CountPopulation_32(MissingFeatures))\n";
OS << " MissingFeatures = NewMissingFeatures;\n";
OS << " continue;\n";
OS << " }\n";
OS << "\n";
OS << " // We have selected a definite instruction, convert the parsed\n"
<< " // operands into the appropriate MCInst.\n";
- OS << " if (!ConvertToMCInst(it->ConvertFn, Inst,\n"
- << " it->Opcode, Operands))\n";
- OS << " return Match_ConversionFail;\n";
+ OS << " convertToMCInst(it->ConvertFn, Inst, it->Opcode, Operands);\n";
OS << "\n";
// Verify the instruction with the target-specific match predicate function.
@@ -2714,6 +2905,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
if (!InsnCleanupFn.empty())
OS << " " << InsnCleanupFn << "(Inst);\n";
+ OS << " Kind = it->ConvertFn;\n";
OS << " return Match_Success;\n";
OS << " }\n\n";
diff --git a/utils/TableGen/CodeEmitterGen.cpp b/utils/TableGen/CodeEmitterGen.cpp
index 31a39b1f04..9c8ad67b42 100644
--- a/utils/TableGen/CodeEmitterGen.cpp
+++ b/utils/TableGen/CodeEmitterGen.cpp
@@ -92,7 +92,7 @@ void CodeEmitterGen::reverseBits(std::vector<Record*> &Insts) {
int CodeEmitterGen::getVariableBit(const std::string &VarName,
BitsInit *BI, int bit) {
if (VarBitInit *VBI = dynamic_cast<VarBitInit*>(BI->getBit(bit))) {
- if (VarInit *VI = dynamic_cast<VarInit*>(VBI->getVariable()))
+ if (VarInit *VI = dynamic_cast<VarInit*>(VBI->getBitVar()))
if (VI->getName() == VarName)
return VBI->getBitNum();
} else if (VarInit *VI = dynamic_cast<VarInit*>(BI->getBit(bit))) {
diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp
index 34f8a34e7a..8713a56916 100644
--- a/utils/TableGen/CodeGenDAGPatterns.cpp
+++ b/utils/TableGen/CodeGenDAGPatterns.cpp
@@ -1410,19 +1410,13 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
// Make sure that the value is representable for this type.
if (Size >= 32) return MadeChange;
- int Val = (II->getValue() << (32-Size)) >> (32-Size);
- if (Val == II->getValue()) return MadeChange;
-
- // If sign-extended doesn't fit, does it fit as unsigned?
- unsigned ValueMask;
- unsigned UnsignedVal;
- ValueMask = unsigned(~uint32_t(0UL) >> (32-Size));
- UnsignedVal = unsigned(II->getValue());
-
- if ((ValueMask & UnsignedVal) == UnsignedVal)
+ // Check that the value doesn't use more bits than we have. It must either
+ // be a sign- or zero-extended equivalent of the original.
+ int64_t SignBitAndAbove = II->getValue() >> (Size - 1);
+ if (SignBitAndAbove == -1 || SignBitAndAbove == 0 || SignBitAndAbove == 1)
return MadeChange;
- TP.error("Integer value '" + itostr(II->getValue())+
+ TP.error("Integer value '" + itostr(II->getValue()) +
"' is out of range for type '" + getEnumName(getType(0)) + "'!");
return MadeChange;
}
@@ -1581,8 +1575,7 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
// If the instruction expects a predicate or optional def operand, we
// codegen this by setting the operand to it's default value if it has a
// non-empty DefaultOps field.
- if ((OperandNode->isSubClassOf("PredicateOperand") ||
- OperandNode->isSubClassOf("OptionalDefOperand")) &&
+ if (OperandNode->isSubClassOf("OperandWithDefaultOps") &&
!CDP.getDefaultOperand(OperandNode).DefaultOps.empty())
continue;
@@ -2033,6 +2026,9 @@ CodeGenDAGPatterns::CodeGenDAGPatterns(RecordKeeper &R) :
// stores, and side effects in many cases by examining an
// instruction's pattern.
InferInstructionFlags();
+
+ // Verify that instruction flags match the patterns.
+ VerifyInstructionFlags();
}
CodeGenDAGPatterns::~CodeGenDAGPatterns() {
@@ -2176,53 +2172,46 @@ void CodeGenDAGPatterns::ParsePatternFragments() {
}
void CodeGenDAGPatterns::ParseDefaultOperands() {
- std::vector<Record*> DefaultOps[2];
- DefaultOps[0] = Records.getAllDerivedDefinitions("PredicateOperand");
- DefaultOps[1] = Records.getAllDerivedDefinitions("OptionalDefOperand");
+ std::vector<Record*> DefaultOps;
+ DefaultOps = Records.getAllDerivedDefinitions("OperandWithDefaultOps");
// Find some SDNode.
assert(!SDNodes.empty() && "No SDNodes parsed?");
Init *SomeSDNode = DefInit::get(SDNodes.begin()->first);
- for (unsigned iter = 0; iter != 2; ++iter) {
- for (unsigned i = 0, e = DefaultOps[iter].size(); i != e; ++i) {
- DagInit *DefaultInfo = DefaultOps[iter][i]->getValueAsDag("DefaultOps");
-
- // Clone the DefaultInfo dag node, changing the operator from 'ops' to
- // SomeSDnode so that we can parse this.
- std::vector<std::pair<Init*, std::string> > Ops;
- for (unsigned op = 0, e = DefaultInfo->getNumArgs(); op != e; ++op)
- Ops.push_back(std::make_pair(DefaultInfo->getArg(op),
- DefaultInfo->getArgName(op)));
- DagInit *DI = DagInit::get(SomeSDNode, "", Ops);
-
- // Create a TreePattern to parse this.
- TreePattern P(DefaultOps[iter][i], DI, false, *this);
- assert(P.getNumTrees() == 1 && "This ctor can only produce one tree!");
-
- // Copy the operands over into a DAGDefaultOperand.
- DAGDefaultOperand DefaultOpInfo;
-
- TreePatternNode *T = P.getTree(0);
- for (unsigned op = 0, e = T->getNumChildren(); op != e; ++op) {
- TreePatternNode *TPN = T->getChild(op);
- while (TPN->ApplyTypeConstraints(P, false))
- /* Resolve all types */;
-
- if (TPN->ContainsUnresolvedType()) {
- if (iter == 0)
- throw "Value #" + utostr(i) + " of PredicateOperand '" +
- DefaultOps[iter][i]->getName() +"' doesn't have a concrete type!";
- else
- throw "Value #" + utostr(i) + " of OptionalDefOperand '" +
- DefaultOps[iter][i]->getName() +"' doesn't have a concrete type!";
- }
- DefaultOpInfo.DefaultOps.push_back(TPN);
+ for (unsigned i = 0, e = DefaultOps.size(); i != e; ++i) {
+ DagInit *DefaultInfo = DefaultOps[i]->getValueAsDag("DefaultOps");
+
+ // Clone the DefaultInfo dag node, changing the operator from 'ops' to
+ // SomeSDnode so that we can parse this.
+ std::vector<std::pair<Init*, std::string> > Ops;
+ for (unsigned op = 0, e = DefaultInfo->getNumArgs(); op != e; ++op)
+ Ops.push_back(std::make_pair(DefaultInfo->getArg(op),
+ DefaultInfo->getArgName(op)));
+ DagInit *DI = DagInit::get(SomeSDNode, "", Ops);
+
+ // Create a TreePattern to parse this.
+ TreePattern P(DefaultOps[i], DI, false, *this);
+ assert(P.getNumTrees() == 1 && "This ctor can only produce one tree!");
+
+ // Copy the operands over into a DAGDefaultOperand.
+ DAGDefaultOperand DefaultOpInfo;
+
+ TreePatternNode *T = P.getTree(0);
+ for (unsigned op = 0, e = T->getNumChildren(); op != e; ++op) {
+ TreePatternNode *TPN = T->getChild(op);
+ while (TPN->ApplyTypeConstraints(P, false))
+ /* Resolve all types */;
+
+ if (TPN->ContainsUnresolvedType()) {
+ throw "Value #" + utostr(i) + " of OperandWithDefaultOps '" +
+ DefaultOps[i]->getName() +"' doesn't have a concrete type!";
}
-
- // Insert it into the DefaultOperands map so we can find it later.
- DefaultOperands[DefaultOps[iter][i]] = DefaultOpInfo;
+ DefaultOpInfo.DefaultOps.push_back(TPN);
}
+
+ // Insert it into the DefaultOperands map so we can find it later.
+ DefaultOperands[DefaultOps[i]] = DefaultOpInfo;
}
}
@@ -2367,36 +2356,29 @@ FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat,
class InstAnalyzer {
const CodeGenDAGPatterns &CDP;
- bool &mayStore;
- bool &mayLoad;
- bool &IsBitcast;
- bool &HasSideEffects;
- bool &IsVariadic;
public:
- InstAnalyzer(const CodeGenDAGPatterns &cdp,
- bool &maystore, bool &mayload, bool &isbc, bool &hse, bool &isv)
- : CDP(cdp), mayStore(maystore), mayLoad(mayload), IsBitcast(isbc),
- HasSideEffects(hse), IsVariadic(isv) {
- }
+ bool hasSideEffects;
+ bool mayStore;
+ bool mayLoad;
+ bool isBitcast;
+ bool isVariadic;
- /// Analyze - Analyze the specified instruction, returning true if the
- /// instruction had a pattern.
- bool Analyze(Record *InstRecord) {
- const TreePattern *Pattern = CDP.getInstruction(InstRecord).getPattern();
- if (Pattern == 0) {
- HasSideEffects = 1;
- return false; // No pattern.
- }
+ InstAnalyzer(const CodeGenDAGPatterns &cdp)
+ : CDP(cdp), hasSideEffects(false), mayStore(false), mayLoad(false),
+ isBitcast(false), isVariadic(false) {}
- // FIXME: Assume only the first tree is the pattern. The others are clobber
- // nodes.
- AnalyzeNode(Pattern->getTree(0));
- return true;
+ void Analyze(const TreePattern *Pat) {
+ // Assume only the first tree is the pattern. The others are clobber nodes.
+ AnalyzeNode(Pat->getTree(0));
+ }
+
+ void Analyze(const PatternToMatch *Pat) {
+ AnalyzeNode(Pat->getSrcPattern());
}
private:
bool IsNodeBitcast(const TreePatternNode *N) const {
- if (HasSideEffects || mayLoad || mayStore || IsVariadic)
+ if (hasSideEffects || mayLoad || mayStore || isVariadic)
return false;
if (N->getNumChildren() != 2)
@@ -2418,6 +2400,7 @@ private:
return OpInfo.getEnumName() == "ISD::BITCAST";
}
+public:
void AnalyzeNode(const TreePatternNode *N) {
if (N->isLeaf()) {
if (DefInit *DI = dynamic_cast<DefInit*>(N->getLeafValue())) {
@@ -2427,7 +2410,7 @@ private:
const ComplexPattern &CP = CDP.getComplexPattern(LeafRec);
if (CP.hasProperty(SDNPMayStore)) mayStore = true;