aboutsummaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
authorEli Bendersky <eliben@chromium.org>2013-07-15 16:09:15 -0700
committerEli Bendersky <eliben@chromium.org>2013-07-15 16:09:15 -0700
commitc6cf05cb5108f356dde97c01ee4188b0671d4542 (patch)
tree436fdc2a55296d3c202e7ef11f31be3be53efb5f /utils
parentc75199c649c739aade160289d93f257edc798cde (diff)
parent7dfcb84fc16b3bf6b2379713b53090757f0a45f9 (diff)
Merge commit '7dfcb84fc16b3bf6b2379713b53090757f0a45f9'
Conflicts: docs/LangRef.rst include/llvm/CodeGen/CallingConvLower.h include/llvm/IRReader/IRReader.h include/llvm/Target/TargetMachine.h lib/CodeGen/CallingConvLower.cpp lib/IRReader/IRReader.cpp lib/IRReader/LLVMBuild.txt lib/IRReader/Makefile lib/LLVMBuild.txt lib/Makefile lib/Support/MemoryBuffer.cpp lib/Support/Unix/PathV2.inc lib/Target/ARM/ARMBaseInstrInfo.cpp lib/Target/ARM/ARMISelLowering.cpp lib/Target/ARM/ARMInstrInfo.td lib/Target/ARM/ARMSubtarget.cpp lib/Target/ARM/ARMTargetMachine.cpp lib/Target/Mips/CMakeLists.txt lib/Target/Mips/MipsDelaySlotFiller.cpp lib/Target/Mips/MipsISelLowering.cpp lib/Target/Mips/MipsInstrInfo.td lib/Target/Mips/MipsSubtarget.cpp lib/Target/Mips/MipsSubtarget.h lib/Target/X86/X86FastISel.cpp lib/Target/X86/X86ISelDAGToDAG.cpp lib/Target/X86/X86ISelLowering.cpp lib/Target/X86/X86InstrControl.td lib/Target/X86/X86InstrFormats.td lib/Transforms/IPO/ExtractGV.cpp lib/Transforms/InstCombine/InstCombineCompares.cpp lib/Transforms/Utils/SimplifyLibCalls.cpp test/CodeGen/X86/fast-isel-divrem.ll test/MC/ARM/data-in-code.ll tools/Makefile tools/llvm-extract/llvm-extract.cpp tools/llvm-link/CMakeLists.txt tools/opt/CMakeLists.txt tools/opt/LLVMBuild.txt tools/opt/Makefile tools/opt/opt.cpp
Diffstat (limited to 'utils')
-rw-r--r--utils/FileCheck/FileCheck.cpp31
-rw-r--r--utils/Makefile2
-rw-r--r--utils/TableGen/AsmMatcherEmitter.cpp114
-rw-r--r--utils/TableGen/CMakeLists.txt1
-rw-r--r--utils/TableGen/CTagsEmitter.cpp99
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.cpp213
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.h8
-rw-r--r--utils/TableGen/CodeGenRegisters.h4
-rw-r--r--utils/TableGen/CodeGenSchedule.cpp331
-rw-r--r--utils/TableGen/CodeGenSchedule.h70
-rw-r--r--utils/TableGen/CodeGenTarget.cpp2
-rw-r--r--utils/TableGen/CodeGenTarget.h6
-rw-r--r--utils/TableGen/DAGISelMatcherGen.cpp53
-rw-r--r--utils/TableGen/RegisterInfoEmitter.cpp2
-rw-r--r--utils/TableGen/SubtargetEmitter.cpp204
-rw-r--r--utils/TableGen/TableGen.cpp8
-rw-r--r--utils/TableGen/TableGenBackends.h1
-rw-r--r--utils/TableGen/X86RecognizableInstr.cpp46
-rw-r--r--utils/TableGen/tdtags453
-rwxr-xr-xutils/git-svn/git-svnrevert52
-rwxr-xr-xutils/git-svn/git-svnup15
-rw-r--r--utils/lit/lit/TestFormats.py3
-rw-r--r--utils/lit/lit/TestRunner.py5
-rw-r--r--utils/lit/lit/discovery.py31
-rwxr-xr-xutils/lit/lit/main.py2
-rw-r--r--utils/lit/tests/Inputs/discovery/lit.cfg9
-rw-r--r--utils/lit/tests/Inputs/exec-discovery-in-tree/lit.cfg7
-rw-r--r--utils/lit/tests/Inputs/exec-discovery-in-tree/obj/lit.site.cfg4
-rw-r--r--utils/lit/tests/Inputs/exec-discovery-in-tree/test-one.txt1
-rw-r--r--utils/lit/tests/Inputs/exec-discovery/lit.site.cfg5
-rw-r--r--utils/lit/tests/Inputs/progress-bar/lit.cfg5
-rw-r--r--utils/lit/tests/Inputs/progress-bar/test-1.txt1
-rw-r--r--utils/lit/tests/Inputs/progress-bar/test-2.txt1
-rw-r--r--utils/lit/tests/Inputs/progress-bar/test-3.txt1
-rw-r--r--utils/lit/tests/Inputs/progress-bar/test-4.txt1
-rw-r--r--utils/lit/tests/discovery.py85
-rw-r--r--utils/lit/tests/progress-bar.py13
-rw-r--r--utils/obj2yaml/CMakeLists.txt7
-rw-r--r--utils/obj2yaml/Makefile20
-rw-r--r--utils/obj2yaml/coff2yaml.cpp361
-rw-r--r--utils/obj2yaml/obj2yaml.cpp86
-rw-r--r--utils/obj2yaml/obj2yaml.h34
-rwxr-xr-xutils/release/tag.sh4
-rwxr-xr-xutils/release/test-release.sh2
-rw-r--r--utils/unittest/UnitTestMain/TestMain.cpp5
-rw-r--r--utils/yaml2obj/CMakeLists.txt5
-rw-r--r--utils/yaml2obj/Makefile20
-rw-r--r--utils/yaml2obj/yaml2obj.cpp879
48 files changed, 1479 insertions, 1833 deletions
diff --git a/utils/FileCheck/FileCheck.cpp b/utils/FileCheck/FileCheck.cpp
index 563cab0d5d..cd7bb5a44f 100644
--- a/utils/FileCheck/FileCheck.cpp
+++ b/utils/FileCheck/FileCheck.cpp
@@ -85,6 +85,9 @@ public:
Pattern(bool matchEOF = false) : MatchEOF(matchEOF) { }
+ /// getLoc - Return the location in source code.
+ SMLoc getLoc() const { return PatternLoc; }
+
/// ParsePattern - Parse the given string into the Pattern. SM provides the
/// SourceMgr used for error reports, and LineNumber is the line number in
/// the input file from which the pattern string was read.
@@ -581,7 +584,7 @@ struct CheckString {
/// NotStrings - These are all of the strings that are disallowed from
/// occurring between this match string and the previous one (or start of
/// file).
- std::vector<std::pair<SMLoc, Pattern> > NotStrings;
+ std::vector<Pattern> NotStrings;
CheckString(const Pattern &P, SMLoc L, bool isCheckNext)
: Pat(P), Loc(L), IsCheckNext(isCheckNext) {}
@@ -604,7 +607,7 @@ static MemoryBuffer *CanonicalizeInputFile(MemoryBuffer *MB,
continue;
}
- // If current char is not a horizontal whitespace or if horizontal
+ // If current char is not a horizontal whitespace or if horizontal
// whitespace canonicalization is disabled, dump it to output as is.
if (PreserveHorizontal || (*Ptr != ' ' && *Ptr != '\t')) {
NewFile.push_back(*Ptr);
@@ -639,17 +642,17 @@ static bool ReadCheckFile(SourceMgr &SM,
<< ec.message() << '\n';
return true;
}
- MemoryBuffer *F = File.take();
// If we want to canonicalize whitespace, strip excess whitespace from the
// buffer containing the CHECK lines. Remove DOS style line endings.
- F = CanonicalizeInputFile(F, NoCanonicalizeWhiteSpace);
+ MemoryBuffer *F =
+ CanonicalizeInputFile(File.take(), NoCanonicalizeWhiteSpace);
SM.AddNewSourceBuffer(F, SMLoc());
// Find all instances of CheckPrefix followed by : in the file.
StringRef Buffer = F->getBuffer();
- std::vector<std::pair<SMLoc, Pattern> > NotMatches;
+ std::vector<Pattern> NotMatches;
// LineNumber keeps track of the line on which CheckPrefix instances are
// found.
@@ -716,8 +719,7 @@ static bool ReadCheckFile(SourceMgr &SM,
// Handle CHECK-NOT.
if (IsCheckNot) {
- NotMatches.push_back(std::make_pair(SMLoc::getFromPointer(Buffer.data()),
- P));
+ NotMatches.push_back(P);
continue;
}
@@ -803,16 +805,16 @@ int main(int argc, char **argv) {
<< ec.message() << '\n';
return 2;
}
- MemoryBuffer *F = File.take();
- if (F->getBufferSize() == 0) {
+ if (File->getBufferSize() == 0) {
errs() << "FileCheck error: '" << InputFilename << "' is empty.\n";
return 2;
}
-
+
// Remove duplicate spaces in the input file if requested.
// Remove DOS style line endings.
- F = CanonicalizeInputFile(F, NoCanonicalizeWhiteSpace);
+ MemoryBuffer *F =
+ CanonicalizeInputFile(File.take(), NoCanonicalizeWhiteSpace);
SM.AddNewSourceBuffer(F, SMLoc());
@@ -877,14 +879,13 @@ int main(int argc, char **argv) {
for (unsigned ChunkNo = 0, e = CheckStr.NotStrings.size();
ChunkNo != e; ++ChunkNo) {
size_t MatchLen = 0;
- size_t Pos = CheckStr.NotStrings[ChunkNo].second.Match(SkippedRegion,
- MatchLen,
- VariableTable);
+ size_t Pos = CheckStr.NotStrings[ChunkNo].Match(SkippedRegion, MatchLen,
+ VariableTable);
if (Pos == StringRef::npos) continue;
SM.PrintMessage(SMLoc::getFromPointer(LastMatch+Pos), SourceMgr::DK_Error,
CheckPrefix+"-NOT: string occurred!");
- SM.PrintMessage(CheckStr.NotStrings[ChunkNo].first, SourceMgr::DK_Note,
+ SM.PrintMessage(CheckStr.NotStrings[ChunkNo].getLoc(), SourceMgr::DK_Note,
CheckPrefix+"-NOT: pattern specified here");
return 1;
}
diff --git a/utils/Makefile b/utils/Makefile
index f972b6596f..d117b5a87f 100644
--- a/utils/Makefile
+++ b/utils/Makefile
@@ -9,7 +9,7 @@
LEVEL = ..
PARALLEL_DIRS := FileCheck FileUpdate TableGen PerfectShuffle \
- count fpcmp llvm-lit not unittest yaml2obj
+ count fpcmp llvm-lit not unittest
ifeq ($(NACL_SANDBOX),1)
# In sandboxed mode, just build the bare minimum
diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp
index 6faf819529..218af219a8 100644
--- a/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/utils/TableGen/AsmMatcherEmitter.cpp
@@ -1322,27 +1322,6 @@ void AsmMatcherInfo::buildInfo() {
if (CGI.TheDef->getValueAsBit("isCodeGenOnly"))
continue;
- // Validate the operand list to ensure we can handle this instruction.
- for (unsigned i = 0, e = CGI.Operands.size(); i != e; ++i) {
- const CGIOperandList::OperandInfo &OI = CGI.Operands[i];
-
- // Validate tied operands.
- if (OI.getTiedRegister() != -1) {
- // If we have a tied operand that consists of multiple MCOperands,
- // reject it. We reject aliases and ignore instructions for now.
- if (OI.MINumOperands != 1) {
- // FIXME: Should reject these. The ARM backend hits this with $lane
- // in a bunch of instructions. The right answer is unclear.
- DEBUG({
- errs() << "warning: '" << CGI.TheDef->getName() << "': "
- << "ignoring instruction with multi-operand tied operand '"
- << OI.Name << "'\n";
- });
- continue;
- }
- }
- }
-
OwningPtr<MatchableInfo> II(new MatchableInfo(CGI));
II->initialize(*this, SingletonRegisters, AsmVariantNo, RegisterPrefix);
@@ -1529,7 +1508,9 @@ buildInstructionOperandReference(MatchableInfo *II,
// we want to canonicalize to:
// "inc $dst"
// so that we know how to provide the $dst operand when filling in the result.
- int OITied = Operands[Idx].getTiedRegister();
+ int OITied = -1;
+ if (Operands[Idx].MINumOperands == 1)
+ OITied = Operands[Idx].getTiedRegister();
if (OITied != -1) {
// The tied operand index is an MIOperand index, find the operand that
// contains it.
@@ -1578,7 +1559,9 @@ void MatchableInfo::buildInstructionResultOperands() {
const CGIOperandList::OperandInfo &OpInfo = ResultInst->Operands[i];
// If this is a tied operand, just copy from the previously handled operand.
- int TiedOp = OpInfo.getTiedRegister();
+ int TiedOp = -1;
+ if (OpInfo.MINumOperands == 1)
+ TiedOp = OpInfo.getTiedRegister();
if (TiedOp != -1) {
ResOperands.push_back(ResOperand::getTiedOp(TiedOp));
continue;
@@ -1586,10 +1569,15 @@ void MatchableInfo::buildInstructionResultOperands() {
// Find out what operand from the asmparser this MCInst operand comes from.
int SrcOperand = findAsmOperandNamed(OpInfo.Name);
- if (OpInfo.Name.empty() || SrcOperand == -1)
- PrintFatalError(TheDef->getLoc(), "Instruction '" +
- TheDef->getName() + "' has operand '" + OpInfo.Name +
- "' that doesn't appear in asm string!");
+ if (OpInfo.Name.empty() || SrcOperand == -1) {
+ // This may happen for operands that are tied to a suboperand of a
+ // complex operand. Simply use a dummy value here; nobody should
+ // use this operand slot.
+ // FIXME: The long term goal is for the MCOperand list to not contain
+ // tied operands at all.
+ ResOperands.push_back(ResOperand::getImmOp(0));
+ continue;
+ }
// Check if the one AsmOperand populates the entire operand.
unsigned NumOperands = OpInfo.MINumOperands;
@@ -1620,7 +1608,9 @@ void MatchableInfo::buildAliasResultOperands() {
const CGIOperandList::OperandInfo *OpInfo = &ResultInst->Operands[i];
// If this is a tied operand, just copy from the previously handled operand.
- int TiedOp = OpInfo->getTiedRegister();
+ int TiedOp = -1;
+ if (OpInfo->MINumOperands == 1)
+ TiedOp = OpInfo->getTiedRegister();
if (TiedOp != -1) {
ResOperands.push_back(ResOperand::getTiedOp(TiedOp));
continue;
@@ -1843,13 +1833,12 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
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");
+ assert(OpInfo.MINumOperands == 1 && "Not a singular MCOperand");
unsigned TiedOp = OpInfo.TiedOperandNum;
assert(i > TiedOp && "Tied operand precedes its target!");
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: {
@@ -2296,29 +2285,25 @@ static std::string GetAliasRequiredFeatures(Record *R,
return Result;
}
-/// emitMnemonicAliases - If the target has any MnemonicAlias<> definitions,
-/// emit a function for them and return true, otherwise return false.
-static bool emitMnemonicAliases(raw_ostream &OS, const AsmMatcherInfo &Info) {
- // Ignore aliases when match-prefix is set.
- if (!MatchPrefix.empty())
- return false;
-
- std::vector<Record*> Aliases =
- Info.getRecords().getAllDerivedDefinitions("MnemonicAlias");
- if (Aliases.empty()) return false;
-
- OS << "static void applyMnemonicAliases(StringRef &Mnemonic, "
- "unsigned Features) {\n";
-
+static void emitMnemonicAliasVariant(raw_ostream &OS,const AsmMatcherInfo &Info,
+ std::vector<Record*> &Aliases,
+ unsigned Indent = 0,
+ StringRef AsmParserVariantName = StringRef()){
// Keep track of all the aliases from a mnemonic. Use an std::map so that the
// iteration order of the map is stable.
std::map<std::string, std::vector<Record*> > AliasesFromMnemonic;
for (unsigned i = 0, e = Aliases.size(); i != e; ++i) {
Record *R = Aliases[i];
+ // FIXME: Allow AssemblerVariantName to be a comma separated list.
+ std::string AsmVariantName = R->getValueAsString("AsmVariantName");
+ if (AsmVariantName != AsmParserVariantName)
+ continue;
AliasesFromMnemonic[R->getValueAsString("FromMnemonic")].push_back(R);
}
-
+ if (AliasesFromMnemonic.empty())
+ return;
+
// Process each alias a "from" mnemonic at a time, building the code executed
// by the string remapper.
std::vector<StringMatcher::StringPair> Cases;
@@ -2370,8 +2355,39 @@ static bool emitMnemonicAliases(raw_ostream &OS, const AsmMatcherInfo &Info) {
Cases.push_back(std::make_pair(I->first, MatchCode));
}
+ StringMatcher("Mnemonic", Cases, OS).Emit(Indent);
+}
+
+/// emitMnemonicAliases - If the target has any MnemonicAlias<> definitions,
+/// emit a function for them and return true, otherwise return false.
+static bool emitMnemonicAliases(raw_ostream &OS, const AsmMatcherInfo &Info,
+ CodeGenTarget &Target) {
+ // Ignore aliases when match-prefix is set.
+ if (!MatchPrefix.empty())
+ return false;
+
+ std::vector<Record*> Aliases =
+ Info.getRecords().getAllDerivedDefinitions("MnemonicAlias");
+ if (Aliases.empty()) return false;
+
+ OS << "static void applyMnemonicAliases(StringRef &Mnemonic, "
+ "unsigned Features, unsigned VariantID) {\n";
+ OS << " switch (VariantID) {\n";
+ unsigned VariantCount = Target.getAsmParserVariantCount();
+ for (unsigned VC = 0; VC != VariantCount; ++VC) {
+ Record *AsmVariant = Target.getAsmParserVariant(VC);
+ int AsmParserVariantNo = AsmVariant->getValueAsInt("Variant");
+ std::string AsmParserVariantName = AsmVariant->getValueAsString("Name");
+ OS << " case " << AsmParserVariantNo << ":\n";
+ emitMnemonicAliasVariant(OS, Info, Aliases, /*Indent=*/2,
+ AsmParserVariantName);
+ OS << " break;\n";
+ }
+ OS << " }\n";
+
+ // Emit aliases that apply to all variants.
+ emitMnemonicAliasVariant(OS, Info, Aliases);
- StringMatcher("Mnemonic", Cases, OS).Emit();
OS << "}\n\n";
return true;
@@ -2674,7 +2690,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << "#undef GET_MATCHER_IMPLEMENTATION\n\n";
// Generate the function that remaps for mnemonic aliases.
- bool HasMnemonicAliases = emitMnemonicAliases(OS, Info);
+ bool HasMnemonicAliases = emitMnemonicAliases(OS, Info, Target);
// Generate the convertToMCInst function to convert operands into an MCInst.
// Also, generate the convertToMapAndConstraints function for MS-style inline
@@ -2832,9 +2848,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
if (HasMnemonicAliases) {
OS << " // Process all MnemonicAliases to remap the mnemonic.\n";
- OS << " // FIXME : Add an entry in AsmParserVariant to check this.\n";
- OS << " if (!VariantID)\n";
- OS << " applyMnemonicAliases(Mnemonic, AvailableFeatures);\n\n";
+ OS << " applyMnemonicAliases(Mnemonic, AvailableFeatures, VariantID);\n\n";
}
// Emit code to compute the class list for this operand vector.
diff --git a/utils/TableGen/CMakeLists.txt b/utils/TableGen/CMakeLists.txt
index d0f44be69a..3ee1974431 100644
--- a/utils/TableGen/CMakeLists.txt
+++ b/utils/TableGen/CMakeLists.txt
@@ -33,4 +33,5 @@ add_tablegen(llvm-tblgen LLVM
X86DisassemblerTables.cpp
X86ModRMFilters.cpp
X86RecognizableInstr.cpp
+ CTagsEmitter.cpp
)
diff --git a/utils/TableGen/CTagsEmitter.cpp b/utils/TableGen/CTagsEmitter.cpp
new file mode 100644
index 0000000000..8bf777839b
--- /dev/null
+++ b/utils/TableGen/CTagsEmitter.cpp
@@ -0,0 +1,99 @@
+//===- CTagsEmitter.cpp - Generate ctags-compatible index ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend emits an index of definitions in ctags(1) format.
+// A helper script, utils/TableGen/tdtags, provides an easier-to-use
+// interface; run 'tdtags -H' for documentation.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "ctags-emitter"
+
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/TableGenBackend.h"
+#include <algorithm>
+#include <string>
+#include <vector>
+using namespace llvm;
+
+namespace llvm { extern SourceMgr SrcMgr; }
+
+namespace {
+
+class Tag {
+private:
+ const std::string *Id;
+ SMLoc Loc;
+public:
+ Tag(const std::string &Name, const SMLoc Location)
+ : Id(&Name), Loc(Location) {}
+ int operator<(const Tag &B) const { return *Id < *B.Id; }
+ void emit(raw_ostream &OS) const {
+ int BufferID = SrcMgr.FindBufferContainingLoc(Loc);
+ MemoryBuffer *CurMB = SrcMgr.getBufferInfo(BufferID).Buffer;
+ const char *BufferName = CurMB->getBufferIdentifier();
+ std::pair<unsigned, unsigned> LineAndColumn = SrcMgr.getLineAndColumn(Loc);
+ OS << *Id << "\t" << BufferName << "\t" << LineAndColumn.first << "\n";
+ }
+};
+
+class CTagsEmitter {
+private:
+ RecordKeeper &Records;
+public:
+ CTagsEmitter(RecordKeeper &R) : Records(R) {}
+
+ void run(raw_ostream &OS);
+
+private:
+ static SMLoc locate(const Record *R);
+};
+
+} // End anonymous namespace.
+
+SMLoc CTagsEmitter::locate(const Record *R) {
+ ArrayRef<SMLoc> Locs = R->getLoc();
+ if (Locs.empty()) {
+ SMLoc NullLoc;
+ return NullLoc;
+ }
+ return Locs.front();
+}
+
+void CTagsEmitter::run(raw_ostream &OS) {
+ const std::map<std::string, Record *> &Classes = Records.getClasses();
+ const std::map<std::string, Record *> &Defs = Records.getDefs();
+ std::vector<Tag> Tags;
+ // Collect tags.
+ Tags.reserve(Classes.size() + Defs.size());
+ for (std::map<std::string, Record *>::const_iterator I = Classes.begin(),
+ E = Classes.end();
+ I != E; ++I)
+ Tags.push_back(Tag(I->first, locate(I->second)));
+ for (std::map<std::string, Record *>::const_iterator I = Defs.begin(),
+ E = Defs.end();
+ I != E; ++I)
+ Tags.push_back(Tag(I->first, locate(I->second)));
+ // Emit tags.
+ std::sort(Tags.begin(), Tags.end());
+ OS << "!_TAG_FILE_FORMAT\t1\t/original ctags format/\n";
+ OS << "!_TAG_FILE_SORTED\t1\t/0=unsorted, 1=sorted, 2=foldcase/\n";
+ for (std::vector<Tag>::const_iterator I = Tags.begin(), E = Tags.end();
+ I != E; ++I)
+ I->emit(OS);
+}
+
+namespace llvm {
+
+void EmitCTags(RecordKeeper &RK, raw_ostream &OS) { CTagsEmitter(RK).run(OS); }
+
+} // End llvm namespace.
diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp
index 72fb77150c..8e5bb7760f 100644
--- a/utils/TableGen/CodeGenDAGPatterns.cpp
+++ b/utils/TableGen/CodeGenDAGPatterns.cpp
@@ -57,7 +57,7 @@ EEVT::TypeSet::TypeSet(MVT::SimpleValueType VT, TreePattern &TP) {
}
-EEVT::TypeSet::TypeSet(const std::vector<MVT::SimpleValueType> &VTList) {
+EEVT::TypeSet::TypeSet(ArrayRef<MVT::SimpleValueType> VTList) {
assert(!VTList.empty() && "empty list?");
TypeVec.append(VTList.begin(), VTList.end());
@@ -76,7 +76,7 @@ bool EEVT::TypeSet::FillWithPossibleTypes(TreePattern &TP,
bool (*Pred)(MVT::SimpleValueType),
const char *PredicateName) {
assert(isCompletelyUnknown());
- const std::vector<MVT::SimpleValueType> &LegalTypes =
+ ArrayRef<MVT::SimpleValueType> LegalTypes =
TP.getDAGPatterns().getTargetInfo().getLegalValueTypes();
if (TP.hasError())
@@ -956,6 +956,40 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N,
llvm_unreachable("Invalid ConstraintType!");
}
+// Update the node type to match an instruction operand or result as specified
+// in the ins or outs lists on the instruction definition. Return true if the
+// type was actually changed.
+bool TreePatternNode::UpdateNodeTypeFromInst(unsigned ResNo,
+ Record *Operand,
+ TreePattern &TP) {
+ // The 'unknown' operand indicates that types should be inferred from the
+ // context.
+ if (Operand->isSubClassOf("unknown_class"))
+ return false;
+
+ // The Operand class specifies a type directly.
+ if (Operand->isSubClassOf("Operand"))
+ return UpdateNodeType(ResNo, getValueType(Operand->getValueAsDef("Type")),
+ TP);
+
+ // PointerLikeRegClass has a type that is determined at runtime.
+ if (Operand->isSubClassOf("PointerLikeRegClass"))
+ return UpdateNodeType(ResNo, MVT::iPTR, TP);
+
+ // Both RegisterClass and RegisterOperand operands derive their types from a
+ // register class def.
+ Record *RC = 0;
+ if (Operand->isSubClassOf("RegisterClass"))
+ RC = Operand;
+ else if (Operand->isSubClassOf("RegisterOperand"))
+ RC = Operand->getValueAsDef("RegClass");
+
+ assert(RC && "Unknown operand type");
+ CodeGenTarget &Tgt = TP.getDAGPatterns().getTargetInfo();
+ return UpdateNodeType(ResNo, Tgt.getRegisterClass(RC).getValueTypes(), TP);
+}
+
+
//===----------------------------------------------------------------------===//
// SDNodeInfo implementation
//
@@ -1287,8 +1321,18 @@ TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) {
/// type which should be applied to it. This will infer the type of register
/// references from the register file information, for example.
///
+/// When Unnamed is set, return the type of a DAG operand with no name, such as
+/// the F8RC register class argument in:
+///
+/// (COPY_TO_REGCLASS GPR:$src, F8RC)
+///
+/// When Unnamed is false, return the type of a named DAG operand such as the
+/// GPR:$src operand above.
+///
static EEVT::TypeSet getImplicitType(Record *R, unsigned ResNo,
- bool NotRegisters, TreePattern &TP) {
+ bool NotRegisters,
+ bool Unnamed,
+ TreePattern &TP) {
// Check to see if this is a register operand.
if (R->isSubClassOf("RegisterOperand")) {
assert(ResNo == 0 && "Regoperand ref only has one result!");
@@ -1302,6 +1346,13 @@ static EEVT::TypeSet getImplicitType(Record *R, unsigned ResNo,
// Check to see if this is a register or a register class.
if (R->isSubClassOf("RegisterClass")) {
assert(ResNo == 0 && "Regclass ref only has one result!");
+ // An unnamed register class represents itself as an i32 immediate, for
+ // example on a COPY_TO_REGCLASS instruction.
+ if (Unnamed)
+ return EEVT::TypeSet(MVT::i32, TP);
+
+ // In a named operand, the register class provides the possible set of
+ // types.
if (NotRegisters)
return EEVT::TypeSet(); // Unknown.
const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo();
@@ -1327,9 +1378,27 @@ static EEVT::TypeSet getImplicitType(Record *R, unsigned ResNo,
return EEVT::TypeSet();
}
- if (R->isSubClassOf("ValueType") || R->isSubClassOf("CondCode")) {
+ if (R->isSubClassOf("ValueType")) {
assert(ResNo == 0 && "This node only has one result!");
- // Using a VTSDNode or CondCodeSDNode.
+ // An unnamed VTSDNode represents itself as an MVT::Other immediate.
+ //
+ // (sext_inreg GPR:$src, i16)
+ // ~~~
+ if (Unnamed)
+ return EEVT::TypeSet(MVT::Other, TP);
+ // With a name, the ValueType simply provides the type of the named
+ // variable.
+ //
+ //