diff options
Diffstat (limited to 'contrib/llvm/utils/TableGen')
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<n>' - 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<Ty>' - 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; |