summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/utils/TableGen
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/utils/TableGen')
-rw-r--r--contrib/llvm/utils/TableGen/ARMDecoderEmitter.cpp20
-rw-r--r--contrib/llvm/utils/TableGen/ARMDecoderEmitter.h3
-rw-r--r--contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp69
-rw-r--r--contrib/llvm/utils/TableGen/AsmMatcherEmitter.h2
-rw-r--r--contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp14
-rw-r--r--contrib/llvm/utils/TableGen/AsmWriterEmitter.h2
-rw-r--r--contrib/llvm/utils/TableGen/AsmWriterInst.cpp2
-rw-r--r--contrib/llvm/utils/TableGen/CallingConvEmitter.cpp2
-rw-r--r--contrib/llvm/utils/TableGen/CallingConvEmitter.h2
-rw-r--r--contrib/llvm/utils/TableGen/ClangASTNodesEmitter.cpp168
-rw-r--r--contrib/llvm/utils/TableGen/ClangASTNodesEmitter.h84
-rw-r--r--contrib/llvm/utils/TableGen/ClangAttrEmitter.cpp756
-rw-r--r--contrib/llvm/utils/TableGen/ClangAttrEmitter.h101
-rw-r--r--contrib/llvm/utils/TableGen/ClangDiagnosticsEmitter.cpp362
-rw-r--r--contrib/llvm/utils/TableGen/ClangDiagnosticsEmitter.h54
-rw-r--r--contrib/llvm/utils/TableGen/ClangSACheckersEmitter.cpp319
-rw-r--r--contrib/llvm/utils/TableGen/ClangSACheckersEmitter.h31
-rw-r--r--contrib/llvm/utils/TableGen/CodeEmitterGen.cpp14
-rw-r--r--contrib/llvm/utils/TableGen/CodeEmitterGen.h2
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp25
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenInstruction.cpp21
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenInstruction.h1
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenRegisters.cpp294
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenRegisters.h112
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenTarget.cpp12
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenTarget.h6
-rw-r--r--contrib/llvm/utils/TableGen/DAGISelEmitter.cpp2
-rw-r--r--contrib/llvm/utils/TableGen/DAGISelEmitter.h2
-rw-r--r--contrib/llvm/utils/TableGen/DAGISelMatcher.cpp2
-rw-r--r--contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp2
-rw-r--r--contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp6
-rw-r--r--contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp20
-rw-r--r--contrib/llvm/utils/TableGen/DisassemblerEmitter.h2
-rw-r--r--contrib/llvm/utils/TableGen/EDEmitter.cpp76
-rw-r--r--contrib/llvm/utils/TableGen/EDEmitter.h2
-rw-r--r--contrib/llvm/utils/TableGen/Error.cpp39
-rw-r--r--contrib/llvm/utils/TableGen/Error.h43
-rw-r--r--contrib/llvm/utils/TableGen/FastISelEmitter.cpp6
-rw-r--r--contrib/llvm/utils/TableGen/FastISelEmitter.h2
-rw-r--r--contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp492
-rw-r--r--contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.h47
-rw-r--r--contrib/llvm/utils/TableGen/InstrEnumEmitter.cpp2
-rw-r--r--contrib/llvm/utils/TableGen/InstrEnumEmitter.h2
-rw-r--r--contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp4
-rw-r--r--contrib/llvm/utils/TableGen/InstrInfoEmitter.h2
-rw-r--r--contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp2
-rw-r--r--contrib/llvm/utils/TableGen/IntrinsicEmitter.h2
-rw-r--r--contrib/llvm/utils/TableGen/LLVMCConfigurationEmitter.cpp3134
-rw-r--r--contrib/llvm/utils/TableGen/LLVMCConfigurationEmitter.h34
-rw-r--r--contrib/llvm/utils/TableGen/NeonEmitter.cpp1558
-rw-r--r--contrib/llvm/utils/TableGen/NeonEmitter.h176
-rw-r--r--contrib/llvm/utils/TableGen/OptParserEmitter.cpp194
-rw-r--r--contrib/llvm/utils/TableGen/OptParserEmitter.h34
-rw-r--r--contrib/llvm/utils/TableGen/PseudoLoweringEmitter.cpp4
-rw-r--r--contrib/llvm/utils/TableGen/PseudoLoweringEmitter.h2
-rw-r--r--contrib/llvm/utils/TableGen/Record.cpp1575
-rw-r--r--contrib/llvm/utils/TableGen/Record.h1500
-rw-r--r--contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp566
-rw-r--r--contrib/llvm/utils/TableGen/RegisterInfoEmitter.h9
-rw-r--r--contrib/llvm/utils/TableGen/SetTheory.cpp4
-rw-r--r--contrib/llvm/utils/TableGen/SubtargetEmitter.cpp2
-rw-r--r--contrib/llvm/utils/TableGen/SubtargetEmitter.h2
-rw-r--r--contrib/llvm/utils/TableGen/TGLexer.cpp435
-rw-r--r--contrib/llvm/utils/TableGen/TGLexer.h125
-rw-r--r--contrib/llvm/utils/TableGen/TGParser.cpp2152
-rw-r--r--contrib/llvm/utils/TableGen/TGParser.h122
-rw-r--r--contrib/llvm/utils/TableGen/TableGen.cpp289
-rw-r--r--contrib/llvm/utils/TableGen/TableGenBackend.cpp25
-rw-r--r--contrib/llvm/utils/TableGen/TableGenBackend.h43
-rw-r--r--contrib/llvm/utils/TableGen/X86DisassemblerTables.cpp93
-rw-r--r--contrib/llvm/utils/TableGen/X86DisassemblerTables.h6
-rw-r--r--contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp100
-rw-r--r--contrib/llvm/utils/TableGen/X86RecognizableInstr.h8
73 files changed, 1409 insertions, 14018 deletions
diff --git a/contrib/llvm/utils/TableGen/ARMDecoderEmitter.cpp b/contrib/llvm/utils/TableGen/ARMDecoderEmitter.cpp
index 8a5dc8b..145b96d 100644
--- a/contrib/llvm/utils/TableGen/ARMDecoderEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/ARMDecoderEmitter.cpp
@@ -18,10 +18,10 @@
#include "ARMDecoderEmitter.h"
#include "CodeGenTarget.h"
-#include "Record.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/TableGen/Record.h"
#include <vector>
#include <map>
@@ -41,7 +41,7 @@ using namespace llvm;
ENTRY(ARM_FORMAT_BRFRM, 2) \
ENTRY(ARM_FORMAT_BRMISCFRM, 3) \
ENTRY(ARM_FORMAT_DPFRM, 4) \
- ENTRY(ARM_FORMAT_DPSOREGFRM, 5) \
+ ENTRY(ARM_FORMAT_DPSOREGREGFRM, 5) \
ENTRY(ARM_FORMAT_LDFRM, 6) \
ENTRY(ARM_FORMAT_STFRM, 7) \
ENTRY(ARM_FORMAT_LDMISCFRM, 8) \
@@ -77,7 +77,8 @@ using namespace llvm;
ENTRY(ARM_FORMAT_N3RegVecSh, 38) \
ENTRY(ARM_FORMAT_NVecExtract, 39) \
ENTRY(ARM_FORMAT_NVecMulScalar, 40) \
- ENTRY(ARM_FORMAT_NVTBL, 41)
+ ENTRY(ARM_FORMAT_NVTBL, 41) \
+ ENTRY(ARM_FORMAT_DPSOREGIMMFRM, 42)
// ARM instruction format specifies the encoding used by the instruction.
#define ENTRY(n, v) n = v,
@@ -1614,15 +1615,6 @@ ARMDEBackend::populateInstruction(const CodeGenInstruction &CGI,
if (!thumbInstruction(Form))
return false;
- // A8.6.189 STM / STMIA / STMEA -- Encoding T1
- // There's only STMIA_UPD for Thumb1.
- if (Name == "tSTMIA")
- return false;
-
- // On Darwin R9 is call-clobbered. Ignore the non-Darwin counterparts.
- if (Name == "tBL" || Name == "tBLXi" || Name == "tBLXr")
- return false;
-
// A8.6.25 BX. Use the generic tBX_Rm, ignore tBX_RET and tBX_RET_vararg.
if (Name == "tBX_RET" || Name == "tBX_RET_vararg")
return false;
@@ -1654,14 +1646,12 @@ ARMDEBackend::populateInstruction(const CodeGenInstruction &CGI,
// Resolve conflicts:
//
- // tBfar conflicts with tBLr9
// t2LDMIA_RET conflict with t2LDM (ditto)
// tMOVCCi conflicts with tMOVi8
// tMOVCCr conflicts with tMOVgpr2gpr
// tLDRcp conflicts with tLDRspi
// t2MOVCCi16 conflicts with tMOVi16
- if (Name == "tBfar" ||
- Name == "t2LDMIA_RET" ||
+ if (Name == "t2LDMIA_RET" ||
Name == "tMOVCCi" || Name == "tMOVCCr" ||
Name == "tLDRcp" ||
Name == "t2MOVCCi16")
diff --git a/contrib/llvm/utils/TableGen/ARMDecoderEmitter.h b/contrib/llvm/utils/TableGen/ARMDecoderEmitter.h
index 1faeb91..486f899 100644
--- a/contrib/llvm/utils/TableGen/ARMDecoderEmitter.h
+++ b/contrib/llvm/utils/TableGen/ARMDecoderEmitter.h
@@ -15,9 +15,8 @@
#ifndef ARMDECODEREMITTER_H
#define ARMDECODEREMITTER_H
-#include "TableGenBackend.h"
-
#include "llvm/Support/DataTypes.h"
+#include "llvm/TableGen/TableGenBackend.h"
namespace llvm {
diff --git a/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp b/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp
index a6a4fec..8b86c23 100644
--- a/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp
@@ -98,8 +98,6 @@
#include "AsmMatcherEmitter.h"
#include "CodeGenTarget.h"
-#include "Error.h"
-#include "Record.h"
#include "StringMatcher.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/PointerUnion.h"
@@ -109,6 +107,8 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
#include <map>
#include <set>
using namespace llvm;
@@ -914,17 +914,17 @@ void AsmMatcherInfo::
BuildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) {
const std::vector<CodeGenRegister*> &Registers =
Target.getRegBank().getRegisters();
- const std::vector<CodeGenRegisterClass> &RegClassList =
- Target.getRegisterClasses();
+ ArrayRef<CodeGenRegisterClass*> RegClassList =
+ Target.getRegBank().getRegClasses();
// The register sets used for matching.
std::set< std::set<Record*> > RegisterSets;
// Gather the defined sets.
- for (std::vector<CodeGenRegisterClass>::const_iterator it =
+ for (ArrayRef<CodeGenRegisterClass*>::const_iterator it =
RegClassList.begin(), ie = RegClassList.end(); it != ie; ++it)
- RegisterSets.insert(std::set<Record*>(it->getOrder().begin(),
- it->getOrder().end()));
+ RegisterSets.insert(std::set<Record*>(
+ (*it)->getOrder().begin(), (*it)->getOrder().end()));
// Add any required singleton sets.
for (SmallPtrSet<Record*, 16>::iterator it = SingletonRegisters.begin(),
@@ -996,18 +996,23 @@ BuildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) {
}
// Name the register classes which correspond to a user defined RegisterClass.
- for (std::vector<CodeGenRegisterClass>::const_iterator
+ for (ArrayRef<CodeGenRegisterClass*>::const_iterator
it = RegClassList.begin(), ie = RegClassList.end(); it != ie; ++it) {
- ClassInfo *CI = RegisterSetClasses[std::set<Record*>(it->getOrder().begin(),
- it->getOrder().end())];
+ const CodeGenRegisterClass &RC = **it;
+ // Def will be NULL for non-user defined register classes.
+ Record *Def = RC.getDef();
+ if (!Def)
+ continue;
+ ClassInfo *CI = RegisterSetClasses[std::set<Record*>(RC.getOrder().begin(),
+ RC.getOrder().end())];
if (CI->ValueName.empty()) {
- CI->ClassName = it->getName();
- CI->Name = "MCK_" + it->getName();
- CI->ValueName = it->getName();
+ CI->ClassName = RC.getName();
+ CI->Name = "MCK_" + RC.getName();
+ CI->ValueName = RC.getName();
} else
- CI->ValueName = CI->ValueName + "," + it->getName();
+ CI->ValueName = CI->ValueName + "," + RC.getName();
- RegisterClassClasses.insert(std::make_pair(it->TheDef, CI));
+ RegisterClassClasses.insert(std::make_pair(Def, CI));
}
// Populate the map for individual registers.
@@ -2172,21 +2177,14 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << "\n#ifdef GET_ASSEMBLER_HEADER\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 TargetAsmParser.\n";
+ OS << " // your subclasses implementation of MCTargetAsmParser.\n";
OS << " unsigned ComputeAvailableFeatures(uint64_t FeatureBits) const;\n";
- OS << " enum MatchResultTy {\n";
- OS << " Match_ConversionFail,\n";
- OS << " Match_InvalidOperand,\n";
- OS << " Match_MissingFeature,\n";
- OS << " Match_MnemonicFail,\n";
- OS << " Match_Success\n";
- OS << " };\n";
OS << " bool ConvertToMCInst(unsigned Kind, MCInst &Inst, "
<< "unsigned Opcode,\n"
<< " const SmallVectorImpl<MCParsedAsmOperand*> "
<< "&Operands);\n";
OS << " bool MnemonicIsValid(StringRef Mnemonic);\n";
- OS << " MatchResultTy MatchInstructionImpl(\n";
+ OS << " unsigned MatchInstructionImpl(\n";
OS << " const SmallVectorImpl<MCParsedAsmOperand*> &Operands,\n";
OS << " MCInst &Inst, unsigned &ErrorInfo);\n";
@@ -2328,7 +2326,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << "}\n\n";
// Finally, build the match function.
- OS << Target.getName() << ClassName << "::MatchResultTy "
+ OS << "unsigned "
<< Target.getName() << ClassName << "::\n"
<< "MatchInstructionImpl(const SmallVectorImpl<MCParsedAsmOperand*>"
<< " &Operands,\n";
@@ -2355,7 +2353,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " }\n\n";
OS << " // Some state to try to produce better error messages.\n";
- OS << " bool HadMatchOtherThanFeatures = false;\n\n";
+ OS << " bool HadMatchOtherThanFeatures = false;\n";
+ OS << " bool HadMatchOtherThanPredicate = false;\n";
+ OS << " unsigned RetCode = Match_InvalidOperand;\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";
@@ -2411,6 +2411,18 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " return Match_ConversionFail;\n";
OS << "\n";
+ // Verify the instruction with the target-specific match predicate function.
+ OS << " // We have a potential match. Check the target predicate to\n"
+ << " // handle any context sensitive constraints.\n"
+ << " unsigned MatchResult;\n"
+ << " if ((MatchResult = checkTargetMatchPredicate(Inst)) !="
+ << " Match_Success) {\n"
+ << " Inst.clear();\n"
+ << " RetCode = MatchResult;\n"
+ << " HadMatchOtherThanPredicate = true;\n"
+ << " continue;\n"
+ << " }\n\n";
+
// Call the post-processing function, if used.
std::string InsnCleanupFn =
AsmParser->getValueAsString("AsmParserInstCleanup");
@@ -2421,8 +2433,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " }\n\n";
OS << " // Okay, we had no match. Try to return a useful error code.\n";
- OS << " if (HadMatchOtherThanFeatures) return Match_MissingFeature;\n";
- OS << " return Match_InvalidOperand;\n";
+ OS << " if (HadMatchOtherThanPredicate || !HadMatchOtherThanFeatures)";
+ OS << " return RetCode;\n";
+ OS << " return Match_MissingFeature;\n";
OS << "}\n\n";
if (Info.OperandMatchInfo.size())
diff --git a/contrib/llvm/utils/TableGen/AsmMatcherEmitter.h b/contrib/llvm/utils/TableGen/AsmMatcherEmitter.h
index c13adf3..e04ac10 100644
--- a/contrib/llvm/utils/TableGen/AsmMatcherEmitter.h
+++ b/contrib/llvm/utils/TableGen/AsmMatcherEmitter.h
@@ -15,7 +15,7 @@
#ifndef ASMMATCHER_EMITTER_H
#define ASMMATCHER_EMITTER_H
-#include "TableGenBackend.h"
+#include "llvm/TableGen/TableGenBackend.h"
#include <cassert>
namespace llvm {
diff --git a/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp b/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp
index f44f050..3123e11 100644
--- a/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp
@@ -14,13 +14,13 @@
#include "AsmWriterEmitter.h"
#include "AsmWriterInst.h"
-#include "Error.h"
#include "CodeGenTarget.h"
-#include "Record.h"
#include "StringToOffsetTable.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/MathExtras.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
#include <algorithm>
using namespace llvm;
@@ -703,8 +703,8 @@ void AsmWriterEmitter::EmitRegIsInRegClass(raw_ostream &O) {
CodeGenTarget Target(Records);
// Enumerate the register classes.
- const std::vector<CodeGenRegisterClass> &RegisterClasses =
- Target.getRegisterClasses();
+ ArrayRef<CodeGenRegisterClass*> RegisterClasses =
+ Target.getRegBank().getRegClasses();
O << "namespace { // Register classes\n";
O << " enum RegClass {\n";
@@ -712,7 +712,7 @@ void AsmWriterEmitter::EmitRegIsInRegClass(raw_ostream &O) {
// Emit the register enum value for each RegisterClass.
for (unsigned I = 0, E = RegisterClasses.size(); I != E; ++I) {
if (I != 0) O << ",\n";
- O << " RC_" << RegisterClasses[I].TheDef->getName();
+ O << " RC_" << RegisterClasses[I]->getName();
}
O << "\n };\n";
@@ -729,10 +729,10 @@ void AsmWriterEmitter::EmitRegIsInRegClass(raw_ostream &O) {
O << " default: break;\n";
for (unsigned I = 0, E = RegisterClasses.size(); I != E; ++I) {
- const CodeGenRegisterClass &RC = RegisterClasses[I];
+ const CodeGenRegisterClass &RC = *RegisterClasses[I];
// Give the register class a legal C name if it's anonymous.
- std::string Name = RC.TheDef->getName();
+ std::string Name = RC.getName();
O << " case RC_" << Name << ":\n";
// Emit the register list now.
diff --git a/contrib/llvm/utils/TableGen/AsmWriterEmitter.h b/contrib/llvm/utils/TableGen/AsmWriterEmitter.h
index 84c925b..731e31c 100644
--- a/contrib/llvm/utils/TableGen/AsmWriterEmitter.h
+++ b/contrib/llvm/utils/TableGen/AsmWriterEmitter.h
@@ -15,7 +15,7 @@
#ifndef ASMWRITER_EMITTER_H
#define ASMWRITER_EMITTER_H
-#include "TableGenBackend.h"
+#include "llvm/TableGen/TableGenBackend.h"
#include <map>
#include <vector>
#include <cassert>
diff --git a/contrib/llvm/utils/TableGen/AsmWriterInst.cpp b/contrib/llvm/utils/TableGen/AsmWriterInst.cpp
index fdf447f..350a2cc 100644
--- a/contrib/llvm/utils/TableGen/AsmWriterInst.cpp
+++ b/contrib/llvm/utils/TableGen/AsmWriterInst.cpp
@@ -13,8 +13,8 @@
#include "AsmWriterInst.h"
#include "CodeGenTarget.h"
-#include "Record.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/TableGen/Record.h"
using namespace llvm;
diff --git a/contrib/llvm/utils/TableGen/CallingConvEmitter.cpp b/contrib/llvm/utils/TableGen/CallingConvEmitter.cpp
index c51afd8..fcdaa08 100644
--- a/contrib/llvm/utils/TableGen/CallingConvEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/CallingConvEmitter.cpp
@@ -13,8 +13,8 @@
//===----------------------------------------------------------------------===//
#include "CallingConvEmitter.h"
-#include "Record.h"
#include "CodeGenTarget.h"
+#include "llvm/TableGen/Record.h"
using namespace llvm;
void CallingConvEmitter::run(raw_ostream &O) {
diff --git a/contrib/llvm/utils/TableGen/CallingConvEmitter.h b/contrib/llvm/utils/TableGen/CallingConvEmitter.h
index 431c33b..7bddd6c 100644
--- a/contrib/llvm/utils/TableGen/CallingConvEmitter.h
+++ b/contrib/llvm/utils/TableGen/CallingConvEmitter.h
@@ -15,7 +15,7 @@
#ifndef CALLINGCONV_EMITTER_H
#define CALLINGCONV_EMITTER_H
-#include "TableGenBackend.h"
+#include "llvm/TableGen/TableGenBackend.h"
#include <cassert>
namespace llvm {
diff --git a/contrib/llvm/utils/TableGen/ClangASTNodesEmitter.cpp b/contrib/llvm/utils/TableGen/ClangASTNodesEmitter.cpp
deleted file mode 100644
index d9d5a3c..0000000
--- a/contrib/llvm/utils/TableGen/ClangASTNodesEmitter.cpp
+++ /dev/null
@@ -1,168 +0,0 @@
-//=== ClangASTNodesEmitter.cpp - Generate Clang AST node tables -*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// These tablegen backends emit Clang AST node tables
-//
-//===----------------------------------------------------------------------===//
-
-#include "ClangASTNodesEmitter.h"
-#include <set>
-using namespace llvm;
-
-//===----------------------------------------------------------------------===//
-// Statement Node Tables (.inc file) generation.
-//===----------------------------------------------------------------------===//
-
-// Returns the first and last non-abstract subrecords
-// Called recursively to ensure that nodes remain contiguous
-std::pair<Record *, Record *> ClangASTNodesEmitter::EmitNode(
- const ChildMap &Tree,
- raw_ostream &OS,
- Record *Base) {
- std::string BaseName = macroName(Base->getName());
-
- ChildIterator i = Tree.lower_bound(Base), e = Tree.upper_bound(Base);
-
- Record *First = 0, *Last = 0;
- // This might be the pseudo-node for Stmt; don't assume it has an Abstract
- // bit
- if (Base->getValue("Abstract") && !Base->getValueAsBit("Abstract"))
- First = Last = Base;
-
- for (; i != e; ++i) {
- Record *R = i->second;
- bool Abstract = R->getValueAsBit("Abstract");
- std::string NodeName = macroName(R->getName());
-
- OS << "#ifndef " << NodeName << "\n";
- OS << "# define " << NodeName << "(Type, Base) "
- << BaseName << "(Type, Base)\n";
- OS << "#endif\n";
-
- if (Abstract)
- OS << "ABSTRACT_" << macroName(Root.getName()) << "(" << NodeName << "("
- << R->getName() << ", " << baseName(*Base) << "))\n";
- else
- OS << NodeName << "(" << R->getName() << ", "
- << baseName(*Base) << ")\n";
-
- if (Tree.find(R) != Tree.end()) {
- const std::pair<Record *, Record *> &Result
- = EmitNode(Tree, OS, R);
- if (!First && Result.first)
- First = Result.first;
- if (Result.second)
- Last = Result.second;
- } else {
- if (!Abstract) {
- Last = R;
-
- if (!First)
- First = R;
- }
- }
-
- OS << "#undef " << NodeName << "\n\n";
- }
-
- if (First) {
- assert (Last && "Got a first node but not a last node for a range!");
- if (Base == &Root)
- OS << "LAST_" << macroName(Root.getName()) << "_RANGE(";
- else
- OS << macroName(Root.getName()) << "_RANGE(";
- OS << Base->getName() << ", " << First->getName() << ", "
- << Last->getName() << ")\n\n";
- }
-
- return std::make_pair(First, Last);
-}
-
-void ClangASTNodesEmitter::run(raw_ostream &OS) {
- // Write the preamble
- OS << "#ifndef ABSTRACT_" << macroName(Root.getName()) << "\n";
- OS << "# define ABSTRACT_" << macroName(Root.getName()) << "(Type) Type\n";
- OS << "#endif\n";
-
- OS << "#ifndef " << macroName(Root.getName()) << "_RANGE\n";
- OS << "# define "
- << macroName(Root.getName()) << "_RANGE(Base, First, Last)\n";
- OS << "#endif\n\n";
-
- OS << "#ifndef LAST_" << macroName(Root.getName()) << "_RANGE\n";
- OS << "# define LAST_"
- << macroName(Root.getName()) << "_RANGE(Base, First, Last) "
- << macroName(Root.getName()) << "_RANGE(Base, First, Last)\n";
- OS << "#endif\n\n";
-
- // Emit statements
- const std::vector<Record*> Stmts
- = Records.getAllDerivedDefinitions(Root.getName());
-
- ChildMap Tree;
-
- for (unsigned i = 0, e = Stmts.size(); i != e; ++i) {
- Record *R = Stmts[i];
-
- if (R->getValue("Base"))
- Tree.insert(std::make_pair(R->getValueAsDef("Base"), R));
- else
- Tree.insert(std::make_pair(&Root, R));
- }
-
- EmitNode(Tree, OS, &Root);
-
- OS << "#undef " << macroName(Root.getName()) << "\n";
- OS << "#undef " << macroName(Root.getName()) << "_RANGE\n";
- OS << "#undef LAST_" << macroName(Root.getName()) << "_RANGE\n";
- OS << "#undef ABSTRACT_" << macroName(Root.getName()) << "\n";
-}
-
-void ClangDeclContextEmitter::run(raw_ostream &OS) {
- // FIXME: Find a .td file format to allow for this to be represented better.
-
- OS << "#ifndef DECL_CONTEXT\n";
- OS << "# define DECL_CONTEXT(DECL)\n";
- OS << "#endif\n";
-
- OS << "#ifndef DECL_CONTEXT_BASE\n";
- OS << "# define DECL_CONTEXT_BASE(DECL) DECL_CONTEXT(DECL)\n";
- OS << "#endif\n";
-
- typedef std::set<Record*> RecordSet;
- typedef std::vector<Record*> RecordVector;
-
- RecordVector DeclContextsVector
- = Records.getAllDerivedDefinitions("DeclContext");
- RecordVector Decls = Records.getAllDerivedDefinitions("Decl");
- RecordSet DeclContexts (DeclContextsVector.begin(), DeclContextsVector.end());
-
- for (RecordVector::iterator i = Decls.begin(), e = Decls.end(); i != e; ++i) {
- Record *R = *i;
-
- if (R->getValue("Base")) {
- Record *B = R->getValueAsDef("Base");
- if (DeclContexts.find(B) != DeclContexts.end()) {
- OS << "DECL_CONTEXT_BASE(" << B->getName() << ")\n";
- DeclContexts.erase(B);
- }
- }
- }
-
- // To keep identical order, RecordVector may be used
- // instead of RecordSet.
- for (RecordVector::iterator
- i = DeclContextsVector.begin(), e = DeclContextsVector.end();
- i != e; ++i)
- if (DeclContexts.find(*i) != DeclContexts.end())
- OS << "DECL_CONTEXT(" << (*i)->getName() << ")\n";
-
- OS << "#undef DECL_CONTEXT\n";
- OS << "#undef DECL_CONTEXT_BASE\n";
-}
diff --git a/contrib/llvm/utils/TableGen/ClangASTNodesEmitter.h b/contrib/llvm/utils/TableGen/ClangASTNodesEmitter.h
deleted file mode 100644
index 712333b..0000000
--- a/contrib/llvm/utils/TableGen/ClangASTNodesEmitter.h
+++ /dev/null
@@ -1,84 +0,0 @@
-//===- ClangASTNodesEmitter.h - Generate Clang AST node tables -*- C++ -*--===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// These tablegen backends emit Clang AST node tables
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef CLANGAST_EMITTER_H
-#define CLANGAST_EMITTER_H
-
-#include "TableGenBackend.h"
-#include "Record.h"
-#include <string>
-#include <cctype>
-#include <map>
-
-namespace llvm {
-
-/// ClangASTNodesEmitter - The top-level class emits .inc files containing
-/// declarations of Clang statements.
-///
-class ClangASTNodesEmitter : public TableGenBackend {
- // A map from a node to each of its derived nodes.
- typedef std::multimap<Record*, Record*> ChildMap;
- typedef ChildMap::const_iterator ChildIterator;
-
- RecordKeeper &Records;
- Record Root;
- const std::string &BaseSuffix;
-
- // Create a macro-ized version of a name
- static std::string macroName(std::string S) {
- for (unsigned i = 0; i < S.size(); ++i)
- S[i] = std::toupper(S[i]);
-
- return S;
- }
-
- // Return the name to be printed in the base field. Normally this is
- // the record's name plus the base suffix, but if it is the root node and
- // the suffix is non-empty, it's just the suffix.
- std::string baseName(Record &R) {
- if (&R == &Root && !BaseSuffix.empty())
- return BaseSuffix;
-
- return R.getName() + BaseSuffix;
- }
-
- std::pair<Record *, Record *> EmitNode (const ChildMap &Tree, raw_ostream& OS,
- Record *Base);
-public:
- explicit ClangASTNodesEmitter(RecordKeeper &R, const std::string &N,
- const std::string &S)
- : Records(R), Root(N, SMLoc(), R), BaseSuffix(S)
- {}
-
- // run - Output the .inc file contents
- void run(raw_ostream &OS);
-};
-
-/// ClangDeclContextEmitter - Emits an addendum to a .inc file to enumerate the
-/// clang declaration contexts.
-///
-class ClangDeclContextEmitter : public TableGenBackend {
- RecordKeeper &Records;
-
-public:
- explicit ClangDeclContextEmitter(RecordKeeper &R)
- : Records(R)
- {}
-
- // run - Output the .inc file contents
- void run(raw_ostream &OS);
-};
-
-} // End llvm namespace
-
-#endif
diff --git a/contrib/llvm/utils/TableGen/ClangAttrEmitter.cpp b/contrib/llvm/utils/TableGen/ClangAttrEmitter.cpp
deleted file mode 100644
index 26bd878..0000000
--- a/contrib/llvm/utils/TableGen/ClangAttrEmitter.cpp
+++ /dev/null
@@ -1,756 +0,0 @@
-//===- ClangAttrEmitter.cpp - Generate Clang attribute handling =-*- C++ -*--=//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// These tablegen backends emit Clang attribute processing code
-//
-//===----------------------------------------------------------------------===//
-
-#include "ClangAttrEmitter.h"
-#include "Record.h"
-#include "llvm/ADT/StringSwitch.h"
-#include <algorithm>
-#include <cctype>
-
-using namespace llvm;
-
-static const std::vector<StringRef>
-getValueAsListOfStrings(Record &R, StringRef FieldName) {
- ListInit *List = R.getValueAsListInit(FieldName);
- assert (List && "Got a null ListInit");
-
- std::vector<StringRef> Strings;
- Strings.reserve(List->getSize());
-
- for (ListInit::iterator i = List->begin(), e = List->end(); i != e; ++i) {
- assert(*i && "Got a null element in a ListInit");
- if (StringInit *S = dynamic_cast<StringInit *>(*i))
- Strings.push_back(S->getValue());
- else if (CodeInit *C = dynamic_cast<CodeInit *>(*i))
- Strings.push_back(C->getValue());
- else
- assert(false && "Got a non-string, non-code element in a ListInit");
- }
-
- return Strings;
-}
-
-std::string ReadPCHRecord(StringRef type) {
- return StringSwitch<std::string>(type)
- .EndsWith("Decl *", "cast_or_null<" + std::string(type, 0, type.size()-1) +
- ">(GetDecl(Record[Idx++]))")
- .Case("QualType", "GetType(Record[Idx++])")
- .Case("Expr *", "ReadSubExpr()")
- .Case("IdentifierInfo *", "GetIdentifierInfo(Record, Idx)")
- .Default("Record[Idx++]");
-}
-
-// Assumes that the way to get the value is SA->getname()
-std::string WritePCHRecord(StringRef type, StringRef name) {
- return StringSwitch<std::string>(type)
- .EndsWith("Decl *", "AddDeclRef(" + std::string(name) +
- ", Record);\n")
- .Case("QualType", "AddTypeRef(" + std::string(name) + ", Record);\n")
- .Case("Expr *", "AddStmt(" + std::string(name) + ");\n")
- .Case("IdentifierInfo *",
- "AddIdentifierRef(" + std::string(name) + ", Record);\n")
- .Default("Record.push_back(" + std::string(name) + ");\n");
-}
-
-namespace {
- class Argument {
- std::string lowerName, upperName;
- StringRef attrName;
-
- public:
- Argument(Record &Arg, StringRef Attr)
- : lowerName(Arg.getValueAsString("Name")), upperName(lowerName),
- attrName(Attr) {
- if (!lowerName.empty()) {
- lowerName[0] = std::tolower(lowerName[0]);
- upperName[0] = std::toupper(upperName[0]);
- }
- }
- virtual ~Argument() {}
-
- StringRef getLowerName() const { return lowerName; }
- StringRef getUpperName() const { return upperName; }
- StringRef getAttrName() const { return attrName; }
-
- // These functions print the argument contents formatted in different ways.
- virtual void writeAccessors(raw_ostream &OS) const = 0;
- virtual void writeAccessorDefinitions(raw_ostream &OS) const {}
- virtual void writeCloneArgs(raw_ostream &OS) const = 0;
- virtual void writeCtorBody(raw_ostream &OS) const {}
- virtual void writeCtorInitializers(raw_ostream &OS) const = 0;
- virtual void writeCtorParameters(raw_ostream &OS) const = 0;
- virtual void writeDeclarations(raw_ostream &OS) const = 0;
- virtual void writePCHReadArgs(raw_ostream &OS) const = 0;
- virtual void writePCHReadDecls(raw_ostream &OS) const = 0;
- virtual void writePCHWrite(raw_ostream &OS) const = 0;
- };
-
- class SimpleArgument : public Argument {
- std::string type;
-
- public:
- SimpleArgument(Record &Arg, StringRef Attr, std::string T)
- : Argument(Arg, Attr), type(T)
- {}
-
- void writeAccessors(raw_ostream &OS) const {
- OS << " " << type << " get" << getUpperName() << "() const {\n";
- OS << " return " << getLowerName() << ";\n";
- OS << " }";
- }
- void writeCloneArgs(raw_ostream &OS) const {
- OS << getLowerName();
- }
- void writeCtorInitializers(raw_ostream &OS) const {
- OS << getLowerName() << "(" << getUpperName() << ")";
- }
- void writeCtorParameters(raw_ostream &OS) const {
- OS << type << " " << getUpperName();
- }
- void writeDeclarations(raw_ostream &OS) const {
- OS << type << " " << getLowerName() << ";";
- }
- void writePCHReadDecls(raw_ostream &OS) const {
- std::string read = ReadPCHRecord(type);
- OS << " " << type << " " << getLowerName() << " = " << read << ";\n";
- }
- void writePCHReadArgs(raw_ostream &OS) const {
- OS << getLowerName();
- }
- void writePCHWrite(raw_ostream &OS) const {
- OS << " " << WritePCHRecord(type, "SA->get" +
- std::string(getUpperName()) + "()");
- }
- };
-
- class StringArgument : public Argument {
- public:
- StringArgument(Record &Arg, StringRef Attr)
- : Argument(Arg, Attr)
- {}
-
- void writeAccessors(raw_ostream &OS) const {
- OS << " llvm::StringRef get" << getUpperName() << "() const {\n";
- OS << " return llvm::StringRef(" << getLowerName() << ", "
- << getLowerName() << "Length);\n";
- OS << " }\n";
- OS << " unsigned get" << getUpperName() << "Length() const {\n";
- OS << " return " << getLowerName() << "Length;\n";
- OS << " }\n";
- OS << " void set" << getUpperName()
- << "(ASTContext &C, llvm::StringRef S) {\n";
- OS << " " << getLowerName() << "Length = S.size();\n";
- OS << " this->" << getLowerName() << " = new (C, 1) char ["
- << getLowerName() << "Length];\n";
- OS << " std::memcpy(this->" << getLowerName() << ", S.data(), "
- << getLowerName() << "Length);\n";
- OS << " }";
- }
- void writeCloneArgs(raw_ostream &OS) const {
- OS << "get" << getUpperName() << "()";
- }
- void writeCtorBody(raw_ostream &OS) const {
- OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
- << ".data(), " << getLowerName() << "Length);";
- }
- void writeCtorInitializers(raw_ostream &OS) const {
- OS << getLowerName() << "Length(" << getUpperName() << ".size()),"
- << getLowerName() << "(new (Ctx, 1) char[" << getLowerName()
- << "Length])";
- }
- void writeCtorParameters(raw_ostream &OS) const {
- OS << "llvm::StringRef " << getUpperName();
- }
- void writeDeclarations(raw_ostream &OS) const {
- OS << "unsigned " << getLowerName() << "Length;\n";
- OS << "char *" << getLowerName() << ";";
- }
- void writePCHReadDecls(raw_ostream &OS) const {
- OS << " std::string " << getLowerName()
- << "= ReadString(Record, Idx);\n";
- }
- void writePCHReadArgs(raw_ostream &OS) const {
- OS << getLowerName();
- }
- void writePCHWrite(raw_ostream &OS) const {
- OS << " AddString(SA->get" << getUpperName() << "(), Record);\n";
- }
- };
-
- class AlignedArgument : public Argument {
- public:
- AlignedArgument(Record &Arg, StringRef Attr)
- : Argument(Arg, Attr)
- {}
-
- void writeAccessors(raw_ostream &OS) const {
- OS << " bool is" << getUpperName() << "Dependent() const;\n";
-
- OS << " unsigned get" << getUpperName() << "(ASTContext &Ctx) const;\n";
-
- OS << " bool is" << getUpperName() << "Expr() const {\n";
- OS << " return is" << getLowerName() << "Expr;\n";
- OS << " }\n";
-
- OS << " Expr *get" << getUpperName() << "Expr() const {\n";
- OS << " assert(is" << getLowerName() << "Expr);\n";
- OS << " return " << getLowerName() << "Expr;\n";
- OS << " }\n";
-
- OS << " TypeSourceInfo *get" << getUpperName() << "Type() const {\n";
- OS << " assert(!is" << getLowerName() << "Expr);\n";
- OS << " return " << getLowerName() << "Type;\n";
- OS << " }";
- }
- void writeAccessorDefinitions(raw_ostream &OS) const {
- OS << "bool " << getAttrName() << "Attr::is" << getUpperName()
- << "Dependent() const {\n";
- OS << " if (is" << getLowerName() << "Expr)\n";
- OS << " return " << getLowerName() << "Expr && (" << getLowerName()
- << "Expr->isValueDependent() || " << getLowerName()
- << "Expr->isTypeDependent());\n";
- OS << " else\n";
- OS << " return " << getLowerName()
- << "Type->getType()->isDependentType();\n";
- OS << "}\n";
-
- // FIXME: Do not do the calculation here
- // FIXME: Handle types correctly
- // A null pointer means maximum alignment
- // FIXME: Load the platform-specific maximum alignment, rather than
- // 16, the x86 max.
- OS << "unsigned " << getAttrName() << "Attr::get" << getUpperName()
- << "(ASTContext &Ctx) const {\n";
- OS << " assert(!is" << getUpperName() << "Dependent());\n";
- OS << " if (is" << getLowerName() << "Expr)\n";
- OS << " return (" << getLowerName() << "Expr ? " << getLowerName()
- << "Expr->EvaluateAsInt(Ctx).getZExtValue() : 16)"
- << "* Ctx.getCharWidth();\n";
- OS << " else\n";
- OS << " return 0; // FIXME\n";
- OS << "}\n";
- }
- void writeCloneArgs(raw_ostream &OS) const {
- OS << "is" << getLowerName() << "Expr, is" << getLowerName()
- << "Expr ? static_cast<void*>(" << getLowerName()
- << "Expr) : " << getLowerName()
- << "Type";
- }
- void writeCtorBody(raw_ostream &OS) const {
- OS << " if (is" << getLowerName() << "Expr)\n";
- OS << " " << getLowerName() << "Expr = reinterpret_cast<Expr *>("
- << getUpperName() << ");\n";
- OS << " else\n";
- OS << " " << getLowerName()
- << "Type = reinterpret_cast<TypeSourceInfo *>(" << getUpperName()
- << ");";
- }
- void writeCtorInitializers(raw_ostream &OS) const {
- OS << "is" << getLowerName() << "Expr(Is" << getUpperName() << "Expr)";
- }
- void writeCtorParameters(raw_ostream &OS) const {
- OS << "bool Is" << getUpperName() << "Expr, void *" << getUpperName();
- }
- void writeDeclarations(raw_ostream &OS) const {
- OS << "bool is" << getLowerName() << "Expr;\n";
- OS << "union {\n";
- OS << "Expr *" << getLowerName() << "Expr;\n";
- OS << "TypeSourceInfo *" << getLowerName() << "Type;\n";
- OS << "};";
- }
- void writePCHReadArgs(raw_ostream &OS) const {
- OS << "is" << getLowerName() << "Expr, " << getLowerName() << "Ptr";
- }
- void writePCHReadDecls(raw_ostream &OS) const {
- OS << " bool is" << getLowerName() << "Expr = Record[Idx++];\n";
- OS << " void *" << getLowerName() << "Ptr;\n";
- OS << " if (is" << getLowerName() << "Expr)\n";
- OS << " " << getLowerName() << "Ptr = ReadExpr(F);\n";
- OS << " else\n";
- OS << " " << getLowerName()
- << "Ptr = GetTypeSourceInfo(F, Record, Idx);\n";
- }
- void writePCHWrite(raw_ostream &OS) const {
- OS << " Record.push_back(SA->is" << getUpperName() << "Expr());\n";
- OS << " if (SA->is" << getUpperName() << "Expr())\n";
- OS << " AddStmt(SA->get" << getUpperName() << "Expr());\n";
- OS << " else\n";
- OS << " AddTypeSourceInfo(SA->get" << getUpperName()
- << "Type(), Record);\n";
- }
- };
-
- class VariadicArgument : public Argument {
- std::string type;
-
- public:
- VariadicArgument(Record &Arg, StringRef Attr, std::string T)
- : Argument(Arg, Attr), type(T)
- {}
-
- std::string getType() const { return type; }
-
- void writeAccessors(raw_ostream &OS) const {
- OS << " typedef " << type << "* " << getLowerName() << "_iterator;\n";
- OS << " " << getLowerName() << "_iterator " << getLowerName()
- << "_begin() const {\n";
- OS << " return " << getLowerName() << ";\n";
- OS << " }\n";
- OS << " " << getLowerName() << "_iterator " << getLowerName()
- << "_end() const {\n";
- OS << " return " << getLowerName() << " + " << getLowerName()
- << "Size;\n";
- OS << " }\n";
- OS << " unsigned " << getLowerName() << "_size() const {\n"
- << " return " << getLowerName() << "Size;\n;";
- OS << " }";
- }
- void writeCloneArgs(raw_ostream &OS) const {
- OS << getLowerName() << ", " << getLowerName() << "Size";
- }
- void writeCtorBody(raw_ostream &OS) const {
- // FIXME: memcpy is not safe on non-trivial types.
- OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
- << ", " << getLowerName() << "Size * sizeof(" << getType() << "));\n";
- }
- void writeCtorInitializers(raw_ostream &OS) const {
- OS << getLowerName() << "Size(" << getUpperName() << "Size), "
- << getLowerName() << "(new (Ctx, 16) " << getType() << "["
- << getLowerName() << "Size])";
- }
- void writeCtorParameters(raw_ostream &OS) const {
- OS << getType() << " *" << getUpperName() << ", unsigned "
- << getUpperName() << "Size";
- }
- void writeDeclarations(raw_ostream &OS) const {
- OS << " unsigned " << getLowerName() << "Size;\n";
- OS << " " << getType() << " *" << getLowerName() << ";";
- }
- void writePCHReadDecls(raw_ostream &OS) const {
- OS << " unsigned " << getLowerName() << "Size = Record[Idx++];\n";
- OS << " llvm::SmallVector<" << type << ", 4> " << getLowerName()
- << ";\n";
- OS << " " << getLowerName() << ".reserve(" << getLowerName()
- << "Size);\n";
- OS << " for (unsigned i = " << getLowerName() << "Size; i; --i)\n";
-
- std::string read = ReadPCHRecord(type);
- OS << " " << getLowerName() << ".push_back(" << read << ");\n";
- }
- void writePCHReadArgs(raw_ostream &OS) const {
- OS << getLowerName() << ".data(), " << getLowerName() << "Size";
- }
- void writePCHWrite(raw_ostream &OS) const{
- OS << " Record.push_back(SA->" << getLowerName() << "_size());\n";
- OS << " for (" << getAttrName() << "Attr::" << getLowerName()
- << "_iterator i = SA->" << getLowerName() << "_begin(), e = SA->"
- << getLowerName() << "_end(); i != e; ++i)\n";
- OS << " " << WritePCHRecord(type, "(*i)");
- }
- };
-
- class EnumArgument : public Argument {
- std::string type;
- std::vector<StringRef> values, enums;
- public:
- EnumArgument(Record &Arg, StringRef Attr)
- : Argument(Arg, Attr), type(Arg.getValueAsString("Type")),
- values(getValueAsListOfStrings(Arg, "Values")),
- enums(getValueAsListOfStrings(Arg, "Enums"))
- {}
-
- void writeAccessors(raw_ostream &OS) const {
- OS << " " << type << " get" << getUpperName() << "() const {\n";
- OS << " return " << getLowerName() << ";\n";
- OS << " }";
- }
- void writeCloneArgs(raw_ostream &OS) const {
- OS << getLowerName();
- }
- void writeCtorInitializers(raw_ostream &OS) const {
- OS << getLowerName() << "(" << getUpperName() << ")";
- }
- void writeCtorParameters(raw_ostream &OS) const {
- OS << type << " " << getUpperName();
- }
- void writeDeclarations(raw_ostream &OS) const {
- // Calculate the various enum values
- std::vector<StringRef> uniques(enums);
- std::sort(uniques.begin(), uniques.end());
- uniques.erase(std::unique(uniques.begin(), uniques.end()),
- uniques.end());
- // FIXME: Emit a proper error
- assert(!uniques.empty());
-
- std::vector<StringRef>::iterator i = uniques.begin(),
- e = uniques.end();
- // The last one needs to not have a comma.
- --e;
-
- OS << "public:\n";
- OS << " enum " << type << " {\n";
- for (; i != e; ++i)
- OS << " " << *i << ",\n";
- OS << " " << *e << "\n";
- OS << " };\n";
- OS << "private:\n";
- OS << " " << type << " " << getLowerName() << ";";
- }
- void writePCHReadDecls(raw_ostream &OS) const {
- OS << " " << getAttrName() << "Attr::" << type << " " << getLowerName()
- << "(static_cast<" << getAttrName() << "Attr::" << type
- << ">(Record[Idx++]));\n";
- }
- void writePCHReadArgs(raw_ostream &OS) const {
- OS << getLowerName();
- }
- void writePCHWrite(raw_ostream &OS) const {
- OS << "Record.push_back(SA->get" << getUpperName() << "());\n";
- }
- };
-
- class VersionArgument : public Argument {
- public:
- VersionArgument(Record &Arg, StringRef Attr)
- : Argument(Arg, Attr)
- {}
-
- void writeAccessors(raw_ostream &OS) const {
- OS << " VersionTuple get" << getUpperName() << "() const {\n";
- OS << " return " << getLowerName() << ";\n";
- OS << " }\n";
- OS << " void set" << getUpperName()
- << "(ASTContext &C, VersionTuple V) {\n";
- OS << " " << getLowerName() << " = V;\n";
- OS << " }";
- }
- void writeCloneArgs(raw_ostream &OS) const {
- OS << "get" << getUpperName() << "()";
- }
- void writeCtorBody(raw_ostream &OS) const {
- }
- void writeCtorInitializers(raw_ostream &OS) const {
- OS << getLowerName() << "(" << getUpperName() << ")";
- }
- void writeCtorParameters(raw_ostream &OS) const {
- OS << "VersionTuple " << getUpperName();
- }
- void writeDeclarations(raw_ostream &OS) const {
- OS << "VersionTuple " << getLowerName() << ";\n";
- }
- void writePCHReadDecls(raw_ostream &OS) const {
- OS << " VersionTuple " << getLowerName()
- << "= ReadVersionTuple(Record, Idx);\n";
- }
- void writePCHReadArgs(raw_ostream &OS) const {
- OS << getLowerName();
- }
- void writePCHWrite(raw_ostream &OS) const {
- OS << " AddVersionTuple(SA->get" << getUpperName() << "(), Record);\n";
- }
- };
-}
-
-static Argument *createArgument(Record &Arg, StringRef Attr,
- Record *Search = 0) {
- if (!Search)
- Search = &Arg;
-
- Argument *Ptr = 0;
- llvm::StringRef ArgName = Search->getName();
-
- if (ArgName == "AlignedArgument") Ptr = new AlignedArgument(Arg, Attr);
- else if (ArgName == "EnumArgument") Ptr = new EnumArgument(Arg, Attr);
- else if (ArgName == "ExprArgument") Ptr = new SimpleArgument(Arg, Attr,
- "Expr *");
- else if (ArgName == "FunctionArgument")
- Ptr = new SimpleArgument(Arg, Attr, "FunctionDecl *");
- else if (ArgName == "IdentifierArgument")
- Ptr = new SimpleArgument(Arg, Attr, "IdentifierInfo *");
- else if (ArgName == "BoolArgument") Ptr = new SimpleArgument(Arg, Attr,
- "bool");
- else if (ArgName == "IntArgument") Ptr = new SimpleArgument(Arg, Attr, "int");
- else if (ArgName == "StringArgument") Ptr = new StringArgument(Arg, Attr);
- else if (ArgName == "TypeArgument")
- Ptr = new SimpleArgument(Arg, Attr, "QualType");
- else if (ArgName == "UnsignedArgument")
- Ptr = new SimpleArgument(Arg, Attr, "unsigned");
- else if (ArgName == "VariadicUnsignedArgument")
- Ptr = new VariadicArgument(Arg, Attr, "unsigned");
- else if (ArgName == "VersionArgument")
- Ptr = new VersionArgument(Arg, Attr);
-
- if (!Ptr) {
- std::vector<Record*> Bases = Search->getSuperClasses();
- for (std::vector<Record*>::iterator i = Bases.begin(), e = Bases.end();
- i != e; ++i) {
- Ptr = createArgument(Arg, Attr, *i);
- if (Ptr)
- break;
- }
- }
- return Ptr;
-}
-
-void ClangAttrClassEmitter::run(raw_ostream &OS) {
- OS << "// This file is generated by TableGen. Do not edit.\n\n";
- OS << "#ifndef LLVM_CLANG_ATTR_CLASSES_INC\n";
- OS << "#define LLVM_CLANG_ATTR_CLASSES_INC\n\n";
-
- std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
-
- for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end();
- i != e; ++i) {
- Record &R = **i;
- const std::string &SuperName = R.getSuperClasses().back()->getName();
-
- OS << "class " << R.getName() << "Attr : public " << SuperName << " {\n";
-
- std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
- std::vector<Argument*> Args;
- std::vector<Argument*>::iterator ai, ae;
- Args.reserve(ArgRecords.size());
-
- for (std::vector<Record*>::iterator ri = ArgRecords.begin(),
- re = ArgRecords.end();
- ri != re; ++ri) {
- Record &ArgRecord = **ri;
- Argument *Arg = createArgument(ArgRecord, R.getName());
- assert(Arg);
- Args.push_back(Arg);
-
- Arg->writeDeclarations(OS);
- OS << "\n\n";
- }
-
- ae = Args.end();
-
- OS << "\n public:\n";
- OS << " " << R.getName() << "Attr(SourceLocation L, ASTContext &Ctx\n";
-
- for (ai = Args.begin(); ai != ae; ++ai) {
- OS << " , ";
- (*ai)->writeCtorParameters(OS);
- OS << "\n";
- }
-
- OS << " )\n";
- OS << " : " << SuperName << "(attr::" << R.getName() << ", L)\n";
-
- for (ai = Args.begin(); ai != ae; ++ai) {
- OS << " , ";
- (*ai)->writeCtorInitializers(OS);
- OS << "\n";
- }
-
- OS << " {\n";
-
- for (ai = Args.begin(); ai != ae; ++ai) {
- (*ai)->writeCtorBody(OS);
- OS << "\n";
- }
- OS << " }\n\n";
-
- OS << " virtual " << R.getName() << "Attr *clone (ASTContext &C) const;\n";
-
- for (ai = Args.begin(); ai != ae; ++ai) {
- (*ai)->writeAccessors(OS);
- OS << "\n\n";
- }
-
- OS << R.getValueAsCode("AdditionalMembers");
- OS << "\n\n";
-
- OS << " static bool classof(const Attr *A) { return A->getKind() == "
- << "attr::" << R.getName() << "; }\n";
- OS << " static bool classof(const " << R.getName()
- << "Attr *) { return true; }\n";
- OS << "};\n\n";
- }
-
- OS << "#endif\n";
-}
-
-void ClangAttrImplEmitter::run(raw_ostream &OS) {
- OS << "// This file is generated by TableGen. Do not edit.\n\n";
-
- std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
- std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ri, re;
- std::vector<Argument*>::iterator ai, ae;
-
- for (; i != e; ++i) {
- Record &R = **i;
- std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
- std::vector<Argument*> Args;
- for (ri = ArgRecords.begin(), re = ArgRecords.end(); ri != re; ++ri)
- Args.push_back(createArgument(**ri, R.getName()));
-
- for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai)
- (*ai)->writeAccessorDefinitions(OS);
-
- OS << R.getName() << "Attr *" << R.getName()
- << "Attr::clone(ASTContext &C) const {\n";
- OS << " return new (C) " << R.getName() << "Attr(getLocation(), C";
- for (ai = Args.begin(); ai != ae; ++ai) {
- OS << ", ";
- (*ai)->writeCloneArgs(OS);
- }
- OS << ");\n}\n\n";
- }
-}
-
-static void EmitAttrList(raw_ostream &OS, StringRef Class,
- const std::vector<Record*> &AttrList) {
- std::vector<Record*>::const_iterator i = AttrList.begin(), e = AttrList.end();
-
- if (i != e) {
- // Move the end iterator back to emit the last attribute.
- for(--e; i != e; ++i)
- OS << Class << "(" << (*i)->getName() << ")\n";
-
- OS << "LAST_" << Class << "(" << (*i)->getName() << ")\n\n";
- }
-}
-
-void ClangAttrListEmitter::run(raw_ostream &OS) {
- OS << "// This file is generated by TableGen. Do not edit.\n\n";
-
- OS << "#ifndef LAST_ATTR\n";
- OS << "#define LAST_ATTR(NAME) ATTR(NAME)\n";
- OS << "#endif\n\n";
-
- OS << "#ifndef INHERITABLE_ATTR\n";
- OS << "#define INHERITABLE_ATTR(NAME) ATTR(NAME)\n";
- OS << "#endif\n\n";
-
- OS << "#ifndef LAST_INHERITABLE_ATTR\n";
- OS << "#define LAST_INHERITABLE_ATTR(NAME) INHERITABLE_ATTR(NAME)\n";
- OS << "#endif\n\n";
-
- OS << "#ifndef INHERITABLE_PARAM_ATTR\n";
- OS << "#define INHERITABLE_PARAM_ATTR(NAME) ATTR(NAME)\n";
- OS << "#endif\n\n";
-
- OS << "#ifndef LAST_INHERITABLE_PARAM_ATTR\n";
- OS << "#define LAST_INHERITABLE_PARAM_ATTR(NAME)"
- " INHERITABLE_PARAM_ATTR(NAME)\n";
- OS << "#endif\n\n";
-
- Record *InhClass = Records.getClass("InheritableAttr");
- Record *InhParamClass = Records.getClass("InheritableParamAttr");
- std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
- NonInhAttrs, InhAttrs, InhParamAttrs;
- for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end();
- i != e; ++i) {
- if ((*i)->isSubClassOf(InhParamClass))
- InhParamAttrs.push_back(*i);
- else if ((*i)->isSubClassOf(InhClass))
- InhAttrs.push_back(*i);
- else
- NonInhAttrs.push_back(*i);
- }
-
- EmitAttrList(OS, "INHERITABLE_PARAM_ATTR", InhParamAttrs);
- EmitAttrList(OS, "INHERITABLE_ATTR", InhAttrs);
- EmitAttrList(OS, "ATTR", NonInhAttrs);
-
- OS << "#undef LAST_ATTR\n";
- OS << "#undef INHERITABLE_ATTR\n";
- OS << "#undef LAST_INHERITABLE_ATTR\n";
- OS << "#undef LAST_INHERITABLE_PARAM_ATTR\n";
- OS << "#undef ATTR\n";
-}
-
-void ClangAttrPCHReadEmitter::run(raw_ostream &OS) {
- OS << "// This file is generated by TableGen. Do not edit.\n\n";
-
- Record *InhClass = Records.getClass("InheritableAttr");
- std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
- ArgRecords;
- std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae;
- std::vector<Argument*> Args;
- std::vector<Argument*>::iterator ri, re;
-
- OS << " switch (Kind) {\n";
- OS << " default:\n";
- OS << " assert(0 && \"Unknown attribute!\");\n";
- OS << " break;\n";
- for (; i != e; ++i) {
- Record &R = **i;
- OS << " case attr::" << R.getName() << ": {\n";
- if (R.isSubClassOf(InhClass))
- OS << " bool isInherited = Record[Idx++];\n";
- ArgRecords = R.getValueAsListOfDefs("Args");
- Args.clear();
- for (ai = ArgRecords.begin(), ae = ArgRecords.end(); ai != ae; ++ai) {
- Argument *A = createArgument(**ai, R.getName());
- Args.push_back(A);
- A->writePCHReadDecls(OS);
- }
- OS << " New = new (*Context) " << R.getName() << "Attr(Loc, *Context";
- for (ri = Args.begin(), re = Args.end(); ri != re; ++ri) {
- OS << ", ";
- (*ri)->writePCHReadArgs(OS);
- }
- OS << ");\n";
- if (R.isSubClassOf(InhClass))
- OS << " cast<InheritableAttr>(New)->setInherited(isInherited);\n";
- OS << " break;\n";
- OS << " }\n";
- }
- OS << " }\n";
-}
-
-void ClangAttrPCHWriteEmitter::run(raw_ostream &OS) {
- Record *InhClass = Records.getClass("InheritableAttr");
- std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;
- std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae;
-
- OS << " switch (A->getKind()) {\n";
- OS << " default:\n";
- OS << " llvm_unreachable(\"Unknown attribute kind!\");\n";
- OS << " break;\n";
- for (; i != e; ++i) {
- Record &R = **i;
- OS << " case attr::" << R.getName() << ": {\n";
- Args = R.getValueAsListOfDefs("Args");
- if (R.isSubClassOf(InhClass) || !Args.empty())
- OS << " const " << R.getName() << "Attr *SA = cast<" << R.getName()
- << "Attr>(A);\n";
- if (R.isSubClassOf(InhClass))
- OS << " Record.push_back(SA->isInherited());\n";
- for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai)
- createArgument(**ai, R.getName())->writePCHWrite(OS);
- OS << " break;\n";
- OS << " }\n";
- }
- OS << " }\n";
-}
-
-void ClangAttrSpellingListEmitter::run(raw_ostream &OS) {
- OS << "// This file is generated by TableGen. Do not edit.\n\n";
-
- std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
-
- for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); I != E; ++I) {
- Record &Attr = **I;
-
- std::vector<StringRef> Spellings = getValueAsListOfStrings(Attr, "Spellings");
-
- for (std::vector<StringRef>::const_iterator I = Spellings.begin(), E = Spellings.end(); I != E; ++I) {
- StringRef Spelling = *I;
- OS << ".Case(\"" << Spelling << "\", true)\n";
- }
- }
-
-}
diff --git a/contrib/llvm/utils/TableGen/ClangAttrEmitter.h b/contrib/llvm/utils/TableGen/ClangAttrEmitter.h
deleted file mode 100644
index af87009..0000000
--- a/contrib/llvm/utils/TableGen/ClangAttrEmitter.h
+++ /dev/null
@@ -1,101 +0,0 @@
-//===- ClangAttrEmitter.h - Generate Clang attribute handling =-*- C++ -*--===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// These tablegen backends emit Clang attribute processing code
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef CLANGATTR_EMITTER_H
-#define CLANGATTR_EMITTER_H
-
-#include "TableGenBackend.h"
-
-namespace llvm {
-
-/// ClangAttrClassEmitter - class emits the class defintions for attributes for
-/// clang.
-class ClangAttrClassEmitter : public TableGenBackend {
- RecordKeeper &Records;
-
- public:
- explicit ClangAttrClassEmitter(RecordKeeper &R)
- : Records(R)
- {}
-
- void run(raw_ostream &OS);
-};
-
-/// ClangAttrImplEmitter - class emits the class method defintions for
-/// attributes for clang.
-class ClangAttrImplEmitter : public TableGenBackend {
- RecordKeeper &Records;
-
- public:
- explicit ClangAttrImplEmitter(RecordKeeper &R)
- : Records(R)
- {}
-
- void run(raw_ostream &OS);
-};
-
-/// ClangAttrListEmitter - class emits the enumeration list for attributes for
-/// clang.
-class ClangAttrListEmitter : public TableGenBackend {
- RecordKeeper &Records;
-
- public:
- explicit ClangAttrListEmitter(RecordKeeper &R)
- : Records(R)
- {}
-
- void run(raw_ostream &OS);
-};
-
-/// ClangAttrPCHReadEmitter - class emits the code to read an attribute from
-/// a clang precompiled header.
-class ClangAttrPCHReadEmitter : public TableGenBackend {
- RecordKeeper &Records;
-
-public:
- explicit ClangAttrPCHReadEmitter(RecordKeeper &R)
- : Records(R)
- {}
-
- void run(raw_ostream &OS);
-};
-
-/// ClangAttrPCHWriteEmitter - class emits the code to read an attribute from
-/// a clang precompiled header.
-class ClangAttrPCHWriteEmitter : public TableGenBackend {
- RecordKeeper &Records;
-
-public:
- explicit ClangAttrPCHWriteEmitter(RecordKeeper &R)
- : Records(R)
- {}
-
- void run(raw_ostream &OS);
-};
-
-/// ClangAttrSpellingListEmitter - class emits the list of spellings for attributes for
-/// clang.
-class ClangAttrSpellingListEmitter : public TableGenBackend {
- RecordKeeper &Records;
-
- public:
- explicit ClangAttrSpellingListEmitter(RecordKeeper &R)
- : Records(R)
- {}
-
- void run(raw_ostream &OS);
-};
-
-}
-
-#endif
diff --git a/contrib/llvm/utils/TableGen/ClangDiagnosticsEmitter.cpp b/contrib/llvm/utils/TableGen/ClangDiagnosticsEmitter.cpp
deleted file mode 100644
index 0a48e75..0000000
--- a/contrib/llvm/utils/TableGen/ClangDiagnosticsEmitter.cpp
+++ /dev/null
@@ -1,362 +0,0 @@
-//=- ClangDiagnosticsEmitter.cpp - Generate Clang diagnostics tables -*- C++ -*-
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// These tablegen backends emit Clang diagnostics tables.
-//
-//===----------------------------------------------------------------------===//
-
-#include "ClangDiagnosticsEmitter.h"
-#include "Record.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/ADT/DenseSet.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/VectorExtras.h"
-#include <map>
-#include <algorithm>
-#include <functional>
-using namespace llvm;
-
-//===----------------------------------------------------------------------===//
-// Diagnostic category computation code.
-//===----------------------------------------------------------------------===//
-
-namespace {
-class DiagGroupParentMap {
- RecordKeeper &Records;
- std::map<const Record*, std::vector<Record*> > Mapping;
-public:
- DiagGroupParentMap(RecordKeeper &records) : Records(records) {
- std::vector<Record*> DiagGroups
- = Records.getAllDerivedDefinitions("DiagGroup");
- for (unsigned i = 0, e = DiagGroups.size(); i != e; ++i) {
- std::vector<Record*> SubGroups =
- DiagGroups[i]->getValueAsListOfDefs("SubGroups");
- for (unsigned j = 0, e = SubGroups.size(); j != e; ++j)
- Mapping[SubGroups[j]].push_back(DiagGroups[i]);
- }
- }
-
- const std::vector<Record*> &getParents(const Record *Group) {
- return Mapping[Group];
- }
-};
-} // end anonymous namespace.
-
-
-static std::string
-getCategoryFromDiagGroup(const Record *Group,
- DiagGroupParentMap &DiagGroupParents) {
- // If the DiagGroup has a category, return it.
- std::string CatName = Group->getValueAsString("CategoryName");
- if (!CatName.empty()) return CatName;
-
- // The diag group may the subgroup of one or more other diagnostic groups,
- // check these for a category as well.
- const std::vector<Record*> &Parents = DiagGroupParents.getParents(Group);
- for (unsigned i = 0, e = Parents.size(); i != e; ++i) {
- CatName = getCategoryFromDiagGroup(Parents[i], DiagGroupParents);
- if (!CatName.empty()) return CatName;
- }
- return "";
-}
-
-/// getDiagnosticCategory - Return the category that the specified diagnostic
-/// lives in.
-static std::string getDiagnosticCategory(const Record *R,
- DiagGroupParentMap &DiagGroupParents) {
- // If the diagnostic is in a group, and that group has a category, use it.
- if (DefInit *Group = dynamic_cast<DefInit*>(R->getValueInit("Group"))) {
- // Check the diagnostic's diag group for a category.
- std::string CatName = getCategoryFromDiagGroup(Group->getDef(),
- DiagGroupParents);
- if (!CatName.empty()) return CatName;
- }
-
- // If the diagnostic itself has a category, get it.
- return R->getValueAsString("CategoryName");
-}
-
-namespace {
- class DiagCategoryIDMap {
- RecordKeeper &Records;
- StringMap<unsigned> CategoryIDs;
- std::vector<std::string> CategoryStrings;
- public:
- DiagCategoryIDMap(RecordKeeper &records) : Records(records) {
- DiagGroupParentMap ParentInfo(Records);
-
- // The zero'th category is "".
- CategoryStrings.push_back("");
- CategoryIDs[""] = 0;
-
- std::vector<Record*> Diags =
- Records.getAllDerivedDefinitions("Diagnostic");
- for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
- std::string Category = getDiagnosticCategory(Diags[i], ParentInfo);
- if (Category.empty()) continue; // Skip diags with no category.
-
- unsigned &ID = CategoryIDs[Category];
- if (ID != 0) continue; // Already seen.
-
- ID = CategoryStrings.size();
- CategoryStrings.push_back(Category);
- }
- }
-
- unsigned getID(StringRef CategoryString) {
- return CategoryIDs[CategoryString];
- }
-
- typedef std::vector<std::string>::iterator iterator;
- iterator begin() { return CategoryStrings.begin(); }
- iterator end() { return CategoryStrings.end(); }
- };
-} // end anonymous namespace.
-
-
-//===----------------------------------------------------------------------===//
-// Warning Tables (.inc file) generation.
-//===----------------------------------------------------------------------===//
-
-void ClangDiagsDefsEmitter::run(raw_ostream &OS) {
- // Write the #if guard
- if (!Component.empty()) {
- std::string ComponentName = UppercaseString(Component);
- OS << "#ifdef " << ComponentName << "START\n";
- OS << "__" << ComponentName << "START = DIAG_START_" << ComponentName
- << ",\n";
- OS << "#undef " << ComponentName << "START\n";
- OS << "#endif\n\n";
- }
-
- const std::vector<Record*> &Diags =
- Records.getAllDerivedDefinitions("Diagnostic");
-
- DiagCategoryIDMap CategoryIDs(Records);
- DiagGroupParentMap DGParentMap(Records);
-
- for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
- const Record &R = *Diags[i];
- // Filter by component.
- if (!Component.empty() && Component != R.getValueAsString("Component"))
- continue;
-
- OS << "DIAG(" << R.getName() << ", ";
- OS << R.getValueAsDef("Class")->getName();
- OS << ", diag::" << R.getValueAsDef("DefaultMapping")->getName();
-
- // Description string.
- OS << ", \"";
- OS.write_escaped(R.getValueAsString("Text")) << '"';
-
- // Warning associated with the diagnostic.
- if (DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("Group"))) {
- OS << ", \"";
- OS.write_escaped(DI->getDef()->getValueAsString("GroupName")) << '"';
- } else {
- OS << ", \"\"";
- }
-
- // SFINAE bit
- if (R.getValueAsBit("SFINAE"))
- OS << ", true";
- else
- OS << ", false";
-
- // Access control bit
- if (R.getValueAsBit("AccessControl"))
- OS << ", true";
- else
- OS << ", false";
-
- // Category number.
- OS << ", " << CategoryIDs.getID(getDiagnosticCategory(&R, DGParentMap));
-
- // Brief
- OS << ", \"";
- OS.write_escaped(R.getValueAsString("Brief")) << '"';
-
- // Explanation
- OS << ", \"";
- OS.write_escaped(R.getValueAsString("Explanation")) << '"';
- OS << ")\n";
- }
-}
-
-//===----------------------------------------------------------------------===//
-// Warning Group Tables generation
-//===----------------------------------------------------------------------===//
-
-static std::string getDiagCategoryEnum(llvm::StringRef name) {
- if (name.empty())
- return "DiagCat_None";
- llvm::SmallString<256> enumName = llvm::StringRef("DiagCat_");
- for (llvm::StringRef::iterator I = name.begin(), E = name.end(); I != E; ++I)
- enumName += isalnum(*I) ? *I : '_';
- return enumName.str();
-}
-
-namespace {
-struct GroupInfo {
- std::vector<const Record*> DiagsInGroup;
- std::vector<std::string> SubGroups;
- unsigned IDNo;
-};
-} // end anonymous namespace.
-
-void ClangDiagGroupsEmitter::run(raw_ostream &OS) {
- // Compute a mapping from a DiagGroup to all of its parents.
- DiagGroupParentMap DGParentMap(Records);
-
- // Invert the 1-[0/1] mapping of diags to group into a one to many mapping of
- // groups to diags in the group.
- std::map<std::string, GroupInfo> DiagsInGroup;
-
- std::vector<Record*> Diags =
- Records.getAllDerivedDefinitions("Diagnostic");
- for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
- const Record *R = Diags[i];
- DefInit *DI = dynamic_cast<DefInit*>(R->getValueInit("Group"));
- if (DI == 0) continue;
- std::string GroupName = DI->getDef()->getValueAsString("GroupName");
- DiagsInGroup[GroupName].DiagsInGroup.push_back(R);
- }
-
- // Add all DiagGroup's to the DiagsInGroup list to make sure we pick up empty
- // groups (these are warnings that GCC supports that clang never produces).
- std::vector<Record*> DiagGroups
- = Records.getAllDerivedDefinitions("DiagGroup");
- for (unsigned i = 0, e = DiagGroups.size(); i != e; ++i) {
- Record *Group = DiagGroups[i];
- GroupInfo &GI = DiagsInGroup[Group->getValueAsString("GroupName")];
-
- std::vector<Record*> SubGroups = Group->getValueAsListOfDefs("SubGroups");
- for (unsigned j = 0, e = SubGroups.size(); j != e; ++j)
- GI.SubGroups.push_back(SubGroups[j]->getValueAsString("GroupName"));
- }
-
- // Assign unique ID numbers to the groups.
- unsigned IDNo = 0;
- for (std::map<std::string, GroupInfo>::iterator
- I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I, ++IDNo)
- I->second.IDNo = IDNo;
-
- // Walk through the groups emitting an array for each diagnostic of the diags
- // that are mapped to.
- OS << "\n#ifdef GET_DIAG_ARRAYS\n";
- unsigned MaxLen = 0;
- for (std::map<std::string, GroupInfo>::iterator
- I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I) {
- MaxLen = std::max(MaxLen, (unsigned)I->first.size());
-
- std::vector<const Record*> &V = I->second.DiagsInGroup;
- if (!V.empty()) {
- OS << "static const short DiagArray" << I->second.IDNo << "[] = { ";
- for (unsigned i = 0, e = V.size(); i != e; ++i)
- OS << "diag::" << V[i]->getName() << ", ";
- OS << "-1 };\n";
- }
-
- const std::vector<std::string> &SubGroups = I->second.SubGroups;
- if (!SubGroups.empty()) {
- OS << "static const short DiagSubGroup" << I->second.IDNo << "[] = { ";
- for (unsigned i = 0, e = SubGroups.size(); i != e; ++i) {
- std::map<std::string, GroupInfo>::iterator RI =
- DiagsInGroup.find(SubGroups[i]);
- assert(RI != DiagsInGroup.end() && "Referenced without existing?");
- OS << RI->second.IDNo << ", ";
- }
- OS << "-1 };\n";
- }
- }
- OS << "#endif // GET_DIAG_ARRAYS\n\n";
-
- // Emit the table now.
- OS << "\n#ifdef GET_DIAG_TABLE\n";
- for (std::map<std::string, GroupInfo>::iterator
- I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I) {
- // Group option string.
- OS << " { ";
- OS << I->first.size() << ", ";
- OS << "\"";
- OS.write_escaped(I->first) << "\","
- << std::string(MaxLen-I->first.size()+1, ' ');
-
- // Diagnostics in the group.
- if (I->second.DiagsInGroup.empty())
- OS << "0, ";
- else
- OS << "DiagArray" << I->second.IDNo << ", ";
-
- // Subgroups.
- if (I->second.SubGroups.empty())
- OS << 0;
- else
- OS << "DiagSubGroup" << I->second.IDNo;
- OS << " },\n";
- }
- OS << "#endif // GET_DIAG_TABLE\n\n";
-
- // Emit the category table next.
- DiagCategoryIDMap CategoriesByID(Records);
- OS << "\n#ifdef GET_CATEGORY_TABLE\n";
- for (DiagCategoryIDMap::iterator I = CategoriesByID.begin(),
- E = CategoriesByID.end(); I != E; ++I)
- OS << "CATEGORY(\"" << *I << "\", " << getDiagCategoryEnum(*I) << ")\n";
- OS << "#endif // GET_CATEGORY_TABLE\n\n";
-}
-
-//===----------------------------------------------------------------------===//
-// Diagnostic name index generation
-//===----------------------------------------------------------------------===//
-
-namespace {
-struct RecordIndexElement
-{
- RecordIndexElement() {}
- explicit RecordIndexElement(Record const &R):
- Name(R.getName()) {}
-
- std::string Name;
-};
-
-struct RecordIndexElementSorter :
- public std::binary_function<RecordIndexElement, RecordIndexElement, bool> {
-
- bool operator()(RecordIndexElement const &Lhs,
- RecordIndexElement const &Rhs) const {
- return Lhs.Name < Rhs.Name;
- }
-
-};
-
-} // end anonymous namespace.
-
-void ClangDiagsIndexNameEmitter::run(raw_ostream &OS) {
- const std::vector<Record*> &Diags =
- Records.getAllDerivedDefinitions("Diagnostic");
-
- std::vector<RecordIndexElement> Index;
- Index.reserve(Diags.size());
- for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
- const Record &R = *(Diags[i]);
- Index.push_back(RecordIndexElement(R));
- }
-
- std::sort(Index.begin(), Index.end(), RecordIndexElementSorter());
-
- for (unsigned i = 0, e = Index.size(); i != e; ++i) {
- const RecordIndexElement &R = Index[i];
-
- OS << "DIAG_NAME_INDEX(" << R.Name << ")\n";
- }
-}
diff --git a/contrib/llvm/utils/TableGen/ClangDiagnosticsEmitter.h b/contrib/llvm/utils/TableGen/ClangDiagnosticsEmitter.h
deleted file mode 100644
index 1e4c8b7..0000000
--- a/contrib/llvm/utils/TableGen/ClangDiagnosticsEmitter.h
+++ /dev/null
@@ -1,54 +0,0 @@
-//===- ClangDiagnosticsEmitter.h - Generate Clang diagnostics tables -*- C++ -*-
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// These tablegen backends emit Clang diagnostics tables.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef CLANGDIAGS_EMITTER_H
-#define CLANGDIAGS_EMITTER_H
-
-#include "TableGenBackend.h"
-
-namespace llvm {
-
-/// ClangDiagsDefsEmitter - The top-level class emits .def files containing
-/// declarations of Clang diagnostics.
-///
-class ClangDiagsDefsEmitter : public TableGenBackend {
- RecordKeeper &Records;
- const std::string& Component;
-public:
- explicit ClangDiagsDefsEmitter(RecordKeeper &R, const std::string& component)
- : Records(R), Component(component) {}
-
- // run - Output the .def file contents
- void run(raw_ostream &OS);
-};
-
-class ClangDiagGroupsEmitter : public TableGenBackend {
- RecordKeeper &Records;
-public:
- explicit ClangDiagGroupsEmitter(RecordKeeper &R) : Records(R) {}
-
- void run(raw_ostream &OS);
-};
-
-class ClangDiagsIndexNameEmitter : public TableGenBackend {
- RecordKeeper &Records;
-public:
- explicit ClangDiagsIndexNameEmitter(RecordKeeper &R) : Records(R) {}
-
- void run(raw_ostream &OS);
-};
-
-
-} // End llvm namespace
-
-#endif
diff --git a/contrib/llvm/utils/TableGen/ClangSACheckersEmitter.cpp b/contrib/llvm/utils/TableGen/ClangSACheckersEmitter.cpp
deleted file mode 100644
index 97739c6..0000000
--- a/contrib/llvm/utils/TableGen/ClangSACheckersEmitter.cpp
+++ /dev/null
@@ -1,319 +0,0 @@
-//=- ClangSACheckersEmitter.cpp - Generate Clang SA checkers tables -*- C++ -*-
-//
-// 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 Clang Static Analyzer checkers tables.
-//
-//===----------------------------------------------------------------------===//
-
-#include "ClangSACheckersEmitter.h"
-#include "Record.h"
-#include "llvm/ADT/DenseSet.h"
-#include <map>
-#include <string>
-using namespace llvm;
-
-//===----------------------------------------------------------------------===//
-// Static Analyzer Checkers Tables generation
-//===----------------------------------------------------------------------===//
-
-/// \brief True if it is specified hidden or a parent package is specified
-/// as hidden, otherwise false.
-static bool isHidden(const Record &R) {
- if (R.getValueAsBit("Hidden"))
- return true;
- // Not declared as hidden, check the parent package if it is hidden.
- if (DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("ParentPackage")))
- return isHidden(*DI->getDef());
-
- return false;
-}
-
-static bool isCheckerNamed(const Record *R) {
- return !R->getValueAsString("CheckerName").empty();
-}
-
-static std::string getPackageFullName(const Record *R);
-
-static std::string getParentPackageFullName(const Record *R) {
- std::string name;
- if (DefInit *DI = dynamic_cast<DefInit*>(R->getValueInit("ParentPackage")))
- name = getPackageFullName(DI->getDef());
- return name;
-}
-
-static std::string getPackageFullName(const Record *R) {
- std::string name = getParentPackageFullName(R);
- if (!name.empty()) name += ".";
- return name + R->getValueAsString("PackageName");
-}
-
-static std::string getCheckerFullName(const Record *R) {
- std::string name = getParentPackageFullName(R);
- if (isCheckerNamed(R)) {
- if (!name.empty()) name += ".";
- name += R->getValueAsString("CheckerName");
- }
- return name;
-}
-
-static std::string getStringValue(const Record &R, StringRef field) {
- if (StringInit *
- SI = dynamic_cast<StringInit*>(R.getValueInit(field)))
- return SI->getValue();
- return std::string();
-}
-
-namespace {
-struct GroupInfo {
- llvm::DenseSet<const Record*> Checkers;
- llvm::DenseSet<const Record *> SubGroups;
- bool Hidden;
- unsigned Index;
-
- GroupInfo() : Hidden(false) { }
-};
-}
-
-static void addPackageToCheckerGroup(const Record *package, const Record *group,
- llvm::DenseMap<const Record *, GroupInfo *> &recordGroupMap) {
- llvm::DenseSet<const Record *> &checkers = recordGroupMap[package]->Checkers;
- for (llvm::DenseSet<const Record *>::iterator
- I = checkers.begin(), E = checkers.end(); I != E; ++I)
- recordGroupMap[group]->Checkers.insert(*I);
-
- llvm::DenseSet<const Record *> &subGroups = recordGroupMap[package]->SubGroups;
- for (llvm::DenseSet<const Record *>::iterator
- I = subGroups.begin(), E = subGroups.end(); I != E; ++I)
- addPackageToCheckerGroup(*I, group, recordGroupMap);
-}
-
-void ClangSACheckersEmitter::run(raw_ostream &OS) {
- std::vector<Record*> checkers = Records.getAllDerivedDefinitions("Checker");
- llvm::DenseMap<const Record *, unsigned> checkerRecIndexMap;
- for (unsigned i = 0, e = checkers.size(); i != e; ++i)
- checkerRecIndexMap[checkers[i]] = i;
-
- // Invert the mapping of checkers to package/group into a one to many
- // mapping of packages/groups to checkers.
- std::map<std::string, GroupInfo> groupInfoByName;
- llvm::DenseMap<const Record *, GroupInfo *> recordGroupMap;
-
- std::vector<Record*> packages = Records.getAllDerivedDefinitions("Package");
- for (unsigned i = 0, e = packages.size(); i != e; ++i) {
- Record *R = packages[i];
- std::string fullName = getPackageFullName(R);
- if (!fullName.empty()) {
- GroupInfo &info = groupInfoByName[fullName];
- info.Hidden = isHidden(*R);
- recordGroupMap[R] = &info;
- }
- }
-
- std::vector<Record*>
- checkerGroups = Records.getAllDerivedDefinitions("CheckerGroup");
- for (unsigned i = 0, e = checkerGroups.size(); i != e; ++i) {
- Record *R = checkerGroups[i];
- std::string name = R->getValueAsString("GroupName");
- if (!name.empty()) {
- GroupInfo &info = groupInfoByName[name];
- recordGroupMap[R] = &info;
- }
- }
-
- for (unsigned i = 0, e = checkers.size(); i != e; ++i) {
- Record *R = checkers[i];
- Record *package = 0;
- if (DefInit *
- DI = dynamic_cast<DefInit*>(R->getValueInit("ParentPackage")))
- package = DI->getDef();
- if (!isCheckerNamed(R) && !package)
- throw "Checker '" + R->getName() + "' is neither named, nor in a package!";
-
- if (isCheckerNamed(R)) {
- // Create a pseudo-group to hold this checker.
- std::string fullName = getCheckerFullName(R);
- GroupInfo &info = groupInfoByName[fullName];
- info.Hidden = R->getValueAsBit("Hidden");
- recordGroupMap[R] = &info;
- info.Checkers.insert(R);
- } else {
- recordGroupMap[package]->Checkers.insert(R);
- }
-
- Record *currR = isCheckerNamed(R) ? R : package;
- // Insert the checker and its parent packages into the subgroups set of
- // the corresponding parent package.
- while (DefInit *DI
- = dynamic_cast<DefInit*>(currR->getValueInit("ParentPackage"))) {
- Record *parentPackage = DI->getDef();
- recordGroupMap[parentPackage]->SubGroups.insert(currR);
- currR = parentPackage;
- }
- // Insert the checker into the set of its group.
- if (DefInit *DI = dynamic_cast<DefInit*>(R->getValueInit("Group")))
- recordGroupMap[DI->getDef()]->Checkers.insert(R);
- }
-
- // If a package is in group, add all its checkers and its sub-packages
- // checkers into the group.
- for (unsigned i = 0, e = packages.size(); i != e; ++i)
- if (DefInit *DI = dynamic_cast<DefInit*>(packages[i]->getValueInit("Group")))
- addPackageToCheckerGroup(packages[i], DI->getDef(), recordGroupMap);
-
- typedef std::map<std::string, const Record *> SortedRecords;
- typedef llvm::DenseMap<const Record *, unsigned> RecToSortIndex;
-
- SortedRecords sortedGroups;
- RecToSortIndex groupToSortIndex;
- OS << "\n#ifdef GET_GROUPS\n";
- {
- for (unsigned i = 0, e = checkerGroups.size(); i != e; ++i)
- sortedGroups[checkerGroups[i]->getValueAsString("GroupName")]
- = checkerGroups[i];
-
- unsigned sortIndex = 0;
- for (SortedRecords::iterator
- I = sortedGroups.begin(), E = sortedGroups.end(); I != E; ++I) {
- const Record *R = I->second;
-
- OS << "GROUP(" << "\"";
- OS.write_escaped(R->getValueAsString("GroupName")) << "\"";
- OS << ")\n";
-
- groupToSortIndex[R] = sortIndex++;
- }
- }
- OS << "#endif // GET_GROUPS\n\n";
-
- OS << "\n#ifdef GET_PACKAGES\n";
- {
- SortedRecords sortedPackages;
- for (unsigned i = 0, e = packages.size(); i != e; ++i)
- sortedPackages[getPackageFullName(packages[i])] = packages[i];
-
- for (SortedRecords::iterator
- I = sortedPackages.begin(), E = sortedPackages.end(); I != E; ++I) {
- const Record &R = *I->second;
-
- OS << "PACKAGE(" << "\"";
- OS.write_escaped(getPackageFullName(&R)) << "\", ";
- // Group index
- if (DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("Group")))
- OS << groupToSortIndex[DI->getDef()] << ", ";
- else
- OS << "-1, ";
- // Hidden bit
- if (isHidden(R))
- OS << "true";
- else
- OS << "false";
- OS << ")\n";
- }
- }
- OS << "#endif // GET_PACKAGES\n\n";
-
- OS << "\n#ifdef GET_CHECKERS\n";
- for (unsigned i = 0, e = checkers.size(); i != e; ++i) {
- const Record &R = *checkers[i];
-
- OS << "CHECKER(" << "\"";
- std::string name;
- if (isCheckerNamed(&R))
- name = getCheckerFullName(&R);
- OS.write_escaped(name) << "\", ";
- OS << R.getName() << ", ";
- OS << getStringValue(R, "DescFile") << ", ";
- OS << "\"";
- OS.write_escaped(getStringValue(R, "HelpText")) << "\", ";
- // Group index
- if (DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("Group")))
- OS << groupToSortIndex[DI->getDef()] << ", ";
- else
- OS << "-1, ";
- // Hidden bit
- if (isHidden(R))
- OS << "true";
- else
- OS << "false";
- OS << ")\n";
- }
- OS << "#endif // GET_CHECKERS\n\n";
-
- unsigned index = 0;
- for (std::map<std::string, GroupInfo>::iterator
- I = groupInfoByName.begin(), E = groupInfoByName.end(); I != E; ++I)
- I->second.Index = index++;
-
- // Walk through the packages/groups/checkers emitting an array for each
- // set of checkers and an array for each set of subpackages.
-
- OS << "\n#ifdef GET_MEMBER_ARRAYS\n";
- unsigned maxLen = 0;
- for (std::map<std::string, GroupInfo>::iterator
- I = groupInfoByName.begin(), E = groupInfoByName.end(); I != E; ++I) {
- maxLen = std::max(maxLen, (unsigned)I->first.size());
-
- llvm::DenseSet<const Record *> &checkers = I->second.Checkers;
- if (!checkers.empty()) {
- OS << "static const short CheckerArray" << I->second.Index << "[] = { ";
- // Make the output order deterministic.
- std::map<int, const Record *> sorted;
- for (llvm::DenseSet<const Record *>::iterator
- I = checkers.begin(), E = checkers.end(); I != E; ++I)
- sorted[(*I)->getID()] = *I;
-
- for (std::map<int, const Record *>::iterator
- I = sorted.begin(), E = sorted.end(); I != E; ++I)
- OS << checkerRecIndexMap[I->second] << ", ";
- OS << "-1 };\n";
- }
-
- llvm::DenseSet<const Record *> &subGroups = I->second.SubGroups;
- if (!subGroups.empty()) {
- OS << "static const short SubPackageArray" << I->second.Index << "[] = { ";
- // Make the output order deterministic.
- std::map<int, const Record *> sorted;
- for (llvm::DenseSet<const Record *>::iterator
- I = subGroups.begin(), E = subGroups.end(); I != E; ++I)
- sorted[(*I)->getID()] = *I;
-
- for (std::map<int, const Record *>::iterator
- I = sorted.begin(), E = sorted.end(); I != E; ++I) {
- OS << recordGroupMap[I->second]->Index << ", ";
- }
- OS << "-1 };\n";
- }
- }
- OS << "#endif // GET_MEMBER_ARRAYS\n\n";
-
- OS << "\n#ifdef GET_CHECKNAME_TABLE\n";
- for (std::map<std::string, GroupInfo>::iterator
- I = groupInfoByName.begin(), E = groupInfoByName.end(); I != E; ++I) {
- // Group option string.
- OS << " { \"";
- OS.write_escaped(I->first) << "\","
- << std::string(maxLen-I->first.size()+1, ' ');
-
- if (I->second.Checkers.empty())
- OS << "0, ";
- else
- OS << "CheckerArray" << I->second.Index << ", ";
-
- // Subgroups.
- if (I->second.SubGroups.empty())
- OS << "0, ";
- else
- OS << "SubPackageArray" << I->second.Index << ", ";
-
- OS << (I->second.Hidden ? "true" : "false");
-
- OS << " },\n";
- }
- OS << "#endif // GET_CHECKNAME_TABLE\n\n";
-}
diff --git a/contrib/llvm/utils/TableGen/ClangSACheckersEmitter.h b/contrib/llvm/utils/TableGen/ClangSACheckersEmitter.h
deleted file mode 100644
index 6bd1635..0000000
--- a/contrib/llvm/utils/TableGen/ClangSACheckersEmitter.h
+++ /dev/null
@@ -1,31 +0,0 @@
-//===- ClangSACheckersEmitter.h - Generate Clang SA checkers tables -*- C++ -*-
-//
-// 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 Clang Static Analyzer checkers tables.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef CLANGSACHECKERS_EMITTER_H
-#define CLANGSACHECKERS_EMITTER_H
-
-#include "TableGenBackend.h"
-
-namespace llvm {
-
-class ClangSACheckersEmitter : public TableGenBackend {
- RecordKeeper &Records;
-public:
- explicit ClangSACheckersEmitter(RecordKeeper &R) : Records(R) {}
-
- void run(raw_ostream &OS);
-};
-
-} // End llvm namespace
-
-#endif
diff --git a/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp b/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp
index d828dfc..c5a1526 100644
--- a/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp
+++ b/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp
@@ -15,7 +15,7 @@
#include "CodeEmitterGen.h"
#include "CodeGenTarget.h"
-#include "Record.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
@@ -41,19 +41,23 @@ void CodeEmitterGen::reverseBits(std::vector<Record*> &Insts) {
BitsInit *BI = R->getValueAsBitsInit("Inst");
unsigned numBits = BI->getNumBits();
- BitsInit *NewBI = new BitsInit(numBits);
+
+ SmallVector<Init *, 16> NewBits(numBits);
+
for (unsigned bit = 0, end = numBits / 2; bit != end; ++bit) {
unsigned bitSwapIdx = numBits - bit - 1;
Init *OrigBit = BI->getBit(bit);
Init *BitSwap = BI->getBit(bitSwapIdx);
- NewBI->setBit(bit, BitSwap);
- NewBI->setBit(bitSwapIdx, OrigBit);
+ NewBits[bit] = BitSwap;
+ NewBits[bitSwapIdx] = OrigBit;
}
if (numBits % 2) {
unsigned middle = (numBits + 1) / 2;
- NewBI->setBit(middle, BI->getBit(middle));
+ NewBits[middle] = BI->getBit(middle);
}
+ BitsInit *NewBI = BitsInit::get(NewBits);
+
// Update the bits in reversed order so that emitInstrOpBits will get the
// correct endianness.
R->getValue("Inst")->setValue(NewBI);
diff --git a/contrib/llvm/utils/TableGen/CodeEmitterGen.h b/contrib/llvm/utils/TableGen/CodeEmitterGen.h
index a874d97..7f6ee2a 100644
--- a/contrib/llvm/utils/TableGen/CodeEmitterGen.h
+++ b/contrib/llvm/utils/TableGen/CodeEmitterGen.h
@@ -14,7 +14,7 @@
#ifndef CODEMITTERGEN_H
#define CODEMITTERGEN_H
-#include "TableGenBackend.h"
+#include "llvm/TableGen/TableGenBackend.h"
#include <vector>
#include <string>
diff --git a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp
index 072893f..dbf1662 100644
--- a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp
+++ b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp
@@ -13,8 +13,8 @@
//===----------------------------------------------------------------------===//
#include "CodeGenDAGPatterns.h"
-#include "Error.h"
-#include "Record.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Debug.h"
@@ -1747,9 +1747,10 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){
// TreePatternNode of its own. For example:
/// (foo GPR, imm) -> (foo GPR, (imm))
if (R->isSubClassOf("SDNode") || R->isSubClassOf("PatFrag"))
- return ParseTreePattern(new DagInit(DI, "",
- std::vector<std::pair<Init*, std::string> >()),
- OpName);
+ return ParseTreePattern(
+ DagInit::get(DI, "",
+ std::vector<std::pair<Init*, std::string> >()),
+ OpName);
// Input argument?
TreePatternNode *Res = new TreePatternNode(DI, 1);
@@ -1771,7 +1772,7 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){
if (BitsInit *BI = dynamic_cast<BitsInit*>(TheInit)) {
// Turn this into an IntInit.
- Init *II = BI->convertInitializerTo(new IntRecTy());
+ Init *II = BI->convertInitializerTo(IntRecTy::get());
if (II == 0 || !dynamic_cast<IntInit*>(II))
error("Bits value must be constants!");
return ParseTreePattern(II, OpName);
@@ -1860,7 +1861,7 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){
else // Otherwise, no chain.
Operator = getDAGPatterns().get_intrinsic_wo_chain_sdnode();
- TreePatternNode *IIDNode = new TreePatternNode(new IntInit(IID), 1);
+ TreePatternNode *IIDNode = new TreePatternNode(IntInit::get(IID), 1);
Children.insert(Children.begin(), IIDNode);
}
@@ -2180,7 +2181,7 @@ void CodeGenDAGPatterns::ParseDefaultOperands() {
// Find some SDNode.
assert(!SDNodes.empty() && "No SDNodes parsed?");
- Init *SomeSDNode = new DefInit(SDNodes.begin()->first);
+ 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) {
@@ -2192,7 +2193,7 @@ void CodeGenDAGPatterns::ParseDefaultOperands() {
for (unsigned op = 0, e = DefaultInfo->getNumArgs(); op != e; ++op)
Ops.push_back(std::make_pair(DefaultInfo->getArg(op),
DefaultInfo->getArgName(op)));
- DagInit *DI = new DagInit(SomeSDNode, "", Ops);
+ DagInit *DI = DagInit::get(SomeSDNode, "", Ops);
// Create a TreePattern to parse this.
TreePattern P(DefaultOps[iter][i], DI, false, *this);
@@ -2828,6 +2829,12 @@ void CodeGenDAGPatterns::InferInstructionFlags() {
InstInfo.isBitcast = IsBitcast;
InstInfo.hasSideEffects = HasSideEffects;
InstInfo.Operands.isVariadic = IsVariadic;
+
+ // Sanity checks.
+ if (InstInfo.isReMaterializable && InstInfo.hasSideEffects)
+ throw TGError(InstInfo.TheDef->getLoc(), "The instruction " +
+ InstInfo.TheDef->getName() +
+ " is rematerializable AND has unmodeled side effects?");
}
}
diff --git a/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp b/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp
index a52ce86..53d499f 100644
--- a/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp
+++ b/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp
@@ -13,8 +13,8 @@
#include "CodeGenInstruction.h"
#include "CodeGenTarget.h"
-#include "Error.h"
-#include "Record.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/STLExtras.h"
@@ -267,8 +267,9 @@ static void ParseConstraints(const std::string &CStr, CGIOperandList &Ops) {
void CGIOperandList::ProcessDisableEncoding(std::string DisableEncoding) {
while (1) {
- std::string OpName;
- tie(OpName, DisableEncoding) = getToken(DisableEncoding, " ,\t");
+ std::pair<StringRef, StringRef> P = getToken(DisableEncoding, " ,\t");
+ std::string OpName = P.first;
+ DisableEncoding = P.second;
if (OpName.empty()) break;
// Figure out which operand this is.
@@ -308,6 +309,7 @@ CodeGenInstruction::CodeGenInstruction(Record *R) : TheDef(R), Operands(R) {
isReMaterializable = R->getValueAsBit("isReMaterializable");
hasDelaySlot = R->getValueAsBit("hasDelaySlot");
usesCustomInserter = R->getValueAsBit("usesCustomInserter");
+ hasPostISelHook = R->getValueAsBit("hasPostISelHook");
hasCtrlDep = R->getValueAsBit("hasCtrlDep");
isNotDuplicable = R->getValueAsBit("isNotDuplicable");
hasSideEffects = R->getValueAsBit("hasSideEffects");
@@ -423,6 +425,13 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo,
// Handle explicit registers.
if (ADI && ADI->getDef()->isSubClassOf("Register")) {
+ if (InstOpRec->isSubClassOf("OptionalDefOperand")) {
+ DagInit *DI = InstOpRec->getValueAsDag("MIOperandInfo");
+ // The operand info should only have a single (register) entry. We
+ // want the register class of it.
+ InstOpRec = dynamic_cast<DefInit*>(DI->getArg(0))->getDef();
+ }
+
if (InstOpRec->isSubClassOf("RegisterOperand"))
InstOpRec = InstOpRec->getValueAsDef("RegClass");
@@ -431,8 +440,8 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo,
if (!T.getRegisterClass(InstOpRec)
.contains(T.getRegBank().getReg(ADI->getDef())))
- throw TGError(Loc, "fixed register " +ADI->getDef()->getName()
- + " is not a member of the " + InstOpRec->getName() +
+ throw TGError(Loc, "fixed register " + ADI->getDef()->getName() +
+ " is not a member of the " + InstOpRec->getName() +
" register class!");
if (!Result->getArgName(AliasOpNo).empty())
diff --git a/contrib/llvm/utils/TableGen/CodeGenInstruction.h b/contrib/llvm/utils/TableGen/CodeGenInstruction.h
index 8d7669a..468277a 100644
--- a/contrib/llvm/utils/TableGen/CodeGenInstruction.h
+++ b/contrib/llvm/utils/TableGen/CodeGenInstruction.h
@@ -233,6 +233,7 @@ namespace llvm {
bool isReMaterializable;
bool hasDelaySlot;
bool usesCustomInserter;
+ bool hasPostISelHook;
bool hasCtrlDep;
bool isNotDuplicable;
bool hasSideEffects;
diff --git a/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp b/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp
index 1acf3a8..8de4615 100644
--- a/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp
+++ b/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp
@@ -14,8 +14,9 @@
#include "CodeGenRegisters.h"
#include "CodeGenTarget.h"
-#include "Error.h"
+#include "llvm/TableGen/Error.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
using namespace llvm;
@@ -182,8 +183,8 @@ struct TupleExpander : SetTheory::Expander {
// Precompute some types.
Record *RegisterCl = Def->getRecords().getClass("Register");
- RecTy *RegisterRecTy = new RecordRecTy(RegisterCl);
- StringInit *BlankName = new StringInit("");
+ RecTy *RegisterRecTy = RecordRecTy::get(RegisterCl);
+ StringInit *BlankName = StringInit::get("");
// Zip them up.
for (unsigned n = 0; n != Length; ++n) {
@@ -195,7 +196,7 @@ struct TupleExpander : SetTheory::Expander {
Record *Reg = Lists[i][n];
if (i) Name += '_';
Name += Reg->getName();
- Tuple.push_back(new DefInit(Reg));
+ Tuple.push_back(DefInit::get(Reg));
CostPerUse = std::max(CostPerUse,
unsigned(Reg->getValueAsInt("CostPerUse")));
}
@@ -216,7 +217,7 @@ struct TupleExpander : SetTheory::Expander {
// Replace the sub-register list with Tuple.
if (RV.getName() == "SubRegs")
- RV.setValue(new ListInit(Tuple, RegisterRecTy));
+ RV.setValue(ListInit::get(Tuple, RegisterRecTy));
// Provide a blank AsmName. MC hacks are required anyway.
if (RV.getName() == "AsmName")
@@ -224,7 +225,7 @@ struct TupleExpander : SetTheory::Expander {
// CostPerUse is aggregated from all Tuple members.
if (RV.getName() == "CostPerUse")
- RV.setValue(new IntInit(CostPerUse));
+ RV.setValue(IntInit::get(CostPerUse));
// Copy fields from the RegisterTuples def.
if (RV.getName() == "SubRegIndices" ||
@@ -255,7 +256,7 @@ struct TupleExpander : SetTheory::Expander {
//===----------------------------------------------------------------------===//
CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R)
- : TheDef(R) {
+ : TheDef(R), Name(R->getName()), EnumValue(-1) {
// Rename anonymous register classes.
if (R->getName().size() > 9 && R->getName()[9] == '.') {
static unsigned AnonCounter = 0;
@@ -272,18 +273,22 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R)
}
assert(!VTs.empty() && "RegisterClass must contain at least one ValueType!");
+ // Allocation order 0 is the full set. AltOrders provides others.
+ const SetTheory::RecVec *Elements = RegBank.getSets().expand(R);
+ ListInit *AltOrders = R->getValueAsListInit("AltOrders");
+ Orders.resize(1 + AltOrders->size());
+
// Default allocation order always contains all registers.
- Elements = RegBank.getSets().expand(R);
- for (unsigned i = 0, e = Elements->size(); i != e; ++i)
+ for (unsigned i = 0, e = Elements->size(); i != e; ++i) {
+ Orders[0].push_back((*Elements)[i]);
Members.insert(RegBank.getReg((*Elements)[i]));
+ }
// Alternative allocation orders may be subsets.
- ListInit *Alts = R->getValueAsListInit("AltOrders");
- AltOrders.resize(Alts->size());
SetTheory::RecSet Order;
- for (unsigned i = 0, e = Alts->size(); i != e; ++i) {
- RegBank.getSets().evaluate(Alts->getElement(i), Order);
- AltOrders[i].append(Order.begin(), Order.end());
+ for (unsigned i = 0, e = AltOrders->size(); i != e; ++i) {
+ RegBank.getSets().evaluate(AltOrders->getElement(i), Order);
+ Orders[1 + i].append(Order.begin(), Order.end());
// Verify that all altorder members are regclass members.
while (!Order.empty()) {
CodeGenRegister *Reg = RegBank.getReg(Order.back());
@@ -328,10 +333,71 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R)
AltOrderSelect = R->getValueAsCode("AltOrderSelect");
}
+// Create an inferred register class that was missing from the .td files.
+// Most properties will be inherited from the closest super-class after the
+// class structure has been computed.
+CodeGenRegisterClass::CodeGenRegisterClass(StringRef Name, Key Props)
+ : Members(*Props.Members),
+ TheDef(0),
+ Name(Name),
+ EnumValue(-1),
+ SpillSize(Props.SpillSize),
+ SpillAlignment(Props.SpillAlignment),
+ CopyCost(0),
+ Allocatable(true) {
+}
+
+// Compute inherited propertied for a synthesized register class.
+void CodeGenRegisterClass::inheritProperties(CodeGenRegBank &RegBank) {
+ assert(!getDef() && "Only synthesized classes can inherit properties");
+ assert(!SuperClasses.empty() && "Synthesized class without super class");
+
+ // The last super-class is the smallest one.
+ CodeGenRegisterClass &Super = *SuperClasses.back();
+
+ // Most properties are copied directly.
+ // Exceptions are members, size, and alignment
+ Namespace = Super.Namespace;
+ VTs = Super.VTs;
+ CopyCost = Super.CopyCost;
+ Allocatable = Super.Allocatable;
+ AltOrderSelect = Super.AltOrderSelect;
+
+ // Copy all allocation orders, filter out foreign registers from the larger
+ // super-class.
+ Orders.resize(Super.Orders.size());
+ for (unsigned i = 0, ie = Super.Orders.size(); i != ie; ++i)
+ for (unsigned j = 0, je = Super.Orders[i].size(); j != je; ++j)
+ if (contains(RegBank.getReg(Super.Orders[i][j])))
+ Orders[i].push_back(Super.Orders[i][j]);
+}
+
bool CodeGenRegisterClass::contains(const CodeGenRegister *Reg) const {
return Members.count(Reg);
}
+namespace llvm {
+ raw_ostream &operator<<(raw_ostream &OS, const CodeGenRegisterClass::Key &K) {
+ OS << "{ S=" << K.SpillSize << ", A=" << K.SpillAlignment;
+ for (CodeGenRegister::Set::const_iterator I = K.Members->begin(),
+ E = K.Members->end(); I != E; ++I)
+ OS << ", " << (*I)->getName();
+ return OS << " }";
+ }
+}
+
+// This is a simple lexicographical order that can be used to search for sets.
+// It is not the same as the topological order provided by TopoOrderRC.
+bool CodeGenRegisterClass::Key::
+operator<(const CodeGenRegisterClass::Key &B) const {
+ assert(Members && B.Members);
+ if (*Members != *B.Members)
+ return *Members < *B.Members;
+ if (SpillSize != B.SpillSize)
+ return SpillSize < B.SpillSize;
+ return SpillAlignment < B.SpillAlignment;
+}
+
// Returns true if RC is a strict subclass.
// RC is a sub-class of this class if it is a valid replacement for any
// instruction operand where a register of this classis required. It must
@@ -341,16 +407,101 @@ bool CodeGenRegisterClass::contains(const CodeGenRegister *Reg) const {
// 2. The RC spill size must not be smaller than our spill size.
// 3. RC spill alignment must be compatible with ours.
//
-bool CodeGenRegisterClass::hasSubClass(const CodeGenRegisterClass *RC) const {
- return SpillAlignment && RC->SpillAlignment % SpillAlignment == 0 &&
- SpillSize <= RC->SpillSize &&
- std::includes(Members.begin(), Members.end(),
- RC->Members.begin(), RC->Members.end(),
+static bool testSubClass(const CodeGenRegisterClass *A,
+ const CodeGenRegisterClass *B) {
+ return A->SpillAlignment && B->SpillAlignment % A->SpillAlignment == 0 &&
+ A->SpillSize <= B->SpillSize &&
+ std::includes(A->getMembers().begin(), A->getMembers().end(),
+ B->getMembers().begin(), B->getMembers().end(),
CodeGenRegister::Less());
}
-const std::string &CodeGenRegisterClass::getName() const {
- return TheDef->getName();
+/// Sorting predicate for register classes. This provides a topological
+/// ordering that arranges all register classes before their sub-classes.
+///
+/// Register classes with the same registers, spill size, and alignment form a
+/// clique. They will be ordered alphabetically.
+///
+static int TopoOrderRC(const void *PA, const void *PB) {
+ const CodeGenRegisterClass *A = *(const CodeGenRegisterClass* const*)PA;
+ const CodeGenRegisterClass *B = *(const CodeGenRegisterClass* const*)PB;
+ if (A == B)
+ return 0;
+
+ // Order by descending set size. Note that the classes' allocation order may
+ // not have been computed yet. The Members set is always vaild.
+ if (A->getMembers().size() > B->getMembers().size())
+ return -1;
+ if (A->getMembers().size() < B->getMembers().size())
+ return 1;
+
+ // Order by ascending spill size.
+ if (A->SpillSize < B->SpillSize)
+ return -1;
+ if (A->SpillSize > B->SpillSize)
+ return 1;
+
+ // Order by ascending spill alignment.
+ if (A->SpillAlignment < B->SpillAlignment)
+ return -1;
+ if (A->SpillAlignment > B->SpillAlignment)
+ return 1;
+
+ // Finally order by name as a tie breaker.
+ return A->getName() < B->getName();
+}
+
+std::string CodeGenRegisterClass::getQualifiedName() const {
+ if (Namespace.empty())
+ return getName();
+ else
+ return Namespace + "::" + getName();
+}
+
+// Compute sub-classes of all register classes.
+// Assume the classes are ordered topologically.
+void CodeGenRegisterClass::computeSubClasses(CodeGenRegBank &RegBank) {
+ ArrayRef<CodeGenRegisterClass*> RegClasses = RegBank.getRegClasses();
+
+ // Visit backwards so sub-classes are seen first.
+ for (unsigned rci = RegClasses.size(); rci; --rci) {
+ CodeGenRegisterClass &RC = *RegClasses[rci - 1];
+ RC.SubClasses.resize(RegClasses.size());
+ RC.SubClasses.set(RC.EnumValue);
+
+ // Normally, all subclasses have IDs >= rci, unless RC is part of a clique.
+ for (unsigned s = rci; s != RegClasses.size(); ++s) {
+ if (RC.SubClasses.test(s))
+ continue;
+ CodeGenRegisterClass *SubRC = RegClasses[s];
+ if (!testSubClass(&RC, SubRC))
+ continue;
+ // SubRC is a sub-class. Grap all its sub-classes so we won't have to
+ // check them again.
+ RC.SubClasses |= SubRC->SubClasses;
+ }
+
+ // Sweep up missed clique members. They will be immediately preceeding RC.
+ for (unsigned s = rci - 1; s && testSubClass(&RC, RegClasses[s - 1]); --s)
+ RC.SubClasses.set(s - 1);
+ }
+
+ // Compute the SuperClasses lists from the SubClasses vectors.
+ for (unsigned rci = 0; rci != RegClasses.size(); ++rci) {
+ const BitVector &SC = RegClasses[rci]->getSubClasses();
+ for (int s = SC.find_first(); s >= 0; s = SC.find_next(s)) {
+ if (unsigned(s) == rci)
+ continue;
+ RegClasses[s]->SuperClasses.push_back(RegClasses[rci]);
+ }
+ }
+
+ // With the class hierarchy in place, let synthesized register classes inherit
+ // properties from their closest super-class. The iteration order here can
+ // propagate properties down multiple levels.
+ for (unsigned rci = 0; rci != RegClasses.size(); ++rci)
+ if (!RegClasses[rci]->getDef())
+ RegClasses[rci]->inheritProperties(RegBank);
}
//===----------------------------------------------------------------------===//
@@ -385,14 +536,29 @@ CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records) : Records(Records) {
getReg((*TupRegs)[j]);
}
+ // Precompute all sub-register maps now all the registers are known.
+ // This will create Composite entries for all inferred sub-register indices.
+ for (unsigned i = 0, e = Registers.size(); i != e; ++i)
+ Registers[i]->getSubRegs(*this);
+
// Read in register class definitions.
std::vector<Record*> RCs = Records.getAllDerivedDefinitions("RegisterClass");
if (RCs.empty())
throw std::string("No 'RegisterClass' subclasses defined!");
+ // Allocate user-defined register classes.
RegClasses.reserve(RCs.size());
for (unsigned i = 0, e = RCs.size(); i != e; ++i)
- RegClasses.push_back(CodeGenRegisterClass(*this, RCs[i]));
+ addToMaps(new CodeGenRegisterClass(*this, RCs[i]));
+
+ // Infer missing classes to create a full algebra.
+ computeInferredRegisterClasses();
+
+ // Order register classes topologically and assign enum values.
+ array_pod_sort(RegClasses.begin(), RegClasses.end(), TopoOrderRC);
+ for (unsigned i = 0, e = RegClasses.size(); i != e; ++i)
+ RegClasses[i]->EnumValue = i;
+ CodeGenRegisterClass::computeSubClasses(*this);
}
CodeGenRegister *CodeGenRegBank::getReg(Record *Def) {
@@ -404,11 +570,19 @@ CodeGenRegister *CodeGenRegBank::getReg(Record *Def) {
return Reg;
}
-CodeGenRegisterClass *CodeGenRegBank::getRegClass(Record *Def) {
- if (Def2RC.empty())
- for (unsigned i = 0, e = RegClasses.size(); i != e; ++i)
- Def2RC[RegClasses[i].TheDef] = &RegClasses[i];
+void CodeGenRegBank::addToMaps(CodeGenRegisterClass *RC) {
+ RegClasses.push_back(RC);
+ if (Record *Def = RC->getDef())
+ Def2RC.insert(std::make_pair(Def, RC));
+
+ // Duplicate classes are rejected by insert().
+ // That's OK, we only care about the properties handled by CGRC::Key.
+ CodeGenRegisterClass::Key K(*RC);
+ Key2RC.insert(std::make_pair(K, RC));
+}
+
+CodeGenRegisterClass *CodeGenRegBank::getRegClass(Record *Def) {
if (CodeGenRegisterClass *RC = Def2RC[Def])
return RC;
@@ -425,7 +599,6 @@ Record *CodeGenRegBank::getCompositeSubRegIndex(Record *A, Record *B,
// None exists, synthesize one.
std::string Name = A->getName() + "_then_" + B->getName();
Comp = new Record(Name, SMLoc(), Records);
- Records.addDef(Comp);
SubRegIndices.push_back(Comp);
return Comp;
}
@@ -438,11 +611,6 @@ unsigned CodeGenRegBank::getSubRegIndexNo(Record *idx) {
}
void CodeGenRegBank::computeComposites() {
- // Precompute all sub-register maps. This will create Composite entries for
- // all inferred sub-register indices.
- for (unsigned i = 0, e = Registers.size(); i != e; ++i)
- Registers[i]->getSubRegs(*this);
-
for (unsigned i = 0, e = Registers.size(); i != e; ++i) {
CodeGenRegister *Reg1 = Registers[i];
const CodeGenRegister::SubRegMap &SRM1 = Reg1->getSubRegs();
@@ -571,6 +739,64 @@ void CodeGenRegBank::computeDerivedInfo() {
computeComposites();
}
+// Infer missing register classes.
+//
+// For every register class RC, make sure that the set of registers in RC with
+// a given SubIxx sub-register form a register class.
+void CodeGenRegBank::computeInferredRegisterClasses() {
+ // When this function is called, the register classes have not been sorted
+ // and assigned EnumValues yet. That means getSubClasses(),
+ // getSuperClasses(), and hasSubClass() functions are defunct.
+
+ // Map SubRegIndex to register set.
+ typedef std::map<Record*, CodeGenRegister::Set, LessRecord> SubReg2SetMap;
+
+ // Visit all register classes, including the ones being added by the loop.
+ for (unsigned rci = 0; rci != RegClasses.size(); ++rci) {
+ CodeGenRegisterClass &RC = *RegClasses[rci];
+
+ // Compute the set of registers supporting each SubRegIndex.
+ SubReg2SetMap SRSets;
+ for (CodeGenRegister::Set::const_iterator RI = RC.getMembers().begin(),
+ RE = RC.getMembers().end(); RI != RE; ++RI) {
+ const CodeGenRegister::SubRegMap &SRM = (*RI)->getSubRegs();
+ for (CodeGenRegister::SubRegMap::const_iterator I = SRM.begin(),
+ E = SRM.end(); I != E; ++I)
+ SRSets[I->first].insert(*RI);
+ }
+
+ // Find matching classes for all SRSets entries. Iterate in SubRegIndex
+ // numerical order to visit synthetic indices last.
+ for (unsigned sri = 0, sre = SubRegIndices.size(); sri != sre; ++sri) {
+ Record *SubIdx = SubRegIndices[sri];
+ SubReg2SetMap::const_iterator I = SRSets.find(SubIdx);
+ // Unsupported SubRegIndex. Skip it.
+ if (I == SRSets.end())
+ continue;
+ // In most cases, all RC registers support the SubRegIndex.
+ if (I->second.size() == RC.getMembers().size()) {
+ RC.setSubClassWithSubReg(SubIdx, &RC);
+ continue;
+ }
+
+ // This is a real subset. See if we have a matching class.
+ CodeGenRegisterClass::Key K(&I->second, RC.SpillSize, RC.SpillAlignment);
+ RCKeyMap::const_iterator FoundI = Key2RC.find(K);
+ if (FoundI != Key2RC.end()) {
+ RC.setSubClassWithSubReg(SubIdx, FoundI->second);
+ continue;
+ }
+
+ // Class doesn't exist.
+ CodeGenRegisterClass *NewRC =
+ new CodeGenRegisterClass(RC.getName() + "_with_" +
+ I->first->getName(), K);
+ addToMaps(NewRC);
+ RC.setSubClassWithSubReg(SubIdx, NewRC);
+ }
+ }
+}
+
/// getRegisterClassForRegister - Find the register class that contains the
/// specified physical register. If the register is not in a register class,
/// return null. If the register is in multiple classes, and the classes have a
@@ -579,10 +805,10 @@ void CodeGenRegBank::computeDerivedInfo() {
const CodeGenRegisterClass*
CodeGenRegBank::getRegClassForRegister(Record *R) {
const CodeGenRegister *Reg = getReg(R);
- const std::vector<CodeGenRegisterClass> &RCs = getRegClasses();
+ ArrayRef<CodeGenRegisterClass*> RCs = getRegClasses();
const CodeGenRegisterClass *FoundRC = 0;
for (unsigned i = 0, e = RCs.size(); i != e; ++i) {
- const CodeGenRegisterClass &RC = RCs[i];
+ const CodeGenRegisterClass &RC = *RCs[i];
if (!RC.contains(Reg))
continue;
diff --git a/contrib/llvm/utils/TableGen/CodeGenRegisters.h b/contrib/llvm/utils/TableGen/CodeGenRegisters.h
index 5edbf47..4fc34b0 100644
--- a/contrib/llvm/utils/TableGen/CodeGenRegisters.h
+++ b/contrib/llvm/utils/TableGen/CodeGenRegisters.h
@@ -15,10 +15,11 @@
#ifndef CODEGEN_REGISTERS_H
#define CODEGEN_REGISTERS_H
-#include "Record.h"
#include "SetTheory.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SetVector.h"
#include <cstdlib>
@@ -69,6 +70,7 @@ namespace llvm {
struct Less {
bool operator()(const CodeGenRegister *A,
const CodeGenRegister *B) const {
+ assert(A && B);
return A->EnumValue < B->EnumValue;
}
};
@@ -85,10 +87,25 @@ namespace llvm {
class CodeGenRegisterClass {
CodeGenRegister::Set Members;
- const std::vector<Record*> *Elements;
- std::vector<SmallVector<Record*, 16> > AltOrders;
- public:
+ // Allocation orders. Order[0] always contains all registers in Members.
+ std::vector<SmallVector<Record*, 16> > Orders;
+ // Bit mask of sub-classes including this, indexed by their EnumValue.
+ BitVector SubClasses;
+ // List of super-classes, topologocally ordered to have the larger classes
+ // first. This is the same as sorting by EnumValue.
+ SmallVector<CodeGenRegisterClass*, 4> SuperClasses;
Record *TheDef;
+ std::string Name;
+
+ // For a synthesized class, inherit missing properties from the nearest
+ // super-class.
+ void inheritProperties(CodeGenRegBank&);
+
+ // Map SubRegIndex -> sub-class
+ DenseMap<Record*, CodeGenRegisterClass*> SubClassWithSubReg;
+
+ public:
+ unsigned EnumValue;
std::string Namespace;
std::vector<MVT::SimpleValueType> VTs;
unsigned SpillSize;
@@ -99,7 +116,12 @@ namespace llvm {
DenseMap<Record*,Record*> SubRegClasses;
std::string AltOrderSelect;
- const std::string &getName() const;
+ // Return the Record that defined this class, or NULL if the class was
+ // created by TableGen.
+ Record *getDef() const { return TheDef; }
+
+ const std::string &getName() const { return Name; }
+ std::string getQualifiedName() const;
const std::vector<MVT::SimpleValueType> &getValueTypes() const {return VTs;}
unsigned getNumValueTypes() const { return VTs.size(); }
@@ -122,22 +144,77 @@ namespace llvm {
// 2. The RC spill size must not be smaller than our spill size.
// 3. RC spill alignment must be compatible with ours.
//
- bool hasSubClass(const CodeGenRegisterClass *RC) const;
+ bool hasSubClass(const CodeGenRegisterClass *RC) const {
+ return SubClasses.test(RC->EnumValue);
+ }
+
+ // getSubClassWithSubReg - Returns the largest sub-class where all
+ // registers have a SubIdx sub-register.
+ CodeGenRegisterClass *getSubClassWithSubReg(Record *SubIdx) const {
+ return SubClassWithSubReg.lookup(SubIdx);
+ }
+
+ void setSubClassWithSubReg(Record *SubIdx, CodeGenRegisterClass *SubRC) {
+ SubClassWithSubReg[SubIdx] = SubRC;
+ }
+
+ // getSubClasses - Returns a constant BitVector of subclasses indexed by
+ // EnumValue.
+ // The SubClasses vector includs an entry for this class.
+ const BitVector &getSubClasses() const { return SubClasses; }
+
+ // getSuperClasses - Returns a list of super classes ordered by EnumValue.
+ // The array does not include an entry for this class.
+ ArrayRef<CodeGenRegisterClass*> getSuperClasses() const {
+ return SuperClasses;
+ }
// Returns an ordered list of class members.
// The order of registers is the same as in the .td file.
// No = 0 is the default allocation order, No = 1 is the first alternative.
ArrayRef<Record*> getOrder(unsigned No = 0) const {
- if (No == 0)
- return *Elements;
- else
- return AltOrders[No - 1];
+ return Orders[No];
}
// Return the total number of allocation orders available.
- unsigned getNumOrders() const { return 1 + AltOrders.size(); }
+ unsigned getNumOrders() const { return Orders.size(); }
+
+ // Get the set of registers. This set contains the same registers as
+ // getOrder(0).
+ const CodeGenRegister::Set &getMembers() const { return Members; }
CodeGenRegisterClass(CodeGenRegBank&, Record *R);
+
+ // A key representing the parts of a register class used for forming
+ // sub-classes. Note the ordering provided by this key is not the same as
+ // the topological order used for the EnumValues.
+ struct Key {
+ const CodeGenRegister::Set *Members;
+ unsigned SpillSize;
+ unsigned SpillAlignment;
+
+ Key(const Key &O)
+ : Members(O.Members),
+ SpillSize(O.SpillSize),
+ SpillAlignment(O.SpillAlignment) {}
+
+ Key(const CodeGenRegister::Set *M, unsigned S = 0, unsigned A = 0)
+ : Members(M), SpillSize(S), SpillAlignment(A) {}
+
+ Key(const CodeGenRegisterClass &RC)
+ : Members(&RC.getMembers()),
+ SpillSize(RC.SpillSize),
+ SpillAlignment(RC.SpillAlignment) {}
+
+ // Lexicographical order of (Members, SpillSize, SpillAlignment).
+ bool operator<(const Key&) const;
+ };
+
+ // Create a non-user defined register class.
+ CodeGenRegisterClass(StringRef Name, Key Props);
+
+ // Called by CodeGenRegBank::CodeGenRegBank().
+ static void computeSubClasses(CodeGenRegBank&);
};
// CodeGenRegBank - Represent a target's registers and the relations between
@@ -151,8 +228,17 @@ namespace llvm {
std::vector<CodeGenRegister*> Registers;
DenseMap<Record*, CodeGenRegister*> Def2Reg;
- std::vector<CodeGenRegisterClass> RegClasses;
+ // Register classes.
+ std::vector<CodeGenRegisterClass*> RegClasses;
DenseMap<Record*, CodeGenRegisterClass*> Def2RC;
+ typedef std::map<CodeGenRegisterClass::Key, CodeGenRegisterClass*> RCKeyMap;
+ RCKeyMap Key2RC;
+
+ // Add RC to *2RC maps.
+ void addToMaps(CodeGenRegisterClass*);
+
+ // Infer missing register classes.
+ void computeInferredRegisterClasses();
// Composite SubRegIndex instances.
// Map (SubRegIndex, SubRegIndex) -> SubRegIndex.
@@ -184,7 +270,7 @@ namespace llvm {
// Find a register from its Record def.
CodeGenRegister *getReg(Record*);
- const std::vector<CodeGenRegisterClass> &getRegClasses() {
+ ArrayRef<CodeGenRegisterClass*> getRegClasses() const {
return RegClasses;
}
diff --git a/contrib/llvm/utils/TableGen/CodeGenTarget.cpp b/contrib/llvm/utils/TableGen/CodeGenTarget.cpp
index 929791c..4a7bad7 100644
--- a/contrib/llvm/utils/TableGen/CodeGenTarget.cpp
+++ b/contrib/llvm/utils/TableGen/CodeGenTarget.cpp
@@ -16,7 +16,7 @@
#include "CodeGenTarget.h"
#include "CodeGenIntrinsics.h"
-#include "Record.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/CommandLine.h"
@@ -184,9 +184,9 @@ std::vector<MVT::SimpleValueType> CodeGenTarget::
getRegisterVTs(Record *R) const {
const CodeGenRegister *Reg = getRegBank().getReg(R);
std::vector<MVT::SimpleValueType> Result;
- const std::vector<CodeGenRegisterClass> &RCs = getRegisterClasses();
+ ArrayRef<CodeGenRegisterClass*> RCs = getRegBank().getRegClasses();
for (unsigned i = 0, e = RCs.size(); i != e; ++i) {
- const CodeGenRegisterClass &RC = RCs[i];
+ const CodeGenRegisterClass &RC = *RCs[i];
if (RC.contains(Reg)) {
const std::vector<MVT::SimpleValueType> &InVTs = RC.getValueTypes();
Result.insert(Result.end(), InVTs.begin(), InVTs.end());
@@ -201,10 +201,10 @@ getRegisterVTs(Record *R) const {
void CodeGenTarget::ReadLegalValueTypes() const {
- const std::vector<CodeGenRegisterClass> &RCs = getRegisterClasses();
+ ArrayRef<CodeGenRegisterClass*> RCs = getRegBank().getRegClasses();
for (unsigned i = 0, e = RCs.size(); i != e; ++i)
- for (unsigned ri = 0, re = RCs[i].VTs.size(); ri != re; ++ri)
- LegalValueTypes.push_back(RCs[i].VTs[ri]);
+ for (unsigned ri = 0, re = RCs[i]->VTs.size(); ri != re; ++ri)
+ LegalValueTypes.push_back(RCs[i]->VTs[ri]);
// Remove duplicates.
std::sort(LegalValueTypes.begin(), LegalValueTypes.end());
diff --git a/contrib/llvm/utils/TableGen/CodeGenTarget.h b/contrib/llvm/utils/TableGen/CodeGenTarget.h
index 143daed..730216c 100644
--- a/contrib/llvm/utils/TableGen/CodeGenTarget.h
+++ b/contrib/llvm/utils/TableGen/CodeGenTarget.h
@@ -19,7 +19,7 @@
#include "CodeGenRegisters.h"
#include "CodeGenInstruction.h"
-#include "Record.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
@@ -107,10 +107,6 @@ public:
return RegAltNameIndices;
}
- const std::vector<CodeGenRegisterClass> &getRegisterClasses() const {
- return getRegBank().getRegClasses();
- }
-
const CodeGenRegisterClass &getRegisterClass(Record *R) const {
return *getRegBank().getRegClass(R);
}
diff --git a/contrib/llvm/utils/TableGen/DAGISelEmitter.cpp b/contrib/llvm/utils/TableGen/DAGISelEmitter.cpp
index d66ae96..7db9003 100644
--- a/contrib/llvm/utils/TableGen/DAGISelEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/DAGISelEmitter.cpp
@@ -13,7 +13,7 @@
#include "DAGISelEmitter.h"
#include "DAGISelMatcher.h"
-#include "Record.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/Support/Debug.h"
using namespace llvm;
diff --git a/contrib/llvm/utils/TableGen/DAGISelEmitter.h b/contrib/llvm/utils/TableGen/DAGISelEmitter.h
index 35ab550..9c9fe42 100644
--- a/contrib/llvm/utils/TableGen/DAGISelEmitter.h
+++ b/contrib/llvm/utils/TableGen/DAGISelEmitter.h
@@ -14,7 +14,7 @@
#ifndef DAGISEL_EMITTER_H
#define DAGISEL_EMITTER_H
-#include "TableGenBackend.h"
+#include "llvm/TableGen/TableGenBackend.h"
#include "CodeGenDAGPatterns.h"
namespace llvm {
diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcher.cpp b/contrib/llvm/utils/TableGen/DAGISelMatcher.cpp
index b12e101..1367e8d 100644
--- a/contrib/llvm/utils/TableGen/DAGISelMatcher.cpp
+++ b/contrib/llvm/utils/TableGen/DAGISelMatcher.cpp
@@ -10,7 +10,7 @@
#include "DAGISelMatcher.h"
#include "CodeGenDAGPatterns.h"
#include "CodeGenTarget.h"
-#include "Record.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/StringExtras.h"
using namespace llvm;
diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp b/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp
index acb0135..3b65b2a 100644
--- a/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp
@@ -13,7 +13,7 @@
#include "DAGISelMatcher.h"
#include "CodeGenDAGPatterns.h"
-#include "Record.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringMap.h"
diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp b/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp
index c5897c7..49ad956 100644
--- a/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp
+++ b/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp
@@ -10,7 +10,7 @@
#include "DAGISelMatcher.h"
#include "CodeGenDAGPatterns.h"
#include "CodeGenRegisters.h"
-#include "Record.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
@@ -26,10 +26,10 @@ static MVT::SimpleValueType getRegisterValueType(Record *R,
bool FoundRC = false;
MVT::SimpleValueType VT = MVT::Other;
const CodeGenRegister *Reg = T.getRegBank().getReg(R);
- const std::vector<CodeGenRegisterClass> &RCs = T.getRegisterClasses();
+ ArrayRef<CodeGenRegisterClass*> RCs = T.getRegBank().getRegClasses();
for (unsigned rc = 0, e = RCs.size(); rc != e; ++rc) {
- const CodeGenRegisterClass &RC = RCs[rc];
+ const CodeGenRegisterClass &RC = *RCs[rc];
if (!RC.contains(Reg))
continue;
diff --git a/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp b/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp
index 07313d1..ff314e9 100644
--- a/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp
@@ -9,12 +9,12 @@
#include "DisassemblerEmitter.h"
#include "CodeGenTarget.h"
-#include "Error.h"
-#include "Record.h"
#include "X86DisassemblerTables.h"
#include "X86RecognizableInstr.h"
#include "ARMDecoderEmitter.h"
#include "FixedLenDecoderEmitter.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
using namespace llvm;
using namespace llvm::X86Disassembler;
@@ -128,12 +128,16 @@ void DisassemblerEmitter::run(raw_ostream &OS) {
return;
}
- // Fixed-instruction-length targets use a common disassembler.
- // ARM use its own implementation for now.
- if (Target.getName() == "ARM") {
- ARMDecoderEmitter(Records).run(OS);
+ // ARM and Thumb have a CHECK() macro to deal with DecodeStatuses.
+ if (Target.getName() == "ARM" ||
+ Target.getName() == "Thumb") {
+ FixedLenDecoderEmitter(Records,
+ "ARM",
+ "if (!Check(S, ", ")) return MCDisassembler::Fail;",
+ "S", "MCDisassembler::Fail",
+ " MCDisassembler::DecodeStatus S = MCDisassembler::Success;\n(void)S;").run(OS);
return;
- }
+ }
- FixedLenDecoderEmitter(Records).run(OS);
+ FixedLenDecoderEmitter(Records, Target.getName()).run(OS);
}
diff --git a/contrib/llvm/utils/TableGen/DisassemblerEmitter.h b/contrib/llvm/utils/TableGen/DisassemblerEmitter.h
index 7229d81..63ee552 100644
--- a/contrib/llvm/utils/TableGen/DisassemblerEmitter.h
+++ b/contrib/llvm/utils/TableGen/DisassemblerEmitter.h
@@ -10,7 +10,7 @@
#ifndef DISASSEMBLEREMITTER_H
#define DISASSEMBLEREMITTER_H
-#include "TableGenBackend.h"
+#include "llvm/TableGen/TableGenBackend.h"
namespace llvm {
diff --git a/contrib/llvm/utils/TableGen/EDEmitter.cpp b/contrib/llvm/utils/TableGen/EDEmitter.cpp
index 2f9814a..abef70e 100644
--- a/contrib/llvm/utils/TableGen/EDEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/EDEmitter.cpp
@@ -17,8 +17,8 @@
#include "AsmWriterInst.h"
#include "CodeGenTarget.h"
-#include "Record.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/MC/EDInstInfo.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
@@ -256,12 +256,15 @@ static int X86TypeFromOpName(LiteralConstantEmitter *type,
REG("GR8");
REG("GR8_NOREX");
REG("GR16");
+ REG("GR16_NOAX");
REG("GR32");
+ REG("GR32_NOAX");
REG("GR32_NOREX");
REG("GR32_TC");
REG("FR32");
REG("RFP32");
REG("GR64");
+ REG("GR64_NOAX");
REG("GR64_TC");
REG("FR64");
REG("VR64");
@@ -279,6 +282,7 @@ static int X86TypeFromOpName(LiteralConstantEmitter *type,
IMM("i16i8imm");
IMM("i32imm");
IMM("i32i8imm");
+ IMM("u32u8imm");
IMM("i64imm");
IMM("i64i8imm");
IMM("i64i32imm");
@@ -554,6 +558,8 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
const std::string &name) {
REG("GPR");
REG("rGPR");
+ REG("GPRnopc");
+ REG("GPRsp");
REG("tcGPR");
REG("cc_out");
REG("s_cc_out");
@@ -575,6 +581,7 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
IMM("nohash_imm");
IMM("p_imm");
IMM("c_imm");
+ IMM("coproc_option_imm");
IMM("imod_op");
IMM("iflags_op");
IMM("cpinst_operand");
@@ -587,26 +594,40 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
IMM("neg_zero");
IMM("imm0_31");
IMM("imm0_31_m1");
+ IMM("imm1_16");
+ IMM("imm1_32");
IMM("nModImm");
IMM("imm0_7");
IMM("imm0_15");
IMM("imm0_255");
IMM("imm0_4095");
IMM("imm0_65535");
+ IMM("imm0_65535_expr");
+ IMM("imm24b");
+ IMM("pkh_lsl_amt");
+ IMM("pkh_asr_amt");
IMM("jt2block_operand");
- IMM("t_imm_s4");
+ IMM("t_imm0_1020s4");
+ IMM("t_imm0_508s4");
IMM("pclabel");
IMM("adrlabel");
IMM("t_adrlabel");
IMM("t2adrlabel");
IMM("shift_imm");
- IMM("ssat_imm");
+ IMM("t2_shift_imm");
IMM("neon_vcvt_imm32");
IMM("shr_imm8");
IMM("shr_imm16");
IMM("shr_imm32");
IMM("shr_imm64");
IMM("t2ldrlabel");
+ IMM("postidx_imm8");
+ IMM("postidx_imm8s4");
+ IMM("imm_sr");
+ IMM("imm1_31");
+ IMM("VectorIndex8");
+ IMM("VectorIndex16");
+ IMM("VectorIndex32");
MISC("brtarget", "kOperandTypeARMBranchTarget"); // ?
MISC("uncondbrtarget", "kOperandTypeARMBranchTarget"); // ?
@@ -617,11 +638,14 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
MISC("br_target", "kOperandTypeARMBranchTarget"); // ?
MISC("bl_target", "kOperandTypeARMBranchTarget"); // ?
+ MISC("blx_target", "kOperandTypeARMBranchTarget"); // ?
MISC("t_bltarget", "kOperandTypeARMBranchTarget"); // ?
MISC("t_blxtarget", "kOperandTypeARMBranchTarget"); // ?
- MISC("so_reg", "kOperandTypeARMSoReg"); // R, R, I
- MISC("shift_so_reg", "kOperandTypeARMSoReg"); // R, R, I
+ MISC("so_reg_imm", "kOperandTypeARMSoRegReg"); // R, R, I
+ MISC("so_reg_reg", "kOperandTypeARMSoRegImm"); // R, R, I
+ MISC("shift_so_reg_reg", "kOperandTypeARMSoRegReg"); // R, R, I
+ MISC("shift_so_reg_imm", "kOperandTypeARMSoRegImm"); // R, R, I
MISC("t2_so_reg", "kOperandTypeThumb2SoReg"); // R, I
MISC("so_imm", "kOperandTypeARMSoImm"); // I
MISC("rot_imm", "kOperandTypeARMRotImm"); // I
@@ -631,8 +655,10 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
MISC("it_pred", "kOperandTypeARMPredicate"); // I
MISC("addrmode_imm12", "kOperandTypeAddrModeImm12"); // R, I
MISC("ldst_so_reg", "kOperandTypeLdStSOReg"); // R, R, I
+ MISC("postidx_reg", "kOperandTypeARMAddrMode3Offset"); // R, I
MISC("addrmode2", "kOperandTypeARMAddrMode2"); // R, R, I
- MISC("am2offset", "kOperandTypeARMAddrMode2Offset"); // R, I
+ MISC("am2offset_reg", "kOperandTypeARMAddrMode2Offset"); // R, I
+ MISC("am2offset_imm", "kOperandTypeARMAddrMode2Offset"); // R, I
MISC("addrmode3", "kOperandTypeARMAddrMode3"); // R, R, I
MISC("am3offset", "kOperandTypeARMAddrMode3Offset"); // R, I
MISC("ldstm_mode", "kOperandTypeARMLdStmMode"); // I
@@ -642,17 +668,20 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
MISC("addrmode6dup", "kOperandTypeARMAddrMode6"); // R, R, I, I
MISC("addrmode6oneL32", "kOperandTypeARMAddrMode6"); // R, R, I, I
MISC("addrmodepc", "kOperandTypeARMAddrModePC"); // R, I
- MISC("addrmode7", "kOperandTypeARMAddrMode7"); // R
+ MISC("addr_offset_none", "kOperandTypeARMAddrMode7"); // R
MISC("reglist", "kOperandTypeARMRegisterList"); // I, R, ...
MISC("dpr_reglist", "kOperandTypeARMDPRRegisterList"); // I, R, ...
MISC("spr_reglist", "kOperandTypeARMSPRRegisterList"); // I, R, ...
MISC("it_mask", "kOperandTypeThumbITMask"); // I
MISC("t2addrmode_reg", "kOperandTypeThumb2AddrModeReg"); // R
+ MISC("t2addrmode_posimm8", "kOperandTypeThumb2AddrModeImm8"); // R, I
+ MISC("t2addrmode_negimm8", "kOperandTypeThumb2AddrModeImm8"); // R, I
MISC("t2addrmode_imm8", "kOperandTypeThumb2AddrModeImm8"); // R, I
MISC("t2am_imm8_offset", "kOperandTypeThumb2AddrModeImm8Offset");//I
MISC("t2addrmode_imm12", "kOperandTypeThumb2AddrModeImm12"); // R, I
MISC("t2addrmode_so_reg", "kOperandTypeThumb2AddrModeSoReg"); // R, R, I
MISC("t2addrmode_imm8s4", "kOperandTypeThumb2AddrModeImm8s4"); // R, I
+ MISC("t2addrmode_imm0_1020s4", "kOperandTypeThumb2AddrModeImm8s4"); // R, I
MISC("t2am_imm8s4_offset", "kOperandTypeThumb2AddrModeImm8s4Offset");
// R, I
MISC("tb_addrmode", "kOperandTypeARMTBAddrMode"); // I
@@ -665,6 +694,8 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
MISC("t_addrmode_rr", "kOperandTypeThumbAddrModeRR"); // R, R
MISC("t_addrmode_sp", "kOperandTypeThumbAddrModeSP"); // R, I
MISC("t_addrmode_pc", "kOperandTypeThumbAddrModePC"); // R, I
+ MISC("addrmode_tbb", "kOperandTypeThumbAddrModeRR"); // R, R
+ MISC("addrmode_tbh", "kOperandTypeThumbAddrModeRR"); // R, R
return 1;
}
@@ -772,11 +803,6 @@ static void populateInstInfo(CompoundConstantEmitter &infoArray,
for (index = 0; index < numInstructions; ++index) {
const CodeGenInstruction& inst = *numberedInstructions[index];
- // We don't need to do anything for pseudo-instructions, as we'll never
- // see them here. We'll only see real instructions.
- if (inst.isPseudo)
- continue;
-
CompoundConstantEmitter *infoStruct = new CompoundConstantEmitter;
infoArray.addEntry(infoStruct);
@@ -809,15 +835,20 @@ static void populateInstInfo(CompoundConstantEmitter &infoArray,
unsigned numSyntaxes = 0;
- if (target.getName() == "X86") {
- X86PopulateOperands(operandTypes, inst);
- X86ExtractSemantics(*instType, operandFlags, inst);
- numSyntaxes = 2;
- }
- else if (target.getName() == "ARM") {
- ARMPopulateOperands(operandTypes, inst);
- ARMExtractSemantics(*instType, operandTypes, operandFlags, inst);
- numSyntaxes = 1;
+ // We don't need to do anything for pseudo-instructions, as we'll never
+ // see them here. We'll only see real instructions.
+ // We still need to emit null initializers for everything.
+ if (!inst.isPseudo) {
+ if (target.getName() == "X86") {
+ X86PopulateOperands(operandTypes, inst);
+ X86ExtractSemantics(*instType, operandFlags, inst);
+ numSyntaxes = 2;
+ }
+ else if (target.getName() == "ARM") {
+ ARMPopulateOperands(operandTypes, inst);
+ ARMExtractSemantics(*instType, operandTypes, operandFlags, inst);
+ numSyntaxes = 1;
+ }
}
CompoundConstantEmitter *operandOrderArray = new CompoundConstantEmitter;
@@ -850,7 +881,8 @@ static void emitCommonEnums(raw_ostream &o, unsigned int &i) {
operandTypes.addEntry("kOperandTypeX86EffectiveAddress");
operandTypes.addEntry("kOperandTypeX86PCRelative");
operandTypes.addEntry("kOperandTypeARMBranchTarget");
- operandTypes.addEntry("kOperandTypeARMSoReg");
+ operandTypes.addEntry("kOperandTypeARMSoRegReg");
+ operandTypes.addEntry("kOperandTypeARMSoRegImm");
operandTypes.addEntry("kOperandTypeARMSoImm");
operandTypes.addEntry("kOperandTypeARMRotImm");
operandTypes.addEntry("kOperandTypeARMSoImm2Part");
diff --git a/contrib/llvm/utils/TableGen/EDEmitter.h b/contrib/llvm/utils/TableGen/EDEmitter.h
index e30373f..f268375 100644
--- a/contrib/llvm/utils/TableGen/EDEmitter.h
+++ b/contrib/llvm/utils/TableGen/EDEmitter.h
@@ -16,7 +16,7 @@
#ifndef SEMANTIC_INFO_EMITTER_H
#define SEMANTIC_INFO_EMITTER_H
-#include "TableGenBackend.h"
+#include "llvm/TableGen/TableGenBackend.h"
namespace llvm {
diff --git a/contrib/llvm/utils/TableGen/Error.cpp b/contrib/llvm/utils/TableGen/Error.cpp
deleted file mode 100644
index 3f6cda8..0000000
--- a/contrib/llvm/utils/TableGen/Error.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-//===- Error.cpp - tblgen error handling helper routines --------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains error handling helper routines to pretty-print diagnostic
-// messages from tblgen.
-//
-//===----------------------------------------------------------------------===//
-
-#include "Error.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/Support/raw_ostream.h"
-
-namespace llvm {
-
-SourceMgr SrcMgr;
-
-void PrintError(SMLoc ErrorLoc, const Twine &Msg) {
- SrcMgr.PrintMessage(ErrorLoc, Msg, "error");
-}
-
-void PrintError(const char *Loc, const Twine &Msg) {
- SrcMgr.PrintMessage(SMLoc::getFromPointer(Loc), Msg, "error");
-}
-
-void PrintError(const Twine &Msg) {
- errs() << "error:" << Msg << "\n";
-}
-
-void PrintError(const TGError &Error) {
- PrintError(Error.getLoc(), Error.getMessage());
-}
-
-} // end namespace llvm
diff --git a/contrib/llvm/utils/TableGen/Error.h b/contrib/llvm/utils/TableGen/Error.h
deleted file mode 100644
index b3a0146..0000000
--- a/contrib/llvm/utils/TableGen/Error.h
+++ /dev/null
@@ -1,43 +0,0 @@
-//===- Error.h - tblgen error handling helper routines ----------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains error handling helper routines to pretty-print diagnostic
-// messages from tblgen.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef ERROR_H
-#define ERROR_H
-
-#include "llvm/Support/SourceMgr.h"
-
-namespace llvm {
-
-class TGError {
- SMLoc Loc;
- std::string Message;
-public:
- TGError(SMLoc loc, const std::string &message) : Loc(loc), Message(message) {}
-
- SMLoc getLoc() const { return Loc; }
- const std::string &getMessage() const { return Message; }
-};
-
-void PrintError(SMLoc ErrorLoc, const Twine &Msg);
-void PrintError(const char *Loc, const Twine &Msg);
-void PrintError(const Twine &Msg);
-void PrintError(const TGError &Error);
-
-
-extern SourceMgr SrcMgr;
-
-
-} // end namespace "llvm"
-
-#endif
diff --git a/contrib/llvm/utils/TableGen/FastISelEmitter.cpp b/contrib/llvm/utils/TableGen/FastISelEmitter.cpp
index f54e8df..9fdc2e3 100644
--- a/contrib/llvm/utils/TableGen/FastISelEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/FastISelEmitter.cpp
@@ -18,8 +18,8 @@
//===----------------------------------------------------------------------===//
#include "FastISelEmitter.h"
-#include "Error.h"
-#include "Record.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/VectorExtras.h"
#include "llvm/Support/Debug.h"
@@ -504,7 +504,7 @@ void FastISelMap::collectPatterns(CodeGenDAGPatterns &CGP) {
std::vector<std::string>* PhysRegInputs = new std::vector<std::string>();
if (InstPatNode->getOperator()->getName() == "imm" ||
- InstPatNode->getOperator()->getName() == "fpimmm")
+ InstPatNode->getOperator()->getName() == "fpimm")
PhysRegInputs->push_back("");
else {
// Compute the PhysRegs used by the given pattern, and check that
diff --git a/contrib/llvm/utils/TableGen/FastISelEmitter.h b/contrib/llvm/utils/TableGen/FastISelEmitter.h
index ce4e77e..4f75ac1 100644
--- a/contrib/llvm/utils/TableGen/FastISelEmitter.h
+++ b/contrib/llvm/utils/TableGen/FastISelEmitter.h
@@ -14,8 +14,8 @@
#ifndef FASTISEL_EMITTER_H
#define FASTISEL_EMITTER_H
-#include "TableGenBackend.h"
#include "CodeGenDAGPatterns.h"
+#include "llvm/TableGen/TableGenBackend.h"
namespace llvm {
diff --git a/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp b/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp
index c9dcb01..02b966a 100644
--- a/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp
@@ -16,7 +16,7 @@
#include "FixedLenDecoderEmitter.h"
#include "CodeGenTarget.h"
-#include "Record.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
@@ -84,11 +84,8 @@ static BitsInit &getBitsField(const Record &def, const char *str) {
// Forward declaration.
class FilterChooser;
-// FIXME: Possibly auto-detected?
-#define BIT_WIDTH 32
-
// Representation of the instruction to work on.
-typedef bit_value_t insn_t[BIT_WIDTH];
+typedef std::vector<bit_value_t> insn_t;
/// Filter - Filter works with FilterChooser to produce the decoding tree for
/// the ISA.
@@ -230,7 +227,7 @@ protected:
// Array of bit values passed down from our parent.
// Set to all BIT_UNFILTERED's for Parent == NULL.
- bit_value_t FilterBitValues[BIT_WIDTH];
+ std::vector<bit_value_t> FilterBitValues;
// Links to the FilterChooser above us in the decoding tree.
FilterChooser *Parent;
@@ -238,21 +235,29 @@ protected:
// Index of the best filter from Filters.
int BestIndex;
+ // Width of instructions
+ unsigned BitWidth;
+
+ // Parent emitter
+ const FixedLenDecoderEmitter *Emitter;
+
public:
FilterChooser(const FilterChooser &FC) :
AllInstructions(FC.AllInstructions), Opcodes(FC.Opcodes),
- Operands(FC.Operands), Filters(FC.Filters), Parent(FC.Parent),
- BestIndex(FC.BestIndex) {
- memcpy(FilterBitValues, FC.FilterBitValues, sizeof(FilterBitValues));
- }
+ Operands(FC.Operands), Filters(FC.Filters),
+ FilterBitValues(FC.FilterBitValues), Parent(FC.Parent),
+ BestIndex(FC.BestIndex), BitWidth(FC.BitWidth),
+ Emitter(FC.Emitter) { }
FilterChooser(const std::vector<const CodeGenInstruction*> &Insts,
const std::vector<unsigned> &IDs,
- std::map<unsigned, std::vector<OperandInfo> > &Ops) :
+ std::map<unsigned, std::vector<OperandInfo> > &Ops,
+ unsigned BW,
+ const FixedLenDecoderEmitter *E) :
AllInstructions(Insts), Opcodes(IDs), Operands(Ops), Filters(),
- Parent(NULL), BestIndex(-1) {
- for (unsigned i = 0; i < BIT_WIDTH; ++i)
- FilterBitValues[i] = BIT_UNFILTERED;
+ Parent(NULL), BestIndex(-1), BitWidth(BW), Emitter(E) {
+ for (unsigned i = 0; i < BitWidth; ++i)
+ FilterBitValues.push_back(BIT_UNFILTERED);
doFilter();
}
@@ -260,13 +265,12 @@ public:
FilterChooser(const std::vector<const CodeGenInstruction*> &Insts,
const std::vector<unsigned> &IDs,
std::map<unsigned, std::vector<OperandInfo> > &Ops,
- bit_value_t (&ParentFilterBitValues)[BIT_WIDTH],
+ std::vector<bit_value_t> &ParentFilterBitValues,
FilterChooser &parent) :
AllInstructions(Insts), Opcodes(IDs), Operands(Ops),
- Filters(), Parent(&parent), BestIndex(-1) {
- for (unsigned i = 0; i < BIT_WIDTH; ++i)
- FilterBitValues[i] = ParentFilterBitValues[i];
-
+ Filters(), FilterBitValues(ParentFilterBitValues),
+ Parent(&parent), BestIndex(-1), BitWidth(parent.BitWidth),
+ Emitter(parent.Emitter) {
doFilter();
}
@@ -274,15 +278,15 @@ public:
bool isTopLevel() { return Parent == NULL; }
// Emit the top level typedef and decodeInstruction() function.
- void emitTop(raw_ostream &o, unsigned Indentation);
+ void emitTop(raw_ostream &o, unsigned Indentation, std::string Namespace);
protected:
// Populates the insn given the uid.
void insnWithID(insn_t &Insn, unsigned Opcode) const {
BitsInit &Bits = getBitsField(*AllInstructions[Opcode]->TheDef, "Inst");
- for (unsigned i = 0; i < BIT_WIDTH; ++i)
- Insn[i] = bitFromBits(Bits, i);
+ for (unsigned i = 0; i < BitWidth; ++i)
+ Insn.push_back(bitFromBits(Bits, i));
}
// Returns the record name.
@@ -300,7 +304,7 @@ protected:
/// dumpFilterArray - dumpFilterArray prints out debugging info for the given
/// filter array as a series of chars.
- void dumpFilterArray(raw_ostream &o, bit_value_t (&filter)[BIT_WIDTH]);
+ void dumpFilterArray(raw_ostream &o, std::vector<bit_value_t> & filter);
/// dumpStack - dumpStack traverses the filter chooser chain and calls
/// dumpFilterArray on each filter chooser up to the top level one.
@@ -326,6 +330,10 @@ protected:
std::vector<unsigned> &EndBits, std::vector<uint64_t> &FieldVals,
insn_t &Insn);
+ // Emits code to check the Predicates member of an instruction are true.
+ // Returns true if predicate matches were emitted, false otherwise.
+ bool emitPredicateMatch(raw_ostream &o, unsigned &Indentation,unsigned Opc);
+
// Emits code to decode the singleton. Return true if we have matched all the
// well-known bits.
bool emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,unsigned Opc);
@@ -333,6 +341,9 @@ protected:
// Emits code to decode the singleton, and then to decode the rest.
void emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,Filter &Best);
+ void emitBinaryParser(raw_ostream &o , unsigned &Indentation,
+ OperandInfo &OpInfo);
+
// Assign a single filter and run with it.
void runSingleFilter(FilterChooser &owner, unsigned startBit, unsigned numBit,
bool mixed);
@@ -375,7 +386,7 @@ Filter::Filter(const Filter &f) :
Filter::Filter(FilterChooser &owner, unsigned startBit, unsigned numBits,
bool mixed) : Owner(&owner), StartBit(startBit), NumBits(numBits),
Mixed(mixed) {
- assert(StartBit + NumBits - 1 < BIT_WIDTH);
+ assert(StartBit + NumBits - 1 < Owner->BitWidth);
NumFiltered = 0;
LastOpcFiltered = 0;
@@ -427,9 +438,8 @@ Filter::~Filter() {
void Filter::recurse() {
std::map<uint64_t, std::vector<unsigned> >::const_iterator mapIterator;
- bit_value_t BitValueArray[BIT_WIDTH];
// Starts by inheriting our parent filter chooser's filter bit values.
- memcpy(BitValueArray, Owner->FilterBitValues, sizeof(BitValueArray));
+ std::vector<bit_value_t> BitValueArray(Owner->FilterBitValues);
unsigned bitIndex;
@@ -493,8 +503,9 @@ void Filter::emit(raw_ostream &o, unsigned &Indentation) {
o << StartBit << "} ...\n";
- o.indent(Indentation) << "switch (fieldFromInstruction(insn, "
- << StartBit << ", " << NumBits << ")) {\n";
+ o.indent(Indentation) << "switch (fieldFromInstruction" << Owner->BitWidth
+ << "(insn, " << StartBit << ", "
+ << NumBits << ")) {\n";
std::map<unsigned, FilterChooser*>::iterator filterIterator;
@@ -559,68 +570,21 @@ unsigned Filter::usefulness() const {
//////////////////////////////////
// Emit the top level typedef and decodeInstruction() function.
-void FilterChooser::emitTop(raw_ostream &o, unsigned Indentation) {
- switch (BIT_WIDTH) {
- case 8:
- o.indent(Indentation) << "typedef uint8_t field_t;\n";
- break;
- case 16:
- o.indent(Indentation) << "typedef uint16_t field_t;\n";
- break;
- case 32:
- o.indent(Indentation) << "typedef uint32_t field_t;\n";
- break;
- case 64:
- o.indent(Indentation) << "typedef uint64_t field_t;\n";
- break;
- default:
- assert(0 && "Unexpected instruction size!");
- }
-
- o << '\n';
-
- o.indent(Indentation) << "static field_t " <<
- "fieldFromInstruction(field_t insn, unsigned startBit, unsigned numBits)\n";
-
- o.indent(Indentation) << "{\n";
-
- ++Indentation; ++Indentation;
- o.indent(Indentation) << "assert(startBit + numBits <= " << BIT_WIDTH
- << " && \"Instruction field out of bounds!\");\n";
- o << '\n';
- o.indent(Indentation) << "field_t fieldMask;\n";
- o << '\n';
- o.indent(Indentation) << "if (numBits == " << BIT_WIDTH << ")\n";
-
- ++Indentation; ++Indentation;
- o.indent(Indentation) << "fieldMask = (field_t)-1;\n";
- --Indentation; --Indentation;
-
- o.indent(Indentation) << "else\n";
-
- ++Indentation; ++Indentation;
- o.indent(Indentation) << "fieldMask = ((1 << numBits) - 1) << startBit;\n";
- --Indentation; --Indentation;
-
- o << '\n';
- o.indent(Indentation) << "return (insn & fieldMask) >> startBit;\n";
- --Indentation; --Indentation;
-
- o.indent(Indentation) << "}\n";
-
- o << '\n';
-
+void FilterChooser::emitTop(raw_ostream &o, unsigned Indentation,
+ std::string Namespace) {
o.indent(Indentation) <<
- "static bool decodeInstruction(MCInst &MI, field_t insn, "
- "uint64_t Address, const void *Decoder) {\n";
- o.indent(Indentation) << " unsigned tmp = 0;\n";
+ "static MCDisassembler::DecodeStatus decode" << Namespace << "Instruction" << BitWidth
+ << "(MCInst &MI, uint" << BitWidth << "_t insn, uint64_t Address, "
+ << "const void *Decoder, const MCSubtargetInfo &STI) {\n";
+ o.indent(Indentation) << " unsigned tmp = 0;\n (void)tmp;\n" << Emitter->Locals << "\n";
+ o.indent(Indentation) << " uint64_t Bits = STI.getFeatureBits();\n";
++Indentation; ++Indentation;
// Emits code to decode the instructions.
emit(o, Indentation);
o << '\n';
- o.indent(Indentation) << "return false;\n";
+ o.indent(Indentation) << "return " << Emitter->ReturnFail << ";\n";
--Indentation; --Indentation;
o.indent(Indentation) << "}\n";
@@ -651,10 +615,10 @@ bool FilterChooser::fieldFromInsn(uint64_t &Field, insn_t &Insn,
/// dumpFilterArray - dumpFilterArray prints out debugging info for the given
/// filter array as a series of chars.
void FilterChooser::dumpFilterArray(raw_ostream &o,
- bit_value_t (&filter)[BIT_WIDTH]) {
+ std::vector<bit_value_t> &filter) {
unsigned bitIndex;
- for (bitIndex = BIT_WIDTH; bitIndex > 0; bitIndex--) {
+ for (bitIndex = BitWidth; bitIndex > 0; bitIndex--) {
switch (filter[bitIndex - 1]) {
case BIT_UNFILTERED:
o << ".";
@@ -727,7 +691,7 @@ unsigned FilterChooser::getIslands(std::vector<unsigned> &StartBits,
int State = 0;
int Val = -1;
- for (unsigned i = 0; i < BIT_WIDTH; ++i) {
+ for (unsigned i = 0; i < BitWidth; ++i) {
Val = Value(Insn[i]);
bool Filtered = PositionFiltered(i);
switch (State) {
@@ -761,7 +725,7 @@ unsigned FilterChooser::getIslands(std::vector<unsigned> &StartBits,
}
// If we are still in Island after the loop, do some housekeeping.
if (State == 2) {
- EndBits.push_back(BIT_WIDTH - 1);
+ EndBits.push_back(BitWidth - 1);
FieldVals.push_back(FieldVal);
++Num;
}
@@ -771,6 +735,70 @@ unsigned FilterChooser::getIslands(std::vector<unsigned> &StartBits,
return Num;
}
+void FilterChooser::emitBinaryParser(raw_ostream &o, unsigned &Indentation,
+ OperandInfo &OpInfo) {
+ std::string &Decoder = OpInfo.Decoder;
+
+ if (OpInfo.numFields() == 1) {
+ OperandInfo::iterator OI = OpInfo.begin();
+ o.indent(Indentation) << " tmp = fieldFromInstruction" << BitWidth
+ << "(insn, " << OI->Base << ", " << OI->Width
+ << ");\n";
+ } else {
+ o.indent(Indentation) << " tmp = 0;\n";
+ for (OperandInfo::iterator OI = OpInfo.begin(), OE = OpInfo.end();
+ OI != OE; ++OI) {
+ o.indent(Indentation) << " tmp |= (fieldFromInstruction" << BitWidth
+ << "(insn, " << OI->Base << ", " << OI->Width
+ << ") << " << OI->Offset << ");\n";
+ }
+ }
+
+ if (Decoder != "")
+ o.indent(Indentation) << " " << Emitter->GuardPrefix << Decoder
+ << "(MI, tmp, Address, Decoder)" << Emitter->GuardPostfix << "\n";
+ else
+ o.indent(Indentation) << " MI.addOperand(MCOperand::CreateImm(tmp));\n";
+
+}
+
+static void emitSinglePredicateMatch(raw_ostream &o, StringRef str,
+ std::string PredicateNamespace) {
+ if (str[0] == '!')
+ o << "!(Bits & " << PredicateNamespace << "::"
+ << str.slice(1,str.size()) << ")";
+ else
+ o << "(Bits & " << PredicateNamespace << "::" << str << ")";
+}
+
+bool FilterChooser::emitPredicateMatch(raw_ostream &o, unsigned &Indentation,
+ unsigned Opc) {
+ ListInit *Predicates = AllInstructions[Opc]->TheDef->getValueAsListInit("Predicates");
+ for (unsigned i = 0; i < Predicates->getSize(); ++i) {
+ Record *Pred = Predicates->getElementAsRecord(i);
+ if (!Pred->getValue("AssemblerMatcherPredicate"))
+ continue;
+
+ std::string P = Pred->getValueAsString("AssemblerCondString");
+
+ if (!P.length())
+ continue;
+
+ if (i != 0)
+ o << " && ";
+
+ StringRef SR(P);
+ std::pair<StringRef, StringRef> pairs = SR.split(',');
+ while (pairs.second.size()) {
+ emitSinglePredicateMatch(o, pairs.first, Emitter->PredicateNamespace);
+ o << " && ";
+ pairs = pairs.second.split(',');
+ }
+ emitSinglePredicateMatch(o, pairs.first, Emitter->PredicateNamespace);
+ }
+ return Predicates->getSize() > 0;
+}
+
// Emits code to decode the singleton. Return true if we have matched all the
// well-known bits.
bool FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,
@@ -789,33 +817,27 @@ bool FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,
// If we have matched all the well-known bits, just issue a return.
if (Size == 0) {
- o.indent(Indentation) << "{\n";
+ o.indent(Indentation) << "if (";
+ if (!emitPredicateMatch(o, Indentation, Opc))
+ o << "1";
+ o << ") {\n";
o.indent(Indentation) << " MI.setOpcode(" << Opc << ");\n";
std::vector<OperandInfo>& InsnOperands = Operands[Opc];
for (std::vector<OperandInfo>::iterator
I = InsnOperands.begin(), E = InsnOperands.end(); I != E; ++I) {
// If a custom instruction decoder was specified, use that.
- if (I->FieldBase == ~0U && I->FieldLength == ~0U) {
- o.indent(Indentation) << " " << I->Decoder
- << "(MI, insn, Address, Decoder);\n";
+ if (I->numFields() == 0 && I->Decoder.size()) {
+ o.indent(Indentation) << " " << Emitter->GuardPrefix << I->Decoder
+ << "(MI, insn, Address, Decoder)" << Emitter->GuardPostfix << "\n";
break;
}
- o.indent(Indentation)
- << " tmp = fieldFromInstruction(insn, " << I->FieldBase
- << ", " << I->FieldLength << ");\n";
- if (I->Decoder != "") {
- o.indent(Indentation) << " " << I->Decoder
- << "(MI, tmp, Address, Decoder);\n";
- } else {
- o.indent(Indentation)
- << " MI.addOperand(MCOperand::CreateImm(tmp));\n";
- }
+ emitBinaryParser(o, Indentation, *I);
}
- o.indent(Indentation) << " return true; // " << nameWithID(Opc)
+ o.indent(Indentation) << " return " << Emitter->ReturnOK << "; // " << nameWithID(Opc)
<< '\n';
- o.indent(Indentation) << "}\n";
+ o.indent(Indentation) << "}\n"; // Closing predicate block.
return true;
}
@@ -827,16 +849,21 @@ bool FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,
for (I = Size; I != 0; --I) {
o << "Inst{" << EndBits[I-1] << '-' << StartBits[I-1] << "} ";
if (I > 1)
- o << "&& ";
+ o << " && ";
else
o << "for singleton decoding...\n";
}
o.indent(Indentation) << "if (";
+ if (emitPredicateMatch(o, Indentation, Opc)) {
+ o << " &&\n";
+ o.indent(Indentation+4);
+ }
for (I = Size; I != 0; --I) {
NumBits = EndBits[I-1] - StartBits[I-1] + 1;
- o << "fieldFromInstruction(insn, " << StartBits[I-1] << ", " << NumBits
+ o << "fieldFromInstruction" << BitWidth << "(insn, "
+ << StartBits[I-1] << ", " << NumBits
<< ") == " << FieldVals[I-1];
if (I > 1)
o << " && ";
@@ -848,24 +875,15 @@ bool FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,
for (std::vector<OperandInfo>::iterator
I = InsnOperands.begin(), E = InsnOperands.end(); I != E; ++I) {
// If a custom instruction decoder was specified, use that.
- if (I->FieldBase == ~0U && I->FieldLength == ~0U) {
- o.indent(Indentation) << " " << I->Decoder
- << "(MI, insn, Address, Decoder);\n";
+ if (I->numFields() == 0 && I->Decoder.size()) {
+ o.indent(Indentation) << " " << Emitter->GuardPrefix << I->Decoder
+ << "(MI, insn, Address, Decoder)" << Emitter->GuardPostfix << "\n";
break;
}
- o.indent(Indentation)
- << " tmp = fieldFromInstruction(insn, " << I->FieldBase
- << ", " << I->FieldLength << ");\n";
- if (I->Decoder != "") {
- o.indent(Indentation) << " " << I->Decoder
- << "(MI, tmp, Address, Decoder);\n";
- } else {
- o.indent(Indentation)
- << " MI.addOperand(MCOperand::CreateImm(tmp));\n";
- }
+ emitBinaryParser(o, Indentation, *I);
}
- o.indent(Indentation) << " return true; // " << nameWithID(Opc)
+ o.indent(Indentation) << " return " << Emitter->ReturnOK << "; // " << nameWithID(Opc)
<< '\n';
o.indent(Indentation) << "}\n";
@@ -965,23 +983,23 @@ bool FilterChooser::filterProcessor(bool AllowMixed, bool Greedy) {
// (MIXED) ------ . ----> (MIXED)
// (FILTERED)---- . ----> (FILTERED)
- bitAttr_t bitAttrs[BIT_WIDTH];
+ std::vector<bitAttr_t> bitAttrs;
// FILTERED bit positions provide no entropy and are not worthy of pursuing.
// Filter::recurse() set either BIT_TRUE or BIT_FALSE for each position.
- for (BitIndex = 0; BitIndex < BIT_WIDTH; ++BitIndex)
+ for (BitIndex = 0; BitIndex < BitWidth; ++BitIndex)
if (FilterBitValues[BitIndex] == BIT_TRUE ||
FilterBitValues[BitIndex] == BIT_FALSE)
- bitAttrs[BitIndex] = ATTR_FILTERED;
+ bitAttrs.push_back(ATTR_FILTERED);
else
- bitAttrs[BitIndex] = ATTR_NONE;
+ bitAttrs.push_back(ATTR_NONE);
for (InsnIndex = 0; InsnIndex < numInstructions; ++InsnIndex) {
insn_t insn;
insnWithID(insn, Opcodes[InsnIndex]);
- for (BitIndex = 0; BitIndex < BIT_WIDTH; ++BitIndex) {
+ for (BitIndex = 0; BitIndex < BitWidth; ++BitIndex) {
switch (bitAttrs[BitIndex]) {
case ATTR_NONE:
if (insn[BitIndex] == BIT_UNSET)
@@ -1027,7 +1045,7 @@ bool FilterChooser::filterProcessor(bool AllowMixed, bool Greedy) {
bitAttr_t RA = ATTR_NONE;
unsigned StartBit = 0;
- for (BitIndex = 0; BitIndex < BIT_WIDTH; BitIndex++) {
+ for (BitIndex = 0; BitIndex < BitWidth; BitIndex++) {
bitAttr_t bitAttr = bitAttrs[BitIndex];
assert(bitAttr != ATTR_NONE && "Bit without attributes");
@@ -1216,8 +1234,9 @@ bool FilterChooser::emit(raw_ostream &o, unsigned &Indentation) {
return true;
}
-bool FixedLenDecoderEmitter::populateInstruction(const CodeGenInstruction &CGI,
- unsigned Opc){
+static bool populateInstruction(const CodeGenInstruction &CGI,
+ unsigned Opc,
+ std::map<unsigned, std::vector<OperandInfo> >& Operands){
const Record &Def = *CGI.TheDef;
// If all the bit positions are not specified; do not decode this instruction.
// We are bound to fail! For proper disassembly, the well-known encoding bits
@@ -1239,7 +1258,7 @@ bool FixedLenDecoderEmitter::populateInstruction(const CodeGenInstruction &CGI,
// of trying to auto-generate the decoder.
std::string InstDecoder = Def.getValueAsString("DecoderMethod");
if (InstDecoder != "") {
- InsnOperands.push_back(OperandInfo(~0U, ~0U, InstDecoder));
+ InsnOperands.push_back(OperandInfo(InstDecoder));
Operands[Opc] = InsnOperands;
return true;
}
@@ -1259,72 +1278,97 @@ bool FixedLenDecoderEmitter::populateInstruction(const CodeGenInstruction &CGI,
for (unsigned i = 0; i < In->getNumArgs(); ++i)
InOutOperands.push_back(std::make_pair(In->getArg(i), In->getArgName(i)));
+ // Search for tied operands, so that we can correctly instantiate
+ // operands that are not explicitly represented in the encoding.
+ std::map<std::string, std::string> TiedNames;
+ for (unsigned i = 0; i < CGI.Operands.size(); ++i) {
+ int tiedTo = CGI.Operands[i].getTiedRegister();
+ if (tiedTo != -1) {
+ TiedNames[InOutOperands[i].second] = InOutOperands[tiedTo].second;
+ TiedNames[InOutOperands[tiedTo].second] = InOutOperands[i].second;
+ }
+ }
+
// For each operand, see if we can figure out where it is encoded.
for (std::vector<std::pair<Init*, std::string> >::iterator
NI = InOutOperands.begin(), NE = InOutOperands.end(); NI != NE; ++NI) {
- unsigned PrevBit = ~0;
- unsigned Base = ~0;
- unsigned PrevPos = ~0;
std::string Decoder = "";
+ // At this point, we can locate the field, but we need to know how to
+ // interpret it. As a first step, require the target to provide callbacks
+ // for decoding register classes.
+ // FIXME: This need to be extended to handle instructions with custom
+ // decoder methods, and operands with (simple) MIOperandInfo's.
+ TypedInit *TI = dynamic_cast<TypedInit*>(NI->first);
+ RecordRecTy *Type = dynamic_cast<RecordRecTy*>(TI->getType());
+ Record *TypeRecord = Type->getRecord();
+ bool isReg = false;
+ if (TypeRecord->isSubClassOf("RegisterOperand"))
+ TypeRecord = TypeRecord->getValueAsDef("RegClass");
+ if (TypeRecord->isSubClassOf("RegisterClass")) {
+ Decoder = "Decode" + TypeRecord->getName() + "RegisterClass";
+ isReg = true;
+ }
+
+ RecordVal *DecoderString = TypeRecord->getValue("DecoderMethod");
+ StringInit *String = DecoderString ?
+ dynamic_cast<StringInit*>(DecoderString->getValue()) : 0;
+ if (!isReg && String && String->getValue() != "")
+ Decoder = String->getValue();
+
+ OperandInfo OpInfo(Decoder);
+ unsigned Base = ~0U;
+ unsigned Width = 0;
+ unsigned Offset = 0;
+
for (unsigned bi = 0; bi < Bits.getNumBits(); ++bi) {
+ VarInit *Var = 0;
VarBitInit *BI = dynamic_cast<VarBitInit*>(Bits.getBit(bi));
- if (!BI) continue;
-
- VarInit *Var = dynamic_cast<VarInit*>(BI->getVariable());
- assert(Var);
- unsigned CurrBit = BI->getBitNum();
- if (Var->getName() != NI->second) continue;
-
- // Figure out the lowest bit of the value, and the width of the field.
- // Deliberately don't try to handle cases where the field is scattered,
- // or where not all bits of the the field are explicit.
- if (Base == ~0U && PrevBit == ~0U && PrevPos == ~0U) {
- if (CurrBit == 0)
- Base = bi;
- else
- continue;
+ if (BI)
+ Var = dynamic_cast<VarInit*>(BI->getVariable());
+ else
+ Var = dynamic_cast<VarInit*>(Bits.getBit(bi));
+
+ if (!Var) {
+ if (Base != ~0U) {
+ OpInfo.addField(Base, Width, Offset);
+ Base = ~0U;
+ Width = 0;
+ Offset = 0;
+ }
+ continue;
}
- if ((PrevPos != ~0U && bi-1 != PrevPos) ||
- (CurrBit != ~0U && CurrBit-1 != PrevBit)) {
- PrevBit = ~0;
- Base = ~0;
- PrevPos = ~0;
+ if (Var->getName() != NI->second &&
+ Var->getName() != TiedNames[NI->second]) {
+ if (Base != ~0U) {
+ OpInfo.addField(Base, Width, Offset);
+ Base = ~0U;
+ Width = 0;
+ Offset = 0;
+ }
+ continue;
}
- PrevPos = bi;
- PrevBit = CurrBit;
-
- // At this point, we can locate the field, but we need to know how to
- // interpret it. As a first step, require the target to provide callbacks
- // for decoding register classes.
- // FIXME: This need to be extended to handle instructions with custom
- // decoder methods, and operands with (simple) MIOperandInfo's.
- TypedInit *TI = dynamic_cast<TypedInit*>(NI->first);
- RecordRecTy *Type = dynamic_cast<RecordRecTy*>(TI->getType());
- Record *TypeRecord = Type->getRecord();
- bool isReg = false;
- if (TypeRecord->isSubClassOf("RegisterOperand"))
- TypeRecord = TypeRecord->getValueAsDef("RegClass");
- if (TypeRecord->isSubClassOf("RegisterClass")) {
- Decoder = "Decode" + TypeRecord->getName() + "RegisterClass";
- isReg = true;
+ if (Base == ~0U) {
+ Base = bi;
+ Width = 1;
+ Offset = BI ? BI->getBitNum() : 0;
+ } else if (BI && BI->getBitNum() != Offset + Width) {
+ OpInfo.addField(Base, Width, Offset);
+ Base = bi;
+ Width = 1;
+ Offset = BI->getBitNum();
+ } else {
+ ++Width;
}
-
- RecordVal *DecoderString = TypeRecord->getValue("DecoderMethod");
- StringInit *String = DecoderString ?
- dynamic_cast<StringInit*>(DecoderString->getValue()) :
- 0;
- if (!isReg && String && String->getValue() != "")
- Decoder = String->getValue();
}
- if (Base != ~0U) {
- InsnOperands.push_back(OperandInfo(Base, PrevBit+1, Decoder));
- DEBUG(errs() << "ENCODED OPERAND: $" << NI->second << " @ ("
- << utostr(Base+PrevBit) << ", " << utostr(Base) << ")\n");
- }
+ if (Base != ~0U)
+ OpInfo.addField(Base, Width, Offset);
+
+ if (OpInfo.numFields() > 0)
+ InsnOperands.push_back(OpInfo);
}
Operands[Opc] = InsnOperands;
@@ -1351,16 +1395,43 @@ bool FixedLenDecoderEmitter::populateInstruction(const CodeGenInstruction &CGI,
return true;
}
-void FixedLenDecoderEmitter::populateInstructions() {
- for (unsigned i = 0, e = NumberedInstructions.size(); i < e; ++i) {
- Record *R = NumberedInstructions[i]->TheDef;
- if (R->getValueAsString("Namespace") == "TargetOpcode" ||
- R->getValueAsBit("isPseudo"))
- continue;
+static void emitHelper(llvm::raw_ostream &o, unsigned BitWidth) {
+ unsigned Indentation = 0;
+ std::string WidthStr = "uint" + utostr(BitWidth) + "_t";
- if (populateInstruction(*NumberedInstructions[i], i))
- Opcodes.push_back(i);
- }
+ o << '\n';
+
+ o.indent(Indentation) << "static " << WidthStr <<
+ " fieldFromInstruction" << BitWidth <<
+ "(" << WidthStr <<" insn, unsigned startBit, unsigned numBits)\n";
+
+ o.indent(Indentation) << "{\n";
+
+ ++Indentation; ++Indentation;
+ o.indent(Indentation) << "assert(startBit + numBits <= " << BitWidth
+ << " && \"Instruction field out of bounds!\");\n";
+ o << '\n';
+ o.indent(Indentation) << WidthStr << " fieldMask;\n";
+ o << '\n';
+ o.indent(Indentation) << "if (numBits == " << BitWidth << ")\n";
+
+ ++Indentation; ++Indentation;
+ o.indent(Indentation) << "fieldMask = (" << WidthStr << ")-1;\n";
+ --Indentation; --Indentation;
+
+ o.indent(Indentation) << "else\n";
+
+ ++Indentation; ++Indentation;
+ o.indent(Indentation) << "fieldMask = ((1 << numBits) - 1) << startBit;\n";
+ --Indentation; --Indentation;
+
+ o << '\n';
+ o.indent(Indentation) << "return (insn & fieldMask) >> startBit;\n";
+ --Indentation; --Indentation;
+
+ o.indent(Indentation) << "}\n";
+
+ o << '\n';
}
// Emits disassembler code for instruction decoding.
@@ -1372,10 +1443,47 @@ void FixedLenDecoderEmitter::run(raw_ostream &o)
o << '\n';
o << "namespace llvm {\n\n";
+ // Parameterize the decoders based on namespace and instruction width.
NumberedInstructions = Target.getInstructionsByEnumValue();
- populateInstructions();
- FilterChooser FC(NumberedInstructions, Opcodes, Operands);
- FC.emitTop(o, 0);
+ std::map<std::pair<std::string, unsigned>,
+ std::vector<unsigned> > OpcMap;
+ std::map<unsigned, std::vector<OperandInfo> > Operands;
+
+ for (unsigned i = 0; i < NumberedInstructions.size(); ++i) {
+ const CodeGenInstruction *Inst = NumberedInstructions[i];
+ Record *Def = Inst->TheDef;
+ unsigned Size = Def->getValueAsInt("Size");
+ if (Def->getValueAsString("Namespace") == "TargetOpcode" ||
+ Def->getValueAsBit("isPseudo") ||
+ Def->getValueAsBit("isAsmParserOnly") ||
+ Def->getValueAsBit("isCodeGenOnly"))
+ continue;
+
+ std::string DecoderNamespace = Def->getValueAsString("DecoderNamespace");
+
+ if (Size) {
+ if (populateInstruction(*Inst, i, Operands)) {
+ OpcMap[std::make_pair(DecoderNamespace, Size)].push_back(i);
+ }
+ }
+ }
+
+ std::set<unsigned> Sizes;
+ for (std::map<std::pair<std::string, unsigned>,
+ std::vector<unsigned> >::iterator
+ I = OpcMap.begin(), E = OpcMap.end(); I != E; ++I) {
+ // If we haven't visited this instruction width before, emit the
+ // helper method to extract fields.
+ if (!Sizes.count(I->first.second)) {
+ emitHelper(o, 8*I->first.second);
+ Sizes.insert(I->first.second);
+ }
+
+ // Emit the decoder for this namespace+width combination.
+ FilterChooser FC(NumberedInstructions, I->second, Operands,
+ 8*I->first.second, this);
+ FC.emitTop(o, 0, I->first.first);
+ }
o << "\n} // End llvm namespace \n";
}
diff --git a/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.h b/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.h
index d46a495..2df5448 100644
--- a/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.h
+++ b/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.h
@@ -16,26 +16,51 @@
#define FixedLenDECODEREMITTER_H
#include "CodeGenTarget.h"
-#include "TableGenBackend.h"
+#include "llvm/TableGen/TableGenBackend.h"
#include "llvm/Support/DataTypes.h"
namespace llvm {
+struct EncodingField {
+ unsigned Base, Width, Offset;
+ EncodingField(unsigned B, unsigned W, unsigned O)
+ : Base(B), Width(W), Offset(O) { }
+};
+
struct OperandInfo {
- unsigned FieldBase;
- unsigned FieldLength;
+ std::vector<EncodingField> Fields;
std::string Decoder;
- OperandInfo(unsigned FB, unsigned FL, std::string D)
- : FieldBase(FB), FieldLength(FL), Decoder(D) { }
+ OperandInfo(std::string D)
+ : Decoder(D) { }
+
+ void addField(unsigned Base, unsigned Width, unsigned Offset) {
+ Fields.push_back(EncodingField(Base, Width, Offset));
+ }
+
+ unsigned numFields() { return Fields.size(); }
+
+ typedef std::vector<EncodingField>::iterator iterator;
+
+ iterator begin() { return Fields.begin(); }
+ iterator end() { return Fields.end(); }
};
class FixedLenDecoderEmitter : public TableGenBackend {
public:
- FixedLenDecoderEmitter(RecordKeeper &R) :
+ FixedLenDecoderEmitter(RecordKeeper &R,
+ std::string PredicateNamespace,
+ std::string GPrefix = "if (",
+ std::string GPostfix = " == MCDisassembler::Fail) return MCDisassembler::Fail;",
+ std::string ROK = "MCDisassembler::Success",
+ std::string RFail = "MCDisassembler::Fail",
+ std::string L = "") :
Records(R), Target(R),
- NumberedInstructions(Target.getInstructionsByEnumValue()) {}
+ NumberedInstructions(Target.getInstructionsByEnumValue()),
+ PredicateNamespace(PredicateNamespace),
+ GuardPrefix(GPrefix), GuardPostfix(GPostfix),
+ ReturnOK(ROK), ReturnFail(RFail), Locals(L) {}
// run - Output the code emitter
void run(raw_ostream &o);
@@ -46,9 +71,11 @@ private:
std::vector<const CodeGenInstruction*> NumberedInstructions;
std::vector<unsigned> Opcodes;
std::map<unsigned, std::vector<OperandInfo> > Operands;
-
- bool populateInstruction(const CodeGenInstruction &CGI, unsigned Opc);
- void populateInstructions();
+public:
+ std::string PredicateNamespace;
+ std::string GuardPrefix, GuardPostfix;
+ std::string ReturnOK, ReturnFail;
+ std::string Locals;
};
} // end llvm namespace
diff --git a/contrib/llvm/utils/TableGen/InstrEnumEmitter.cpp b/contrib/llvm/utils/TableGen/InstrEnumEmitter.cpp
index aa59689..5981afd 100644
--- a/contrib/llvm/utils/TableGen/InstrEnumEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/InstrEnumEmitter.cpp
@@ -14,7 +14,7 @@
#include "InstrEnumEmitter.h"
#include "CodeGenTarget.h"
-#include "Record.h"
+#include "llvm/TableGen/Record.h"
#include <cstdio>
using namespace llvm;
diff --git a/contrib/llvm/utils/TableGen/InstrEnumEmitter.h b/contrib/llvm/utils/TableGen/InstrEnumEmitter.h
index 89f8b65..c29a309 100644
--- a/contrib/llvm/utils/TableGen/InstrEnumEmitter.h
+++ b/contrib/llvm/utils/TableGen/InstrEnumEmitter.h
@@ -15,7 +15,7 @@
#ifndef INSTRENUM_EMITTER_H
#define INSTRENUM_EMITTER_H
-#include "TableGenBackend.h"
+#include "llvm/TableGen/TableGenBackend.h"
namespace llvm {
diff --git a/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp b/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp
index 5ebaf17..8341724 100644
--- a/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp
@@ -14,7 +14,7 @@
#include "InstrInfoEmitter.h"
#include "CodeGenTarget.h"
-#include "Record.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/ADT/StringExtras.h"
#include <algorithm>
using namespace llvm;
@@ -268,6 +268,7 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
<< Inst.TheDef->getName() << "\", 0";
// Emit all of the target indepedent flags...
+ if (Inst.isPseudo) OS << "|(1<<MCID::Pseudo)";
if (Inst.isReturn) OS << "|(1<<MCID::Return)";
if (Inst.isBranch) OS << "|(1<<MCID::Branch)";
if (Inst.isIndirectBranch) OS << "|(1<<MCID::IndirectBranch)";
@@ -288,6 +289,7 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
if (Inst.isNotDuplicable) OS << "|(1<<MCID::NotDuplicable)";
if (Inst.Operands.hasOptionalDef) OS << "|(1<<MCID::HasOptionalDef)";
if (Inst.usesCustomInserter) OS << "|(1<<MCID::UsesCustomInserter)";
+ if (Inst.hasPostISelHook) OS << "|(1<<MCID::HasPostISelHook)";
if (Inst.Operands.isVariadic)OS << "|(1<<MCID::Variadic)";
if (Inst.hasSideEffects) OS << "|(1<<MCID::UnmodeledSideEffects)";
if (Inst.isAsCheapAsAMove) OS << "|(1<<MCID::CheapAsAMove)";
diff --git a/contrib/llvm/utils/TableGen/InstrInfoEmitter.h b/contrib/llvm/utils/TableGen/InstrInfoEmitter.h
index 165ce42..1461e2c 100644
--- a/contrib/llvm/utils/TableGen/InstrInfoEmitter.h
+++ b/contrib/llvm/utils/TableGen/InstrInfoEmitter.h
@@ -15,8 +15,8 @@
#ifndef INSTRINFO_EMITTER_H
#define INSTRINFO_EMITTER_H
-#include "TableGenBackend.h"
#include "CodeGenDAGPatterns.h"
+#include "llvm/TableGen/TableGenBackend.h"
#include <vector>
#include <map>
diff --git a/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp b/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp
index e5e7cea..782b89e 100644
--- a/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp
@@ -13,8 +13,8 @@
#include "CodeGenTarget.h"
#include "IntrinsicEmitter.h"
-#include "Record.h"
#include "StringMatcher.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/ADT/StringExtras.h"
#include <algorithm>
using namespace llvm;
diff --git a/contrib/llvm/utils/TableGen/IntrinsicEmitter.h b/contrib/llvm/utils/TableGen/IntrinsicEmitter.h
index b1efecb..eb6379c 100644
--- a/contrib/llvm/utils/TableGen/IntrinsicEmitter.h
+++ b/contrib/llvm/utils/TableGen/IntrinsicEmitter.h
@@ -15,7 +15,7 @@
#define INTRINSIC_EMITTER_H
#include "CodeGenIntrinsics.h"
-#include "TableGenBackend.h"
+#include "llvm/TableGen/TableGenBackend.h"
namespace llvm {
class IntrinsicEmitter : public TableGenBackend {
diff --git a/contrib/llvm/utils/TableGen/LLVMCConfigurationEmitter.cpp b/contrib/llvm/utils/TableGen/LLVMCConfigurationEmitter.cpp
deleted file mode 100644
index cd0cbeb..0000000
--- a/contrib/llvm/utils/TableGen/LLVMCConfigurationEmitter.cpp
+++ /dev/null
@@ -1,3134 +0,0 @@
-//===- LLVMCConfigurationEmitter.cpp - Generate LLVMC config ----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open
-// Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This tablegen backend is responsible for emitting LLVMC configuration code.
-//
-//===----------------------------------------------------------------------===//
-
-#include "LLVMCConfigurationEmitter.h"
-#include "Record.h"
-
-#include "llvm/ADT/IntrusiveRefCntPtr.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/StringSet.h"
-
-#include <algorithm>
-#include <cassert>
-#include <functional>
-#include <stdexcept>
-#include <string>
-#include <typeinfo>
-
-
-using namespace llvm;
-
-namespace {
-
-//===----------------------------------------------------------------------===//
-/// Typedefs
-
-typedef std::vector<Record*> RecordVector;
-typedef std::vector<const DagInit*> DagVector;
-typedef std::vector<std::string> StrVector;
-
-//===----------------------------------------------------------------------===//
-/// Constants
-
-// Indentation.
-const unsigned TabWidth = 4;
-const unsigned Indent1 = TabWidth*1;
-const unsigned Indent2 = TabWidth*2;
-const unsigned Indent3 = TabWidth*3;
-const unsigned Indent4 = TabWidth*4;
-
-// Default help string.
-const char * const DefaultHelpString = "NO HELP MESSAGE PROVIDED";
-
-// Name for the "sink" option.
-const char * const SinkOptionName = "SinkOption";
-
-//===----------------------------------------------------------------------===//
-/// Helper functions
-
-/// Id - An 'identity' function object.
-struct Id {
- template<typename T0>
- void operator()(const T0&) const {
- }
- template<typename T0, typename T1>
- void operator()(const T0&, const T1&) const {
- }
- template<typename T0, typename T1, typename T2>
- void operator()(const T0&, const T1&, const T2&) const {
- }
-};
-
-int InitPtrToInt(const Init* ptr) {
- const IntInit& val = dynamic_cast<const IntInit&>(*ptr);
- return val.getValue();
-}
-
-bool InitPtrToBool(const Init* ptr) {
- bool ret = false;
- const DefInit& val = dynamic_cast<const DefInit&>(*ptr);
- const std::string& str = val.getAsString();
-
- if (str == "true") {
- ret = true;
- }
- else if (str == "false") {
- ret = false;
- }
- else {
- throw "Incorrect boolean value: '" + str +
- "': must be either 'true' or 'false'";
- }
-
- return ret;
-}
-
-const std::string& InitPtrToString(const Init* ptr) {
- const StringInit& val = dynamic_cast<const StringInit&>(*ptr);
- return val.getValue();
-}
-
-const ListInit& InitPtrToList(const Init* ptr) {
- const ListInit& val = dynamic_cast<const ListInit&>(*ptr);
- return val;
-}
-
-const DagInit& InitPtrToDag(const Init* ptr) {
- const DagInit& val = dynamic_cast<const DagInit&>(*ptr);
- return val;
-}
-
-const std::string GetOperatorName(const DagInit& D) {
- return D.getOperator()->getAsString();
-}
-
-/// CheckBooleanConstant - Check that the provided value is a boolean constant.
-void CheckBooleanConstant(const Init* I) {
- InitPtrToBool(I);
-}
-
-// CheckNumberOfArguments - Ensure that the number of args in d is
-// greater than or equal to min_arguments, otherwise throw an exception.
-void CheckNumberOfArguments (const DagInit& d, unsigned minArgs) {
- if (d.getNumArgs() < minArgs)
- throw GetOperatorName(d) + ": too few arguments!";
-}
-
-// EscapeVariableName - Escape commas and other symbols not allowed
-// in the C++ variable names. Makes it possible to use options named
-// like "Wa," (useful for prefix options).
-std::string EscapeVariableName (const std::string& Var) {
- std::string ret;
- for (unsigned i = 0; i != Var.size(); ++i) {
- char cur_char = Var[i];
- if (cur_char == ',') {
- ret += "_comma_";
- }
- else if (cur_char == '+') {
- ret += "_plus_";
- }
- else if (cur_char == '-') {
- ret += "_dash_";
- }
- else {
- ret.push_back(cur_char);
- }
- }
- return ret;
-}
-
-/// EscapeQuotes - Replace '"' with '\"'.
-std::string EscapeQuotes (const std::string& Var) {
- std::string ret;
- for (unsigned i = 0; i != Var.size(); ++i) {
- char cur_char = Var[i];
- if (cur_char == '"') {
- ret += "\\\"";
- }
- else {
- ret.push_back(cur_char);
- }
- }
- return ret;
-}
-
-/// OneOf - Does the input string contain this character?
-bool OneOf(const char* lst, char c) {
- while (*lst) {
- if (*lst++ == c)
- return true;
- }
- return false;
-}
-
-template <class I, class S>
-void CheckedIncrement(I& P, I E, S ErrorString) {
- ++P;
- if (P == E)
- throw ErrorString;
-}
-
-//===----------------------------------------------------------------------===//
-/// Back-end specific code
-
-
-/// OptionType - One of six different option types. See the
-/// documentation for detailed description of differences.
-namespace OptionType {
-
- enum OptionType { Alias, Switch, SwitchList,
- Parameter, ParameterList, Prefix, PrefixList };
-
- bool IsAlias(OptionType t) {
- return (t == Alias);
- }
-
- bool IsList (OptionType t) {
- return (t == SwitchList || t == ParameterList || t == PrefixList);
- }
-
- bool IsSwitch (OptionType t) {
- return (t == Switch);
- }
-
- bool IsSwitchList (OptionType t) {
- return (t == SwitchList);
- }
-
- bool IsParameter (OptionType t) {
- return (t == Parameter || t == Prefix);
- }
-
-}
-
-OptionType::OptionType stringToOptionType(const std::string& T) {
- if (T == "alias_option")
- return OptionType::Alias;
- else if (T == "switch_option")
- return OptionType::Switch;
- else if (T == "switch_list_option")
- return OptionType::SwitchList;
- else if (T == "parameter_option")
- return OptionType::Parameter;
- else if (T == "parameter_list_option")
- return OptionType::ParameterList;
- else if (T == "prefix_option")
- return OptionType::Prefix;
- else if (T == "prefix_list_option")
- return OptionType::PrefixList;
- else
- throw "Unknown option type: " + T + '!';
-}
-
-namespace OptionDescriptionFlags {
- enum OptionDescriptionFlags { Required = 0x1, Hidden = 0x2,
- ReallyHidden = 0x4, OneOrMore = 0x8,
- Optional = 0x10, CommaSeparated = 0x20,
- ForwardNotSplit = 0x40, ZeroOrMore = 0x80 };
-}
-
-/// OptionDescription - Represents data contained in a single
-/// OptionList entry.
-struct OptionDescription {
- OptionType::OptionType Type;
- std::string Name;
- unsigned Flags;
- std::string Help;
- unsigned MultiVal;
- Init* InitVal;
-
- OptionDescription(OptionType::OptionType t = OptionType::Switch,
- const std::string& n = "",
- const std::string& h = DefaultHelpString)
- : Type(t), Name(n), Flags(0x0), Help(h), MultiVal(1), InitVal(0)
- {}
-
- /// GenTypeDeclaration - Returns the C++ variable type of this
- /// option.
- const char* GenTypeDeclaration() const;
-
- /// GenVariableName - Returns the variable name used in the
- /// generated C++ code.
- std::string GenVariableName() const
- { return "autogenerated::" + GenOptionType() + EscapeVariableName(Name); }
-
- /// GenPlainVariableName - Returns the variable name without the namespace
- /// prefix.
- std::string GenPlainVariableName() const
- { return GenOptionType() + EscapeVariableName(Name); }
-
- /// Merge - Merge two option descriptions.
- void Merge (const OptionDescription& other);
-
- /// CheckConsistency - Check that the flags are consistent.
- void CheckConsistency() const;
-
- // Misc convenient getters/setters.
-
- bool isAlias() const;
-
- bool isMultiVal() const;
-
- bool isCommaSeparated() const;
- void setCommaSeparated();
-
- bool isForwardNotSplit() const;
- void setForwardNotSplit();
-
- bool isRequired() const;
- void setRequired();
-
- bool isOneOrMore() const;
- void setOneOrMore();
-
- bool isZeroOrMore() const;
- void setZeroOrMore();
-
- bool isOptional() const;
- void setOptional();
-
- bool isHidden() const;
- void setHidden();
-
- bool isReallyHidden() const;
- void setReallyHidden();
-
- bool isSwitch() const
- { return OptionType::IsSwitch(this->Type); }
-
- bool isSwitchList() const
- { return OptionType::IsSwitchList(this->Type); }
-
- bool isParameter() const
- { return OptionType::IsParameter(this->Type); }
-
- bool isList() const
- { return OptionType::IsList(this->Type); }
-
- bool isParameterList() const
- { return (OptionType::IsList(this->Type)
- && !OptionType::IsSwitchList(this->Type)); }
-
-private:
-
- // GenOptionType - Helper function used by GenVariableName().
- std::string GenOptionType() const;
-};
-
-void OptionDescription::CheckConsistency() const {
- unsigned i = 0;
-
- i += this->isRequired();
- i += this->isOptional();
- i += this->isOneOrMore();
- i += this->isZeroOrMore();
-
- if (i > 1) {
- throw "Only one of (required), (optional), (one_or_more) or "
- "(zero_or_more) properties is allowed!";
- }
-}
-
-void OptionDescription::Merge (const OptionDescription& other)
-{
- if (other.Type != Type)
- throw "Conflicting definitions for the option " + Name + "!";
-
- if (Help == other.Help || Help == DefaultHelpString)
- Help = other.Help;
- else if (other.Help != DefaultHelpString) {
- llvm::errs() << "Warning: several different help strings"
- " defined for option " + Name + "\n";
- }
-
- Flags |= other.Flags;
-}
-
-bool OptionDescription::isAlias() const {
- return OptionType::IsAlias(this->Type);
-}
-
-bool OptionDescription::isMultiVal() const {
- return MultiVal > 1;
-}
-
-bool OptionDescription::isCommaSeparated() const {
- return Flags & OptionDescriptionFlags::CommaSeparated;
-}
-void OptionDescription::setCommaSeparated() {
- Flags |= OptionDescriptionFlags::CommaSeparated;
-}
-
-bool OptionDescription::isForwardNotSplit() const {
- return Flags & OptionDescriptionFlags::ForwardNotSplit;
-}
-void OptionDescription::setForwardNotSplit() {
- Flags |= OptionDescriptionFlags::ForwardNotSplit;
-}
-
-bool OptionDescription::isRequired() const {
- return Flags & OptionDescriptionFlags::Required;
-}
-void OptionDescription::setRequired() {
- Flags |= OptionDescriptionFlags::Required;
-}
-
-bool OptionDescription::isOneOrMore() const {
- return Flags & OptionDescriptionFlags::OneOrMore;
-}
-void OptionDescription::setOneOrMore() {
- Flags |= OptionDescriptionFlags::OneOrMore;
-}
-
-bool OptionDescription::isZeroOrMore() const {
- return Flags & OptionDescriptionFlags::ZeroOrMore;
-}
-void OptionDescription::setZeroOrMore() {
- Flags |= OptionDescriptionFlags::ZeroOrMore;
-}
-
-bool OptionDescription::isOptional() const {
- return Flags & OptionDescriptionFlags::Optional;
-}
-void OptionDescription::setOptional() {
- Flags |= OptionDescriptionFlags::Optional;
-}
-
-bool OptionDescription::isHidden() const {
- return Flags & OptionDescriptionFlags::Hidden;
-}
-void OptionDescription::setHidden() {
- Flags |= OptionDescriptionFlags::Hidden;
-}
-
-bool OptionDescription::isReallyHidden() const {
- return Flags & OptionDescriptionFlags::ReallyHidden;
-}
-void OptionDescription::setReallyHidden() {
- Flags |= OptionDescriptionFlags::ReallyHidden;
-}
-
-const char* OptionDescription::GenTypeDeclaration() const {
- switch (Type) {
- case OptionType::Alias:
- return "cl::alias";
- case OptionType::PrefixList:
- case OptionType::ParameterList:
- return "cl::list<std::string>";
- case OptionType::Switch:
- return "cl::opt<bool>";
- case OptionType::SwitchList:
- return "cl::list<bool>";
- case OptionType::Parameter:
- case OptionType::Prefix:
- default:
- return "cl::opt<std::string>";
- }
-}
-
-std::string OptionDescription::GenOptionType() const {
- switch (Type) {
- case OptionType::Alias:
- return "Alias_";
- case OptionType::PrefixList:
- case OptionType::ParameterList:
- return "List_";
- case OptionType::Switch:
- return "Switch_";
- case OptionType::SwitchList:
- return "SwitchList_";
- case OptionType::Prefix:
- case OptionType::Parameter:
- default:
- return "Parameter_";
- }
-}
-
-/// OptionDescriptions - An OptionDescription array plus some helper
-/// functions.
-class OptionDescriptions {
- typedef StringMap<OptionDescription> container_type;
-
- /// Descriptions - A list of OptionDescriptions.
- container_type Descriptions;
-
-public:
- /// FindOption - exception-throwing wrapper for find().
- const OptionDescription& FindOption(const std::string& OptName) const;
-
- // Wrappers for FindOption that throw an exception in case the option has a
- // wrong type.
- const OptionDescription& FindSwitch(const std::string& OptName) const;
- const OptionDescription& FindParameter(const std::string& OptName) const;
- const OptionDescription& FindParameterList(const std::string& OptName) const;
- const OptionDescription&
- FindListOrParameter(const std::string& OptName) const;
- const OptionDescription&
- FindParameterListOrParameter(const std::string& OptName) const;
-
- /// insertDescription - Insert new OptionDescription into
- /// OptionDescriptions list
- void InsertDescription (const OptionDescription& o);
-
- // Support for STL-style iteration
- typedef container_type::const_iterator const_iterator;
- const_iterator begin() const { return Descriptions.begin(); }
- const_iterator end() const { return Descriptions.end(); }
-};
-
-const OptionDescription&
-OptionDescriptions::FindOption(const std::string& OptName) const {
- const_iterator I = Descriptions.find(OptName);
- if (I != Descriptions.end())
- return I->second;
- else
- throw OptName + ": no such option!";
-}
-
-const OptionDescription&
-OptionDescriptions::FindSwitch(const std::string& OptName) const {
- const OptionDescription& OptDesc = this->FindOption(OptName);
- if (!OptDesc.isSwitch())
- throw OptName + ": incorrect option type - should be a switch!";
- return OptDesc;
-}
-
-const OptionDescription&
-OptionDescriptions::FindParameterList(const std::string& OptName) const {
- const OptionDescription& OptDesc = this->FindOption(OptName);
- if (!OptDesc.isList() || OptDesc.isSwitchList())
- throw OptName + ": incorrect option type - should be a parameter list!";
- return OptDesc;
-}
-
-const OptionDescription&
-OptionDescriptions::FindParameter(const std::string& OptName) const {
- const OptionDescription& OptDesc = this->FindOption(OptName);
- if (!OptDesc.isParameter())
- throw OptName + ": incorrect option type - should be a parameter!";
- return OptDesc;
-}
-
-const OptionDescription&
-OptionDescriptions::FindListOrParameter(const std::string& OptName) const {
- const OptionDescription& OptDesc = this->FindOption(OptName);
- if (!OptDesc.isList() && !OptDesc.isParameter())
- throw OptName
- + ": incorrect option type - should be a list or parameter!";
- return OptDesc;
-}
-
-const OptionDescription&
-OptionDescriptions::FindParameterListOrParameter
-(const std::string& OptName) const {
- const OptionDescription& OptDesc = this->FindOption(OptName);
- if ((!OptDesc.isList() && !OptDesc.isParameter()) || OptDesc.isSwitchList())
- throw OptName
- + ": incorrect option type - should be a parameter list or parameter!";
- return OptDesc;
-}
-
-void OptionDescriptions::InsertDescription (const OptionDescription& o) {
- container_type::iterator I = Descriptions.find(o.Name);
- if (I != Descriptions.end()) {
- OptionDescription& D = I->second;
- D.Merge(o);
- }
- else {
- Descriptions[o.Name] = o;
- }
-}
-
-/// HandlerTable - A base class for function objects implemented as
-/// 'tables of handlers'.
-template <typename Handler>
-class HandlerTable {
-protected:
- // Implementation details.
-
- /// HandlerMap - A map from property names to property handlers
- typedef StringMap<Handler> HandlerMap;
-
- static HandlerMap Handlers_;
- static bool staticMembersInitialized_;
-
-public:
-
- Handler GetHandler (const std::string& HandlerName) const {
- typename HandlerMap::iterator method = Handlers_.find(HandlerName);
-
- if (method != Handlers_.end()) {
- Handler h = method->second;
- return h;
- }
- else {
- throw "No handler found for property " + HandlerName + "!";
- }
- }
-
- void AddHandler(const char* Property, Handler H) {
- Handlers_[Property] = H;
- }
-
-};
-
-template <class Handler, class FunctionObject>
-Handler GetHandler(FunctionObject* Obj, const DagInit& Dag) {
- const std::string& HandlerName = GetOperatorName(Dag);
- return Obj->GetHandler(HandlerName);
-}
-
-template <class FunctionObject>
-void InvokeDagInitHandler(FunctionObject* Obj, Init* I) {
- typedef void (FunctionObject::*Handler) (const DagInit&);
-
- const DagInit& Dag = InitPtrToDag(I);
- Handler h = GetHandler<Handler>(Obj, Dag);
-
- ((Obj)->*(h))(Dag);
-}
-
-template <class FunctionObject>
-void InvokeDagInitHandler(const FunctionObject* const Obj,
- const Init* I, unsigned IndentLevel, raw_ostream& O)
-{
- typedef void (FunctionObject::*Handler)
- (const DagInit&, unsigned IndentLevel, raw_ostream& O) const;
-
- const DagInit& Dag = InitPtrToDag(I);
- Handler h = GetHandler<Handler>(Obj, Dag);
-
- ((Obj)->*(h))(Dag, IndentLevel, O);
-}
-
-template <typename H>
-typename HandlerTable<H>::HandlerMap HandlerTable<H>::Handlers_;
-
-template <typename H>
-bool HandlerTable<H>::staticMembersInitialized_ = false;
-
-
-/// CollectOptionProperties - Function object for iterating over an
-/// option property list.
-class CollectOptionProperties;
-typedef void (CollectOptionProperties::* CollectOptionPropertiesHandler)
-(const DagInit&);
-
-class CollectOptionProperties
-: public HandlerTable<CollectOptionPropertiesHandler>
-{
-private:
-
- /// optDescs_ - OptionDescriptions table. This is where the
- /// information is stored.
- OptionDescription& optDesc_;
-
-public:
-
- explicit CollectOptionProperties(OptionDescription& OD)
- : optDesc_(OD)
- {
- if (!staticMembersInitialized_) {
- AddHandler("help", &CollectOptionProperties::onHelp);
- AddHandler("hidden", &CollectOptionProperties::onHidden);
- AddHandler("init", &CollectOptionProperties::onInit);
- AddHandler("multi_val", &CollectOptionProperties::onMultiVal);
- AddHandler("one_or_more", &CollectOptionProperties::onOneOrMore);
- AddHandler("zero_or_more", &CollectOptionProperties::onZeroOrMore);
- AddHandler("really_hidden", &CollectOptionProperties::onReallyHidden);
- AddHandler("required", &CollectOptionProperties::onRequired);
- AddHandler("optional", &CollectOptionProperties::onOptional);
- AddHandler("comma_separated", &CollectOptionProperties::onCommaSeparated);
- AddHandler("forward_not_split",
- &CollectOptionProperties::onForwardNotSplit);
-
- staticMembersInitialized_ = true;
- }
- }
-
- /// operator() - Just forwards to the corresponding property
- /// handler.
- void operator() (Init* I) {
- InvokeDagInitHandler(this, I);
- }
-
-private:
-
- /// Option property handlers --
- /// Methods that handle option properties such as (help) or (hidden).
-
- void onHelp (const DagInit& d) {
- CheckNumberOfArguments(d, 1);
- optDesc_.Help = EscapeQuotes(InitPtrToString(d.getArg(0)));
- }
-
- void onHidden (const DagInit& d) {
- CheckNumberOfArguments(d, 0);
- optDesc_.setHidden();
- }
-
- void onReallyHidden (const DagInit& d) {
- CheckNumberOfArguments(d, 0);
- optDesc_.setReallyHidden();
- }
-
- void onCommaSeparated (const DagInit& d) {
- CheckNumberOfArguments(d, 0);
- if (!optDesc_.isParameterList())
- throw "'comma_separated' is valid only on parameter list options!";
- optDesc_.setCommaSeparated();
- }
-
- void onForwardNotSplit (const DagInit& d) {
- CheckNumberOfArguments(d, 0);
- if (!optDesc_.isParameter())
- throw "'forward_not_split' is valid only for parameter options!";
- optDesc_.setForwardNotSplit();
- }
-
- void onRequired (const DagInit& d) {
- CheckNumberOfArguments(d, 0);
-
- optDesc_.setRequired();
- optDesc_.CheckConsistency();
- }
-
- void onInit (const DagInit& d) {
- CheckNumberOfArguments(d, 1);
- Init* i = d.getArg(0);
- const std::string& str = i->getAsString();
-
- bool correct = optDesc_.isParameter() && dynamic_cast<StringInit*>(i);
- correct |= (optDesc_.isSwitch() && (str == "true" || str == "false"));
-
- if (!correct)
- throw "Incorrect usage of the 'init' option property!";
-
- optDesc_.InitVal = i;
- }
-
- void onOneOrMore (const DagInit& d) {
- CheckNumberOfArguments(d, 0);
-
- optDesc_.setOneOrMore();
- optDesc_.CheckConsistency();
- }
-
- void onZeroOrMore (const DagInit& d) {
- CheckNumberOfArguments(d, 0);
-
- if (optDesc_.isList())
- llvm::errs() << "Warning: specifying the 'zero_or_more' property "
- "on a list option has no effect.\n";
-
- optDesc_.setZeroOrMore();
- optDesc_.CheckConsistency();
- }
-
- void onOptional (const DagInit& d) {
- CheckNumberOfArguments(d, 0);
-
- if (!optDesc_.isList())
- llvm::errs() << "Warning: specifying the 'optional' property"
- "on a non-list option has no effect.\n";
-
- optDesc_.setOptional();
- optDesc_.CheckConsistency();
- }
-
- void onMultiVal (const DagInit& d) {
- CheckNumberOfArguments(d, 1);
- int val = InitPtrToInt(d.getArg(0));
- if (val < 2)
- throw "Error in the 'multi_val' property: "
- "the value must be greater than 1!";
- if (!optDesc_.isParameterList())
- throw "The multi_val property is valid only on list options!";
- optDesc_.MultiVal = val;
- }
-
-};
-
-/// AddOption - A function object that is applied to every option
-/// description. Used by CollectOptionDescriptions.
-class AddOption {
-private:
- OptionDescriptions& OptDescs_;
-
-public:
- explicit AddOption(OptionDescriptions& OD) : OptDescs_(OD)
- {}
-
- void operator()(const Init* i) {
- const DagInit& d = InitPtrToDag(i);
- CheckNumberOfArguments(d, 1);
-
- const OptionType::OptionType Type =
- stringToOptionType(GetOperatorName(d));
- const std::string& Name = InitPtrToString(d.getArg(0));
-
- OptionDescription OD(Type, Name);
-
- CheckNumberOfArguments(d, 2);
-
- // Alias option store the aliased option name in the 'Help' field and do not
- // have any properties.
- if (OD.isAlias()) {
- OD.Help = InitPtrToString(d.getArg(1));
- }
- else {
- processOptionProperties(d, OD);
- }
-
- // Switch options are ZeroOrMore by default.
- if (OD.isSwitch()) {
- if (!(OD.isOptional() || OD.isOneOrMore() || OD.isRequired()))
- OD.setZeroOrMore();
- }
-
- OptDescs_.InsertDescription(OD);
- }
-
-private:
- /// processOptionProperties - Go through the list of option
- /// properties and call a corresponding handler for each.
- static void processOptionProperties (const DagInit& d, OptionDescription& o) {
- CheckNumberOfArguments(d, 2);
- DagInit::const_arg_iterator B = d.arg_begin();
- // Skip the first argument: it's always the option name.
- ++B;
- std::for_each(B, d.arg_end(), CollectOptionProperties(o));
- }
-
-};
-
-/// CollectOptionDescriptions - Collects option properties from all
-/// OptionLists.
-void CollectOptionDescriptions (const RecordVector& V,
- OptionDescriptions& OptDescs)
-{
- // For every OptionList:
- for (RecordVector::const_iterator B = V.begin(), E = V.end(); B!=E; ++B)
- {
- // Throws an exception if the value does not exist.
- ListInit* PropList = (*B)->getValueAsListInit("options");
-
- // For every option description in this list: invoke AddOption.
- std::for_each(PropList->begin(), PropList->end(), AddOption(OptDescs));
- }
-}
-
-// Tool information record
-
-namespace ToolFlags {
- enum ToolFlags { Join = 0x1, Sink = 0x2 };
-}
-
-struct ToolDescription : public RefCountedBase<ToolDescription> {
- std::string Name;
- Init* CmdLine;
- Init* Actions;
- StrVector InLanguage;
- std::string InFileOption;
- std::string OutFileOption;
- StrVector OutLanguage;
- std::string OutputSuffix;
- unsigned Flags;
- const Init* OnEmpty;
-
- // Various boolean properties
- void setSink() { Flags |= ToolFlags::Sink; }
- bool isSink() const { return Flags & ToolFlags::Sink; }
- void setJoin() { Flags |= ToolFlags::Join; }
- bool isJoin() const { return Flags & ToolFlags::Join; }
-
- // Default ctor here is needed because StringMap can only store
- // DefaultConstructible objects
- ToolDescription (const std::string &n = "")
- : Name(n), CmdLine(0), Actions(0), OutFileOption("-o"),
- Flags(0), OnEmpty(0)
- {}
-};
-
-/// ToolDescriptions - A list of Tool information records.
-typedef std::vector<IntrusiveRefCntPtr<ToolDescription> > ToolDescriptions;
-
-
-/// CollectToolProperties - Function object for iterating over a list of
-/// tool property records.
-
-class CollectToolProperties;
-typedef void (CollectToolProperties::* CollectToolPropertiesHandler)
-(const DagInit&);
-
-class CollectToolProperties : public HandlerTable<CollectToolPropertiesHandler>
-{
-private:
-
- /// toolDesc_ - Properties of the current Tool. This is where the
- /// information is stored.
- ToolDescription& toolDesc_;
-
-public:
-
- explicit CollectToolProperties (ToolDescription& d)
- : toolDesc_(d)
- {
- if (!staticMembersInitialized_) {
-
- AddHandler("actions", &CollectToolProperties::onActions);
- AddHandler("command", &CollectToolProperties::onCommand);
- AddHandler("in_language", &CollectToolProperties::onInLanguage);
- AddHandler("join", &CollectToolProperties::onJoin);
- AddHandler("out_language", &CollectToolProperties::onOutLanguage);
-
- AddHandler("out_file_option", &CollectToolProperties::onOutFileOption);
- AddHandler("in_file_option", &CollectToolProperties::onInFileOption);
-
- AddHandler("output_suffix", &CollectToolProperties::onOutputSuffix);
- AddHandler("sink", &CollectToolProperties::onSink);
- AddHandler("works_on_empty", &CollectToolProperties::onWorksOnEmpty);
-
- staticMembersInitialized_ = true;
- }
- }
-
- void operator() (Init* I) {
- InvokeDagInitHandler(this, I);
- }
-
-private:
-
- /// Property handlers --
- /// Functions that extract information about tool properties from
- /// DAG representation.
-
- void onActions (const DagInit& d) {
- CheckNumberOfArguments(d, 1);
- Init* Case = d.getArg(0);
- if (typeid(*Case) != typeid(DagInit) ||
- GetOperatorName(static_cast<DagInit&>(*Case)) != "case")
- throw "The argument to (actions) should be a 'case' construct!";
- toolDesc_.Actions = Case;
- }
-
- void onCommand (const DagInit& d) {
- CheckNumberOfArguments(d, 1);
- toolDesc_.CmdLine = d.getArg(0);
- }
-
- /// onInOutLanguage - Common implementation of on{In,Out}Language().
- void onInOutLanguage (const DagInit& d, StrVector& OutVec) {
- CheckNumberOfArguments(d, 1);
-
- // Copy strings to the output vector.
- for (unsigned i = 0, NumArgs = d.getNumArgs(); i < NumArgs; ++i) {
- OutVec.push_back(InitPtrToString(d.getArg(i)));
- }
-
- // Remove duplicates.
- std::sort(OutVec.begin(), OutVec.end());
- StrVector::iterator newE = std::unique(OutVec.begin(), OutVec.end());
- OutVec.erase(newE, OutVec.end());
- }
-
-
- void onInLanguage (const DagInit& d) {
- this->onInOutLanguage(d, toolDesc_.InLanguage);
- }
-
- void onJoin (const DagInit& d) {
- bool isReallyJoin = false;
-
- if (d.getNumArgs() == 0) {
- isReallyJoin = true;
- }
- else {
- Init* I = d.getArg(0);
- isReallyJoin = InitPtrToBool(I);
- }
-
- // Is this *really* a join tool? We allow (join false) for generating two
- // tool descriptions from a single generic one.
- // TOFIX: come up with a cleaner solution.
- if (isReallyJoin) {
- toolDesc_.setJoin();
- }
- }
-
- void onOutLanguage (const DagInit& d) {
- this->onInOutLanguage(d, toolDesc_.OutLanguage);
- }
-
- void onOutFileOption (const DagInit& d) {
- CheckNumberOfArguments(d, 1);
- toolDesc_.OutFileOption = InitPtrToString(d.getArg(0));
- }
-
- void onInFileOption (const DagInit& d) {
- CheckNumberOfArguments(d, 1);
- toolDesc_.InFileOption = InitPtrToString(d.getArg(0));
- }
-
- void onOutputSuffix (const DagInit& d) {
- CheckNumberOfArguments(d, 1);
- toolDesc_.OutputSuffix = InitPtrToString(d.getArg(0));
- }
-
- void onSink (const DagInit& d) {
- CheckNumberOfArguments(d, 0);
- toolDesc_.setSink();
- }
-
- void onWorksOnEmpty (const DagInit& d) {
- toolDesc_.OnEmpty = d.getArg(0);
- }
-
-};
-
-/// CollectToolDescriptions - Gather information about tool properties
-/// from the parsed TableGen data (basically a wrapper for the
-/// CollectToolProperties function object).
-void CollectToolDescriptions (const RecordVector& Tools,
- ToolDescriptions& ToolDescs)
-{
- // Iterate over a properties list of every Tool definition
- for (RecordVector::const_iterator B = Tools.begin(),
- E = Tools.end(); B!=E; ++B) {
- const Record* T = *B;
- // Throws an exception if the value does not exist.
- ListInit* PropList = T->getValueAsListInit("properties");
-
- IntrusiveRefCntPtr<ToolDescription>
- ToolDesc(new ToolDescription(T->getName()));
-
- std::for_each(PropList->begin(), PropList->end(),
- CollectToolProperties(*ToolDesc));
- ToolDescs.push_back(ToolDesc);
- }
-}
-
-/// FillInEdgeVector - Merge all compilation graph definitions into
-/// one single edge list.
-void FillInEdgeVector(const RecordVector& CompilationGraphs,
- DagVector& Out) {
- for (RecordVector::const_iterator B = CompilationGraphs.begin(),
- E = CompilationGraphs.end(); B != E; ++B) {
- const ListInit* Edges = (*B)->getValueAsListInit("edges");
-
- for (ListInit::const_iterator B = Edges->begin(),
- E = Edges->end(); B != E; ++B) {
- Out.push_back(&InitPtrToDag(*B));
- }
- }
-}
-
-/// NotInGraph - Helper function object for FilterNotInGraph.
-struct NotInGraph {
-private:
- const llvm::StringSet<>& ToolsInGraph_;
-
-public:
- NotInGraph(const llvm::StringSet<>& ToolsInGraph)
- : ToolsInGraph_(ToolsInGraph)
- {}
-
- bool operator()(const IntrusiveRefCntPtr<ToolDescription>& x) {
- return (ToolsInGraph_.count(x->Name) == 0);
- }
-};
-
-/// FilterNotInGraph - Filter out from ToolDescs all Tools not
-/// mentioned in the compilation graph definition.
-void FilterNotInGraph (const DagVector& EdgeVector,
- ToolDescriptions& ToolDescs) {
-
- // List all tools mentioned in the graph.
- llvm::StringSet<> ToolsInGraph;
-
- for (DagVector::const_iterator B = EdgeVector.begin(),
- E = EdgeVector.end(); B != E; ++B) {
-
- const DagInit* Edge = *B;
- const std::string& NodeA = InitPtrToString(Edge->getArg(0));
- const std::string& NodeB = InitPtrToString(Edge->getArg(1));
-
- if (NodeA != "root")
- ToolsInGraph.insert(NodeA);
- ToolsInGraph.insert(NodeB);
- }
-
- // Filter ToolPropertiesList.
- ToolDescriptions::iterator new_end =
- std::remove_if(ToolDescs.begin(), ToolDescs.end(),
- NotInGraph(ToolsInGraph));
- ToolDescs.erase(new_end, ToolDescs.end());
-}
-
-/// FillInToolToLang - Fills in two tables that map tool names to
-/// input & output language names. Helper function used by TypecheckGraph().
-void FillInToolToLang (const ToolDescriptions& ToolDescs,
- StringMap<StringSet<> >& ToolToInLang,
- StringMap<StringSet<> >& ToolToOutLang) {
- for (ToolDescriptions::const_iterator B = ToolDescs.begin(),
- E = ToolDescs.end(); B != E; ++B) {
- const ToolDescription& D = *(*B);
- for (StrVector::const_iterator B = D.InLanguage.begin(),
- E = D.InLanguage.end(); B != E; ++B)
- ToolToInLang[D.Name].insert(*B);
- for (StrVector::const_iterator B = D.OutLanguage.begin(),
- E = D.OutLanguage.end(); B != E; ++B)
- ToolToOutLang[D.Name].insert(*B);
- }
-}
-
-/// Intersect - Is set intersection non-empty?
-bool Intersect (const StringSet<>& S1, const StringSet<>& S2) {
- for (StringSet<>::const_iterator B = S1.begin(), E = S1.end(); B != E; ++B) {
- if (S2.count(B->first()) != 0)
- return true;
- }
- return false;
-}
-
-/// TypecheckGraph - Check that names for output and input languages
-/// on all edges do match.
-void TypecheckGraph (const DagVector& EdgeVector,
- const ToolDescriptions& ToolDescs) {
- StringMap<StringSet<> > ToolToInLang;
- StringMap<StringSet<> > ToolToOutLang;
-
- FillInToolToLang(ToolDescs, ToolToInLang, ToolToOutLang);
-
- for (DagVector::const_iterator B = EdgeVector.begin(),
- E = EdgeVector.end(); B != E; ++B) {
- const DagInit* Edge = *B;
- const std::string& NodeA = InitPtrToString(Edge->getArg(0));
- const std::string& NodeB = InitPtrToString(Edge->getArg(1));
- StringMap<StringSet<> >::iterator IA = ToolToOutLang.find(NodeA);
- StringMap<StringSet<> >::iterator IB = ToolToInLang.find(NodeB);
-
- if (NodeB == "root")
- throw "Edges back to the root are not allowed!";
-
- if (NodeA != "root") {
- if (IA == ToolToOutLang.end())
- throw NodeA + ": no output language defined!";
- if (IB == ToolToInLang.end())
- throw NodeB + ": no input language defined!";
-
- if (!Intersect(IA->second, IB->second)) {
- throw "Edge " + NodeA + "->" + NodeB
- + ": output->input language mismatch";
- }
- }
- }
-}
-
-/// WalkCase - Walks the 'case' expression DAG and invokes
-/// TestCallback on every test, and StatementCallback on every
-/// statement. Handles 'case' nesting, but not the 'and' and 'or'
-/// combinators (that is, they are passed directly to TestCallback).
-/// TestCallback must have type 'void TestCallback(const DagInit*, unsigned
-/// IndentLevel, bool FirstTest)'.
-/// StatementCallback must have type 'void StatementCallback(const Init*,
-/// unsigned IndentLevel)'.
-template <typename F1, typename F2>
-void WalkCase(const Init* Case, F1 TestCallback, F2 StatementCallback,
- unsigned IndentLevel = 0)
-{
- const DagInit& d = InitPtrToDag(Case);
-
- // Error checks.
- if (GetOperatorName(d) != "case")
- throw "WalkCase should be invoked only on 'case' expressions!";
-
- if (d.getNumArgs() < 2)
- throw "There should be at least one clause in the 'case' expression:\n"
- + d.getAsString();
-
- // Main loop.
- bool even = false;
- const unsigned numArgs = d.getNumArgs();
- unsigned i = 1;
- for (DagInit::const_arg_iterator B = d.arg_begin(), E = d.arg_end();
- B != E; ++B) {
- Init* arg = *B;
-
- if (!even)
- {
- // Handle test.
- const DagInit& Test = InitPtrToDag(arg);
-
- if (GetOperatorName(Test) == "default" && (i+1 != numArgs))
- throw "The 'default' clause should be the last in the "
- "'case' construct!";
- if (i == numArgs)
- throw "Case construct handler: no corresponding action "
- "found for the test " + Test.getAsString() + '!';
-
- TestCallback(Test, IndentLevel, (i == 1));
- }
- else
- {
- if (dynamic_cast<DagInit*>(arg)
- && GetOperatorName(static_cast<DagInit&>(*arg)) == "case") {
- // Nested 'case'.
- WalkCase(arg, TestCallback, StatementCallback, IndentLevel + Indent1);
- }
-
- // Handle statement.
- StatementCallback(arg, IndentLevel);
- }
-
- ++i;
- even = !even;
- }
-}
-
-/// ExtractOptionNames - A helper function object used by
-/// CheckForSuperfluousOptions() to walk the 'case' DAG.
-class ExtractOptionNames {
- llvm::StringSet<>& OptionNames_;
-
- void processDag(const Init* Statement) {
- const DagInit& Stmt = InitPtrToDag(Statement);
- const std::string& ActionName = GetOperatorName(Stmt);
- if (ActionName == "forward" || ActionName == "forward_as" ||
- ActionName == "forward_value" ||
- ActionName == "forward_transformed_value" ||
- ActionName == "parameter_equals" || ActionName == "element_in_list") {
- CheckNumberOfArguments(Stmt, 1);
-
- Init* Arg = Stmt.getArg(0);
- if (typeid(*Arg) == typeid(StringInit))
- OptionNames_.insert(InitPtrToString(Arg));
- }
- else if (ActionName == "any_switch_on" || ActionName == "switch_on" ||
- ActionName == "any_not_empty" || ActionName == "any_empty" ||
- ActionName == "not_empty" || ActionName == "empty") {
- for (unsigned i = 0, NumArgs = Stmt.getNumArgs(); i < NumArgs; ++i) {
- Init* Arg = Stmt.getArg(i);
- if (typeid(*Arg) == typeid(StringInit))
- OptionNames_.insert(InitPtrToString(Arg));
- }
- }
- else if (ActionName == "and" || ActionName == "or" || ActionName == "not") {
- for (unsigned i = 0, NumArgs = Stmt.getNumArgs(); i < NumArgs; ++i) {
- this->processDag(Stmt.getArg(i));
- }
- }
- }
-
-public:
- ExtractOptionNames(llvm::StringSet<>& OptionNames) : OptionNames_(OptionNames)
- {}
-
- void operator()(const Init* Statement) {
- // Statement is either a dag, or a list of dags.
- if (typeid(*Statement) == typeid(ListInit)) {
- const ListInit& DagList = *static_cast<const ListInit*>(Statement);
- for (ListInit::const_iterator B = DagList.begin(), E = DagList.end();
- B != E; ++B)
- this->processDag(*B);
- }
- else {
- this->processDag(Statement);
- }
- }
-
- void operator()(const DagInit& Test, unsigned, bool) {
- this->operator()(&Test);
- }
- void operator()(const Init* Statement, unsigned) {
- this->operator()(Statement);
- }
-};
-
-/// IsOptionalEdge - Validate that the 'optional_edge' has proper structure.
-bool IsOptionalEdge (const DagInit& Edg) {
- return (GetOperatorName(Edg) == "optional_edge") && (Edg.getNumArgs() > 2);
-}
-
-/// CheckForSuperfluousOptions - Check that there are no side
-/// effect-free options (specified only in the OptionList). Otherwise,
-/// output a warning.
-void CheckForSuperfluousOptions (const DagVector& EdgeVector,
- const ToolDescriptions& ToolDescs,
- const OptionDescriptions& OptDescs) {
- llvm::StringSet<> nonSuperfluousOptions;
-
- // Add all options mentioned in the ToolDesc.Actions to the set of
- // non-superfluous options.
- for (ToolDescriptions::const_iterator B = ToolDescs.begin(),
- E = ToolDescs.end(); B != E; ++B) {
- const ToolDescription& TD = *(*B);
- ExtractOptionNames Callback(nonSuperfluousOptions);
- if (TD.Actions)
- WalkCase(TD.Actions, Callback, Callback);
- }
-
- // Add all options mentioned in the 'case' clauses of the
- // OptionalEdges of the compilation graph to the set of
- // non-superfluous options.
- for (DagVector::const_iterator B = EdgeVector.begin(),
- E = EdgeVector.end(); B != E; ++B) {
- const DagInit& Edge = **B;
- if (IsOptionalEdge(Edge)) {
- const DagInit& Weight = InitPtrToDag(Edge.getArg(2));
- WalkCase(&Weight, ExtractOptionNames(nonSuperfluousOptions), Id());
- }
- }
-
- // Check that all options in OptDescs belong to the set of
- // non-superfluous options.
- for (OptionDescriptions::const_iterator B = OptDescs.begin(),
- E = OptDescs.end(); B != E; ++B) {
- const OptionDescription& Val = B->second;
- if (!nonSuperfluousOptions.count(Val.Name)
- && Val.Type != OptionType::Alias)
- llvm::errs() << "Warning: option '-" << Val.Name << "' has no effect! "
- "Probable cause: this option is specified only in the OptionList.\n";
- }
-}
-
-/// EmitCaseTest0Args - Helper function used by EmitCaseConstructHandler().
-bool EmitCaseTest0Args(const std::string& TestName, raw_ostream& O) {
- if (TestName == "single_input_file") {
- O << "InputFilenames.size() == 1";
- return true;
- }
- else if (TestName == "multiple_input_files") {
- O << "InputFilenames.size() > 1";
- return true;
- }
-
- return false;
-}
-
-/// EmitMultipleArgumentTest - Helper function used by
-/// EmitCaseTestMultipleArgs()
-template <typename F>
-void EmitMultipleArgumentTest(const DagInit& D, const char* LogicOp,
- F Callback, raw_ostream& O)
-{
- for (unsigned i = 0, NumArgs = D.getNumArgs(); i < NumArgs; ++i) {
- if (i != 0)
- O << ' ' << LogicOp << ' ';
- Callback(InitPtrToString(D.getArg(i)), O);
- }
-}
-
-// Callbacks for use with EmitMultipleArgumentTest
-
-class EmitSwitchOn {
- const OptionDescriptions& OptDescs_;
-public:
- EmitSwitchOn(const OptionDescriptions& OptDescs) : OptDescs_(OptDescs)
- {}
-
- void operator()(const std::string& OptName, raw_ostream& O) const {
- const OptionDescription& OptDesc = OptDescs_.FindSwitch(OptName);
- O << OptDesc.GenVariableName();
- }
-};
-
-class EmitEmptyTest {
- bool EmitNegate_;
- const OptionDescriptions& OptDescs_;
-public:
- EmitEmptyTest(bool EmitNegate, const OptionDescriptions& OptDescs)
- : EmitNegate_(EmitNegate), OptDescs_(OptDescs)
- {}
-
- void operator()(const std::string& OptName, raw_ostream& O) const {
- const char* Neg = (EmitNegate_ ? "!" : "");
- if (OptName == "o") {
- O << Neg << "OutputFilename.empty()";
- }
- else if (OptName == "save-temps") {
- O << Neg << "(SaveTemps == SaveTempsEnum::Unset)";
- }
- else {
- const OptionDescription& OptDesc = OptDescs_.FindListOrParameter(OptName);
- O << Neg << OptDesc.GenVariableName() << ".empty()";
- }
- }
-};
-
-
-/// EmitCaseTestMultipleArgs - Helper function used by EmitCaseTest1Arg()
-bool EmitCaseTestMultipleArgs (const std::string& TestName,
- const DagInit& d,
- const OptionDescriptions& OptDescs,
- raw_ostream& O) {
- if (TestName == "any_switch_on") {
- EmitMultipleArgumentTest(d, "||", EmitSwitchOn(OptDescs), O);
- return true;
- }
- else if (TestName == "switch_on") {
- EmitMultipleArgumentTest(d, "&&", EmitSwitchOn(OptDescs), O);
- return true;
- }
- else if (TestName == "any_not_empty") {
- EmitMultipleArgumentTest(d, "||", EmitEmptyTest(true, OptDescs), O);
- return true;
- }
- else if (TestName == "any_empty") {
- EmitMultipleArgumentTest(d, "||", EmitEmptyTest(false, OptDescs), O);
- return true;
- }
- else if (TestName == "not_empty") {
- EmitMultipleArgumentTest(d, "&&", EmitEmptyTest(true, OptDescs), O);
- return true;
- }
- else if (TestName == "empty") {
- EmitMultipleArgumentTest(d, "&&", EmitEmptyTest(false, OptDescs), O);
- return true;
- }
-
- return false;
-}
-
-/// EmitCaseTest1Arg - Helper function used by EmitCaseTest1OrMoreArgs()
-bool EmitCaseTest1Arg (const std::string& TestName,
- const DagInit& d,
- const OptionDescriptions& OptDescs,
- raw_ostream& O) {
- const std::string& Arg = InitPtrToString(d.getArg(0));
-
- if (TestName == "input_languages_contain") {
- O << "InLangs.count(\"" << Arg << "\") != 0";
- return true;
- }
- else if (TestName == "in_language") {
- // This works only for single-argument Tool::GenerateAction. Join
- // tools can process several files in different languages simultaneously.
-
- // TODO: make this work with Edge::Weight (if possible).
- O << "LangMap.GetLanguage(inFile) == \"" << Arg << '\"';
- return true;
- }
-
- return false;
-}
-
-/// EmitCaseTest1OrMoreArgs - Helper function used by
-/// EmitCaseConstructHandler()
-bool EmitCaseTest1OrMoreArgs(const std::string& TestName,
- const DagInit& d,
- const OptionDescriptions& OptDescs,
- raw_ostream& O) {
- CheckNumberOfArguments(d, 1);
- return EmitCaseTest1Arg(TestName, d, OptDescs, O) ||
- EmitCaseTestMultipleArgs(TestName, d, OptDescs, O);
-}
-
-/// EmitCaseTest2Args - Helper function used by EmitCaseConstructHandler().
-bool EmitCaseTest2Args(const std::string& TestName,
- const DagInit& d,
- unsigned IndentLevel,
- const OptionDescriptions& OptDescs,
- raw_ostream& O) {
- CheckNumberOfArguments(d, 2);
- const std::string& OptName = InitPtrToString(d.getArg(0));
- const std::string& OptArg = InitPtrToString(d.getArg(1));
-
- if (TestName == "parameter_equals") {
- const OptionDescription& OptDesc = OptDescs.FindParameter(OptName);
- O << OptDesc.GenVariableName() << " == \"" << OptArg << "\"";
- return true;
- }
- else if (TestName == "element_in_list") {
- const OptionDescription& OptDesc = OptDescs.FindParameterList(OptName);
- const std::string& VarName = OptDesc.GenVariableName();
- O << "std::find(" << VarName << ".begin(),\n";
- O.indent(IndentLevel + Indent1)
- << VarName << ".end(), \""
- << OptArg << "\") != " << VarName << ".end()";
- return true;
- }
-
- return false;
-}
-
-// Forward declaration.
-// EmitLogicalOperationTest and EmitCaseTest are mutually recursive.
-void EmitCaseTest(const DagInit& d, unsigned IndentLevel,
- const OptionDescriptions& OptDescs,
- raw_ostream& O);
-
-/// EmitLogicalOperationTest - Helper function used by
-/// EmitCaseConstructHandler.
-void EmitLogicalOperationTest(const DagInit& d, const char* LogicOp,
- unsigned IndentLevel,
- const OptionDescriptions& OptDescs,
- raw_ostream& O) {
- O << '(';
- for (unsigned i = 0, NumArgs = d.getNumArgs(); i < NumArgs; ++i) {
- const DagInit& InnerTest = InitPtrToDag(d.getArg(i));
- EmitCaseTest(InnerTest, IndentLevel, OptDescs, O);
- if (i != NumArgs - 1) {
- O << ")\n";
- O.indent(IndentLevel + Indent1) << ' ' << LogicOp << " (";
- }
- else {
- O << ')';
- }
- }
-}
-
-void EmitLogicalNot(const DagInit& d, unsigned IndentLevel,
- const OptionDescriptions& OptDescs, raw_ostream& O)
-{
- CheckNumberOfArguments(d, 1);
- const DagInit& InnerTest = InitPtrToDag(d.getArg(0));
- O << "! (";
- EmitCaseTest(InnerTest, IndentLevel, OptDescs, O);
- O << ")";
-}
-
-/// EmitCaseTest - Helper function used by EmitCaseConstructHandler.
-void EmitCaseTest(const DagInit& d, unsigned IndentLevel,
- const OptionDescriptions& OptDescs,
- raw_ostream& O) {
- const std::string& TestName = GetOperatorName(d);
-
- if (TestName == "and")
- EmitLogicalOperationTest(d, "&&", IndentLevel, OptDescs, O);
- else if (TestName == "or")
- EmitLogicalOperationTest(d, "||", IndentLevel, OptDescs, O);
- else if (TestName == "not")
- EmitLogicalNot(d, IndentLevel, OptDescs, O);
- else if (EmitCaseTest0Args(TestName, O))
- return;
- else if (EmitCaseTest1OrMoreArgs(TestName, d, OptDescs, O))
- return;
- else if (EmitCaseTest2Args(TestName, d, IndentLevel, OptDescs, O))
- return;
- else
- throw "Unknown test '" + TestName + "' used in the 'case' construct!";
-}
-
-
-/// EmitCaseTestCallback - Callback used by EmitCaseConstructHandler.
-class EmitCaseTestCallback {
- bool EmitElseIf_;
- const OptionDescriptions& OptDescs_;
- raw_ostream& O_;
-public:
-
- EmitCaseTestCallback(bool EmitElseIf,
- const OptionDescriptions& OptDescs, raw_ostream& O)
- : EmitElseIf_(EmitElseIf), OptDescs_(OptDescs), O_(O)
- {}
-
- void operator()(const DagInit& Test, unsigned IndentLevel, bool FirstTest)
- {
- if (GetOperatorName(Test) == "default") {
- O_.indent(IndentLevel) << "else {\n";
- }
- else {
- O_.indent(IndentLevel)
- << ((!FirstTest && EmitElseIf_) ? "else if (" : "if (");
- EmitCaseTest(Test, IndentLevel, OptDescs_, O_);
- O_ << ") {\n";
- }
- }
-};
-
-/// EmitCaseStatementCallback - Callback used by EmitCaseConstructHandler.
-template <typename F>
-class EmitCaseStatementCallback {
- F Callback_;
- raw_ostream& O_;
-public:
-
- EmitCaseStatementCallback(F Callback, raw_ostream& O)
- : Callback_(Callback), O_(O)
- {}
-
- void operator() (const Init* Statement, unsigned IndentLevel) {
- // Is this a nested 'case'?
- bool IsCase = dynamic_cast<const DagInit*>(Statement) &&
- GetOperatorName(static_cast<const DagInit&>(*Statement)) == "case";
-
- // If so, ignore it, it is handled by our caller, WalkCase.
- if (!IsCase) {
- if (typeid(*Statement) == typeid(ListInit)) {
- const ListInit& DagList = *static_cast<const ListInit*>(Statement);
- for (ListInit::const_iterator B = DagList.begin(), E = DagList.end();
- B != E; ++B)
- Callback_(*B, (IndentLevel + Indent1), O_);
- }
- else {
- Callback_(Statement, (IndentLevel + Indent1), O_);
- }
- }
- O_.indent(IndentLevel) << "}\n";
- }
-
-};
-
-/// EmitCaseConstructHandler - Emit code that handles the 'case'
-/// construct. Takes a function object that should emit code for every case
-/// clause. Implemented on top of WalkCase.
-/// Callback's type is void F(const Init* Statement, unsigned IndentLevel,
-/// raw_ostream& O).
-/// EmitElseIf parameter controls the type of condition that is emitted ('if
-/// (..) {..} else if (..) {} .. else {..}' vs. 'if (..) {..} if(..) {..}
-/// .. else {..}').
-template <typename F>
-void EmitCaseConstructHandler(const Init* Case, unsigned IndentLevel,
- F Callback, bool EmitElseIf,
- const OptionDescriptions& OptDescs,
- raw_ostream& O) {
- WalkCase(Case, EmitCaseTestCallback(EmitElseIf, OptDescs, O),
- EmitCaseStatementCallback<F>(Callback, O), IndentLevel);
-}
-
-/// TokenizeCmdLine - converts from
-/// "$CALL(HookName, 'Arg1', 'Arg2')/path -arg1 -arg2" to
-/// ["$CALL(", "HookName", "Arg1", "Arg2", ")/path", "-arg1", "-arg2"].
-void TokenizeCmdLine(const std::string& CmdLine, StrVector& Out) {
- const char* Delimiters = " \t\n\v\f\r";
- enum TokenizerState
- { Normal, SpecialCommand, InsideSpecialCommand, InsideQuotationMarks }
- cur_st = Normal;
-
- if (CmdLine.empty())
- return;
- Out.push_back("");
-
- std::string::size_type B = CmdLine.find_first_not_of(Delimiters),
- E = CmdLine.size();
-
- for (; B != E; ++B) {
- char cur_ch = CmdLine[B];
-
- switch (cur_st) {
- case Normal:
- if (cur_ch == '$') {
- cur_st = SpecialCommand;
- break;
- }
- if (OneOf(Delimiters, cur_ch)) {
- // Skip whitespace
- B = CmdLine.find_first_not_of(Delimiters, B);
- if (B == std::string::npos) {
- B = E-1;
- continue;
- }
- --B;
- Out.push_back("");
- continue;
- }
- break;
-
-
- case SpecialCommand:
- if (OneOf(Delimiters, cur_ch)) {
- cur_st = Normal;
- Out.push_back("");
- continue;
- }
- if (cur_ch == '(') {
- Out.push_back("");
- cur_st = InsideSpecialCommand;
- continue;
- }
- break;
-
- case InsideSpecialCommand:
- if (OneOf(Delimiters, cur_ch)) {
- continue;
- }
- if (cur_ch == '\'') {
- cur_st = InsideQuotationMarks;
- Out.push_back("");
- continue;
- }
- if (cur_ch == ')') {
- cur_st = Normal;
- Out.push_back("");
- }
- if (cur_ch == ',') {
- continue;
- }
-
- break;
-
- case InsideQuotationMarks:
- if (cur_ch == '\'') {
- cur_st = InsideSpecialCommand;
- continue;
- }
- break;
- }
-
- Out.back().push_back(cur_ch);
- }
-}
-
-/// SubstituteCall - Given "$CALL(HookName, [Arg1 [, Arg2 [...]]])", output
-/// "hooks::HookName([Arg1 [, Arg2 [, ...]]])". Helper function used by
-/// SubstituteSpecialCommands().
-StrVector::const_iterator
-SubstituteCall (StrVector::const_iterator Pos,
- StrVector::const_iterator End,
- bool IsJoin, raw_ostream& O)
-{
- const char* errorMessage = "Syntax error in $CALL invocation!";
- CheckedIncrement(Pos, End, errorMessage);
- const std::string& CmdName = *Pos;
-
- if (CmdName == ")")
- throw "$CALL invocation: empty argument list!";
-
- O << "hooks::";
- O << CmdName << "(";
-
-
- bool firstIteration = true;
- while (true) {
- CheckedIncrement(Pos, End, errorMessage);
- const std::string& Arg = *Pos;
- assert(Arg.size() != 0);
-
- if (Arg[0] == ')')
- break;
-
- if (firstIteration)
- firstIteration = false;
- else
- O << ", ";
-
- if (Arg == "$INFILE") {
- if (IsJoin)
- throw "$CALL(Hook, $INFILE) can't be used with a Join tool!";
- else
- O << "inFile.c_str()";
- }
- else {
- O << '"' << Arg << '"';
- }
- }
-
- O << ')';
-
- return Pos;
-}
-
-/// SubstituteEnv - Given '$ENV(VAR_NAME)', output 'getenv("VAR_NAME")'. Helper
-/// function used by SubstituteSpecialCommands().
-StrVector::const_iterator
-SubstituteEnv (StrVector::const_iterator Pos,
- StrVector::const_iterator End, raw_ostream& O)
-{
- const char* errorMessage = "Syntax error in $ENV invocation!";
- CheckedIncrement(Pos, End, errorMessage);
- const std::string& EnvName = *Pos;
-
- if (EnvName == ")")
- throw "$ENV invocation: empty argument list!";
-
- O << "checkCString(std::getenv(\"";
- O << EnvName;
- O << "\"))";
-
- CheckedIncrement(Pos, End, errorMessage);
-
- return Pos;
-}
-
-/// SubstituteSpecialCommands - Given an invocation of $CALL or $ENV, output
-/// handler code. Helper function used by EmitCmdLineVecFill().
-StrVector::const_iterator
-SubstituteSpecialCommands (StrVector::const_iterator Pos,
- StrVector::const_iterator End,
- bool IsJoin, raw_ostream& O)
-{
-
- const std::string& cmd = *Pos;
-
- // Perform substitution.
- if (cmd == "$CALL") {
- Pos = SubstituteCall(Pos, End, IsJoin, O);
- }
- else if (cmd == "$ENV") {
- Pos = SubstituteEnv(Pos, End, O);
- }
- else {
- throw "Unknown special command: " + cmd;
- }
-
- // Handle '$CMD(ARG)/additional/text'.
- const std::string& Leftover = *Pos;
- assert(Leftover.at(0) == ')');
- if (Leftover.size() != 1)
- O << " + std::string(\"" << (Leftover.c_str() + 1) << "\")";
-
- return Pos;
-}
-
-/// EmitCmdLineVecFill - Emit code that fills in the command line
-/// vector. Helper function used by EmitGenerateActionMethod().
-void EmitCmdLineVecFill(const Init* CmdLine, const std::string& ToolName,
- bool IsJoin, unsigned IndentLevel,
- raw_ostream& O) {
- StrVector StrVec;
- TokenizeCmdLine(InitPtrToString(CmdLine), StrVec);
-
- if (StrVec.empty())
- throw "Tool '" + ToolName + "' has empty command line!";
-
- StrVector::const_iterator B = StrVec.begin(), E = StrVec.end();
-
- // Emit the command itself.
- assert(!StrVec[0].empty());
- O.indent(IndentLevel) << "cmd = ";
- if (StrVec[0][0] == '$') {
- B = SubstituteSpecialCommands(B, E, IsJoin, O);
- ++B;
- }
- else {
- O << '"' << StrVec[0] << '"';
- ++B;
- }
- O << ";\n";
-
- // Go through the command arguments.
- assert(B <= E);
- for (; B != E; ++B) {
- const std::string& cmd = *B;
-
- assert(!cmd.empty());
- O.indent(IndentLevel);
-
- if (cmd.at(0) == '$') {
- O << "vec.push_back(std::make_pair(0, ";
- B = SubstituteSpecialCommands(B, E, IsJoin, O);
- O << "));\n";
- }
- else {
- O << "vec.push_back(std::make_pair(0, \"" << cmd << "\"));\n";
- }
- }
-
-}
-
-/// EmitForEachListElementCycleHeader - Emit common code for iterating through
-/// all elements of a list. Helper function used by
-/// EmitForwardOptionPropertyHandlingCode.
-void EmitForEachListElementCycleHeader (const OptionDescription& D,
- unsigned IndentLevel,
- raw_ostream& O) {
- unsigned IndentLevel1 = IndentLevel + Indent1;
-
- O.indent(IndentLevel)
- << "for (" << D.GenTypeDeclaration()
- << "::iterator B = " << D.GenVariableName() << ".begin(),\n";
- O.indent(IndentLevel)
- << "E = " << D.GenVariableName() << ".end(); B != E;) {\n";
- O.indent(IndentLevel1) << "unsigned pos = " << D.GenVariableName()
- << ".getPosition(B - " << D.GenVariableName()
- << ".begin());\n";
-}
-
-/// EmitForwardOptionPropertyHandlingCode - Helper function used to
-/// implement EmitActionHandler. Emits code for
-/// handling the (forward) and (forward_as) option properties.
-void EmitForwardOptionPropertyHandlingCode (const OptionDescription& D,
- unsigned IndentLevel,
- const std::string& NewName,
- raw_ostream& O) {
- const std::string& Name = NewName.empty()
- ? ("-" + D.Name)
- : NewName;
- unsigned IndentLevel1 = IndentLevel + Indent1;
-
- switch (D.Type) {
- case OptionType::Switch:
- O.indent(IndentLevel)
- << "vec.push_back(std::make_pair(" << D.GenVariableName()
- << ".getPosition(), \"" << Name << "\"));\n";
- break;
- case OptionType::Parameter:
- O.indent(IndentLevel) << "vec.push_back(std::make_pair("
- << D.GenVariableName()
- <<".getPosition(), \"" << Name;
-
- if (!D.isForwardNotSplit()) {
- O << "\"));\n";
- O.indent(IndentLevel) << "vec.push_back(std::make_pair("
- << D.GenVariableName() << ".getPosition(), "
- << D.GenVariableName() << "));\n";
- }
- else {
- O << "=\" + " << D.GenVariableName() << "));\n";
- }
- break;
- case OptionType::Prefix:
- O.indent(IndentLevel) << "vec.push_back(std::make_pair("
- << D.GenVariableName() << ".getPosition(), \""
- << Name << "\" + "
- << D.GenVariableName() << "));\n";
- break;
- case OptionType::PrefixList:
- EmitForEachListElementCycleHeader(D, IndentLevel, O);
- O.indent(IndentLevel1) << "vec.push_back(std::make_pair(pos, \""
- << Name << "\" + " << "*B));\n";
- O.indent(IndentLevel1) << "++B;\n";
-
- for (int i = 1, j = D.MultiVal; i < j; ++i) {
- O.indent(IndentLevel1) << "vec.push_back(std::make_pair(pos, *B));\n";
- O.indent(IndentLevel1) << "++B;\n";
- }
-
- O.indent(IndentLevel) << "}\n";
- break;
- case OptionType::ParameterList:
- EmitForEachListElementCycleHeader(D, IndentLevel, O);
- O.indent(IndentLevel1) << "vec.push_back(std::make_pair(pos, \""
- << Name << "\"));\n";
-
- for (int i = 0, j = D.MultiVal; i < j; ++i) {
- O.indent(IndentLevel1) << "vec.push_back(std::make_pair(pos, *B));\n";
- O.indent(IndentLevel1) << "++B;\n";
- }
-
- O.indent(IndentLevel) << "}\n";
- break;
- case OptionType::SwitchList:
- EmitForEachListElementCycleHeader(D, IndentLevel, O);
- O.indent(IndentLevel1) << "vec.push_back(std::make_pair(pos, \""
- << Name << "\"));\n";
- O.indent(IndentLevel1) << "++B;\n";
- O.indent(IndentLevel) << "}\n";
- break;
- case OptionType::Alias:
- default:
- throw "Aliases are not allowed in tool option descriptions!";
- }
-}
-
-/// ActionHandlingCallbackBase - Base class of EmitActionHandlersCallback and
-/// EmitPreprocessOptionsCallback.
-struct ActionHandlingCallbackBase
-{
-
- void onErrorDag(const DagInit& d,
- unsigned IndentLevel, raw_ostream& O) const
- {
- O.indent(IndentLevel)
- << "PrintError(\""
- << (d.getNumArgs() >= 1 ? InitPtrToString(d.getArg(0)) : "Unknown error!")
- << "\");\n";
- O.indent(IndentLevel) << "return 1;\n";
- }
-
- void onWarningDag(const DagInit& d,
- unsigned IndentLevel, raw_ostream& O) const
- {
- CheckNumberOfArguments(d, 1);
- O.indent(IndentLevel) << "llvm::errs() << \""
- << InitPtrToString(d.getArg(0)) << "\";\n";
- }
-
-};
-
-/// EmitActionHandlersCallback - Emit code that handles actions. Used by
-/// EmitGenerateActionMethod() as an argument to EmitCaseConstructHandler().
-class EmitActionHandlersCallback;
-
-typedef void (EmitActionHandlersCallback::* EmitActionHandlersCallbackHandler)
-(const DagInit&, unsigned, raw_ostream&) const;
-
-class EmitActionHandlersCallback :
- public ActionHandlingCallbackBase,
- public HandlerTable<EmitActionHandlersCallbackHandler>
-{
- typedef EmitActionHandlersCallbackHandler Handler;
-
- const OptionDescriptions& OptDescs;
-
- /// EmitHookInvocation - Common code for hook invocation from actions. Used by
- /// onAppendCmd and onOutputSuffix.
- void EmitHookInvocation(const std::string& Str,
- const char* BlockOpen, const char* BlockClose,
- unsigned IndentLevel, raw_ostream& O) const
- {
- StrVector Out;
- TokenizeCmdLine(Str, Out);
-
- for (StrVector::const_iterator B = Out.begin(), E = Out.end();
- B != E; ++B) {
- const std::string& cmd = *B;
-
- O.indent(IndentLevel) << BlockOpen;
-
- if (cmd.at(0) == '$')
- B = SubstituteSpecialCommands(B, E, /* IsJoin = */ true, O);
- else
- O << '"' << cmd << '"';
-
- O << BlockClose;
- }
- }
-
- void onAppendCmd (const DagInit& Dag,
- unsigned IndentLevel, raw_ostream& O) const
- {
- CheckNumberOfArguments(Dag, 1);
- this->EmitHookInvocation(InitPtrToString(Dag.getArg(0)),
- "vec.push_back(std::make_pair(65536, ", "));\n",
- IndentLevel, O);
- }
-
- void onForward (const DagInit& Dag,
- unsigned IndentLevel, raw_ostream& O) const
- {
- CheckNumberOfArguments(Dag, 1);
- const std::string& Name = InitPtrToString(Dag.getArg(0));
- EmitForwardOptionPropertyHandlingCode(OptDescs.FindOption(Name),
- IndentLevel, "", O);
- }
-
- void onForwardAs (const DagInit& Dag,
- unsigned IndentLevel, raw_ostream& O) const
- {
- CheckNumberOfArguments(Dag, 2);
- const std::string& Name = InitPtrToString(Dag.getArg(0));
- const std::string& NewName = InitPtrToString(Dag.getArg(1));
- EmitForwardOptionPropertyHandlingCode(OptDescs.FindOption(Name),
- IndentLevel, NewName, O);
- }
-
- void onForwardValue (const DagInit& Dag,
- unsigned IndentLevel, raw_ostream& O) const
- {
- CheckNumberOfArguments(Dag, 1);
- const std::string& Name = InitPtrToString(Dag.getArg(0));
- const OptionDescription& D = OptDescs.FindParameterListOrParameter(Name);
-
- if (D.isSwitchList()) {
- throw std::runtime_error
- ("forward_value is not allowed with switch_list");
- }
-
- if (D.isParameter()) {
- O.indent(IndentLevel) << "vec.push_back(std::make_pair("
- << D.GenVariableName() << ".getPosition(), "
- << D.GenVariableName() << "));\n";
- }
- else {
- O.indent(IndentLevel) << "for (" << D.GenTypeDeclaration()
- << "::iterator B = " << D.GenVariableName()
- << ".begin(), \n";
- O.indent(IndentLevel + Indent1) << " E = " << D.GenVariableName()
- << ".end(); B != E; ++B)\n";
- O.indent(IndentLevel) << "{\n";
- O.indent(IndentLevel + Indent1)
- << "unsigned pos = " << D.GenVariableName()
- << ".getPosition(B - " << D.GenVariableName()
- << ".begin());\n";
- O.indent(IndentLevel + Indent1)
- << "vec.push_back(std::make_pair(pos, *B));\n";
- O.indent(IndentLevel) << "}\n";
- }
- }
-
- void onForwardTransformedValue (const DagInit& Dag,
- unsigned IndentLevel, raw_ostream& O) const
- {
- CheckNumberOfArguments(Dag, 2);
- const std::string& Name = InitPtrToString(Dag.getArg(0));
- const std::string& Hook = InitPtrToString(Dag.getArg(1));
- const OptionDescription& D = OptDescs.FindParameterListOrParameter(Name);
-
- O.indent(IndentLevel) << "vec.push_back(std::make_pair("
- << D.GenVariableName() << ".getPosition("
- << (D.isList() ? "0" : "") << "), "
- << "hooks::" << Hook << "(" << D.GenVariableName()
- << (D.isParameter() ? ".c_str()" : "") << ")));\n";
- }
-
- void onNoOutFile (const DagInit& Dag,
- unsigned IndentLevel, raw_ostream& O) const
- {
- CheckNumberOfArguments(Dag, 0);
- O.indent(IndentLevel) << "no_out_file = true;\n";
- }
-
- void onOutputSuffix (const DagInit& Dag,
- unsigned IndentLevel, raw_ostream& O) const
- {
- CheckNumberOfArguments(Dag, 1);
- this->EmitHookInvocation(InitPtrToString(Dag.getArg(0)),
- "output_suffix = ", ";\n", IndentLevel, O);
- }
-
- void onStopCompilation (const DagInit& Dag,
- unsigned IndentLevel, raw_ostream& O) const
- {
- O.indent(IndentLevel) << "stop_compilation = true;\n";
- }
-
-
- void onUnpackValues (const DagInit& Dag,
- unsigned IndentLevel, raw_ostream& O) const
- {
- throw "'unpack_values' is deprecated. "
- "Use 'comma_separated' + 'forward_value' instead!";
- }
-
- public:
-
- explicit EmitActionHandlersCallback(const OptionDescriptions& OD)
- : OptDescs(OD)
- {
- if (!staticMembersInitialized_) {
- AddHandler("error", &EmitActionHandlersCallback::onErrorDag);
- AddHandler("warning", &EmitActionHandlersCallback::onWarningDag);
- AddHandler("append_cmd", &EmitActionHandlersCallback::onAppendCmd);
- AddHandler("forward", &EmitActionHandlersCallback::onForward);
- AddHandler("forward_as", &EmitActionHandlersCallback::onForwardAs);
- AddHandler("forward_value", &EmitActionHandlersCallback::onForwardValue);
- AddHandler("forward_transformed_value",
- &EmitActionHandlersCallback::onForwardTransformedValue);
- AddHandler("no_out_file",
- &EmitActionHandlersCallback::onNoOutFile);
- AddHandler("output_suffix", &EmitActionHandlersCallback::onOutputSuffix);
- AddHandler("stop_compilation",
- &EmitActionHandlersCallback::onStopCompilation);
- AddHandler("unpack_values",
- &EmitActionHandlersCallback::onUnpackValues);
-
-
- staticMembersInitialized_ = true;
- }
- }
-
- void operator()(const Init* I,
- unsigned IndentLevel, raw_ostream& O) const
- {
- InvokeDagInitHandler(this, I, IndentLevel, O);
- }
-};
-
-void EmitGenerateActionMethodHeader(const ToolDescription& D,
- bool IsJoin, bool Naked,
- raw_ostream& O)
-{
- O.indent(Indent1) << "int GenerateAction(Action& Out,\n";
-
- if (IsJoin)
- O.indent(Indent2) << "const PathVector& inFiles,\n";
- else
- O.indent(Indent2) << "const sys::Path& inFile,\n";
-
- O.indent(Indent2) << "const bool HasChildren,\n";
- O.indent(Indent2) << "const llvm::sys::Path& TempDir,\n";
- O.indent(Indent2) << "const InputLanguagesSet& InLangs,\n";
- O.indent(Indent2) << "const LanguageMap& LangMap) const\n";
- O.indent(Indent1) << "{\n";
-
- if (!Naked) {
- O.indent(Indent2) << "std::string cmd;\n";
- O.indent(Indent2) << "std::string out_file;\n";
- O.indent(Indent2)
- << "std::vector<std::pair<unsigned, std::string> > vec;\n";
- O.indent(Indent2) << "bool stop_compilation = !HasChildren;\n";
- O.indent(Indent2) << "bool no_out_file = false;\n";
- O.indent(Indent2) << "std::string output_suffix(\""
- << D.OutputSuffix << "\");\n";
- }
-}
-
-// EmitGenerateActionMethod - Emit either a normal or a "join" version of the
-// Tool::GenerateAction() method.
-void EmitGenerateActionMethod (const ToolDescription& D,
- const OptionDescriptions& OptDescs,
- bool IsJoin, raw_ostream& O) {
-
- EmitGenerateActionMethodHeader(D, IsJoin, /* Naked = */ false, O);
-
- if (!D.CmdLine)
- throw "Tool " + D.Name + " has no cmd_line property!";
-
- // Process the 'command' property.
- O << '\n';
- EmitCmdLineVecFill(D.CmdLine, D.Name, IsJoin, Indent2, O);
- O << '\n';
-
- // Process the 'actions' list of this tool.
- if (D.Actions)
- EmitCaseConstructHandler(D.Actions, Indent2,
- EmitActionHandlersCallback(OptDescs),
- false, OptDescs, O);
- O << '\n';
-
- // Input file (s)
- if (!D.InFileOption.empty()) {
- O.indent(Indent2)
- << "vec.push_back(std::make_pair(InputFilenames.getPosition(0), \""
- << D.InFileOption << "\");\n";
- }
-
- if (IsJoin) {
- O.indent(Indent2)
- << "for (PathVector::const_iterator B = inFiles.begin(),\n";
- O.indent(Indent3) << "E = inFiles.end(); B != E; ++B)\n";
- O.indent(Indent2) << "{\n";
- O.indent(Indent3) << "vec.push_back(std::make_pair("
- << "InputFilenames.getPosition(B - inFiles.begin()), "
- << "B->str()));\n";
- O.indent(Indent2) << "}\n";
- }
- else {
- O.indent(Indent2) << "vec.push_back(std::make_pair("
- << "InputFilenames.getPosition(0), inFile.str()));\n";
- }
-
- // Output file
- O.indent(Indent2) << "if (!no_out_file) {\n";
- if (!D.OutFileOption.empty())
- O.indent(Indent3) << "vec.push_back(std::make_pair(65536, \""
- << D.OutFileOption << "\"));\n";
-
- O.indent(Indent3) << "out_file = this->OutFilename("
- << (IsJoin ? "sys::Path(),\n" : "inFile,\n");
- O.indent(Indent4) <<
- "TempDir, stop_compilation, output_suffix.c_str()).str();\n\n";
- O.indent(Indent3) << "vec.push_back(std::make_pair(65536, out_file));\n";
-
- O.indent(Indent2) << "}\n\n";
-
- // Handle the Sink property.
- std::string SinkOption("autogenerated::");
- SinkOption += SinkOptionName;
- if (D.isSink()) {
- O.indent(Indent2) << "if (!" << SinkOption << ".empty()) {\n";
- O.indent(Indent3) << "for (cl::list<std::string>::iterator B = "
- << SinkOption << ".begin(), E = " << SinkOption
- << ".end(); B != E; ++B)\n";
- O.indent(Indent4) << "vec.push_back(std::make_pair(" << SinkOption
- << ".getPosition(B - " << SinkOption
- << ".begin()), *B));\n";
- O.indent(Indent2) << "}\n";
- }
-
- O.indent(Indent2) << "Out.Construct(cmd, this->SortArgs(vec), "
- << "stop_compilation, out_file);\n";
- O.indent(Indent2) << "return 0;\n";
- O.indent(Indent1) << "}\n\n";
-}
-
-/// EmitGenerateActionMethods - Emit two GenerateAction() methods for
-/// a given Tool class.
-void EmitGenerateActionMethods (const ToolDescription& ToolDesc,
- const OptionDescriptions& OptDescs,
- raw_ostream& O) {
- if (!ToolDesc.isJoin()) {
- EmitGenerateActionMethodHeader(ToolDesc, /* IsJoin = */ true,
- /* Naked = */ true, O);
- O.indent(Indent2) << "PrintError(\"" << ToolDesc.Name
- << " is not a Join tool!\");\n";
- O.indent(Indent2) << "return -1;\n";
- O.indent(Indent1) << "}\n\n";
- }
- else {
- EmitGenerateActionMethod(ToolDesc, OptDescs, true, O);
- }
-
- EmitGenerateActionMethod(ToolDesc, OptDescs, false, O);
-}
-
-/// EmitInOutLanguageMethods - Emit the [Input,Output]Language()
-/// methods for a given Tool class.
-void EmitInOutLanguageMethods (const ToolDescription& D, raw_ostream& O) {
- O.indent(Indent1) << "const char** InputLanguages() const {\n";
- O.indent(Indent2) << "return InputLanguages_;\n";
- O.indent(Indent1) << "}\n\n";
-
- O.indent(Indent1) << "const char** OutputLanguages() const {\n";
- O.indent(Indent2) << "return OutputLanguages_;\n";
- O.indent(Indent1) << "}\n\n";
-}
-
-/// EmitNameMethod - Emit the Name() method for a given Tool class.
-void EmitNameMethod (const ToolDescription& D, raw_ostream& O) {
- O.indent(Indent1) << "const char* Name() const {\n";
- O.indent(Indent2) << "return \"" << D.Name << "\";\n";
- O.indent(Indent1) << "}\n\n";
-}
-
-/// EmitIsJoinMethod - Emit the IsJoin() method for a given Tool
-/// class.
-void EmitIsJoinMethod (const ToolDescription& D, raw_ostream& O) {
- O.indent(Indent1) << "bool IsJoin() const {\n";
- if (D.isJoin())
- O.indent(Indent2) << "return true;\n";
- else
- O.indent(Indent2) << "return false;\n";
- O.indent(Indent1) << "}\n\n";
-}
-
-/// EmitWorksOnEmptyCallback - Callback used by EmitWorksOnEmptyMethod in
-/// conjunction with EmitCaseConstructHandler.
-void EmitWorksOnEmptyCallback (const Init* Value,
- unsigned IndentLevel, raw_ostream& O) {
- CheckBooleanConstant(Value);
- O.indent(IndentLevel) << "return " << Value->getAsString() << ";\n";
-}
-
-/// EmitWorksOnEmptyMethod - Emit the WorksOnEmpty() method for a given Tool
-/// class.
-void EmitWorksOnEmptyMethod (const ToolDescription& D,
- const OptionDescriptions& OptDescs,
- raw_ostream& O)
-{
- O.indent(Indent1) << "bool WorksOnEmpty() const {\n";
- if (D.OnEmpty == 0)
- O.indent(Indent2) << "return false;\n";
- else
- EmitCaseConstructHandler(D.OnEmpty, Indent2, EmitWorksOnEmptyCallback,
- /*EmitElseIf = */ true, OptDescs, O);
- O.indent(Indent1) << "}\n\n";
-}
-
-/// EmitStrArray - Emit definition of a 'const char**' static member
-/// variable. Helper used by EmitStaticMemberDefinitions();
-void EmitStrArray(const std::string& Name, const std::string& VarName,
- const StrVector& StrVec, raw_ostream& O) {
- O << "const char* " << Name << "::" << VarName << "[] = {";
- for (StrVector::const_iterator B = StrVec.begin(), E = StrVec.end();
- B != E; ++B)
- O << '\"' << *B << "\", ";
- O << "0};\n";
-}
-
-/// EmitStaticMemberDefinitions - Emit static member definitions for a
-/// given Tool class.
-void EmitStaticMemberDefinitions(const ToolDescription& D, raw_ostream& O) {
- if (D.InLanguage.empty())
- throw "Tool " + D.Name + " has no 'in_language' property!";
- if (D.OutLanguage.empty())
- throw "Tool " + D.Name + " has no 'out_language' property!";
-
- EmitStrArray(D.Name, "InputLanguages_", D.InLanguage, O);
- EmitStrArray(D.Name, "OutputLanguages_", D.OutLanguage, O);
- O << '\n';
-}
-
-/// EmitToolClassDefinition - Emit a Tool class definition.
-void EmitToolClassDefinition (const ToolDescription& D,
- const OptionDescriptions& OptDescs,
- raw_ostream& O) {
- if (D.Name == "root")
- return;
-
- // Header
- O << "class " << D.Name << " : public ";
- if (D.isJoin())
- O << "JoinTool";
- else
- O << "Tool";
-
- O << " {\nprivate:\n";
- O.indent(Indent1) << "static const char* InputLanguages_[];\n";
- O.indent(Indent1) << "static const char* OutputLanguages_[];\n\n";
-
- O << "public:\n";
- EmitNameMethod(D, O);
- EmitInOutLanguageMethods(D, O);
- EmitIsJoinMethod(D, O);
- EmitWorksOnEmptyMethod(D, OptDescs, O);
- EmitGenerateActionMethods(D, OptDescs, O);
-
- // Close class definition
- O << "};\n";
-
- EmitStaticMemberDefinitions(D, O);
-
-}
-
-/// EmitOptionDefinitions - Iterate over a list of option descriptions
-/// and emit registration code.
-void EmitOptionDefinitions (const OptionDescriptions& descs,
- bool HasSink, raw_ostream& O)
-{
- std::vector<OptionDescription> Aliases;
-
- // Emit static cl::Option variables.
- for (OptionDescriptions::const_iterator B = descs.begin(),
- E = descs.end(); B!=E; ++B) {
- const OptionDescription& val = B->second;
-
- if (val.Type == OptionType::Alias) {
- Aliases.push_back(val);
- continue;
- }
-
- O << val.GenTypeDeclaration() << ' '
- << val.GenPlainVariableName();
-
- O << "(\"" << val.Name << "\"\n";
-
- if (val.Type == OptionType::Prefix || val.Type == OptionType::PrefixList)
- O << ", cl::Prefix";
-
- if (val.isRequired()) {
- if (val.isList() && !val.isMultiVal())
- O << ", cl::OneOrMore";
- else
- O << ", cl::Required";
- }
-
- if (val.isOptional())
- O << ", cl::Optional";
-
- if (val.isOneOrMore())
- O << ", cl::OneOrMore";
-
- if (val.isZeroOrMore())
- O << ", cl::ZeroOrMore";
-
- if (val.isReallyHidden())
- O << ", cl::ReallyHidden";
- else if (val.isHidden())
- O << ", cl::Hidden";
-
- if (val.isCommaSeparated())
- O << ", cl::CommaSeparated";
-
- if (val.MultiVal > 1)
- O << ", cl::multi_val(" << val.MultiVal << ')';
-
- if (val.InitVal) {
- const std::string& str = val.InitVal->getAsString();
- O << ", cl::init(" << str << ')';
- }
-
- if (!val.Help.empty())
- O << ", cl::desc(\"" << val.Help << "\")";
-
- O << ");\n\n";
- }
-
- // Emit the aliases (they should go after all the 'proper' options).
- for (std::vector<OptionDescription>::const_iterator
- B = Aliases.begin(), E = Aliases.end(); B != E; ++B) {
- const OptionDescription& val = *B;
-
- O << val.GenTypeDeclaration() << ' '
- << val.GenPlainVariableName()
- << "(\"" << val.Name << '\"';
-
- const OptionDescription& D = descs.FindOption(val.Help);
- O << ", cl::aliasopt(" << D.GenVariableName() << ")";
-
- O << ", cl::desc(\"" << "An alias for -" + val.Help << "\"));\n";
- }
-
- // Emit the sink option.
- if (HasSink)
- O << "cl::list<std::string> " << SinkOptionName << "(cl::Sink);\n";
-
- O << '\n';
-}
-
-/// EmitPreprocessOptionsCallback - Helper function passed to
-/// EmitCaseConstructHandler() by EmitPreprocessOptions().
-
-class EmitPreprocessOptionsCallback;
-
-typedef void
-(EmitPreprocessOptionsCallback::* EmitPreprocessOptionsCallbackHandler)
-(const DagInit&, unsigned, raw_ostream&) const;
-
-class EmitPreprocessOptionsCallback :
- public ActionHandlingCallbackBase,
- public HandlerTable<EmitPreprocessOptionsCallbackHandler>
-{
- typedef EmitPreprocessOptionsCallbackHandler Handler;
- typedef void
- (EmitPreprocessOptionsCallback::* HandlerImpl)
- (const Init*, unsigned, raw_ostream&) const;
-
- const OptionDescriptions& OptDescs_;
-
- void onEachArgument(const DagInit& d, HandlerImpl h,
- unsigned IndentLevel, raw_ostream& O) const
- {
- CheckNumberOfArguments(d, 1);
-
- for (unsigned i = 0, NumArgs = d.getNumArgs(); i < NumArgs; ++i) {
- ((this)->*(h))(d.getArg(i), IndentLevel, O);
- }
- }
-
- void onUnsetOptionImpl(const Init* I,
- unsigned IndentLevel, raw_ostream& O) const
- {
- const std::string& OptName = InitPtrToString(I);
- const OptionDescription& OptDesc = OptDescs_.FindOption(OptName);
-
- if (OptDesc.isSwitch()) {
- O.indent(IndentLevel) << OptDesc.GenVariableName() << " = false;\n";
- }
- else if (OptDesc.isParameter()) {
- O.indent(IndentLevel) << OptDesc.GenVariableName() << " = \"\";\n";
- }
- else if (OptDesc.isList()) {
- O.indent(IndentLevel) << OptDesc.GenVariableName() << ".clear();\n";
- }
- else {
- throw "Can't apply 'unset_option' to alias option '" + OptName + "'!";
- }
- }
-
- void onUnsetOption(const DagInit& d,
- unsigned IndentLevel, raw_ostream& O) const
- {
- this->onEachArgument(d, &EmitPreprocessOptionsCallback::onUnsetOptionImpl,
- IndentLevel, O);
- }
-
- void onSetOptionImpl(const DagInit& D,
- unsigned IndentLevel, raw_ostream& O) const {
- CheckNumberOfArguments(D, 2);
-
- const std::string& OptName = InitPtrToString(D.getArg(0));
- const OptionDescription& OptDesc = OptDescs_.FindOption(OptName);
- const Init* Value = D.getArg(1);
-
- if (OptDesc.isList()) {
- const ListInit& List = InitPtrToList(Value);
-
- O.indent(IndentLevel) << OptDesc.GenVariableName() << ".clear();\n";
- for (ListInit::const_iterator B = List.begin(), E = List.end();
- B != E; ++B) {
- const Init* CurElem = *B;
- if (OptDesc.isSwitchList())
- CheckBooleanConstant(CurElem);
-
- O.indent(IndentLevel)
- << OptDesc.GenVariableName() << ".push_back(\""
- << (OptDesc.isSwitchList() ? CurElem->getAsString()
- : InitPtrToString(CurElem))
- << "\");\n";
- }
- }
- else if (OptDesc.isSwitch()) {
- CheckBooleanConstant(Value);
- O.indent(IndentLevel) << OptDesc.GenVariableName()
- << " = " << Value->getAsString() << ";\n";
- }
- else if (OptDesc.isParameter()) {
- const std::string& Str = InitPtrToString(Value);
- O.indent(IndentLevel) << OptDesc.GenVariableName()
- << " = \"" << Str << "\";\n";
- }
- else {
- throw "Can't apply 'set_option' to alias option '" + OptName + "'!";
- }
- }
-
- void onSetSwitch(const Init* I,
- unsigned IndentLevel, raw_ostream& O) const {
- const std::string& OptName = InitPtrToString(I);
- const OptionDescription& OptDesc = OptDescs_.FindOption(OptName);
-
- if (OptDesc.isSwitch())
- O.indent(IndentLevel) << OptDesc.GenVariableName() << " = true;\n";
- else
- throw "set_option: -" + OptName + " is not a switch option!";
- }
-
- void onSetOption(const DagInit& d,
- unsigned IndentLevel, raw_ostream& O) const
- {
- CheckNumberOfArguments(d, 1);
-
- // 2-argument form: (set_option "A", true), (set_option "B", "C"),
- // (set_option "D", ["E", "F"])
- if (d.getNumArgs() == 2) {
- const OptionDescription& OptDesc =
- OptDescs_.FindOption(InitPtrToString(d.getArg(0)));
- const Init* Opt2 = d.getArg(1);
-
- if (!OptDesc.isSwitch() || typeid(*Opt2) != typeid(StringInit)) {
- this->onSetOptionImpl(d, IndentLevel, O);
- return;
- }
- }
-
- // Multiple argument form: (set_option "A"), (set_option "B", "C", "D")
- this->onEachArgument(d, &EmitPreprocessOptionsCallback::onSetSwitch,
- IndentLevel, O);
- }
-
-public:
-
- EmitPreprocessOptionsCallback(const OptionDescriptions& OptDescs)
- : OptDescs_(OptDescs)
- {
- if (!staticMembersInitialized_) {
- AddHandler("error", &EmitPreprocessOptionsCallback::onErrorDag);
- AddHandler("warning", &EmitPreprocessOptionsCallback::onWarningDag);
- AddHandler("unset_option", &EmitPreprocessOptionsCallback::onUnsetOption);
- AddHandler("set_option", &EmitPreprocessOptionsCallback::onSetOption);
-
- staticMembersInitialized_ = true;
- }
- }
-
- void operator()(const Init* I,
- unsigned IndentLevel, raw_ostream& O) const
- {
- InvokeDagInitHandler(this, I, IndentLevel, O);
- }
-
-};
-
-/// EmitPreprocessOptions - Emit the PreprocessOptions() function.
-void EmitPreprocessOptions (const RecordKeeper& Records,
- const OptionDescriptions& OptDecs, raw_ostream& O)
-{
- O << "int PreprocessOptions () {\n";
-
- const RecordVector& OptionPreprocessors =
- Records.getAllDerivedDefinitions("OptionPreprocessor");
-
- for (RecordVector::const_iterator B = OptionPreprocessors.begin(),
- E = OptionPreprocessors.end(); B!=E; ++B) {
- DagInit* Case = (*B)->getValueAsDag("preprocessor");
- EmitCaseConstructHandler(Case, Indent1,
- EmitPreprocessOptionsCallback(OptDecs),
- false, OptDecs, O);
- }
-
- O << '\n';
- O.indent(Indent1) << "return 0;\n";
- O << "}\n\n";
-}
-
-class DoEmitPopulateLanguageMap;
-typedef void (DoEmitPopulateLanguageMap::* DoEmitPopulateLanguageMapHandler)
-(const DagInit& D);
-
-class DoEmitPopulateLanguageMap
-: public HandlerTable<DoEmitPopulateLanguageMapHandler>
-{
-private:
- raw_ostream& O_;
-
-public:
-
- explicit DoEmitPopulateLanguageMap (raw_ostream& O) : O_(O) {
- if (!staticMembersInitialized_) {
- AddHandler("lang_to_suffixes",
- &DoEmitPopulateLanguageMap::onLangToSuffixes);
-
- staticMembersInitialized_ = true;
- }
- }
-
- void operator() (Init* I) {
- InvokeDagInitHandler(this, I);
- }
-
-private:
-
- void onLangToSuffixes (const DagInit& d) {
- CheckNumberOfArguments(d, 2);
-
- const std::string& Lang = InitPtrToString(d.getArg(0));
- Init* Suffixes = d.getArg(1);
-
- // Second argument to lang_to_suffixes is either a single string...
- if (typeid(*Suffixes) == typeid(StringInit)) {
- O_.indent(Indent1) << "langMap[\"" << InitPtrToString(Suffixes)
- << "\"] = \"" << Lang << "\";\n";
- }
- // ...or a list of strings.
- else {
- const ListInit& Lst = InitPtrToList(Suffixes);
- assert(Lst.size() != 0);
- for (ListInit::const_iterator B = Lst.begin(), E = Lst.end();
- B != E; ++B) {
- O_.indent(Indent1) << "langMap[\"" << InitPtrToString(*B)
- << "\"] = \"" << Lang << "\";\n";
- }
- }
- }
-
-};
-
-/// EmitPopulateLanguageMap - Emit the PopulateLanguageMap() function.
-void EmitPopulateLanguageMap (const RecordKeeper& Records, raw_ostream& O)
-{
- O << "int PopulateLanguageMap (LanguageMap& langMap) {\n";
-
- // For each LanguageMap:
- const RecordVector& LangMaps =
- Records.getAllDerivedDefinitions("LanguageMap");
-
- // Call DoEmitPopulateLanguageMap.
- for (RecordVector::const_iterator B = LangMaps.begin(),
- E = LangMaps.end(); B!=E; ++B) {
- ListInit* LangMap = (*B)->getValueAsListInit("map");
- std::for_each(LangMap->begin(), LangMap->end(),
- DoEmitPopulateLanguageMap(O));
- }
-
- O << '\n';
- O.indent(Indent1) << "return 0;\n";
- O << "}\n\n";
-}
-
-/// EmitEdgePropertyHandlerCallback - Emits code that handles edge
-/// properties. Helper function passed to EmitCaseConstructHandler() by
-/// EmitEdgeClass().
-void EmitEdgePropertyHandlerCallback (const Init* i, unsigned IndentLevel,
- raw_ostream& O) {
- const DagInit& d = InitPtrToDag(i);
- const std::string& OpName = GetOperatorName(d);
-
- if (OpName == "inc_weight") {
- O.indent(IndentLevel) << "ret += ";
- }
- else if (OpName == "error") {
- CheckNumberOfArguments(d, 1);
- O.indent(IndentLevel) << "PrintError(\""
- << InitPtrToString(d.getArg(0))
- << "\");\n";
- O.indent(IndentLevel) << "return -1;\n";
- return;
- }
- else {
- throw "Unknown operator in edge properties list: '" + OpName + "'!"
- "\nOnly 'inc_weight', 'dec_weight' and 'error' are allowed.";
- }
-
- if (d.getNumArgs() > 0)
- O << InitPtrToInt(d.getArg(0)) << ";\n";
- else
- O << "2;\n";
-
-}
-
-/// EmitEdgeClass - Emit a single Edge# class.
-void EmitEdgeClass (unsigned N, const std::string& Target,
- const DagInit& Case, const OptionDescriptions& OptDescs,
- raw_ostream& O) {
-
- // Class constructor.
- O << "class Edge" << N << ": public Edge {\n"
- << "public:\n";
- O.indent(Indent1) << "Edge" << N << "() : Edge(\"" << Target
- << "\") {}\n\n";
-
- // Function Weight().
- O.indent(Indent1)
- << "int Weight(const InputLanguagesSet& InLangs) const {\n";
- O.indent(Indent2) << "unsigned ret = 0;\n";
-
- // Handle the 'case' construct.
- EmitCaseConstructHandler(&Case, Indent2, EmitEdgePropertyHandlerCallback,
- false, OptDescs, O);
-
- O.indent(Indent2) << "return ret;\n";
- O.indent(Indent1) << "}\n\n};\n\n";
-}
-
-/// EmitEdgeClasses - Emit Edge* classes that represent graph edges.
-void EmitEdgeClasses (const DagVector& EdgeVector,
- const OptionDescriptions& OptDescs,
- raw_ostream& O) {
- int i = 0;
- for (DagVector::const_iterator B = EdgeVector.begin(),
- E = EdgeVector.end(); B != E; ++B) {
- const DagInit& Edge = **B;
- const std::string& Name = GetOperatorName(Edge);
-
- if (Name == "optional_edge") {
- assert(IsOptionalEdge(Edge));
- const std::string& NodeB = InitPtrToString(Edge.getArg(1));
-
- const DagInit& Weight = InitPtrToDag(Edge.getArg(2));
- EmitEdgeClass(i, NodeB, Weight, OptDescs, O);
- }
- else if (Name != "edge") {
- throw "Unknown edge class: '" + Name + "'!";
- }
-
- ++i;
- }
-}
-
-/// EmitPopulateCompilationGraph - Emit the PopulateCompilationGraph() function.
-void EmitPopulateCompilationGraph (const DagVector& EdgeVector,
- const ToolDescriptions& ToolDescs,
- raw_ostream& O)
-{
- O << "int PopulateCompilationGraph (CompilationGraph& G) {\n";
-
- for (ToolDescriptions::const_iterator B = ToolDescs.begin(),
- E = ToolDescs.end(); B != E; ++B)
- O.indent(Indent1) << "G.insertNode(new " << (*B)->Name << "());\n";
-
- O << '\n';
-
- // Insert edges.
-
- int i = 0;
- for (DagVector::const_iterator B = EdgeVector.begin(),
- E = EdgeVector.end(); B != E; ++B) {
- const DagInit& Edge = **B;
- const std::string& NodeA = InitPtrToString(Edge.getArg(0));
- const std::string& NodeB = InitPtrToString(Edge.getArg(1));
-
- O.indent(Indent1) << "if (int ret = G.insertEdge(\"" << NodeA << "\", ";
-
- if (IsOptionalEdge(Edge))
- O << "new Edge" << i << "()";
- else
- O << "new SimpleEdge(\"" << NodeB << "\")";
-
- O << "))\n";
- O.indent(Indent2) << "return ret;\n";
-
- ++i;
- }
-
- O << '\n';
- O.indent(Indent1) << "return 0;\n";
- O << "}\n\n";
-}
-
-/// HookInfo - Information about the hook type and number of arguments.
-struct HookInfo {
-
- // A hook can either have a single parameter of type std::vector<std::string>,
- // or NumArgs parameters of type const char*.
- enum HookType { ListHook, ArgHook };
-
- HookType Type;
- unsigned NumArgs;
-
- HookInfo() : Type(ArgHook), NumArgs(1)
- {}
-
- HookInfo(HookType T) : Type(T), NumArgs(1)
- {}
-
- HookInfo(unsigned N) : Type(ArgHook), NumArgs(N)
- {}
-};
-
-typedef llvm::StringMap<HookInfo> HookInfoMap;
-
-/// ExtractHookNames - Extract the hook names from all instances of
-/// $CALL(HookName) in the provided command line string/action. Helper
-/// function used by FillInHookNames().
-class ExtractHookNames {
- HookInfoMap& HookNames_;
- const OptionDescriptions& OptDescs_;
-public:
- ExtractHookNames(HookInfoMap& HookNames, const OptionDescriptions& OptDescs)
- : HookNames_(HookNames), OptDescs_(OptDescs)
- {}
-
- void onAction (const DagInit& Dag) {
- const std::string& Name = GetOperatorName(Dag);
-
- if (Name == "forward_transformed_value") {
- CheckNumberOfArguments(Dag, 2);
- const std::string& OptName = InitPtrToString(Dag.getArg(0));
- const std::string& HookName = InitPtrToString(Dag.getArg(1));
- const OptionDescription& D =
- OptDescs_.FindParameterListOrParameter(OptName);
-
- HookNames_[HookName] = HookInfo(D.isList() ? HookInfo::ListHook
- : HookInfo::ArgHook);
- }
- else if (Name == "append_cmd" || Name == "output_suffix") {
- CheckNumberOfArguments(Dag, 1);
- this->onCmdLine(InitPtrToString(Dag.getArg(0)));
- }
- }
-
- void onCmdLine(const std::string& Cmd) {
- StrVector cmds;
- TokenizeCmdLine(Cmd, cmds);
-
- for (StrVector::const_iterator B = cmds.begin(), E = cmds.end();
- B != E; ++B) {
- const std::string& cmd = *B;
-
- if (cmd == "$CALL") {
- unsigned NumArgs = 0;
- CheckedIncrement(B, E, "Syntax error in $CALL invocation!");
- const std::string& HookName = *B;
-
- if (HookName.at(0) == ')')
- throw "$CALL invoked with no arguments!";
-
- while (++B != E && B->at(0) != ')') {
- ++NumArgs;
- }
-
- HookInfoMap::const_iterator H = HookNames_.find(HookName);
-
- if (H != HookNames_.end() && H->second.NumArgs != NumArgs &&
- H->second.Type != HookInfo::ArgHook)
- throw "Overloading of hooks is not allowed. Overloaded hook: "
- + HookName;
- else
- HookNames_[HookName] = HookInfo(NumArgs);
- }
- }
- }
-
- void operator()(const Init* Arg) {
-
- // We're invoked on an action (either a dag or a dag list).
- if (typeid(*Arg) == typeid(DagInit)) {
- const DagInit& Dag = InitPtrToDag(Arg);
- this->onAction(Dag);
- return;
- }
- else if (typeid(*Arg) == typeid(ListInit)) {
- const ListInit& List = InitPtrToList(Arg);
- for (ListInit::const_iterator B = List.begin(), E = List.end(); B != E;
- ++B) {
- const DagInit& Dag = InitPtrToDag(*B);
- this->onAction(Dag);
- }
- return;
- }
-
- // We're invoked on a command line string.
- this->onCmdLine(InitPtrToString(Arg));
- }
-
- void operator()(const Init* Statement, unsigned) {
- this->operator()(Statement);
- }
-};
-
-/// FillInHookNames - Actually extract the hook names from all command
-/// line strings. Helper function used by EmitHookDeclarations().
-void FillInHookNames(const ToolDescriptions& ToolDescs,
- const OptionDescriptions& OptDescs,
- HookInfoMap& HookNames)
-{
- // For all tool descriptions:
- for (ToolDescriptions::const_iterator B = ToolDescs.begin(),
- E = ToolDescs.end(); B != E; ++B) {
- const ToolDescription& D = *(*B);
-
- // Look for 'forward_transformed_value' in 'actions'.
- if (D.Actions)
- WalkCase(D.Actions, Id(), ExtractHookNames(HookNames, OptDescs));
-
- // Look for hook invocations in 'cmd_line'.
- if (!D.CmdLine)
- continue;
- if (dynamic_cast<StringInit*>(D.CmdLine))
- // This is a string.
- ExtractHookNames(HookNames, OptDescs).operator()(D.CmdLine);
- else
- // This is a 'case' construct.
- WalkCase(D.CmdLine, Id(), ExtractHookNames(HookNames, OptDescs));
- }
-}
-
-/// EmitHookDeclarations - Parse CmdLine fields of all the tool
-/// property records and emit hook function declaration for each
-/// instance of $CALL(HookName).
-void EmitHookDeclarations(const ToolDescriptions& ToolDescs,
- const OptionDescriptions& OptDescs, raw_ostream& O) {
- HookInfoMap HookNames;
-
- FillInHookNames(ToolDescs, OptDescs, HookNames);
- if (HookNames.empty())
- return;
-
- for (HookInfoMap::const_iterator B = HookNames.begin(),
- E = HookNames.end(); B != E; ++B) {
- StringRef HookName = B->first();
- const HookInfo &Info = B->second;
-
- O.indent(Indent1) << "std::string " << HookName << "(";
-
- if (Info.Type == HookInfo::ArgHook) {
- for (unsigned i = 0, j = Info.NumArgs; i < j; ++i) {
- O << "const char* Arg" << i << (i+1 == j ? "" : ", ");
- }
- }
- else {
- O << "const std::vector<std::string>& Arg";
- }
-
- O <<");\n";
- }
-}
-
-/// EmitIncludes - Emit necessary #include directives and some
-/// additional declarations.
-void EmitIncludes(raw_ostream& O) {
- O << "#include \"llvm/CompilerDriver/BuiltinOptions.h\"\n"
- << "#include \"llvm/CompilerDriver/CompilationGraph.h\"\n"
- << "#include \"llvm/CompilerDriver/Error.h\"\n"
- << "#include \"llvm/CompilerDriver/Tool.h\"\n\n"
-
- << "#include \"llvm/Support/CommandLine.h\"\n"
- << "#include \"llvm/Support/raw_ostream.h\"\n\n"
-
- << "#include <algorithm>\n"
- << "#include <cstdlib>\n"
- << "#include <iterator>\n"
- << "#include <stdexcept>\n\n"
-
- << "using namespace llvm;\n"
- << "using namespace llvmc;\n\n"
-
- << "inline const char* checkCString(const char* s)\n"
- << "{ return s == NULL ? \"\" : s; }\n\n";
-}
-
-
-/// DriverData - Holds all information about the driver.
-struct DriverData {
- OptionDescriptions OptDescs;
- ToolDescriptions ToolDescs;
- DagVector Edges;
- bool HasSink;
-};
-
-/// HasSink - Go through the list of tool descriptions and check if
-/// there are any with the 'sink' property set.
-bool HasSink(const ToolDescriptions& ToolDescs) {
- for (ToolDescriptions::const_iterator B = ToolDescs.begin(),
- E = ToolDescs.end(); B != E; ++B)
- if ((*B)->isSink())
- return true;
-
- return false;
-}
-
-/// CollectDriverData - Collect compilation graph edges, tool properties and
-/// option properties from the parse tree.
-void CollectDriverData (const RecordKeeper& Records, DriverData& Data) {
- // Collect option properties.
- const RecordVector& OptionLists =
- Records.getAllDerivedDefinitions("OptionList");
- CollectOptionDescriptions(OptionLists, Data.OptDescs);
-
- // Collect tool properties.
- const RecordVector& Tools = Records.getAllDerivedDefinitions("Tool");
- CollectToolDescriptions(Tools, Data.ToolDescs);
- Data.HasSink = HasSink(Data.ToolDescs);
-
- // Collect compilation graph edges.
- const RecordVector& CompilationGraphs =
- Records.getAllDerivedDefinitions("CompilationGraph");
- FillInEdgeVector(CompilationGraphs, Data.Edges);
-}
-
-/// CheckDriverData - Perform some sanity checks on the collected data.
-void CheckDriverData(DriverData& Data) {
- // Filter out all tools not mentioned in the compilation graph.
- FilterNotInGraph(Data.Edges, Data.ToolDescs);
-
- // Typecheck the compilation graph.
- // TODO: use a genuine graph representation instead of a vector and check for
- // multiple edges.
- TypecheckGraph(Data.Edges, Data.ToolDescs);
-
- // Check that there are no options without side effects (specified
- // only in the OptionList).
- CheckForSuperfluousOptions(Data.Edges, Data.ToolDescs, Data.OptDescs);
-}
-
-void EmitDriverCode(const DriverData& Data,
- raw_ostream& O, RecordKeeper &Records) {
- // Emit file header.
- EmitIncludes(O);
-
- // Emit global option registration code.
- O << "namespace llvmc {\n"
- << "namespace autogenerated {\n\n";
- EmitOptionDefinitions(Data.OptDescs, Data.HasSink, O);
- O << "} // End namespace autogenerated.\n"
- << "} // End namespace llvmc.\n\n";
-
- // Emit hook declarations.
- O << "namespace hooks {\n";
- EmitHookDeclarations(Data.ToolDescs, Data.OptDescs, O);
- O << "} // End namespace hooks.\n\n";
-
- O << "namespace {\n\n";
- O << "using namespace llvmc::autogenerated;\n\n";
-
- // Emit Tool classes.
- for (ToolDescriptions::const_iterator B = Data.ToolDescs.begin(),
- E = Data.ToolDescs.end(); B!=E; ++B)
- EmitToolClassDefinition(*(*B), Data.OptDescs, O);
-
- // Emit Edge# classes.
- EmitEdgeClasses(Data.Edges, Data.OptDescs, O);
-
- O << "} // End anonymous namespace.\n\n";
-
- O << "namespace llvmc {\n";
- O << "namespace autogenerated {\n\n";
-
- // Emit PreprocessOptions() function.
- EmitPreprocessOptions(Records, Data.OptDescs, O);
-
- // Emit PopulateLanguageMap() function
- // (language map maps from file extensions to language names).
- EmitPopulateLanguageMap(Records, O);
-
- // Emit PopulateCompilationGraph() function.
- EmitPopulateCompilationGraph(Data.Edges, Data.ToolDescs, O);
-
- O << "} // End namespace autogenerated.\n";
- O << "} // End namespace llvmc.\n\n";
-
- // EOF
-}
-
-
-// End of anonymous namespace
-}
-
-/// run - The back-end entry point.
-void LLVMCConfigurationEmitter::run (raw_ostream &O) {
- try {
- DriverData Data;
-
- CollectDriverData(Records, Data);
- CheckDriverData(Data);
-
- this->EmitSourceFileHeader("llvmc-based driver: auto-generated code", O);
- EmitDriverCode(Data, O, Records);
-
- } catch (std::exception& Error) {
- throw Error.what() + std::string(" - usually this means a syntax error.");
- }
-}
diff --git a/contrib/llvm/utils/TableGen/LLVMCConfigurationEmitter.h b/contrib/llvm/utils/TableGen/LLVMCConfigurationEmitter.h
deleted file mode 100644
index 0f2ff37..0000000
--- a/contrib/llvm/utils/TableGen/LLVMCConfigurationEmitter.h
+++ /dev/null
@@ -1,34 +0,0 @@
-//===- LLVMCConfigurationEmitter.cpp - Generate LLVMCC config ---*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open
-// Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This tablegen backend is responsible for emitting LLVMCC configuration code.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_UTILS_TABLEGEN_LLVMCCONF_EMITTER_H
-#define LLVM_UTILS_TABLEGEN_LLVMCCONF_EMITTER_H
-
-#include "TableGenBackend.h"
-
-namespace llvm {
-
- /// LLVMCConfigurationEmitter - TableGen backend that generates
- /// configuration code for LLVMC.
- class LLVMCConfigurationEmitter : public TableGenBackend {
- RecordKeeper &Records;
- public:
- explicit LLVMCConfigurationEmitter(RecordKeeper &records) :
- Records(records) {}
-
- // run - Output the asmwriter, returning true on failure.
- void run(raw_ostream &o);
- };
-}
-
-#endif //LLVM_UTILS_TABLEGEN_LLVMCCONF_EMITTER_H
diff --git a/contrib/llvm/utils/TableGen/NeonEmitter.cpp b/contrib/llvm/utils/TableGen/NeonEmitter.cpp
deleted file mode 100644
index ef977443..0000000
--- a/contrib/llvm/utils/TableGen/NeonEmitter.cpp
+++ /dev/null
@@ -1,1558 +0,0 @@
-//===- NeonEmitter.cpp - Generate arm_neon.h for use with clang -*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This tablegen backend is responsible for emitting arm_neon.h, which includes
-// a declaration and definition of each function specified by the ARM NEON
-// compiler interface. See ARM document DUI0348B.
-//
-// Each NEON instruction is implemented in terms of 1 or more functions which
-// are suffixed with the element type of the input vectors. Functions may be
-// implemented in terms of generic vector operations such as +, *, -, etc. or
-// by calling a __builtin_-prefixed function which will be handled by clang's
-// CodeGen library.
-//
-// Additional validation code can be generated by this file when runHeader() is
-// called, rather than the normal run() entry point. A complete set of tests
-// for Neon intrinsics can be generated by calling the runTests() entry point.
-//
-//===----------------------------------------------------------------------===//
-
-#include "NeonEmitter.h"
-#include "Error.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringExtras.h"
-#include <string>
-
-using namespace llvm;
-
-/// ParseTypes - break down a string such as "fQf" into a vector of StringRefs,
-/// which each StringRef representing a single type declared in the string.
-/// for "fQf" we would end up with 2 StringRefs, "f", and "Qf", representing
-/// 2xfloat and 4xfloat respectively.
-static void ParseTypes(Record *r, std::string &s,
- SmallVectorImpl<StringRef> &TV) {
- const char *data = s.data();
- int len = 0;
-
- for (unsigned i = 0, e = s.size(); i != e; ++i, ++len) {
- if (data[len] == 'P' || data[len] == 'Q' || data[len] == 'U')
- continue;
-
- switch (data[len]) {
- case 'c':
- case 's':
- case 'i':
- case 'l':
- case 'h':
- case 'f':
- break;
- default:
- throw TGError(r->getLoc(),
- "Unexpected letter: " + std::string(data + len, 1));
- break;
- }
- TV.push_back(StringRef(data, len + 1));
- data += len + 1;
- len = -1;
- }
-}
-
-/// Widen - Convert a type code into the next wider type. char -> short,
-/// short -> int, etc.
-static char Widen(const char t) {
- switch (t) {
- case 'c':
- return 's';
- case 's':
- return 'i';
- case 'i':
- return 'l';
- case 'h':
- return 'f';
- default: throw "unhandled type in widen!";
- }
- return '\0';
-}
-
-/// Narrow - Convert a type code into the next smaller type. short -> char,
-/// float -> half float, etc.
-static char Narrow(const char t) {
- switch (t) {
- case 's':
- return 'c';
- case 'i':
- return 's';
- case 'l':
- return 'i';
- case 'f':
- return 'h';
- default: throw "unhandled type in narrow!";
- }
- return '\0';
-}
-
-/// For a particular StringRef, return the base type code, and whether it has
-/// the quad-vector, polynomial, or unsigned modifiers set.
-static char ClassifyType(StringRef ty, bool &quad, bool &poly, bool &usgn) {
- unsigned off = 0;
-
- // remember quad.
- if (ty[off] == 'Q') {
- quad = true;
- ++off;
- }
-
- // remember poly.
- if (ty[off] == 'P') {
- poly = true;
- ++off;
- }
-
- // remember unsigned.
- if (ty[off] == 'U') {
- usgn = true;
- ++off;
- }
-
- // base type to get the type string for.
- return ty[off];
-}
-
-/// ModType - Transform a type code and its modifiers based on a mod code. The
-/// mod code definitions may be found at the top of arm_neon.td.
-static char ModType(const char mod, char type, bool &quad, bool &poly,
- bool &usgn, bool &scal, bool &cnst, bool &pntr) {
- switch (mod) {
- case 't':
- if (poly) {
- poly = false;
- usgn = true;
- }
- break;
- case 'u':
- usgn = true;
- poly = false;
- if (type == 'f')
- type = 'i';
- break;
- case 'x':
- usgn = false;
- poly = false;
- if (type == 'f')
- type = 'i';
- break;
- case 'f':
- if (type == 'h')
- quad = true;
- type = 'f';
- usgn = false;
- break;
- case 'g':
- quad = false;
- break;
- case 'w':
- type = Widen(type);
- quad = true;
- break;
- case 'n':
- type = Widen(type);
- break;
- case 'i':
- type = 'i';
- scal = true;
- break;
- case 'l':
- type = 'l';
- scal = true;
- usgn = true;
- break;
- case 's':
- case 'a':
- scal = true;
- break;
- case 'k':
- quad = true;
- break;
- case 'c':
- cnst = true;
- case 'p':
- pntr = true;
- scal = true;
- break;
- case 'h':
- type = Narrow(type);
- if (type == 'h')
- quad = false;
- break;
- case 'e':
- type = Narrow(type);
- usgn = true;
- break;
- default:
- break;
- }
- return type;
-}
-
-/// TypeString - for a modifier and type, generate the name of the typedef for
-/// that type. QUc -> uint8x8_t.
-static std::string TypeString(const char mod, StringRef typestr) {
- bool quad = false;
- bool poly = false;
- bool usgn = false;
- bool scal = false;
- bool cnst = false;
- bool pntr = false;
-
- if (mod == 'v')
- return "void";
- if (mod == 'i')
- return "int";
-
- // base type to get the type string for.
- char type = ClassifyType(typestr, quad, poly, usgn);
-
- // Based on the modifying character, change the type and width if necessary.
- type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
-
- SmallString<128> s;
-
- if (usgn)
- s.push_back('u');
-
- switch (type) {
- case 'c':
- s += poly ? "poly8" : "int8";
- if (scal)
- break;
- s += quad ? "x16" : "x8";
- break;
- case 's':
- s += poly ? "poly16" : "int16";
- if (scal)
- break;
- s += quad ? "x8" : "x4";
- break;
- case 'i':
- s += "int32";
- if (scal)
- break;
- s += quad ? "x4" : "x2";
- break;
- case 'l':
- s += "int64";
- if (scal)
- break;
- s += quad ? "x2" : "x1";
- break;
- case 'h':
- s += "float16";
- if (scal)
- break;
- s += quad ? "x8" : "x4";
- break;
- case 'f':
- s += "float32";
- if (scal)
- break;
- s += quad ? "x4" : "x2";
- break;
- default:
- throw "unhandled type!";
- break;
- }
-
- if (mod == '2')
- s += "x2";
- if (mod == '3')
- s += "x3";
- if (mod == '4')
- s += "x4";
-
- // Append _t, finishing the type string typedef type.
- s += "_t";
-
- if (cnst)
- s += " const";
-
- if (pntr)
- s += " *";
-
- return s.str();
-}
-
-/// BuiltinTypeString - for a modifier and type, generate the clang
-/// BuiltinsARM.def prototype code for the function. See the top of clang's
-/// Builtins.def for a description of the type strings.
-static std::string BuiltinTypeString(const char mod, StringRef typestr,
- ClassKind ck, bool ret) {
- bool quad = false;
- bool poly = false;
- bool usgn = false;
- bool scal = false;
- bool cnst = false;
- bool pntr = false;
-
- if (mod == 'v')
- return "v"; // void
- if (mod == 'i')
- return "i"; // int
-
- // base type to get the type string for.
- char type = ClassifyType(typestr, quad, poly, usgn);
-
- // Based on the modifying character, change the type and width if necessary.
- type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
-
- // All pointers are void* pointers. Change type to 'v' now.
- if (pntr) {
- usgn = false;
- poly = false;
- type = 'v';
- }
- // Treat half-float ('h') types as unsigned short ('s') types.
- if (type == 'h') {
- type = 's';
- usgn = true;
- }
- usgn = usgn | poly | ((ck == ClassI || ck == ClassW) && scal && type != 'f');
-
- if (scal) {
- SmallString<128> s;
-
- if (usgn)
- s.push_back('U');
- else if (type == 'c')
- s.push_back('S'); // make chars explicitly signed
-
- if (type == 'l') // 64-bit long
- s += "LLi";
- else
- s.push_back(type);
-
- if (cnst)
- s.push_back('C');
- if (pntr)
- s.push_back('*');
- return s.str();
- }
-
- // Since the return value must be one type, return a vector type of the
- // appropriate width which we will bitcast. An exception is made for
- // returning structs of 2, 3, or 4 vectors which are returned in a sret-like
- // fashion, storing them to a pointer arg.
- if (ret) {
- if (mod >= '2' && mod <= '4')
- return "vv*"; // void result with void* first argument
- if (mod == 'f' || (ck != ClassB && type == 'f'))
- return quad ? "V4f" : "V2f";
- if (ck != ClassB && type == 's')
- return quad ? "V8s" : "V4s";
- if (ck != ClassB && type == 'i')
- return quad ? "V4i" : "V2i";
- if (ck != ClassB && type == 'l')
- return quad ? "V2LLi" : "V1LLi";
-
- return quad ? "V16Sc" : "V8Sc";
- }
-
- // Non-return array types are passed as individual vectors.
- if (mod == '2')
- return quad ? "V16ScV16Sc" : "V8ScV8Sc";
- if (mod == '3')
- return quad ? "V16ScV16ScV16Sc" : "V8ScV8ScV8Sc";
- if (mod == '4')
- return quad ? "V16ScV16ScV16ScV16Sc" : "V8ScV8ScV8ScV8Sc";
-
- if (mod == 'f' || (ck != ClassB && type == 'f'))
- return quad ? "V4f" : "V2f";
- if (ck != ClassB && type == 's')
- return quad ? "V8s" : "V4s";
- if (ck != ClassB && type == 'i')
- return quad ? "V4i" : "V2i";
- if (ck != ClassB && type == 'l')
- return quad ? "V2LLi" : "V1LLi";
-
- return quad ? "V16Sc" : "V8Sc";
-}
-
-/// MangleName - Append a type or width suffix to a base neon function name,
-/// and insert a 'q' in the appropriate location if the operation works on
-/// 128b rather than 64b. E.g. turn "vst2_lane" into "vst2q_lane_f32", etc.
-static std::string MangleName(const std::string &name, StringRef typestr,
- ClassKind ck) {
- if (name == "vcvt_f32_f16")
- return name;
-
- bool quad = false;
- bool poly = false;
- bool usgn = false;
- char type = ClassifyType(typestr, quad, poly, usgn);
-
- std::string s = name;
-
- switch (type) {
- case 'c':
- switch (ck) {
- case ClassS: s += poly ? "_p8" : usgn ? "_u8" : "_s8"; break;
- case ClassI: s += "_i8"; break;
- case ClassW: s += "_8"; break;
- default: break;
- }
- break;
- case 's':
- switch (ck) {
- case ClassS: s += poly ? "_p16" : usgn ? "_u16" : "_s16"; break;
- case ClassI: s += "_i16"; break;
- case ClassW: s += "_16"; break;
- default: break;
- }
- break;
- case 'i':
- switch (ck) {
- case ClassS: s += usgn ? "_u32" : "_s32"; break;
- case ClassI: s += "_i32"; break;
- case ClassW: s += "_32"; break;
- default: break;
- }
- break;
- case 'l':
- switch (ck) {
- case ClassS: s += usgn ? "_u64" : "_s64"; break;
- case ClassI: s += "_i64"; break;
- case ClassW: s += "_64"; break;
- default: break;
- }
- break;
- case 'h':
- switch (ck) {
- case ClassS:
- case ClassI: s += "_f16"; break;
- case ClassW: s += "_16"; break;
- default: break;
- }
- break;
- case 'f':
- switch (ck) {
- case ClassS:
- case ClassI: s += "_f32"; break;
- case ClassW: s += "_32"; break;
- default: break;
- }
- break;
- default:
- throw "unhandled type!";
- break;
- }
- if (ck == ClassB)
- s += "_v";
-
- // Insert a 'q' before the first '_' character so that it ends up before
- // _lane or _n on vector-scalar operations.
- if (quad) {
- size_t pos = s.find('_');
- s = s.insert(pos, "q");
- }
- return s;
-}
-
-/// UseMacro - Examine the prototype string to determine if the intrinsic
-/// should be defined as a preprocessor macro instead of an inline function.
-static bool UseMacro(const std::string &proto) {
- // If this builtin takes an immediate argument, we need to #define it rather
- // than use a standard declaration, so that SemaChecking can range check
- // the immediate passed by the user.
- if (proto.find('i') != std::string::npos)
- return true;
-
- // Pointer arguments need to use macros to avoid hiding aligned attributes
- // from the pointer type.
- if (proto.find('p') != std::string::npos ||
- proto.find('c') != std::string::npos)
- return true;
-
- return false;
-}
-
-/// MacroArgUsedDirectly - Return true if argument i for an intrinsic that is
-/// defined as a macro should be accessed directly instead of being first
-/// assigned to a local temporary.
-static bool MacroArgUsedDirectly(const std::string &proto, unsigned i) {
- return (proto[i] == 'i' || proto[i] == 'p' || proto[i] == 'c');
-}
-
-// Generate the string "(argtype a, argtype b, ...)"
-static std::string GenArgs(const std::string &proto, StringRef typestr) {
- bool define = UseMacro(proto);
- char arg = 'a';
-
- std::string s;
- s += "(";
-
- for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
- if (define) {
- // Some macro arguments are used directly instead of being assigned
- // to local temporaries; prepend an underscore prefix to make their
- // names consistent with the local temporaries.
- if (MacroArgUsedDirectly(proto, i))
- s += "__";
- } else {
- s += TypeString(proto[i], typestr) + " __";
- }
- s.push_back(arg);
- if ((i + 1) < e)
- s += ", ";
- }
-
- s += ")";
- return s;
-}
-
-// Macro arguments are not type-checked like inline function arguments, so
-// assign them to local temporaries to get the right type checking.
-static std::string GenMacroLocals(const std::string &proto, StringRef typestr) {
- char arg = 'a';
- std::string s;
- bool generatedLocal = false;
-
- for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
- // Do not create a temporary for an immediate argument.
- // That would defeat the whole point of using a macro!
- if (proto[i] == 'i')
- continue;
- generatedLocal = true;
-
- // For other (non-immediate) arguments that are used directly, a local
- // temporary is still needed to get the correct type checking, even though
- // that temporary is not used for anything.
- if (MacroArgUsedDirectly(proto, i)) {
- s += TypeString(proto[i], typestr) + " __";
- s.push_back(arg);
- s += "_ = (__";
- s.push_back(arg);
- s += "); (void)__";
- s.push_back(arg);
- s += "_; ";
- continue;
- }
-
- s += TypeString(proto[i], typestr) + " __";
- s.push_back(arg);
- s += " = (";
- s.push_back(arg);
- s += "); ";
- }
-
- if (generatedLocal)
- s += "\\\n ";
- return s;
-}
-
-// Use the vmovl builtin to sign-extend or zero-extend a vector.
-static std::string Extend(StringRef typestr, const std::string &a) {
- std::string s;
- s = MangleName("vmovl", typestr, ClassS);
- s += "(" + a + ")";
- return s;
-}
-
-static std::string Duplicate(unsigned nElts, StringRef typestr,
- const std::string &a) {
- std::string s;
-
- s = "(" + TypeString('d', typestr) + "){ ";
- for (unsigned i = 0; i != nElts; ++i) {
- s += a;
- if ((i + 1) < nElts)
- s += ", ";
- }
- s += " }";
-
- return s;
-}
-
-static std::string SplatLane(unsigned nElts, const std::string &vec,
- const std::string &lane) {
- std::string s = "__builtin_shufflevector(" + vec + ", " + vec;
- for (unsigned i = 0; i < nElts; ++i)
- s += ", " + lane;
- s += ")";
- return s;
-}
-
-static unsigned GetNumElements(StringRef typestr, bool &quad) {
- quad = false;
- bool dummy = false;
- char type = ClassifyType(typestr, quad, dummy, dummy);
- unsigned nElts = 0;
- switch (type) {
- case 'c': nElts = 8; break;
- case 's': nElts = 4; break;
- case 'i': nElts = 2; break;
- case 'l': nElts = 1; break;
- case 'h': nElts = 4; break;
- case 'f': nElts = 2; break;
- default:
- throw "unhandled type!";
- break;
- }
- if (quad) nElts <<= 1;
- return nElts;
-}
-
-// Generate the definition for this intrinsic, e.g. "a + b" for OpAdd.
-static std::string GenOpString(OpKind op, const std::string &proto,
- StringRef typestr) {
- bool quad;
- unsigned nElts = GetNumElements(typestr, quad);
- bool define = UseMacro(proto);
-
- std::string ts = TypeString(proto[0], typestr);
- std::string s;
- if (!define) {
- s = "return ";
- }
-
- switch(op) {
- case OpAdd:
- s += "__a + __b;";
- break;
- case OpAddl:
- s += Extend(typestr, "__a") + " + " + Extend(typestr, "__b") + ";";
- break;
- case OpAddw:
- s += "__a + " + Extend(typestr, "__b") + ";";
- break;
- case OpSub:
- s += "__a - __b;";
- break;
- case OpSubl:
- s += Extend(typestr, "__a") + " - " + Extend(typestr, "__b") + ";";
- break;
- case OpSubw:
- s += "__a - " + Extend(typestr, "__b") + ";";
- break;
- case OpMulN:
- s += "__a * " + Duplicate(nElts, typestr, "__b") + ";";
- break;
- case OpMulLane:
- s += "__a * " + SplatLane(nElts, "__b", "__c") + ";";
- break;
- case OpMul:
- s += "__a * __b;";
- break;
- case OpMullLane:
- s += MangleName("vmull", typestr, ClassS) + "(__a, " +
- SplatLane(nElts, "__b", "__c") + ");";
- break;
- case OpMlaN:
- s += "__a + (__b * " + Duplicate(nElts, typestr, "__c") + ");";
- break;
- case OpMlaLane:
- s += "__a + (__b * " + SplatLane(nElts, "__c", "__d") + ");";
- break;
- case OpMla:
- s += "__a + (__b * __c);";
- break;
- case OpMlalN:
- s += "__a + " + MangleName("vmull", typestr, ClassS) + "(__b, " +
- Duplicate(nElts, typestr, "__c") + ");";
- break;
- case OpMlalLane:
- s += "__a + " + MangleName("vmull", typestr, ClassS) + "(__b, " +
- SplatLane(nElts, "__c", "__d") + ");";
- break;
- case OpMlal:
- s += "__a + " + MangleName("vmull", typestr, ClassS) + "(__b, __c);";
- break;
- case OpMlsN:
- s += "__a - (__b * " + Duplicate(nElts, typestr, "__c") + ");";
- break;
- case OpMlsLane:
- s += "__a - (__b * " + SplatLane(nElts, "__c", "__d") + ");";
- break;
- case OpMls:
- s += "__a - (__b * __c);";
- break;
- case OpMlslN:
- s += "__a - " + MangleName("vmull", typestr, ClassS) + "(__b, " +
- Duplicate(nElts, typestr, "__c") + ");";
- break;
- case OpMlslLane:
- s += "__a - " + MangleName("vmull", typestr, ClassS) + "(__b, " +
- SplatLane(nElts, "__c", "__d") + ");";
- break;
- case OpMlsl:
- s += "__a - " + MangleName("vmull", typestr, ClassS) + "(__b, __c);";
- break;
- case OpQDMullLane:
- s += MangleName("vqdmull", typestr, ClassS) + "(__a, " +
- SplatLane(nElts, "__b", "__c") + ");";
- break;
- case OpQDMlalLane:
- s += MangleName("vqdmlal", typestr, ClassS) + "(__a, __b, " +
- SplatLane(nElts, "__c", "__d") + ");";
- break;
- case OpQDMlslLane:
- s += MangleName("vqdmlsl", typestr, ClassS) + "(__a, __b, " +
- SplatLane(nElts, "__c", "__d") + ");";
- break;
- case OpQDMulhLane:
- s += MangleName("vqdmulh", typestr, ClassS) + "(__a, " +
- SplatLane(nElts, "__b", "__c") + ");";
- break;
- case OpQRDMulhLane:
- s += MangleName("vqrdmulh", typestr, ClassS) + "(__a, " +
- SplatLane(nElts, "__b", "__c") + ");";
- break;
- case OpEq:
- s += "(" + ts + ")(__a == __b);";
- break;
- case OpGe:
- s += "(" + ts + ")(__a >= __b);";
- break;
- case OpLe:
- s += "(" + ts + ")(__a <= __b);";
- break;
- case OpGt:
- s += "(" + ts + ")(__a > __b);";
- break;
- case OpLt:
- s += "(" + ts + ")(__a < __b);";
- break;
- case OpNeg:
- s += " -__a;";
- break;
- case OpNot:
- s += " ~__a;";
- break;
- case OpAnd:
- s += "__a & __b;";
- break;
- case OpOr:
- s += "__a | __b;";
- break;
- case OpXor:
- s += "__a ^ __b;";
- break;
- case OpAndNot:
- s += "__a & ~__b;";
- break;
- case OpOrNot:
- s += "__a | ~__b;";
- break;
- case OpCast:
- s += "(" + ts + ")__a;";
- break;
- case OpConcat:
- s += "(" + ts + ")__builtin_shufflevector((int64x1_t)__a";
- s += ", (int64x1_t)__b, 0, 1);";
- break;
- case OpHi:
- s += "(" + ts +
- ")__builtin_shufflevector((int64x2_t)__a, (int64x2_t)__a, 1);";
- break;
- case OpLo:
- s += "(" + ts +
- ")__builtin_shufflevector((int64x2_t)__a, (int64x2_t)__a, 0);";
- break;
- case OpDup:
- s += Duplicate(nElts, typestr, "__a") + ";";
- break;
- case OpDupLane:
- s += SplatLane(nElts, "__a", "__b") + ";";
- break;
- case OpSelect:
- // ((0 & 1) | (~0 & 2))
- s += "(" + ts + ")";
- ts = TypeString(proto[1], typestr);
- s += "((__a & (" + ts + ")__b) | ";
- s += "(~__a & (" + ts + ")__c));";
- break;
- case OpRev16:
- s += "__builtin_shufflevector(__a, __a";
- for (unsigned i = 2; i <= nElts; i += 2)
- for (unsigned j = 0; j != 2; ++j)
- s += ", " + utostr(i - j - 1);
- s += ");";
- break;
- case OpRev32: {
- unsigned WordElts = nElts >> (1 + (int)quad);
- s += "__builtin_shufflevector(__a, __a";
- for (unsigned i = WordElts; i <= nElts; i += WordElts)
- for (unsigned j = 0; j != WordElts; ++j)
- s += ", " + utostr(i - j - 1);
- s += ");";
- break;
- }
- case OpRev64: {
- unsigned DblWordElts = nElts >> (int)quad;
- s += "__builtin_shufflevector(__a, __a";
- for (unsigned i = DblWordElts; i <= nElts; i += DblWordElts)
- for (unsigned j = 0; j != DblWordElts; ++j)
- s += ", " + utostr(i - j - 1);
- s += ");";
- break;
- }
- case OpAbdl: {
- std::string abd = MangleName("vabd", typestr, ClassS) + "(__a, __b)";
- if (typestr[0] != 'U') {
- // vabd results are always unsigned and must be zero-extended.
- std::string utype = "U" + typestr.str();
- s += "(" + TypeString(proto[0], typestr) + ")";
- abd = "(" + TypeString('d', utype) + ")" + abd;
- s += Extend(utype, abd) + ";";
- } else {
- s += Extend(typestr, abd) + ";";
- }
- break;
- }
- case OpAba:
- s += "__a + " + MangleName("vabd", typestr, ClassS) + "(__b, __c);";
- break;
- case OpAbal: {
- s += "__a + ";
- std::string abd = MangleName("vabd", typestr, ClassS) + "(__b, __c)";
- if (typestr[0] != 'U') {
- // vabd results are always unsigned and must be zero-extended.
- std::string utype = "U" + typestr.str();
- s += "(" + TypeString(proto[0], typestr) + ")";
- abd = "(" + TypeString('d', utype) + ")" + abd;
- s += Extend(utype, abd) + ";";
- } else {
- s += Extend(typestr, abd) + ";";
- }
- break;
- }
- default:
- throw "unknown OpKind!";
- break;
- }
- return s;
-}
-
-static unsigned GetNeonEnum(const std::string &proto, StringRef typestr) {
- unsigned mod = proto[0];
- unsigned ret = 0;
-
- if (mod == 'v' || mod == 'f')
- mod = proto[1];
-
- bool quad = false;
- bool poly = false;
- bool usgn = false;
- bool scal = false;
- bool cnst = false;
- bool pntr = false;
-
- // Base type to get the type string for.
- char type = ClassifyType(typestr, quad, poly, usgn);
-
- // Based on the modifying character, change the type and width if necessary.
- type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
-
- if (usgn)
- ret |= 0x08;
- if (quad && proto[1] != 'g')
- ret |= 0x10;
-
- switch (type) {
- case 'c':
- ret |= poly ? 5 : 0;
- break;
- case 's':
- ret |= poly ? 6 : 1;
- break;
- case 'i':
- ret |= 2;
- break;
- case 'l':
- ret |= 3;
- break;
- case 'h':
- ret |= 7;
- break;
- case 'f':
- ret |= 4;
- break;
- default:
- throw "unhandled type!";
- break;
- }
- return ret;
-}
-
-// Generate the definition for this intrinsic, e.g. __builtin_neon_cls(a)
-static std::string GenBuiltin(const std::string &name, const std::string &proto,
- StringRef typestr, ClassKind ck) {
- std::string s;
-
- // If this builtin returns a struct 2, 3, or 4 vectors, pass it as an implicit
- // sret-like argument.
- bool sret = (proto[0] >= '2' && proto[0] <= '4');
-
- bool define = UseMacro(proto);
-
- // Check if the prototype has a scalar operand with the type of the vector
- // elements. If not, bitcasting the args will take care of arg checking.
- // The actual signedness etc. will be taken care of with special enums.
- if (proto.find('s') == std::string::npos)
- ck = ClassB;
-
- if (proto[0] != 'v') {
- std::string ts = TypeString(proto[0], typestr);
-
- if (define) {
- if (sret)
- s += ts + " r; ";
- else
- s += "(" + ts + ")";
- } else if (sret) {
- s += ts + " r; ";
- } else {
- s += "return (" + ts + ")";
- }
- }
-
- bool splat = proto.find('a') != std::string::npos;
-
- s += "__builtin_neon_";
- if (splat) {
- // Call the non-splat builtin: chop off the "_n" suffix from the name.
- std::string vname(name, 0, name.size()-2);
- s += MangleName(vname, typestr, ck);
- } else {
- s += MangleName(name, typestr, ck);
- }
- s += "(";
-
- // Pass the address of the return variable as the first argument to sret-like
- // builtins.
- if (sret)
- s += "&r, ";
-
- char arg = 'a';
- for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
- std::string args = std::string(&arg, 1);
-
- // Use the local temporaries instead of the macro arguments.
- args = "__" + args;
-
- bool argQuad = false;
- bool argPoly = false;
- bool argUsgn = false;
- bool argScalar = false;
- bool dummy = false;
- char argType = ClassifyType(typestr, argQuad, argPoly, argUsgn);
- argType = ModType(proto[i], argType, argQuad, argPoly, argUsgn, argScalar,
- dummy, dummy);
-
- // Handle multiple-vector values specially, emitting each subvector as an
- // argument to the __builtin.
- if (proto[i] >= '2' && proto[i] <= '4') {
- // Check if an explicit cast is needed.
- if (argType != 'c' || argPoly || argUsgn)
- args = (argQuad ? "(int8x16_t)" : "(int8x8_t)") + args;
-
- for (unsigned vi = 0, ve = proto[i] - '0'; vi != ve; ++vi) {
- s += args + ".val[" + utostr(vi) + "]";
- if ((vi + 1) < ve)
- s += ", ";
- }
- if ((i + 1) < e)
- s += ", ";
-
- continue;
- }
-
- if (splat && (i + 1) == e)
- args = Duplicate(GetNumElements(typestr, argQuad), typestr, args);
-
- // Check if an explicit cast is needed.
- if ((splat || !argScalar) &&
- ((ck == ClassB && argType != 'c') || argPoly || argUsgn)) {
- std::string argTypeStr = "c";
- if (ck != ClassB)
- argTypeStr = argType;
- if (argQuad)
- argTypeStr = "Q" + argTypeStr;
- args = "(" + TypeString('d', argTypeStr) + ")" + args;
- }
-
- s += args;
- if ((i + 1) < e)
- s += ", ";
- }
-
- // Extra constant integer to hold type class enum for this function, e.g. s8
- if (ck == ClassB)
- s += ", " + utostr(GetNeonEnum(proto, typestr));
-
- s += ");";
-
- if (proto[0] != 'v' && sret) {
- if (define)
- s += " r;";
- else
- s += " return r;";
- }
- return s;
-}
-
-static std::string GenBuiltinDef(const std::string &name,
- const std::string &proto,
- StringRef typestr, ClassKind ck) {
- std::string s("BUILTIN(__builtin_neon_");
-
- // If all types are the same size, bitcasting the args will take care
- // of arg checking. The actual signedness etc. will be taken care of with
- // special enums.
- if (proto.find('s') == std::string::npos)
- ck = ClassB;
-
- s += MangleName(name, typestr, ck);
- s += ", \"";
-
- for (unsigned i = 0, e = proto.size(); i != e; ++i)
- s += BuiltinTypeString(proto[i], typestr, ck, i == 0);
-
- // Extra constant integer to hold type class enum for this function, e.g. s8
- if (ck == ClassB)
- s += "i";
-
- s += "\", \"n\")";
- return s;
-}
-
-static std::string GenIntrinsic(const std::string &name,
- const std::string &proto,
- StringRef outTypeStr, StringRef inTypeStr,
- OpKind kind, ClassKind classKind) {
- assert(!proto.empty() && "");
- bool define = UseMacro(proto);
- std::string s;
-
- // static always inline + return type
- if (define)
- s += "#define ";
- else
- s += "__ai " + TypeString(proto[0], outTypeStr) + " ";
-
- // Function name with type suffix
- std::string mangledName = MangleName(name, outTypeStr, ClassS);
- if (outTypeStr != inTypeStr) {
- // If the input type is different (e.g., for vreinterpret), append a suffix
- // for the input type. String off a "Q" (quad) prefix so that MangleName
- // does not insert another "q" in the name.
- unsigned typeStrOff = (inTypeStr[0] == 'Q' ? 1 : 0);
- StringRef inTypeNoQuad = inTypeStr.substr(typeStrOff);
- mangledName = MangleName(mangledName, inTypeNoQuad, ClassS);
- }
- s += mangledName;
-
- // Function arguments
- s += GenArgs(proto, inTypeStr);
-
- // Definition.
- if (define) {
- s += " __extension__ ({ \\\n ";
- s += GenMacroLocals(proto, inTypeStr);
- } else {
- s += " { \\\n ";
- }
-
- if (kind != OpNone)
- s += GenOpString(kind, proto, outTypeStr);
- else
- s += GenBuiltin(name, proto, outTypeStr, classKind);
- if (define)
- s += " })";
- else
- s += " }";
- s += "\n";
- return s;
-}
-
-/// run - Read the records in arm_neon.td and output arm_neon.h. arm_neon.h
-/// is comprised of type definitions and function declarations.
-void NeonEmitter::run(raw_ostream &OS) {
- OS <<
- "/*===---- arm_neon.h - ARM Neon intrinsics ------------------------------"
- "---===\n"
- " *\n"
- " * Permission is hereby granted, free of charge, to any person obtaining "
- "a copy\n"
- " * of this software and associated documentation files (the \"Software\"),"
- " to deal\n"
- " * in the Software without restriction, including without limitation the "
- "rights\n"
- " * to use, copy, modify, merge, publish, distribute, sublicense, "
- "and/or sell\n"
- " * copies of the Software, and to permit persons to whom the Software is\n"
- " * furnished to do so, subject to the following conditions:\n"
- " *\n"
- " * The above copyright notice and this permission notice shall be "
- "included in\n"
- " * all copies or substantial portions of the Software.\n"
- " *\n"
- " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, "
- "EXPRESS OR\n"
- " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF "
- "MERCHANTABILITY,\n"
- " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT "
- "SHALL THE\n"
- " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR "
- "OTHER\n"
- " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, "
- "ARISING FROM,\n"
- " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER "
- "DEALINGS IN\n"
- " * THE SOFTWARE.\n"
- " *\n"
- " *===--------------------------------------------------------------------"
- "---===\n"
- " */\n\n";
-
- OS << "#ifndef __ARM_NEON_H\n";
- OS << "#define __ARM_NEON_H\n\n";
-
- OS << "#ifndef __ARM_NEON__\n";
- OS << "#error \"NEON support not enabled\"\n";
- OS << "#endif\n\n";
-
- OS << "#include <stdint.h>\n\n";
-
- // Emit NEON-specific scalar typedefs.
- OS << "typedef float float32_t;\n";
- OS << "typedef int8_t poly8_t;\n";
- OS << "typedef int16_t poly16_t;\n";
- OS << "typedef uint16_t float16_t;\n";
-
- // Emit Neon vector typedefs.
- std::string TypedefTypes("cQcsQsiQilQlUcQUcUsQUsUiQUiUlQUlhQhfQfPcQPcPsQPs");
- SmallVector<StringRef, 24> TDTypeVec;
- ParseTypes(0, TypedefTypes, TDTypeVec);
-
- // Emit vector typedefs.
- for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) {
- bool dummy, quad = false, poly = false;
- (void) ClassifyType(TDTypeVec[i], quad, poly, dummy);
- if (poly)
- OS << "typedef __attribute__((neon_polyvector_type(";
- else
- OS << "typedef __attribute__((neon_vector_type(";
-
- unsigned nElts = GetNumElements(TDTypeVec[i], quad);
- OS << utostr(nElts) << "))) ";
- if (nElts < 10)
- OS << " ";
-
- OS << TypeString('s', TDTypeVec[i]);
- OS << " " << TypeString('d', TDTypeVec[i]) << ";\n";
- }
- OS << "\n";
-
- // Emit struct typedefs.
- for (unsigned vi = 2; vi != 5; ++vi) {
- for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) {
- std::string ts = TypeString('d', TDTypeVec[i]);
- std::string vs = TypeString('0' + vi, TDTypeVec[i]);
- OS << "typedef struct " << vs << " {\n";
- OS << " " << ts << " val";
- OS << "[" << utostr(vi) << "]";
- OS << ";\n} ";
- OS << vs << ";\n\n";
- }
- }
-
- OS << "#define __ai static __attribute__((__always_inline__))\n\n";
-
- std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
-
- // Emit vmovl, vmull and vabd intrinsics first so they can be used by other
- // intrinsics. (Some of the saturating multiply instructions are also
- // used to implement the corresponding "_lane" variants, but tablegen
- // sorts the records into alphabetical order so that the "_lane" variants
- // come after the intrinsics they use.)
- emitIntrinsic(OS, Records.getDef("VMOVL"));
- emitIntrinsic(OS, Records.getDef("VMULL"));
- emitIntrinsic(OS, Records.getDef("VABD"));
-
- for (unsigned i = 0, e = RV.size(); i != e; ++i) {
- Record *R = RV[i];
- if (R->getName() != "VMOVL" &&
- R->getName() != "VMULL" &&
- R->getName() != "VABD")
- emitIntrinsic(OS, R);
- }
-
- OS << "#undef __ai\n\n";
- OS << "#endif /* __ARM_NEON_H */\n";
-}
-
-/// emitIntrinsic - Write out the arm_neon.h header file definitions for the
-/// intrinsics specified by record R.
-void NeonEmitter::emitIntrinsic(raw_ostream &OS, Record *R) {
- std::string name = R->getValueAsString("Name");
- std::string Proto = R->getValueAsString("Prototype");
- std::string Types = R->getValueAsString("Types");
-
- SmallVector<StringRef, 16> TypeVec;
- ParseTypes(R, Types, TypeVec);
-
- OpKind kind = OpMap[R->getValueAsDef("Operand")->getName()];
-
- ClassKind classKind = ClassNone;
- if (R->getSuperClasses().size() >= 2)
- classKind = ClassMap[R->getSuperClasses()[1]];
- if (classKind == ClassNone && kind == OpNone)
- throw TGError(R->getLoc(), "Builtin has no class kind");
-
- for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
- if (kind == OpReinterpret) {
- bool outQuad = false;
- bool dummy = false;
- (void)ClassifyType(TypeVec[ti], outQuad, dummy, dummy);
- for (unsigned srcti = 0, srcte = TypeVec.size();
- srcti != srcte; ++srcti) {
- bool inQuad = false;
- (void)ClassifyType(TypeVec[srcti], inQuad, dummy, dummy);
- if (srcti == ti || inQuad != outQuad)
- continue;
- OS << GenIntrinsic(name, Proto, TypeVec[ti], TypeVec[srcti],
- OpCast, ClassS);
- }
- } else {
- OS << GenIntrinsic(name, Proto, TypeVec[ti], TypeVec[ti],
- kind, classKind);
- }
- }
- OS << "\n";
-}
-
-static unsigned RangeFromType(const char mod, StringRef typestr) {
- // base type to get the type string for.
- bool quad = false, dummy = false;
- char type = ClassifyType(typestr, quad, dummy, dummy);
- type = ModType(mod, type, quad, dummy, dummy, dummy, dummy, dummy);
-
- switch (type) {
- case 'c':
- return (8 << (int)quad) - 1;
- case 'h':
- case 's':
- return (4 << (int)quad) - 1;
- case 'f':
- case 'i':
- return (2 << (int)quad) - 1;
- case 'l':
- return (1 << (int)quad) - 1;
- default:
- throw "unhandled type!";
- break;
- }
- assert(0 && "unreachable");
- return 0;
-}
-
-/// runHeader - Emit a file with sections defining:
-/// 1. the NEON section of BuiltinsARM.def.
-/// 2. the SemaChecking code for the type overload checking.
-/// 3. the SemaChecking code for validation of intrinsic immedate arguments.
-void NeonEmitter::runHeader(raw_ostream &OS) {
- std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
-
- StringMap<OpKind> EmittedMap;
-
- // Generate BuiltinsARM.def for NEON
- OS << "#ifdef GET_NEON_BUILTINS\n";
- for (unsigned i = 0, e = RV.size(); i != e; ++i) {
- Record *R = RV[i];
- OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
- if (k != OpNone)
- continue;
-
- std::string Proto = R->getValueAsString("Prototype");
-
- // Functions with 'a' (the splat code) in the type prototype should not get
- // their own builtin as they use the non-splat variant.
- if (Proto.find('a') != std::string::npos)
- continue;
-
- std::string Types = R->getValueAsString("Types");
- SmallVector<StringRef, 16> TypeVec;
- ParseTypes(R, Types, TypeVec);
-
- if (R->getSuperClasses().size() < 2)
- throw TGError(R->getLoc(), "Builtin has no class kind");
-
- std::string name = R->getValueAsString("Name");
- ClassKind ck = ClassMap[R->getSuperClasses()[1]];
-
- for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
- // Generate the BuiltinsARM.def declaration for this builtin, ensuring
- // that each unique BUILTIN() macro appears only once in the output
- // stream.
- std::string bd = GenBuiltinDef(name, Proto, TypeVec[ti], ck);
- if (EmittedMap.count(bd))
- continue;
-
- EmittedMap[bd] = OpNone;
- OS << bd << "\n";
- }
- }
- OS << "#endif\n\n";
-
- // Generate the overloaded type checking code for SemaChecking.cpp
- OS << "#ifdef GET_NEON_OVERLOAD_CHECK\n";
- for (unsigned i = 0, e = RV.size(); i != e; ++i) {
- Record *R = RV[i];
- OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
- if (k != OpNone)
- continue;
-
- std::string Proto = R->getValueAsString("Prototype");
- std::string Types = R->getValueAsString("Types");
- std::string name = R->getValueAsString("Name");
-
- // Functions with 'a' (the splat code) in the type prototype should not get
- // their own builtin as they use the non-splat variant.
- if (Proto.find('a') != std::string::npos)
- continue;
-
- // Functions which have a scalar argument cannot be overloaded, no need to
- // check them if we are emitting the type checking code.
- if (Proto.find('s') != std::string::npos)
- continue;
-
- SmallVector<StringRef, 16> TypeVec;
- ParseTypes(R, Types, TypeVec);
-
- if (R->getSuperClasses().size() < 2)
- throw TGError(R->getLoc(), "Builtin has no class kind");
-
- int si = -1, qi = -1;
- unsigned mask = 0, qmask = 0;
- for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
- // Generate the switch case(s) for this builtin for the type validation.
- bool quad = false, poly = false, usgn = false;
- (void) ClassifyType(TypeVec[ti], quad, poly, usgn);
-
- if (quad) {
- qi = ti;
- qmask |= 1 << GetNeonEnum(Proto, TypeVec[ti]);
- } else {
- si = ti;
- mask |= 1 << GetNeonEnum(Proto, TypeVec[ti]);
- }
- }
- if (mask)
- OS << "case ARM::BI__builtin_neon_"
- << MangleName(name, TypeVec[si], ClassB)
- << ": mask = " << "0x" << utohexstr(mask) << "; break;\n";
- if (qmask)
- OS << "case ARM::BI__builtin_neon_"
- << MangleName(name, TypeVec[qi], ClassB)
- << ": mask = " << "0x" << utohexstr(qmask) << "; break;\n";
- }
- OS << "#endif\n\n";
-
- // Generate the intrinsic range checking code for shift/lane immediates.
- OS << "#ifdef GET_NEON_IMMEDIATE_CHECK\n";
- for (unsigned i = 0, e = RV.size(); i != e; ++i) {
- Record *R = RV[i];
-
- OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
- if (k != OpNone)
- continue;
-
- std::string name = R->getValueAsString("Name");
- std::string Proto = R->getValueAsString("Prototype");
- std::string Types = R->getValueAsString("Types");
-
- // Functions with 'a' (the splat code) in the type prototype should not get
- // their own builtin as they use the non-splat variant.
- if (Proto.find('a') != std::string::npos)
- continue;
-
- // Functions which do not have an immediate do not need to have range
- // checking code emitted.
- size_t immPos = Proto.find('i');
- if (immPos == std::string::npos)
- continue;
-
- SmallVector<StringRef, 16> TypeVec;
- ParseTypes(R, Types, TypeVec);
-
- if (R->getSuperClasses().size() < 2)
- throw TGError(R->getLoc(), "Builtin has no class kind");
-
- ClassKind ck = ClassMap[R->getSuperClasses()[1]];
-
- for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
- std::string namestr, shiftstr, rangestr;
-
- if (R->getValueAsBit("isVCVT_N")) {
- // VCVT between floating- and fixed-point values takes an immediate
- // in the range 1 to 32.
- ck = ClassB;
- rangestr = "l = 1; u = 31"; // upper bound = l + u
- } else if (Proto.find('s') == std::string::npos) {
- // Builtins which are overloaded by type will need to have their upper
- // bound computed at Sema time based on the type constant.
- ck = ClassB;
- if (R->getValueAsBit("isShift")) {
- shiftstr = ", true";
-
- // Right shifts have an 'r' in the name, left shifts do not.
- if (name.find('r') != std::string::npos)
- rangestr = "l = 1; ";
- }
- rangestr += "u = RFT(TV" + shiftstr + ")";
- } else {
- // The immediate generally refers to a lane in the preceding argument.
- assert(immPos > 0 && "unexpected immediate operand");
- rangestr = "u = " + utostr(RangeFromType(Proto[immPos-1], TypeVec[ti]));
- }
- // Make sure cases appear only once by uniquing them in a string map.
- namestr = MangleName(name, TypeVec[ti], ck);
- if (EmittedMap.count(namestr))
- continue;
- EmittedMap[namestr] = OpNone;
-
- // Calculate the index of the immediate that should be range checked.
- unsigned immidx = 0;
-
- // Builtins that return a struct of multiple vectors have an extra
- // leading arg for the struct return.
- if (Proto[0] >= '2' && Proto[0] <= '4')
- ++immidx;
-
- // Add one to the index for each argument until we reach the immediate
- // to be checked. Structs of vectors are passed as multiple arguments.
- for (unsigned ii = 1, ie = Proto.size(); ii != ie; ++ii) {
- switch (Proto[ii]) {
- default: immidx += 1; break;
- case '2': immidx += 2; break;
- case '3': immidx += 3; break;
- case '4': immidx += 4; break;
- case 'i': ie = ii + 1; break;
- }
- }
- OS << "case ARM::BI__builtin_neon_" << MangleName(name, TypeVec[ti], ck)
- << ": i = " << immidx << "; " << rangestr << "; break;\n";
- }
- }
- OS << "#endif\n\n";
-}
-
-/// GenTest - Write out a test for the intrinsic specified by the name and
-/// type strings, including the embedded patterns for FileCheck to match.
-static std::string GenTest(const std::string &name,
- const std::string &proto,
- StringRef outTypeStr, StringRef inTypeStr,
- bool isShift) {
- assert(!proto.empty() && "");
- std::string s;
-
- // Function name with type suffix
- std::string mangledName = MangleName(name, outTypeStr, ClassS);
- if (outTypeStr != inTypeStr) {
- // If the input type is different (e.g., for vreinterpret), append a suffix
- // for the input type. String off a "Q" (quad) prefix so that MangleName
- // does not insert another "q" in the name.
- unsigned typeStrOff = (inTypeStr[0] == 'Q' ? 1 : 0);
- StringRef inTypeNoQuad = inTypeStr.substr(typeStrOff);
- mangledName = MangleName(mangledName, inTypeNoQuad, ClassS);
- }
-
- // Emit the FileCheck patterns.
- s += "// CHECK: test_" + mangledName + "\n";
- // s += "// CHECK: \n"; // FIXME: + expected instruction opcode.
-
- // Emit the start of the test function.
- s += TypeString(proto[0], outTypeStr) + " test_" + mangledName + "(";
- char arg = 'a';
- std::string comma;
- for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
- // Do not create arguments for values that must be immediate constants.
- if (proto[i] == 'i')
- continue;
- s += comma + TypeString(proto[i], inTypeStr) + " ";
- s.push_back(arg);
- comma = ", ";
- }
- s += ") { \\\n ";
-
- if (proto[0] != 'v')
- s += "return ";
- s += mangledName + "(";
- arg = 'a';
- for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
- if (proto[i] == 'i') {
- // For immediate operands, test the maximum value.
- if (isShift)
- s += "1"; // FIXME
- else
- // The immediate generally refers to a lane in the preceding argument.
- s += utostr(RangeFromType(proto[i-1], inTypeStr));
- } else {
- s.push_back(arg);
- }
- if ((i + 1) < e)
- s += ", ";
- }
- s += ");\n}\n\n";
- return s;
-}
-
-/// runTests - Write out a complete set of tests for all of the Neon
-/// intrinsics.
-void NeonEmitter::runTests(raw_ostream &OS) {
- OS <<
- "// RUN: %clang_cc1 -triple thumbv7-apple-darwin \\\n"
- "// RUN: -target-cpu cortex-a9 -ffreestanding -S -o - %s | FileCheck %s\n"
- "\n"
- "#include <arm_neon.h>\n"
- "\n";
-
- std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
- for (unsigned i = 0, e = RV.size(); i != e; ++i) {
- Record *R = RV[i];
- std::string name = R->getValueAsString("Name");
- std::string Proto = R->getValueAsString("Prototype");
- std::string Types = R->getValueAsString("Types");
- bool isShift = R->getValueAsBit("isShift");
-
- SmallVector<StringRef, 16> TypeVec;
- ParseTypes(R, Types, TypeVec);
-
- OpKind kind = OpMap[R->getValueAsDef("Operand")->getName()];
- for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
- if (kind == OpReinterpret) {
- bool outQuad = false;
- bool dummy = false;
- (void)ClassifyType(TypeVec[ti], outQuad, dummy, dummy);
- for (unsigned srcti = 0, srcte = TypeVec.size();
- srcti != srcte; ++srcti) {
- bool inQuad = false;
- (void)ClassifyType(TypeVec[srcti], inQuad, dummy, dummy);
- if (srcti == ti || inQuad != outQuad)
- continue;
- OS << GenTest(name, Proto, TypeVec[ti], TypeVec[srcti], isShift);
- }
- } else {
- OS << GenTest(name, Proto, TypeVec[ti], TypeVec[ti], isShift);
- }
- }
- OS << "\n";
- }
-}
-
diff --git a/contrib/llvm/utils/TableGen/NeonEmitter.h b/contrib/llvm/utils/TableGen/NeonEmitter.h
deleted file mode 100644
index 12e4e86..0000000
--- a/contrib/llvm/utils/TableGen/NeonEmitter.h
+++ /dev/null
@@ -1,176 +0,0 @@
-//===- NeonEmitter.h - Generate arm_neon.h for use with clang ---*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This tablegen backend is responsible for emitting arm_neon.h, which includes
-// a declaration and definition of each function specified by the ARM NEON
-// compiler interface. See ARM document DUI0348B.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef NEON_EMITTER_H
-#define NEON_EMITTER_H
-
-#include "Record.h"
-#include "TableGenBackend.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/StringMap.h"
-
-enum OpKind {
- OpNone,
- OpAdd,
- OpAddl,
- OpAddw,
- OpSub,
- OpSubl,
- OpSubw,
- OpMul,
- OpMla,
- OpMlal,
- OpMls,
- OpMlsl,
- OpMulN,
- OpMlaN,
- OpMlsN,
- OpMlalN,
- OpMlslN,
- OpMulLane,
- OpMullLane,
- OpMlaLane,
- OpMlsLane,
- OpMlalLane,
- OpMlslLane,
- OpQDMullLane,
- OpQDMlalLane,
- OpQDMlslLane,
- OpQDMulhLane,
- OpQRDMulhLane,
- OpEq,
- OpGe,
- OpLe,
- OpGt,
- OpLt,
- OpNeg,
- OpNot,
- OpAnd,
- OpOr,
- OpXor,
- OpAndNot,
- OpOrNot,
- OpCast,
- OpConcat,
- OpDup,
- OpDupLane,
- OpHi,
- OpLo,
- OpSelect,
- OpRev16,
- OpRev32,
- OpRev64,
- OpReinterpret,
- OpAbdl,
- OpAba,
- OpAbal
-};
-
-enum ClassKind {
- ClassNone,
- ClassI, // generic integer instruction, e.g., "i8" suffix
- ClassS, // signed/unsigned/poly, e.g., "s8", "u8" or "p8" suffix
- ClassW, // width-specific instruction, e.g., "8" suffix
- ClassB // bitcast arguments with enum argument to specify type
-};
-
-namespace llvm {
-
- class NeonEmitter : public TableGenBackend {
- RecordKeeper &Records;
- StringMap<OpKind> OpMap;
- DenseMap<Record*, ClassKind> ClassMap;
-
- public:
- NeonEmitter(RecordKeeper &R) : Records(R) {
- OpMap["OP_NONE"] = OpNone;
- OpMap["OP_ADD"] = OpAdd;
- OpMap["OP_ADDL"] = OpAddl;
- OpMap["OP_ADDW"] = OpAddw;
- OpMap["OP_SUB"] = OpSub;
- OpMap["OP_SUBL"] = OpSubl;
- OpMap["OP_SUBW"] = OpSubw;
- OpMap["OP_MUL"] = OpMul;
- OpMap["OP_MLA"] = OpMla;
- OpMap["OP_MLAL"] = OpMlal;
- OpMap["OP_MLS"] = OpMls;
- OpMap["OP_MLSL"] = OpMlsl;
- OpMap["OP_MUL_N"] = OpMulN;
- OpMap["OP_MLA_N"] = OpMlaN;
- OpMap["OP_MLS_N"] = OpMlsN;
- OpMap["OP_MLAL_N"] = OpMlalN;
- OpMap["OP_MLSL_N"] = OpMlslN;
- OpMap["OP_MUL_LN"]= OpMulLane;
- OpMap["OP_MULL_LN"] = OpMullLane;
- OpMap["OP_MLA_LN"]= OpMlaLane;
- OpMap["OP_MLS_LN"]= OpMlsLane;
- OpMap["OP_MLAL_LN"] = OpMlalLane;
- OpMap["OP_MLSL_LN"] = OpMlslLane;
- OpMap["OP_QDMULL_LN"] = OpQDMullLane;
- OpMap["OP_QDMLAL_LN"] = OpQDMlalLane;
- OpMap["OP_QDMLSL_LN"] = OpQDMlslLane;
- OpMap["OP_QDMULH_LN"] = OpQDMulhLane;
- OpMap["OP_QRDMULH_LN"] = OpQRDMulhLane;
- OpMap["OP_EQ"] = OpEq;
- OpMap["OP_GE"] = OpGe;
- OpMap["OP_LE"] = OpLe;
- OpMap["OP_GT"] = OpGt;
- OpMap["OP_LT"] = OpLt;
- OpMap["OP_NEG"] = OpNeg;
- OpMap["OP_NOT"] = OpNot;
- OpMap["OP_AND"] = OpAnd;
- OpMap["OP_OR"] = OpOr;
- OpMap["OP_XOR"] = OpXor;
- OpMap["OP_ANDN"] = OpAndNot;
- OpMap["OP_ORN"] = OpOrNot;
- OpMap["OP_CAST"] = OpCast;
- OpMap["OP_CONC"] = OpConcat;
- OpMap["OP_HI"] = OpHi;
- OpMap["OP_LO"] = OpLo;
- OpMap["OP_DUP"] = OpDup;
- OpMap["OP_DUP_LN"] = OpDupLane;
- OpMap["OP_SEL"] = OpSelect;
- OpMap["OP_REV16"] = OpRev16;
- OpMap["OP_REV32"] = OpRev32;
- OpMap["OP_REV64"] = OpRev64;
- OpMap["OP_REINT"] = OpReinterpret;
- OpMap["OP_ABDL"] = OpAbdl;
- OpMap["OP_ABA"] = OpAba;
- OpMap["OP_ABAL"] = OpAbal;
-
- Record *SI = R.getClass("SInst");
- Record *II = R.getClass("IInst");
- Record *WI = R.getClass("WInst");
- ClassMap[SI] = ClassS;
- ClassMap[II] = ClassI;
- ClassMap[WI] = ClassW;
- }
-
- // run - Emit arm_neon.h.inc
- void run(raw_ostream &o);
-
- // runHeader - Emit all the __builtin prototypes used in arm_neon.h
- void runHeader(raw_ostream &o);
-
- // runTests - Emit tests for all the Neon intrinsics.
- void runTests(raw_ostream &o);
-
- private:
- void emitIntrinsic(raw_ostream &OS, Record *R);
- };
-
-} // End llvm namespace
-
-#endif
diff --git a/contrib/llvm/utils/TableGen/OptParserEmitter.cpp b/contrib/llvm/utils/TableGen/OptParserEmitter.cpp
deleted file mode 100644
index 431026c..0000000
--- a/contrib/llvm/utils/TableGen/OptParserEmitter.cpp
+++ /dev/null
@@ -1,194 +0,0 @@
-//===- OptParserEmitter.cpp - Table Driven Command Line Parsing -----------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "OptParserEmitter.h"
-#include "Record.h"
-#include "llvm/ADT/STLExtras.h"
-using namespace llvm;
-
-static int StrCmpOptionName(const char *A, const char *B) {
- char a = *A, b = *B;
- while (a == b) {
- if (a == '\0')
- return 0;
-
- a = *++A;
- b = *++B;
- }
-
- if (a == '\0') // A is a prefix of B.
- return 1;
- if (b == '\0') // B is a prefix of A.
- return -1;
-
- // Otherwise lexicographic.
- return (a < b) ? -1 : 1;
-}
-
-static int CompareOptionRecords(const void *Av, const void *Bv) {
- const Record *A = *(Record**) Av;
- const Record *B = *(Record**) Bv;
-
- // Sentinel options precede all others and are only ordered by precedence.
- bool ASent = A->getValueAsDef("Kind")->getValueAsBit("Sentinel");
- bool BSent = B->getValueAsDef("Kind")->getValueAsBit("Sentinel");
- if (ASent != BSent)
- return ASent ? -1 : 1;
-
- // Compare options by name, unless they are sentinels.
- if (!ASent)
- if (int Cmp = StrCmpOptionName(A->getValueAsString("Name").c_str(),
- B->getValueAsString("Name").c_str()))
- return Cmp;
-
- // Then by the kind precedence;
- int APrec = A->getValueAsDef("Kind")->getValueAsInt("Precedence");
- int BPrec = B->getValueAsDef("Kind")->getValueAsInt("Precedence");
- assert(APrec != BPrec && "Options are equivalent!");
- return APrec < BPrec ? -1 : 1;
-}
-
-static const std::string getOptionName(const Record &R) {
- // Use the record name unless EnumName is defined.
- if (dynamic_cast<UnsetInit*>(R.getValueInit("EnumName")))
- return R.getName();
-
- return R.getValueAsString("EnumName");
-}
-
-static raw_ostream &write_cstring(raw_ostream &OS, llvm::StringRef Str) {
- OS << '"';
- OS.write_escaped(Str);
- OS << '"';
- return OS;
-}
-
-void OptParserEmitter::run(raw_ostream &OS) {
- // Get the option groups and options.
- const std::vector<Record*> &Groups =
- Records.getAllDerivedDefinitions("OptionGroup");
- std::vector<Record*> Opts = Records.getAllDerivedDefinitions("Option");
-
- if (GenDefs)
- EmitSourceFileHeader("Option Parsing Definitions", OS);
- else
- EmitSourceFileHeader("Option Parsing Table", OS);
-
- array_pod_sort(Opts.begin(), Opts.end(), CompareOptionRecords);
- if (GenDefs) {
- OS << "#ifndef OPTION\n";
- OS << "#error \"Define OPTION prior to including this file!\"\n";
- OS << "#endif\n\n";
-
- OS << "/////////\n";
- OS << "// Groups\n\n";
- for (unsigned i = 0, e = Groups.size(); i != e; ++i) {
- const Record &R = *Groups[i];
-
- // Start a single option entry.
- OS << "OPTION(";
-
- // The option string.
- OS << '"' << R.getValueAsString("Name") << '"';
-
- // The option identifier name.
- OS << ", "<< getOptionName(R);
-
- // The option kind.
- OS << ", Group";
-
- // The containing option group (if any).
- OS << ", ";
- if (const DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("Group")))
- OS << getOptionName(*DI->getDef());
- else
- OS << "INVALID";
-
- // The other option arguments (unused for groups).
- OS << ", INVALID, 0, 0";
-
- // The option help text.
- if (!dynamic_cast<UnsetInit*>(R.getValueInit("HelpText"))) {
- OS << ",\n";
- OS << " ";
- write_cstring(OS, R.getValueAsString("HelpText"));
- } else
- OS << ", 0";
-
- // The option meta-variable name (unused).
- OS << ", 0)\n";
- }
- OS << "\n";
-
- OS << "//////////\n";
- OS << "// Options\n\n";
- for (unsigned i = 0, e = Opts.size(); i != e; ++i) {
- const Record &R = *Opts[i];
-
- // Start a single option entry.
- OS << "OPTION(";
-
- // The option string.
- write_cstring(OS, R.getValueAsString("Name"));
-
- // The option identifier name.
- OS << ", "<< getOptionName(R);
-
- // The option kind.
- OS << ", " << R.getValueAsDef("Kind")->getValueAsString("Name");
-
- // The containing option group (if any).
- OS << ", ";
- if (const DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("Group")))
- OS << getOptionName(*DI->getDef());
- else
- OS << "INVALID";
-
- // The option alias (if any).
- OS << ", ";
- if (const DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("Alias")))
- OS << getOptionName(*DI->getDef());
- else
- OS << "INVALID";
-
- // The option flags.
- const ListInit *LI = R.getValueAsListInit("Flags");
- if (LI->empty()) {
- OS << ", 0";
- } else {
- OS << ", ";
- for (unsigned i = 0, e = LI->size(); i != e; ++i) {
- if (i)
- OS << " | ";
- OS << dynamic_cast<DefInit*>(LI->getElement(i))->getDef()->getName();
- }
- }
-
- // The option parameter field.
- OS << ", " << R.getValueAsInt("NumArgs");
-
- // The option help text.
- if (!dynamic_cast<UnsetInit*>(R.getValueInit("HelpText"))) {
- OS << ",\n";
- OS << " ";
- write_cstring(OS, R.getValueAsString("HelpText"));
- } else
- OS << ", 0";
-
- // The option meta-variable name.
- OS << ", ";
- if (!dynamic_cast<UnsetInit*>(R.getValueInit("MetaVarName")))
- write_cstring(OS, R.getValueAsString("MetaVarName"));
- else
- OS << "0";
-
- OS << ")\n";
- }
- }
-}
diff --git a/contrib/llvm/utils/TableGen/OptParserEmitter.h b/contrib/llvm/utils/TableGen/OptParserEmitter.h
deleted file mode 100644
index 241a3f2..0000000
--- a/contrib/llvm/utils/TableGen/OptParserEmitter.h
+++ /dev/null
@@ -1,34 +0,0 @@
-//===- OptParserEmitter.h - Table Driven Command Line Parsing ---*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef UTILS_TABLEGEN_OPTPARSEREMITTER_H
-#define UTILS_TABLEGEN_OPTPARSEREMITTER_H
-
-#include "TableGenBackend.h"
-
-namespace llvm {
- /// OptParserEmitter - This tablegen backend takes an input .td file
- /// describing a list of options and emits a data structure for parsing and
- /// working with those options when given an input command line.
- class OptParserEmitter : public TableGenBackend {
- RecordKeeper &Records;
- bool GenDefs;
-
- public:
- OptParserEmitter(RecordKeeper &R, bool _GenDefs)
- : Records(R), GenDefs(_GenDefs) {}
-
- /// run - Output the option parsing information.
- ///
- /// \param GenHeader - Generate the header describing the option IDs.x
- void run(raw_ostream &OS);
- };
-}
-
-#endif
diff --git a/contrib/llvm/utils/TableGen/PseudoLoweringEmitter.cpp b/contrib/llvm/utils/TableGen/PseudoLoweringEmitter.cpp
index db33c1f..c685527 100644
--- a/contrib/llvm/utils/TableGen/PseudoLoweringEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/PseudoLoweringEmitter.cpp
@@ -8,10 +8,10 @@
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "pseudo-lowering"
-#include "Error.h"
#include "CodeGenInstruction.h"
#include "PseudoLoweringEmitter.h"
-#include "Record.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/ADT/IndexedMap.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/ErrorHandling.h"
diff --git a/contrib/llvm/utils/TableGen/PseudoLoweringEmitter.h b/contrib/llvm/utils/TableGen/PseudoLoweringEmitter.h
index 2749280..325bc8b 100644
--- a/contrib/llvm/utils/TableGen/PseudoLoweringEmitter.h
+++ b/contrib/llvm/utils/TableGen/PseudoLoweringEmitter.h
@@ -12,7 +12,7 @@
#include "CodeGenInstruction.h"
#include "CodeGenTarget.h"
-#include "TableGenBackend.h"
+#include "llvm/TableGen/TableGenBackend.h"
#include "llvm/ADT/IndexedMap.h"
#include "llvm/ADT/SmallVector.h"
diff --git a/contrib/llvm/utils/TableGen/Record.cpp b/contrib/llvm/utils/TableGen/Record.cpp
deleted file mode 100644
index 730eca1..0000000
--- a/contrib/llvm/utils/TableGen/Record.cpp
+++ /dev/null
@@ -1,1575 +0,0 @@
-//===- Record.cpp - Record implementation ---------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Implement the tablegen record classes.
-//
-//===----------------------------------------------------------------------===//
-
-#include "Record.h"
-#include "Error.h"
-#include "llvm/Support/DataTypes.h"
-#include "llvm/Support/Format.h"
-#include "llvm/ADT/StringExtras.h"
-
-using namespace llvm;
-
-//===----------------------------------------------------------------------===//
-// Type implementations
-//===----------------------------------------------------------------------===//
-
-void RecTy::dump() const { print(errs()); }
-
-Init *BitRecTy::convertValue(BitsInit *BI) {
- if (BI->getNumBits() != 1) return 0; // Only accept if just one bit!
- return BI->getBit(0);
-}
-
-bool BitRecTy::baseClassOf(const BitsRecTy *RHS) const {
- return RHS->getNumBits() == 1;
-}
-
-Init *BitRecTy::convertValue(IntInit *II) {
- int64_t Val = II->getValue();
- if (Val != 0 && Val != 1) return 0; // Only accept 0 or 1 for a bit!
-
- return new BitInit(Val != 0);
-}
-
-Init *BitRecTy::convertValue(TypedInit *VI) {
- if (dynamic_cast<BitRecTy*>(VI->getType()))
- return VI; // Accept variable if it is already of bit type!
- return 0;
-}
-
-std::string BitsRecTy::getAsString() const {
- return "bits<" + utostr(Size) + ">";
-}
-
-Init *BitsRecTy::convertValue(UnsetInit *UI) {
- BitsInit *Ret = new BitsInit(Size);
-
- for (unsigned i = 0; i != Size; ++i)
- Ret->setBit(i, new UnsetInit());
- return Ret;
-}
-
-Init *BitsRecTy::convertValue(BitInit *UI) {
- if (Size != 1) return 0; // Can only convert single bit.
- BitsInit *Ret = new BitsInit(1);
- Ret->setBit(0, UI);
- return Ret;
-}
-
-/// canFitInBitfield - Return true if the number of bits is large enough to hold
-/// the integer value.
-static bool canFitInBitfield(int64_t Value, unsigned NumBits) {
- // For example, with NumBits == 4, we permit Values from [-7 .. 15].
- return (NumBits >= sizeof(Value) * 8) ||
- (Value >> NumBits == 0) || (Value >> (NumBits-1) == -1);
-}
-
-/// convertValue from Int initializer to bits type: Split the integer up into the
-/// appropriate bits.
-///
-Init *BitsRecTy::convertValue(IntInit *II) {
- int64_t Value = II->getValue();
- // Make sure this bitfield is large enough to hold the integer value.
- if (!canFitInBitfield(Value, Size))
- return 0;
-
- BitsInit *Ret = new BitsInit(Size);
- for (unsigned i = 0; i != Size; ++i)
- Ret->setBit(i, new BitInit(Value & (1LL << i)));
-
- return Ret;
-}
-
-Init *BitsRecTy::convertValue(BitsInit *BI) {
- // If the number of bits is right, return it. Otherwise we need to expand or
- // truncate.
- if (BI->getNumBits() == Size) return BI;
- return 0;
-}
-
-Init *BitsRecTy::convertValue(TypedInit *VI) {
- if (BitsRecTy *BRT = dynamic_cast<BitsRecTy*>(VI->getType()))
- if (BRT->Size == Size) {
- BitsInit *Ret = new BitsInit(Size);
- for (unsigned i = 0; i != Size; ++i)
- Ret->setBit(i, new VarBitInit(VI, i));
- return Ret;
- }
-
- if (Size == 1 && dynamic_cast<BitRecTy*>(VI->getType())) {
- BitsInit *Ret = new BitsInit(1);
- Ret->setBit(0, VI);
- return Ret;
- }
-
- if (TernOpInit *Tern = dynamic_cast<TernOpInit*>(VI)) {
- if (Tern->getOpcode() == TernOpInit::IF) {
- Init *LHS = Tern->getLHS();
- Init *MHS = Tern->getMHS();
- Init *RHS = Tern->getRHS();
-
- IntInit *MHSi = dynamic_cast<IntInit*>(MHS);
- IntInit *RHSi = dynamic_cast<IntInit*>(RHS);
-
- if (MHSi && RHSi) {
- int64_t MHSVal = MHSi->getValue();
- int64_t RHSVal = RHSi->getValue();
-
- if (canFitInBitfield(MHSVal, Size) && canFitInBitfield(RHSVal, Size)) {
- BitsInit *Ret = new BitsInit(Size);
-
- for (unsigned i = 0; i != Size; ++i)
- Ret->setBit(i, new TernOpInit(TernOpInit::IF, LHS,
- new IntInit((MHSVal & (1LL << i)) ? 1 : 0),
- new IntInit((RHSVal & (1LL << i)) ? 1 : 0),
- VI->getType()));
-
- return Ret;
- }
- } else {
- BitsInit *MHSbs = dynamic_cast<BitsInit*>(MHS);
- BitsInit *RHSbs = dynamic_cast<BitsInit*>(RHS);
-
- if (MHSbs && RHSbs) {
- BitsInit *Ret = new BitsInit(Size);
-
- for (unsigned i = 0; i != Size; ++i)
- Ret->setBit(i, new TernOpInit(TernOpInit::IF, LHS,
- MHSbs->getBit(i),
- RHSbs->getBit(i),
- VI->getType()));
-
- return Ret;
- }
- }
- }
- }
-
- return 0;
-}
-
-Init *IntRecTy::convertValue(BitInit *BI) {
- return new IntInit(BI->getValue());
-}
-
-Init *IntRecTy::convertValue(BitsInit *BI) {
- int64_t Result = 0;
- for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i)
- if (BitInit *Bit = dynamic_cast<BitInit*>(BI->getBit(i))) {
- Result |= Bit->getValue() << i;
- } else {
- return 0;
- }
- return new IntInit(Result);
-}
-
-Init *IntRecTy::convertValue(TypedInit *TI) {
- if (TI->getType()->typeIsConvertibleTo(this))
- return TI; // Accept variable if already of the right type!
- return 0;
-}
-
-Init *StringRecTy::convertValue(UnOpInit *BO) {
- if (BO->getOpcode() == UnOpInit::CAST) {
- Init *L = BO->getOperand()->convertInitializerTo(this);
- if (L == 0) return 0;
- if (L != BO->getOperand())
- return new UnOpInit(UnOpInit::CAST, L, new StringRecTy);
- return BO;
- }
-
- return convertValue((TypedInit*)BO);
-}
-
-Init *StringRecTy::convertValue(BinOpInit *BO) {
- if (BO->getOpcode() == BinOpInit::STRCONCAT) {
- Init *L = BO->getLHS()->convertInitializerTo(this);
- Init *R = BO->getRHS()->convertInitializerTo(this);
- if (L == 0 || R == 0) return 0;
- if (L != BO->getLHS() || R != BO->getRHS())
- return new BinOpInit(BinOpInit::STRCONCAT, L, R, new StringRecTy);
- return BO;
- }
-
- return convertValue((TypedInit*)BO);
-}
-
-
-Init *StringRecTy::convertValue(TypedInit *TI) {
- if (dynamic_cast<StringRecTy*>(TI->getType()))
- return TI; // Accept variable if already of the right type!
- return 0;
-}
-
-std::string ListRecTy::getAsString() const {
- return "list<" + Ty->getAsString() + ">";
-}
-
-Init *ListRecTy::convertValue(ListInit *LI) {
- std::vector<Init*> Elements;
-
- // Verify that all of the elements of the list are subclasses of the
- // appropriate class!
- for (unsigned i = 0, e = LI->getSize(); i != e; ++i)
- if (Init *CI = LI->getElement(i)->convertInitializerTo(Ty))
- Elements.push_back(CI);
- else
- return 0;
-
- ListRecTy *LType = dynamic_cast<ListRecTy*>(LI->getType());
- if (LType == 0) {
- return 0;
- }
-
- return new ListInit(Elements, new ListRecTy(Ty));
-}
-
-Init *ListRecTy::convertValue(TypedInit *TI) {
- // Ensure that TI is compatible with our class.
- if (ListRecTy *LRT = dynamic_cast<ListRecTy*>(TI->getType()))
- if (LRT->getElementType()->typeIsConvertibleTo(getElementType()))
- return TI;
- return 0;
-}
-
-Init *CodeRecTy::convertValue(TypedInit *TI) {
- if (TI->getType()->typeIsConvertibleTo(this))
- return TI;
- return 0;
-}
-
-Init *DagRecTy::convertValue(TypedInit *TI) {
- if (TI->getType()->typeIsConvertibleTo(this))
- return TI;
- return 0;
-}
-
-Init *DagRecTy::convertValue(UnOpInit *BO) {
- if (BO->getOpcode() == UnOpInit::CAST) {
- Init *L = BO->getOperand()->convertInitializerTo(this);
- if (L == 0) return 0;
- if (L != BO->getOperand())
- return new UnOpInit(UnOpInit::CAST, L, new DagRecTy);
- return BO;
- }
- return 0;
-}
-
-Init *DagRecTy::convertValue(BinOpInit *BO) {
- if (BO->getOpcode() == BinOpInit::CONCAT) {
- Init *L = BO->getLHS()->convertInitializerTo(this);
- Init *R = BO->getRHS()->convertInitializerTo(this);
- if (L == 0 || R == 0) return 0;
- if (L != BO->getLHS() || R != BO->getRHS())
- return new BinOpInit(BinOpInit::CONCAT, L, R, new DagRecTy);
- return BO;
- }
- return 0;
-}
-
-std::string RecordRecTy::getAsString() const {
- return Rec->getName();
-}
-
-Init *RecordRecTy::convertValue(DefInit *DI) {
- // Ensure that DI is a subclass of Rec.
- if (!DI->getDef()->isSubClassOf(Rec))
- return 0;
- return DI;
-}
-
-Init *RecordRecTy::convertValue(TypedInit *TI) {
- // Ensure that TI is compatible with Rec.
- if (RecordRecTy *RRT = dynamic_cast<RecordRecTy*>(TI->getType()))
- if (RRT->getRecord()->isSubClassOf(getRecord()) ||
- RRT->getRecord() == getRecord())
- return TI;
- return 0;
-}
-
-bool RecordRecTy::baseClassOf(const RecordRecTy *RHS) const {
- if (Rec == RHS->getRecord() || RHS->getRecord()->isSubClassOf(Rec))
- return true;
-
- const std::vector<Record*> &SC = Rec->getSuperClasses();
- for (unsigned i = 0, e = SC.size(); i != e; ++i)
- if (RHS->getRecord()->isSubClassOf(SC[i]))
- return true;
-
- return false;
-}
-
-
-/// resolveTypes - Find a common type that T1 and T2 convert to.
-/// Return 0 if no such type exists.
-///
-RecTy *llvm::resolveTypes(RecTy *T1, RecTy *T2) {
- if (!T1->typeIsConvertibleTo(T2)) {
- if (!T2->typeIsConvertibleTo(T1)) {
- // If one is a Record type, check superclasses
- RecordRecTy *RecTy1 = dynamic_cast<RecordRecTy*>(T1);
- if (RecTy1) {
- // See if T2 inherits from a type T1 also inherits from
- const std::vector<Record *> &T1SuperClasses =
- RecTy1->getRecord()->getSuperClasses();
- for(std::vector<Record *>::const_iterator i = T1SuperClasses.begin(),
- iend = T1SuperClasses.end();
- i != iend;
- ++i) {
- RecordRecTy *SuperRecTy1 = new RecordRecTy(*i);
- RecTy *NewType1 = resolveTypes(SuperRecTy1, T2);
- if (NewType1 != 0) {
- if (NewType1 != SuperRecTy1) {
- delete SuperRecTy1;
- }
- return NewType1;
- }
- }
- }
- RecordRecTy *RecTy2 = dynamic_cast<RecordRecTy*>(T2);
- if (RecTy2) {
- // See if T1 inherits from a type T2 also inherits from
- const std::vector<Record *> &T2SuperClasses =
- RecTy2->getRecord()->getSuperClasses();
- for (std::vector<Record *>::const_iterator i = T2SuperClasses.begin(),
- iend = T2SuperClasses.end();
- i != iend;
- ++i) {
- RecordRecTy *SuperRecTy2 = new RecordRecTy(*i);
- RecTy *NewType2 = resolveTypes(T1, SuperRecTy2);
- if (NewType2 != 0) {
- if (NewType2 != SuperRecTy2) {
- delete SuperRecTy2;
- }
- return NewType2;
- }
- }
- }
- return 0;
- }
- return T2;
- }
- return T1;
-}
-
-
-//===----------------------------------------------------------------------===//
-// Initializer implementations
-//===----------------------------------------------------------------------===//
-
-void Init::dump() const { return print(errs()); }
-
-Init *BitsInit::convertInitializerBitRange(const std::vector<unsigned> &Bits) {
- BitsInit *BI = new BitsInit(Bits.size());
- for (unsigned i = 0, e = Bits.size(); i != e; ++i) {
- if (Bits[i] >= getNumBits()) {
- delete BI;
- return 0;
- }
- BI->setBit(i, getBit(Bits[i]));
- }
- return BI;
-}
-
-std::string BitsInit::getAsString() const {
- std::string Result = "{ ";
- for (unsigned i = 0, e = getNumBits(); i != e; ++i) {
- if (i) Result += ", ";
- if (Init *Bit = getBit(e-i-1))
- Result += Bit->getAsString();
- else
- Result += "*";
- }
- return Result + " }";
-}
-
-// resolveReferences - If there are any field references that refer to fields
-// that have been filled in, we can propagate the values now.
-//
-Init *BitsInit::resolveReferences(Record &R, const RecordVal *RV) {
- bool Changed = false;
- BitsInit *New = new BitsInit(getNumBits());
-
- for (unsigned i = 0, e = Bits.size(); i != e; ++i) {
- Init *B;
- Init *CurBit = getBit(i);
-
- do {
- B = CurBit;
- CurBit = CurBit->resolveReferences(R, RV);
- Changed |= B != CurBit;
- } while (B != CurBit);
- New->setBit(i, CurBit);
- }
-
- if (Changed)
- return New;
- delete New;
- return this;
-}
-
-std::string IntInit::getAsString() const {
- return itostr(Value);
-}
-
-Init *IntInit::convertInitializerBitRange(const std::vector<unsigned> &Bits) {
- BitsInit *BI = new BitsInit(Bits.size());
-
- for (unsigned i = 0, e = Bits.size(); i != e; ++i) {
- if (Bits[i] >= 64) {
- delete BI;
- return 0;
- }
- BI->setBit(i, new BitInit(Value & (INT64_C(1) << Bits[i])));
- }
- return BI;
-}
-
-Init *ListInit::convertInitListSlice(const std::vector<unsigned> &Elements) {
- std::vector<Init*> Vals;
- for (unsigned i = 0, e = Elements.size(); i != e; ++i) {
- if (Elements[i] >= getSize())
- return 0;
- Vals.push_back(getElement(Elements[i]));
- }
- return new ListInit(Vals, getType());
-}
-
-Record *ListInit::getElementAsRecord(unsigned i) const {
- assert(i < Values.size() && "List element index out of range!");
- DefInit *DI = dynamic_cast<DefInit*>(Values[i]);
- if (DI == 0) throw "Expected record in list!";
- return DI->getDef();
-}
-
-Init *ListInit::resolveReferences(Record &R, const RecordVal *RV) {
- std::vector<Init*> Resolved;
- Resolved.reserve(getSize());
- bool Changed = false;
-
- for (unsigned i = 0, e = getSize(); i != e; ++i) {
- Init *E;
- Init *CurElt = getElement(i);
-
- do {
- E = CurElt;
- CurElt = CurElt->resolveReferences(R, RV);
- Changed |= E != CurElt;
- } while (E != CurElt);
- Resolved.push_back(E);
- }
-
- if (Changed)
- return new ListInit(Resolved, getType());
- return this;
-}
-
-Init *ListInit::resolveListElementReference(Record &R, const RecordVal *IRV,
- unsigned Elt) {
- if (Elt >= getSize())
- return 0; // Out of range reference.
- Init *E = getElement(Elt);
- // If the element is set to some value, or if we are resolving a reference
- // to a specific variable and that variable is explicitly unset, then
- // replace the VarListElementInit with it.
- if (IRV || !dynamic_cast<UnsetInit*>(E))
- return E;
- return 0;
-}
-
-std::string ListInit::getAsString() const {
- std::string Result = "[";
- for (unsigned i = 0, e = Values.size(); i != e; ++i) {
- if (i) Result += ", ";
- Result += Values[i]->getAsString();
- }
- return Result + "]";
-}
-
-Init *OpInit::resolveBitReference(Record &R, const RecordVal *IRV,
- unsigned Bit) {
- Init *Folded = Fold(&R, 0);
-
- if (Folded != this) {
- TypedInit *Typed = dynamic_cast<TypedInit *>(Folded);
- if (Typed) {
- return Typed->resolveBitReference(R, IRV, Bit);
- }
- }
-
- return 0;
-}
-
-Init *OpInit::resolveListElementReference(Record &R, const RecordVal *IRV,
- unsigned Elt) {
- Init *Folded = Fold(&R, 0);
-
- if (Folded != this) {
- TypedInit *Typed = dynamic_cast<TypedInit *>(Folded);
- if (Typed) {
- return Typed->resolveListElementReference(R, IRV, Elt);
- }
- }
-
- return 0;
-}
-
-Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) {
- switch (getOpcode()) {
- default: assert(0 && "Unknown unop");
- case CAST: {
- if (getType()->getAsString() == "string") {
- StringInit *LHSs = dynamic_cast<StringInit*>(LHS);
- if (LHSs) {
- return LHSs;
- }
-
- DefInit *LHSd = dynamic_cast<DefInit*>(LHS);
- if (LHSd) {
- return new StringInit(LHSd->getDef()->getName());
- }
- } else {
- StringInit *LHSs = dynamic_cast<StringInit*>(LHS);
- if (LHSs) {
- std::string Name = LHSs->getValue();
-
- // From TGParser::ParseIDValue
- if (CurRec) {
- if (const RecordVal *RV = CurRec->getValue(Name)) {
- if (RV->getType() != getType())
- throw "type mismatch in cast";
- return new VarInit(Name, RV->getType());
- }
-
- std::string TemplateArgName = CurRec->getName()+":"+Name;
- if (CurRec->isTemplateArg(TemplateArgName)) {
- const RecordVal *RV = CurRec->getValue(TemplateArgName);
- assert(RV && "Template arg doesn't exist??");
-
- if (RV->getType() != getType())
- throw "type mismatch in cast";
-
- return new VarInit(TemplateArgName, RV->getType());
- }
- }
-
- if (CurMultiClass) {
- std::string MCName = CurMultiClass->Rec.getName()+"::"+Name;
- if (CurMultiClass->Rec.isTemplateArg(MCName)) {
- const RecordVal *RV = CurMultiClass->Rec.getValue(MCName);
- assert(RV && "Template arg doesn't exist??");
-
- if (RV->getType() != getType())
- throw "type mismatch in cast";
-
- return new VarInit(MCName, RV->getType());
- }
- }
-
- if (Record *D = (CurRec->getRecords()).getDef(Name))
- return new DefInit(D);
-
- throw TGError(CurRec->getLoc(), "Undefined reference:'" + Name + "'\n");
- }
- }
- break;
- }
- case HEAD: {
- ListInit *LHSl = dynamic_cast<ListInit*>(LHS);
- if (LHSl) {
- if (LHSl->getSize() == 0) {
- assert(0 && "Empty list in car");
- return 0;
- }
- return LHSl->getElement(0);
- }
- break;
- }
- case TAIL: {
- ListInit *LHSl = dynamic_cast<ListInit*>(LHS);
- if (LHSl) {
- if (LHSl->getSize() == 0) {
- assert(0 && "Empty list in cdr");
- return 0;
- }
- ListInit *Result = new ListInit(LHSl->begin()+1, LHSl->end(),
- LHSl->getType());
- return Result;
- }
- break;
- }
- case EMPTY: {
- ListInit *LHSl = dynamic_cast<ListInit*>(LHS);
- if (LHSl) {
- if (LHSl->getSize() == 0) {
- return new IntInit(1);
- } else {
- return new IntInit(0);
- }
- }
- StringInit *LHSs = dynamic_cast<StringInit*>(LHS);
- if (LHSs) {
- if (LHSs->getValue().empty()) {
- return new IntInit(1);
- } else {
- return new IntInit(0);
- }
- }
-
- break;
- }
- }
- return this;
-}
-
-Init *UnOpInit::resolveReferences(Record &R, const RecordVal *RV) {
- Init *lhs = LHS->resolveReferences(R, RV);
-
- if (LHS != lhs)
- return (new UnOpInit(getOpcode(), lhs, getType()))->Fold(&R, 0);
- return Fold(&R, 0);
-}
-
-std::string UnOpInit::getAsString() const {
- std::string Result;
- switch (Opc) {
- case CAST: Result = "!cast<" + getType()->getAsString() + ">"; break;
- case HEAD: Result = "!head"; break;
- case TAIL: Result = "!tail"; break;
- case EMPTY: Result = "!empty"; break;
- }
- return Result + "(" + LHS->getAsString() + ")";
-}
-
-Init *BinOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) {
- switch (getOpcode()) {
- default: assert(0 && "Unknown binop");
- case CONCAT: {
- DagInit *LHSs = dynamic_cast<DagInit*>(LHS);
- DagInit *RHSs = dynamic_cast<DagInit*>(RHS);
- if (LHSs && RHSs) {
- DefInit *LOp = dynamic_cast<DefInit*>(LHSs->getOperator());
- DefInit *ROp = dynamic_cast<DefInit*>(RHSs->getOperator());
- if (LOp == 0 || ROp == 0 || LOp->getDef() != ROp->getDef())
- throw "Concated Dag operators do not match!";
- std::vector<Init*> Args;
- std::vector<std::string> ArgNames;
- for (unsigned i = 0, e = LHSs->getNumArgs(); i != e; ++i) {
- Args.push_back(LHSs->getArg(i));
- ArgNames.push_back(LHSs->getArgName(i));
- }
- for (unsigned i = 0, e = RHSs->getNumArgs(); i != e; ++i) {
- Args.push_back(RHSs->getArg(i));
- ArgNames.push_back(RHSs->getArgName(i));
- }
- return new DagInit(LHSs->getOperator(), "", Args, ArgNames);
- }
- break;
- }
- case STRCONCAT: {
- StringInit *LHSs = dynamic_cast<StringInit*>(LHS);
- StringInit *RHSs = dynamic_cast<StringInit*>(RHS);
- if (LHSs && RHSs)
- return new StringInit(LHSs->getValue() + RHSs->getValue());
- break;
- }
- case EQ: {
- // try to fold eq comparison for 'bit' and 'int', otherwise fallback
- // to string objects.
- IntInit* L =
- dynamic_cast<IntInit*>(LHS->convertInitializerTo(new IntRecTy()));
- IntInit* R =
- dynamic_cast<IntInit*>(RHS->convertInitializerTo(new IntRecTy()));
-
- if (L && R)
- return new IntInit(L->getValue() == R->getValue());
-
- StringInit *LHSs = dynamic_cast<StringInit*>(LHS);
- StringInit *RHSs = dynamic_cast<StringInit*>(RHS);
-
- // Make sure we've resolved
- if (LHSs && RHSs)
- return new IntInit(LHSs->getValue() == RHSs->getValue());
-
- break;
- }
- case SHL:
- case SRA:
- case SRL: {
- IntInit *LHSi = dynamic_cast<IntInit*>(LHS);
- IntInit *RHSi = dynamic_cast<IntInit*>(RHS);
- if (LHSi && RHSi) {
- int64_t LHSv = LHSi->getValue(), RHSv = RHSi->getValue();
- int64_t Result;
- switch (getOpcode()) {
- default: assert(0 && "Bad opcode!");
- case SHL: Result = LHSv << RHSv; break;
- case SRA: Result = LHSv >> RHSv; break;
- case SRL: Result = (uint64_t)LHSv >> (uint64_t)RHSv; break;
- }
- return new IntInit(Result);
- }
- break;
- }
- }
- return this;
-}
-
-Init *BinOpInit::resolveReferences(Record &R, const RecordVal *RV) {
- Init *lhs = LHS->resolveReferences(R, RV);
- Init *rhs = RHS->resolveReferences(R, RV);
-
- if (LHS != lhs || RHS != rhs)
- return (new BinOpInit(getOpcode(), lhs, rhs, getType()))->Fold(&R, 0);
- return Fold(&R, 0);
-}
-
-std::string BinOpInit::getAsString() const {
- std::string Result;
- switch (Opc) {
- case CONCAT: Result = "!con"; break;
- case SHL: Result = "!shl"; break;
- case SRA: Result = "!sra"; break;
- case SRL: Result = "!srl"; break;
- case EQ: Result = "!eq"; break;
- case STRCONCAT: Result = "!strconcat"; break;
- }
- return Result + "(" + LHS->getAsString() + ", " + RHS->getAsString() + ")";
-}
-
-static Init *ForeachHelper(Init *LHS, Init *MHS, Init *RHS, RecTy *Type,
- Record *CurRec, MultiClass *CurMultiClass);
-
-static Init *EvaluateOperation(OpInit *RHSo, Init *LHS, Init *Arg,
- RecTy *Type, Record *CurRec,
- MultiClass *CurMultiClass) {
- std::vector<Init *> NewOperands;
-
- TypedInit *TArg = dynamic_cast<TypedInit*>(Arg);
-
- // If this is a dag, recurse
- if (TArg && TArg->getType()->getAsString() == "dag") {
- Init *Result = ForeachHelper(LHS, Arg, RHSo, Type,
- CurRec, CurMultiClass);
- if (Result != 0) {
- return Result;
- } else {
- return 0;
- }
- }
-
- for (int i = 0; i < RHSo->getNumOperands(); ++i) {
- OpInit *RHSoo = dynamic_cast<OpInit*>(RHSo->getOperand(i));
-
- if (RHSoo) {
- Init *Result = EvaluateOperation(RHSoo, LHS, Arg,
- Type, CurRec, CurMultiClass);
- if (Result != 0) {
- NewOperands.push_back(Result);
- } else {
- NewOperands.push_back(Arg);
- }
- } else if (LHS->getAsString() == RHSo->getOperand(i)->getAsString()) {
- NewOperands.push_back(Arg);
- } else {
- NewOperands.push_back(RHSo->getOperand(i));
- }
- }
-
- // Now run the operator and use its result as the new leaf
- OpInit *NewOp = RHSo->clone(NewOperands);
- Init *NewVal = NewOp->Fold(CurRec, CurMultiClass);
- if (NewVal != NewOp) {
- delete NewOp;
- return NewVal;
- }
- return 0;
-}
-
-static Init *ForeachHelper(Init *LHS, Init *MHS, Init *RHS, RecTy *Type,
- Record *CurRec, MultiClass *CurMultiClass) {
- DagInit *MHSd = dynamic_cast<DagInit*>(MHS);
- ListInit *MHSl = dynamic_cast<ListInit*>(MHS);
-
- DagRecTy *DagType = dynamic_cast<DagRecTy*>(Type);
- ListRecTy *ListType = dynamic_cast<ListRecTy*>(Type);
-
- OpInit *RHSo = dynamic_cast<OpInit*>(RHS);
-
- if (!RHSo) {
- throw TGError(CurRec->getLoc(), "!foreach requires an operator\n");
- }
-
- TypedInit *LHSt = dynamic_cast<TypedInit*>(LHS);
-
- if (!LHSt) {
- throw TGError(CurRec->getLoc(), "!foreach requires typed variable\n");
- }
-
- if ((MHSd && DagType) || (MHSl && ListType)) {
- if (MHSd) {
- Init *Val = MHSd->getOperator();
- Init *Result = EvaluateOperation(RHSo, LHS, Val,
- Type, CurRec, CurMultiClass);
- if (Result != 0) {
- Val = Result;
- }
-
- std::vector<std::pair<Init *, std::string> > args;
- for (unsigned int i = 0; i < MHSd->getNumArgs(); ++i) {
- Init *Arg;
- std::string ArgName;
- Arg = MHSd->getArg(i);
- ArgName = MHSd->getArgName(i);
-
- // Process args
- Init *Result = EvaluateOperation(RHSo, LHS, Arg, Type,
- CurRec, CurMultiClass);
- if (Result != 0) {
- Arg = Result;
- }
-
- // TODO: Process arg names
- args.push_back(std::make_pair(Arg, ArgName));
- }
-
- return new DagInit(Val, "", args);
- }
- if (MHSl) {
- std::vector<Init *> NewOperands;
- std::vector<Init *> NewList(MHSl->begin(), MHSl->end());
-
- for (ListInit::iterator li = NewList.begin(),
- liend = NewList.end();
- li != liend;
- ++li) {
- Init *Item = *li;
- NewOperands.clear();
- for(int i = 0; i < RHSo->getNumOperands(); ++i) {
- // First, replace the foreach variable with the list item
- if (LHS->getAsString() == RHSo->getOperand(i)->getAsString()) {
- NewOperands.push_back(Item);
- } else {
- NewOperands.push_back(RHSo->getOperand(i));
- }
- }
-
- // Now run the operator and use its result as the new list item
- OpInit *NewOp = RHSo->clone(NewOperands);
- Init *NewItem = NewOp->Fold(CurRec, CurMultiClass);
- if (NewItem != NewOp) {
- *li = NewItem;
- delete NewOp;
- }
- }
- return new ListInit(NewList, MHSl->getType());
- }
- }
- return 0;
-}
-
-Init *TernOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) {
- switch (getOpcode()) {
- default: assert(0 && "Unknown binop");
- case SUBST: {
- DefInit *LHSd = dynamic_cast<DefInit*>(LHS);
- VarInit *LHSv = dynamic_cast<VarInit*>(LHS);
- StringInit *LHSs = dynamic_cast<StringInit*>(LHS);
-
- DefInit *MHSd = dynamic_cast<DefInit*>(MHS);
- VarInit *MHSv = dynamic_cast<VarInit*>(MHS);
- StringInit *MHSs = dynamic_cast<StringInit*>(MHS);
-
- DefInit *RHSd = dynamic_cast<DefInit*>(RHS);
- VarInit *RHSv = dynamic_cast<VarInit*>(RHS);
- StringInit *RHSs = dynamic_cast<StringInit*>(RHS);
-
- if ((LHSd && MHSd && RHSd)
- || (LHSv && MHSv && RHSv)
- || (LHSs && MHSs && RHSs)) {
- if (RHSd) {
- Record *Val = RHSd->getDef();
- if (LHSd->getAsString() == RHSd->getAsString()) {
- Val = MHSd->getDef();
- }
- return new DefInit(Val);
- }
- if (RHSv) {
- std::string Val = RHSv->getName();
- if (LHSv->getAsString() == RHSv->getAsString()) {
- Val = MHSv->getName();
- }
- return new VarInit(Val, getType());
- }
- if (RHSs) {
- std::string Val = RHSs->getValue();
-
- std::string::size_type found;
- std::string::size_type idx = 0;
- do {
- found = Val.find(LHSs->getValue(), idx);
- if (found != std::string::npos) {
- Val.replace(found, LHSs->getValue().size(), MHSs->getValue());
- }
- idx = found + MHSs->getValue().size();
- } while (found != std::string::npos);
-
- return new StringInit(Val);
- }
- }
- break;
- }
-
- case FOREACH: {
- Init *Result = ForeachHelper(LHS, MHS, RHS, getType(),
- CurRec, CurMultiClass);
- if (Result != 0) {
- return Result;
- }
- break;
- }
-
- case IF: {
- IntInit *LHSi = dynamic_cast<IntInit*>(LHS);
- if (Init *I = LHS->convertInitializerTo(new IntRecTy()))
- LHSi = dynamic_cast<IntInit*>(I);
- if (LHSi) {
- if (LHSi->getValue()) {
- return MHS;
- } else {
- return RHS;
- }
- }
- break;
- }
- }
-
- return this;
-}
-
-Init *TernOpInit::resolveReferences(Record &R, const RecordVal *RV) {
- Init *lhs = LHS->resolveReferences(R, RV);
-
- if (Opc == IF && lhs != LHS) {
- IntInit *Value = dynamic_cast<IntInit*>(lhs);
- if (Init *I = lhs->convertInitializerTo(new IntRecTy()))
- Value = dynamic_cast<IntInit*>(I);
- if (Value != 0) {
- // Short-circuit
- if (Value->getValue()) {
- Init *mhs = MHS->resolveReferences(R, RV);
- return (new TernOpInit(getOpcode(), lhs, mhs,
- RHS, getType()))->Fold(&R, 0);
- } else {
- Init *rhs = RHS->resolveReferences(R, RV);
- return (new TernOpInit(getOpcode(), lhs, MHS,
- rhs, getType()))->Fold(&R, 0);
- }
- }
- }
-
- Init *mhs = MHS->resolveReferences(R, RV);
- Init *rhs = RHS->resolveReferences(R, RV);
-
- if (LHS != lhs || MHS != mhs || RHS != rhs)
- return (new TernOpInit(getOpcode(), lhs, mhs, rhs, getType()))->Fold(&R, 0);
- return Fold(&R, 0);
-}
-
-std::string TernOpInit::getAsString() const {
- std::string Result;
- switch (Opc) {
- case SUBST: Result = "!subst"; break;
- case FOREACH: Result = "!foreach"; break;
- case IF: Result = "!if"; break;
- }
- return Result + "(" + LHS->getAsString() + ", " + MHS->getAsString() + ", "
- + RHS->getAsString() + ")";
-}
-
-RecTy *TypedInit::getFieldType(const std::string &FieldName) const {
- RecordRecTy *RecordType = dynamic_cast<RecordRecTy *>(getType());
- if (RecordType) {
- RecordVal *Field = RecordType->getRecord()->getValue(FieldName);
- if (Field) {
- return Field->getType();
- }
- }
- return 0;
-}
-
-Init *TypedInit::convertInitializerBitRange(const std::vector<unsigned> &Bits) {
- BitsRecTy *T = dynamic_cast<BitsRecTy*>(getType());
- if (T == 0) return 0; // Cannot subscript a non-bits variable.
- unsigned NumBits = T->getNumBits();
-
- BitsInit *BI = new BitsInit(Bits.size());
- for (unsigned i = 0, e = Bits.size(); i != e; ++i) {
- if (Bits[i] >= NumBits) {
- delete BI;
- return 0;
- }
- BI->setBit(i, new VarBitInit(this, Bits[i]));
- }
- return BI;
-}
-
-Init *TypedInit::convertInitListSlice(const std::vector<unsigned> &Elements) {
- ListRecTy *T = dynamic_cast<ListRecTy*>(getType());
- if (T == 0) return 0; // Cannot subscript a non-list variable.
-
- if (Elements.size() == 1)
- return new VarListElementInit(this, Elements[0]);
-
- std::vector<Init*> ListInits;
- ListInits.reserve(Elements.size());
- for (unsigned i = 0, e = Elements.size(); i != e; ++i)
- ListInits.push_back(new VarListElementInit(this, Elements[i]));
- return new ListInit(ListInits, T);
-}
-
-
-Init *VarInit::resolveBitReference(Record &R, const RecordVal *IRV,
- unsigned Bit) {
- if (R.isTemplateArg(getName())) return 0;
- if (IRV && IRV->getName() != getName()) return 0;
-
- RecordVal *RV = R.getValue(getName());
- assert(RV && "Reference to a non-existent variable?");
- assert(dynamic_cast<BitsInit*>(RV->getValue()));
- BitsInit *BI = (BitsInit*)RV->getValue();
-
- assert(Bit < BI->getNumBits() && "Bit reference out of range!");
- Init *B = BI->getBit(Bit);
-
- // If the bit is set to some value, or if we are resolving a reference to a
- // specific variable and that variable is explicitly unset, then replace the
- // VarBitInit with it.
- if (IRV || !dynamic_cast<UnsetInit*>(B))
- return B;
- return 0;
-}
-
-Init *VarInit::resolveListElementReference(Record &R, const RecordVal *IRV,
- unsigned Elt) {
- if (R.isTemplateArg(getName())) return 0;
- if (IRV && IRV->getName() != getName()) return 0;
-
- RecordVal *RV = R.getValue(getName());
- assert(RV && "Reference to a non-existent variable?");
- ListInit *LI = dynamic_cast<ListInit*>(RV->getValue());
- if (!LI) {
- VarInit *VI = dynamic_cast<VarInit*>(RV->getValue());
- assert(VI && "Invalid list element!");
- return new VarListElementInit(VI, Elt);
- }
-
- if (Elt >= LI->getSize())
- return 0; // Out of range reference.
- Init *E = LI->getElement(Elt);
- // If the element is set to some value, or if we are resolving a reference
- // to a specific variable and that variable is explicitly unset, then
- // replace the VarListElementInit with it.
- if (IRV || !dynamic_cast<UnsetInit*>(E))
- return E;
- return 0;
-}
-
-
-RecTy *VarInit::getFieldType(const std::string &FieldName) const {
- if (RecordRecTy *RTy = dynamic_cast<RecordRecTy*>(getType()))
- if (const RecordVal *RV = RTy->getRecord()->getValue(FieldName))
- return RV->getType();
- return 0;
-}
-
-Init *VarInit::getFieldInit(Record &R, const RecordVal *RV,
- const std::string &FieldName) const {
- if (dynamic_cast<RecordRecTy*>(getType()))
- if (const RecordVal *Val = R.getValue(VarName)) {
- if (RV != Val && (RV || dynamic_cast<UnsetInit*>(Val->getValue())))
- return 0;
- Init *TheInit = Val->getValue();
- assert(TheInit != this && "Infinite loop detected!");
- if (Init *I = TheInit->getFieldInit(R, RV, FieldName))
- return I;
- else
- return 0;
- }
- return 0;
-}
-
-/// resolveReferences - This method is used by classes that refer to other
-/// variables which may not be defined at the time the expression is formed.
-/// If a value is set for the variable later, this method will be called on
-/// users of the value to allow the value to propagate out.
-///
-Init *VarInit::resolveReferences(Record &R, const RecordVal *RV) {
- if (RecordVal *Val = R.getValue(VarName))
- if (RV == Val || (RV == 0 && !dynamic_cast<UnsetInit*>(Val->getValue())))
- return Val->getValue();
- return this;
-}
-
-std::string VarBitInit::getAsString() const {
- return TI->getAsString() + "{" + utostr(Bit) + "}";
-}
-
-Init *VarBitInit::resolveReferences(Record &R, const RecordVal *RV) {
- if (Init *I = getVariable()->resolveBitReference(R, RV, getBitNum()))
- return I;
- return this;
-}
-
-std::string VarListElementInit::getAsString() const {
- return TI->getAsString() + "[" + utostr(Element) + "]";
-}
-
-Init *VarListElementInit::resolveReferences(Record &R, const RecordVal *RV) {
- if (Init *I = getVariable()->resolveListElementReference(R, RV,
- getElementNum()))
- return I;
- return this;
-}
-
-Init *VarListElementInit::resolveBitReference(Record &R, const RecordVal *RV,
- unsigned Bit) {
- // FIXME: This should be implemented, to support references like:
- // bit B = AA[0]{1};
- return 0;
-}
-
-Init *VarListElementInit::
-resolveListElementReference(Record &R, const RecordVal *RV, unsigned Elt) {
- // FIXME: This should be implemented, to support references like:
- // int B = AA[0][1];
- return 0;
-}
-
-RecTy *DefInit::getFieldType(const std::string &FieldName) const {
- if (const RecordVal *RV = Def->getValue(FieldName))
- return RV->getType();
- return 0;
-}
-
-Init *DefInit::getFieldInit(Record &R, const RecordVal *RV,
- const std::string &FieldName) const {
- return Def->getValue(FieldName)->getValue();
-}
-
-
-std::string DefInit::getAsString() const {
- return Def->getName();
-}
-
-Init *FieldInit::resolveBitReference(Record &R, const RecordVal *RV,
- unsigned Bit) {
- if (Init *BitsVal = Rec->getFieldInit(R, RV, FieldName))
- if (BitsInit *BI = dynamic_cast<BitsInit*>(BitsVal)) {
- assert(Bit < BI->getNumBits() && "Bit reference out of range!");
- Init *B = BI->getBit(Bit);
-
- if (dynamic_cast<BitInit*>(B)) // If the bit is set.
- return B; // Replace the VarBitInit with it.
- }
- return 0;
-}
-
-Init *FieldInit::resolveListElementReference(Record &R, const RecordVal *RV,
- unsigned Elt) {
- if (Init *ListVal = Rec->getFieldInit(R, RV, FieldName))
- if (ListInit *LI = dynamic_cast<ListInit*>(ListVal)) {
- if (Elt >= LI->getSize()) return 0;
- Init *E = LI->getElement(Elt);
-
- // If the element is set to some value, or if we are resolving a
- // reference to a specific variable and that variable is explicitly
- // unset, then replace the VarListElementInit with it.
- if (RV || !dynamic_cast<UnsetInit*>(E))
- return E;
- }
- return 0;
-}
-
-Init *FieldInit::resolveReferences(Record &R, const RecordVal *RV) {
- Init *NewRec = RV ? Rec->resolveReferences(R, RV) : Rec;
-
- Init *BitsVal = NewRec->getFieldInit(R, RV, FieldName);
- if (BitsVal) {
- Init *BVR = BitsVal->resolveReferences(R, RV);
- return BVR->isComplete() ? BVR : this;
- }
-
- if (NewRec != Rec) {
- return new FieldInit(NewRec, FieldName);
- }
- return this;
-}
-
-Init *DagInit::resolveReferences(Record &R, const RecordVal *RV) {
- std::vector<Init*> NewArgs;
- for (unsigned i = 0, e = Args.size(); i != e; ++i)
- NewArgs.push_back(Args[i]->resolveReferences(R, RV));
-
- Init *Op = Val->resolveReferences(R, RV);
-
- if (Args != NewArgs || Op != Val)
- return new DagInit(Op, ValName, NewArgs, ArgNames);
-
- return this;
-}
-
-
-std::string DagInit::getAsString() const {
- std::string Result = "(" + Val->getAsString();
- if (!ValName.empty())
- Result += ":" + ValName;
- if (Args.size()) {
- Result += " " + Args[0]->getAsString();
- if (!ArgNames[0].empty()) Result += ":$" + ArgNames[0];
- for (unsigned i = 1, e = Args.size(); i != e; ++i) {
- Result += ", " + Args[i]->getAsString();
- if (!ArgNames[i].empty()) Result += ":$" + ArgNames[i];
- }
- }
- return Result + ")";
-}
-
-
-//===----------------------------------------------------------------------===//
-// Other implementations
-//===----------------------------------------------------------------------===//
-
-RecordVal::RecordVal(const std::string &N, RecTy *T, unsigned P)
- : Name(N), Ty(T), Prefix(P) {
- Value = Ty->convertValue(new UnsetInit());
- assert(Value && "Cannot create unset value for current type!");
-}
-
-void RecordVal::dump() const { errs() << *this; }
-
-void RecordVal::print(raw_ostream &OS, bool PrintSem) const {
- if (getPrefix()) OS << "field ";
- OS << *getType() << " " << getName();
-
- if (getValue())
- OS << " = " << *getValue();
-
- if (PrintSem) OS << ";\n";
-}
-
-unsigned Record::LastID = 0;
-
-void Record::setName(const std::string &Name) {
- if (TrackedRecords.getDef(getName()) == this) {
- TrackedRecords.removeDef(getName());
- this->Name = Name;
- TrackedRecords.addDef(this);
- } else {
- TrackedRecords.removeClass(getName());
- this->Name = Name;
- TrackedRecords.addClass(this);
- }
-}
-
-/// resolveReferencesTo - If anything in this record refers to RV, replace the
-/// reference to RV with the RHS of RV. If RV is null, we resolve all possible
-/// references.
-void Record::resolveReferencesTo(const RecordVal *RV) {
- for (unsigned i = 0, e = Values.size(); i != e; ++i) {
- if (Init *V = Values[i].getValue())
- Values[i].setValue(V->resolveReferences(*this, RV));
- }
-}
-
-void Record::dump() const { errs() << *this; }
-
-raw_ostream &llvm::operator<<(raw_ostream &OS, const Record &R) {
- OS << R.getName();
-
- const std::vector<std::string> &TArgs = R.getTemplateArgs();
- if (!TArgs.empty()) {
- OS << "<";
- for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {
- if (i) OS << ", ";
- const RecordVal *RV = R.getValue(TArgs[i]);
- assert(RV && "Template argument record not found??");
- RV->print(OS, false);
- }
- OS << ">";
- }
-
- OS << " {";
- const std::vector<Record*> &SC = R.getSuperClasses();
- if (!SC.empty()) {
- OS << "\t//";
- for (unsigned i = 0, e = SC.size(); i != e; ++i)
- OS << " " << SC[i]->getName();
- }
- OS << "\n";
-
- const std::vector<RecordVal> &Vals = R.getValues();
- for (unsigned i = 0, e = Vals.size(); i != e; ++i)
- if (Vals[i].getPrefix() && !R.isTemplateArg(Vals[i].getName()))
- OS << Vals[i];
- for (unsigned i = 0, e = Vals.size(); i != e; ++i)
- if (!Vals[i].getPrefix() && !R.isTemplateArg(Vals[i].getName()))
- OS << Vals[i];
-
- return OS << "}\n";
-}
-
-/// getValueInit - Return the initializer for a value with the specified name,
-/// or throw an exception if the field does not exist.
-///
-Init *Record::getValueInit(StringRef FieldName) const {
- const RecordVal *R = getValue(FieldName);
- if (R == 0 || R->getValue() == 0)
- throw "Record `" + getName() + "' does not have a field named `" +
- FieldName.str() + "'!\n";
- return R->getValue();
-}
-
-
-/// getValueAsString - This method looks up the specified field and returns its
-/// value as a string, throwing an exception if the field does not exist or if
-/// the value is not a string.
-///
-std::string Record::getValueAsString(StringRef FieldName) const {
- const RecordVal *R = getValue(FieldName);
- if (R == 0 || R->getValue() == 0)
- throw "Record `" + getName() + "' does not have a field named `" +
- FieldName.str() + "'!\n";
-
- if (const StringInit *SI = dynamic_cast<const StringInit*>(R->getValue()))
- return SI->getValue();
- throw "Record `" + getName() + "', field `" + FieldName.str() +
- "' does not have a string initializer!";
-}
-
-/// getValueAsBitsInit - This method looks up the specified field and returns
-/// its value as a BitsInit, throwing an exception if the field does not exist
-/// or if the value is not the right type.
-///
-BitsInit *Record::getValueAsBitsInit(StringRef FieldName) const {
- const RecordVal *R = getValue(FieldName);
- if (R == 0 || R->getValue() == 0)
- throw "Record `" + getName() + "' does not have a field named `" +
- FieldName.str() + "'!\n";
-
- if (BitsInit *BI = dynamic_cast<BitsInit*>(R->getValue()))
- return BI;
- throw "Record `" + getName() + "', field `" + FieldName.str() +
- "' does not have a BitsInit initializer!";
-}
-
-/// getValueAsListInit - This method looks up the specified field and returns
-/// its value as a ListInit, throwing an exception if the field does not exist
-/// or if the value is not the right type.
-///
-ListInit *Record::getValueAsListInit(StringRef FieldName) const {
- const RecordVal *R = getValue(FieldName);
- if (R == 0 || R->getValue() == 0)
- throw "Record `" + getName() + "' does not have a field named `" +
- FieldName.str() + "'!\n";
-
- if (ListInit *LI = dynamic_cast<ListInit*>(R->getValue()))
- return LI;
- throw "Record `" + getName() + "', field `" + FieldName.str() +
- "' does not have a list initializer!";
-}
-
-/// getValueAsListOfDefs - This method looks up the specified field and returns
-/// its value as a vector of records, throwing an exception if the field does
-/// not exist or if the value is not the right type.
-///
-std::vector<Record*>
-Record::getValueAsListOfDefs(StringRef FieldName) const {
- ListInit *List = getValueAsListInit(FieldName);
- std::vector<Record*> Defs;
- for (unsigned i = 0; i < List->getSize(); i++) {
- if (DefInit *DI = dynamic_cast<DefInit*>(List->getElement(i))) {
- Defs.push_back(DI->getDef());
- } else {
- throw "Record `" + getName() + "', field `" + FieldName.str() +
- "' list is not entirely DefInit!";
- }
- }
- return Defs;
-}
-
-/// getValueAsInt - This method looks up the specified field and returns its
-/// value as an int64_t, throwing an exception if the field does not exist or if
-/// the value is not the right type.
-///
-int64_t Record::getValueAsInt(StringRef FieldName) const {
- const RecordVal *R = getValue(FieldName);
- if (R == 0 || R->getValue() == 0)
- throw "Record `" + getName() + "' does not have a field named `" +
- FieldName.str() + "'!\n";
-
- if (IntInit *II = dynamic_cast<IntInit*>(R->getValue()))
- return II->getValue();
- throw "Record `" + getName() + "', field `" + FieldName.str() +
- "' does not have an int initializer!";
-}
-
-/// getValueAsListOfInts - This method looks up the specified field and returns
-/// its value as a vector of integers, throwing an exception if the field does
-/// not exist or if the value is not the right type.
-///
-std::vector<int64_t>
-Record::getValueAsListOfInts(StringRef FieldName) const {
- ListInit *List = getValueAsListInit(FieldName);
- std::vector<int64_t> Ints;
- for (unsigned i = 0; i < List->getSize(); i++) {
- if (IntInit *II = dynamic_cast<IntInit*>(List->getElement(i))) {
- Ints.push_back(II->getValue());
- } else {
- throw "Record `" + getName() + "', field `" + FieldName.str() +
- "' does not have a list of ints initializer!";
- }
- }
- return Ints;
-}
-
-/// getValueAsListOfStrings - This method looks up the specified field and
-/// returns its value as a vector of strings, throwing an exception if the
-/// field does not exist or if the value is not the right type.
-///
-std::vector<std::string>
-Record::getValueAsListOfStrings(StringRef FieldName) const {
- ListInit *List = getValueAsListInit(FieldName);
- std::vector<std::string> Strings;
- for (unsigned i = 0; i < List->getSize(); i++) {
- if (StringInit *II = dynamic_cast<StringInit*>(List->getElement(i))) {
- Strings.push_back(II->getValue());
- } else {
- throw "Record `" + getName() + "', field `" + FieldName.str() +
- "' does not have a list of strings initializer!";
- }
- }
- return Strings;
-}
-
-/// getValueAsDef - This method looks up the specified field and returns its
-/// value as a Record, throwing an exception if the field does not exist or if
-/// the value is not the right type.
-///
-Record *Record::getValueAsDef(StringRef FieldName) const {
- const RecordVal *R = getValue(FieldName);
- if (R == 0 || R->getValue() == 0)
- throw "Record `" + getName() + "' does not have a field named `" +
- FieldName.str() + "'!\n";
-
- if (DefInit *DI = dynamic_cast<DefInit*>(R->getValue()))
- return DI->getDef();
- throw "Record `" + getName() + "', field `" + FieldName.str() +
- "' does not have a def initializer!";
-}
-
-/// getValueAsBit - This method looks up the specified field and returns its
-/// value as a bit, throwing an exception if the field does not exist or if
-/// the value is not the right type.
-///
-bool Record::getValueAsBit(StringRef FieldName) const {
- const RecordVal *R = getValue(FieldName);
- if (R == 0 || R->getValue() == 0)
- throw "Record `" + getName() + "' does not have a field named `" +
- FieldName.str() + "'!\n";
-
- if (BitInit *BI = dynamic_cast<BitInit*>(R->getValue()))
- return BI->getValue();
- throw "Record `" + getName() + "', field `" + FieldName.str() +
- "' does not have a bit initializer!";
-}
-
-/// getValueAsDag - This method looks up the specified field and returns its
-/// value as an Dag, throwing an exception if the field does not exist or if
-/// the value is not the right type.
-///
-DagInit *Record::getValueAsDag(StringRef FieldName) const {
- const RecordVal *R = getValue(FieldName);
- if (R == 0 || R->getValue() == 0)
- throw "Record `" + getName() + "' does not have a field named `" +
- FieldName.str() + "'!\n";
-
- if (DagInit *DI = dynamic_cast<DagInit*>(R->getValue()))
- return DI;
- throw "Record `" + getName() + "', field `" + FieldName.str() +
- "' does not have a dag initializer!";
-}
-
-std::string Record::getValueAsCode(StringRef FieldName) const {
- const RecordVal *R = getValue(FieldName);
- if (R == 0 || R->getValue() == 0)
- throw "Record `" + getName() + "' does not have a field named `" +
- FieldName.str() + "'!\n";
-
- if (const CodeInit *CI = dynamic_cast<const CodeInit*>(R->getValue()))
- return CI->getValue();
- throw "Record `" + getName() + "', field `" + FieldName.str() +
- "' does not have a code initializer!";
-}
-
-
-void MultiClass::dump() const {
- errs() << "Record:\n";
- Rec.dump();
-
- errs() << "Defs:\n";
- for (RecordVector::const_iterator r = DefPrototypes.begin(),
- rend = DefPrototypes.end();
- r != rend;
- ++r) {
- (*r)->dump();
- }
-}
-
-
-void RecordKeeper::dump() const { errs() << *this; }
-
-raw_ostream &llvm::operator<<(raw_ostream &OS, const RecordKeeper &RK) {
- OS << "------------- Classes -----------------\n";
- const std::map<std::string, Record*> &Classes = RK.getClasses();
- for (std::map<std::string, Record*>::const_iterator I = Classes.begin(),
- E = Classes.end(); I != E; ++I)
- OS << "class " << *I->second;
-
- OS << "------------- Defs -----------------\n";
- const std::map<std::string, Record*> &Defs = RK.getDefs();
- for (std::map<std::string, Record*>::const_iterator I = Defs.begin(),
- E = Defs.end(); I != E; ++I)
- OS << "def " << *I->second;
- return OS;
-}
-
-
-/// getAllDerivedDefinitions - This method returns all concrete definitions
-/// that derive from the specified class name. If a class with the specified
-/// name does not exist, an error is printed and true is returned.
-std::vector<Record*>
-RecordKeeper::getAllDerivedDefinitions(const std::string &ClassName) const {
- Record *Class = getClass(ClassName);
- if (!Class)
- throw "ERROR: Couldn't find the `" + ClassName + "' class!\n";
-
- std::vector<Record*> Defs;
- for (std::map<std::string, Record*>::const_iterator I = getDefs().begin(),
- E = getDefs().end(); I != E; ++I)
- if (I->second->isSubClassOf(Class))
- Defs.push_back(I->second);
-
- return Defs;
-}
-
diff --git a/contrib/llvm/utils/TableGen/Record.h b/contrib/llvm/utils/TableGen/Record.h
deleted file mode 100644
index 2f4080b..0000000
--- a/contrib/llvm/utils/TableGen/Record.h
+++ /dev/null
@@ -1,1500 +0,0 @@
-//===- Record.h - Classes to represent Table Records ------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the main TableGen data structures, including the TableGen
-// types, values, and high-level data structures.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef RECORD_H
-#define RECORD_H
-
-#include "llvm/Support/SourceMgr.h"
-#include "llvm/Support/DataTypes.h"
-#include "llvm/Support/raw_ostream.h"
-#include <map>
-
-namespace llvm {
-class raw_ostream;
-
-// RecTy subclasses.
-class BitRecTy;
-class BitsRecTy;
-class IntRecTy;
-class StringRecTy;
-class ListRecTy;
-class CodeRecTy;
-class DagRecTy;
-class RecordRecTy;
-
-// Init subclasses.
-class Init;
-class UnsetInit;
-class BitInit;
-class BitsInit;
-class IntInit;
-class StringInit;
-class CodeInit;
-class ListInit;
-class UnOpInit;
-class BinOpInit;
-class TernOpInit;
-class DefInit;
-class DagInit;
-class TypedInit;
-class VarInit;
-class FieldInit;
-class VarBitInit;
-class VarListElementInit;
-
-// Other classes.
-class Record;
-class RecordVal;
-struct MultiClass;
-class RecordKeeper;
-
-//===----------------------------------------------------------------------===//
-// Type Classes
-//===----------------------------------------------------------------------===//
-
-struct RecTy {
- virtual ~RecTy() {}
-
- virtual std::string getAsString() const = 0;
- void print(raw_ostream &OS) const { OS << getAsString(); }
- void dump() const;
-
- /// typeIsConvertibleTo - Return true if all values of 'this' type can be
- /// converted to the specified type.
- virtual bool typeIsConvertibleTo(const RecTy *RHS) const = 0;
-
-public: // These methods should only be called from subclasses of Init
- virtual Init *convertValue( UnsetInit *UI) { return 0; }
- virtual Init *convertValue( BitInit *BI) { return 0; }
- virtual Init *convertValue( BitsInit *BI) { return 0; }
- virtual Init *convertValue( IntInit *II) { return 0; }
- virtual Init *convertValue(StringInit *SI) { return 0; }
- virtual Init *convertValue( ListInit *LI) { return 0; }
- virtual Init *convertValue( UnOpInit *UI) {
- return convertValue((TypedInit*)UI);
- }
- virtual Init *convertValue( BinOpInit *UI) {
- return convertValue((TypedInit*)UI);
- }
- virtual Init *convertValue( TernOpInit *UI) {
- return convertValue((TypedInit*)UI);
- }
- virtual Init *convertValue( CodeInit *CI) { return 0; }
- virtual Init *convertValue(VarBitInit *VB) { return 0; }
- virtual Init *convertValue( DefInit *DI) { return 0; }
- virtual Init *convertValue( DagInit *DI) { return 0; }
- virtual Init *convertValue( TypedInit *TI) { return 0; }
- virtual Init *convertValue( VarInit *VI) {
- return convertValue((TypedInit*)VI);
- }
- virtual Init *convertValue( FieldInit *FI) {
- return convertValue((TypedInit*)FI);
- }
-
-public: // These methods should only be called by subclasses of RecTy.
- // baseClassOf - These virtual methods should be overloaded to return true iff
- // all values of type 'RHS' can be converted to the 'this' type.
- virtual bool baseClassOf(const BitRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const BitsRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const IntRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const StringRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const ListRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const DagRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
-};
-
-inline raw_ostream &operator<<(raw_ostream &OS, const RecTy &Ty) {
- Ty.print(OS);
- return OS;
-}
-
-
-/// BitRecTy - 'bit' - Represent a single bit
-///
-class BitRecTy : public RecTy {
-public:
- virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; }
- virtual Init *convertValue( BitInit *BI) { return (Init*)BI; }
- virtual Init *convertValue( BitsInit *BI);
- virtual Init *convertValue( IntInit *II);
- virtual Init *convertValue(StringInit *SI) { return 0; }
- virtual Init *convertValue( ListInit *LI) { return 0; }
- virtual Init *convertValue( CodeInit *CI) { return 0; }
- virtual Init *convertValue(VarBitInit *VB) { return (Init*)VB; }
- virtual Init *convertValue( DefInit *DI) { return 0; }
- virtual Init *convertValue( DagInit *DI) { return 0; }
- virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);}
- virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);}
- virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);}
- virtual Init *convertValue( TypedInit *TI);
- virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);}
- virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
-
- std::string getAsString() const { return "bit"; }
-
- bool typeIsConvertibleTo(const RecTy *RHS) const {
- return RHS->baseClassOf(this);
- }
- virtual bool baseClassOf(const BitRecTy *RHS) const { return true; }
- virtual bool baseClassOf(const BitsRecTy *RHS) const;
- virtual bool baseClassOf(const IntRecTy *RHS) const { return true; }
- virtual bool baseClassOf(const StringRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const ListRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const DagRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
-
-};
-
-
-// BitsRecTy - 'bits<n>' - Represent a fixed number of bits
-/// BitsRecTy - 'bits&lt;n&gt;' - Represent a fixed number of bits
-///
-class BitsRecTy : public RecTy {
- unsigned Size;
-public:
- explicit BitsRecTy(unsigned Sz) : Size(Sz) {}
-
- unsigned getNumBits() const { return Size; }
-
- virtual Init *convertValue( UnsetInit *UI);
- virtual Init *convertValue( BitInit *UI);
- virtual Init *convertValue( BitsInit *BI);
- virtual Init *convertValue( IntInit *II);
- virtual Init *convertValue(StringInit *SI) { return 0; }
- virtual Init *convertValue( ListInit *LI) { return 0; }
- virtual Init *convertValue( CodeInit *CI) { return 0; }
- virtual Init *convertValue(VarBitInit *VB) { return 0; }
- virtual Init *convertValue( DefInit *DI) { return 0; }
- virtual Init *convertValue( DagInit *DI) { return 0; }
- virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);}
- virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);}
- virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);}
- virtual Init *convertValue( TypedInit *TI);
- virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);}
- virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
-
- std::string getAsString() const;
-
- bool typeIsConvertibleTo(const RecTy *RHS) const {
- return RHS->baseClassOf(this);
- }
- virtual bool baseClassOf(const BitRecTy *RHS) const { return Size == 1; }
- virtual bool baseClassOf(const BitsRecTy *RHS) const {
- return RHS->Size == Size;
- }
- virtual bool baseClassOf(const IntRecTy *RHS) const { return true; }
- virtual bool baseClassOf(const StringRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const ListRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const DagRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
-
-};
-
-
-/// IntRecTy - 'int' - Represent an integer value of no particular size
-///
-class IntRecTy : public RecTy {
-public:
- virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; }
- virtual Init *convertValue( BitInit *BI);
- virtual Init *convertValue( BitsInit *BI);
- virtual Init *convertValue( IntInit *II) { return (Init*)II; }
- virtual Init *convertValue(StringInit *SI) { return 0; }
- virtual Init *convertValue( ListInit *LI) { return 0; }
- virtual Init *convertValue( CodeInit *CI) { return 0; }
- virtual Init *convertValue(VarBitInit *VB) { return 0; }
- virtual Init *convertValue( DefInit *DI) { return 0; }
- virtual Init *convertValue( DagInit *DI) { return 0; }
- virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);}
- virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);}
- virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);}
- virtual Init *convertValue( TypedInit *TI);
- virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);}
- virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
-
- std::string getAsString() const { return "int"; }
-
- bool typeIsConvertibleTo(const RecTy *RHS) const {
- return RHS->baseClassOf(this);
- }
-
- virtual bool baseClassOf(const BitRecTy *RHS) const { return true; }
- virtual bool baseClassOf(const BitsRecTy *RHS) const { return true; }
- virtual bool baseClassOf(const IntRecTy *RHS) const { return true; }
- virtual bool baseClassOf(const StringRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const ListRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const DagRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
-
-};
-
-/// StringRecTy - 'string' - Represent an string value
-///
-class StringRecTy : public RecTy {
-public:
- virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; }
- virtual Init *convertValue( BitInit *BI) { return 0; }
- virtual Init *convertValue( BitsInit *BI) { return 0; }
- virtual Init *convertValue( IntInit *II) { return 0; }
- virtual Init *convertValue(StringInit *SI) { return (Init*)SI; }
- virtual Init *convertValue( ListInit *LI) { return 0; }
- virtual Init *convertValue( UnOpInit *BO);
- virtual Init *convertValue( BinOpInit *BO);
- virtual Init *convertValue( TernOpInit *BO) { return RecTy::convertValue(BO);}
-
- virtual Init *convertValue( CodeInit *CI) { return 0; }
- virtual Init *convertValue(VarBitInit *VB) { return 0; }
- virtual Init *convertValue( DefInit *DI) { return 0; }
- virtual Init *convertValue( DagInit *DI) { return 0; }
- virtual Init *convertValue( TypedInit *TI);
- virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);}
- virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
-
- std::string getAsString() const { return "string"; }
-
- bool typeIsConvertibleTo(const RecTy *RHS) const {
- return RHS->baseClassOf(this);
- }
-
- virtual bool baseClassOf(const BitRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const BitsRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const IntRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const StringRecTy *RHS) const { return true; }
- virtual bool baseClassOf(const ListRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const DagRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
-};
-
-// ListRecTy - 'list<Ty>' - Represent a list of values, all of which must be of
-// the specified type.
-/// ListRecTy - 'list&lt;Ty&gt;' - Represent a list of values, all of which must
-/// be of the specified type.
-///
-class ListRecTy : public RecTy {
- RecTy *Ty;
-public:
- explicit ListRecTy(RecTy *T) : Ty(T) {}
-
- RecTy *getElementType() const { return Ty; }
-
- virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; }
- virtual Init *convertValue( BitInit *BI) { return 0; }
- virtual Init *convertValue( BitsInit *BI) { return 0; }
- virtual Init *convertValue( IntInit *II) { return 0; }
- virtual Init *convertValue(StringInit *SI) { return 0; }
- virtual Init *convertValue( ListInit *LI);
- virtual Init *convertValue( CodeInit *CI) { return 0; }
- virtual Init *convertValue(VarBitInit *VB) { return 0; }
- virtual Init *convertValue( DefInit *DI) { return 0; }
- virtual Init *convertValue( DagInit *DI) { return 0; }
- virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);}
- virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);}
- virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);}
- virtual Init *convertValue( TypedInit *TI);
- virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);}
- virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
-
- std::string getAsString() const;
-
- bool typeIsConvertibleTo(const RecTy *RHS) const {
- return RHS->baseClassOf(this);
- }
-
- virtual bool baseClassOf(const BitRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const BitsRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const IntRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const StringRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const ListRecTy *RHS) const {
- return RHS->getElementType()->typeIsConvertibleTo(Ty);
- }
- virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const DagRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
-};
-
-/// CodeRecTy - 'code' - Represent an code fragment, function or method.
-///
-class CodeRecTy : public RecTy {
-public:
- virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; }
- virtual Init *convertValue( BitInit *BI) { return 0; }
- virtual Init *convertValue( BitsInit *BI) { return 0; }
- virtual Init *convertValue( IntInit *II) { return 0; }
- virtual Init *convertValue(StringInit *SI) { return 0; }
- virtual Init *convertValue( ListInit *LI) { return 0; }
- virtual Init *convertValue( CodeInit *CI) { return (Init*)CI; }
- virtual Init *convertValue(VarBitInit *VB) { return 0; }
- virtual Init *convertValue( DefInit *DI) { return 0; }
- virtual Init *convertValue( DagInit *DI) { return 0; }
- virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);}
- virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);}
- virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);}
- virtual Init *convertValue( TypedInit *TI);
- virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);}
- virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
-
- std::string getAsString() const { return "code"; }
-
- bool typeIsConvertibleTo(const RecTy *RHS) const {
- return RHS->baseClassOf(this);
- }
- virtual bool baseClassOf(const BitRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const BitsRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const IntRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const StringRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const ListRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const CodeRecTy *RHS) const { return true; }
- virtual bool baseClassOf(const DagRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
-};
-
-/// DagRecTy - 'dag' - Represent a dag fragment
-///
-class DagRecTy : public RecTy {
-public:
- virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; }
- virtual Init *convertValue( BitInit *BI) { return 0; }
- virtual Init *convertValue( BitsInit *BI) { return 0; }
- virtual Init *convertValue( IntInit *II) { return 0; }
- virtual Init *convertValue(StringInit *SI) { return 0; }
- virtual Init *convertValue( ListInit *LI) { return 0; }
- virtual Init *convertValue( CodeInit *CI) { return 0; }
- virtual Init *convertValue(VarBitInit *VB) { return 0; }
- virtual Init *convertValue( DefInit *DI) { return 0; }
- virtual Init *convertValue( UnOpInit *BO);
- virtual Init *convertValue( BinOpInit *BO);
- virtual Init *convertValue( TernOpInit *BO) { return RecTy::convertValue(BO);}
- virtual Init *convertValue( DagInit *CI) { return (Init*)CI; }
- virtual Init *convertValue( TypedInit *TI);
- virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);}
- virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
-
- std::string getAsString() const { return "dag"; }
-
- bool typeIsConvertibleTo(const RecTy *RHS) const {
- return RHS->baseClassOf(this);
- }
-
- virtual bool baseClassOf(const BitRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const BitsRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const IntRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const StringRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const ListRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const DagRecTy *RHS) const { return true; }
- virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
-};
-
-
-/// RecordRecTy - '[classname]' - Represent an instance of a class, such as:
-/// (R32 X = EAX).
-///
-class RecordRecTy : public RecTy {
- Record *Rec;
-public:
- explicit RecordRecTy(Record *R) : Rec(R) {}
-
- Record *getRecord() const { return Rec; }
-
- virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; }
- virtual Init *convertValue( BitInit *BI) { return 0; }
- virtual Init *convertValue( BitsInit *BI) { return 0; }
- virtual Init *convertValue( IntInit *II) { return 0; }
- virtual Init *convertValue(StringInit *SI) { return 0; }
- virtual Init *convertValue( ListInit *LI) { return 0; }
- virtual Init *convertValue( CodeInit *CI) { return 0; }
- virtual Init *convertValue(VarBitInit *VB) { return 0; }
- virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);}
- virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);}
- virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);}
- virtual Init *convertValue( DefInit *DI);
- virtual Init *convertValue( DagInit *DI) { return 0; }
- virtual Init *convertValue( TypedInit *VI);
- virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);}
- virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
-
- std::string getAsString() const;
-
- bool typeIsConvertibleTo(const RecTy *RHS) const {
- return RHS->baseClassOf(this);
- }
- virtual bool baseClassOf(const BitRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const BitsRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const IntRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const StringRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const ListRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const DagRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const RecordRecTy *RHS) const;
-};
-
-/// resolveTypes - Find a common type that T1 and T2 convert to.
-/// Return 0 if no such type exists.
-///
-RecTy *resolveTypes(RecTy *T1, RecTy *T2);
-
-//===----------------------------------------------------------------------===//
-// Initializer Classes
-//===----------------------------------------------------------------------===//
-
-class Init {
-public:
- virtual ~Init() {}
-
- /// isComplete - This virtual method should be overridden by values that may
- /// not be completely specified yet.
- virtual bool isComplete() const { return true; }
-
- /// print - Print out this value.
- void print(raw_ostream &OS) const { OS << getAsString(); }
-
- /// getAsString - Convert this value to a string form.
- virtual std::string getAsString() const = 0;
-
- /// dump - Debugging method that may be called through a debugger, just
- /// invokes print on stderr.
- void dump() const;
-
- /// convertInitializerTo - This virtual function is a simple call-back
- /// function that should be overridden to call the appropriate
- /// RecTy::convertValue method.
- ///
- virtual Init *convertInitializerTo(RecTy *Ty) = 0;
-
- /// convertInitializerBitRange - This method is used to implement the bitrange
- /// selection operator. Given an initializer, it selects the specified bits
- /// out, returning them as a new init of bits type. If it is not legal to use
- /// the bit subscript operator on this initializer, return null.
- ///
- virtual Init *convertInitializerBitRange(const std::vector<unsigned> &Bits) {
- return 0;
- }
-
- /// convertInitListSlice - This method is used to implement the list slice
- /// selection operator. Given an initializer, it selects the specified list
- /// elements, returning them as a new init of list type. If it is not legal
- /// to take a slice of this, return null.
- ///
- virtual Init *convertInitListSlice(const std::vector<unsigned> &Elements) {
- return 0;
- }
-
- /// getFieldType - This method is used to implement the FieldInit class.
- /// Implementors of this method should return the type of the named field if
- /// they are of record type.
- ///
- virtual RecTy *getFieldType(const std::string &FieldName) const { return 0; }
-
- /// getFieldInit - This method complements getFieldType to return the
- /// initializer for the specified field. If getFieldType returns non-null
- /// this method should return non-null, otherwise it returns null.
- ///
- virtual Init *getFieldInit(Record &R, const RecordVal *RV,
- const std::string &FieldName) const {
- return 0;
- }
-
- /// resolveReferences - This method is used by classes that refer to other
- /// variables which may not be defined at the time the expression is formed.
- /// If a value is set for the variable later, this method will be called on
- /// users of the value to allow the value to propagate out.
- ///
- virtual Init *resolveReferences(Record &R, const RecordVal *RV) {
- return this;
- }
-};
-
-inline raw_ostream &operator<<(raw_ostream &OS, const Init &I) {
- I.print(OS); return OS;
-}
-
-/// TypedInit - This is the common super-class of types that have a specific,
-/// explicit, type.
-///
-class TypedInit : public Init {
- RecTy *Ty;
-public:
- explicit TypedInit(RecTy *T) : Ty(T) {}
-
- RecTy *getType() const { return Ty; }
-
- virtual Init *convertInitializerBitRange(const std::vector<unsigned> &Bits);
- virtual Init *convertInitListSlice(const std::vector<unsigned> &Elements);
-
- /// getFieldType - This method is used to implement the FieldInit class.
- /// Implementors of this method should return the type of the named field if
- /// they are of record type.
- ///
- virtual RecTy *getFieldType(const std::string &FieldName) const;
-
- /// resolveBitReference - This method is used to implement
- /// VarBitInit::resolveReferences. If the bit is able to be resolved, we
- /// simply return the resolved value, otherwise we return null.
- ///
- virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
- unsigned Bit) = 0;
-
- /// resolveListElementReference - This method is used to implement
- /// VarListElementInit::resolveReferences. If the list element is resolvable
- /// now, we return the resolved value, otherwise we return null.
- virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
- unsigned Elt) = 0;
-};
-
-
-/// UnsetInit - ? - Represents an uninitialized value
-///
-class UnsetInit : public Init {
-public:
- virtual Init *convertInitializerTo(RecTy *Ty) {
- return Ty->convertValue(this);
- }
-
- virtual bool isComplete() const { return false; }
- virtual std::string getAsString() const { return "?"; }
-};
-
-
-/// BitInit - true/false - Represent a concrete initializer for a bit.
-///
-class BitInit : public Init {
- bool Value;
-public:
- explicit BitInit(bool V) : Value(V) {}
-
- bool getValue() const { return Value; }
-
- virtual Init *convertInitializerTo(RecTy *Ty) {
- return Ty->convertValue(this);
- }
-
- virtual std::string getAsString() const { return Value ? "1" : "0"; }
-};
-
-/// BitsInit - { a, b, c } - Represents an initializer for a BitsRecTy value.
-/// It contains a vector of bits, whose size is determined by the type.
-///
-class BitsInit : public Init {
- std::vector<Init*> Bits;
-public:
- explicit BitsInit(unsigned Size) : Bits(Size) {}
-
- unsigned getNumBits() const { return Bits.size(); }
-
- Init *getBit(unsigned Bit) const {
- assert(Bit < Bits.size() && "Bit index out of range!");
- return Bits[Bit];
- }
- void setBit(unsigned Bit, Init *V) {
- assert(Bit < Bits.size() && "Bit index out of range!");
- assert(Bits[Bit] == 0 && "Bit already set!");
- Bits[Bit] = V;
- }
-
- virtual Init *convertInitializerTo(RecTy *Ty) {
- return Ty->convertValue(this);
- }
- virtual Init *convertInitializerBitRange(const std::vector<unsigned> &Bits);
-
- virtual bool isComplete() const {
- for (unsigned i = 0; i != getNumBits(); ++i)
- if (!getBit(i)->isComplete()) return false;
- return true;
- }
- bool allInComplete() const {
- for (unsigned i = 0; i != getNumBits(); ++i)
- if (getBit(i)->isComplete()) return false;
- return true;
- }
- virtual std::string getAsString() const;
-
- virtual Init *resolveReferences(Record &R, const RecordVal *RV);
-};
-
-
-/// IntInit - 7 - Represent an initalization by a literal integer value.
-///
-class IntInit : public TypedInit {
- int64_t Value;
-public:
- explicit IntInit(int64_t V) : TypedInit(new IntRecTy), Value(V) {}
-
- int64_t getValue() const { return Value; }
-
- virtual Init *convertInitializerTo(RecTy *Ty) {
- return Ty->convertValue(this);
- }
- virtual Init *convertInitializerBitRange(const std::vector<unsigned> &Bits);
-
- virtual std::string getAsString() const;
-
- /// resolveBitReference - This method is used to implement
- /// VarBitInit::resolveReferences. If the bit is able to be resolved, we
- /// simply return the resolved value, otherwise we return null.
- ///
- virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
- unsigned Bit) {
- assert(0 && "Illegal bit reference off int");
- return 0;
- }
-
- /// resolveListElementReference - This method is used to implement
- /// VarListElementInit::resolveReferences. If the list element is resolvable
- /// now, we return the resolved value, otherwise we return null.
- virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
- unsigned Elt) {
- assert(0 && "Illegal element reference off int");
- return 0;
- }
-};
-
-
-/// StringInit - "foo" - Represent an initialization by a string value.
-///
-class StringInit : public TypedInit {
- std::string Value;
-public:
- explicit StringInit(const std::string &V)
- : TypedInit(new StringRecTy), Value(V) {}
-
- const std::string &getValue() const { return Value; }
-
- virtual Init *convertInitializerTo(RecTy *Ty) {
- return Ty->convertValue(this);
- }
-
- virtual std::string getAsString() const { return "\"" + Value + "\""; }
-
- /// resolveBitReference - This method is used to implement
- /// VarBitInit::resolveReferences. If the bit is able to be resolved, we
- /// simply return the resolved value, otherwise we return null.
- ///
- virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
- unsigned Bit) {
- assert(0 && "Illegal bit reference off string");
- return 0;
- }
-
- /// resolveListElementReference - This method is used to implement
- /// VarListElementInit::resolveReferences. If the list element is resolvable
- /// now, we return the resolved value, otherwise we return null.
- virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
- unsigned Elt) {
- assert(0 && "Illegal element reference off string");
- return 0;
- }
-};
-
-/// CodeInit - "[{...}]" - Represent a code fragment.
-///
-class CodeInit : public Init {
- std::string Value;
-public:
- explicit CodeInit(const std::string &V) : Value(V) {}
-
- const std::string &getValue() const { return Value; }
-
- virtual Init *convertInitializerTo(RecTy *Ty) {
- return Ty->convertValue(this);
- }
-
- virtual std::string getAsString() const { return "[{" + Value + "}]"; }
-};
-
-/// ListInit - [AL, AH, CL] - Represent a list of defs
-///
-class ListInit : public TypedInit {
- std::vector<Init*> Values;
-public:
- typedef std::vector<Init*>::iterator iterator;
- typedef std::vector<Init*>::const_iterator const_iterator;
-
- explicit ListInit(std::vector<Init*> &Vs, RecTy *EltTy)
- : TypedInit(new ListRecTy(EltTy)) {
- Values.swap(Vs);
- }
- explicit ListInit(iterator Start, iterator End, RecTy *EltTy)
- : TypedInit(new ListRecTy(EltTy)), Values(Start, End) {}
-
- unsigned getSize() const { return Values.size(); }
- Init *getElement(unsigned i) const {
- assert(i < Values.size() && "List element index out of range!");
- return Values[i];
- }
-
- Record *getElementAsRecord(unsigned i) const;
-
- Init *convertInitListSlice(const std::vector<unsigned> &Elements);
-
- virtual Init *convertInitializerTo(RecTy *Ty) {
- return Ty->convertValue(this);
- }
-
- /// resolveReferences - This method is used by classes that refer to other
- /// variables which may not be defined at the time they expression is formed.
- /// If a value is set for the variable later, this method will be called on
- /// users of the value to allow the value to propagate out.
- ///
- virtual Init *resolveReferences(Record &R, const RecordVal *RV);
-
- virtual std::string getAsString() const;
-
- inline iterator begin() { return Values.begin(); }
- inline const_iterator begin() const { return Values.begin(); }
- inline iterator end () { return Values.end(); }
- inline const_iterator end () const { return Values.end(); }
-
- inline size_t size () const { return Values.size(); }
- inline bool empty() const { return Values.empty(); }
-
- /// resolveBitReference - This method is used to implement
- /// VarBitInit::resolveReferences. If the bit is able to be resolved, we
- /// simply return the resolved value, otherwise we return null.
- ///
- virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
- unsigned Bit) {
- assert(0 && "Illegal bit reference off list");
- return 0;
- }
-
- /// resolveListElementReference - This method is used to implement
- /// VarListElementInit::resolveReferences. If the list element is resolvable
- /// now, we return the resolved value, otherwise we return null.
- virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
- unsigned Elt);
-};
-
-
-/// OpInit - Base class for operators
-///
-class OpInit : public TypedInit {
-public:
- OpInit(RecTy *Type) : TypedInit(Type) {}
-
- // Clone - Clone this operator, replacing arguments with the new list
- virtual OpInit *clone(std::vector<Init *> &Operands) = 0;
-
- virtual int getNumOperands() const = 0;
- virtual Init *getOperand(int i) = 0;
-
- // Fold - If possible, fold this to a simpler init. Return this if not
- // possible to fold.
- virtual Init *Fold(Record *CurRec, MultiClass *CurMultiClass) = 0;
-
- virtual Init *convertInitializerTo(RecTy *Ty) {
- return Ty->convertValue(this);
- }
-
- virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
- unsigned Bit);
- virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
- unsigned Elt);
-};
-
-
-/// UnOpInit - !op (X) - Transform an init.
-///
-class UnOpInit : public OpInit {
-public:
- enum UnaryOp { CAST, HEAD, TAIL, EMPTY };
-private:
- UnaryOp Opc;
- Init *LHS;
-public:
- UnOpInit(UnaryOp opc, Init *lhs, RecTy *Type) :
- OpInit(Type), Opc(opc), LHS(lhs) {
- }
-
- // Clone - Clone this operator, replacing arguments with the new list
- virtual OpInit *clone(std::vector<Init *> &Operands) {
- assert(Operands.size() == 1 &&
- "Wrong number of operands for unary operation");
- return new UnOpInit(getOpcode(), *Operands.begin(), getType());
- }
-
- int getNumOperands() const { return 1; }
- Init *getOperand(int i) {
- assert(i == 0 && "Invalid operand id for unary operator");
- return getOperand();
- }
-
- UnaryOp getOpcode() const { return Opc; }
- Init *getOperand() const { return LHS; }
-
- // Fold - If possible, fold this to a simpler init. Return this if not
- // possible to fold.
- Init *Fold(Record *CurRec, MultiClass *CurMultiClass);
-
- virtual Init *resolveReferences(Record &R, const RecordVal *RV);
-
- virtual std::string getAsString() const;
-};
-
-/// BinOpInit - !op (X, Y) - Combine two inits.
-///
-class BinOpInit : public OpInit {
-public:
- enum BinaryOp { SHL, SRA, SRL, STRCONCAT, CONCAT, EQ };
-private:
- BinaryOp Opc;
- Init *LHS, *RHS;
-public:
- BinOpInit(BinaryOp opc, Init *lhs, Init *rhs, RecTy *Type) :
- OpInit(Type), Opc(opc), LHS(lhs), RHS(rhs) {
- }
-
- // Clone - Clone this operator, replacing arguments with the new list
- virtual OpInit *clone(std::vector<Init *> &Operands) {
- assert(Operands.size() == 2 &&
- "Wrong number of operands for binary operation");
- return new BinOpInit(getOpcode(), Operands[0], Operands[1], getType());
- }
-
- int getNumOperands() const { return 2; }
- Init *getOperand(int i) {
- assert((i == 0 || i == 1) && "Invalid operand id for binary operator");
- if (i == 0) {
- return getLHS();
- } else {
- return getRHS();
- }
- }
-
- BinaryOp getOpcode() const { return Opc; }
- Init *getLHS() const { return LHS; }
- Init *getRHS() const { return RHS; }
-
- // Fold - If possible, fold this to a simpler init. Return this if not
- // possible to fold.
- Init *Fold(Record *CurRec, MultiClass *CurMultiClass);
-
- virtual Init *resolveReferences(Record &R, const RecordVal *RV);
-
- virtual std::string getAsString() const;
-};
-
-/// TernOpInit - !op (X, Y, Z) - Combine two inits.
-///
-class TernOpInit : public OpInit {
-public:
- enum TernaryOp { SUBST, FOREACH, IF };
-private:
- TernaryOp Opc;
- Init *LHS, *MHS, *RHS;
-public:
- TernOpInit(TernaryOp opc, Init *lhs, Init *mhs, Init *rhs, RecTy *Type) :
- OpInit(Type), Opc(opc), LHS(lhs), MHS(mhs), RHS(rhs) {
- }
-
- // Clone - Clone this operator, replacing arguments with the new list
- virtual OpInit *clone(std::vector<Init *> &Operands) {
- assert(Operands.size() == 3 &&
- "Wrong number of operands for ternary operation");
- return new TernOpInit(getOpcode(), Operands[0], Operands[1], Operands[2],
- getType());
- }
-
- int getNumOperands() const { return 3; }
- Init *getOperand(int i) {
- assert((i == 0 || i == 1 || i == 2) &&
- "Invalid operand id for ternary operator");
- if (i == 0) {
- return getLHS();
- } else if (i == 1) {
- return getMHS();
- } else {
- return getRHS();
- }
- }
-
- TernaryOp getOpcode() const { return Opc; }
- Init *getLHS() const { return LHS; }
- Init *getMHS() const { return MHS; }
- Init *getRHS() const { return RHS; }
-
- // Fold - If possible, fold this to a simpler init. Return this if not
- // possible to fold.
- Init *Fold(Record *CurRec, MultiClass *CurMultiClass);
-
- virtual bool isComplete() const { return false; }
-
- virtual Init *resolveReferences(Record &R, const RecordVal *RV);
-
- virtual std::string getAsString() const;
-};
-
-
-/// VarInit - 'Opcode' - Represent a reference to an entire variable object.
-///
-class VarInit : public TypedInit {
- std::string VarName;
-public:
- explicit VarInit(const std::string &VN, RecTy *T)
- : TypedInit(T), VarName(VN) {}
-
- virtual Init *convertInitializerTo(RecTy *Ty) {
- return Ty->convertValue(this);
- }
-
- const std::string &getName() const { return VarName; }
-
- virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
- unsigned Bit);
- virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
- unsigned Elt);
-
- virtual RecTy *getFieldType(const std::string &FieldName) const;
- virtual Init *getFieldInit(Record &R, const RecordVal *RV,
- const std::string &FieldName) const;
-
- /// resolveReferences - This method is used by classes that refer to other
- /// variables which may not be defined at the time they expression is formed.
- /// If a value is set for the variable later, this method will be called on
- /// users of the value to allow the value to propagate out.
- ///
- virtual Init *resolveReferences(Record &R, const RecordVal *RV);
-
- virtual std::string getAsString() const { return VarName; }
-};
-
-
-/// VarBitInit - Opcode{0} - Represent access to one bit of a variable or field.
-///
-class VarBitInit : public Init {
- TypedInit *TI;
- unsigned Bit;
-public:
- VarBitInit(TypedInit *T, unsigned B) : TI(T), Bit(B) {
- assert(T->getType() && dynamic_cast<BitsRecTy*>(T->getType()) &&
- ((BitsRecTy*)T->getType())->getNumBits() > B &&
- "Illegal VarBitInit expression!");
- }
-
- virtual Init *convertInitializerTo(RecTy *Ty) {
- return Ty->convertValue(this);
- }
-
- TypedInit *getVariable() const { return TI; }
- unsigned getBitNum() const { return Bit; }
-
- virtual std::string getAsString() const;
- virtual Init *resolveReferences(Record &R, const RecordVal *RV);
-};
-
-/// VarListElementInit - List[4] - Represent access to one element of a var or
-/// field.
-class VarListElementInit : public TypedInit {
- TypedInit *TI;
- unsigned Element;
-public:
- VarListElementInit(TypedInit *T, unsigned E)
- : TypedInit(dynamic_cast<ListRecTy*>(T->getType())->getElementType()),
- TI(T), Element(E) {
- assert(T->getType() && dynamic_cast<ListRecTy*>(T->getType()) &&
- "Illegal VarBitInit expression!");
- }
-
- virtual Init *convertInitializerTo(RecTy *Ty) {
- return Ty->convertValue(this);
- }
-
- TypedInit *getVariable() const { return TI; }
- unsigned getElementNum() const { return Element; }
-
- virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
- unsigned Bit);
-
- /// resolveListElementReference - This method is used to implement
- /// VarListElementInit::resolveReferences. If the list element is resolvable
- /// now, we return the resolved value, otherwise we return null.
- virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
- unsigned Elt);
-
- virtual std::string getAsString() const;
- virtual Init *resolveReferences(Record &R, const RecordVal *RV);
-};
-
-/// DefInit - AL - Represent a reference to a 'def' in the description
-///
-class DefInit : public TypedInit {
- Record *Def;
-public:
- explicit DefInit(Record *D) : TypedInit(new RecordRecTy(D)), Def(D) {}
-
- virtual Init *convertInitializerTo(RecTy *Ty) {
- return Ty->convertValue(this);
- }
-
- Record *getDef() const { return Def; }
-
- //virtual Init *convertInitializerBitRange(const std::vector<unsigned> &Bits);
-
- virtual RecTy *getFieldType(const std::string &FieldName) const;
- virtual Init *getFieldInit(Record &R, const RecordVal *RV,
- const std::string &FieldName) const;
-
- virtual std::string getAsString() const;
-
- /// resolveBitReference - This method is used to implement
- /// VarBitInit::resolveReferences. If the bit is able to be resolved, we
- /// simply return the resolved value, otherwise we return null.
- ///
- virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
- unsigned Bit) {
- assert(0 && "Illegal bit reference off def");
- return 0;
- }
-
- /// resolveListElementReference - This method is used to implement
- /// VarListElementInit::resolveReferences. If the list element is resolvable
- /// now, we return the resolved value, otherwise we return null.
- virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
- unsigned Elt) {
- assert(0 && "Illegal element reference off def");
- return 0;
- }
-};
-
-
-/// FieldInit - X.Y - Represent a reference to a subfield of a variable
-///
-class FieldInit : public TypedInit {
- Init *Rec; // Record we are referring to
- std::string FieldName; // Field we are accessing
-public:
- FieldInit(Init *R, const std::string &FN)
- : TypedInit(R->getFieldType(FN)), Rec(R), FieldName(FN) {
- assert(getType() && "FieldInit with non-record type!");
- }
-
- virtual Init *convertInitializerTo(RecTy *Ty) {
- return Ty->convertValue(this);
- }
-
- virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
- unsigned Bit);
- virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
- unsigned Elt);
-
- virtual Init *resolveReferences(Record &R, const RecordVal *RV);
-
- virtual std::string getAsString() const {
- return Rec->getAsString() + "." + FieldName;
- }
-};
-
-/// DagInit - (v a, b) - Represent a DAG tree value. DAG inits are required
-/// to have at least one value then a (possibly empty) list of arguments. Each
-/// argument can have a name associated with it.
-///
-class DagInit : public TypedInit {
- Init *Val;
- std::string ValName;
- std::vector<Init*> Args;
- std::vector<std::string> ArgNames;
-public:
- DagInit(Init *V, std::string VN,
- const std::vector<std::pair<Init*, std::string> > &args)
- : TypedInit(new DagRecTy), Val(V), ValName(VN) {
- Args.reserve(args.size());
- ArgNames.reserve(args.size());
- for (unsigned i = 0, e = args.size(); i != e; ++i) {
- Args.push_back(args[i].first);
- ArgNames.push_back(args[i].second);
- }
- }
- DagInit(Init *V, std::string VN, const std::vector<Init*> &args,
- const std::vector<std::string> &argNames)
- : TypedInit(new DagRecTy), Val(V), ValName(VN), Args(args),
- ArgNames(argNames) { }
-
- virtual Init *convertInitializerTo(RecTy *Ty) {
- return Ty->convertValue(this);
- }
-
- Init *getOperator() const { return Val; }
-
- const std::string &getName() const { return ValName; }
-
- unsigned getNumArgs() const { return Args.size(); }
- Init *getArg(unsigned Num) const {
- assert(Num < Args.size() && "Arg number out of range!");
- return Args[Num];
- }
- const std::string &getArgName(unsigned Num) const {
- assert(Num < ArgNames.size() && "Arg number out of range!");
- return ArgNames[Num];
- }
-
- void setArg(unsigned Num, Init *I) {
- assert(Num < Args.size() && "Arg number out of range!");
- Args[Num] = I;
- }
-
- virtual Init *resolveReferences(Record &R, const RecordVal *RV);
-
- virtual std::string getAsString() const;
-
- typedef std::vector<Init*>::iterator arg_iterator;
- typedef std::vector<Init*>::const_iterator const_arg_iterator;
- typedef std::vector<std::string>::iterator name_iterator;
- typedef std::vector<std::string>::const_iterator const_name_iterator;
-
- inline arg_iterator arg_begin() { return Args.begin(); }
- inline const_arg_iterator arg_begin() const { return Args.begin(); }
- inline arg_iterator arg_end () { return Args.end(); }
- inline const_arg_iterator arg_end () const { return Args.end(); }
-
- inline size_t arg_size () const { return Args.size(); }
- inline bool arg_empty() const { return Args.empty(); }
-
- inline name_iterator name_begin() { return ArgNames.begin(); }
- inline const_name_iterator name_begin() const { return ArgNames.begin(); }
- inline name_iterator name_end () { return ArgNames.end(); }
- inline const_name_iterator name_end () const { return ArgNames.end(); }
-
- inline size_t name_size () const { return ArgNames.size(); }
- inline bool name_empty() const { return ArgNames.empty(); }
-
- virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
- unsigned Bit) {
- assert(0 && "Illegal bit reference off dag");
- return 0;
- }
-
- virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
- unsigned Elt) {
- assert(0 && "Illegal element reference off dag");
- return 0;
- }
-};
-
-//===----------------------------------------------------------------------===//
-// High-Level Classes
-//===----------------------------------------------------------------------===//
-
-class RecordVal {
- std::string Name;
- RecTy *Ty;
- unsigned Prefix;
- Init *Value;
-public:
- RecordVal(const std::string &N, RecTy *T, unsigned P);
-
- const std::string &getName() const { return Name; }
-
- unsigned getPrefix() const { return Prefix; }
- RecTy *getType() const { return Ty; }
- Init *getValue() const { return Value; }
-
- bool setValue(Init *V) {
- if (V) {
- Value = V->convertInitializerTo(Ty);
- return Value == 0;
- }
- Value = 0;
- return false;
- }
-
- void dump() const;
- void print(raw_ostream &OS, bool PrintSem = true) const;
-};
-
-inline raw_ostream &operator<<(raw_ostream &OS, const RecordVal &RV) {
- RV.print(OS << " ");
- return OS;
-}
-
-class Record {
- static unsigned LastID;
-
- // Unique record ID.
- unsigned ID;
- std::string Name;
- SMLoc Loc;
- std::vector<std::string> TemplateArgs;
- std::vector<RecordVal> Values;
- std::vector<Record*> SuperClasses;
-
- // Tracks Record instances. Not owned by Record.
- RecordKeeper &TrackedRecords;
-
-public:
-
- // Constructs a record.
- explicit Record(const std::string &N, SMLoc loc, RecordKeeper &records) :
- ID(LastID++), Name(N), Loc(loc), TrackedRecords(records) {}
- ~Record() {}
-
-
- static unsigned getNewUID() { return LastID++; }
-
-
- unsigned getID() const { return ID; }
-
- const std::string &getName() const { return Name; }
- void setName(const std::string &Name); // Also updates RecordKeeper.
-
- SMLoc getLoc() const { return Loc; }
-
- const std::vector<std::string> &getTemplateArgs() const {
- return TemplateArgs;
- }
- const std::vector<RecordVal> &getValues() const { return Values; }
- const std::vector<Record*> &getSuperClasses() const { return SuperClasses; }
-
- bool isTemplateArg(StringRef Name) const {
- for (unsigned i = 0, e = TemplateArgs.size(); i != e; ++i)
- if (TemplateArgs[i] == Name) return true;
- return false;
- }
-
- const RecordVal *getValue(StringRef Name) const {
- for (unsigned i = 0, e = Values.size(); i != e; ++i)
- if (Values[i].getName() == Name) return &Values[i];
- return 0;
- }
- RecordVal *getValue(StringRef Name) {
- for (unsigned i = 0, e = Values.size(); i != e; ++i)
- if (Values[i].getName() == Name) return &Values[i];
- return 0;
- }
-
- void addTemplateArg(StringRef Name) {
- assert(!isTemplateArg(Name) && "Template arg already defined!");
- TemplateArgs.push_back(Name);
- }
-
- void addValue(const RecordVal &RV) {
- assert(getValue(RV.getName()) == 0 && "Value already added!");
- Values.push_back(RV);
- }
-
- void removeValue(StringRef Name) {
- for (unsigned i = 0, e = Values.size(); i != e; ++i)
- if (Values[i].getName() == Name) {
- Values.erase(Values.begin()+i);
- return;
- }
- assert(0 && "Cannot remove an entry that does not exist!");
- }
-
- bool isSubClassOf(const Record *R) const {
- for (unsigned i = 0, e = SuperClasses.size(); i != e; ++i)
- if (SuperClasses[i] == R)
- return true;
- return false;
- }
-
- bool isSubClassOf(StringRef Name) const {
- for (unsigned i = 0, e = SuperClasses.size(); i != e; ++i)
- if (SuperClasses[i]->getName() == Name)
- return true;
- return false;
- }
-
- void addSuperClass(Record *R) {
- assert(!isSubClassOf(R) && "Already subclassing record!");
- SuperClasses.push_back(R);
- }
-
- /// resolveReferences - If there are any field references that refer to fields
- /// that have been filled in, we can propagate the values now.
- ///
- void resolveReferences() { resolveReferencesTo(0); }
-
- /// resolveReferencesTo - If anything in this record refers to RV, replace the
- /// reference to RV with the RHS of RV. If RV is null, we resolve all
- /// possible references.
- void resolveReferencesTo(const RecordVal *RV);
-
- RecordKeeper &getRecords() const {
- return TrackedRecords;
- }
-
- void dump() const;
-
- //===--------------------------------------------------------------------===//
- // High-level methods useful to tablegen back-ends
- //
-
- /// getValueInit - Return the initializer for a value with the specified name,
- /// or throw an exception if the field does not exist.
- ///
- Init *getValueInit(StringRef FieldName) const;
-
- /// getValueAsString - This method looks up the specified field and returns
- /// its value as a string, throwing an exception if the field does not exist
- /// or if the value is not a string.
- ///
- std::string getValueAsString(StringRef FieldName) const;
-
- /// getValueAsBitsInit - This method looks up the specified field and returns
- /// its value as a BitsInit, throwing an exception if the field does not exist
- /// or if the value is not the right type.
- ///
- BitsInit *getValueAsBitsInit(StringRef FieldName) const;
-
- /// getValueAsListInit - This method looks up the specified field and returns
- /// its value as a ListInit, throwing an exception if the field does not exist
- /// or if the value is not the right type.
- ///
- ListInit *getValueAsListInit(StringRef FieldName) const;
-
- /// getValueAsListOfDefs - This method looks up the specified field and
- /// returns its value as a vector of records, throwing an exception if the
- /// field does not exist or if the value is not the right type.
- ///
- std::vector<Record*> getValueAsListOfDefs(StringRef FieldName) const;
-
- /// getValueAsListOfInts - This method looks up the specified field and
- /// returns its value as a vector of integers, throwing an exception if the
- /// field does not exist or if the value is not the right type.
- ///
- std::vector<int64_t> getValueAsListOfInts(StringRef FieldName) const;
-
- /// getValueAsListOfStrings - This method looks up the specified field and
- /// returns its value as a vector of strings, throwing an exception if the
- /// field does not exist or if the value is not the right type.
- ///
- std::vector<std::string> getValueAsListOfStrings(StringRef FieldName) const;
-
- /// getValueAsDef - This method looks up the specified field and returns its
- /// value as a Record, throwing an exception if the field does not exist or if
- /// the value is not the right type.
- ///
- Record *getValueAsDef(StringRef FieldName) const;
-
- /// getValueAsBit - This method looks up the specified field and returns its
- /// value as a bit, throwing an exception if the field does not exist or if
- /// the value is not the right type.
- ///
- bool getValueAsBit(StringRef FieldName) const;
-
- /// getValueAsInt - This method looks up the specified field and returns its
- /// value as an int64_t, throwing an exception if the field does not exist or
- /// if the value is not the right type.
- ///
- int64_t getValueAsInt(StringRef FieldName) const;
-
- /// getValueAsDag - This method looks up the specified field and returns its
- /// value as an Dag, throwing an exception if the field does not exist or if
- /// the value is not the right type.
- ///
- DagInit *getValueAsDag(StringRef FieldName) const;
-
- /// getValueAsCode - This method looks up the specified field and returns
- /// its value as the string data in a CodeInit, throwing an exception if the
- /// field does not exist or if the value is not a code object.
- ///
- std::string getValueAsCode(StringRef FieldName) const;
-};
-
-raw_ostream &operator<<(raw_ostream &OS, const Record &R);
-
-struct MultiClass {
- Record Rec; // Placeholder for template args and Name.
- typedef std::vector<Record*> RecordVector;
- RecordVector DefPrototypes;
-
- void dump() const;
-
- MultiClass(const std::string &Name, SMLoc Loc, RecordKeeper &Records) :
- Rec(Name, Loc, Records) {}
-};
-
-class RecordKeeper {
- std::map<std::string, Record*> Classes, Defs;
-public:
- ~RecordKeeper() {
- for (std::map<std::string, Record*>::iterator I = Classes.begin(),
- E = Classes.end(); I != E; ++I)
- delete I->second;
- for (std::map<std::string, Record*>::iterator I = Defs.begin(),
- E = Defs.end(); I != E; ++I)
- delete I->second;
- }
-
- const std::map<std::string, Record*> &getClasses() const { return Classes; }
- const std::map<std::string, Record*> &getDefs() const { return Defs; }
-
- Record *getClass(const std::string &Name) const {
- std::map<std::string, Record*>::const_iterator I = Classes.find(Name);
- return I == Classes.end() ? 0 : I->second;
- }
- Record *getDef(const std::string &Name) const {
- std::map<std::string, Record*>::const_iterator I = Defs.find(Name);
- return I == Defs.end() ? 0 : I->second;
- }
- void addClass(Record *R) {
- assert(getClass(R->getName()) == 0 && "Class already exists!");
- Classes.insert(std::make_pair(R->getName(), R));
- }
- void addDef(Record *R) {
- assert(getDef(R->getName()) == 0 && "Def already exists!");
- Defs.insert(std::make_pair(R->getName(), R));
- }
-
- /// removeClass - Remove, but do not delete, the specified record.
- ///
- void removeClass(const std::string &Name) {
- assert(Classes.count(Name) && "Class does not exist!");
- Classes.erase(Name);
- }
- /// removeDef - Remove, but do not delete, the specified record.
- ///
- void removeDef(const std::string &Name) {
- assert(Defs.count(Name) && "Def does not exist!");
- Defs.erase(Name);
- }
-
- //===--------------------------------------------------------------------===//
- // High-level helper methods, useful for tablegen backends...
-
- /// getAllDerivedDefinitions - This method returns all concrete definitions
- /// that derive from the specified class name. If a class with the specified
- /// name does not exist, an exception is thrown.
- std::vector<Record*>
- getAllDerivedDefinitions(const std::string &ClassName) const;
-
- void dump() const;
-};
-
-/// LessRecord - Sorting predicate to sort record pointers by name.
-///
-struct LessRecord {
- bool operator()(const Record *Rec1, const Record *Rec2) const {
- return StringRef(Rec1->getName()).compare_numeric(Rec2->getName()) < 0;
- }
-};
-
-/// LessRecordFieldName - Sorting predicate to sort record pointers by their
-/// name field.
-///
-struct LessRecordFieldName {
- bool operator()(const Record *Rec1, const Record *Rec2) const {
- return Rec1->getValueAsString("Name") < Rec2->getValueAsString("Name");
- }
-};
-
-raw_ostream &operator<<(raw_ostream &OS, const RecordKeeper &RK);
-
-} // End llvm namespace
-
-#endif
diff --git a/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp b/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp
index 65d4a9b..b0f4ffc 100644
--- a/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp
@@ -16,7 +16,8 @@
#include "RegisterInfoEmitter.h"
#include "CodeGenTarget.h"
#include "CodeGenRegisters.h"
-#include "Record.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Format.h"
@@ -39,6 +40,9 @@ RegisterInfoEmitter::runEnums(raw_ostream &OS,
OS << "namespace llvm {\n\n";
+ OS << "class MCRegisterClass;\n"
+ << "extern MCRegisterClass " << Namespace << "MCRegisterClasses[];\n\n";
+
if (!Namespace.empty())
OS << "namespace " << Namespace << " {\n";
OS << "enum {\n NoRegister,\n";
@@ -53,8 +57,7 @@ RegisterInfoEmitter::runEnums(raw_ostream &OS,
if (!Namespace.empty())
OS << "}\n";
- const std::vector<CodeGenRegisterClass> &RegisterClasses =
- Target.getRegisterClasses();
+ ArrayRef<CodeGenRegisterClass*> RegisterClasses = Bank.getRegClasses();
if (!RegisterClasses.empty()) {
OS << "\n// Register classes\n";
if (!Namespace.empty())
@@ -62,7 +65,7 @@ RegisterInfoEmitter::runEnums(raw_ostream &OS,
OS << "enum {\n";
for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) {
if (i) OS << ",\n";
- OS << " " << RegisterClasses[i].getName() << "RegClassID";
+ OS << " " << RegisterClasses[i]->getName() << "RegClassID";
OS << " = " << i;
}
OS << "\n };\n";
@@ -91,6 +94,147 @@ RegisterInfoEmitter::runEnums(raw_ostream &OS,
OS << "#endif // GET_REGINFO_ENUM\n\n";
}
+void
+RegisterInfoEmitter::EmitRegMapping(raw_ostream &OS,
+ const std::vector<CodeGenRegister*> &Regs,
+ bool isCtor) {
+
+ // Collect all information about dwarf register numbers
+ typedef std::map<Record*, std::vector<int64_t>, LessRecord> DwarfRegNumsMapTy;
+ DwarfRegNumsMapTy DwarfRegNums;
+
+ // First, just pull all provided information to the map
+ unsigned maxLength = 0;
+ for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
+ Record *Reg = Regs[i]->TheDef;
+ std::vector<int64_t> RegNums = Reg->getValueAsListOfInts("DwarfNumbers");
+ maxLength = std::max((size_t)maxLength, RegNums.size());
+ if (DwarfRegNums.count(Reg))
+ errs() << "Warning: DWARF numbers for register " << getQualifiedName(Reg)
+ << "specified multiple times\n";
+ DwarfRegNums[Reg] = RegNums;
+ }
+
+ if (!maxLength)
+ return;
+
+ // Now we know maximal length of number list. Append -1's, where needed
+ for (DwarfRegNumsMapTy::iterator
+ I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I)
+ for (unsigned i = I->second.size(), e = maxLength; i != e; ++i)
+ I->second.push_back(-1);
+
+ // Emit reverse information about the dwarf register numbers.
+ for (unsigned j = 0; j < 2; ++j) {
+ OS << " switch (";
+ if (j == 0)
+ OS << "DwarfFlavour";
+ else
+ OS << "EHFlavour";
+ OS << ") {\n"
+ << " default:\n"
+ << " assert(0 && \"Unknown DWARF flavour\");\n"
+ << " break;\n";
+
+ for (unsigned i = 0, e = maxLength; i != e; ++i) {
+ OS << " case " << i << ":\n";
+ for (DwarfRegNumsMapTy::iterator
+ I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I) {
+ int DwarfRegNo = I->second[i];
+ if (DwarfRegNo < 0)
+ continue;
+ OS << " ";
+ if (!isCtor)
+ OS << "RI->";
+ OS << "mapDwarfRegToLLVMReg(" << DwarfRegNo << ", "
+ << getQualifiedName(I->first) << ", ";
+ if (j == 0)
+ OS << "false";
+ else
+ OS << "true";
+ OS << " );\n";
+ }
+ OS << " break;\n";
+ }
+ OS << " }\n";
+ }
+
+ for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
+ Record *Reg = Regs[i]->TheDef;
+ const RecordVal *V = Reg->getValue("DwarfAlias");
+ if (!V || !V->getValue())
+ continue;
+
+ DefInit *DI = dynamic_cast<DefInit*>(V->getValue());
+ Record *Alias = DI->getDef();
+ DwarfRegNums[Reg] = DwarfRegNums[Alias];
+ }
+
+ // Emit information about the dwarf register numbers.
+ for (unsigned j = 0; j < 2; ++j) {
+ OS << " switch (";
+ if (j == 0)
+ OS << "DwarfFlavour";
+ else
+ OS << "EHFlavour";
+ OS << ") {\n"
+ << " default:\n"
+ << " assert(0 && \"Unknown DWARF flavour\");\n"
+ << " break;\n";
+
+ for (unsigned i = 0, e = maxLength; i != e; ++i) {
+ OS << " case " << i << ":\n";
+ // Sort by name to get a stable order.
+ for (DwarfRegNumsMapTy::iterator
+ I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I) {
+ int RegNo = I->second[i];
+ OS << " ";
+ if (!isCtor)
+ OS << "RI->";
+ OS << "mapLLVMRegToDwarfReg(" << getQualifiedName(I->first) << ", "
+ << RegNo << ", ";
+ if (j == 0)
+ OS << "false";
+ else
+ OS << "true";
+ OS << " );\n";
+ }
+ OS << " break;\n";
+ }
+ OS << " }\n";
+ }
+}
+
+// Print a BitVector as a sequence of hex numbers using a little-endian mapping.
+// Width is the number of bits per hex number.
+static void printBitVectorAsHex(raw_ostream &OS,
+ const BitVector &Bits,
+ unsigned Width) {
+ assert(Width <= 32 && "Width too large");
+ unsigned Digits = (Width + 3) / 4;
+ for (unsigned i = 0, e = Bits.size(); i < e; i += Width) {
+ unsigned Value = 0;
+ for (unsigned j = 0; j != Width && i + j != e; ++j)
+ Value |= Bits.test(i + j) << j;
+ OS << format("0x%0*x, ", Digits, Value);
+ }
+}
+
+// Helper to emit a set of bits into a constant byte array.
+class BitVectorEmitter {
+ BitVector Values;
+public:
+ void add(unsigned v) {
+ if (v >= Values.size())
+ Values.resize(((v/8)+1)*8); // Round up to the next byte.
+ Values[v] = true;
+ }
+
+ void print(raw_ostream &OS) {
+ printBitVectorAsHex(OS, Values, 8);
+ }
+};
+
//
// runMCDesc - Print out MC register descriptions.
//
@@ -186,11 +330,73 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
}
OS << "};\n\n"; // End of register descriptors...
+ ArrayRef<CodeGenRegisterClass*> RegisterClasses = RegBank.getRegClasses();
+
+ // Loop over all of the register classes... emitting each one.
+ OS << "namespace { // Register classes...\n";
+
+ // Emit the register enum value arrays for each RegisterClass
+ for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
+ const CodeGenRegisterClass &RC = *RegisterClasses[rc];
+ ArrayRef<Record*> Order = RC.getOrder();
+
+ // Give the register class a legal C name if it's anonymous.
+ std::string Name = RC.getName();
+
+ // Emit the register list now.
+ OS << " // " << Name << " Register Class...\n"
+ << " static const unsigned " << Name
+ << "[] = {\n ";
+ for (unsigned i = 0, e = Order.size(); i != e; ++i) {
+ Record *Reg = Order[i];
+ OS << getQualifiedName(Reg) << ", ";
+ }
+ OS << "\n };\n\n";
+
+ OS << " // " << Name << " Bit set.\n"
+ << " static const unsigned char " << Name
+ << "Bits[] = {\n ";
+ BitVectorEmitter BVE;
+ for (unsigned i = 0, e = Order.size(); i != e; ++i) {
+ Record *Reg = Order[i];
+ BVE.add(Target.getRegBank().getReg(Reg)->EnumValue);
+ }
+ BVE.print(OS);
+ OS << "\n };\n\n";
+
+ }
+ OS << "}\n\n";
+
+ OS << "MCRegisterClass " << TargetName << "MCRegisterClasses[] = {\n";
+
+ for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
+ const CodeGenRegisterClass &RC = *RegisterClasses[rc];
+ OS << " MCRegisterClass(" << RC.getQualifiedName() + "RegClassID" << ", "
+ << '\"' << RC.getName() << "\", "
+ << RC.SpillSize/8 << ", "
+ << RC.SpillAlignment/8 << ", "
+ << RC.CopyCost << ", "
+ << RC.Allocatable << ", "
+ << RC.getName() << ", " << RC.getName() << " + "
+ << RC.getOrder().size() << ", "
+ << RC.getName() << "Bits, sizeof(" << RC.getName() << "Bits)"
+ << "),\n";
+ }
+
+ OS << "};\n\n";
+
// MCRegisterInfo initialization routine.
OS << "static inline void Init" << TargetName
- << "MCRegisterInfo(MCRegisterInfo *RI) {\n";
+ << "MCRegisterInfo(MCRegisterInfo *RI, unsigned RA, "
+ << "unsigned DwarfFlavour = 0, unsigned EHFlavour = 0) {\n";
OS << " RI->InitMCRegisterInfo(" << TargetName << "RegDesc, "
- << Regs.size()+1 << ");\n}\n\n";
+ << Regs.size()+1 << ", RA, " << TargetName << "MCRegisterClasses, "
+ << RegisterClasses.size() << ");\n\n";
+
+ EmitRegMapping(OS, Regs, false);
+
+ OS << "}\n\n";
+
OS << "} // End llvm namespace \n";
OS << "#endif // GET_REGINFO_MC_DESC\n\n";
@@ -213,17 +419,15 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target,
OS << "namespace llvm {\n\n";
OS << "struct " << ClassName << " : public TargetRegisterInfo {\n"
- << " explicit " << ClassName << "();\n"
- << " virtual int getDwarfRegNumFull(unsigned RegNum, "
- << "unsigned Flavour) const;\n"
- << " virtual int getLLVMRegNumFull(unsigned DwarfRegNum, "
- << "unsigned Flavour) const;\n"
- << " virtual int getDwarfRegNum(unsigned RegNum, bool isEH) const = 0;\n"
+ << " explicit " << ClassName
+ << "(unsigned RA, unsigned D = 0, unsigned E = 0);\n"
<< " virtual bool needsStackRealignment(const MachineFunction &) const\n"
<< " { return false; }\n"
<< " unsigned getSubReg(unsigned RegNo, unsigned Index) const;\n"
<< " unsigned getSubRegIndex(unsigned RegNo, unsigned SubRegNo) const;\n"
<< " unsigned composeSubRegIndices(unsigned, unsigned) const;\n"
+ << " const TargetRegisterClass *"
+ "getSubClassWithSubReg(const TargetRegisterClass*, unsigned) const;\n"
<< "};\n\n";
const std::vector<Record*> &SubRegIndices = RegBank.getSubRegIndices();
@@ -241,15 +445,14 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target,
OS << "}\n";
}
- const std::vector<CodeGenRegisterClass> &RegisterClasses =
- Target.getRegisterClasses();
+ ArrayRef<CodeGenRegisterClass*> RegisterClasses = RegBank.getRegClasses();
if (!RegisterClasses.empty()) {
- OS << "namespace " << RegisterClasses[0].Namespace
+ OS << "namespace " << RegisterClasses[0]->Namespace
<< " { // Register classes\n";
for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) {
- const CodeGenRegisterClass &RC = RegisterClasses[i];
+ const CodeGenRegisterClass &RC = *RegisterClasses[i];
const std::string &Name = RC.getName();
// Output the register class definition.
@@ -285,42 +488,30 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << "namespace llvm {\n\n";
+ // Get access to MCRegisterClass data.
+ OS << "extern MCRegisterClass " << Target.getName()
+ << "MCRegisterClasses[];\n";
+
// Start out by emitting each of the register classes.
- const std::vector<CodeGenRegisterClass> &RegisterClasses =
- Target.getRegisterClasses();
+ ArrayRef<CodeGenRegisterClass*> RegisterClasses = RegBank.getRegClasses();
// Collect all registers belonging to any allocatable class.
std::set<Record*> AllocatableRegs;
- // Loop over all of the register classes... emitting each one.
- OS << "namespace { // Register classes...\n";
-
- // Emit the register enum value arrays for each RegisterClass
+ // Collect allocatable registers.
for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
- const CodeGenRegisterClass &RC = RegisterClasses[rc];
+ const CodeGenRegisterClass &RC = *RegisterClasses[rc];
ArrayRef<Record*> Order = RC.getOrder();
- // Collect allocatable registers.
if (RC.Allocatable)
AllocatableRegs.insert(Order.begin(), Order.end());
-
- // Give the register class a legal C name if it's anonymous.
- std::string Name = RC.getName();
-
- // Emit the register list now.
- OS << " // " << Name << " Register Class...\n"
- << " static const unsigned " << Name
- << "[] = {\n ";
- for (unsigned i = 0, e = Order.size(); i != e; ++i) {
- Record *Reg = Order[i];
- OS << getQualifiedName(Reg) << ", ";
- }
- OS << "\n };\n\n";
}
+ OS << "namespace { // Register classes...\n";
+
// Emit the ValueType arrays for each RegisterClass
for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
- const CodeGenRegisterClass &RC = RegisterClasses[rc];
+ const CodeGenRegisterClass &RC = *RegisterClasses[rc];
// Give the register class a legal C name if it's anonymous.
std::string Name = RC.getName() + "VTs";
@@ -338,65 +529,39 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
// Now that all of the structs have been emitted, emit the instances.
if (!RegisterClasses.empty()) {
- OS << "namespace " << RegisterClasses[0].Namespace
+ OS << "namespace " << RegisterClasses[0]->Namespace
<< " { // Register class instances\n";
for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i)
- OS << " " << RegisterClasses[i].getName() << "Class\t"
- << RegisterClasses[i].getName() << "RegClass;\n";
+ OS << " " << RegisterClasses[i]->getName() << "Class\t"
+ << RegisterClasses[i]->getName() << "RegClass;\n";
- std::map<unsigned, std::set<unsigned> > SuperClassMap;
std::map<unsigned, std::set<unsigned> > SuperRegClassMap;
- OS << "\n";
+
+ OS << "\n static const TargetRegisterClass* const "
+ << "NullRegClasses[] = { NULL };\n\n";
unsigned NumSubRegIndices = RegBank.getSubRegIndices().size();
if (NumSubRegIndices) {
- // Emit the sub-register classes for each RegisterClass
+ // Compute the super-register classes for each RegisterClass
for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
- const CodeGenRegisterClass &RC = RegisterClasses[rc];
- std::vector<Record*> SRC(NumSubRegIndices);
+ const CodeGenRegisterClass &RC = *RegisterClasses[rc];
for (DenseMap<Record*,Record*>::const_iterator
i = RC.SubRegClasses.begin(),
e = RC.SubRegClasses.end(); i != e; ++i) {
- // Build SRC array.
- unsigned idx = RegBank.getSubRegIndexNo(i->first);
- SRC.at(idx-1) = i->second;
-
// Find the register class number of i->second for SuperRegClassMap.
- for (unsigned rc2 = 0, e2 = RegisterClasses.size(); rc2 != e2; ++rc2) {
- const CodeGenRegisterClass &RC2 = RegisterClasses[rc2];
- if (RC2.TheDef == i->second) {
- SuperRegClassMap[rc2].insert(rc);
- break;
- }
- }
- }
-
- // Give the register class a legal C name if it's anonymous.
- std::string Name = RC.TheDef->getName();
-
- OS << " // " << Name
- << " Sub-register Classes...\n"
- << " static const TargetRegisterClass* const "
- << Name << "SubRegClasses[] = {\n ";
-
- for (unsigned idx = 0; idx != NumSubRegIndices; ++idx) {
- if (idx)
- OS << ", ";
- if (SRC[idx])
- OS << "&" << getQualifiedName(SRC[idx]) << "RegClass";
- else
- OS << "0";
+ const CodeGenRegisterClass *RC2 = RegBank.getRegClass(i->second);
+ assert(RC2 && "Invalid register class in SubRegClasses");
+ SuperRegClassMap[RC2->EnumValue].insert(rc);
}
- OS << "\n };\n\n";
}
// Emit the super-register classes for each RegisterClass
for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
- const CodeGenRegisterClass &RC = RegisterClasses[rc];
+ const CodeGenRegisterClass &RC = *RegisterClasses[rc];
// Give the register class a legal C name if it's anonymous.
- std::string Name = RC.TheDef->getName();
+ std::string Name = RC.getName();
OS << " // " << Name
<< " Super-register Classes...\n"
@@ -409,10 +574,10 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
if (I != SuperRegClassMap.end()) {
for (std::set<unsigned>::iterator II = I->second.begin(),
EE = I->second.end(); II != EE; ++II) {
- const CodeGenRegisterClass &RC2 = RegisterClasses[*II];
+ const CodeGenRegisterClass &RC2 = *RegisterClasses[*II];
if (!Empty)
OS << ", ";
- OS << "&" << getQualifiedName(RC2.TheDef) << "RegClass";
+ OS << "&" << RC2.getQualifiedName() << "RegClass";
Empty = false;
}
}
@@ -420,97 +585,51 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << (!Empty ? ", " : "") << "NULL";
OS << "\n };\n\n";
}
- } else {
- // No subregindices in this target
- OS << " static const TargetRegisterClass* const "
- << "NullRegClasses[] = { NULL };\n\n";
}
// Emit the sub-classes array for each RegisterClass
for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
- const CodeGenRegisterClass &RC = RegisterClasses[rc];
+ const CodeGenRegisterClass &RC = *RegisterClasses[rc];
// Give the register class a legal C name if it's anonymous.
- std::string Name = RC.TheDef->getName();
-
- OS << " // " << Name
- << " Register Class sub-classes...\n"
- << " static const TargetRegisterClass* const "
- << Name << "Subclasses[] = {\n ";
-
- bool Empty = true;
- for (unsigned rc2 = 0, e2 = RegisterClasses.size(); rc2 != e2; ++rc2) {
- const CodeGenRegisterClass &RC2 = RegisterClasses[rc2];
-
- // Sub-classes are used to determine if a virtual register can be used
- // as an instruction operand, or if it must be copied first.
- if (rc == rc2 || !RC.hasSubClass(&RC2)) continue;
-
- if (!Empty) OS << ", ";
- OS << "&" << getQualifiedName(RC2.TheDef) << "RegClass";
- Empty = false;
-
- std::map<unsigned, std::set<unsigned> >::iterator SCMI =
- SuperClassMap.find(rc2);
- if (SCMI == SuperClassMap.end()) {
- SuperClassMap.insert(std::make_pair(rc2, std::set<unsigned>()));
- SCMI = SuperClassMap.find(rc2);
- }
- SCMI->second.insert(rc);
- }
+ std::string Name = RC.getName();
- OS << (!Empty ? ", " : "") << "NULL";
- OS << "\n };\n\n";
+ OS << " static const unsigned " << Name << "SubclassMask[] = { ";
+ printBitVectorAsHex(OS, RC.getSubClasses(), 32);
+ OS << "};\n\n";
}
+ // Emit NULL terminated super-class lists.
for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
- const CodeGenRegisterClass &RC = RegisterClasses[rc];
+ const CodeGenRegisterClass &RC = *RegisterClasses[rc];
+ ArrayRef<CodeGenRegisterClass*> Supers = RC.getSuperClasses();
- // Give the register class a legal C name if it's anonymous.
- std::string Name = RC.TheDef->getName();
-
- OS << " // " << Name
- << " Register Class super-classes...\n"
- << " static const TargetRegisterClass* const "
- << Name << "Superclasses[] = {\n ";
-
- bool Empty = true;
- std::map<unsigned, std::set<unsigned> >::iterator I =
- SuperClassMap.find(rc);
- if (I != SuperClassMap.end()) {
- for (std::set<unsigned>::iterator II = I->second.begin(),
- EE = I->second.end(); II != EE; ++II) {
- const CodeGenRegisterClass &RC2 = RegisterClasses[*II];
- if (!Empty) OS << ", ";
- OS << "&" << getQualifiedName(RC2.TheDef) << "RegClass";
- Empty = false;
- }
- }
+ // Skip classes without supers. We can reuse NullRegClasses.
+ if (Supers.empty())
+ continue;
- OS << (!Empty ? ", " : "") << "NULL";
- OS << "\n };\n\n";
+ OS << " static const TargetRegisterClass* const "
+ << RC.getName() << "Superclasses[] = {\n";
+ for (unsigned i = 0; i != Supers.size(); ++i)
+ OS << " &" << Supers[i]->getQualifiedName() << "RegClass,\n";
+ OS << " NULL\n };\n\n";
}
// Emit methods.
for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) {
- const CodeGenRegisterClass &RC = RegisterClasses[i];
+ const CodeGenRegisterClass &RC = *RegisterClasses[i];
OS << RC.getName() << "Class::" << RC.getName()
- << "Class() : TargetRegisterClass("
- << RC.getName() + "RegClassID" << ", "
- << '\"' << RC.getName() << "\", "
+ << "Class() : TargetRegisterClass(&"
+ << Target.getName() << "MCRegisterClasses["
+ << RC.getName() + "RegClassID" << "], "
<< RC.getName() + "VTs" << ", "
- << RC.getName() + "Subclasses" << ", "
- << RC.getName() + "Superclasses" << ", "
- << (NumSubRegIndices ? RC.getName() + "Sub" : std::string("Null"))
- << "RegClasses, "
- << (NumSubRegIndices ? RC.getName() + "Super" : std::string("Null"))
- << "RegClasses, "
- << RC.SpillSize/8 << ", "
- << RC.SpillAlignment/8 << ", "
- << RC.CopyCost << ", "
- << RC.Allocatable << ", "
- << RC.getName() << ", " << RC.getName() << " + "
- << RC.getOrder().size()
+ << RC.getName() + "SubclassMask" << ", ";
+ if (RC.getSuperClasses().empty())
+ OS << "NullRegClasses, ";
+ else
+ OS << RC.getName() + "Superclasses, ";
+ OS << (NumSubRegIndices ? RC.getName() + "Super" : std::string("Null"))
+ << "RegClasses"
<< ") {}\n";
if (!RC.AltOrderSelect.empty()) {
OS << "\nstatic inline unsigned " << RC.getName()
@@ -525,10 +644,12 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << (elem ? ", " : " ") << getQualifiedName(Elems[elem]);
OS << " };\n";
}
- OS << " static const ArrayRef<unsigned> Order[] = {\n"
- << " ArrayRef<unsigned>(" << RC.getName();
+ OS << " const MCRegisterClass &MCR = " << Target.getName()
+ << "MCRegisterClasses[" << RC.getQualifiedName() + "RegClassID];"
+ << " static const ArrayRef<unsigned> Order[] = {\n"
+ << " makeArrayRef(MCR.begin(), MCR.getNumRegs()";
for (unsigned oi = 1, oe = RC.getNumOrders(); oi != oe; ++oi)
- OS << "),\n ArrayRef<unsigned>(AltOrder" << oi;
+ OS << "),\n makeArrayRef(AltOrder" << oi;
OS << ")\n };\n const unsigned Select = " << RC.getName()
<< "AltOrderSelect(MF);\n assert(Select < " << RC.getNumOrders()
<< ");\n return Order[Select];\n}\n";
@@ -541,7 +662,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << "\nnamespace {\n";
OS << " const TargetRegisterClass* const RegisterClasses[] = {\n";
for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i)
- OS << " &" << getQualifiedName(RegisterClasses[i].TheDef)
+ OS << " &" << RegisterClasses[i]->getQualifiedName()
<< "RegClass,\n";
OS << " };\n";
OS << "}\n"; // End of anonymous namespace...
@@ -658,106 +779,59 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
}
OS << " }\n}\n\n";
+ // Emit getSubClassWithSubReg.
+ OS << "const TargetRegisterClass *" << ClassName
+ << "::getSubClassWithSubReg(const TargetRegisterClass *RC, unsigned Idx)"
+ " const {\n";
+ if (SubRegIndices.empty()) {
+ OS << " assert(Idx == 0 && \"Target has no sub-registers\");\n"
+ << " return RC;\n";
+ } else {
+ // Use the smallest type that can hold a regclass ID with room for a
+ // sentinel.
+ if (RegisterClasses.size() < UINT8_MAX)
+ OS << " static const uint8_t Table[";
+ else if (RegisterClasses.size() < UINT16_MAX)
+ OS << " static const uint16_t Table[";
+ else
+ throw "Too many register classes.";
+ OS << RegisterClasses.size() << "][" << SubRegIndices.size() << "] = {\n";
+ for (unsigned rci = 0, rce = RegisterClasses.size(); rci != rce; ++rci) {
+ const CodeGenRegisterClass &RC = *RegisterClasses[rci];
+ OS << " {\t// " << RC.getName() << "\n";
+ for (unsigned sri = 0, sre = SubRegIndices.size(); sri != sre; ++sri) {
+ Record *Idx = SubRegIndices[sri];
+ if (CodeGenRegisterClass *SRC = RC.getSubClassWithSubReg(Idx))
+ OS << " " << SRC->EnumValue + 1 << ",\t// " << Idx->getName()
+ << " -> " << SRC->getName() << "\n";
+ else
+ OS << " 0,\t// " << Idx->getName() << "\n";
+ }
+ OS << " },\n";
+ }
+ OS << " };\n assert(RC && \"Missing regclass\");\n"
+ << " if (!Idx) return RC;\n --Idx;\n"
+ << " assert(Idx < " << SubRegIndices.size() << " && \"Bad subreg\");\n"
+ << " unsigned TV = Table[RC->getID()][Idx];\n"
+ << " return TV ? getRegClass(TV - 1) : 0;\n";
+ }
+ OS << "}\n\n";
+
// Emit the constructor of the class...
OS << "extern MCRegisterDesc " << TargetName << "RegDesc[];\n";
OS << ClassName << "::" << ClassName
- << "()\n"
+ << "(unsigned RA, unsigned DwarfFlavour, unsigned EHFlavour)\n"
<< " : TargetRegisterInfo(" << TargetName << "RegInfoDesc"
<< ", RegisterClasses, RegisterClasses+" << RegisterClasses.size() <<",\n"
<< " " << TargetName << "SubRegIndexTable) {\n"
<< " InitMCRegisterInfo(" << TargetName << "RegDesc, "
- << Regs.size()+1 << ");\n"
- << "}\n\n";
+ << Regs.size()+1 << ", RA, " << TargetName << "MCRegisterClasses, "
+ << RegisterClasses.size() << ");\n\n";
- // Collect all information about dwarf register numbers
- typedef std::map<Record*, std::vector<int64_t>, LessRecord> DwarfRegNumsMapTy;
- DwarfRegNumsMapTy DwarfRegNums;
+ EmitRegMapping(OS, Regs, true);
- // First, just pull all provided information to the map
- unsigned maxLength = 0;
- for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
- Record *Reg = Regs[i]->TheDef;
- std::vector<int64_t> RegNums = Reg->getValueAsListOfInts("DwarfNumbers");
- maxLength = std::max((size_t)maxLength, RegNums.size());
- if (DwarfRegNums.count(Reg))
- errs() << "Warning: DWARF numbers for register " << getQualifiedName(Reg)
- << "specified multiple times\n";
- DwarfRegNums[Reg] = RegNums;
- }
-
- // Now we know maximal length of number list. Append -1's, where needed
- for (DwarfRegNumsMapTy::iterator
- I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I)
- for (unsigned i = I->second.size(), e = maxLength; i != e; ++i)
- I->second.push_back(-1);
-
- // Emit reverse information about the dwarf register numbers.
- OS << "int " << ClassName << "::getLLVMRegNumFull(unsigned DwarfRegNum, "
- << "unsigned Flavour) const {\n"
- << " switch (Flavour) {\n"
- << " default:\n"
- << " assert(0 && \"Unknown DWARF flavour\");\n"
- << " return -1;\n";
-
- for (unsigned i = 0, e = maxLength; i != e; ++i) {
- OS << " case " << i << ":\n"
- << " switch (DwarfRegNum) {\n"
- << " default:\n"
- << " assert(0 && \"Invalid DwarfRegNum\");\n"
- << " return -1;\n";
-
- for (DwarfRegNumsMapTy::iterator
- I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I) {
- int DwarfRegNo = I->second[i];
- if (DwarfRegNo >= 0)
- OS << " case " << DwarfRegNo << ":\n"
- << " return " << getQualifiedName(I->first) << ";\n";
- }
- OS << " };\n";
- }
-
- OS << " };\n}\n\n";
-
- for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
- Record *Reg = Regs[i]->TheDef;
- const RecordVal *V = Reg->getValue("DwarfAlias");
- if (!V || !V->getValue())
- continue;
-
- DefInit *DI = dynamic_cast<DefInit*>(V->getValue());
- Record *Alias = DI->getDef();
- DwarfRegNums[Reg] = DwarfRegNums[Alias];
- }
-
- // Emit information about the dwarf register numbers.
- OS << "int " << ClassName << "::getDwarfRegNumFull(unsigned RegNum, "
- << "unsigned Flavour) const {\n"
- << " switch (Flavour) {\n"
- << " default:\n"
- << " assert(0 && \"Unknown DWARF flavour\");\n"
- << " return -1;\n";
-
- for (unsigned i = 0, e = maxLength; i != e; ++i) {
- OS << " case " << i << ":\n"
- << " switch (RegNum) {\n"
- << " default:\n"
- << " assert(0 && \"Invalid RegNum\");\n"
- << " return -1;\n";
-
- // Sort by name to get a stable order.
-
-
- for (DwarfRegNumsMapTy::iterator
- I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I) {
- int RegNo = I->second[i];
- OS << " case " << getQualifiedName(I->first) << ":\n"
- << " return " << RegNo << ";\n";
- }
- OS << " };\n";
- }
-
- OS << " };\n}\n\n";
+ OS << "}\n\n";
OS << "} // End llvm namespace \n";
OS << "#endif // GET_REGINFO_TARGET_DESC\n\n";
diff --git a/contrib/llvm/utils/TableGen/RegisterInfoEmitter.h b/contrib/llvm/utils/TableGen/RegisterInfoEmitter.h
index 2c01b5c..0fd4d07 100644
--- a/contrib/llvm/utils/TableGen/RegisterInfoEmitter.h
+++ b/contrib/llvm/utils/TableGen/RegisterInfoEmitter.h
@@ -16,11 +16,13 @@
#ifndef REGISTER_INFO_EMITTER_H
#define REGISTER_INFO_EMITTER_H
-#include "TableGenBackend.h"
+#include "llvm/TableGen/TableGenBackend.h"
+#include <vector>
namespace llvm {
class CodeGenRegBank;
+struct CodeGenRegister;
class CodeGenTarget;
class RegisterInfoEmitter : public TableGenBackend {
@@ -44,6 +46,11 @@ public:
// run - Output the register file description.
void run(raw_ostream &o);
+
+private:
+ void EmitRegMapping(raw_ostream &o,
+ const std::vector<CodeGenRegister*> &Regs, bool isCtor);
+ void EmitRegClasses(raw_ostream &OS, CodeGenTarget &Target);
};
} // End llvm namespace
diff --git a/contrib/llvm/utils/TableGen/SetTheory.cpp b/contrib/llvm/utils/TableGen/SetTheory.cpp
index 21ac09c..bef73f3 100644
--- a/contrib/llvm/utils/TableGen/SetTheory.cpp
+++ b/contrib/llvm/utils/TableGen/SetTheory.cpp
@@ -13,8 +13,8 @@
//===----------------------------------------------------------------------===//
#include "SetTheory.h"
-#include "Error.h"
-#include "Record.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/Support/Format.h"
using namespace llvm;
diff --git a/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp b/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp
index 978e91a..103a403 100644
--- a/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp
@@ -13,7 +13,7 @@
#include "SubtargetEmitter.h"
#include "CodeGenTarget.h"
-#include "Record.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Debug.h"
#include <algorithm>
diff --git a/contrib/llvm/utils/TableGen/SubtargetEmitter.h b/contrib/llvm/utils/TableGen/SubtargetEmitter.h
index b239f3d..ff01274 100644
--- a/contrib/llvm/utils/TableGen/SubtargetEmitter.h
+++ b/contrib/llvm/utils/TableGen/SubtargetEmitter.h
@@ -14,7 +14,7 @@
#ifndef SUBTARGET_EMITTER_H
#define SUBTARGET_EMITTER_H
-#include "TableGenBackend.h"
+#include "llvm/TableGen/TableGenBackend.h"
#include "llvm/MC/MCInstrItineraries.h"
#include <vector>
#include <map>
diff --git a/contrib/llvm/utils/TableGen/TGLexer.cpp b/contrib/llvm/utils/TableGen/TGLexer.cpp
deleted file mode 100644
index b4b90ff..0000000
--- a/contrib/llvm/utils/TableGen/TGLexer.cpp
+++ /dev/null
@@ -1,435 +0,0 @@
-//===- TGLexer.cpp - Lexer for TableGen -----------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Implement the Lexer for TableGen.
-//
-//===----------------------------------------------------------------------===//
-
-#include "TGLexer.h"
-#include "Error.h"
-#include "llvm/Support/SourceMgr.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Config/config.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/ADT/Twine.h"
-#include <cctype>
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-#include <cerrno>
-using namespace llvm;
-
-TGLexer::TGLexer(SourceMgr &SM) : SrcMgr(SM) {
- CurBuffer = 0;
- CurBuf = SrcMgr.getMemoryBuffer(CurBuffer);
- CurPtr = CurBuf->getBufferStart();
- TokStart = 0;
-}
-
-SMLoc TGLexer::getLoc() const {
- return SMLoc::getFromPointer(TokStart);
-}
-
-/// ReturnError - Set the error to the specified string at the specified
-/// location. This is defined to always return tgtok::Error.
-tgtok::TokKind TGLexer::ReturnError(const char *Loc, const Twine &Msg) {
- PrintError(Loc, Msg);
- return tgtok::Error;
-}
-
-int TGLexer::getNextChar() {
- char CurChar = *CurPtr++;
- switch (CurChar) {
- default:
- return (unsigned char)CurChar;
- case 0: {
- // A nul character in the stream is either the end of the current buffer or
- // a random nul in the file. Disambiguate that here.
- if (CurPtr-1 != CurBuf->getBufferEnd())
- return 0; // Just whitespace.
-
- // If this is the end of an included file, pop the parent file off the
- // include stack.
- SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
- if (ParentIncludeLoc != SMLoc()) {
- CurBuffer = SrcMgr.FindBufferContainingLoc(ParentIncludeLoc);
- CurBuf = SrcMgr.getMemoryBuffer(CurBuffer);
- CurPtr = ParentIncludeLoc.getPointer();
- return getNextChar();
- }
-
- // Otherwise, return end of file.
- --CurPtr; // Another call to lex will return EOF again.
- return EOF;
- }
- case '\n':
- case '\r':
- // Handle the newline character by ignoring it and incrementing the line
- // count. However, be careful about 'dos style' files with \n\r in them.
- // Only treat a \n\r or \r\n as a single line.
- if ((*CurPtr == '\n' || (*CurPtr == '\r')) &&
- *CurPtr != CurChar)
- ++CurPtr; // Eat the two char newline sequence.
- return '\n';
- }
-}
-
-tgtok::TokKind TGLexer::LexToken() {
- TokStart = CurPtr;
- // This always consumes at least one character.
- int CurChar = getNextChar();
-
- switch (CurChar) {
- default:
- // Handle letters: [a-zA-Z_#]
- if (isalpha(CurChar) || CurChar == '_' || CurChar == '#')
- return LexIdentifier();
-
- // Unknown character, emit an error.
- return ReturnError(TokStart, "Unexpected character");
- case EOF: return tgtok::Eof;
- case ':': return tgtok::colon;
- case ';': return tgtok::semi;
- case '.': return tgtok::period;
- case ',': return tgtok::comma;
- case '<': return tgtok::less;
- case '>': return tgtok::greater;
- case ']': return tgtok::r_square;
- case '{': return tgtok::l_brace;
- case '}': return tgtok::r_brace;
- case '(': return tgtok::l_paren;
- case ')': return tgtok::r_paren;
- case '=': return tgtok::equal;
- case '?': return tgtok::question;
-
- case 0:
- case ' ':
- case '\t':
- case '\n':
- case '\r':
- // Ignore whitespace.
- return LexToken();
- case '/':
- // If this is the start of a // comment, skip until the end of the line or
- // the end of the buffer.
- if (*CurPtr == '/')
- SkipBCPLComment();
- else if (*CurPtr == '*') {
- if (SkipCComment())
- return tgtok::Error;
- } else // Otherwise, this is an error.
- return ReturnError(TokStart, "Unexpected character");
- return LexToken();
- case '-': case '+':
- case '0': case '1': case '2': case '3': case '4': case '5': case '6':
- case '7': case '8': case '9':
- return LexNumber();
- case '"': return LexString();
- case '$': return LexVarName();
- case '[': return LexBracket();
- case '!': return LexExclaim();
- }
-}
-
-/// LexString - Lex "[^"]*"
-tgtok::TokKind TGLexer::LexString() {
- const char *StrStart = CurPtr;
-
- CurStrVal = "";
-
- while (*CurPtr != '"') {
- // If we hit the end of the buffer, report an error.
- if (*CurPtr == 0 && CurPtr == CurBuf->getBufferEnd())
- return ReturnError(StrStart, "End of file in string literal");
-
- if (*CurPtr == '\n' || *CurPtr == '\r')
- return ReturnError(StrStart, "End of line in string literal");
-
- if (*CurPtr != '\\') {
- CurStrVal += *CurPtr++;
- continue;
- }
-
- ++CurPtr;
-
- switch (*CurPtr) {
- case '\\': case '\'': case '"':
- // These turn into their literal character.
- CurStrVal += *CurPtr++;
- break;
- case 't':
- CurStrVal += '\t';
- ++CurPtr;
- break;
- case 'n':
- CurStrVal += '\n';
- ++CurPtr;
- break;
-
- case '\n':
- case '\r':
- return ReturnError(CurPtr, "escaped newlines not supported in tblgen");
-
- // If we hit the end of the buffer, report an error.
- case '\0':
- if (CurPtr == CurBuf->getBufferEnd())
- return ReturnError(StrStart, "End of file in string literal");
- // FALL THROUGH
- default:
- return ReturnError(CurPtr, "invalid escape in string literal");
- }
- }
-
- ++CurPtr;
- return tgtok::StrVal;
-}
-
-tgtok::TokKind TGLexer::LexVarName() {
- if (!isalpha(CurPtr[0]) && CurPtr[0] != '_')
- return ReturnError(TokStart, "Invalid variable name");
-
- // Otherwise, we're ok, consume the rest of the characters.
- const char *VarNameStart = CurPtr++;
-
- while (isalpha(*CurPtr) || isdigit(*CurPtr) || *CurPtr == '_')
- ++CurPtr;
-
- CurStrVal.assign(VarNameStart, CurPtr);
- return tgtok::VarName;
-}
-
-
-tgtok::TokKind TGLexer::LexIdentifier() {
- // The first letter is [a-zA-Z_#].
- const char *IdentStart = TokStart;
-
- // Match the rest of the identifier regex: [0-9a-zA-Z_#]*
- while (isalpha(*CurPtr) || isdigit(*CurPtr) || *CurPtr == '_' ||
- *CurPtr == '#')
- ++CurPtr;
-
-
- // Check to see if this identifier is a keyword.
- unsigned Len = CurPtr-IdentStart;
-
- if (Len == 3 && !memcmp(IdentStart, "int", 3)) return tgtok::Int;
- if (Len == 3 && !memcmp(IdentStart, "bit", 3)) return tgtok::Bit;
- if (Len == 4 && !memcmp(IdentStart, "bits", 4)) return tgtok::Bits;
- if (Len == 6 && !memcmp(IdentStart, "string", 6)) return tgtok::String;
- if (Len == 4 && !memcmp(IdentStart, "list", 4)) return tgtok::List;
- if (Len == 4 && !memcmp(IdentStart, "code", 4)) return tgtok::Code;
- if (Len == 3 && !memcmp(IdentStart, "dag", 3)) return tgtok::Dag;
-
- if (Len == 5 && !memcmp(IdentStart, "class", 5)) return tgtok::Class;
- if (Len == 3 && !memcmp(IdentStart, "def", 3)) return tgtok::Def;
- if (Len == 4 && !memcmp(IdentStart, "defm", 4)) return tgtok::Defm;
- if (Len == 10 && !memcmp(IdentStart, "multiclass", 10))
- return tgtok::MultiClass;
- if (Len == 5 && !memcmp(IdentStart, "field", 5)) return tgtok::Field;
- if (Len == 3 && !memcmp(IdentStart, "let", 3)) return tgtok::Let;
- if (Len == 2 && !memcmp(IdentStart, "in", 2)) return tgtok::In;
-
- if (Len == 7 && !memcmp(IdentStart, "include", 7)) {
- if (LexInclude()) return tgtok::Error;
- return Lex();
- }
-
- CurStrVal.assign(IdentStart, CurPtr);
- return tgtok::Id;
-}
-
-/// LexInclude - We just read the "include" token. Get the string token that
-/// comes next and enter the include.
-bool TGLexer::LexInclude() {
- // The token after the include must be a string.
- tgtok::TokKind Tok = LexToken();
- if (Tok == tgtok::Error) return true;
- if (Tok != tgtok::StrVal) {
- PrintError(getLoc(), "Expected filename after include");
- return true;
- }
-
- // Get the string.
- std::string Filename = CurStrVal;
- std::string IncludedFile;
-
-
- CurBuffer = SrcMgr.AddIncludeFile(Filename, SMLoc::getFromPointer(CurPtr),
- IncludedFile);
- if (CurBuffer == -1) {
- PrintError(getLoc(), "Could not find include file '" + Filename + "'");
- return true;
- }
-
- Dependencies.push_back(IncludedFile);
- // Save the line number and lex buffer of the includer.
- CurBuf = SrcMgr.getMemoryBuffer(CurBuffer);
- CurPtr = CurBuf->getBufferStart();
- return false;
-}
-
-void TGLexer::SkipBCPLComment() {
- ++CurPtr; // skip the second slash.
- while (1) {
- switch (*CurPtr) {
- case '\n':
- case '\r':
- return; // Newline is end of comment.
- case 0:
- // If this is the end of the buffer, end the comment.
- if (CurPtr == CurBuf->getBufferEnd())
- return;
- break;
- }
- // Otherwise, skip the character.
- ++CurPtr;
- }
-}
-
-/// SkipCComment - This skips C-style /**/ comments. The only difference from C
-/// is that we allow nesting.
-bool TGLexer::SkipCComment() {
- ++CurPtr; // skip the star.
- unsigned CommentDepth = 1;
-
- while (1) {
- int CurChar = getNextChar();
- switch (CurChar) {
- case EOF:
- PrintError(TokStart, "Unterminated comment!");
- return true;
- case '*':
- // End of the comment?
- if (CurPtr[0] != '/') break;
-
- ++CurPtr; // End the */.
- if (--CommentDepth == 0)
- return false;
- break;
- case '/':
- // Start of a nested comment?
- if (CurPtr[0] != '*') break;
- ++CurPtr;
- ++CommentDepth;
- break;
- }
- }
-}
-
-/// LexNumber - Lex:
-/// [-+]?[0-9]+
-/// 0x[0-9a-fA-F]+
-/// 0b[01]+
-tgtok::TokKind TGLexer::LexNumber() {
- if (CurPtr[-1] == '0') {
- if (CurPtr[0] == 'x') {
- ++CurPtr;
- const char *NumStart = CurPtr;
- while (isxdigit(CurPtr[0]))
- ++CurPtr;
-
- // Requires at least one hex digit.
- if (CurPtr == NumStart)
- return ReturnError(TokStart, "Invalid hexadecimal number");
-
- errno = 0;
- CurIntVal = strtoll(NumStart, 0, 16);
- if (errno == EINVAL)
- return ReturnError(TokStart, "Invalid hexadecimal number");
- if (errno == ERANGE) {
- errno = 0;
- CurIntVal = (int64_t)strtoull(NumStart, 0, 16);
- if (errno == EINVAL)
- return ReturnError(TokStart, "Invalid hexadecimal number");
- if (errno == ERANGE)
- return ReturnError(TokStart, "Hexadecimal number out of range");
- }
- return tgtok::IntVal;
- } else if (CurPtr[0] == 'b') {
- ++CurPtr;
- const char *NumStart = CurPtr;
- while (CurPtr[0] == '0' || CurPtr[0] == '1')
- ++CurPtr;
-
- // Requires at least one binary digit.
- if (CurPtr == NumStart)
- return ReturnError(CurPtr-2, "Invalid binary number");
- CurIntVal = strtoll(NumStart, 0, 2);
- return tgtok::IntVal;
- }
- }
-
- // Check for a sign without a digit.
- if (!isdigit(CurPtr[0])) {
- if (CurPtr[-1] == '-')
- return tgtok::minus;
- else if (CurPtr[-1] == '+')
- return tgtok::plus;
- }
-
- while (isdigit(CurPtr[0]))
- ++CurPtr;
- CurIntVal = strtoll(TokStart, 0, 10);
- return tgtok::IntVal;
-}
-
-/// LexBracket - We just read '['. If this is a code block, return it,
-/// otherwise return the bracket. Match: '[' and '[{ ( [^}]+ | }[^]] )* }]'
-tgtok::TokKind TGLexer::LexBracket() {
- if (CurPtr[0] != '{')
- return tgtok::l_square;
- ++CurPtr;
- const char *CodeStart = CurPtr;
- while (1) {
- int Char = getNextChar();
- if (Char == EOF) break;
-
- if (Char != '}') continue;
-
- Char = getNextChar();
- if (Char == EOF) break;
- if (Char == ']') {
- CurStrVal.assign(CodeStart, CurPtr-2);
- return tgtok::CodeFragment;
- }
- }
-
- return ReturnError(CodeStart-2, "Unterminated Code Block");
-}
-
-/// LexExclaim - Lex '!' and '![a-zA-Z]+'.
-tgtok::TokKind TGLexer::LexExclaim() {
- if (!isalpha(*CurPtr))
- return ReturnError(CurPtr - 1, "Invalid \"!operator\"");
-
- const char *Start = CurPtr++;
- while (isalpha(*CurPtr))
- ++CurPtr;
-
- // Check to see which operator this is.
- tgtok::TokKind Kind =
- StringSwitch<tgtok::TokKind>(StringRef(Start, CurPtr - Start))
- .Case("eq", tgtok::XEq)
- .Case("if", tgtok::XIf)
- .Case("head", tgtok::XHead)
- .Case("tail", tgtok::XTail)
- .Case("con", tgtok::XConcat)
- .Case("shl", tgtok::XSHL)
- .Case("sra", tgtok::XSRA)
- .Case("srl", tgtok::XSRL)
- .Case("cast", tgtok::XCast)
- .Case("empty", tgtok::XEmpty)
- .Case("subst", tgtok::XSubst)
- .Case("foreach", tgtok::XForEach)
- .Case("strconcat", tgtok::XStrConcat)
- .Default(tgtok::Error);
-
- return Kind != tgtok::Error ? Kind : ReturnError(Start-1, "Unknown operator");
-}
-
diff --git a/contrib/llvm/utils/TableGen/TGLexer.h b/contrib/llvm/utils/TableGen/TGLexer.h
deleted file mode 100644
index 84d328b..0000000
--- a/contrib/llvm/utils/TableGen/TGLexer.h
+++ /dev/null
@@ -1,125 +0,0 @@
-//===- TGLexer.h - Lexer for TableGen Files ---------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This class represents the Lexer for tablegen files.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef TGLEXER_H
-#define TGLEXER_H
-
-#include "llvm/Support/DataTypes.h"
-#include <string>
-#include <vector>
-#include <cassert>
-
-namespace llvm {
-class MemoryBuffer;
-class SourceMgr;
-class SMLoc;
-class Twine;
-
-namespace tgtok {
- enum TokKind {
- // Markers
- Eof, Error,
-
- // Tokens with no info.
- minus, plus, // - +
- l_square, r_square, // [ ]
- l_brace, r_brace, // { }
- l_paren, r_paren, // ( )
- less, greater, // < >
- colon, semi, // : ;
- comma, period, // , .
- equal, question, // = ?
-
- // Keywords.
- Bit, Bits, Class, Code, Dag, Def, Defm, Field, In, Int, Let, List,
- MultiClass, String,
-
- // !keywords.
- XConcat, XSRA, XSRL, XSHL, XStrConcat, XCast, XSubst,
- XForEach, XHead, XTail, XEmpty, XIf, XEq,
-
- // Integer value.
- IntVal,
-
- // String valued tokens.
- Id, StrVal, VarName, CodeFragment
- };
-}
-
-/// TGLexer - TableGen Lexer class.
-class TGLexer {
- SourceMgr &SrcMgr;
-
- const char *CurPtr;
- const MemoryBuffer *CurBuf;
-
- // Information about the current token.
- const char *TokStart;
- tgtok::TokKind CurCode;
- std::string CurStrVal; // This is valid for ID, STRVAL, VARNAME, CODEFRAGMENT
- int64_t CurIntVal; // This is valid for INTVAL.
-
- /// CurBuffer - This is the current buffer index we're lexing from as managed
- /// by the SourceMgr object.
- int CurBuffer;
- /// Dependencies - This is the list of all included files.
- std::vector<std::string> Dependencies;
-
-public:
- TGLexer(SourceMgr &SrcMgr);
- ~TGLexer() {}
-
- tgtok::TokKind Lex() {
- return CurCode = LexToken();
- }
-
- const std::vector<std::string> &getDependencies() const {
- return Dependencies;
- }
-
- tgtok::TokKind getCode() const { return CurCode; }
-
- const std::string &getCurStrVal() const {
- assert((CurCode == tgtok::Id || CurCode == tgtok::StrVal ||
- CurCode == tgtok::VarName || CurCode == tgtok::CodeFragment) &&
- "This token doesn't have a string value");
- return CurStrVal;
- }
- int64_t getCurIntVal() const {
- assert(CurCode == tgtok::IntVal && "This token isn't an integer");
- return CurIntVal;
- }
-
- SMLoc getLoc() const;
-
-private:
- /// LexToken - Read the next token and return its code.
- tgtok::TokKind LexToken();
-
- tgtok::TokKind ReturnError(const char *Loc, const Twine &Msg);
-
- int getNextChar();
- void SkipBCPLComment();
- bool SkipCComment();
- tgtok::TokKind LexIdentifier();
- bool LexInclude();
- tgtok::TokKind LexString();
- tgtok::TokKind LexVarName();
- tgtok::TokKind LexNumber();
- tgtok::TokKind LexBracket();
- tgtok::TokKind LexExclaim();
-};
-
-} // end namespace llvm
-
-#endif
diff --git a/contrib/llvm/utils/TableGen/TGParser.cpp b/contrib/llvm/utils/TableGen/TGParser.cpp
deleted file mode 100644
index 59097f9..0000000
--- a/contrib/llvm/utils/TableGen/TGParser.cpp
+++ /dev/null
@@ -1,2152 +0,0 @@
-//===- TGParser.cpp - Parser for TableGen Files ---------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Implement the Parser for TableGen.
-//
-//===----------------------------------------------------------------------===//
-
-#include "TGParser.h"
-#include "Record.h"
-#include "llvm/ADT/StringExtras.h"
-#include <algorithm>
-#include <sstream>
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/Support/CommandLine.h"
-using namespace llvm;
-
-//===----------------------------------------------------------------------===//
-// Support Code for the Semantic Actions.
-//===----------------------------------------------------------------------===//
-
-namespace llvm {
-struct SubClassReference {
- SMLoc RefLoc;
- Record *Rec;
- std::vector<Init*> TemplateArgs;
- SubClassReference() : Rec(0) {}
-
- bool isInvalid() const { return Rec == 0; }
-};
-
-struct SubMultiClassReference {
- SMLoc RefLoc;
- MultiClass *MC;
- std::vector<Init*> TemplateArgs;
- SubMultiClassReference() : MC(0) {}
-
- bool isInvalid() const { return MC == 0; }
- void dump() const;
-};
-
-void SubMultiClassReference::dump() const {
- errs() << "Multiclass:\n";
-
- MC->dump();
-
- errs() << "Template args:\n";
- for (std::vector<Init *>::const_iterator i = TemplateArgs.begin(),
- iend = TemplateArgs.end();
- i != iend;
- ++i) {
- (*i)->dump();
- }
-}
-
-} // end namespace llvm
-
-bool TGParser::AddValue(Record *CurRec, SMLoc Loc, const RecordVal &RV) {
- if (CurRec == 0)
- CurRec = &CurMultiClass->Rec;
-
- if (RecordVal *ERV = CurRec->getValue(RV.getName())) {
- // The value already exists in the class, treat this as a set.
- if (ERV->setValue(RV.getValue()))
- return Error(Loc, "New definition of '" + RV.getName() + "' of type '" +
- RV.getType()->getAsString() + "' is incompatible with " +
- "previous definition of type '" +
- ERV->getType()->getAsString() + "'");
- } else {
- CurRec->addValue(RV);
- }
- return false;
-}
-
-/// SetValue -
-/// Return true on error, false on success.
-bool TGParser::SetValue(Record *CurRec, SMLoc Loc, const std::string &ValName,
- const std::vector<unsigned> &BitList, Init *V) {
- if (!V) return false;
-
- if (CurRec == 0) CurRec = &CurMultiClass->Rec;
-
- RecordVal *RV = CurRec->getValue(ValName);
- if (RV == 0)
- return Error(Loc, "Value '" + ValName + "' unknown!");
-
- // Do not allow assignments like 'X = X'. This will just cause infinite loops
- // in the resolution machinery.
- if (BitList.empty())
- if (VarInit *VI = dynamic_cast<VarInit*>(V))
- if (VI->getName() == ValName)
- return false;
-
- // If we are assigning to a subset of the bits in the value... then we must be
- // assigning to a field of BitsRecTy, which must have a BitsInit
- // initializer.
- //
- if (!BitList.empty()) {
- BitsInit *CurVal = dynamic_cast<BitsInit*>(RV->getValue());
- if (CurVal == 0)
- return Error(Loc, "Value '" + ValName + "' is not a bits type");
-
- // Convert the incoming value to a bits type of the appropriate size...
- Init *BI = V->convertInitializerTo(new BitsRecTy(BitList.size()));
- if (BI == 0) {
- V->convertInitializerTo(new BitsRecTy(BitList.size()));
- return Error(Loc, "Initializer is not compatible with bit range");
- }
-
- // We should have a BitsInit type now.
- BitsInit *BInit = dynamic_cast<BitsInit*>(BI);
- assert(BInit != 0);
-
- BitsInit *NewVal = new BitsInit(CurVal->getNumBits());
-
- // Loop over bits, assigning values as appropriate.
- for (unsigned i = 0, e = BitList.size(); i != e; ++i) {
- unsigned Bit = BitList[i];
- if (NewVal->getBit(Bit))
- return Error(Loc, "Cannot set bit #" + utostr(Bit) + " of value '" +
- ValName + "' more than once");
- NewVal->setBit(Bit, BInit->getBit(i));
- }
-
- for (unsigned i = 0, e = CurVal->getNumBits(); i != e; ++i)
- if (NewVal->getBit(i) == 0)
- NewVal->setBit(i, CurVal->getBit(i));
-
- V = NewVal;
- }
-
- if (RV->setValue(V))
- return Error(Loc, "Value '" + ValName + "' of type '" +
- RV->getType()->getAsString() +
- "' is incompatible with initializer '" + V->getAsString() +"'");
- return false;
-}
-
-/// AddSubClass - Add SubClass as a subclass to CurRec, resolving its template
-/// args as SubClass's template arguments.
-bool TGParser::AddSubClass(Record *CurRec, SubClassReference &SubClass) {
- Record *SC = SubClass.Rec;
- // Add all of the values in the subclass into the current class.
- const std::vector<RecordVal> &Vals = SC->getValues();
- for (unsigned i = 0, e = Vals.size(); i != e; ++i)
- if (AddValue(CurRec, SubClass.RefLoc, Vals[i]))
- return true;
-
- const std::vector<std::string> &TArgs = SC->getTemplateArgs();
-
- // Ensure that an appropriate number of template arguments are specified.
- if (TArgs.size() < SubClass.TemplateArgs.size())
- return Error(SubClass.RefLoc, "More template args specified than expected");
-
- // Loop over all of the template arguments, setting them to the specified
- // value or leaving them as the default if necessary.
- for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {
- if (i < SubClass.TemplateArgs.size()) {
- // If a value is specified for this template arg, set it now.
- if (SetValue(CurRec, SubClass.RefLoc, TArgs[i], std::vector<unsigned>(),
- SubClass.TemplateArgs[i]))
- return true;
-
- // Resolve it next.
- CurRec->resolveReferencesTo(CurRec->getValue(TArgs[i]));
-
- // Now remove it.
- CurRec->removeValue(TArgs[i]);
-
- } else if (!CurRec->getValue(TArgs[i])->getValue()->isComplete()) {
- return Error(SubClass.RefLoc,"Value not specified for template argument #"
- + utostr(i) + " (" + TArgs[i] + ") of subclass '" +
- SC->getName() + "'!");
- }
- }
-
- // Since everything went well, we can now set the "superclass" list for the
- // current record.
- const std::vector<Record*> &SCs = SC->getSuperClasses();
- for (unsigned i = 0, e = SCs.size(); i != e; ++i) {
- if (CurRec->isSubClassOf(SCs[i]))
- return Error(SubClass.RefLoc,
- "Already subclass of '" + SCs[i]->getName() + "'!\n");
- CurRec->addSuperClass(SCs[i]);
- }
-
- if (CurRec->isSubClassOf(SC))
- return Error(SubClass.RefLoc,
- "Already subclass of '" + SC->getName() + "'!\n");
- CurRec->addSuperClass(SC);
- return false;
-}
-
-/// AddSubMultiClass - Add SubMultiClass as a subclass to
-/// CurMC, resolving its template args as SubMultiClass's
-/// template arguments.
-bool TGParser::AddSubMultiClass(MultiClass *CurMC,
- SubMultiClassReference &SubMultiClass) {
- MultiClass *SMC = SubMultiClass.MC;
- Record *CurRec = &CurMC->Rec;
-
- const std::vector<RecordVal> &MCVals = CurRec->getValues();
-
- // Add all of the values in the subclass into the current class.
- const std::vector<RecordVal> &SMCVals = SMC->Rec.getValues();
- for (unsigned i = 0, e = SMCVals.size(); i != e; ++i)
- if (AddValue(CurRec, SubMultiClass.RefLoc, SMCVals[i]))
- return true;
-
- int newDefStart = CurMC->DefPrototypes.size();
-
- // Add all of the defs in the subclass into the current multiclass.
- for (MultiClass::RecordVector::const_iterator i = SMC->DefPrototypes.begin(),
- iend = SMC->DefPrototypes.end();
- i != iend;
- ++i) {
- // Clone the def and add it to the current multiclass
- Record *NewDef = new Record(**i);
-
- // Add all of the values in the superclass into the current def.
- for (unsigned i = 0, e = MCVals.size(); i != e; ++i)
- if (AddValue(NewDef, SubMultiClass.RefLoc, MCVals[i]))
- return true;
-
- CurMC->DefPrototypes.push_back(NewDef);
- }
-
- const std::vector<std::string> &SMCTArgs = SMC->Rec.getTemplateArgs();
-
- // Ensure that an appropriate number of template arguments are
- // specified.
- if (SMCTArgs.size() < SubMultiClass.TemplateArgs.size())
- return Error(SubMultiClass.RefLoc,
- "More template args specified than expected");
-
- // Loop over all of the template arguments, setting them to the specified
- // value or leaving them as the default if necessary.
- for (unsigned i = 0, e = SMCTArgs.size(); i != e; ++i) {
- if (i < SubMultiClass.TemplateArgs.size()) {
- // If a value is specified for this template arg, set it in the
- // superclass now.
- if (SetValue(CurRec, SubMultiClass.RefLoc, SMCTArgs[i],
- std::vector<unsigned>(),
- SubMultiClass.TemplateArgs[i]))
- return true;
-
- // Resolve it next.
- CurRec->resolveReferencesTo(CurRec->getValue(SMCTArgs[i]));
-
- // Now remove it.
- CurRec->removeValue(SMCTArgs[i]);
-
- // If a value is specified for this template arg, set it in the
- // new defs now.
- for (MultiClass::RecordVector::iterator j =
- CurMC->DefPrototypes.begin() + newDefStart,
- jend = CurMC->DefPrototypes.end();
- j != jend;
- ++j) {
- Record *Def = *j;
-
- if (SetValue(Def, SubMultiClass.RefLoc, SMCTArgs[i],
- std::vector<unsigned>(),
- SubMultiClass.TemplateArgs[i]))
- return true;
-
- // Resolve it next.
- Def->resolveReferencesTo(Def->getValue(SMCTArgs[i]));
-
- // Now remove it
- Def->removeValue(SMCTArgs[i]);
- }
- } else if (!CurRec->getValue(SMCTArgs[i])->getValue()->isComplete()) {
- return Error(SubMultiClass.RefLoc,
- "Value not specified for template argument #"
- + utostr(i) + " (" + SMCTArgs[i] + ") of subclass '" +
- SMC->Rec.getName() + "'!");
- }
- }
-
- return false;
-}
-
-//===----------------------------------------------------------------------===//
-// Parser Code
-//===----------------------------------------------------------------------===//
-
-/// isObjectStart - Return true if this is a valid first token for an Object.
-static bool isObjectStart(tgtok::TokKind K) {
- return K == tgtok::Class || K == tgtok::Def ||
- K == tgtok::Defm || K == tgtok::Let || K == tgtok::MultiClass;
-}
-
-static std::string GetNewAnonymousName() {
- static unsigned AnonCounter = 0;
- return "anonymous."+utostr(AnonCounter++);
-}
-
-/// ParseObjectName - If an object name is specified, return it. Otherwise,
-/// return an anonymous name.
-/// ObjectName ::= ID
-/// ObjectName ::= /*empty*/
-///
-std::string TGParser::ParseObjectName() {
- if (Lex.getCode() != tgtok::Id)
- return GetNewAnonymousName();
-
- std::string Ret = Lex.getCurStrVal();
- Lex.Lex();
- return Ret;
-}
-
-
-/// ParseClassID - Parse and resolve a reference to a class name. This returns
-/// null on error.
-///
-/// ClassID ::= ID
-///
-Record *TGParser::ParseClassID() {
- if (Lex.getCode() != tgtok::Id) {
- TokError("expected name for ClassID");
- return 0;
- }
-
- Record *Result = Records.getClass(Lex.getCurStrVal());
- if (Result == 0)
- TokError("Couldn't find class '" + Lex.getCurStrVal() + "'");
-
- Lex.Lex();
- return Result;
-}
-
-/// ParseMultiClassID - Parse and resolve a reference to a multiclass name.
-/// This returns null on error.
-///
-/// MultiClassID ::= ID
-///
-MultiClass *TGParser::ParseMultiClassID() {
- if (Lex.getCode() != tgtok::Id) {
- TokError("expected name for ClassID");
- return 0;
- }
-
- MultiClass *Result = MultiClasses[Lex.getCurStrVal()];
- if (Result == 0)
- TokError("Couldn't find class '" + Lex.getCurStrVal() + "'");
-
- Lex.Lex();
- return Result;
-}
-
-Record *TGParser::ParseDefmID() {
- if (Lex.getCode() != tgtok::Id) {
- TokError("expected multiclass name");
- return 0;
- }
-
- MultiClass *MC = MultiClasses[Lex.getCurStrVal()];
- if (MC == 0) {
- TokError("Couldn't find multiclass '" + Lex.getCurStrVal() + "'");
- return 0;
- }
-
- Lex.Lex();
- return &MC->Rec;
-}
-
-
-/// ParseSubClassReference - Parse a reference to a subclass or to a templated
-/// subclass. This returns a SubClassRefTy with a null Record* on error.
-///
-/// SubClassRef ::= ClassID
-/// SubClassRef ::= ClassID '<' ValueList '>'
-///
-SubClassReference TGParser::
-ParseSubClassReference(Record *CurRec, bool isDefm) {
- SubClassReference Result;
- Result.RefLoc = Lex.getLoc();
-
- if (isDefm)
- Result.Rec = ParseDefmID();
- else
- Result.Rec = ParseClassID();
- if (Result.Rec == 0) return Result;
-
- // If there is no template arg list, we're done.
- if (Lex.getCode() != tgtok::less)
- return Result;
- Lex.Lex(); // Eat the '<'
-
- if (Lex.getCode() == tgtok::greater) {
- TokError("subclass reference requires a non-empty list of template values");
- Result.Rec = 0;
- return Result;
- }
-
- Result.TemplateArgs = ParseValueList(CurRec, Result.Rec);
- if (Result.TemplateArgs.empty()) {
- Result.Rec = 0; // Error parsing value list.
- return Result;
- }
-
- if (Lex.getCode() != tgtok::greater) {
- TokError("expected '>' in template value list");
- Result.Rec = 0;
- return Result;
- }
- Lex.Lex();
-
- return Result;
-}
-
-/// ParseSubMultiClassReference - Parse a reference to a subclass or to a
-/// templated submulticlass. This returns a SubMultiClassRefTy with a null
-/// Record* on error.
-///
-/// SubMultiClassRef ::= MultiClassID
-/// SubMultiClassRef ::= MultiClassID '<' ValueList '>'
-///
-SubMultiClassReference TGParser::
-ParseSubMultiClassReference(MultiClass *CurMC) {
- SubMultiClassReference Result;
- Result.RefLoc = Lex.getLoc();
-
- Result.MC = ParseMultiClassID();
- if (Result.MC == 0) return Result;
-
- // If there is no template arg list, we're done.
- if (Lex.getCode() != tgtok::less)
- return Result;
- Lex.Lex(); // Eat the '<'
-
- if (Lex.getCode() == tgtok::greater) {
- TokError("subclass reference requires a non-empty list of template values");
- Result.MC = 0;
- return Result;
- }
-
- Result.TemplateArgs = ParseValueList(&CurMC->Rec, &Result.MC->Rec);
- if (Result.TemplateArgs.empty()) {
- Result.MC = 0; // Error parsing value list.
- return Result;
- }
-
- if (Lex.getCode() != tgtok::greater) {
- TokError("expected '>' in template value list");
- Result.MC = 0;
- return Result;
- }
- Lex.Lex();
-
- return Result;
-}
-
-/// ParseRangePiece - Parse a bit/value range.
-/// RangePiece ::= INTVAL
-/// RangePiece ::= INTVAL '-' INTVAL
-/// RangePiece ::= INTVAL INTVAL
-bool TGParser::ParseRangePiece(std::vector<unsigned> &Ranges) {
- if (Lex.getCode() != tgtok::IntVal) {
- TokError("expected integer or bitrange");
- return true;
- }
- int64_t Start = Lex.getCurIntVal();
- int64_t End;
-
- if (Start < 0)
- return TokError("invalid range, cannot be negative");
-
- switch (Lex.Lex()) { // eat first character.
- default:
- Ranges.push_back(Start);
- return false;
- case tgtok::minus:
- if (Lex.Lex() != tgtok::IntVal) {
- TokError("expected integer value as end of range");
- return true;
- }
- End = Lex.getCurIntVal();
- break;
- case tgtok::IntVal:
- End = -Lex.getCurIntVal();
- break;
- }
- if (End < 0)
- return TokError("invalid range, cannot be negative");
- Lex.Lex();
-
- // Add to the range.
- if (Start < End) {
- for (; Start <= End; ++Start)
- Ranges.push_back(Start);
- } else {
- for (; Start >= End; --Start)
- Ranges.push_back(Start);
- }
- return false;
-}
-
-/// ParseRangeList - Parse a list of scalars and ranges into scalar values.
-///
-/// RangeList ::= RangePiece (',' RangePiece)*
-///
-std::vector<unsigned> TGParser::ParseRangeList() {
- std::vector<unsigned> Result;
-
- // Parse the first piece.
- if (ParseRangePiece(Result))
- return std::vector<unsigned>();
- while (Lex.getCode() == tgtok::comma) {
- Lex.Lex(); // Eat the comma.
-
- // Parse the next range piece.
- if (ParseRangePiece(Result))
- return std::vector<unsigned>();
- }
- return Result;
-}
-
-/// ParseOptionalRangeList - Parse either a range list in <>'s or nothing.
-/// OptionalRangeList ::= '<' RangeList '>'
-/// OptionalRangeList ::= /*empty*/
-bool TGParser::ParseOptionalRangeList(std::vector<unsigned> &Ranges) {
- if (Lex.getCode() != tgtok::less)
- return false;
-
- SMLoc StartLoc = Lex.getLoc();
- Lex.Lex(); // eat the '<'
-
- // Parse the range list.
- Ranges = ParseRangeList();
- if (Ranges.empty()) return true;
-
- if (Lex.getCode() != tgtok::greater) {
- TokError("expected '>' at end of range list");
- return Error(StartLoc, "to match this '<'");
- }
- Lex.Lex(); // eat the '>'.
- return false;
-}
-
-/// ParseOptionalBitList - Parse either a bit list in {}'s or nothing.
-/// OptionalBitList ::= '{' RangeList '}'
-/// OptionalBitList ::= /*empty*/
-bool TGParser::ParseOptionalBitList(std::vector<unsigned> &Ranges) {
- if (Lex.getCode() != tgtok::l_brace)
- return false;
-
- SMLoc StartLoc = Lex.getLoc();
- Lex.Lex(); // eat the '{'
-
- // Parse the range list.
- Ranges = ParseRangeList();
- if (Ranges.empty()) return true;
-
- if (Lex.getCode() != tgtok::r_brace) {
- TokError("expected '}' at end of bit list");
- return Error(StartLoc, "to match this '{'");
- }
- Lex.Lex(); // eat the '}'.
- return false;
-}
-
-
-/// ParseType - Parse and return a tblgen type. This returns null on error.
-///
-/// Type ::= STRING // string type
-/// Type ::= BIT // bit type
-/// Type ::= BITS '<' INTVAL '>' // bits<x> type
-/// Type ::= INT // int type
-/// Type ::= LIST '<' Type '>' // list<x> type
-/// Type ::= CODE // code type
-/// Type ::= DAG // dag type
-/// Type ::= ClassID // Record Type
-///
-RecTy *TGParser::ParseType() {
- switch (Lex.getCode()) {
- default: TokError("Unknown token when expecting a type"); return 0;
- case tgtok::String: Lex.Lex(); return new StringRecTy();
- case tgtok::Bit: Lex.Lex(); return new BitRecTy();
- case tgtok::Int: Lex.Lex(); return new IntRecTy();
- case tgtok::Code: Lex.Lex(); return new CodeRecTy();
- case tgtok::Dag: Lex.Lex(); return new DagRecTy();
- case tgtok::Id:
- if (Record *R = ParseClassID()) return new RecordRecTy(R);
- return 0;
- case tgtok::Bits: {
- if (Lex.Lex() != tgtok::less) { // Eat 'bits'
- TokError("expected '<' after bits type");
- return 0;
- }
- if (Lex.Lex() != tgtok::IntVal) { // Eat '<'
- TokError("expected integer in bits<n> type");
- return 0;
- }
- uint64_t Val = Lex.getCurIntVal();
- if (Lex.Lex() != tgtok::greater) { // Eat count.
- TokError("expected '>' at end of bits<n> type");
- return 0;
- }
- Lex.Lex(); // Eat '>'
- return new BitsRecTy(Val);
- }
- case tgtok::List: {
- if (Lex.Lex() != tgtok::less) { // Eat 'bits'
- TokError("expected '<' after list type");
- return 0;
- }
- Lex.Lex(); // Eat '<'
- RecTy *SubType = ParseType();
- if (SubType == 0) return 0;
-
- if (Lex.getCode() != tgtok::greater) {
- TokError("expected '>' at end of list<ty> type");
- return 0;
- }
- Lex.Lex(); // Eat '>'
- return new ListRecTy(SubType);
- }
- }
-}
-
-/// ParseIDValue - Parse an ID as a value and decode what it means.
-///
-/// IDValue ::= ID [def local value]
-/// IDValue ::= ID [def template arg]
-/// IDValue ::= ID [multiclass local value]
-/// IDValue ::= ID [multiclass template argument]
-/// IDValue ::= ID [def name]
-///
-Init *TGParser::ParseIDValue(Record *CurRec) {
- assert(Lex.getCode() == tgtok::Id && "Expected ID in ParseIDValue");
- std::string Name = Lex.getCurStrVal();
- SMLoc Loc = Lex.getLoc();
- Lex.Lex();
- return ParseIDValue(CurRec, Name, Loc);
-}
-
-/// ParseIDValue - This is just like ParseIDValue above, but it assumes the ID
-/// has already been read.
-Init *TGParser::ParseIDValue(Record *CurRec,
- const std::string &Name, SMLoc NameLoc) {
- if (CurRec) {
- if (const RecordVal *RV = CurRec->getValue(Name))
- return new VarInit(Name, RV->getType());
-
- std::string TemplateArgName = CurRec->getName()+":"+Name;
- if (CurRec->isTemplateArg(TemplateArgName)) {
- const RecordVal *RV = CurRec->getValue(TemplateArgName);
- assert(RV && "Template arg doesn't exist??");
- return new VarInit(TemplateArgName, RV->getType());
- }
- }
-
- if (CurMultiClass) {
- std::string MCName = CurMultiClass->Rec.getName()+"::"+Name;
- if (CurMultiClass->Rec.isTemplateArg(MCName)) {
- const RecordVal *RV = CurMultiClass->Rec.getValue(MCName);
- assert(RV && "Template arg doesn't exist??");
- return new VarInit(MCName, RV->getType());
- }
- }
-
- if (Record *D = Records.getDef(Name))
- return new DefInit(D);
-
- Error(NameLoc, "Variable not defined: '" + Name + "'");
- return 0;
-}
-
-/// ParseOperation - Parse an operator. This returns null on error.
-///
-/// Operation ::= XOperator ['<' Type '>'] '(' Args ')'
-///
-Init *TGParser::ParseOperation(Record *CurRec) {
- switch (Lex.getCode()) {
- default:
- TokError("unknown operation");
- return 0;
- break;
- case tgtok::XHead:
- case tgtok::XTail:
- case tgtok::XEmpty:
- case tgtok::XCast: { // Value ::= !unop '(' Value ')'
- UnOpInit::UnaryOp Code;
- RecTy *Type = 0;
-
- switch (Lex.getCode()) {
- default: assert(0 && "Unhandled code!");
- case tgtok::XCast:
- Lex.Lex(); // eat the operation
- Code = UnOpInit::CAST;
-
- Type = ParseOperatorType();
-
- if (Type == 0) {
- TokError("did not get type for unary operator");
- return 0;
- }
-
- break;
- case tgtok::XHead:
- Lex.Lex(); // eat the operation
- Code = UnOpInit::HEAD;
- break;
- case tgtok::XTail:
- Lex.Lex(); // eat the operation
- Code = UnOpInit::TAIL;
- break;
- case tgtok::XEmpty:
- Lex.Lex(); // eat the operation
- Code = UnOpInit::EMPTY;
- Type = new IntRecTy;
- break;
- }
- if (Lex.getCode() != tgtok::l_paren) {
- TokError("expected '(' after unary operator");
- return 0;
- }
- Lex.Lex(); // eat the '('
-
- Init *LHS = ParseValue(CurRec);
- if (LHS == 0) return 0;
-
- if (Code == UnOpInit::HEAD
- || Code == UnOpInit::TAIL
- || Code == UnOpInit::EMPTY) {
- ListInit *LHSl = dynamic_cast<ListInit*>(LHS);
- StringInit *LHSs = dynamic_cast<StringInit*>(LHS);
- TypedInit *LHSt = dynamic_cast<TypedInit*>(LHS);
- if (LHSl == 0 && LHSs == 0 && LHSt == 0) {
- TokError("expected list or string type argument in unary operator");
- return 0;
- }
- if (LHSt) {
- ListRecTy *LType = dynamic_cast<ListRecTy*>(LHSt->getType());
- StringRecTy *SType = dynamic_cast<StringRecTy*>(LHSt->getType());
- if (LType == 0 && SType == 0) {
- TokError("expected list or string type argumnet in unary operator");
- return 0;
- }
- }
-
- if (Code == UnOpInit::HEAD
- || Code == UnOpInit::TAIL) {
- if (LHSl == 0 && LHSt == 0) {
- TokError("expected list type argumnet in unary operator");
- return 0;
- }
-
- if (LHSl && LHSl->getSize() == 0) {
- TokError("empty list argument in unary operator");
- return 0;
- }
- if (LHSl) {
- Init *Item = LHSl->getElement(0);
- TypedInit *Itemt = dynamic_cast<TypedInit*>(Item);
- if (Itemt == 0) {
- TokError("untyped list element in unary operator");
- return 0;
- }
- if (Code == UnOpInit::HEAD) {
- Type = Itemt->getType();
- } else {
- Type = new ListRecTy(Itemt->getType());
- }
- } else {
- assert(LHSt && "expected list type argument in unary operator");
- ListRecTy *LType = dynamic_cast<ListRecTy*>(LHSt->getType());
- if (LType == 0) {
- TokError("expected list type argumnet in unary operator");
- return 0;
- }
- if (Code == UnOpInit::HEAD) {
- Type = LType->getElementType();
- } else {
- Type = LType;
- }
- }
- }
- }
-
- if (Lex.getCode() != tgtok::r_paren) {
- TokError("expected ')' in unary operator");
- return 0;
- }
- Lex.Lex(); // eat the ')'
- return (new UnOpInit(Code, LHS, Type))->Fold(CurRec, CurMultiClass);
- }
-
- case tgtok::XConcat:
- case tgtok::XSRA:
- case tgtok::XSRL:
- case tgtok::XSHL:
- case tgtok::XEq:
- case tgtok::XStrConcat: { // Value ::= !binop '(' Value ',' Value ')'
- tgtok::TokKind OpTok = Lex.getCode();
- SMLoc OpLoc = Lex.getLoc();
- Lex.Lex(); // eat the operation
-
- BinOpInit::BinaryOp Code;
- RecTy *Type = 0;
-
- switch (OpTok) {
- default: assert(0 && "Unhandled code!");
- case tgtok::XConcat: Code = BinOpInit::CONCAT; Type = new DagRecTy(); break;
- case tgtok::XSRA: Code = BinOpInit::SRA; Type = new IntRecTy(); break;
- case tgtok::XSRL: Code = BinOpInit::SRL; Type = new IntRecTy(); break;
- case tgtok::XSHL: Code = BinOpInit::SHL; Type = new IntRecTy(); break;
- case tgtok::XEq: Code = BinOpInit::EQ; Type = new BitRecTy(); break;
- case tgtok::XStrConcat:
- Code = BinOpInit::STRCONCAT;
- Type = new StringRecTy();
- break;
- }
-
- if (Lex.getCode() != tgtok::l_paren) {
- TokError("expected '(' after binary operator");
- return 0;
- }
- Lex.Lex(); // eat the '('
-
- SmallVector<Init*, 2> InitList;
-
- InitList.push_back(ParseValue(CurRec));
- if (InitList.back() == 0) return 0;
-
- while (Lex.getCode() == tgtok::comma) {
- Lex.Lex(); // eat the ','
-
- InitList.push_back(ParseValue(CurRec));
- if (InitList.back() == 0) return 0;
- }
-
- if (Lex.getCode() != tgtok::r_paren) {
- TokError("expected ')' in operator");
- return 0;
- }
- Lex.Lex(); // eat the ')'
-
- // We allow multiple operands to associative operators like !strconcat as
- // shorthand for nesting them.
- if (Code == BinOpInit::STRCONCAT) {
- while (InitList.size() > 2) {
- Init *RHS = InitList.pop_back_val();
- RHS = (new BinOpInit(Code, InitList.back(), RHS, Type))
- ->Fold(CurRec, CurMultiClass);
- InitList.back() = RHS;
- }
- }
-
- if (InitList.size() == 2)
- return (new BinOpInit(Code, InitList[0], InitList[1], Type))
- ->Fold(CurRec, CurMultiClass);
-
- Error(OpLoc, "expected two operands to operator");
- return 0;
- }
-
- case tgtok::XIf:
- case tgtok::XForEach:
- case tgtok::XSubst: { // Value ::= !ternop '(' Value ',' Value ',' Value ')'
- TernOpInit::TernaryOp Code;
- RecTy *Type = 0;
-
- tgtok::TokKind LexCode = Lex.getCode();
- Lex.Lex(); // eat the operation
- switch (LexCode) {
- default: assert(0 && "Unhandled code!");
- case tgtok::XIf:
- Code = TernOpInit::IF;
- break;
- case tgtok::XForEach:
- Code = TernOpInit::FOREACH;
- break;
- case tgtok::XSubst:
- Code = TernOpInit::SUBST;
- break;
- }
- if (Lex.getCode() != tgtok::l_paren) {
- TokError("expected '(' after ternary operator");
- return 0;
- }
- Lex.Lex(); // eat the '('
-
- Init *LHS = ParseValue(CurRec);
- if (LHS == 0) return 0;
-
- if (Lex.getCode() != tgtok::comma) {
- TokError("expected ',' in ternary operator");
- return 0;
- }
- Lex.Lex(); // eat the ','
-
- Init *MHS = ParseValue(CurRec);
- if (MHS == 0) return 0;
-
- if (Lex.getCode() != tgtok::comma) {
- TokError("expected ',' in ternary operator");
- return 0;
- }
- Lex.Lex(); // eat the ','
-
- Init *RHS = ParseValue(CurRec);
- if (RHS == 0) return 0;
-
- if (Lex.getCode() != tgtok::r_paren) {
- TokError("expected ')' in binary operator");
- return 0;
- }
- Lex.Lex(); // eat the ')'
-
- switch (LexCode) {
- default: assert(0 && "Unhandled code!");
- case tgtok::XIf: {
- // FIXME: The `!if' operator doesn't handle non-TypedInit well at
- // all. This can be made much more robust.
- TypedInit *MHSt = dynamic_cast<TypedInit*>(MHS);
- TypedInit *RHSt = dynamic_cast<TypedInit*>(RHS);
-
- RecTy *MHSTy = 0;
- RecTy *RHSTy = 0;
-
- if (MHSt == 0 && RHSt == 0) {
- BitsInit *MHSbits = dynamic_cast<BitsInit*>(MHS);
- BitsInit *RHSbits = dynamic_cast<BitsInit*>(RHS);
-
- if (MHSbits && RHSbits &&
- MHSbits->getNumBits() == RHSbits->getNumBits()) {
- Type = new BitRecTy();
- break;
- } else {
- BitInit *MHSbit = dynamic_cast<BitInit*>(MHS);
- BitInit *RHSbit = dynamic_cast<BitInit*>(RHS);
-
- if (MHSbit && RHSbit) {
- Type = new BitRecTy();
- break;
- }
- }
- } else if (MHSt != 0 && RHSt != 0) {
- MHSTy = MHSt->getType();
- RHSTy = RHSt->getType();
- }
-
- if (!MHSTy || !RHSTy) {
- TokError("could not get type for !if");
- return 0;
- }
-
- if (MHSTy->typeIsConvertibleTo(RHSTy)) {
- Type = RHSTy;
- } else if (RHSTy->typeIsConvertibleTo(MHSTy)) {
- Type = MHSTy;
- } else {
- TokError("inconsistent types for !if");
- return 0;
- }
- break;
- }
- case tgtok::XForEach: {
- TypedInit *MHSt = dynamic_cast<TypedInit *>(MHS);
- if (MHSt == 0) {
- TokError("could not get type for !foreach");
- return 0;
- }
- Type = MHSt->getType();
- break;
- }
- case tgtok::XSubst: {
- TypedInit *RHSt = dynamic_cast<TypedInit *>(RHS);
- if (RHSt == 0) {
- TokError("could not get type for !subst");
- return 0;
- }
- Type = RHSt->getType();
- break;
- }
- }
- return (new TernOpInit(Code, LHS, MHS, RHS, Type))->Fold(CurRec,
- CurMultiClass);
- }
- }
- TokError("could not parse operation");
- return 0;
-}
-
-/// ParseOperatorType - Parse a type for an operator. This returns
-/// null on error.
-///
-/// OperatorType ::= '<' Type '>'
-///
-RecTy *TGParser::ParseOperatorType() {
- RecTy *Type = 0;
-
- if (Lex.getCode() != tgtok::less) {
- TokError("expected type name for operator");
- return 0;
- }
- Lex.Lex(); // eat the <
-
- Type = ParseType();
-
- if (Type == 0) {
- TokError("expected type name for operator");
- return 0;
- }
-
- if (Lex.getCode() != tgtok::greater) {
- TokError("expected type name for operator");
- return 0;
- }
- Lex.Lex(); // eat the >
-
- return Type;
-}
-
-
-/// ParseSimpleValue - Parse a tblgen value. This returns null on error.
-///
-/// SimpleValue ::= IDValue
-/// SimpleValue ::= INTVAL
-/// SimpleValue ::= STRVAL+
-/// SimpleValue ::= CODEFRAGMENT
-/// SimpleValue ::= '?'
-/// SimpleValue ::= '{' ValueList '}'
-/// SimpleValue ::= ID '<' ValueListNE '>'
-/// SimpleValue ::= '[' ValueList ']'
-/// SimpleValue ::= '(' IDValue DagArgList ')'
-/// SimpleValue ::= CONCATTOK '(' Value ',' Value ')'
-/// SimpleValue ::= SHLTOK '(' Value ',' Value ')'
-/// SimpleValue ::= SRATOK '(' Value ',' Value ')'
-/// SimpleValue ::= SRLTOK '(' Value ',' Value ')'
-/// SimpleValue ::= STRCONCATTOK '(' Value ',' Value ')'
-///
-Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType) {
- Init *R = 0;
- switch (Lex.getCode()) {
- default: TokError("Unknown token when parsing a value"); break;
- case tgtok::IntVal: R = new IntInit(Lex.getCurIntVal()); Lex.Lex(); break;
- case tgtok::StrVal: {
- std::string Val = Lex.getCurStrVal();
- Lex.Lex();
-
- // Handle multiple consecutive concatenated strings.
- while (Lex.getCode() == tgtok::StrVal) {
- Val += Lex.getCurStrVal();
- Lex.Lex();
- }
-
- R = new StringInit(Val);
- break;
- }
- case tgtok::CodeFragment:
- R = new CodeInit(Lex.getCurStrVal());
- Lex.Lex();
- break;
- case tgtok::question:
- R = new UnsetInit();
- Lex.Lex();
- break;
- case tgtok::Id: {
- SMLoc NameLoc = Lex.getLoc();
- std::string Name = Lex.getCurStrVal();
- if (Lex.Lex() != tgtok::less) // consume the Id.
- return ParseIDValue(CurRec, Name, NameLoc); // Value ::= IDValue
-
- // Value ::= ID '<' ValueListNE '>'
- if (Lex.Lex() == tgtok::greater) {
- TokError("expected non-empty value list");
- return 0;
- }
-
- // This is a CLASS<initvalslist> expression. This is supposed to synthesize
- // a new anonymous definition, deriving from CLASS<initvalslist> with no
- // body.
- Record *Class = Records.getClass(Name);
- if (!Class) {
- Error(NameLoc, "Expected a class name, got '" + Name + "'");
- return 0;
- }
-
- std::vector<Init*> ValueList = ParseValueList(CurRec, Class);
- if (ValueList.empty()) return 0;
-
- if (Lex.getCode() != tgtok::greater) {
- TokError("expected '>' at end of value list");
- return 0;
- }
- Lex.Lex(); // eat the '>'
-
- // Create the new record, set it as CurRec temporarily.
- static unsigned AnonCounter = 0;
- Record *NewRec = new Record("anonymous.val."+utostr(AnonCounter++),
- NameLoc,
- Records);
- SubClassReference SCRef;
- SCRef.RefLoc = NameLoc;
- SCRef.Rec = Class;
- SCRef.TemplateArgs = ValueList;
- // Add info about the subclass to NewRec.
- if (AddSubClass(NewRec, SCRef))
- return 0;
- NewRec->resolveReferences();
- Records.addDef(NewRec);
-
- // The result of the expression is a reference to the new record.
- return new DefInit(NewRec);
- }
- case tgtok::l_brace: { // Value ::= '{' ValueList '}'
- SMLoc BraceLoc = Lex.getLoc();
- Lex.Lex(); // eat the '{'
- std::vector<Init*> Vals;
-
- if (Lex.getCode() != tgtok::r_brace) {
- Vals = ParseValueList(CurRec);
- if (Vals.empty()) return 0;
- }
- if (Lex.getCode() != tgtok::r_brace) {
- TokError("expected '}' at end of bit list value");
- return 0;
- }
- Lex.Lex(); // eat the '}'
-
- BitsInit *Result = new BitsInit(Vals.size());
- for (unsigned i = 0, e = Vals.size(); i != e; ++i) {
- Init *Bit = Vals[i]->convertInitializerTo(new BitRecTy());
- if (Bit == 0) {
- Error(BraceLoc, "Element #" + utostr(i) + " (" + Vals[i]->getAsString()+
- ") is not convertable to a bit");
- return 0;
- }
- Result->setBit(Vals.size()-i-1, Bit);
- }
- return Result;
- }
- case tgtok::l_square: { // Value ::= '[' ValueList ']'
- Lex.Lex(); // eat the '['
- std::vector<Init*> Vals;
-
- RecTy *DeducedEltTy = 0;
- ListRecTy *GivenListTy = 0;
-
- if (ItemType != 0) {
- ListRecTy *ListType = dynamic_cast<ListRecTy*>(ItemType);
- if (ListType == 0) {
- std::stringstream s;
- s << "Type mismatch for list, expected list type, got "
- << ItemType->getAsString();
- TokError(s.str());
- return 0;
- }
- GivenListTy = ListType;
- }
-
- if (Lex.getCode() != tgtok::r_square) {
- Vals = ParseValueList(CurRec, 0,
- GivenListTy ? GivenListTy->getElementType() : 0);
- if (Vals.empty()) return 0;
- }
- if (Lex.getCode() != tgtok::r_square) {
- TokError("expected ']' at end of list value");
- return 0;
- }
- Lex.Lex(); // eat the ']'
-
- RecTy *GivenEltTy = 0;
- if (Lex.getCode() == tgtok::less) {
- // Optional list element type
- Lex.Lex(); // eat the '<'
-
- GivenEltTy = ParseType();
- if (GivenEltTy == 0) {
- // Couldn't parse element type
- return 0;
- }
-
- if (Lex.getCode() != tgtok::greater) {
- TokError("expected '>' at end of list element type");
- return 0;
- }
- Lex.Lex(); // eat the '>'
- }
-
- // Check elements
- RecTy *EltTy = 0;
- for (std::vector<Init *>::iterator i = Vals.begin(), ie = Vals.end();
- i != ie;
- ++i) {
- TypedInit *TArg = dynamic_cast<TypedInit*>(*i);
- if (TArg == 0) {
- TokError("Untyped list element");
- return 0;
- }
- if (EltTy != 0) {
- EltTy = resolveTypes(EltTy, TArg->getType());
- if (EltTy == 0) {
- TokError("Incompatible types in list elements");
- return 0;
- }
- } else {
- EltTy = TArg->getType();
- }
- }
-
- if (GivenEltTy != 0) {
- if (EltTy != 0) {
- // Verify consistency
- if (!EltTy->typeIsConvertibleTo(GivenEltTy)) {
- TokError("Incompatible types in list elements");
- return 0;
- }
- }
- EltTy = GivenEltTy;
- }
-
- if (EltTy == 0) {
- if (ItemType == 0) {
- TokError("No type for list");
- return 0;
- }
- DeducedEltTy = GivenListTy->getElementType();
- } else {
- // Make sure the deduced type is compatible with the given type
- if (GivenListTy) {
- if (!EltTy->typeIsConvertibleTo(GivenListTy->getElementType())) {
- TokError("Element type mismatch for list");
- return 0;
- }
- }
- DeducedEltTy = EltTy;
- }
-
- return new ListInit(Vals, DeducedEltTy);
- }
- case tgtok::l_paren: { // Value ::= '(' IDValue DagArgList ')'
- Lex.Lex(); // eat the '('
- if (Lex.getCode() != tgtok::Id && Lex.getCode() != tgtok::XCast) {
- TokError("expected identifier in dag init");
- return 0;
- }
-
- Init *Operator = ParseValue(CurRec);
- if (Operator == 0) return 0;
-
- // If the operator name is present, parse it.
- std::string OperatorName;
- if (Lex.getCode() == tgtok::colon) {
- if (Lex.Lex() != tgtok::VarName) { // eat the ':'
- TokError("expected variable name in dag operator");
- return 0;
- }
- OperatorName = Lex.getCurStrVal();
- Lex.Lex(); // eat the VarName.
- }
-
- std::vector<std::pair<llvm::Init*, std::string> > DagArgs;
- if (Lex.getCode() != tgtok::r_paren) {
- DagArgs = ParseDagArgList(CurRec);
- if (DagArgs.empty()) return 0;
- }
-
- if (Lex.getCode() != tgtok::r_paren) {
- TokError("expected ')' in dag init");
- return 0;
- }
- Lex.Lex(); // eat the ')'
-
- return new DagInit(Operator, OperatorName, DagArgs);
- }
-
- case tgtok::XHead:
- case tgtok::XTail:
- case tgtok::XEmpty:
- case tgtok::XCast: // Value ::= !unop '(' Value ')'
- case tgtok::XConcat:
- case tgtok::XSRA:
- case tgtok::XSRL:
- case tgtok::XSHL:
- case tgtok::XEq:
- case tgtok::XStrConcat: // Value ::= !binop '(' Value ',' Value ')'
- case tgtok::XIf:
- case tgtok::XForEach:
- case tgtok::XSubst: { // Value ::= !ternop '(' Value ',' Value ',' Value ')'
- return ParseOperation(CurRec);
- }
- }
-
- return R;
-}
-
-/// ParseValue - Parse a tblgen value. This returns null on error.
-///
-/// Value ::= SimpleValue ValueSuffix*
-/// ValueSuffix ::= '{' BitList '}'
-/// ValueSuffix ::= '[' BitList ']'
-/// ValueSuffix ::= '.' ID
-///
-Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType) {
- Init *Result = ParseSimpleValue(CurRec, ItemType);
- if (Result == 0) return 0;
-
- // Parse the suffixes now if present.
- while (1) {
- switch (Lex.getCode()) {
- default: return Result;
- case tgtok::l_brace: {
- SMLoc CurlyLoc = Lex.getLoc();
- Lex.Lex(); // eat the '{'
- std::vector<unsigned> Ranges = ParseRangeList();
- if (Ranges.empty()) return 0;
-
- // Reverse the bitlist.
- std::reverse(Ranges.begin(), Ranges.end());
- Result = Result->convertInitializerBitRange(Ranges);
- if (Result == 0) {
- Error(CurlyLoc, "Invalid bit range for value");
- return 0;
- }
-
- // Eat the '}'.
- if (Lex.getCode() != tgtok::r_brace) {
- TokError("expected '}' at end of bit range list");
- return 0;
- }
- Lex.Lex();
- break;
- }
- case tgtok::l_square: {
- SMLoc SquareLoc = Lex.getLoc();
- Lex.Lex(); // eat the '['
- std::vector<unsigned> Ranges = ParseRangeList();
- if (Ranges.empty()) return 0;
-
- Result = Result->convertInitListSlice(Ranges);
- if (Result == 0) {
- Error(SquareLoc, "Invalid range for list slice");
- return 0;
- }
-
- // Eat the ']'.
- if (Lex.getCode() != tgtok::r_square) {
- TokError("expected ']' at end of list slice");
- return 0;
- }
- Lex.Lex();
- break;
- }
- case tgtok::period:
- if (Lex.Lex() != tgtok::Id) { // eat the .
- TokError("expected field identifier after '.'");
- return 0;
- }
- if (!Result->getFieldType(Lex.getCurStrVal())) {
- TokError("Cannot access field '" + Lex.getCurStrVal() + "' of value '" +
- Result->getAsString() + "'");
- return 0;
- }
- Result = new FieldInit(Result, Lex.getCurStrVal());
- Lex.Lex(); // eat field name
- break;
- }
- }
-}
-
-/// ParseDagArgList - Parse the argument list for a dag literal expression.
-///
-/// ParseDagArgList ::= Value (':' VARNAME)?
-/// ParseDagArgList ::= ParseDagArgList ',' Value (':' VARNAME)?
-std::vector<std::pair<llvm::Init*, std::string> >
-TGParser::ParseDagArgList(Record *CurRec) {
- std::vector<std::pair<llvm::Init*, std::string> > Result;
-
- while (1) {
- Init *Val = ParseValue(CurRec);
- if (Val == 0) return std::vector<std::pair<llvm::Init*, std::string> >();
-
- // If the variable name is present, add it.
- std::string VarName;
- if (Lex.getCode() == tgtok::colon) {
- if (Lex.Lex() != tgtok::VarName) { // eat the ':'
- TokError("expected variable name in dag literal");
- return std::vector<std::pair<llvm::Init*, std::string> >();
- }
- VarName = Lex.getCurStrVal();
- Lex.Lex(); // eat the VarName.
- }
-
- Result.push_back(std::make_pair(Val, VarName));
-
- if (Lex.getCode() != tgtok::comma) break;
- Lex.Lex(); // eat the ','
- }
-
- return Result;
-}
-
-
-/// ParseValueList - Parse a comma separated list of values, returning them as a
-/// vector. Note that this always expects to be able to parse at least one
-/// value. It returns an empty list if this is not possible.
-///
-/// ValueList ::= Value (',' Value)
-///
-std::vector<Init*> TGParser::ParseValueList(Record *CurRec, Record *ArgsRec,
- RecTy *EltTy) {
- std::vector<Init*> Result;
- RecTy *ItemType = EltTy;
- unsigned int ArgN = 0;
- if (ArgsRec != 0 && EltTy == 0) {
- const std::vector<std::string> &TArgs = ArgsRec->getTemplateArgs();
- const RecordVal *RV = ArgsRec->getValue(TArgs[ArgN]);
- assert(RV && "Template argument record not found??");
- ItemType = RV->getType();
- ++ArgN;
- }
- Result.push_back(ParseValue(CurRec, ItemType));
- if (Result.back() == 0) return std::vector<Init*>();
-
- while (Lex.getCode() == tgtok::comma) {
- Lex.Lex(); // Eat the comma
-
- if (ArgsRec != 0 && EltTy == 0) {
- const std::vector<std::string> &TArgs = ArgsRec->getTemplateArgs();
- if (ArgN >= TArgs.size()) {
- TokError("too many template arguments");
- return std::vector<Init*>();
- }
- const RecordVal *RV = ArgsRec->getValue(TArgs[ArgN]);
- assert(RV && "Template argument record not found??");
- ItemType = RV->getType();
- ++ArgN;
- }
- Result.push_back(ParseValue(CurRec, ItemType));
- if (Result.back() == 0) return std::vector<Init*>();
- }
-
- return Result;
-}
-
-
-/// ParseDeclaration - Read a declaration, returning the name of field ID, or an
-/// empty string on error. This can happen in a number of different context's,
-/// including within a def or in the template args for a def (which which case
-/// CurRec will be non-null) and within the template args for a multiclass (in
-/// which case CurRec will be null, but CurMultiClass will be set). This can
-/// also happen within a def that is within a multiclass, which will set both
-/// CurRec and CurMultiClass.
-///
-/// Declaration ::= FIELD? Type ID ('=' Value)?
-///
-std::string TGParser::ParseDeclaration(Record *CurRec,
- bool ParsingTemplateArgs) {
- // Read the field prefix if present.
- bool HasField = Lex.getCode() == tgtok::Field;
- if (HasField) Lex.Lex();
-
- RecTy *Type = ParseType();
- if (Type == 0) return "";
-
- if (Lex.getCode() != tgtok::Id) {
- TokError("Expected identifier in declaration");
- return "";
- }
-
- SMLoc IdLoc = Lex.getLoc();
- std::string DeclName = Lex.getCurStrVal();
- Lex.Lex();
-
- if (ParsingTemplateArgs) {
- if (CurRec) {
- DeclName = CurRec->getName() + ":" + DeclName;
- } else {
- assert(CurMultiClass);
- }
- if (CurMultiClass)
- DeclName = CurMultiClass->Rec.getName() + "::" + DeclName;
- }
-
- // Add the value.
- if (AddValue(CurRec, IdLoc, RecordVal(DeclName, Type, HasField)))
- return "";
-
- // If a value is present, parse it.
- if (Lex.getCode() == tgtok::equal) {
- Lex.Lex();
- SMLoc ValLoc = Lex.getLoc();
- Init *Val = ParseValue(CurRec, Type);
- if (Val == 0 ||
- SetValue(CurRec, ValLoc, DeclName, std::vector<unsigned>(), Val))
- return "";
- }
-
- return DeclName;
-}
-
-/// ParseTemplateArgList - Read a template argument list, which is a non-empty
-/// sequence of template-declarations in <>'s. If CurRec is non-null, these are
-/// template args for a def, which may or may not be in a multiclass. If null,
-/// these are the template args for a multiclass.
-///
-/// TemplateArgList ::= '<' Declaration (',' Declaration)* '>'
-///
-bool TGParser::ParseTemplateArgList(Record *CurRec) {
- assert(Lex.getCode() == tgtok::less && "Not a template arg list!");
- Lex.Lex(); // eat the '<'
-
- Record *TheRecToAddTo = CurRec ? CurRec : &CurMultiClass->Rec;
-
- // Read the first declaration.
- std::string TemplArg = ParseDeclaration(CurRec, true/*templateargs*/);
- if (TemplArg.empty())
- return true;
-
- TheRecToAddTo->addTemplateArg(TemplArg);
-
- while (Lex.getCode() == tgtok::comma) {
- Lex.Lex(); // eat the ','
-
- // Read the following declarations.
- TemplArg = ParseDeclaration(CurRec, true/*templateargs*/);
- if (TemplArg.empty())
- return true;
- TheRecToAddTo->addTemplateArg(TemplArg);
- }
-
- if (Lex.getCode() != tgtok::greater)
- return TokError("expected '>' at end of template argument list");
- Lex.Lex(); // eat the '>'.
- return false;
-}
-
-
-/// ParseBodyItem - Parse a single item at within the body of a def or class.
-///
-/// BodyItem ::= Declaration ';'
-/// BodyItem ::= LET ID OptionalBitList '=' Value ';'
-bool TGParser::ParseBodyItem(Record *CurRec) {
- if (Lex.getCode() != tgtok::Let) {
- if (ParseDeclaration(CurRec, false).empty())
- return true;
-
- if (Lex.getCode() != tgtok::semi)
- return TokError("expected ';' after declaration");
- Lex.Lex();
- return false;
- }
-
- // LET ID OptionalRangeList '=' Value ';'
- if (Lex.Lex() != tgtok::Id)
- return TokError("expected field identifier after let");
-
- SMLoc IdLoc = Lex.getLoc();
- std::string FieldName = Lex.getCurStrVal();
- Lex.Lex(); // eat the field name.
-
- std::vector<unsigned> BitList;
- if (ParseOptionalBitList(BitList))
- return true;
- std::reverse(BitList.begin(), BitList.end());
-
- if (Lex.getCode() != tgtok::equal)
- return TokError("expected '=' in let expression");
- Lex.Lex(); // eat the '='.
-
- RecordVal *Field = CurRec->getValue(FieldName);
- if (Field == 0)
- return TokError("Value '" + FieldName + "' unknown!");
-
- RecTy *Type = Field->getType();
-
- Init *Val = ParseValue(CurRec, Type);
- if (Val == 0) return true;
-
- if (Lex.getCode() != tgtok::semi)
- return TokError("expected ';' after let expression");
- Lex.Lex();
-
- return SetValue(CurRec, IdLoc, FieldName, BitList, Val);
-}
-
-/// ParseBody - Read the body of a class or def. Return true on error, false on
-/// success.
-///
-/// Body ::= ';'
-/// Body ::= '{' BodyList '}'
-/// BodyList BodyItem*
-///
-bool TGParser::ParseBody(Record *CurRec) {
- // If this is a null definition, just eat the semi and return.
- if (Lex.getCode() == tgtok::semi) {
- Lex.Lex();
- return false;
- }
-
- if (Lex.getCode() != tgtok::l_brace)
- return TokError("Expected ';' or '{' to start body");
- // Eat the '{'.
- Lex.Lex();
-
- while (Lex.getCode() != tgtok::r_brace)
- if (ParseBodyItem(CurRec))
- return true;
-
- // Eat the '}'.
- Lex.Lex();
- return false;
-}
-
-/// ParseObjectBody - Parse the body of a def or class. This consists of an
-/// optional ClassList followed by a Body. CurRec is the current def or class
-/// that is being parsed.
-///
-/// ObjectBody ::= BaseClassList Body
-/// BaseClassList ::= /*empty*/
-/// BaseClassList ::= ':' BaseClassListNE
-/// BaseClassListNE ::= SubClassRef (',' SubClassRef)*
-///
-bool TGParser::ParseObjectBody(Record *CurRec) {
- // If there is a baseclass list, read it.
- if (Lex.getCode() == tgtok::colon) {
- Lex.Lex();
-
- // Read all of the subclasses.
- SubClassReference SubClass = ParseSubClassReference(CurRec, false);
- while (1) {
- // Check for error.
- if (SubClass.Rec == 0) return true;
-
- // Add it.
- if (AddSubClass(CurRec, SubClass))
- return true;
-
- if (Lex.getCode() != tgtok::comma) break;
- Lex.Lex(); // eat ','.
- SubClass = ParseSubClassReference(CurRec, false);
- }
- }
-
- // Process any variables on the let stack.
- for (unsigned i = 0, e = LetStack.size(); i != e; ++i)
- for (unsigned j = 0, e = LetStack[i].size(); j != e; ++j)
- if (SetValue(CurRec, LetStack[i][j].Loc, LetStack[i][j].Name,
- LetStack[i][j].Bits, LetStack[i][j].Value))
- return true;
-
- return ParseBody(CurRec);
-}
-
-/// ParseDef - Parse and return a top level or multiclass def, return the record
-/// corresponding to it. This returns null on error.
-///
-/// DefInst ::= DEF ObjectName ObjectBody
-///
-bool TGParser::ParseDef(MultiClass *CurMultiClass) {
- SMLoc DefLoc = Lex.getLoc();
- assert(Lex.getCode() == tgtok::Def && "Unknown tok");
- Lex.Lex(); // Eat the 'def' token.
-
- // Parse ObjectName and make a record for it.
- Record *CurRec = new Record(ParseObjectName(), DefLoc, Records);
-
- if (!CurMultiClass) {
- // Top-level def definition.
-
- // Ensure redefinition doesn't happen.
- if (Records.getDef(CurRec->getName())) {
- Error(DefLoc, "def '" + CurRec->getName() + "' already defined");
- return true;
- }
- Records.addDef(CurRec);
- } else {
- // Otherwise, a def inside a multiclass, add it to the multiclass.
- for (unsigned i = 0, e = CurMultiClass->DefPrototypes.size(); i != e; ++i)
- if (CurMultiClass->DefPrototypes[i]->getName() == CurRec->getName()) {
- Error(DefLoc, "def '" + CurRec->getName() +
- "' already defined in this multiclass!");
- return true;
- }
- CurMultiClass->DefPrototypes.push_back(CurRec);
- }
-
- if (ParseObjectBody(CurRec))
- return true;
-
- if (CurMultiClass == 0) // Def's in multiclasses aren't really defs.
- CurRec->resolveReferences();
-
- // If ObjectBody has template arguments, it's an error.
- assert(CurRec->getTemplateArgs().empty() && "How'd this get template args?");
-
- if (CurMultiClass) {
- // Copy the template arguments for the multiclass into the def.
- const std::vector<std::string> &TArgs =
- CurMultiClass->Rec.getTemplateArgs();
-
- for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {
- const RecordVal *RV = CurMultiClass->Rec.getValue(TArgs[i]);
- assert(RV && "Template arg doesn't exist?");
- CurRec->addValue(*RV);
- }
- }
-
- return false;
-}
-
-
-/// ParseClass - Parse a tblgen class definition.
-///
-/// ClassInst ::= CLASS ID TemplateArgList? ObjectBody
-///
-bool TGParser::ParseClass() {
- assert(Lex.getCode() == tgtok::Class && "Unexpected token!");
- Lex.Lex();
-
- if (Lex.getCode() != tgtok::Id)
- return TokError("expected class name after 'class' keyword");
-
- Record *CurRec = Records.getClass(Lex.getCurStrVal());
- if (CurRec) {
- // If the body was previously defined, this is an error.
- if (!CurRec->getValues().empty() ||
- !CurRec->getSuperClasses().empty() ||
- !CurRec->getTemplateArgs().empty())
- return TokError("Class '" + CurRec->getName() + "' already defined");
- } else {
- // If this is the first reference to this class, create and add it.
- CurRec = new Record(Lex.getCurStrVal(), Lex.getLoc(), Records);
- Records.addClass(CurRec);
- }
- Lex.Lex(); // eat the name.
-
- // If there are template args, parse them.
- if (Lex.getCode() == tgtok::less)
- if (ParseTemplateArgList(CurRec))
- return true;
-
- // Finally, parse the object body.
- return ParseObjectBody(CurRec);
-}
-
-/// ParseLetList - Parse a non-empty list of assignment expressions into a list
-/// of LetRecords.
-///
-/// LetList ::= LetItem (',' LetItem)*
-/// LetItem ::= ID OptionalRangeList '=' Value
-///
-std::vector<LetRecord> TGParser::ParseLetList() {
- std::vector<LetRecord> Result;
-
- while (1) {
- if (Lex.getCode() != tgtok::Id) {
- TokError("expected identifier in let definition");
- return std::vector<LetRecord>();
- }
- std::string Name = Lex.getCurStrVal();
- SMLoc NameLoc = Lex.getLoc();
- Lex.Lex(); // Eat the identifier.
-
- // Check for an optional RangeList.
- std::vector<unsigned> Bits;
- if (ParseOptionalRangeList(Bits))
- return std::vector<LetRecord>();
- std::reverse(Bits.begin(), Bits.end());
-
- if (Lex.getCode() != tgtok::equal) {
- TokError("expected '=' in let expression");
- return std::vector<LetRecord>();
- }
- Lex.Lex(); // eat the '='.
-
- Init *Val = ParseValue(0);
- if (Val == 0) return std::vector<LetRecord>();
-
- // Now that we have everything, add the record.
- Result.push_back(LetRecord(Name, Bits, Val, NameLoc));
-
- if (Lex.getCode() != tgtok::comma)
- return Result;
- Lex.Lex(); // eat the comma.
- }
-}
-
-/// ParseTopLevelLet - Parse a 'let' at top level. This can be a couple of
-/// different related productions. This works inside multiclasses too.
-///
-/// Object ::= LET LetList IN '{' ObjectList '}'
-/// Object ::= LET LetList IN Object
-///
-bool TGParser::ParseTopLevelLet(MultiClass *CurMultiClass) {
- assert(Lex.getCode() == tgtok::Let && "Unexpected token");
- Lex.Lex();
-
- // Add this entry to the let stack.
- std::vector<LetRecord> LetInfo = ParseLetList();
- if (LetInfo.empty()) return true;
- LetStack.push_back(LetInfo);
-
- if (Lex.getCode() != tgtok::In)
- return TokError("expected 'in' at end of top-level 'let'");
- Lex.Lex();
-
- // If this is a scalar let, just handle it now
- if (Lex.getCode() != tgtok::l_brace) {
- // LET LetList IN Object
- if (ParseObject(CurMultiClass))
- return true;
- } else { // Object ::= LETCommand '{' ObjectList '}'
- SMLoc BraceLoc = Lex.getLoc();
- // Otherwise, this is a group let.
- Lex.Lex(); // eat the '{'.
-
- // Parse the object list.
- if (ParseObjectList(CurMultiClass))
- return true;
-
- if (Lex.getCode() != tgtok::r_brace) {
- TokError("expected '}' at end of top level let command");
- return Error(BraceLoc, "to match this '{'");
- }
- Lex.Lex();
- }
-
- // Outside this let scope, this let block is not active.
- LetStack.pop_back();
- return false;
-}
-
-/// ParseMultiClass - Parse a multiclass definition.
-///
-/// MultiClassInst ::= MULTICLASS ID TemplateArgList?
-/// ':' BaseMultiClassList '{' MultiClassDef+ '}'
-///
-bool TGParser::ParseMultiClass() {
- assert(Lex.getCode() == tgtok::MultiClass && "Unexpected token");
- Lex.Lex(); // Eat the multiclass token.
-
- if (Lex.getCode() != tgtok::Id)
- return TokError("expected identifier after multiclass for name");
- std::string Name = Lex.getCurStrVal();
-
- if (MultiClasses.count(Name))
- return TokError("multiclass '" + Name + "' already defined");
-
- CurMultiClass = MultiClasses[Name] = new MultiClass(Name,
- Lex.getLoc(), Records);
- Lex.Lex(); // Eat the identifier.
-
- // If there are template args, parse them.
- if (Lex.getCode() == tgtok::less)
- if (ParseTemplateArgList(0))
- return true;
-
- bool inherits = false;
-
- // If there are submulticlasses, parse them.
- if (Lex.getCode() == tgtok::colon) {
- inherits = true;
-
- Lex.Lex();
-
- // Read all of the submulticlasses.
- SubMultiClassReference SubMultiClass =
- ParseSubMultiClassReference(CurMultiClass);
- while (1) {
- // Check for error.
- if (SubMultiClass.MC == 0) return true;
-
- // Add it.
- if (AddSubMultiClass(CurMultiClass, SubMultiClass))
- return true;
-
- if (Lex.getCode() != tgtok::comma) break;
- Lex.Lex(); // eat ','.
- SubMultiClass = ParseSubMultiClassReference(CurMultiClass);
- }
- }
-
- if (Lex.getCode() != tgtok::l_brace) {
- if (!inherits)
- return TokError("expected '{' in multiclass definition");
- else if (Lex.getCode() != tgtok::semi)
- return TokError("expected ';' in multiclass definition");
- else
- Lex.Lex(); // eat the ';'.
- } else {
- if (Lex.Lex() == tgtok::r_brace) // eat the '{'.
- return TokError("multiclass must contain at least one def");
-
- while (Lex.getCode() != tgtok::r_brace) {
- switch (Lex.getCode()) {
- default:
- return TokError("expected 'let', 'def' or 'defm' in multiclass body");
- case tgtok::Let:
- case tgtok::Def:
- case tgtok::Defm:
- if (ParseObject(CurMultiClass))
- return true;
- break;
- }
- }
- Lex.Lex(); // eat the '}'.
- }
-
- CurMultiClass = 0;
- return false;
-}
-
-/// ParseDefm - Parse the instantiation of a multiclass.
-///
-/// DefMInst ::= DEFM ID ':' DefmSubClassRef ';'
-///
-bool TGParser::ParseDefm(MultiClass *CurMultiClass) {
- assert(Lex.getCode() == tgtok::Defm && "Unexpected token!");
-
- std::string DefmPrefix;
- if (Lex.Lex() == tgtok::Id) { // eat the defm.
- DefmPrefix = Lex.getCurStrVal();
- Lex.Lex(); // Eat the defm prefix.
- }
-
- SMLoc DefmPrefixLoc = Lex.getLoc();
- if (Lex.getCode() != tgtok::colon)
- return TokError("expected ':' after defm identifier");
-
- // Keep track of the new generated record definitions.
- std::vector<Record*> NewRecDefs;
-
- // This record also inherits from a regular class (non-multiclass)?
- bool InheritFromClass = false;
-
- // eat the colon.
- Lex.Lex();
-
- SMLoc SubClassLoc = Lex.getLoc();
- SubClassReference Ref = ParseSubClassReference(0, true);
-
- while (1) {
- if (Ref.Rec == 0) return true;
-
- // To instantiate a multiclass, we need to first get the multiclass, then
- // instantiate each def contained in the multiclass with the SubClassRef
- // template parameters.
- MultiClass *MC = MultiClasses[Ref.Rec->getName()];
- assert(MC && "Didn't lookup multiclass correctly?");
- std::vector<Init*> &TemplateVals = Ref.TemplateArgs;
-
- // Verify that the correct number of template arguments were specified.
- const std::vector<std::string> &TArgs = MC->Rec.getTemplateArgs();
- if (TArgs.size() < TemplateVals.size())
- return Error(SubClassLoc,
- "more template args specified than multiclass expects");
-
- // Loop over all the def's in the multiclass, instantiating each one.
- for (unsigned i = 0, e = MC->DefPrototypes.size(); i != e; ++i) {
- Record *DefProto = MC->DefPrototypes[i];
-
- // Add in the defm name. If the defm prefix is empty, give each
- // instantiated def a unique name. Otherwise, if "#NAME#" exists in the
- // name, substitute the prefix for #NAME#. Otherwise, use the defm name
- // as a prefix.
- std::string DefName = DefProto->getName();
- if (DefmPrefix.empty()) {
- DefName = GetNewAnonymousName();
- } else {
- std::string::size_type idx = DefName.find("#NAME#");
- if (idx != std::string::npos) {
- DefName.replace(idx, 6, DefmPrefix);
- } else {
- // Add the suffix to the defm name to get the new name.
- DefName = DefmPrefix + DefName;
- }
- }
-
- Record *CurRec = new Record(DefName, DefmPrefixLoc, Records);
-
- SubClassReference Ref;
- Ref.RefLoc = DefmPrefixLoc;
- Ref.Rec = DefProto;
- AddSubClass(CurRec, Ref);
-
- // Loop over all of the template arguments, setting them to the specified
- // value or leaving them as the default if necessary.
- for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {
- // Check if a value is specified for this temp-arg.
- if (i < TemplateVals.size()) {
- // Set it now.
- if (SetValue(CurRec, DefmPrefixLoc, TArgs[i], std::vector<unsigned>(),
- TemplateVals[i]))
- return true;
-
- // Resolve it next.
- CurRec->resolveReferencesTo(CurRec->getValue(TArgs[i]));
-
- // Now remove it.
- CurRec->removeValue(TArgs[i]);
-
- } else if (!CurRec->getValue(TArgs[i])->getValue()->isComplete()) {
- return Error(SubClassLoc,
- "value not specified for template argument #"+
- utostr(i) + " (" + TArgs[i] + ") of multiclassclass '" +
- MC->Rec.getName() + "'");
- }
- }
-
- // If the mdef is inside a 'let' expression, add to each def.
- for (unsigned i = 0, e = LetStack.size(); i != e; ++i)
- for (unsigned j = 0, e = LetStack[i].size(); j != e; ++j)
- if (SetValue(CurRec, LetStack[i][j].Loc, LetStack[i][j].Name,
- LetStack[i][j].Bits, LetStack[i][j].Value)) {
- Error(DefmPrefixLoc, "when instantiating this defm");
- return true;
- }
-
- // Ensure redefinition doesn't happen.
- if (Records.getDef(CurRec->getName()))
- return Error(DefmPrefixLoc, "def '" + CurRec->getName() +
- "' already defined, instantiating defm with subdef '" +
- DefProto->getName() + "'");
-
- // Don't create a top level definition for defm inside multiclasses,
- // instead, only update the prototypes and bind the template args
- // with the new created definition.
- if (CurMultiClass) {
- for (unsigned i = 0, e = CurMultiClass->DefPrototypes.size();
- i != e; ++i) {
- if (CurMultiClass->DefPrototypes[i]->getName() == CurRec->getName()) {
- Error(DefmPrefixLoc, "defm '" + CurRec->getName() +
- "' already defined in this multiclass!");
- return 0;
- }
- }
- CurMultiClass->DefPrototypes.push_back(CurRec);
-
- // Copy the template arguments for the multiclass into the new def.
- const std::vector<std::string> &TA =
- CurMultiClass->Rec.getTemplateArgs();
-
- for (unsigned i = 0, e = TA.size(); i != e; ++i) {
- const RecordVal *RV = CurMultiClass->Rec.getValue(TA[i]);
- assert(RV && "Template arg doesn't exist?");
- CurRec->addValue(*RV);
- }
- } else {
- Records.addDef(CurRec);
- }
-
- NewRecDefs.push_back(CurRec);
- }
-
- if (Lex.getCode() != tgtok::comma) break;
- Lex.Lex(); // eat ','.
-
- SubClassLoc = Lex.getLoc();
-
- // A defm can inherit from regular classes (non-multiclass) as
- // long as they come in the end of the inheritance list.
- InheritFromClass = (Records.getClass(Lex.getCurStrVal()) != 0);
-
- if (InheritFromClass)
- break;
-
- Ref = ParseSubClassReference(0, true);
- }
-
- if (InheritFromClass) {
- // Process all the classes to inherit as if they were part of a
- // regular 'def' and inherit all record values.
- SubClassReference SubClass = ParseSubClassReference(0, false);
- while (1) {
- // Check for error.
- if (SubClass.Rec == 0) return true;
-
- // Get the expanded definition prototypes and teach them about
- // the record values the current class to inherit has
- for (unsigned i = 0, e = NewRecDefs.size(); i != e; ++i) {
- Record *CurRec = NewRecDefs[i];
-
- // Add it.
- if (AddSubClass(CurRec, SubClass))
- return true;
-
- // Process any variables on the let stack.
- for (unsigned i = 0, e = LetStack.size(); i != e; ++i)
- for (unsigned j = 0, e = LetStack[i].size(); j != e; ++j)
- if (SetValue(CurRec, LetStack[i][j].Loc, LetStack[i][j].Name,
- LetStack[i][j].Bits, LetStack[i][j].Value))
- return true;
- }
-
- if (Lex.getCode() != tgtok::comma) break;
- Lex.Lex(); // eat ','.
- SubClass = ParseSubClassReference(0, false);
- }
- }
-
- if (!CurMultiClass)
- for (unsigned i = 0, e = NewRecDefs.size(); i != e; ++i)
- NewRecDefs[i]->resolveReferences();
-
- if (Lex.getCode() != tgtok::semi)
- return TokError("expected ';' at end of defm");
- Lex.Lex();
-
- return false;
-}
-
-/// ParseObject
-/// Object ::= ClassInst
-/// Object ::= DefInst
-/// Object ::= MultiClassInst
-/// Object ::= DefMInst
-/// Object ::= LETCommand '{' ObjectList '}'
-/// Object ::= LETCommand Object
-bool TGParser::ParseObject(MultiClass *MC) {
- switch (Lex.getCode()) {
- default:
- return TokError("Expected class, def, defm, multiclass or let definition");
- case tgtok::Let: return ParseTopLevelLet(MC);
- case tgtok::Def: return ParseDef(MC);
- case tgtok::Defm: return ParseDefm(MC);
- case tgtok::Class: return ParseClass();
- case tgtok::MultiClass: return ParseMultiClass();
- }
-}
-
-/// ParseObjectList
-/// ObjectList :== Object*
-bool TGParser::ParseObjectList(MultiClass *MC) {
- while (isObjectStart(Lex.getCode())) {
- if (ParseObject(MC))
- return true;
- }
- return false;
-}
-
-bool TGParser::ParseFile() {
- Lex.Lex(); // Prime the lexer.
- if (ParseObjectList()) return true;
-
- // If we have unread input at the end of the file, report it.
- if (Lex.getCode() == tgtok::Eof)
- return false;
-
- return TokError("Unexpected input at top level");
-}
-
diff --git a/contrib/llvm/utils/TableGen/TGParser.h b/contrib/llvm/utils/TableGen/TGParser.h
deleted file mode 100644
index dce7e1d..0000000
--- a/contrib/llvm/utils/TableGen/TGParser.h
+++ /dev/null
@@ -1,122 +0,0 @@
-//===- TGParser.h - Parser for TableGen Files -------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This class represents the Parser for tablegen files.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef TGPARSER_H
-#define TGPARSER_H
-
-#include "TGLexer.h"
-#include "Error.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/Support/SourceMgr.h"
-#include <map>
-
-namespace llvm {
- class Record;
- class RecordVal;
- class RecordKeeper;
- struct RecTy;
- class Init;
- struct MultiClass;
- struct SubClassReference;
- struct SubMultiClassReference;
-
- struct LetRecord {
- std::string Name;
- std::vector<unsigned> Bits;
- Init *Value;
- SMLoc Loc;
- LetRecord(const std::string &N, const std::vector<unsigned> &B, Init *V,
- SMLoc L)
- : Name(N), Bits(B), Value(V), Loc(L) {
- }
- };
-
-class TGParser {
- TGLexer Lex;
- std::vector<std::vector<LetRecord> > LetStack;
- std::map<std::string, MultiClass*> MultiClasses;
-
- /// CurMultiClass - If we are parsing a 'multiclass' definition, this is the
- /// current value.
- MultiClass *CurMultiClass;
-
- // Record tracker
- RecordKeeper &Records;
-public:
- TGParser(SourceMgr &SrcMgr, RecordKeeper &records) :
- Lex(SrcMgr), CurMultiClass(0), Records(records) {}
-
- /// ParseFile - Main entrypoint for parsing a tblgen file. These parser
- /// routines return true on error, or false on success.
- bool ParseFile();
-
- bool Error(SMLoc L, const Twine &Msg) const {
- PrintError(L, Msg);
- return true;
- }
- bool TokError(const Twine &Msg) const {
- return Error(Lex.getLoc(), Msg);
- }
- const std::vector<std::string> &getDependencies() const {
- return Lex.getDependencies();
- }
-private: // Semantic analysis methods.
- bool AddValue(Record *TheRec, SMLoc Loc, const RecordVal &RV);
- bool SetValue(Record *TheRec, SMLoc Loc, const std::string &ValName,
- const std::vector<unsigned> &BitList, Init *V);
- bool AddSubClass(Record *Rec, SubClassReference &SubClass);
- bool AddSubMultiClass(MultiClass *CurMC,
- SubMultiClassReference &SubMultiClass);
-
-private: // Parser methods.
- bool ParseObjectList(MultiClass *MC = 0);
- bool ParseObject(MultiClass *MC);
- bool ParseClass();
- bool ParseMultiClass();
- bool ParseDefm(MultiClass *CurMultiClass);
- bool ParseDef(MultiClass *CurMultiClass);
- bool ParseTopLevelLet(MultiClass *CurMultiClass);
- std::vector<LetRecord> ParseLetList();
-
- bool ParseObjectBody(Record *CurRec);
- bool ParseBody(Record *CurRec);
- bool ParseBodyItem(Record *CurRec);
-
- bool ParseTemplateArgList(Record *CurRec);
- std::string ParseDeclaration(Record *CurRec, bool ParsingTemplateArgs);
-
- SubClassReference ParseSubClassReference(Record *CurRec, bool isDefm);
- SubMultiClassReference ParseSubMultiClassReference(MultiClass *CurMC);
-
- Init *ParseIDValue(Record *CurRec);
- Init *ParseIDValue(Record *CurRec, const std::string &Name, SMLoc NameLoc);
- Init *ParseSimpleValue(Record *CurRec, RecTy *ItemType = 0);
- Init *ParseValue(Record *CurRec, RecTy *ItemType = 0);
- std::vector<Init*> ParseValueList(Record *CurRec, Record *ArgsRec = 0, RecTy *EltTy = 0);
- std::vector<std::pair<llvm::Init*, std::string> > ParseDagArgList(Record *);
- bool ParseOptionalRangeList(std::vector<unsigned> &Ranges);
- bool ParseOptionalBitList(std::vector<unsigned> &Ranges);
- std::vector<unsigned> ParseRangeList();
- bool ParseRangePiece(std::vector<unsigned> &Ranges);
- RecTy *ParseType();
- Init *ParseOperation(Record *CurRec);
- RecTy *ParseOperatorType();
- std::string ParseObjectName();
- Record *ParseClassID();
- MultiClass *ParseMultiClassID();
- Record *ParseDefmID();
-};
-
-} // end namespace llvm
-
-#endif
diff --git a/contrib/llvm/utils/TableGen/TableGen.cpp b/contrib/llvm/utils/TableGen/TableGen.cpp
index e8eacb8..eacfdf6 100644
--- a/contrib/llvm/utils/TableGen/TableGen.cpp
+++ b/contrib/llvm/utils/TableGen/TableGen.cpp
@@ -1,4 +1,4 @@
-//===- TableGen.cpp - Top-Level TableGen implementation -------------------===//
+//===- TableGen.cpp - Top-Level TableGen implementation for LLVM ----------===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,48 +7,34 @@
//
//===----------------------------------------------------------------------===//
//
-// TableGen is a tool which can be used to build up a description of something,
-// then invoke one or more "tablegen backends" to emit information about the
-// description in some predefined format. In practice, this is used by the LLVM
-// code generators to automate generation of a code generator through a
-// high-level description of the target.
+// This file contains the main function for LLVM's TableGen.
//
//===----------------------------------------------------------------------===//
#include "AsmMatcherEmitter.h"
#include "AsmWriterEmitter.h"
#include "CallingConvEmitter.h"
-#include "ClangASTNodesEmitter.h"
-#include "ClangAttrEmitter.h"
-#include "ClangDiagnosticsEmitter.h"
-#include "ClangSACheckersEmitter.h"
#include "CodeEmitterGen.h"
#include "DAGISelEmitter.h"
#include "DisassemblerEmitter.h"
#include "EDEmitter.h"
-#include "Error.h"
#include "FastISelEmitter.h"
#include "InstrInfoEmitter.h"
#include "IntrinsicEmitter.h"
-#include "LLVMCConfigurationEmitter.h"
-#include "NeonEmitter.h"
-#include "OptParserEmitter.h"
#include "PseudoLoweringEmitter.h"
-#include "Record.h"
#include "RegisterInfoEmitter.h"
#include "ARMDecoderEmitter.h"
#include "SubtargetEmitter.h"
#include "SetTheory.h"
-#include "TGParser.h"
-#include "llvm/ADT/OwningPtr.h"
+
#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/Signals.h"
-#include "llvm/Support/system_error.h"
-#include <algorithm>
-#include <cstdio>
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Main.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/TableGenAction.h"
+
using namespace llvm;
enum ActionType {
@@ -62,29 +48,12 @@ enum ActionType {
GenDisassembler,
GenPseudoLowering,
GenCallingConv,
- GenClangAttrClasses,
- GenClangAttrImpl,
- GenClangAttrList,
- GenClangAttrPCHRead,
- GenClangAttrPCHWrite,
- GenClangAttrSpellingList,
- GenClangDiagsDefs,
- GenClangDiagGroups,
- GenClangDiagsIndexName,
- GenClangDeclNodes,
- GenClangStmtNodes,
- GenClangSACheckers,
GenDAGISel,
GenFastISel,
- GenOptParserDefs, GenOptParserImpl,
GenSubtarget,
GenIntrinsic,
GenTgtIntrinsic,
- GenLLVMCConf,
GenEDInfo,
- GenArmNeon,
- GenArmNeonSema,
- GenArmNeonTest,
PrintEnums,
PrintSets
};
@@ -116,52 +85,14 @@ namespace {
"Generate a DAG instruction selector"),
clEnumValN(GenFastISel, "gen-fast-isel",
"Generate a \"fast\" instruction selector"),
- clEnumValN(GenOptParserDefs, "gen-opt-parser-defs",
- "Generate option definitions"),
- clEnumValN(GenOptParserImpl, "gen-opt-parser-impl",
- "Generate option parser implementation"),
clEnumValN(GenSubtarget, "gen-subtarget",
"Generate subtarget enumerations"),
clEnumValN(GenIntrinsic, "gen-intrinsic",
"Generate intrinsic information"),
clEnumValN(GenTgtIntrinsic, "gen-tgt-intrinsic",
"Generate target intrinsic information"),
- clEnumValN(GenClangAttrClasses, "gen-clang-attr-classes",
- "Generate clang attribute clases"),
- clEnumValN(GenClangAttrImpl, "gen-clang-attr-impl",
- "Generate clang attribute implementations"),
- clEnumValN(GenClangAttrList, "gen-clang-attr-list",
- "Generate a clang attribute list"),
- clEnumValN(GenClangAttrPCHRead, "gen-clang-attr-pch-read",
- "Generate clang PCH attribute reader"),
- clEnumValN(GenClangAttrPCHWrite, "gen-clang-attr-pch-write",
- "Generate clang PCH attribute writer"),
- clEnumValN(GenClangAttrSpellingList,
- "gen-clang-attr-spelling-list",
- "Generate a clang attribute spelling list"),
- clEnumValN(GenClangDiagsDefs, "gen-clang-diags-defs",
- "Generate Clang diagnostics definitions"),
- clEnumValN(GenClangDiagGroups, "gen-clang-diag-groups",
- "Generate Clang diagnostic groups"),
- clEnumValN(GenClangDiagsIndexName,
- "gen-clang-diags-index-name",
- "Generate Clang diagnostic name index"),
- clEnumValN(GenClangDeclNodes, "gen-clang-decl-nodes",
- "Generate Clang AST declaration nodes"),
- clEnumValN(GenClangStmtNodes, "gen-clang-stmt-nodes",
- "Generate Clang AST statement nodes"),
- clEnumValN(GenClangSACheckers, "gen-clang-sa-checkers",
- "Generate Clang Static Analyzer checkers"),
- clEnumValN(GenLLVMCConf, "gen-llvmc",
- "Generate LLVMC configuration library"),
clEnumValN(GenEDInfo, "gen-enhanced-disassembly-info",
"Generate enhanced disassembly info"),
- clEnumValN(GenArmNeon, "gen-arm-neon",
- "Generate arm_neon.h for clang"),
- clEnumValN(GenArmNeonSema, "gen-arm-neon-sema",
- "Generate ARM NEON sema support for clang"),
- clEnumValN(GenArmNeonTest, "gen-arm-neon-test",
- "Generate ARM NEON tests for clang"),
clEnumValN(PrintEnums, "print-enums",
"Print enum values for a class"),
clEnumValN(PrintSets, "print-sets",
@@ -171,198 +102,66 @@ namespace {
cl::opt<std::string>
Class("class", cl::desc("Print Enum list for this class"),
cl::value_desc("class name"));
-
- cl::opt<std::string>
- OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"),
- cl::init("-"));
-
- cl::opt<std::string>
- DependFilename("d", cl::desc("Dependency filename"), cl::value_desc("filename"),
- cl::init(""));
-
- cl::opt<std::string>
- InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-"));
-
- cl::list<std::string>
- IncludeDirs("I", cl::desc("Directory of include files"),
- cl::value_desc("directory"), cl::Prefix);
-
- cl::opt<std::string>
- ClangComponent("clang-component",
- cl::desc("Only use warnings from specified component"),
- cl::value_desc("component"), cl::Hidden);
}
-
-int main(int argc, char **argv) {
- RecordKeeper Records;
-
- sys::PrintStackTraceOnErrorSignal();
- PrettyStackTraceProgram X(argc, argv);
- cl::ParseCommandLineOptions(argc, argv);
-
-
- try {
- // Parse the input file.
- OwningPtr<MemoryBuffer> File;
- if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename.c_str(), File)) {
- errs() << "Could not open input file '" << InputFilename << "': "
- << ec.message() <<"\n";
- return 1;
- }
- MemoryBuffer *F = File.take();
-
- // Tell SrcMgr about this buffer, which is what TGParser will pick up.
- SrcMgr.AddNewSourceBuffer(F, SMLoc());
-
- // Record the location of the include directory so that the lexer can find
- // it later.
- SrcMgr.setIncludeDirs(IncludeDirs);
-
- TGParser Parser(SrcMgr, Records);
-
- if (Parser.ParseFile())
- return 1;
-
- std::string Error;
- tool_output_file Out(OutputFilename.c_str(), Error);
- if (!Error.empty()) {
- errs() << argv[0] << ": error opening " << OutputFilename
- << ":" << Error << "\n";
- return 1;
- }
- if (!DependFilename.empty()) {
- if (OutputFilename == "-") {
- errs() << argv[0] << ": the option -d must be used together with -o\n";
- return 1;
- }
- tool_output_file DepOut(DependFilename.c_str(), Error);
- if (!Error.empty()) {
- errs() << argv[0] << ": error opening " << DependFilename
- << ":" << Error << "\n";
- return 1;
- }
- DepOut.os() << DependFilename << ":";
- const std::vector<std::string> &Dependencies = Parser.getDependencies();
- for (std::vector<std::string>::const_iterator I = Dependencies.begin(),
- E = Dependencies.end();
- I != E; ++I) {
- DepOut.os() << " " << (*I);
- }
- DepOut.os() << "\n";
- DepOut.keep();
- }
-
+class LLVMTableGenAction : public TableGenAction {
+public:
+ bool operator()(raw_ostream &OS, RecordKeeper &Records) {
switch (Action) {
case PrintRecords:
- Out.os() << Records; // No argument, dump all contents
+ OS << Records; // No argument, dump all contents
break;
case GenEmitter:
- CodeEmitterGen(Records).run(Out.os());
+ CodeEmitterGen(Records).run(OS);
break;
case GenRegisterInfo:
- RegisterInfoEmitter(Records).run(Out.os());
+ RegisterInfoEmitter(Records).run(OS);
break;
case GenInstrInfo:
- InstrInfoEmitter(Records).run(Out.os());
+ InstrInfoEmitter(Records).run(OS);
break;
case GenCallingConv:
- CallingConvEmitter(Records).run(Out.os());
+ CallingConvEmitter(Records).run(OS);
break;
case GenAsmWriter:
- AsmWriterEmitter(Records).run(Out.os());
+ AsmWriterEmitter(Records).run(OS);
break;
case GenARMDecoder:
- ARMDecoderEmitter(Records).run(Out.os());
+ ARMDecoderEmitter(Records).run(OS);
break;
case GenAsmMatcher:
- AsmMatcherEmitter(Records).run(Out.os());
- break;
- case GenClangAttrClasses:
- ClangAttrClassEmitter(Records).run(Out.os());
- break;
- case GenClangAttrImpl:
- ClangAttrImplEmitter(Records).run(Out.os());
- break;
- case GenClangAttrList:
- ClangAttrListEmitter(Records).run(Out.os());
- break;
- case GenClangAttrPCHRead:
- ClangAttrPCHReadEmitter(Records).run(Out.os());
- break;
- case GenClangAttrPCHWrite:
- ClangAttrPCHWriteEmitter(Records).run(Out.os());
- break;
- case GenClangAttrSpellingList:
- ClangAttrSpellingListEmitter(Records).run(Out.os());
- break;
- case GenClangDiagsDefs:
- ClangDiagsDefsEmitter(Records, ClangComponent).run(Out.os());
- break;
- case GenClangDiagGroups:
- ClangDiagGroupsEmitter(Records).run(Out.os());
- break;
- case GenClangDiagsIndexName:
- ClangDiagsIndexNameEmitter(Records).run(Out.os());
- break;
- case GenClangDeclNodes:
- ClangASTNodesEmitter(Records, "Decl", "Decl").run(Out.os());
- ClangDeclContextEmitter(Records).run(Out.os());
- break;
- case GenClangStmtNodes:
- ClangASTNodesEmitter(Records, "Stmt", "").run(Out.os());
- break;
- case GenClangSACheckers:
- ClangSACheckersEmitter(Records).run(Out.os());
+ AsmMatcherEmitter(Records).run(OS);
break;
case GenDisassembler:
- DisassemblerEmitter(Records).run(Out.os());
+ DisassemblerEmitter(Records).run(OS);
break;
case GenPseudoLowering:
- PseudoLoweringEmitter(Records).run(Out.os());
- break;
- case GenOptParserDefs:
- OptParserEmitter(Records, true).run(Out.os());
- break;
- case GenOptParserImpl:
- OptParserEmitter(Records, false).run(Out.os());
+ PseudoLoweringEmitter(Records).run(OS);
break;
case GenDAGISel:
- DAGISelEmitter(Records).run(Out.os());
+ DAGISelEmitter(Records).run(OS);
break;
case GenFastISel:
- FastISelEmitter(Records).run(Out.os());
+ FastISelEmitter(Records).run(OS);
break;
case GenSubtarget:
- SubtargetEmitter(Records).run(Out.os());
+ SubtargetEmitter(Records).run(OS);
break;
case GenIntrinsic:
- IntrinsicEmitter(Records).run(Out.os());
+ IntrinsicEmitter(Records).run(OS);
break;
case GenTgtIntrinsic:
- IntrinsicEmitter(Records, true).run(Out.os());
- break;
- case GenLLVMCConf:
- LLVMCConfigurationEmitter(Records).run(Out.os());
+ IntrinsicEmitter(Records, true).run(OS);
break;
case GenEDInfo:
- EDEmitter(Records).run(Out.os());
- break;
- case GenArmNeon:
- NeonEmitter(Records).run(Out.os());
- break;
- case GenArmNeonSema:
- NeonEmitter(Records).runHeader(Out.os());
- break;
- case GenArmNeonTest:
- NeonEmitter(Records).runTests(Out.os());
+ EDEmitter(Records).run(OS);
break;
case PrintEnums:
{
std::vector<Record*> Recs = Records.getAllDerivedDefinitions(Class);
for (unsigned i = 0, e = Recs.size(); i != e; ++i)
- Out.os() << Recs[i]->getName() << ", ";
- Out.os() << "\n";
+ OS << Recs[i]->getName() << ", ";
+ OS << "\n";
break;
}
case PrintSets:
@@ -371,33 +170,29 @@ int main(int argc, char **argv) {
Sets.addFieldExpander("Set", "Elements");
std::vector<Record*> Recs = Records.getAllDerivedDefinitions("Set");
for (unsigned i = 0, e = Recs.size(); i != e; ++i) {
- Out.os() << Recs[i]->getName() << " = [";
+ OS << Recs[i]->getName() << " = [";
const std::vector<Record*> *Elts = Sets.expand(Recs[i]);
assert(Elts && "Couldn't expand Set instance");
for (unsigned ei = 0, ee = Elts->size(); ei != ee; ++ei)
- Out.os() << ' ' << (*Elts)[ei]->getName();
- Out.os() << " ]\n";
+ OS << ' ' << (*Elts)[ei]->getName();
+ OS << " ]\n";
}
break;
}
default:
assert(1 && "Invalid Action");
- return 1;
+ return true;
}
- // Declare success.
- Out.keep();
- return 0;
-
- } catch (const TGError &Error) {
- PrintError(Error);
- } catch (const std::string &Error) {
- PrintError(Error);
- } catch (const char *Error) {
- PrintError(Error);
- } catch (...) {
- errs() << argv[0] << ": Unknown unexpected exception occurred.\n";
+ return false;
}
+};
+
+int main(int argc, char **argv) {
+ sys::PrintStackTraceOnErrorSignal();
+ PrettyStackTraceProgram X(argc, argv);
+ cl::ParseCommandLineOptions(argc, argv);
- return 1;
+ LLVMTableGenAction Action;
+ return TableGenMain(argv[0], Action);
}
diff --git a/contrib/llvm/utils/TableGen/TableGenBackend.cpp b/contrib/llvm/utils/TableGen/TableGenBackend.cpp
deleted file mode 100644
index b3e33b5..0000000
--- a/contrib/llvm/utils/TableGen/TableGenBackend.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-//===- TableGenBackend.cpp - Base class for TableGen Backends ---*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file provides useful services for TableGen backends...
-//
-//===----------------------------------------------------------------------===//
-
-#include "TableGenBackend.h"
-#include "Record.h"
-using namespace llvm;
-
-void TableGenBackend::EmitSourceFileHeader(const std::string &Desc,
- raw_ostream &OS) const {
- OS << "//===- TableGen'erated file -------------------------------------*-"
- " C++ -*-===//\n//\n// " << Desc << "\n//\n// Automatically generate"
- "d file, do not edit!\n//\n//===------------------------------------"
- "----------------------------------===//\n\n";
-}
-
diff --git a/contrib/llvm/utils/TableGen/TableGenBackend.h b/contrib/llvm/utils/TableGen/TableGenBackend.h
deleted file mode 100644
index 9c2b948..0000000
--- a/contrib/llvm/utils/TableGen/TableGenBackend.h
+++ /dev/null
@@ -1,43 +0,0 @@
-//===- TableGenBackend.h - Base class for TableGen Backends -----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// The TableGenBackend class is provided as a common interface for all TableGen
-// backends. It provides useful services and an standardized interface.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef TABLEGENBACKEND_H
-#define TABLEGENBACKEND_H
-
-#include "llvm/Support/raw_ostream.h"
-#include <string>
-
-namespace llvm {
-
-class Record;
-class RecordKeeper;
-
-struct TableGenBackend {
- virtual ~TableGenBackend() {}
-
- // run - All TableGen backends should implement the run method, which should
- // be the main entry point.
- virtual void run(raw_ostream &OS) = 0;
-
-
-public: // Useful helper routines...
- /// EmitSourceFileHeader - Output a LLVM style file header to the specified
- /// ostream.
- void EmitSourceFileHeader(const std::string &Desc, raw_ostream &OS) const;
-
-};
-
-} // End llvm namespace
-
-#endif
diff --git a/contrib/llvm/utils/TableGen/X86DisassemblerTables.cpp b/contrib/llvm/utils/TableGen/X86DisassemblerTables.cpp
index 7431059..e8c9a48 100644
--- a/contrib/llvm/utils/TableGen/X86DisassemblerTables.cpp
+++ b/contrib/llvm/utils/TableGen/X86DisassemblerTables.cpp
@@ -17,7 +17,7 @@
#include "X86DisassemblerShared.h"
#include "X86DisassemblerTables.h"
-#include "TableGenBackend.h"
+#include "llvm/TableGen/TableGenBackend.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
@@ -32,26 +32,32 @@ using namespace X86Disassembler;
/// @param parent - The class that may be the superset
/// @return - True if child is a subset of parent, false otherwise.
static inline bool inheritsFrom(InstructionContext child,
- InstructionContext parent) {
+ InstructionContext parent,
+ bool VEX_LIG = false) {
if (child == parent)
return true;
switch (parent) {
case IC:
- return true;
+ return(inheritsFrom(child, IC_64BIT) ||
+ inheritsFrom(child, IC_OPSIZE) ||
+ inheritsFrom(child, IC_XD) ||
+ inheritsFrom(child, IC_XS));
case IC_64BIT:
return(inheritsFrom(child, IC_64BIT_REXW) ||
inheritsFrom(child, IC_64BIT_OPSIZE) ||
inheritsFrom(child, IC_64BIT_XD) ||
inheritsFrom(child, IC_64BIT_XS));
case IC_OPSIZE:
- return(inheritsFrom(child, IC_64BIT_OPSIZE));
+ return inheritsFrom(child, IC_64BIT_OPSIZE);
case IC_XD:
- return(inheritsFrom(child, IC_64BIT_XD) ||
- inheritsFrom(child, IC_VEX_XD));
+ return inheritsFrom(child, IC_64BIT_XD);
case IC_XS:
- return(inheritsFrom(child, IC_64BIT_XS) ||
- inheritsFrom(child, IC_VEX_XS));
+ return inheritsFrom(child, IC_64BIT_XS);
+ case IC_XD_OPSIZE:
+ return inheritsFrom(child, IC_64BIT_XD_OPSIZE);
+ case IC_XS_OPSIZE:
+ return inheritsFrom(child, IC_64BIT_XS_OPSIZE);
case IC_64BIT_REXW:
return(inheritsFrom(child, IC_64BIT_REXW_XS) ||
inheritsFrom(child, IC_64BIT_REXW_XD) ||
@@ -62,42 +68,37 @@ static inline bool inheritsFrom(InstructionContext child,
return(inheritsFrom(child, IC_64BIT_REXW_XD));
case IC_64BIT_XS:
return(inheritsFrom(child, IC_64BIT_REXW_XS));
- case IC_64BIT_REXW_XD:
+ case IC_64BIT_XD_OPSIZE:
+ case IC_64BIT_XS_OPSIZE:
return false;
+ case IC_64BIT_REXW_XD:
case IC_64BIT_REXW_XS:
- return false;
case IC_64BIT_REXW_OPSIZE:
return false;
case IC_VEX:
- return(inheritsFrom(child, IC_VEX_XS) ||
- inheritsFrom(child, IC_VEX_XD) ||
- inheritsFrom(child, IC_VEX_L) ||
- inheritsFrom(child, IC_VEX_W) ||
- inheritsFrom(child, IC_VEX_OPSIZE));
+ return inheritsFrom(child, IC_VEX_W) ||
+ (VEX_LIG && inheritsFrom(child, IC_VEX_L));
case IC_VEX_XS:
- return(inheritsFrom(child, IC_VEX_L_XS) ||
- inheritsFrom(child, IC_VEX_W_XS));
+ return inheritsFrom(child, IC_VEX_W_XS) ||
+ (VEX_LIG && inheritsFrom(child, IC_VEX_L_XS));
case IC_VEX_XD:
- return(inheritsFrom(child, IC_VEX_L_XD) ||
- inheritsFrom(child, IC_VEX_W_XD));
- case IC_VEX_L:
- return(inheritsFrom(child, IC_VEX_L_XS) ||
- inheritsFrom(child, IC_VEX_L_XD));
- case IC_VEX_L_XS:
- return false;
- case IC_VEX_L_XD:
- return false;
+ return inheritsFrom(child, IC_VEX_W_XD) ||
+ (VEX_LIG && inheritsFrom(child, IC_VEX_L_XD));
+ case IC_VEX_OPSIZE:
+ return inheritsFrom(child, IC_VEX_W_OPSIZE) ||
+ (VEX_LIG && inheritsFrom(child, IC_VEX_L_OPSIZE));
case IC_VEX_W:
- return(inheritsFrom(child, IC_VEX_W_XS) ||
- inheritsFrom(child, IC_VEX_W_XD) ||
- inheritsFrom(child, IC_VEX_W_OPSIZE));
case IC_VEX_W_XS:
- return false;
case IC_VEX_W_XD:
+ case IC_VEX_W_OPSIZE:
+ return false;
+ case IC_VEX_L:
+ case IC_VEX_L_XS:
+ case IC_VEX_L_XD:
+ case IC_VEX_L_OPSIZE:
return false;
- case IC_VEX_OPSIZE:
- return inheritsFrom(child, IC_VEX_W_OPSIZE);
default:
+ llvm_unreachable("Unknown instruction class");
return false;
}
}
@@ -515,6 +516,8 @@ void DisassemblerTables::emitContextTable(raw_ostream &o, uint32_t &i) const {
o << "IC_VEX_XD";
else if ((index & ATTR_VEX) && (index & ATTR_XS))
o << "IC_VEX_XS";
+ else if (index & ATTR_VEX)
+ o << "IC_VEX";
else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && (index & ATTR_XS))
o << "IC_64BIT_REXW_XS";
else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && (index & ATTR_XD))
@@ -522,6 +525,10 @@ void DisassemblerTables::emitContextTable(raw_ostream &o, uint32_t &i) const {
else if ((index & ATTR_64BIT) && (index & ATTR_REXW) &&
(index & ATTR_OPSIZE))
o << "IC_64BIT_REXW_OPSIZE";
+ else if ((index & ATTR_64BIT) && (index & ATTR_XD) && (index & ATTR_OPSIZE))
+ o << "IC_64BIT_XD_OPSIZE";
+ else if ((index & ATTR_64BIT) && (index & ATTR_XS) && (index & ATTR_OPSIZE))
+ o << "IC_64BIT_XS_OPSIZE";
else if ((index & ATTR_64BIT) && (index & ATTR_XS))
o << "IC_64BIT_XS";
else if ((index & ATTR_64BIT) && (index & ATTR_XD))
@@ -532,14 +539,16 @@ void DisassemblerTables::emitContextTable(raw_ostream &o, uint32_t &i) const {
o << "IC_64BIT_REXW";
else if ((index & ATTR_64BIT))
o << "IC_64BIT";
+ else if ((index & ATTR_XS) && (index & ATTR_OPSIZE))
+ o << "IC_XS_OPSIZE";
+ else if ((index & ATTR_XD) && (index & ATTR_OPSIZE))
+ o << "IC_XD_OPSIZE";
else if (index & ATTR_XS)
o << "IC_XS";
else if (index & ATTR_XD)
o << "IC_XD";
else if (index & ATTR_OPSIZE)
o << "IC_OPSIZE";
- else if (index & ATTR_VEX)
- o << "IC_VEX";
else
o << "IC";
@@ -616,8 +625,11 @@ void DisassemblerTables::setTableFields(ModRMDecision &decision,
if(newInfo.filtered)
continue; // filtered instructions get lowest priority
- if(previousInfo.name == "NOOP")
- continue; // special case for XCHG32ar and NOOP
+ if(previousInfo.name == "NOOP" && (newInfo.name == "XCHG16ar" ||
+ newInfo.name == "XCHG32ar" ||
+ newInfo.name == "XCHG32ar64" ||
+ newInfo.name == "XCHG64ar"))
+ continue; // special case for XCHG*ar and NOOP
if (outranks(previousInfo.insnContext, newInfo.insnContext))
continue;
@@ -643,14 +655,19 @@ void DisassemblerTables::setTableFields(OpcodeType type,
InstructionContext insnContext,
uint8_t opcode,
const ModRMFilter &filter,
- InstrUID uid) {
+ InstrUID uid,
+ bool is32bit,
+ bool ignoresVEX_L) {
unsigned index;
ContextDecision &decision = *Tables[type];
for (index = 0; index < IC_max; ++index) {
+ if (is32bit && inheritsFrom((InstructionContext)index, IC_64BIT))
+ continue;
+
if (inheritsFrom((InstructionContext)index,
- InstructionSpecifiers[uid].insnContext))
+ InstructionSpecifiers[uid].insnContext, ignoresVEX_L))
setTableFields(decision.opcodeDecisions[index].modRMDecisions[opcode],
filter,
uid,
diff --git a/contrib/llvm/utils/TableGen/X86DisassemblerTables.h b/contrib/llvm/utils/TableGen/X86DisassemblerTables.h
index d16ebfc..e148cd2 100644
--- a/contrib/llvm/utils/TableGen/X86DisassemblerTables.h
+++ b/contrib/llvm/utils/TableGen/X86DisassemblerTables.h
@@ -260,11 +260,15 @@ public:
/// @param filter - The ModRMFilter that decides which ModR/M byte values
/// correspond to the desired instruction.
/// @param uid - The unique ID of the instruction.
+ /// @param is32bit - Instructon is only 32-bit
+ /// @param ignoresVEX_L - Instruction ignores VEX.L
void setTableFields(OpcodeType type,
InstructionContext insnContext,
uint8_t opcode,
const ModRMFilter &filter,
- InstrUID uid);
+ InstrUID uid,
+ bool is32bit,
+ bool ignoresVEX_L);
/// specForUID - Returns the instruction specifier for a given unique
/// instruction ID. Used when resolving collisions.
diff --git a/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp b/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp
index ea3bb70..cae8237 100644
--- a/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp
+++ b/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp
@@ -68,7 +68,7 @@ namespace X86Local {
DC = 7, DD = 8, DE = 9, DF = 10,
XD = 11, XS = 12,
T8 = 13, P_TA = 14,
- A6 = 15, A7 = 16
+ A6 = 15, A7 = 16, TF = 17
};
}
@@ -217,6 +217,7 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables,
HasVEXPrefix = Rec->getValueAsBit("hasVEXPrefix");
HasVEX_4VPrefix = Rec->getValueAsBit("hasVEX_4VPrefix");
HasVEX_WPrefix = Rec->getValueAsBit("hasVEX_WPrefix");
+ IgnoresVEX_L = Rec->getValueAsBit("ignoresVEX_L");
HasLockPrefix = Rec->getValueAsBit("hasLockPrefix");
IsCodeGenOnly = Rec->getValueAsBit("isCodeGenOnly");
@@ -225,15 +226,21 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables,
Operands = &insn.Operands.OperandList;
- IsSSE = HasOpSizePrefix && (Name.find("16") == Name.npos);
+ IsSSE = (HasOpSizePrefix && (Name.find("16") == Name.npos)) ||
+ (Name.find("CRC32") != Name.npos);
HasFROperands = hasFROperands();
HasVEX_LPrefix = has256BitOperands() || Rec->getValueAsBit("hasVEX_L");
// Check for 64-bit inst which does not require REX
+ Is32Bit = false;
Is64Bit = false;
// FIXME: Is there some better way to check for In64BitMode?
std::vector<Record*> Predicates = Rec->getValueAsListOfDefs("Predicates");
for (unsigned i = 0, e = Predicates.size(); i != e; ++i) {
+ if (Predicates[i]->getName().find("32Bit") != Name.npos) {
+ Is32Bit = true;
+ break;
+ }
if (Predicates[i]->getName().find("64Bit") != Name.npos) {
Is64Bit = true;
break;
@@ -249,6 +256,8 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables,
Rec->getName() == "REX64_PREFIX" ||
Rec->getName().find("VMREAD64") != Name.npos ||
Rec->getName().find("VMWRITE64") != Name.npos ||
+ Rec->getName().find("INVEPT64") != Name.npos ||
+ Rec->getName().find("INVVPID64") != Name.npos ||
Rec->getName().find("MOV64") != Name.npos ||
Rec->getName().find("PUSH64") != Name.npos ||
Rec->getName().find("POP64") != Name.npos;
@@ -257,7 +266,7 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables,
}
void RecognizableInstr::processInstr(DisassemblerTables &tables,
- const CodeGenInstruction &insn,
+ const CodeGenInstruction &insn,
InstrUID uid)
{
// Ignore "asm parser only" instructions.
@@ -276,7 +285,9 @@ InstructionContext RecognizableInstr::insnContext() const {
InstructionContext insnContext;
if (HasVEX_4VPrefix || HasVEXPrefix) {
- if (HasOpSizePrefix && HasVEX_LPrefix)
+ if (HasVEX_LPrefix && HasVEX_WPrefix)
+ llvm_unreachable("Don't support VEX.L and VEX.W together");
+ else if (HasOpSizePrefix && HasVEX_LPrefix)
insnContext = IC_VEX_L_OPSIZE;
else if (HasOpSizePrefix && HasVEX_WPrefix)
insnContext = IC_VEX_W_OPSIZE;
@@ -303,13 +314,19 @@ InstructionContext RecognizableInstr::insnContext() const {
} else if (Is64Bit || HasREX_WPrefix) {
if (HasREX_WPrefix && HasOpSizePrefix)
insnContext = IC_64BIT_REXW_OPSIZE;
+ else if (HasOpSizePrefix &&
+ (Prefix == X86Local::XD || Prefix == X86Local::TF))
+ insnContext = IC_64BIT_XD_OPSIZE;
+ else if (HasOpSizePrefix && Prefix == X86Local::XS)
+ insnContext = IC_64BIT_XS_OPSIZE;
else if (HasOpSizePrefix)
insnContext = IC_64BIT_OPSIZE;
else if (HasREX_WPrefix && Prefix == X86Local::XS)
insnContext = IC_64BIT_REXW_XS;
- else if (HasREX_WPrefix && Prefix == X86Local::XD)
+ else if (HasREX_WPrefix &&
+ (Prefix == X86Local::XD || Prefix == X86Local::TF))
insnContext = IC_64BIT_REXW_XD;
- else if (Prefix == X86Local::XD)
+ else if (Prefix == X86Local::XD || Prefix == X86Local::TF)
insnContext = IC_64BIT_XD;
else if (Prefix == X86Local::XS)
insnContext = IC_64BIT_XS;
@@ -318,11 +335,16 @@ InstructionContext RecognizableInstr::insnContext() const {
else
insnContext = IC_64BIT;
} else {
- if (HasOpSizePrefix)
+ if (HasOpSizePrefix &&
+ (Prefix == X86Local::XD || Prefix == X86Local::TF))
+ insnContext = IC_XD_OPSIZE;
+ else if (HasOpSizePrefix && Prefix == X86Local::XS)
+ insnContext = IC_XS_OPSIZE;
+ else if (HasOpSizePrefix)
insnContext = IC_OPSIZE;
- else if (Prefix == X86Local::XD)
+ else if (Prefix == X86Local::XD || Prefix == X86Local::TF)
insnContext = IC_XD;
- else if (Prefix == X86Local::XS)
+ else if (Prefix == X86Local::XS || Prefix == X86Local::REP)
insnContext = IC_XS;
else
insnContext = IC;
@@ -342,20 +364,13 @@ RecognizableInstr::filter_ret RecognizableInstr::filter() const {
return FILTER_STRONG;
if (Form == X86Local::Pseudo ||
- IsCodeGenOnly)
+ (IsCodeGenOnly && Name.find("_REV") == Name.npos))
return FILTER_STRONG;
if (Form == X86Local::MRMInitReg)
return FILTER_STRONG;
- // TEMPORARY pending bug fixes
-
- if (Name.find("VMOVDQU") != Name.npos ||
- Name.find("VMOVDQA") != Name.npos ||
- Name.find("VROUND") != Name.npos)
- return FILTER_STRONG;
-
// Filter out artificial instructions
if (Name.find("TAILJMP") != Name.npos ||
@@ -401,7 +416,7 @@ RecognizableInstr::filter_ret RecognizableInstr::filter() const {
// Filter out alternate forms of AVX instructions
if (Name.find("_alt") != Name.npos ||
Name.find("XrYr") != Name.npos ||
- Name.find("r64r") != Name.npos ||
+ (Name.find("r64r") != Name.npos && Name.find("r64r64") == Name.npos) ||
Name.find("_64mr") != Name.npos ||
Name.find("Xrr") != Name.npos ||
Name.find("rr64") != Name.npos)
@@ -623,20 +638,43 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) {
case X86Local::MRMDestReg:
// Operand 1 is a register operand in the R/M field.
// Operand 2 is a register operand in the Reg/Opcode field.
+ // - In AVX, there is a register operand in the VEX.vvvv field here -
// Operand 3 (optional) is an immediate.
- assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 &&
- "Unexpected number of operands for MRMDestRegFrm");
+ if (HasVEX_4VPrefix)
+ assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 4 &&
+ "Unexpected number of operands for MRMDestRegFrm with VEX_4V");
+ else
+ assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 &&
+ "Unexpected number of operands for MRMDestRegFrm");
+
HANDLE_OPERAND(rmRegister)
+
+ if (HasVEX_4VPrefix)
+ // FIXME: In AVX, the register below becomes the one encoded
+ // in ModRMVEX and the one above the one in the VEX.VVVV field
+ HANDLE_OPERAND(vvvvRegister)
+
HANDLE_OPERAND(roRegister)
HANDLE_OPTIONAL(immediate)
break;
case X86Local::MRMDestMem:
// Operand 1 is a memory operand (possibly SIB-extended)
// Operand 2 is a register operand in the Reg/Opcode field.
+ // - In AVX, there is a register operand in the VEX.vvvv field here -
// Operand 3 (optional) is an immediate.
- assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 &&
- "Unexpected number of operands for MRMDestMemFrm");
+ if (HasVEX_4VPrefix)
+ assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 4 &&
+ "Unexpected number of operands for MRMDestMemFrm with VEX_4V");
+ else
+ assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 &&
+ "Unexpected number of operands for MRMDestMemFrm");
HANDLE_OPERAND(memory)
+
+ if (HasVEX_4VPrefix)
+ // FIXME: In AVX, the register below becomes the one encoded
+ // in ModRMVEX and the one above the one in the VEX.VVVV field
+ HANDLE_OPERAND(vvvvRegister)
+
HANDLE_OPERAND(roRegister)
HANDLE_OPTIONAL(immediate)
break;
@@ -805,6 +843,7 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
opcodeToSet = Opcode;
break;
case X86Local::T8:
+ case X86Local::TF:
opcodeType = THREEBYTE_38;
if (needsModRMForDecode(Form))
filter = new ModFilter(isRegFormat(Form));
@@ -855,6 +894,7 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
}
opcodeToSet = 0xd8 + (Prefix - X86Local::D8);
break;
+ case X86Local::REP:
default:
opcodeType = ONEBYTE;
switch (Opcode) {
@@ -926,7 +966,7 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
insnContext(),
currentOpcode,
*filter,
- UID);
+ UID, Is32Bit, IgnoresVEX_L);
Spec->modifierType = MODIFIER_OPCODE;
Spec->modifierBase = opcodeToSet;
@@ -936,14 +976,14 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
insnContext(),
opcodeToSet,
*filter,
- UID);
+ UID, Is32Bit, IgnoresVEX_L);
}
} else {
tables.setTableFields(opcodeType,
insnContext(),
opcodeToSet,
*filter,
- UID);
+ UID, Is32Bit, IgnoresVEX_L);
Spec->modifierType = MODIFIER_NONE;
Spec->modifierBase = opcodeToSet;
@@ -984,6 +1024,7 @@ OperandType RecognizableInstr::typeFromString(const std::string &s,
TYPE("i32mem", TYPE_Mv)
TYPE("i32imm", TYPE_IMMv)
TYPE("i32i8imm", TYPE_IMM32)
+ TYPE("u32u8imm", TYPE_IMM32)
TYPE("GR32", TYPE_Rv)
TYPE("i64mem", TYPE_Mv)
TYPE("i64i32imm", TYPE_IMM64)
@@ -1029,6 +1070,9 @@ OperandType RecognizableInstr::typeFromString(const std::string &s,
TYPE("offset32", TYPE_MOFFS32)
TYPE("offset64", TYPE_MOFFS64)
TYPE("VR256", TYPE_XMM256)
+ TYPE("GR16_NOAX", TYPE_Rv)
+ TYPE("GR32_NOAX", TYPE_Rv)
+ TYPE("GR64_NOAX", TYPE_R64)
errs() << "Unhandled type string " << s << "\n";
llvm_unreachable("Unhandled type string");
}
@@ -1044,6 +1088,7 @@ OperandEncoding RecognizableInstr::immediateEncodingFromString
ENCODING("i16imm", ENCODING_IW)
}
ENCODING("i32i8imm", ENCODING_IB)
+ ENCODING("u32u8imm", ENCODING_IB)
ENCODING("SSECC", ENCODING_IB)
ENCODING("i16imm", ENCODING_Iv)
ENCODING("i16i8imm", ENCODING_IB)
@@ -1097,6 +1142,8 @@ OperandEncoding RecognizableInstr::roRegisterEncodingFromString
OperandEncoding RecognizableInstr::vvvvRegisterEncodingFromString
(const std::string &s,
bool hasOpSizePrefix) {
+ ENCODING("GR32", ENCODING_VVVV)
+ ENCODING("GR64", ENCODING_VVVV)
ENCODING("FR32", ENCODING_VVVV)
ENCODING("FR64", ENCODING_VVVV)
ENCODING("VR128", ENCODING_VVVV)
@@ -1169,6 +1216,9 @@ OperandEncoding RecognizableInstr::opcodeModifierEncodingFromString
ENCODING("GR64", ENCODING_RO)
ENCODING("GR16", ENCODING_Rv)
ENCODING("GR8", ENCODING_RB)
+ ENCODING("GR16_NOAX", ENCODING_Rv)
+ ENCODING("GR32_NOAX", ENCODING_Rv)
+ ENCODING("GR64_NOAX", ENCODING_RO)
errs() << "Unhandled opcode modifier encoding " << s << "\n";
llvm_unreachable("Unhandled opcode modifier encoding");
}
diff --git a/contrib/llvm/utils/TableGen/X86RecognizableInstr.h b/contrib/llvm/utils/TableGen/X86RecognizableInstr.h
index 677d9f0..4441597 100644
--- a/contrib/llvm/utils/TableGen/X86RecognizableInstr.h
+++ b/contrib/llvm/utils/TableGen/X86RecognizableInstr.h
@@ -20,8 +20,8 @@
#include "X86DisassemblerTables.h"
#include "CodeGenTarget.h"
-#include "Record.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/ADT/SmallVector.h"
@@ -60,12 +60,16 @@ private:
bool HasVEX_WPrefix;
/// Inferred from the operands; indicates whether the L bit in the VEX prefix is set
bool HasVEX_LPrefix;
+ // The ignoreVEX_L field from the record
+ bool IgnoresVEX_L;
/// The hasLockPrefix field from the record
bool HasLockPrefix;
/// The isCodeGenOnly filed from the record
bool IsCodeGenOnly;
- // Whether the instruction has the predicate "Mode64Bit"
+ // Whether the instruction has the predicate "In64BitMode"
bool Is64Bit;
+ // Whether the instruction has the predicate "In32BitMode"
+ bool Is32Bit;
/// The instruction name as listed in the tables
std::string Name;
OpenPOWER on IntegriCloud