diff options
Diffstat (limited to 'utils')
-rw-r--r-- | utils/TableGen/ClangASTNodesEmitter.cpp | 61 | ||||
-rw-r--r-- | utils/TableGen/ClangASTNodesEmitter.h | 84 | ||||
-rw-r--r-- | utils/TableGen/ClangAttrEmitter.cpp | 175 | ||||
-rw-r--r-- | utils/TableGen/ClangAttrEmitter.h | 153 | ||||
-rw-r--r-- | utils/TableGen/ClangDiagnosticsEmitter.cpp | 294 | ||||
-rw-r--r-- | utils/TableGen/ClangDiagnosticsEmitter.h | 54 | ||||
-rw-r--r-- | utils/TableGen/ClangSACheckersEmitter.cpp | 8 | ||||
-rw-r--r-- | utils/TableGen/ClangSACheckersEmitter.h | 31 | ||||
-rw-r--r-- | utils/TableGen/NeonEmitter.cpp | 233 | ||||
-rw-r--r-- | utils/TableGen/NeonEmitter.h | 210 | ||||
-rw-r--r-- | utils/TableGen/OptParserEmitter.cpp | 13 | ||||
-rw-r--r-- | utils/TableGen/OptParserEmitter.h | 34 | ||||
-rw-r--r-- | utils/TableGen/TableGen.cpp | 58 | ||||
-rw-r--r-- | utils/TableGen/TableGenBackends.h | 56 | ||||
-rwxr-xr-x | utils/analyzer/CmpRuns.py | 135 | ||||
-rw-r--r-- | utils/analyzer/SATestAdd.py | 2 | ||||
-rw-r--r-- | utils/analyzer/SATestBuild.py | 33 | ||||
-rw-r--r-- | utils/analyzer/SumTimerInfo.py | 75 | ||||
-rwxr-xr-x | utils/analyzer/reducer.pl | 65 | ||||
-rw-r--r-- | utils/clang-completion-mode.el | 40 | ||||
-rw-r--r-- | utils/clangVisualizers.txt | 313 |
21 files changed, 1318 insertions, 809 deletions
diff --git a/utils/TableGen/ClangASTNodesEmitter.cpp b/utils/TableGen/ClangASTNodesEmitter.cpp index d9d5a3c..c51ca96 100644 --- a/utils/TableGen/ClangASTNodesEmitter.cpp +++ b/utils/TableGen/ClangASTNodesEmitter.cpp @@ -11,10 +11,58 @@ // //===----------------------------------------------------------------------===// -#include "ClangASTNodesEmitter.h" +#include "llvm/TableGen/Record.h" +#include "llvm/TableGen/TableGenBackend.h" +#include <cctype> +#include <map> #include <set> +#include <string> using namespace llvm; +/// ClangASTNodesEmitter - The top-level class emits .inc files containing +/// declarations of Clang statements. +/// +namespace { +class ClangASTNodesEmitter { + // 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); +}; +} // end anonymous namespace + //===----------------------------------------------------------------------===// // Statement Node Tables (.inc file) generation. //===----------------------------------------------------------------------===// @@ -124,7 +172,15 @@ void ClangASTNodesEmitter::run(raw_ostream &OS) { OS << "#undef ABSTRACT_" << macroName(Root.getName()) << "\n"; } -void ClangDeclContextEmitter::run(raw_ostream &OS) { +namespace clang { +void EmitClangASTNodes(RecordKeeper &RK, raw_ostream &OS, + const std::string &N, const std::string &S) { + ClangASTNodesEmitter(RK, N, S).run(OS); +} + +// Emits and addendum to a .inc file to enumerate the clang declaration +// contexts. +void EmitClangDeclContext(RecordKeeper &Records, raw_ostream &OS) { // FIXME: Find a .td file format to allow for this to be represented better. OS << "#ifndef DECL_CONTEXT\n"; @@ -166,3 +222,4 @@ void ClangDeclContextEmitter::run(raw_ostream &OS) { OS << "#undef DECL_CONTEXT\n"; OS << "#undef DECL_CONTEXT_BASE\n"; } +} // end namespace clang diff --git a/utils/TableGen/ClangASTNodesEmitter.h b/utils/TableGen/ClangASTNodesEmitter.h deleted file mode 100644 index edd9316..0000000 --- a/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 "llvm/TableGen/TableGenBackend.h" -#include "llvm/TableGen/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/utils/TableGen/ClangAttrEmitter.cpp b/utils/TableGen/ClangAttrEmitter.cpp index 7951fc4..1b1a478 100644 --- a/utils/TableGen/ClangAttrEmitter.cpp +++ b/utils/TableGen/ClangAttrEmitter.cpp @@ -11,12 +11,13 @@ // //===----------------------------------------------------------------------===// -#include "ClangAttrEmitter.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/TableGen/Record.h" +#include "llvm/TableGen/StringMatcher.h" +#include "llvm/TableGen/TableGenBackend.h" #include <algorithm> #include <cctype> -#include <set> using namespace llvm; @@ -660,7 +661,10 @@ static void writeAvailabilityValue(raw_ostream &OS) { << " OS << \""; } -void ClangAttrClassEmitter::run(raw_ostream &OS) { +namespace clang { + +// Emits the class definitions for attributes. +void EmitClangAttrClass(RecordKeeper &Records, 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"; @@ -670,6 +674,10 @@ void ClangAttrClassEmitter::run(raw_ostream &OS) { for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(); i != e; ++i) { Record &R = **i; + + if (!R.getValueAsBit("ASTNode")) + continue; + const std::string &SuperName = R.getSuperClasses().back()->getName(); OS << "class " << R.getName() << "Attr : public " << SuperName << " {\n"; @@ -745,7 +753,8 @@ void ClangAttrClassEmitter::run(raw_ostream &OS) { OS << "#endif\n"; } -void ClangAttrImplEmitter::run(raw_ostream &OS) { +// Emits the class method definitions for attributes. +void EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS) { OS << "// This file is generated by TableGen. Do not edit.\n\n"; std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); @@ -754,8 +763,12 @@ void ClangAttrImplEmitter::run(raw_ostream &OS) { for (; i != e; ++i) { Record &R = **i; + + if (!R.getValueAsBit("ASTNode")) + continue; + std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args"); - std::vector<StringRef> Spellings = getValueAsListOfStrings(R, "Spellings"); + std::vector<Record*> Spellings = R.getValueAsListOfDefs("Spellings"); std::vector<Argument*> Args; for (ri = ArgRecords.begin(), re = ArgRecords.end(); ri != re; ++ri) Args.push_back(createArgument(**ri, R.getName())); @@ -775,9 +788,10 @@ void ClangAttrImplEmitter::run(raw_ostream &OS) { OS << "void " << R.getName() << "Attr::printPretty(" << "llvm::raw_ostream &OS, ASTContext &Ctx) const {\n"; if (Spellings.begin() != Spellings.end()) { - OS << " OS << \" __attribute__((" << *Spellings.begin(); + std::string Spelling = (*Spellings.begin())->getValueAsString("Name"); + OS << " OS << \" __attribute__((" << Spelling; if (Args.size()) OS << "("; - if (*Spellings.begin()=="availability") { + if (Spelling == "availability") { writeAvailabilityValue(OS); } else { for (ai = Args.begin(); ai != ae; ++ai) { @@ -792,20 +806,29 @@ void ClangAttrImplEmitter::run(raw_ostream &OS) { } } +} // end namespace clang + 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) + for(--e; i != e; ++i) { + if (!(*i)->getValueAsBit("ASTNode")) + continue; + OS << Class << "(" << (*i)->getName() << ")\n"; + } OS << "LAST_" << Class << "(" << (*i)->getName() << ")\n\n"; } } -void ClangAttrListEmitter::run(raw_ostream &OS) { +namespace clang { + +// Emits the enumeration list for attributes. +void EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS) { OS << "// This file is generated by TableGen. Do not edit.\n\n"; OS << "#ifndef LAST_ATTR\n"; @@ -835,6 +858,9 @@ void ClangAttrListEmitter::run(raw_ostream &OS) { NonInhAttrs, InhAttrs, InhParamAttrs; for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(); i != e; ++i) { + if (!(*i)->getValueAsBit("ASTNode")) + continue; + if ((*i)->isSubClassOf(InhParamClass)) InhParamAttrs.push_back(*i); else if ((*i)->isSubClassOf(InhClass)) @@ -854,7 +880,8 @@ void ClangAttrListEmitter::run(raw_ostream &OS) { OS << "#undef ATTR\n"; } -void ClangAttrPCHReadEmitter::run(raw_ostream &OS) { +// Emits the code to read an attribute from a precompiled header. +void EmitClangAttrPCHRead(RecordKeeper &Records, raw_ostream &OS) { OS << "// This file is generated by TableGen. Do not edit.\n\n"; Record *InhClass = Records.getClass("InheritableAttr"); @@ -870,6 +897,9 @@ void ClangAttrPCHReadEmitter::run(raw_ostream &OS) { OS << " break;\n"; for (; i != e; ++i) { Record &R = **i; + if (!R.getValueAsBit("ASTNode")) + continue; + OS << " case attr::" << R.getName() << ": {\n"; if (R.isSubClassOf(InhClass)) OS << " bool isInherited = Record[Idx++];\n"; @@ -894,7 +924,8 @@ void ClangAttrPCHReadEmitter::run(raw_ostream &OS) { OS << " }\n"; } -void ClangAttrPCHWriteEmitter::run(raw_ostream &OS) { +// Emits the code to write an attribute to a precompiled header. +void EmitClangAttrPCHWrite(RecordKeeper &Records, 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; @@ -905,6 +936,8 @@ void ClangAttrPCHWriteEmitter::run(raw_ostream &OS) { OS << " break;\n"; for (; i != e; ++i) { Record &R = **i; + if (!R.getValueAsBit("ASTNode")) + continue; OS << " case attr::" << R.getName() << ": {\n"; Args = R.getValueAsListOfDefs("Args"); if (R.isSubClassOf(InhClass) || !Args.empty()) @@ -920,7 +953,8 @@ void ClangAttrPCHWriteEmitter::run(raw_ostream &OS) { OS << " }\n"; } -void ClangAttrSpellingListEmitter::run(raw_ostream &OS) { +// Emits the list of spellings for attributes. +void EmitClangAttrSpellingList(RecordKeeper &Records, raw_ostream &OS) { OS << "// This file is generated by TableGen. Do not edit.\n\n"; std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); @@ -928,17 +962,17 @@ void ClangAttrSpellingListEmitter::run(raw_ostream &OS) { for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); I != E; ++I) { Record &Attr = **I; - std::vector<StringRef> Spellings = getValueAsListOfStrings(Attr, "Spellings"); + std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings"); - for (std::vector<StringRef>::const_iterator I = Spellings.begin(), E = Spellings.end(); I != E; ++I) { - StringRef Spelling = *I; - OS << ".Case(\"" << Spelling << "\", true)\n"; + for (std::vector<Record*>::const_iterator I = Spellings.begin(), E = Spellings.end(); I != E; ++I) { + OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", true)\n"; } } } -void ClangAttrLateParsedListEmitter::run(raw_ostream &OS) { +// Emits the LateParsed property for attributes. +void EmitClangAttrLateParsedList(RecordKeeper &Records, raw_ostream &OS) { OS << "// This file is generated by TableGen. Do not edit.\n\n"; std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); @@ -950,19 +984,23 @@ void ClangAttrLateParsedListEmitter::run(raw_ostream &OS) { bool LateParsed = Attr.getValueAsBit("LateParsed"); if (LateParsed) { - std::vector<StringRef> Spellings = - getValueAsListOfStrings(Attr, "Spellings"); + std::vector<Record*> Spellings = + Attr.getValueAsListOfDefs("Spellings"); - for (std::vector<StringRef>::const_iterator I = Spellings.begin(), + // FIXME: Handle non-GNU attributes + for (std::vector<Record*>::const_iterator I = Spellings.begin(), E = Spellings.end(); I != E; ++I) { - OS << ".Case(\"" << (*I) << "\", " << LateParsed << ")\n"; + if ((*I)->getValueAsString("Variety") != "GNU") + continue; + OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", " + << LateParsed << ")\n"; } } } } - -void ClangAttrTemplateInstantiateEmitter::run(raw_ostream &OS) { +// Emits code to instantiate dependent attributes on templates. +void EmitClangAttrTemplateInstantiate(RecordKeeper &Records, raw_ostream &OS) { OS << "// This file is generated by TableGen. Do not edit.\n\n"; std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); @@ -979,8 +1017,18 @@ void ClangAttrTemplateInstantiateEmitter::run(raw_ostream &OS) { for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); I != E; ++I) { Record &R = **I; + if (!R.getValueAsBit("ASTNode")) + continue; OS << " case attr::" << R.getName() << ": {\n"; + bool ShouldClone = R.getValueAsBit("Clone"); + + if (!ShouldClone) { + OS << " return NULL;\n"; + OS << " }\n"; + continue; + } + OS << " const " << R.getName() << "Attr *A = cast<" << R.getName() << "Attr>(At);\n"; bool TDependent = R.getValueAsBit("TemplateDependent"); @@ -1024,7 +1072,8 @@ void ClangAttrTemplateInstantiateEmitter::run(raw_ostream &OS) { << "} // end namespace clang\n"; } -void ClangAttrParsedAttrListEmitter::run(raw_ostream &OS) { +// Emits the list of parsed attributes. +void EmitClangAttrParsedAttrList(RecordKeeper &Records, raw_ostream &OS) { OS << "// This file is generated by TableGen. Do not edit.\n\n"; OS << "#ifndef PARSED_ATTR\n"; @@ -1032,61 +1081,85 @@ void ClangAttrParsedAttrListEmitter::run(raw_ostream &OS) { OS << "#endif\n\n"; std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); - std::set<StringRef> ProcessedAttrs; for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); I != E; ++I) { Record &Attr = **I; bool SemaHandler = Attr.getValueAsBit("SemaHandler"); - + bool DistinctSpellings = Attr.getValueAsBit("DistinctSpellings"); + if (SemaHandler) { - std::vector<StringRef> Spellings = - getValueAsListOfStrings(Attr, "Spellings"); - - for (std::vector<StringRef>::const_iterator I = Spellings.begin(), - E = Spellings.end(); I != E; ++I) { - StringRef AttrName = *I; + if (DistinctSpellings) { + std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings"); + + for (std::vector<Record*>::const_iterator I = Spellings.begin(), + E = Spellings.end(); I != E; ++I) { + std::string AttrName = (*I)->getValueAsString("Name"); - AttrName = NormalizeAttrName(AttrName); - // skip if a normalized version has been processed. - if (ProcessedAttrs.find(AttrName) != ProcessedAttrs.end()) - continue; - else - ProcessedAttrs.insert(AttrName); + StringRef Spelling = NormalizeAttrName(AttrName); + OS << "PARSED_ATTR(" << Spelling << ")\n"; + } + } else { + StringRef AttrName = Attr.getName(); + AttrName = NormalizeAttrName(AttrName); OS << "PARSED_ATTR(" << AttrName << ")\n"; } } } } -void ClangAttrParsedAttrKindsEmitter::run(raw_ostream &OS) { +// Emits the kind list of parsed attributes +void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) { OS << "// This file is generated by TableGen. Do not edit.\n\n"; - + OS << "\n"; + std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); + std::vector<StringMatcher::StringPair> Matches; for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); I != E; ++I) { Record &Attr = **I; bool SemaHandler = Attr.getValueAsBit("SemaHandler"); - - if (SemaHandler) { - std::vector<StringRef> Spellings = - getValueAsListOfStrings(Attr, "Spellings"); + bool Ignored = Attr.getValueAsBit("Ignored"); + bool DistinctSpellings = Attr.getValueAsBit("DistinctSpellings"); + if (SemaHandler || Ignored) { + std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings"); - for (std::vector<StringRef>::const_iterator I = Spellings.begin(), + for (std::vector<Record*>::const_iterator I = Spellings.begin(), E = Spellings.end(); I != E; ++I) { - StringRef AttrName = *I, Spelling = *I; - - AttrName = NormalizeAttrName(AttrName); - Spelling = NormalizeAttrSpelling(Spelling); + std::string RawSpelling = (*I)->getValueAsString("Name"); + StringRef AttrName = NormalizeAttrName(DistinctSpellings + ? StringRef(RawSpelling) + : StringRef(Attr.getName())); + + SmallString<64> Spelling; + if ((*I)->getValueAsString("Variety") == "CXX11") { + Spelling += (*I)->getValueAsString("Namespace"); + Spelling += "::"; + } + Spelling += NormalizeAttrSpelling(RawSpelling); - OS << ".Case(\"" << Spelling << "\", " << "AT_" << AttrName << ")\n"; + if (SemaHandler) + Matches.push_back( + StringMatcher::StringPair( + StringRef(Spelling), + "return AttributeList::AT_" + AttrName.str() + ";")); + else + Matches.push_back( + StringMatcher::StringPair( + StringRef(Spelling), + "return AttributeList::IgnoredAttribute;")); } } } + + OS << "static AttributeList::Kind getAttrKind(StringRef Name) {\n"; + StringMatcher("Name", Matches, OS).Emit(); + OS << "return AttributeList::UnknownAttribute;\n" + << "}\n"; } - +} // end namespace clang diff --git a/utils/TableGen/ClangAttrEmitter.h b/utils/TableGen/ClangAttrEmitter.h deleted file mode 100644 index d119a09..0000000 --- a/utils/TableGen/ClangAttrEmitter.h +++ /dev/null @@ -1,153 +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 "llvm/TableGen/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); -}; - -/// ClangAttrLateParsedListEmitter emits the LateParsed property for attributes -/// for clang. -class ClangAttrLateParsedListEmitter : public TableGenBackend { - RecordKeeper &Records; - - public: - explicit ClangAttrLateParsedListEmitter(RecordKeeper &R) - : Records(R) - {} - - void run(raw_ostream &OS); -}; - -/// ClangAttrTemplateInstantiateEmitter emits code to instantiate dependent -/// attributes on templates. -class ClangAttrTemplateInstantiateEmitter : public TableGenBackend { - RecordKeeper &Records; - - public: - explicit ClangAttrTemplateInstantiateEmitter(RecordKeeper &R) - : Records(R) - {} - - void run(raw_ostream &OS); -}; - -/// ClangAttrParsedAttrListEmitter emits the list of parsed attributes -/// for clang. -class ClangAttrParsedAttrListEmitter : public TableGenBackend { - RecordKeeper &Records; - -public: - explicit ClangAttrParsedAttrListEmitter(RecordKeeper &R) - : Records(R) - {} - - void run(raw_ostream &OS); -}; - -/// ClangAttrParsedAttrKindsEmitter emits the kind list of parsed attributes -/// for clang. -class ClangAttrParsedAttrKindsEmitter : public TableGenBackend { - RecordKeeper &Records; - -public: - explicit ClangAttrParsedAttrKindsEmitter(RecordKeeper &R) - : Records(R) - {} - - void run(raw_ostream &OS); -}; - -} - -#endif diff --git a/utils/TableGen/ClangDiagnosticsEmitter.cpp b/utils/TableGen/ClangDiagnosticsEmitter.cpp index 8a49619..8615d2d 100644 --- a/utils/TableGen/ClangDiagnosticsEmitter.cpp +++ b/utils/TableGen/ClangDiagnosticsEmitter.cpp @@ -11,16 +11,19 @@ // //===----------------------------------------------------------------------===// -#include "ClangDiagnosticsEmitter.h" -#include "llvm/TableGen/Record.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/Compiler.h" +#include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/StringMap.h" #include "llvm/ADT/SmallString.h" -#include <map> +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/Optional.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" +#include "llvm/TableGen/Record.h" +#include "llvm/TableGen/TableGenBackend.h" #include <algorithm> +#include <cctype> #include <functional> +#include <map> #include <set> using namespace llvm; @@ -78,7 +81,7 @@ static std::string getDiagnosticCategory(const Record *R, DiagGroupParents); if (!CatName.empty()) return CatName; } - + // If the diagnostic itself has a category, get it. return R->getValueAsString("CategoryName"); } @@ -135,6 +138,8 @@ static void groupDiagnostics(const std::vector<Record*> &Diags, const Record *R = Diags[i]; DefInit *DI = dynamic_cast<DefInit*>(R->getValueInit("Group")); if (DI == 0) continue; + assert(R->getValueAsDef("Class")->getName() != "CLASS_NOTE" && + "Note can't be in a DiagGroup"); std::string GroupName = DI->getDef()->getValueAsString("GroupName"); DiagsInGroup[GroupName].DiagsInGroup.push_back(R); } @@ -158,10 +163,201 @@ static void groupDiagnostics(const std::vector<Record*> &Diags, } //===----------------------------------------------------------------------===// +// Infer members of -Wpedantic. +//===----------------------------------------------------------------------===// + +typedef std::vector<const Record *> RecordVec; +typedef llvm::DenseSet<const Record *> RecordSet; +typedef llvm::PointerUnion<RecordVec*, RecordSet*> VecOrSet; + +namespace { +class InferPedantic { + typedef llvm::DenseMap<const Record*, + std::pair<unsigned, llvm::Optional<unsigned> > > GMap; + + DiagGroupParentMap &DiagGroupParents; + const std::vector<Record*> &Diags; + const std::vector<Record*> DiagGroups; + std::map<std::string, GroupInfo> &DiagsInGroup; + llvm::DenseSet<const Record*> DiagsSet; + GMap GroupCount; +public: + InferPedantic(DiagGroupParentMap &DiagGroupParents, + const std::vector<Record*> &Diags, + const std::vector<Record*> &DiagGroups, + std::map<std::string, GroupInfo> &DiagsInGroup) + : DiagGroupParents(DiagGroupParents), + Diags(Diags), + DiagGroups(DiagGroups), + DiagsInGroup(DiagsInGroup) {} + + /// Compute the set of diagnostics and groups that are immediately + /// in -Wpedantic. + void compute(VecOrSet DiagsInPedantic, + VecOrSet GroupsInPedantic); + +private: + /// Determine whether a group is a subgroup of another group. + bool isSubGroupOfGroup(const Record *Group, + llvm::StringRef RootGroupName); + + /// Determine if the diagnostic is an extension. + bool isExtension(const Record *Diag); + + /// Determine if the diagnostic is off by default. + bool isOffByDefault(const Record *Diag); + + /// Increment the count for a group, and transitively marked + /// parent groups when appropriate. + void markGroup(const Record *Group); + + /// Return true if the diagnostic is in a pedantic group. + bool groupInPedantic(const Record *Group, bool increment = false); +}; +} // end anonymous namespace + +bool InferPedantic::isSubGroupOfGroup(const Record *Group, + llvm::StringRef GName) { + + const std::string &GroupName = Group->getValueAsString("GroupName"); + if (GName == GroupName) + return true; + + const std::vector<Record*> &Parents = DiagGroupParents.getParents(Group); + for (unsigned i = 0, e = Parents.size(); i != e; ++i) + if (isSubGroupOfGroup(Parents[i], GName)) + return true; + + return false; +} + +/// Determine if the diagnostic is an extension. +bool InferPedantic::isExtension(const Record *Diag) { + const std::string &ClsName = Diag->getValueAsDef("Class")->getName(); + return ClsName == "CLASS_EXTENSION"; +} + +bool InferPedantic::isOffByDefault(const Record *Diag) { + const std::string &DefMap = Diag->getValueAsDef("DefaultMapping")->getName(); + return DefMap == "MAP_IGNORE"; +} + +bool InferPedantic::groupInPedantic(const Record *Group, bool increment) { + GMap::mapped_type &V = GroupCount[Group]; + // Lazily compute the threshold value for the group count. + if (!V.second.hasValue()) { + const GroupInfo &GI = DiagsInGroup[Group->getValueAsString("GroupName")]; + V.second = GI.SubGroups.size() + GI.DiagsInGroup.size(); + } + + if (increment) + ++V.first; + + // Consider a group in -Wpendatic IFF if has at least one diagnostic + // or subgroup AND all of those diagnostics and subgroups are covered + // by -Wpedantic via our computation. + return V.first != 0 && V.first == V.second.getValue(); +} + +void InferPedantic::markGroup(const Record *Group) { + // If all the diagnostics and subgroups have been marked as being + // covered by -Wpedantic, increment the count of parent groups. Once the + // group's count is equal to the number of subgroups and diagnostics in + // that group, we can safely add this group to -Wpedantic. + if (groupInPedantic(Group, /* increment */ true)) { + const std::vector<Record*> &Parents = DiagGroupParents.getParents(Group); + for (unsigned i = 0, e = Parents.size(); i != e; ++i) + markGroup(Parents[i]); + } +} + +void InferPedantic::compute(VecOrSet DiagsInPedantic, + VecOrSet GroupsInPedantic) { + // All extensions that are not on by default are implicitly in the + // "pedantic" group. For those that aren't explicitly included in -Wpedantic, + // mark them for consideration to be included in -Wpedantic directly. + for (unsigned i = 0, e = Diags.size(); i != e; ++i) { + Record *R = Diags[i]; + if (isExtension(R) && isOffByDefault(R)) { + DiagsSet.insert(R); + if (DefInit *Group = dynamic_cast<DefInit*>(R->getValueInit("Group"))) { + const Record *GroupRec = Group->getDef(); + if (!isSubGroupOfGroup(GroupRec, "pedantic")) { + markGroup(GroupRec); + } + } + } + } + + // Compute the set of diagnostics that are directly in -Wpedantic. We + // march through Diags a second time to ensure the results are emitted + // in deterministic order. + for (unsigned i = 0, e = Diags.size(); i != e; ++i) { + Record *R = Diags[i]; + if (!DiagsSet.count(R)) + continue; + // Check if the group is implicitly in -Wpedantic. If so, + // the diagnostic should not be directly included in the -Wpedantic + // diagnostic group. + if (DefInit *Group = dynamic_cast<DefInit*>(R->getValueInit("Group"))) + if (groupInPedantic(Group->getDef())) + continue; + + // The diagnostic is not included in a group that is (transitively) in + // -Wpedantic. Include it in -Wpedantic directly. + if (RecordVec *V = DiagsInPedantic.dyn_cast<RecordVec*>()) + V->push_back(R); + else { + DiagsInPedantic.get<RecordSet*>()->insert(R); + } + } + + if (!GroupsInPedantic) + return; + + // Compute the set of groups that are directly in -Wpedantic. We + // march through the groups to ensure the results are emitted + /// in a deterministc order. + for (unsigned i = 0, ei = DiagGroups.size(); i != ei; ++i) { + Record *Group = DiagGroups[i]; + if (!groupInPedantic(Group)) + continue; + + unsigned ParentsInPedantic = 0; + const std::vector<Record*> &Parents = DiagGroupParents.getParents(Group); + for (unsigned j = 0, ej = Parents.size(); j != ej; ++j) { + if (groupInPedantic(Parents[j])) + ++ParentsInPedantic; + } + // If all the parents are in -Wpedantic, this means that this diagnostic + // group will be indirectly included by -Wpedantic already. In that + // case, do not add it directly to -Wpedantic. If the group has no + // parents, obviously it should go into -Wpedantic. + if (Parents.size() > 0 && ParentsInPedantic == Parents.size()) + continue; + + if (RecordVec *V = GroupsInPedantic.dyn_cast<RecordVec*>()) + V->push_back(Group); + else { + GroupsInPedantic.get<RecordSet*>()->insert(Group); + } + } +} + +//===----------------------------------------------------------------------===// // Warning Tables (.inc file) generation. //===----------------------------------------------------------------------===// -void ClangDiagsDefsEmitter::run(raw_ostream &OS) { +static bool isError(const Record &Diag) { + const std::string &ClsName = Diag.getValueAsDef("Class")->getName(); + return ClsName == "CLASS_ERROR"; +} + +/// ClangDiagsDefsEmitter - The top-level class emits .def files containing +/// declarations of Clang diagnostics. +namespace clang { +void EmitClangDiagsDefs(RecordKeeper &Records, raw_ostream &OS, + const std::string &Component) { // Write the #if guard if (!Component.empty()) { std::string ComponentName = StringRef(Component).upper(); @@ -184,8 +380,25 @@ void ClangDiagsDefsEmitter::run(raw_ostream &OS) { DiagCategoryIDMap CategoryIDs(Records); DiagGroupParentMap DGParentMap(Records); + // Compute the set of diagnostics that are in -Wpedantic. + RecordSet DiagsInPedantic; + InferPedantic inferPedantic(DGParentMap, Diags, DiagGroups, DiagsInGroup); + inferPedantic.compute(&DiagsInPedantic, (RecordVec*)0); + for (unsigned i = 0, e = Diags.size(); i != e; ++i) { const Record &R = *Diags[i]; + + // Check if this is an error that is accidentally in a warning + // group. + if (isError(R)) { + if (DefInit *Group = dynamic_cast<DefInit*>(R.getValueInit("Group"))) { + const Record *GroupRec = Group->getDef(); + const std::string &GroupName = GroupRec->getValueAsString("GroupName"); + throw "Error " + R.getName() + " cannot be in a warning group [" + + GroupName + "]"; + } + } + // Filter by component. if (!Component.empty() && Component != R.getValueAsString("Component")) continue; @@ -205,6 +418,11 @@ void ClangDiagsDefsEmitter::run(raw_ostream &OS) { DiagsInGroup.find(DI->getDef()->getValueAsString("GroupName")); assert(I != DiagsInGroup.end()); OS << ", " << I->second.IDNo; + } else if (DiagsInPedantic.count(&R)) { + std::map<std::string, GroupInfo>::iterator I = + DiagsInGroup.find("pedantic"); + assert(I != DiagsInGroup.end() && "pedantic group not defined"); + OS << ", " << I->second.IDNo; } else { OS << ", 0"; } @@ -242,6 +460,7 @@ void ClangDiagsDefsEmitter::run(raw_ostream &OS) { OS << ")\n"; } } +} // end namespace clang //===----------------------------------------------------------------------===// // Warning Group Tables generation @@ -255,11 +474,12 @@ static std::string getDiagCategoryEnum(llvm::StringRef name) { enumName += isalnum(*I) ? *I : '_'; return enumName.str(); } - -void ClangDiagGroupsEmitter::run(raw_ostream &OS) { + +namespace clang { +void EmitClangDiagGroups(RecordKeeper &Records, raw_ostream &OS) { // Compute a mapping from a DiagGroup to all of its parents. DiagGroupParentMap DGParentMap(Records); - + std::vector<Record*> Diags = Records.getAllDerivedDefinitions("Diagnostic"); @@ -268,7 +488,15 @@ void ClangDiagGroupsEmitter::run(raw_ostream &OS) { std::map<std::string, GroupInfo> DiagsInGroup; groupDiagnostics(Diags, DiagGroups, DiagsInGroup); - + + // All extensions are implicitly in the "pedantic" group. Record the + // implicit set of groups in the "pedantic" group, and use this information + // later when emitting the group information for Pedantic. + RecordVec DiagsInPedantic; + RecordVec GroupsInPedantic; + InferPedantic inferPedantic(DGParentMap, Diags, DiagGroups, DiagsInGroup); + inferPedantic.compute(&DiagsInPedantic, &GroupsInPedantic); + // Walk through the groups emitting an array for each diagnostic of the diags // that are mapped to. OS << "\n#ifdef GET_DIAG_ARRAYS\n"; @@ -276,17 +504,23 @@ void ClangDiagGroupsEmitter::run(raw_ostream &OS) { for (std::map<std::string, GroupInfo>::iterator I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I) { MaxLen = std::max(MaxLen, (unsigned)I->first.size()); - + const bool IsPedantic = I->first == "pedantic"; + std::vector<const Record*> &V = I->second.DiagsInGroup; - if (!V.empty()) { + if (!V.empty() || (IsPedantic && !DiagsInPedantic.empty())) { OS << "static const short DiagArray" << I->second.IDNo << "[] = { "; for (unsigned i = 0, e = V.size(); i != e; ++i) OS << "diag::" << V[i]->getName() << ", "; + // Emit the diagnostics implicitly in "pedantic". + if (IsPedantic) { + for (unsigned i = 0, e = DiagsInPedantic.size(); i != e; ++i) + OS << "diag::" << DiagsInPedantic[i]->getName() << ", "; + } OS << "-1 };\n"; } const std::vector<std::string> &SubGroups = I->second.SubGroups; - if (!SubGroups.empty()) { + if (!SubGroups.empty() || (IsPedantic && !GroupsInPedantic.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 = @@ -294,6 +528,18 @@ void ClangDiagGroupsEmitter::run(raw_ostream &OS) { assert(RI != DiagsInGroup.end() && "Referenced without existing?"); OS << RI->second.IDNo << ", "; } + // Emit the groups implicitly in "pedantic". + if (IsPedantic) { + for (unsigned i = 0, e = GroupsInPedantic.size(); i != e; ++i) { + const std::string &GroupName = + GroupsInPedantic[i]->getValueAsString("GroupName"); + std::map<std::string, GroupInfo>::iterator RI = + DiagsInGroup.find(GroupName); + assert(RI != DiagsInGroup.end() && "Referenced without existing?"); + OS << RI->second.IDNo << ", "; + } + } + OS << "-1 };\n"; } } @@ -313,15 +559,22 @@ void ClangDiagGroupsEmitter::run(raw_ostream &OS) { throw "Invalid character in diagnostic group '" + I->first + "'"; OS.write_escaped(I->first) << "\"," << std::string(MaxLen-I->first.size()+1, ' '); - + + // Special handling for 'pedantic'. + const bool IsPedantic = I->first == "pedantic"; + // Diagnostics in the group. - if (I->second.DiagsInGroup.empty()) + const bool hasDiags = !I->second.DiagsInGroup.empty() || + (IsPedantic && !DiagsInPedantic.empty()); + if (!hasDiags) OS << "0, "; else OS << "DiagArray" << I->second.IDNo << ", "; // Subgroups. - if (I->second.SubGroups.empty()) + const bool hasSubGroups = !I->second.SubGroups.empty() || + (IsPedantic && !GroupsInPedantic.empty()); + if (!hasSubGroups) OS << 0; else OS << "DiagSubGroup" << I->second.IDNo; @@ -337,6 +590,7 @@ void ClangDiagGroupsEmitter::run(raw_ostream &OS) { OS << "CATEGORY(\"" << *I << "\", " << getDiagCategoryEnum(*I) << ")\n"; OS << "#endif // GET_CATEGORY_TABLE\n\n"; } +} // end namespace clang //===----------------------------------------------------------------------===// // Diagnostic name index generation @@ -364,7 +618,8 @@ struct RecordIndexElementSorter : } // end anonymous namespace. -void ClangDiagsIndexNameEmitter::run(raw_ostream &OS) { +namespace clang { +void EmitClangDiagsIndexName(RecordKeeper &Records, raw_ostream &OS) { const std::vector<Record*> &Diags = Records.getAllDerivedDefinitions("Diagnostic"); @@ -383,3 +638,4 @@ void ClangDiagsIndexNameEmitter::run(raw_ostream &OS) { OS << "DIAG_NAME_INDEX(" << R.Name << ")\n"; } } +} // end namespace clang diff --git a/utils/TableGen/ClangDiagnosticsEmitter.h b/utils/TableGen/ClangDiagnosticsEmitter.h deleted file mode 100644 index 73d3c4d..0000000 --- a/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 "llvm/TableGen/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/utils/TableGen/ClangSACheckersEmitter.cpp b/utils/TableGen/ClangSACheckersEmitter.cpp index 423b68a..5a0db50 100644 --- a/utils/TableGen/ClangSACheckersEmitter.cpp +++ b/utils/TableGen/ClangSACheckersEmitter.cpp @@ -11,9 +11,9 @@ // //===----------------------------------------------------------------------===// -#include "ClangSACheckersEmitter.h" -#include "llvm/TableGen/Record.h" #include "llvm/ADT/DenseSet.h" +#include "llvm/TableGen/Record.h" +#include "llvm/TableGen/TableGenBackend.h" #include <map> #include <string> using namespace llvm; @@ -93,7 +93,8 @@ static void addPackageToCheckerGroup(const Record *package, const Record *group, addPackageToCheckerGroup(*I, group, recordGroupMap); } -void ClangSACheckersEmitter::run(raw_ostream &OS) { +namespace clang { +void EmitClangSACheckers(RecordKeeper &Records, 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) @@ -317,3 +318,4 @@ void ClangSACheckersEmitter::run(raw_ostream &OS) { } OS << "#endif // GET_CHECKNAME_TABLE\n\n"; } +} // end namespace clang diff --git a/utils/TableGen/ClangSACheckersEmitter.h b/utils/TableGen/ClangSACheckersEmitter.h deleted file mode 100644 index 5a0e148..0000000 --- a/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 "llvm/TableGen/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/utils/TableGen/NeonEmitter.cpp b/utils/TableGen/NeonEmitter.cpp index e6f2e53..6837306 100644 --- a/utils/TableGen/NeonEmitter.cpp +++ b/utils/TableGen/NeonEmitter.cpp @@ -23,16 +23,206 @@ // //===----------------------------------------------------------------------===// -#include "NeonEmitter.h" -#include "llvm/TableGen/Error.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringMap.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/TableGen/Error.h" +#include "llvm/TableGen/Record.h" +#include "llvm/TableGen/TableGenBackend.h" #include <string> - using namespace llvm; +enum OpKind { + OpNone, + OpUnavailable, + 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 +}; + +/// NeonTypeFlags - Flags to identify the types for overloaded Neon +/// builtins. These must be kept in sync with the flags in +/// include/clang/Basic/TargetBuiltins.h. +namespace { +class NeonTypeFlags { + enum { + EltTypeMask = 0xf, + UnsignedFlag = 0x10, + QuadFlag = 0x20 + }; + uint32_t Flags; + +public: + enum EltType { + Int8, + Int16, + Int32, + Int64, + Poly8, + Poly16, + Float16, + Float32 + }; + + NeonTypeFlags(unsigned F) : Flags(F) {} + NeonTypeFlags(EltType ET, bool IsUnsigned, bool IsQuad) : Flags(ET) { + if (IsUnsigned) + Flags |= UnsignedFlag; + if (IsQuad) + Flags |= QuadFlag; + } + + uint32_t getFlags() const { return Flags; } +}; +} // end anonymous namespace + +namespace { +class NeonEmitter { + RecordKeeper &Records; + StringMap<OpKind> OpMap; + DenseMap<Record*, ClassKind> ClassMap; + +public: + NeonEmitter(RecordKeeper &R) : Records(R) { + OpMap["OP_NONE"] = OpNone; + OpMap["OP_UNAVAILABLE"] = OpUnavailable; + 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 anonymous namespace + /// 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 @@ -1012,7 +1202,7 @@ static std::string GenIntrinsic(const std::string &name, StringRef outTypeStr, StringRef inTypeStr, OpKind kind, ClassKind classKind) { assert(!proto.empty() && ""); - bool define = UseMacro(proto); + bool define = UseMacro(proto) && kind != OpUnavailable; std::string s; // static always inline + return type @@ -1040,9 +1230,11 @@ static std::string GenIntrinsic(const std::string &name, if (define) { s += " __extension__ ({ \\\n "; s += GenMacroLocals(proto, inTypeStr); - } else { - s += " { \\\n "; - } + } else if (kind == OpUnavailable) { + s += " __attribute__((unavailable));\n"; + return s; + } else + s += " {\n "; if (kind != OpNone) s += GenOpString(kind, proto, outTypeStr); @@ -1238,7 +1430,7 @@ static unsigned RangeFromType(const char mod, StringRef typestr) { /// 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. +/// 3. the SemaChecking code for validation of intrinsic immediate arguments. void NeonEmitter::runHeader(raw_ostream &OS) { std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst"); @@ -1312,7 +1504,7 @@ void NeonEmitter::runHeader(raw_ostream &OS) { throw TGError(R->getLoc(), "Builtin has no class kind"); int si = -1, qi = -1; - unsigned mask = 0, qmask = 0; + uint64_t 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; @@ -1320,10 +1512,10 @@ void NeonEmitter::runHeader(raw_ostream &OS) { if (quad) { qi = ti; - qmask |= 1 << GetNeonEnum(Proto, TypeVec[ti]); + qmask |= 1ULL << GetNeonEnum(Proto, TypeVec[ti]); } else { si = ti; - mask |= 1 << GetNeonEnum(Proto, TypeVec[ti]); + mask |= 1ULL << GetNeonEnum(Proto, TypeVec[ti]); } } @@ -1360,7 +1552,7 @@ void NeonEmitter::runHeader(raw_ostream &OS) { if (mask) { OS << "case ARM::BI__builtin_neon_" << MangleName(name, TypeVec[si], ClassB) - << ": mask = " << "0x" << utohexstr(mask); + << ": mask = " << "0x" << utohexstr(mask) << "ULL"; if (PtrArgNum >= 0) OS << "; PtrArgNum = " << PtrArgNum; if (HasConstPtr) @@ -1370,7 +1562,7 @@ void NeonEmitter::runHeader(raw_ostream &OS) { if (qmask) { OS << "case ARM::BI__builtin_neon_" << MangleName(name, TypeVec[qi], ClassB) - << ": mask = " << "0x" << utohexstr(qmask); + << ": mask = " << "0x" << utohexstr(qmask) << "ULL"; if (PtrArgNum >= 0) OS << "; PtrArgNum = " << PtrArgNum; if (HasConstPtr) @@ -1505,7 +1697,7 @@ static std::string GenTest(const std::string &name, s.push_back(arg); comma = ", "; } - s += ") { \\\n "; + s += ") {\n "; if (proto[0] != 'v') s += "return "; @@ -1551,6 +1743,8 @@ void NeonEmitter::runTests(raw_ostream &OS) { ParseTypes(R, Types, TypeVec); OpKind kind = OpMap[R->getValueAsDef("Operand")->getName()]; + if (kind == OpUnavailable) + continue; for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) { if (kind == OpReinterpret) { bool outQuad = false; @@ -1572,3 +1766,14 @@ void NeonEmitter::runTests(raw_ostream &OS) { } } +namespace clang { +void EmitNeon(RecordKeeper &Records, raw_ostream &OS) { + NeonEmitter(Records).run(OS); +} +void EmitNeonSema(RecordKeeper &Records, raw_ostream &OS) { + NeonEmitter(Records).runHeader(OS); +} +void EmitNeonTest(RecordKeeper &Records, raw_ostream &OS) { + NeonEmitter(Records).runTests(OS); +} +} // End namespace clang diff --git a/utils/TableGen/NeonEmitter.h b/utils/TableGen/NeonEmitter.h deleted file mode 100644 index dec7451..0000000 --- a/utils/TableGen/NeonEmitter.h +++ /dev/null @@ -1,210 +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 "llvm/TableGen/Record.h" -#include "llvm/TableGen/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 -}; - -/// NeonTypeFlags - Flags to identify the types for overloaded Neon -/// builtins. These must be kept in sync with the flags in -/// include/clang/Basic/TargetBuiltins.h. -class NeonTypeFlags { - enum { - EltTypeMask = 0xf, - UnsignedFlag = 0x10, - QuadFlag = 0x20 - }; - uint32_t Flags; - -public: - enum EltType { - Int8, - Int16, - Int32, - Int64, - Poly8, - Poly16, - Float16, - Float32 - }; - - NeonTypeFlags(unsigned F) : Flags(F) {} - NeonTypeFlags(EltType ET, bool IsUnsigned, bool IsQuad) : Flags(ET) { - if (IsUnsigned) - Flags |= UnsignedFlag; - if (IsQuad) - Flags |= QuadFlag; - } - - uint32_t getFlags() const { return Flags; } -}; - -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/utils/TableGen/OptParserEmitter.cpp b/utils/TableGen/OptParserEmitter.cpp index dea22d3..b0431a9 100644 --- a/utils/TableGen/OptParserEmitter.cpp +++ b/utils/TableGen/OptParserEmitter.cpp @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#include "OptParserEmitter.h" #include "llvm/TableGen/Record.h" +#include "llvm/TableGen/TableGenBackend.h" #include "llvm/ADT/STLExtras.h" using namespace llvm; @@ -69,16 +69,20 @@ static raw_ostream &write_cstring(raw_ostream &OS, llvm::StringRef Str) { return OS; } -void OptParserEmitter::run(raw_ostream &OS) { +/// 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. +namespace clang { +void EmitOptParser(RecordKeeper &Records, raw_ostream &OS, bool GenDefs) { // 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); + emitSourceFileHeader("Option Parsing Definitions", OS); else - EmitSourceFileHeader("Option Parsing Table", OS); + emitSourceFileHeader("Option Parsing Table", OS); array_pod_sort(Opts.begin(), Opts.end(), CompareOptionRecords); if (GenDefs) { @@ -192,3 +196,4 @@ void OptParserEmitter::run(raw_ostream &OS) { } } } +} // end namespace clang diff --git a/utils/TableGen/OptParserEmitter.h b/utils/TableGen/OptParserEmitter.h deleted file mode 100644 index ca667ca..0000000 --- a/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 "llvm/TableGen/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/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp index 5ff88db..d3408ed 100644 --- a/utils/TableGen/TableGen.cpp +++ b/utils/TableGen/TableGen.cpp @@ -11,12 +11,7 @@ // //===----------------------------------------------------------------------===// -#include "ClangASTNodesEmitter.h" -#include "ClangAttrEmitter.h" -#include "ClangDiagnosticsEmitter.h" -#include "ClangSACheckersEmitter.h" -#include "NeonEmitter.h" -#include "OptParserEmitter.h" +#include "TableGenBackends.h" // Declares all backends. #include "llvm/Support/CommandLine.h" #include "llvm/Support/PrettyStackTrace.h" @@ -27,6 +22,7 @@ #include "llvm/TableGen/TableGenAction.h" using namespace llvm; +using namespace clang; enum ActionType { GenClangAttrClasses, @@ -42,6 +38,7 @@ enum ActionType { GenClangDiagsDefs, GenClangDiagGroups, GenClangDiagsIndexName, + GenClangCommentNodes, GenClangDeclNodes, GenClangStmtNodes, GenClangSACheckers, @@ -90,6 +87,8 @@ namespace { clEnumValN(GenClangDiagsIndexName, "gen-clang-diags-index-name", "Generate Clang diagnostic name index"), + clEnumValN(GenClangCommentNodes, "gen-clang-comment-nodes", + "Generate Clang AST comment nodes"), clEnumValN(GenClangDeclNodes, "gen-clang-decl-nodes", "Generate Clang AST declaration nodes"), clEnumValN(GenClangStmtNodes, "gen-clang-stmt-nodes", @@ -114,68 +113,71 @@ public: bool operator()(raw_ostream &OS, RecordKeeper &Records) { switch (Action) { case GenClangAttrClasses: - ClangAttrClassEmitter(Records).run(OS); + EmitClangAttrClass(Records, OS); break; case GenClangAttrImpl: - ClangAttrImplEmitter(Records).run(OS); + EmitClangAttrImpl(Records, OS); break; case GenClangAttrList: - ClangAttrListEmitter(Records).run(OS); + EmitClangAttrList(Records, OS); break; case GenClangAttrPCHRead: - ClangAttrPCHReadEmitter(Records).run(OS); + EmitClangAttrPCHRead(Records, OS); break; case GenClangAttrPCHWrite: - ClangAttrPCHWriteEmitter(Records).run(OS); + EmitClangAttrPCHWrite(Records, OS); break; case GenClangAttrSpellingList: - ClangAttrSpellingListEmitter(Records).run(OS); + EmitClangAttrSpellingList(Records, OS); break; case GenClangAttrLateParsedList: - ClangAttrLateParsedListEmitter(Records).run(OS); + EmitClangAttrLateParsedList(Records, OS); break; case GenClangAttrTemplateInstantiate: - ClangAttrTemplateInstantiateEmitter(Records).run(OS); + EmitClangAttrTemplateInstantiate(Records, OS); break; case GenClangAttrParsedAttrList: - ClangAttrParsedAttrListEmitter(Records).run(OS); + EmitClangAttrParsedAttrList(Records, OS); break; case GenClangAttrParsedAttrKinds: - ClangAttrParsedAttrKindsEmitter(Records).run(OS); + EmitClangAttrParsedAttrKinds(Records, OS); break; case GenClangDiagsDefs: - ClangDiagsDefsEmitter(Records, ClangComponent).run(OS); + EmitClangDiagsDefs(Records, OS, ClangComponent); break; case GenClangDiagGroups: - ClangDiagGroupsEmitter(Records).run(OS); + EmitClangDiagGroups(Records, OS); break; case GenClangDiagsIndexName: - ClangDiagsIndexNameEmitter(Records).run(OS); + EmitClangDiagsIndexName(Records, OS); + break; + case GenClangCommentNodes: + EmitClangASTNodes(Records, OS, "Comment", ""); break; case GenClangDeclNodes: - ClangASTNodesEmitter(Records, "Decl", "Decl").run(OS); - ClangDeclContextEmitter(Records).run(OS); + EmitClangASTNodes(Records, OS, "Decl", "Decl"); + EmitClangDeclContext(Records, OS); break; case GenClangStmtNodes: - ClangASTNodesEmitter(Records, "Stmt", "").run(OS); + EmitClangASTNodes(Records, OS, "Stmt", ""); break; case GenClangSACheckers: - ClangSACheckersEmitter(Records).run(OS); + EmitClangSACheckers(Records, OS); break; case GenOptParserDefs: - OptParserEmitter(Records, true).run(OS); + EmitOptParser(Records, OS, true); break; case GenOptParserImpl: - OptParserEmitter(Records, false).run(OS); + EmitOptParser(Records, OS, false); break; case GenArmNeon: - NeonEmitter(Records).run(OS); + EmitNeon(Records, OS); break; case GenArmNeonSema: - NeonEmitter(Records).runHeader(OS); + EmitNeonSema(Records, OS); break; case GenArmNeonTest: - NeonEmitter(Records).runTests(OS); + EmitNeonTest(Records, OS); break; } diff --git a/utils/TableGen/TableGenBackends.h b/utils/TableGen/TableGenBackends.h new file mode 100644 index 0000000..779de7c --- /dev/null +++ b/utils/TableGen/TableGenBackends.h @@ -0,0 +1,56 @@ +//===- TableGenBackends.h - Declarations for Clang TableGen Backends ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declarations for all of the Clang TableGen +// backends. A "TableGen backend" is just a function. See +// "$LLVM_ROOT/utils/TableGen/TableGenBackends.h" for more info. +// +//===----------------------------------------------------------------------===// + +#include <string> + +namespace llvm { + class raw_ostream; + class RecordKeeper; +} + +using llvm::raw_ostream; +using llvm::RecordKeeper; + +namespace clang { + +void EmitClangDeclContext(RecordKeeper &RK, raw_ostream &OS); +void EmitClangASTNodes(RecordKeeper &RK, raw_ostream &OS, + const std::string &N, const std::string &S); + +void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS); +void EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS); +void EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS); +void EmitClangAttrPCHRead(RecordKeeper &Records, raw_ostream &OS); +void EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS); +void EmitClangAttrSpellingList(RecordKeeper &Records, raw_ostream &OS); +void EmitClangAttrLateParsedList(RecordKeeper &Records, raw_ostream &OS); +void EmitClangAttrTemplateInstantiate(RecordKeeper &Records, raw_ostream &OS); +void EmitClangAttrParsedAttrList(RecordKeeper &Records, raw_ostream &OS); +void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS); + +void EmitClangDiagsDefs(RecordKeeper &Records, raw_ostream &OS, + const std::string &Component); +void EmitClangDiagGroups(RecordKeeper &Records, raw_ostream &OS); +void EmitClangDiagsIndexName(RecordKeeper &Records, raw_ostream &OS); + +void EmitClangSACheckers(RecordKeeper &Records, raw_ostream &OS); + +void EmitNeon(RecordKeeper &Records, raw_ostream &OS); +void EmitNeonSema(RecordKeeper &Records, raw_ostream &OS); +void EmitNeonTest(RecordKeeper &Records, raw_ostream &OS); + +void EmitOptParser(RecordKeeper &Records, raw_ostream &OS, bool GenDefs); + +} // end namespace clang diff --git a/utils/analyzer/CmpRuns.py b/utils/analyzer/CmpRuns.py index e68c45df..f2961cf 100755 --- a/utils/analyzer/CmpRuns.py +++ b/utils/analyzer/CmpRuns.py @@ -11,12 +11,67 @@ two perspectives: 2. For use by end users who want to integrate regular static analyzer testing into a buildbot like environment. + +Usage: + + # Load the results of both runs, to obtain lists of the corresponding + # AnalysisDiagnostic objects. + # + # root - the name of the root directory, which will be disregarded when + # determining the source file name + # + resultsA = loadResults(dirA, opts, root, deleteEmpty) + resultsB = loadResults(dirB, opts, root, deleteEmpty) + + # Generate a relation from diagnostics in run A to diagnostics in run B + # to obtain a list of triples (a, b, confidence). + diff = compareResults(resultsA, resultsB) + """ import os import plistlib # +class AnalysisDiagnostic: + def __init__(self, data, report, htmlReport): + self._data = data + self._loc = self._data['location'] + self._report = report + self._htmlReport = htmlReport + + def getFileName(self): + return self._report.run.getSourceName(self._report.files[self._loc['file']]) + + def getLine(self): + return self._loc['line'] + + def getColumn(self): + return self._loc['col'] + + def getCategory(self): + return self._data['category'] + + def getDescription(self): + return self._data['description'] + + def getIssueIdentifier(self) : + id = '' + if 'issue_context' in self._data : + id += self._data['issue_context'] + ":" + if 'issue_hash' in self._data : + id += str(self._data['issue_hash']) + ":" + return id + ":" + self.getFileName() + + def getReport(self): + if self._htmlReport is None: + return " " + return os.path.join(self._report.run.path, self._htmlReport) + + def getReadableName(self): + return '%s:%d:%d, %s: %s' % (self.getFileName(), self.getLine(), + self.getColumn(), self.getCategory(), + self.getDescription()) class multidict: def __init__(self, elts=()): @@ -45,8 +100,9 @@ class multidict: # class CmpOptions: - def __init__(self, verboseLog=None, root=""): - self.root = root + def __init__(self, verboseLog=None, rootA="", rootB=""): + self.rootA = rootA + self.rootB = rootB self.verboseLog = verboseLog class AnalysisReport: @@ -54,49 +110,22 @@ class AnalysisReport: self.run = run self.files = files -class AnalysisDiagnostic: - def __init__(self, data, report, htmlReport): - self.data = data - self.report = report - self.htmlReport = htmlReport - - def getReadableName(self): - loc = self.data['location'] - filename = self.report.run.getSourceName(self.report.files[loc['file']]) - line = loc['line'] - column = loc['col'] - category = self.data['category'] - description = self.data['description'] - - # FIXME: Get a report number based on this key, to 'distinguish' - # reports, or something. - - return '%s:%d:%d, %s: %s' % (filename, line, column, category, - description) - - def getReportData(self): - if self.htmlReport is None: - return " " - return os.path.join(self.report.run.path, self.htmlReport) - # We could also dump the report with: - # return open(os.path.join(self.report.run.path, - # self.htmlReport), "rb").read() - class AnalysisRun: - def __init__(self, path, opts): + def __init__(self, path, root, opts): self.path = path + self.root = root self.reports = [] self.diagnostics = [] self.opts = opts def getSourceName(self, path): - if path.startswith(self.opts.root): - return path[len(self.opts.root):] + if path.startswith(self.root): + return path[len(self.root):] return path -def loadResults(path, opts, deleteEmpty=True): - run = AnalysisRun(path, opts) - +def loadResults(path, opts, root = "", deleteEmpty=True): + run = AnalysisRun(path, root, opts) + for f in os.listdir(path): if (not f.startswith('report') or not f.endswith('plist')): @@ -134,6 +163,9 @@ def loadResults(path, opts, deleteEmpty=True): return run +def cmpAnalysisDiagnostic(d) : + return d.getIssueIdentifier() + def compareResults(A, B): """ compareResults - Generate a relation from diagnostics in run A to @@ -152,14 +184,14 @@ def compareResults(A, B): neqB = [] eltsA = list(A.diagnostics) eltsB = list(B.diagnostics) - eltsA.sort(key = lambda d: d.data) - eltsB.sort(key = lambda d: d.data) + eltsA.sort(key = cmpAnalysisDiagnostic) + eltsB.sort(key = cmpAnalysisDiagnostic) while eltsA and eltsB: a = eltsA.pop() b = eltsB.pop() - if a.data['location'] == b.data['location']: + if (a.getIssueIdentifier() == b.getIssueIdentifier()) : res.append((a, b, 0)) - elif a.data > b.data: + elif a._data > b._data: neqA.append(a) eltsB.append(b) else: @@ -181,10 +213,10 @@ def compareResults(A, B): return res -def cmpScanBuildResults(dirA, dirB, opts, deleteEmpty=True): +def dumpScanBuildResultsDiff(dirA, dirB, opts, deleteEmpty=True): # Load the run results. - resultsA = loadResults(dirA, opts, deleteEmpty) - resultsB = loadResults(dirB, opts, deleteEmpty) + resultsA = loadResults(dirA, opts, opts.rootA, deleteEmpty) + resultsB = loadResults(dirB, opts, opts.rootB, deleteEmpty) # Open the verbose log, if given. if opts.verboseLog: @@ -201,13 +233,13 @@ def cmpScanBuildResults(dirA, dirB, opts, deleteEmpty=True): foundDiffs += 1 if auxLog: print >>auxLog, ("('ADDED', %r, %r)" % (b.getReadableName(), - b.getReportData())) + b.getReport())) elif b is None: print "REMOVED: %r" % a.getReadableName() foundDiffs += 1 if auxLog: print >>auxLog, ("('REMOVED', %r, %r)" % (a.getReadableName(), - a.getReportData())) + a.getReport())) elif confidence: print "CHANGED: %r to %r" % (a.getReadableName(), b.getReadableName()) @@ -216,8 +248,8 @@ def cmpScanBuildResults(dirA, dirB, opts, deleteEmpty=True): print >>auxLog, ("('CHANGED', %r, %r, %r, %r)" % (a.getReadableName(), b.getReadableName(), - a.getReportData(), - b.getReportData())) + a.getReport(), + b.getReport())) else: pass @@ -233,8 +265,11 @@ def cmpScanBuildResults(dirA, dirB, opts, deleteEmpty=True): def main(): from optparse import OptionParser parser = OptionParser("usage: %prog [options] [dir A] [dir B]") - parser.add_option("", "--root", dest="root", - help="Prefix to ignore on source files", + parser.add_option("", "--rootA", dest="rootA", + help="Prefix to ignore on source files for directory A", + action="store", type=str, default="") + parser.add_option("", "--rootB", dest="rootB", + help="Prefix to ignore on source files for directory B", action="store", type=str, default="") parser.add_option("", "--verbose-log", dest="verboseLog", help="Write additional information to LOG [default=None]", @@ -247,7 +282,7 @@ def main(): dirA,dirB = args - cmpScanBuildResults(dirA, dirB, opts) + dumpScanBuildResultsDiff(dirA, dirB, opts) if __name__ == '__main__': main() diff --git a/utils/analyzer/SATestAdd.py b/utils/analyzer/SATestAdd.py index ce64bc8..2d32533 100644 --- a/utils/analyzer/SATestAdd.py +++ b/utils/analyzer/SATestAdd.py @@ -41,7 +41,7 @@ def addNewProject(ID, IsScanBuild) : sys.exit(-1) # Build the project. - SATestBuild.testProject(ID, True, IsScanBuild, Dir) + SATestBuild.testProject(ID, IsScanBuild, IsReferenceBuild=True, Dir=Dir) # Add the project ID to the project map. ProjectMapPath = os.path.join(CurDir, SATestBuild.ProjectMapFile) diff --git a/utils/analyzer/SATestBuild.py b/utils/analyzer/SATestBuild.py index 3fccb9a..fd4bc8a 100644 --- a/utils/analyzer/SATestBuild.py +++ b/utils/analyzer/SATestBuild.py @@ -72,12 +72,10 @@ SBOutputDirReferencePrefix = "Ref" # The list of checkers used during analyzes. # Currently, consists of all the non experimental checkers. -Checkers="experimental.security.taint,core,deadcode,cplusplus,security,unix,osx,cocoa" +Checkers="experimental.security.taint,core,deadcode,security,unix,osx" Verbose = 1 -IsReferenceBuild = False - # Make sure we flush the output after every print statement. class flushfile(object): def __init__(self, f): @@ -100,7 +98,7 @@ def getProjectMapPath(): def getProjectDir(ID): return os.path.join(os.path.abspath(os.curdir), ID) -def getSBOutputDirName() : +def getSBOutputDirName(IsReferenceBuild) : if IsReferenceBuild == True : return SBOutputDirReferencePrefix + SBOutputDirName else : @@ -210,7 +208,7 @@ def runAnalyzePreprocessed(Dir, SBOutputDir): if Failed == False: os.remove(LogFile.name); -def buildProject(Dir, SBOutputDir, IsScanBuild): +def buildProject(Dir, SBOutputDir, IsScanBuild, IsReferenceBuild): TBegin = time.time() BuildLogPath = os.path.join(SBOutputDir, LogFolderName, BuildLogName) @@ -295,7 +293,7 @@ def checkBuild(SBOutputDir): FailuresCopied = NumOfFailuresInSummary Idx = 0 - for FailLogPathI in glob.glob(SBOutputDir + "/*/failures/*.stderr.txt"): + for FailLogPathI in Failures: if Idx >= NumOfFailuresInSummary: break; Idx += 1 @@ -359,7 +357,7 @@ def runCmpResults(Dir): OLD_STDOUT = sys.stdout sys.stdout = Discarder() # Scan the results, delete empty plist files. - NumDiffs = CmpRuns.cmpScanBuildResults(RefDir, NewDir, Opts, False) + NumDiffs = CmpRuns.dumpScanBuildResultsDiff(RefDir, NewDir, Opts, False) sys.stdout = OLD_STDOUT if (NumDiffs > 0) : print "Warning: %r differences in diagnostics. See %s" % \ @@ -373,7 +371,7 @@ def updateSVN(Mode, ProjectsMap): ProjectsMap.seek(0) for I in csv.reader(ProjectsMap): ProjName = I[0] - Path = os.path.join(ProjName, getSBOutputDirName()) + Path = os.path.join(ProjName, getSBOutputDirName(True)) if Mode == "delete": Command = "svn delete %s" % (Path,) @@ -382,7 +380,7 @@ def updateSVN(Mode, ProjectsMap): if Verbose == 1: print " Executing: %s" % (Command,) - check_call(Command, shell=True) + check_call(Command, shell=True) if Mode == "delete": CommitCommand = "svn commit -m \"[analyzer tests] Remove " \ @@ -392,12 +390,12 @@ def updateSVN(Mode, ProjectsMap): "reference results.\"" if Verbose == 1: print " Executing: %s" % (CommitCommand,) - check_call(CommitCommand, shell=True) + check_call(CommitCommand, shell=True) except: print "Error: SVN update failed." sys.exit(-1) -def testProject(ID, IsScanBuild, Dir=None): +def testProject(ID, IsScanBuild, IsReferenceBuild=False, Dir=None): print " \n\n--- Building project %s" % (ID,) TBegin = time.time() @@ -408,10 +406,10 @@ def testProject(ID, IsScanBuild, Dir=None): print " Build directory: %s." % (Dir,) # Set the build results directory. - RelOutputDir = getSBOutputDirName() + RelOutputDir = getSBOutputDirName(IsReferenceBuild) SBOutputDir = os.path.join(Dir, RelOutputDir) - buildProject(Dir, SBOutputDir, IsScanBuild) + buildProject(Dir, SBOutputDir, IsScanBuild, IsReferenceBuild) checkBuild(SBOutputDir) @@ -421,10 +419,7 @@ def testProject(ID, IsScanBuild, Dir=None): print "Completed tests for project %s (time: %.2f)." % \ (ID, (time.time()-TBegin)) -def testAll(InIsReferenceBuild = False, UpdateSVN = False): - global IsReferenceBuild - IsReferenceBuild = InIsReferenceBuild - +def testAll(IsReferenceBuild = False, UpdateSVN = False): PMapFile = open(getProjectMapPath(), "rb") try: # Validate the input. @@ -439,13 +434,13 @@ def testAll(InIsReferenceBuild = False, UpdateSVN = False): # When we are regenerating the reference results, we might need to # update svn. Remove reference results from SVN. if UpdateSVN == True: - assert(InIsReferenceBuild == True); + assert(IsReferenceBuild == True); updateSVN("delete", PMapFile); # Test the projects. PMapFile.seek(0) for I in csv.reader(PMapFile): - testProject(I[0], int(I[1])) + testProject(I[0], int(I[1]), IsReferenceBuild) # Add reference results to SVN. if UpdateSVN == True: diff --git a/utils/analyzer/SumTimerInfo.py b/utils/analyzer/SumTimerInfo.py new file mode 100644 index 0000000..a6731bb --- /dev/null +++ b/utils/analyzer/SumTimerInfo.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python + +""" +Script to Summarize statistics in the scan-build output. + +Statistics are enabled by passing '-internal-stats' option to scan-build +(or '-analyzer-stats' to the analyzer). + +""" + +import string +from operator import itemgetter +import sys + +if __name__ == '__main__': + if len(sys.argv) < 2: + print >> sys.stderr, 'Usage: ', sys.argv[0],\ + 'scan_build_output_file' + sys.exit(-1) + + f = open(sys.argv[1], 'r') + Time = 0.0 + TotalTime = 0.0 + MaxTime = 0.0 + Warnings = 0 + Count = 0 + FunctionsAnalyzed = 0 + ReachableBlocks = 0 + ReachedMaxSteps = 0 + NumSteps = 0 + MaxCFGSize = 0 + Mode = 1 + for line in f: + if ("Miscellaneous Ungrouped Timers" in line) : + Mode = 1 + if (("Analyzer Total Time" in line) and (Mode == 1)) : + s = line.split() + Time = Time + float(s[6]) + Count = Count + 1 + if (float(s[6]) > MaxTime) : + MaxTime = float(s[6]) + if ((("warning generated." in line) or ("warnings generated." in line)) and Mode == 1) : + s = line.split() + Warnings = Warnings + int(s[0]) + if (("The # of functions analysed (as top level)." in line) and (Mode == 1)) : + s = line.split() + FunctionsAnalyzed = FunctionsAnalyzed + int(s[0]) + if (("The % of reachable basic blocks" in line) and (Mode == 1)) : + s = line.split() + ReachableBlocks = ReachableBlocks + int(s[0]) + if (("The # of times we reached the max number of steps." in line) and (Mode == 1)) : + s = line.split() + ReachedMaxSteps = ReachedMaxSteps + int(s[0]) + if (("The maximum number of basic blocks in a function" in line) and (Mode == 1)) : + s = line.split() + if (MaxCFGSize < int(s[0])) : + MaxCFGSize = int(s[0]) + if (("The # of steps executed." in line) and (Mode == 1)) : + s = line.split() + NumSteps = NumSteps + int(s[0]) + if ((") Total" in line) and (Mode == 1)) : + s = line.split() + TotalTime = TotalTime + float(s[6]) + + print "TU Count %d" % (Count) + print "Time %f" % (Time) + print "Warnings %d" % (Warnings) + print "Functions Analyzed %d" % (FunctionsAnalyzed) + print "Reachable Blocks %d" % (ReachableBlocks) + print "Reached Max Steps %d" % (ReachedMaxSteps) + print "Number of Steps %d" % (NumSteps) + print "MaxTime %f" % (MaxTime) + print "TotalTime %f" % (TotalTime) + print "Max CFG Size %d" % (MaxCFGSize) +
\ No newline at end of file diff --git a/utils/analyzer/reducer.pl b/utils/analyzer/reducer.pl new file mode 100755 index 0000000..872f61b --- /dev/null +++ b/utils/analyzer/reducer.pl @@ -0,0 +1,65 @@ +#!/usr/bin/perl -w +use strict; +use File::Temp qw/ tempdir /; +my $prog = "reducer"; + +die "$prog <code file> <error string> [optional command]\n" if ($#ARGV < 0); +my $file = shift @ARGV; +die "$prog: [error] cannot read file $file\n" if (! -r $file); + +my $magic = shift @ARGV; +die "$prog: [error] no error string specified\n" if (! defined $magic); + +# Create a backup of the file. +my $dir = tempdir( CLEANUP => 1 ); +print "$prog: created temporary directory '$dir'\n"; +my $srcFile = "$dir/$file"; +`cp $file $srcFile`; + +# Create the script. +my $scriptFile = "$dir/script"; +open(OUT, ">$scriptFile") or die "$prog: cannot create '$scriptFile'\n"; +my $reduceOut = "$dir/reduceOut"; + +my $command; +if (scalar(@ARGV) > 0) { $command = \@ARGV; } +else { + my $compiler = "clang"; + $command = [$compiler, "-fsyntax-only", "-Wfatal-errors", "-Wno-deprecated-declarations", "-Wimplicit-function-declaration"]; +} +push @$command, $srcFile; +my $commandStr = "@$command"; + +print OUT <<ENDTEXT; +#!/usr/bin/perl -w +use strict; +my \$BAD = 1; +my \$GOOD = 0; +`rm -f $reduceOut`; +my \$command = "$commandStr > $reduceOut 2>&1"; +system(\$command); +open(IN, "$reduceOut") or exit(\$BAD); +my \$found = 0; +while(<IN>) { + if (/$magic/) { exit \$GOOD; } +} +exit \$BAD; +ENDTEXT +close(OUT); +`chmod +x $scriptFile`; + +print "$prog: starting reduction\n"; +sub multidelta($) { + my ($level) = @_; + system("multidelta -level=$level $scriptFile $srcFile"); +} + +for (my $i = 1 ; $i <= 5; $i++) { + foreach my $level (0,0,1,1,2,2,10) { + multidelta($level); + } +} + +# Copy the final file. +`cp $srcFile $file.reduced`; +print "$prog: generated '$file.reduced"; diff --git a/utils/clang-completion-mode.el b/utils/clang-completion-mode.el index 36d8181..6cf5cb5 100644 --- a/utils/clang-completion-mode.el +++ b/utils/clang-completion-mode.el @@ -32,8 +32,12 @@ ;; ;; (load-library "clang-completion-mode") ;; +;; Once you have done this, you can set various parameters with +;; +;; M-x customize-group RET clang-completion-mode RET +;; ;; Finally, to try Clang-based code completion in a particular buffer, -;; use M-x clang-completion-mode. When "Clang-CC" shows up in the mode +;; use M-x clang-completion-mode. When "Clang" shows up in the mode ;; line, Clang's code-completion is enabled. ;; ;; Clang's code completion is based on parsing the complete source @@ -95,24 +99,29 @@ This variable will typically contain include paths, e.g., -I~/MyProject." (delq nil (mapcar (lambda (x) (and (funcall condp x) x)) lst))) -;; Determine whether +;; Determine whether FIXME: explain better (defun is-completion-line (line) (or (string-match "OVERLOAD:" line) (string-match (concat "COMPLETION: " clang-completion-substring) line))) + +;; re-process the completions when further input narrows the field (defun clang-completion-display (buffer) + (fill-buffer buffer)) + +(defun fill-buffer (buffer) (let* ((all-lines (split-string clang-result-string "\n")) (completion-lines (filter 'is-completion-line all-lines))) (if (consp completion-lines) (progn - ;; Erase the process buffer + ;; Erase the process buffer. (let ((cur (current-buffer))) (set-buffer buffer) (goto-char (point-min)) (erase-buffer) (set-buffer cur)) - ;; Display the process buffer + ;; Display the process buffer. (display-buffer buffer) ;; Insert the code-completion string into the process buffer. @@ -120,28 +129,11 @@ This variable will typically contain include paths, e.g., -I~/MyProject." (insert (mapconcat 'identity completion-lines "\n"))) )))) -;; Process "sentinal" that, on successful code completion, replaces the +;; Process "sentinel" that, on successful code completion, replaces the ;; contents of the code-completion buffer with the new code-completion results ;; and ensures that the buffer is visible. (defun clang-completion-sentinel (proc event) - (let* ((all-lines (split-string clang-result-string "\n")) - (completion-lines (filter 'is-completion-line all-lines))) - (if (consp completion-lines) - (progn - ;; Erase the process buffer - (let ((cur (current-buffer))) - (set-buffer (process-buffer proc)) - (goto-char (point-min)) - (erase-buffer) - (set-buffer cur)) - - ;; Display the process buffer - (display-buffer (process-buffer proc)) - - ;; Insert the code-completion string into the process buffer. - (with-current-buffer (process-buffer proc) - (insert (mapconcat 'identity completion-lines "\n"))) - )))) + (fill-buffer (process-buffer proc))) (defun clang-complete () (let* ((cc-point (concat (buffer-file-name) @@ -159,7 +151,7 @@ This variable will typically contain include paths, e.g., -I~/MyProject." `("-code-completion-at" ,cc-point) (list (buffer-file-name)))) (cc-buffer-name (concat "*Clang Completion for " (buffer-name) "*"))) - ;; Start the code-completion process + ;; Start the code-completion process. (if (buffer-file-name) (progn ;; If there is already a code-completion process, kill it first. diff --git a/utils/clangVisualizers.txt b/utils/clangVisualizers.txt index 0fef65f..8019b9c 100644 --- a/utils/clangVisualizers.txt +++ b/utils/clangVisualizers.txt @@ -3,15 +3,47 @@ llvm::SmallVector<*,*>{ preview ( + #if ((($T1*)$e.EndX - ($T1*)$e.BeginX) == 0) ( "empty" ) + #else ( + #( + "[", + ($T1*)$e.EndX - ($T1*)$e.BeginX, + "](", + #array( + expr: (($T1*)$e.BeginX)[$i], + size: ($T1*)$e.EndX - ($T1*)$e.BeginX + ), + ")" + ) + ) + ) + + children ( #( - "[", - ($T1*)$e.EndX - ($T1*)$e.BeginX, - "](", + #([size] : ($T1*)$e.EndX - ($T1*)$e.BeginX), + #([capacity] : ($T1*)$e.CapacityX - ($T1*)$e.BeginX), #array( expr: (($T1*)$e.BeginX)[$i], size: ($T1*)$e.EndX - ($T1*)$e.BeginX - ), - ")" + ) + ) + ) +} + +llvm::SmallVectorImpl<*>{ + preview ( + #if ((($T1*)$e.EndX - ($T1*)$e.BeginX) == 0) ( "empty" ) + #else ( + #( + "[", + ($T1*)$e.EndX - ($T1*)$e.BeginX, + "](", + #array( + expr: (($T1*)$e.BeginX)[$i], + size: ($T1*)$e.EndX - ($T1*)$e.BeginX + ), + ")" + ) ) ) @@ -27,6 +59,11 @@ llvm::SmallVector<*,*>{ ) } +llvm::SmallString<*>{ + preview ([$e.BeginX,s]) + stringview ([$e.BeginX,sb]) +} + llvm::StringRef{ preview ([$e.Data,s]) stringview ([$e.Data,sb]) @@ -55,6 +92,7 @@ llvm::PointerIntPair<*,*,*,*>{ children ( #( + #([raw members] : [$e,!]), #([ptr] : ($T1*)($e.Value & $e.PointerBitMask)), #([int] : ($T3)($e.Value >> $e.IntShift) & $e.IntMask) ) @@ -63,18 +101,16 @@ llvm::PointerIntPair<*,*,*,*>{ llvm::PointerUnion<*,*>{ preview ( - #if ((($e.Val.Value >> $e.Val.IntShift) & $e.Val.IntMask) == 0) ( - "PT1" - ) #else ( - "PT2" - ) + #if ((($e.Val.Value >> $e.Val.IntShift) & $e.Val.IntMask) == 0) ( "PT1" ) + #else ( "PT2" ) ) children ( #( + #([raw members] : [$e,!]), #if ((($e.Val.Value >> $e.Val.IntShift) & $e.Val.IntMask) == 0) ( #([ptr] : ($T1)($e.Val.Value & $e.Val.PointerBitMask)) - ) #else ( + ) #else ( #([ptr] : ($T2)($e.Val.Value & $e.Val.PointerBitMask)) ) ) @@ -83,13 +119,9 @@ llvm::PointerUnion<*,*>{ llvm::PointerUnion3<*,*,*>{ preview ( - #if (($e.Val.Val.Value & 0x2) == 2) ( - "PT2" - ) #elif (($e.Val.Val.Value & 0x1) == 1) ( - "PT3" - ) #else ( - "PT1" - ) + #if (($e.Val.Val.Value & 0x2) == 2) ( "PT2" ) + #elif (($e.Val.Val.Value & 0x1) == 1) ( "PT3" ) + #else ( "PT1" ) ) children ( @@ -107,22 +139,17 @@ llvm::PointerUnion3<*,*,*>{ llvm::PointerUnion4<*,*,*,*>{ preview ( - #if (($e.Val.Val.Value & 0x3) == 3) ( - "PT4" - ) #elif (($e.Val.Val.Value & 0x2) == 2) ( - "PT2" - ) #elif (($e.Val.Val.Value & 0x1) == 1) ( - "PT3" - ) #else ( - "PT1" - ) + #if (($e.Val.Val.Value & 0x3) == 3) ( "PT4" ) + #elif (($e.Val.Val.Value & 0x2) == 2) ( "PT2" ) + #elif (($e.Val.Val.Value & 0x1) == 1) ( "PT3" ) + #else ( "PT1" ) ) children ( #( #if (($e.Val.Val.Value & 0x3) == 3) ( #([ptr] : ($T4)(($e.Val.Val.Value >> 2) << 2)) - ) #elif (($e.Val.Val.Value & 0x2) == 2) ( + ) #elif (($e.Val.Val.Value & 0x2) == 2) ( #([ptr] : ($T2)(($e.Val.Val.Value >> 2) << 2)) ) #elif (($e.Val.Val.Value & 0x1) == 1) ( #([ptr] : ($T3)(($e.Val.Val.Value >> 2) << 2)) @@ -132,3 +159,233 @@ llvm::PointerUnion4<*,*,*,*>{ ) ) } + +llvm::IntrusiveRefCntPtr<*>{ + preview ( + #if ($e.Obj == 0) ( "empty" ) + #else ( + #( + "[RefCnt=", $e.Obj->ref_cnt, + ", ", + "Obj=", $e.Obj, + "]" + ) + ) + ) + + children ( + #if ($e.Obj == 0) ( #array(expr: 0, size: 0) ) + #else ( + #( + #(RefCnt : $e.Obj->ref_cnt), + #(Obj : $e.Obj) + ) + ) + ) +} + +llvm::OwningPtr<*>{ + preview ( + #if ($e.Ptr == 0) ( "empty" ) + #else ( $e.Ptr ) + ) + + children ( + #if ($e.Ptr == 0) ( #array(expr: 0, size: 0) ) + #else ( #(Ptr : $e.Ptr) ) + ) +} + +llvm::SmallPtrSet<*,*>{ + preview ( + #( + #if (($e.CurArray) == ($e.SmallArray)) ( "[Small Mode] " ) + #else ( "[Big Mode] " ), + "NumElements=", $e.NumElements, + " CurArraySize=", $e.CurArraySize + ) + ) + + children ( + #( + #([raw members] : [$c,!]), + #(NumElements : $e.NumElements), + #(CurArraySize : $e.CurArraySize), + #array( + expr: $e.CurArray[$i], + size: $e.CurArraySize + 1 + ) : ($T1*)&$e + ) + ) +} + +llvm::DenseMap<*,*,*>{ + preview ( + #if ($e.NumEntries == 0) ( "empty" ) + #else ( + #( + "[NumEntries=", $e.NumEntries, + " NumBuckets=", $e.NumBuckets, + "]" + ) + ) + ) + + children ( + #if ($e.NumEntries == 0) ( #array(expr: 0, size: 0) ) + #else ( + #( + #([raw members] : [$c,!]), + #(NumEntries : $e.NumEntries), + #(NumBuckets : $e.NumBuckets), + #array( + expr: $e.Buckets[$i], + size: $e.NumBuckets + ) + ) + ) + ) +} + +llvm::StringMap<*,*>{ + preview ( + #( + "[NumBuckets=", $e.NumBuckets, + " ItemSize=", $e.ItemSize, + "]" + ) + ) + + children ( + #( + #([raw members] : [$c,!]), + #(NumBuckets : $e.NumBuckets), + #(ItemSize : $e.ItemSize), + #array( + expr: $e.TheTable[$i], + size: $e.NumBuckets, + ) : (llvm::StringMapEntry<$T1>*)&$e + ) + ) +} + +llvm::StringMapEntry<*>{ + preview ( + #if ($e.StrLen == 0) ( "empty" ) + #else ( #(Entry : $e.second) ) + ) + + children ( + #if ($e.StrLen == 0) ( "empty" ) + #else ( #(Entry : $e.second) ) + ) +} + +clang::DirectoryEntry|clang::FileEntry|clang::PragmaHandler{ + preview ( [$e.Name,s] ) + children ( + #( + #([raw members] : [$c,!]), + #(Name : [$e.Name,s]) + ) + ) +} + +clang::DeclarationName{ + preview ( + ; enum values from clang::DeclarationName::StoredNameKind + #if ($e.Ptr == 0) ( + "empty" + ) #elif (($e.Ptr & $e.PtrMask) == $e.StoredIdentifier) ( + #else ( #("Identifier, ", (clang::IdentifierInfo*)($e.Ptr & ~$e.PtrMask)) ) + ) #elif (($e.Ptr & $e.PtrMask) == $e.StoredObjCZeroArgSelector) ( + #("ZeroArgSelector, ", (clang::IdentifierInfo*)($e.Ptr & ~$e.PtrMask)) + ) #elif (($e.Ptr & $e.PtrMask) == $e.StoredObjCOneArgSelector) ( + #("OneArgSelector, ", (clang::IdentifierInfo*)($e.Ptr & ~$e.PtrMask)) + ) #elif (($e.Ptr & $e.PtrMask) == $e.StoredDeclarationNameExtra) ( + #switch (((clang::DeclarationNameExtra*)($e.Ptr & ~$e.PtrMask)).ExtraKindOrNumArgs) + #case 0 ( ;DeclarationNameExtra::CXXConstructor + #("CXXConstructorName, ", (clang::CXXSpecialName*)($e.Ptr & ~$e.PtrMask)) + ) + #case 1 ( ;DeclarationNameExtra::CXXDestructor + #("CXXDestructorName, ", (clang::CXXSpecialName*)($e.Ptr & ~$e.PtrMask)) + ) + #case 2 ( ;DeclarationNameExtra::CXXConversionFunction + #("CXXConversionFunctionName, ", (clang::CXXSpecialName*)($e.Ptr & ~$e.PtrMask)) + ) + #case 46 ( ;DeclarationNameExtra::CXXLiteralOperator + #("CXXLiteralOperatorName, ", (clang::CXXLiteralOperatorIdName*)($e.Ptr & ~$e.PtrMask)) + ) + #case 47 ( ;DeclarationNameExtra::CXXUsingDirective + #("CXXUsingDirective") ;TODO What to add here? + ) + #default ( + #if (((clang::DeclarationNameExtra*)($e.Ptr & ~$e.PtrMask)).ExtraKindOrNumArgs < 47) ( + #("CXXOperatorName, ", (clang::CXXOperatorIdName*)($e.Ptr & ~$e.PtrMask)) + ) #else ( + #("ObjCMultiArgSelector, ", (clang::MultiKeywordSelector*)($e.Ptr & ~$e.PtrMask)) + ) + ) + ) + ) + + children ( + #( + ; enum values from clang::DeclarationName::StoredNameKind + #if ($e.Ptr == 0) ( + #array( expr: 0, size: 0 ) + ) #else ( + #( + #([raw members] : [$e.Ptr,!]), + if (($e.Ptr & $e.PtrMask) == $e.StoredIdentifier) ( + #(Ptr : (clang::IdentifierInfo*)($e.Ptr & ~$e.PtrMask)) + ) #elif (($e.Ptr & $e.PtrMask) == $e.StoredObjCZeroArgSelector) ( + #(Ptr : (clang::IdentifierInfo*)($e.Ptr & ~$e.PtrMask)) + ) #elif (($e.Ptr & $e.PtrMask) == $e.StoredObjCOneArgSelector) ( + #(Ptr : (clang::IdentifierInfo*)($e.Ptr & ~$e.PtrMask)) + ) #elif (($e.Ptr & $e.PtrMask) == $e.StoredDeclarationNameExtra) ( + #switch (((clang::DeclarationNameExtra*)($e.Ptr & ~$e.PtrMask)).ExtraKindOrNumArgs) + #case 0 ( ;DeclarationNameExtra::CXXConstructor + #(Ptr : (clang::CXXSpecialName*)($e.Ptr & ~$e.PtrMask)) + ) + #case 1 ( ;DeclarationNameExtra::CXXDestructor + #(Ptr : (clang::CXXSpecialName*)($e.Ptr & ~$e.PtrMask)) + ) + #case 2 ( ;DeclarationNameExtra::CXXConversionFunction + #(Ptr : (clang::CXXSpecialName*)($e.Ptr & ~$e.PtrMask)) + ) + #case 46 ( ;DeclarationNameExtra::CXXLiteralOperator + #(Ptr : (clang::CXXLiteralOperatorIdName*)($e.Ptr & ~$e.PtrMask)) + ) + #case 47 ( ;DeclarationNameExtra::CXXUsingDirective + #(Ptr : $e.Ptr) ;TODO What to add here? + ) + #default ( + #if (((clang::DeclarationNameExtra*)($e.Ptr & ~$e.PtrMask)).ExtraKindOrNumArgs < 47) ( + #(Ptr : (CXXOperatorIdName*)($e.Ptr & ~$e.PtrMask)) + ) #else ( + #(Ptr : (clang::MultiKeywordSelector*)($e.Ptr & ~$e.PtrMask)) + ) + ) + ) + ) + ) + ) + ) +} + +clang::DeclSpec{ + preview ( + #( + "[", + (clang::DeclSpec::SCS)$e.StorageClassSpec, + ", ", + (clang::TypeSpecifierType)$e.TypeSpecType, + "]" + ) + ) +} + +llvm::Triple{ + preview ( $e.Data ) +} |