diff options
Diffstat (limited to 'contrib/llvm/tools/clang/utils/TableGen')
8 files changed, 523 insertions, 129 deletions
diff --git a/contrib/llvm/tools/clang/utils/TableGen/CMakeLists.txt b/contrib/llvm/tools/clang/utils/TableGen/CMakeLists.txt deleted file mode 100644 index 75a6167..0000000 --- a/contrib/llvm/tools/clang/utils/TableGen/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -set(LLVM_REQUIRES_EH 1) -set(LLVM_REQUIRES_RTTI 1) - -add_tablegen(clang-tblgen CLANG - ClangASTNodesEmitter.cpp - ClangAttrEmitter.cpp - ClangDiagnosticsEmitter.cpp - ClangSACheckersEmitter.cpp - NeonEmitter.cpp - OptParserEmitter.cpp - TableGen.cpp - ) diff --git a/contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp b/contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp index 5c236be..7951fc4 100644 --- a/contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp +++ b/contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp @@ -16,6 +16,7 @@ #include "llvm/TableGen/Record.h" #include <algorithm> #include <cctype> +#include <set> using namespace llvm; @@ -33,8 +34,6 @@ getValueAsListOfStrings(Record &R, StringRef FieldName) { assert(*i && "Got a null element in a ListInit"); if (StringInit *S = dynamic_cast<StringInit *>(*i)) Strings.push_back(S->getValue()); - else if (CodeInit *C = dynamic_cast<CodeInit *>(*i)) - Strings.push_back(C->getValue()); else assert(false && "Got a non-string, non-code element in a ListInit"); } @@ -67,6 +66,30 @@ static std::string WritePCHRecord(StringRef type, StringRef name) { .Default("Record.push_back(" + std::string(name) + ");\n"); } +// Normalize attribute name by removing leading and trailing +// underscores. For example, __foo, foo__, __foo__ would +// become foo. +static StringRef NormalizeAttrName(StringRef AttrName) { + if (AttrName.startswith("__")) + AttrName = AttrName.substr(2, AttrName.size()); + + if (AttrName.endswith("__")) + AttrName = AttrName.substr(0, AttrName.size() - 2); + + return AttrName; +} + +// Normalize attribute spelling only if the spelling has both leading +// and trailing underscores. For example, __ms_struct__ will be +// normalized to "ms_struct"; __cdecl will remain intact. +static StringRef NormalizeAttrSpelling(StringRef AttrSpelling) { + if (AttrSpelling.startswith("__") && AttrSpelling.endswith("__")) { + AttrSpelling = AttrSpelling.substr(2, AttrSpelling.size() - 4); + } + + return AttrSpelling; +} + namespace { class Argument { std::string lowerName, upperName; @@ -91,6 +114,8 @@ namespace { virtual void writeAccessors(raw_ostream &OS) const = 0; virtual void writeAccessorDefinitions(raw_ostream &OS) const {} virtual void writeCloneArgs(raw_ostream &OS) const = 0; + virtual void writeTemplateInstantiationArgs(raw_ostream &OS) const = 0; + virtual void writeTemplateInstantiation(raw_ostream &OS) const {} virtual void writeCtorBody(raw_ostream &OS) const {} virtual void writeCtorInitializers(raw_ostream &OS) const = 0; virtual void writeCtorParameters(raw_ostream &OS) const = 0; @@ -98,6 +123,7 @@ namespace { virtual void writePCHReadArgs(raw_ostream &OS) const = 0; virtual void writePCHReadDecls(raw_ostream &OS) const = 0; virtual void writePCHWrite(raw_ostream &OS) const = 0; + virtual void writeValue(raw_ostream &OS) const = 0; }; class SimpleArgument : public Argument { @@ -108,6 +134,8 @@ namespace { : Argument(Arg, Attr), type(T) {} + std::string getType() const { return type; } + void writeAccessors(raw_ostream &OS) const { OS << " " << type << " get" << getUpperName() << "() const {\n"; OS << " return " << getLowerName() << ";\n"; @@ -116,6 +144,9 @@ namespace { void writeCloneArgs(raw_ostream &OS) const { OS << getLowerName(); } + void writeTemplateInstantiationArgs(raw_ostream &OS) const { + OS << "A->get" << getUpperName() << "()"; + } void writeCtorInitializers(raw_ostream &OS) const { OS << getLowerName() << "(" << getUpperName() << ")"; } @@ -136,6 +167,19 @@ namespace { OS << " " << WritePCHRecord(type, "SA->get" + std::string(getUpperName()) + "()"); } + void writeValue(raw_ostream &OS) const { + if (type == "FunctionDecl *") { + OS << "\" << get" << getUpperName() << "()->getNameInfo().getAsString() << \""; + } else if (type == "IdentifierInfo *") { + OS << "\" << get" << getUpperName() << "()->getName() << \""; + } else if (type == "QualType") { + OS << "\" << get" << getUpperName() << "().getAsString() << \""; + } else if (type == "SourceLocation") { + OS << "\" << get" << getUpperName() << "().getRawEncoding() << \""; + } else { + OS << "\" << get" << getUpperName() << "() << \""; + } + } }; class StringArgument : public Argument { @@ -164,6 +208,9 @@ namespace { void writeCloneArgs(raw_ostream &OS) const { OS << "get" << getUpperName() << "()"; } + void writeTemplateInstantiationArgs(raw_ostream &OS) const { + OS << "A->get" << getUpperName() << "()"; + } void writeCtorBody(raw_ostream &OS) const { OS << " std::memcpy(" << getLowerName() << ", " << getUpperName() << ".data(), " << getLowerName() << "Length);"; @@ -190,6 +237,9 @@ namespace { void writePCHWrite(raw_ostream &OS) const { OS << " AddString(SA->get" << getUpperName() << "(), Record);\n"; } + void writeValue(raw_ostream &OS) const { + OS << "\\\"\" << get" << getUpperName() << "() << \"\\\""; + } }; class AlignedArgument : public Argument { @@ -251,6 +301,10 @@ namespace { << "Expr) : " << getLowerName() << "Type"; } + void writeTemplateInstantiationArgs(raw_ostream &OS) const { + // FIXME: move the definition in Sema::InstantiateAttrs to here. + // In the meantime, aligned attributes are cloned. + } void writeCtorBody(raw_ostream &OS) const { OS << " if (is" << getLowerName() << "Expr)\n"; OS << " " << getLowerName() << "Expr = reinterpret_cast<Expr *>(" @@ -293,6 +347,9 @@ namespace { OS << " AddTypeSourceInfo(SA->get" << getUpperName() << "Type(), Record);\n"; } + void writeValue(raw_ostream &OS) const { + OS << "\" << get" << getUpperName() << "(Ctx) << \""; + } }; class VariadicArgument : public Argument { @@ -317,12 +374,17 @@ namespace { << "Size;\n"; OS << " }\n"; OS << " unsigned " << getLowerName() << "_size() const {\n" - << " return " << getLowerName() << "Size;\n;"; + << " return " << getLowerName() << "Size;\n"; OS << " }"; } void writeCloneArgs(raw_ostream &OS) const { OS << getLowerName() << ", " << getLowerName() << "Size"; } + void writeTemplateInstantiationArgs(raw_ostream &OS) const { + // This isn't elegant, but we have to go through public methods... + OS << "A->" << getLowerName() << "_begin(), " + << "A->" << getLowerName() << "_size()"; + } void writeCtorBody(raw_ostream &OS) const { // FIXME: memcpy is not safe on non-trivial types. OS << " std::memcpy(" << getLowerName() << ", " << getUpperName() @@ -362,6 +424,18 @@ namespace { << getLowerName() << "_end(); i != e; ++i)\n"; OS << " " << WritePCHRecord(type, "(*i)"); } + void writeValue(raw_ostream &OS) const { + OS << "\";\n"; + OS << " bool isFirst = true;\n" + << " for (" << getAttrName() << "Attr::" << getLowerName() + << "_iterator i = " << getLowerName() << "_begin(), e = " + << getLowerName() << "_end(); i != e; ++i) {\n" + << " if (isFirst) isFirst = false;\n" + << " else OS << \", \";\n" + << " OS << *i;\n" + << " }\n"; + OS << " OS << \""; + } }; class EnumArgument : public Argument { @@ -382,6 +456,9 @@ namespace { void writeCloneArgs(raw_ostream &OS) const { OS << getLowerName(); } + void writeTemplateInstantiationArgs(raw_ostream &OS) const { + OS << "A->get" << getUpperName() << "()"; + } void writeCtorInitializers(raw_ostream &OS) const { OS << getLowerName() << "(" << getUpperName() << ")"; } @@ -422,6 +499,9 @@ namespace { void writePCHWrite(raw_ostream &OS) const { OS << "Record.push_back(SA->get" << getUpperName() << "());\n"; } + void writeValue(raw_ostream &OS) const { + OS << "\" << get" << getUpperName() << "() << \""; + } }; class VersionArgument : public Argument { @@ -442,6 +522,9 @@ namespace { void writeCloneArgs(raw_ostream &OS) const { OS << "get" << getUpperName() << "()"; } + void writeTemplateInstantiationArgs(raw_ostream &OS) const { + OS << "A->get" << getUpperName() << "()"; + } void writeCtorBody(raw_ostream &OS) const { } void writeCtorInitializers(raw_ostream &OS) const { @@ -463,6 +546,64 @@ namespace { void writePCHWrite(raw_ostream &OS) const { OS << " AddVersionTuple(SA->get" << getUpperName() << "(), Record);\n"; } + void writeValue(raw_ostream &OS) const { + OS << getLowerName() << "=\" << get" << getUpperName() << "() << \""; + } + }; + + class ExprArgument : public SimpleArgument { + public: + ExprArgument(Record &Arg, StringRef Attr) + : SimpleArgument(Arg, Attr, "Expr *") + {} + + void writeTemplateInstantiationArgs(raw_ostream &OS) const { + OS << "tempInst" << getUpperName(); + } + + void writeTemplateInstantiation(raw_ostream &OS) const { + OS << " " << getType() << " tempInst" << getUpperName() << ";\n"; + OS << " {\n"; + OS << " EnterExpressionEvaluationContext " + << "Unevaluated(S, Sema::Unevaluated);\n"; + OS << " ExprResult " << "Result = S.SubstExpr(" + << "A->get" << getUpperName() << "(), TemplateArgs);\n"; + OS << " tempInst" << getUpperName() << " = " + << "Result.takeAs<Expr>();\n"; + OS << " }\n"; + } + }; + + class VariadicExprArgument : public VariadicArgument { + public: + VariadicExprArgument(Record &Arg, StringRef Attr) + : VariadicArgument(Arg, Attr, "Expr *") + {} + + void writeTemplateInstantiationArgs(raw_ostream &OS) const { + OS << "tempInst" << getUpperName() << ", " + << "A->" << getLowerName() << "_size()"; + } + + void writeTemplateInstantiation(raw_ostream &OS) const { + OS << " " << getType() << " *tempInst" << getUpperName() + << " = new (C, 16) " << getType() + << "[A->" << getLowerName() << "_size()];\n"; + OS << " {\n"; + OS << " EnterExpressionEvaluationContext " + << "Unevaluated(S, Sema::Unevaluated);\n"; + OS << " " << getType() << " *TI = tempInst" << getUpperName() + << ";\n"; + OS << " " << getType() << " *I = A->" << getLowerName() + << "_begin();\n"; + OS << " " << getType() << " *E = A->" << getLowerName() + << "_end();\n"; + OS << " for (; I != E; ++I, ++TI) {\n"; + OS << " ExprResult Result = S.SubstExpr(*I, TemplateArgs);\n"; + OS << " *TI = Result.takeAs<Expr>();\n"; + OS << " }\n"; + OS << " }\n"; + } }; } @@ -476,8 +617,7 @@ static Argument *createArgument(Record &Arg, StringRef Attr, if (ArgName == "AlignedArgument") Ptr = new AlignedArgument(Arg, Attr); else if (ArgName == "EnumArgument") Ptr = new EnumArgument(Arg, Attr); - else if (ArgName == "ExprArgument") Ptr = new SimpleArgument(Arg, Attr, - "Expr *"); + else if (ArgName == "ExprArgument") Ptr = new ExprArgument(Arg, Attr); else if (ArgName == "FunctionArgument") Ptr = new SimpleArgument(Arg, Attr, "FunctionDecl *"); else if (ArgName == "IdentifierArgument") @@ -495,7 +635,7 @@ static Argument *createArgument(Record &Arg, StringRef Attr, else if (ArgName == "VariadicUnsignedArgument") Ptr = new VariadicArgument(Arg, Attr, "unsigned"); else if (ArgName == "VariadicExprArgument") - Ptr = new VariadicArgument(Arg, Attr, "Expr *"); + Ptr = new VariadicExprArgument(Arg, Attr); else if (ArgName == "VersionArgument") Ptr = new VersionArgument(Arg, Attr); @@ -511,6 +651,15 @@ static Argument *createArgument(Record &Arg, StringRef Attr, return Ptr; } +static void writeAvailabilityValue(raw_ostream &OS) { + OS << "\" << getPlatform()->getName();\n" + << " if (!getIntroduced().empty()) OS << \", introduced=\" << getIntroduced();\n" + << " if (!getDeprecated().empty()) OS << \", deprecated=\" << getDeprecated();\n" + << " if (!getObsoleted().empty()) OS << \", obsoleted=\" << getObsoleted();\n" + << " if (getUnavailable()) OS << \", unavailable\";\n" + << " OS << \""; +} + void ClangAttrClassEmitter::run(raw_ostream &OS) { OS << "// This file is generated by TableGen. Do not edit.\n\n"; OS << "#ifndef LLVM_CLANG_ATTR_CLASSES_INC\n"; @@ -571,19 +720,25 @@ void ClangAttrClassEmitter::run(raw_ostream &OS) { OS << " }\n\n"; OS << " virtual " << R.getName() << "Attr *clone (ASTContext &C) const;\n"; + OS << " virtual void printPretty(llvm::raw_ostream &OS, ASTContext &Ctx) const;\n"; for (ai = Args.begin(); ai != ae; ++ai) { (*ai)->writeAccessors(OS); OS << "\n\n"; } - OS << R.getValueAsCode("AdditionalMembers"); + OS << R.getValueAsString("AdditionalMembers"); OS << "\n\n"; OS << " static bool classof(const Attr *A) { return A->getKind() == " << "attr::" << R.getName() << "; }\n"; OS << " static bool classof(const " << R.getName() << "Attr *) { return true; }\n"; + + bool LateParsed = R.getValueAsBit("LateParsed"); + OS << " virtual bool isLateParsed() const { return " + << LateParsed << "; }\n"; + OS << "};\n\n"; } @@ -600,6 +755,7 @@ void ClangAttrImplEmitter::run(raw_ostream &OS) { for (; i != e; ++i) { Record &R = **i; std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args"); + std::vector<StringRef> Spellings = getValueAsListOfStrings(R, "Spellings"); std::vector<Argument*> Args; for (ri = ArgRecords.begin(), re = ArgRecords.end(); ri != re; ++ri) Args.push_back(createArgument(**ri, R.getName())); @@ -615,6 +771,24 @@ void ClangAttrImplEmitter::run(raw_ostream &OS) { (*ai)->writeCloneArgs(OS); } OS << ");\n}\n\n"; + + OS << "void " << R.getName() << "Attr::printPretty(" + << "llvm::raw_ostream &OS, ASTContext &Ctx) const {\n"; + if (Spellings.begin() != Spellings.end()) { + OS << " OS << \" __attribute__((" << *Spellings.begin(); + if (Args.size()) OS << "("; + if (*Spellings.begin()=="availability") { + writeAvailabilityValue(OS); + } else { + for (ai = Args.begin(); ai != ae; ++ai) { + if (ai!=Args.begin()) OS <<", "; + (*ai)->writeValue(OS); + } + } + if (Args.size()) OS << ")"; + OS << "))\";\n"; + } + OS << "}\n\n"; } } @@ -786,3 +960,133 @@ void ClangAttrLateParsedListEmitter::run(raw_ostream &OS) { } } } + + +void ClangAttrTemplateInstantiateEmitter::run(raw_ostream &OS) { + OS << "// This file is generated by TableGen. Do not edit.\n\n"; + + std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); + + OS << "namespace clang {\n" + << "namespace sema {\n\n" + << "Attr *instantiateTemplateAttribute(const Attr *At, ASTContext &C, " + << "Sema &S,\n" + << " const MultiLevelTemplateArgumentList &TemplateArgs) {\n" + << " switch (At->getKind()) {\n" + << " default:\n" + << " break;\n"; + + for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); + I != E; ++I) { + Record &R = **I; + + OS << " case attr::" << R.getName() << ": {\n"; + OS << " const " << R.getName() << "Attr *A = cast<" + << R.getName() << "Attr>(At);\n"; + bool TDependent = R.getValueAsBit("TemplateDependent"); + + if (!TDependent) { + OS << " return A->clone(C);\n"; + OS << " }\n"; + continue; + } + + std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args"); + std::vector<Argument*> Args; + std::vector<Argument*>::iterator ai, ae; + Args.reserve(ArgRecords.size()); + + for (std::vector<Record*>::iterator ri = ArgRecords.begin(), + re = ArgRecords.end(); + ri != re; ++ri) { + Record &ArgRecord = **ri; + Argument *Arg = createArgument(ArgRecord, R.getName()); + assert(Arg); + Args.push_back(Arg); + } + ae = Args.end(); + + for (ai = Args.begin(); ai != ae; ++ai) { + (*ai)->writeTemplateInstantiation(OS); + } + OS << " return new (C) " << R.getName() << "Attr(A->getLocation(), C"; + for (ai = Args.begin(); ai != ae; ++ai) { + OS << ", "; + (*ai)->writeTemplateInstantiationArgs(OS); + } + OS << ");\n }\n"; + } + OS << " } // end switch\n" + << " llvm_unreachable(\"Unknown attribute!\");\n" + << " return 0;\n" + << "}\n\n" + << "} // end namespace sema\n" + << "} // end namespace clang\n"; +} + +void ClangAttrParsedAttrListEmitter::run(raw_ostream &OS) { + OS << "// This file is generated by TableGen. Do not edit.\n\n"; + + OS << "#ifndef PARSED_ATTR\n"; + OS << "#define PARSED_ATTR(NAME) NAME\n"; + 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"); + + 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; + + AttrName = NormalizeAttrName(AttrName); + // skip if a normalized version has been processed. + if (ProcessedAttrs.find(AttrName) != ProcessedAttrs.end()) + continue; + else + ProcessedAttrs.insert(AttrName); + + OS << "PARSED_ATTR(" << AttrName << ")\n"; + } + } + } +} + +void ClangAttrParsedAttrKindsEmitter::run(raw_ostream &OS) { + OS << "// This file is generated by TableGen. Do not edit.\n\n"; + + std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); + + for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); + I != E; ++I) { + Record &Attr = **I; + + bool SemaHandler = Attr.getValueAsBit("SemaHandler"); + + 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, Spelling = *I; + + AttrName = NormalizeAttrName(AttrName); + Spelling = NormalizeAttrSpelling(Spelling); + + OS << ".Case(\"" << Spelling << "\", " << "AT_" << AttrName << ")\n"; + } + } + } +} + + diff --git a/contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.h b/contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.h index 5acca56..d119a09 100644 --- a/contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.h +++ b/contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.h @@ -109,6 +109,45 @@ class ClangAttrLateParsedListEmitter : public TableGenBackend { 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/contrib/llvm/tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp b/contrib/llvm/tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp index da2fb70..8a49619 100644 --- a/contrib/llvm/tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp +++ b/contrib/llvm/tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp @@ -16,13 +16,12 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/Compiler.h" #include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/SmallString.h" -#include "llvm/ADT/VectorExtras.h" #include <map> #include <algorithm> #include <functional> +#include <set> using namespace llvm; //===----------------------------------------------------------------------===// @@ -51,7 +50,6 @@ public: }; } // end anonymous namespace. - static std::string getCategoryFromDiagGroup(const Record *Group, DiagGroupParentMap &DiagGroupParents) { @@ -120,8 +118,44 @@ namespace { iterator begin() { return CategoryStrings.begin(); } iterator end() { return CategoryStrings.end(); } }; + + struct GroupInfo { + std::vector<const Record*> DiagsInGroup; + std::vector<std::string> SubGroups; + unsigned IDNo; + }; } // end anonymous namespace. +/// \brief Invert the 1-[0/1] mapping of diags to group into a one to many +/// mapping of groups to diags in the group. +static void groupDiagnostics(const std::vector<Record*> &Diags, + const std::vector<Record*> &DiagGroups, + std::map<std::string, GroupInfo> &DiagsInGroup) { + for (unsigned i = 0, e = Diags.size(); i != e; ++i) { + const Record *R = Diags[i]; + DefInit *DI = dynamic_cast<DefInit*>(R->getValueInit("Group")); + if (DI == 0) continue; + std::string GroupName = DI->getDef()->getValueAsString("GroupName"); + DiagsInGroup[GroupName].DiagsInGroup.push_back(R); + } + + // Add all DiagGroup's to the DiagsInGroup list to make sure we pick up empty + // groups (these are warnings that GCC supports that clang never produces). + for (unsigned i = 0, e = DiagGroups.size(); i != e; ++i) { + Record *Group = DiagGroups[i]; + GroupInfo &GI = DiagsInGroup[Group->getValueAsString("GroupName")]; + + std::vector<Record*> SubGroups = Group->getValueAsListOfDefs("SubGroups"); + for (unsigned j = 0, e = SubGroups.size(); j != e; ++j) + GI.SubGroups.push_back(SubGroups[j]->getValueAsString("GroupName")); + } + + // Assign unique ID numbers to the groups. + unsigned IDNo = 0; + for (std::map<std::string, GroupInfo>::iterator + I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I, ++IDNo) + I->second.IDNo = IDNo; +} //===----------------------------------------------------------------------===// // Warning Tables (.inc file) generation. @@ -130,7 +164,7 @@ namespace { void ClangDiagsDefsEmitter::run(raw_ostream &OS) { // Write the #if guard if (!Component.empty()) { - std::string ComponentName = UppercaseString(Component); + std::string ComponentName = StringRef(Component).upper(); OS << "#ifdef " << ComponentName << "START\n"; OS << "__" << ComponentName << "START = DIAG_START_" << ComponentName << ",\n"; @@ -140,7 +174,13 @@ void ClangDiagsDefsEmitter::run(raw_ostream &OS) { const std::vector<Record*> &Diags = Records.getAllDerivedDefinitions("Diagnostic"); - + + std::vector<Record*> DiagGroups + = Records.getAllDerivedDefinitions("DiagGroup"); + + std::map<std::string, GroupInfo> DiagsInGroup; + groupDiagnostics(Diags, DiagGroups, DiagsInGroup); + DiagCategoryIDMap CategoryIDs(Records); DiagGroupParentMap DGParentMap(Records); @@ -158,12 +198,15 @@ void ClangDiagsDefsEmitter::run(raw_ostream &OS) { OS << ", \""; OS.write_escaped(R.getValueAsString("Text")) << '"'; - // Warning associated with the diagnostic. + // Warning associated with the diagnostic. This is stored as an index into + // the alphabetically sorted warning table. if (DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("Group"))) { - OS << ", \""; - OS.write_escaped(DI->getDef()->getValueAsString("GroupName")) << '"'; + std::map<std::string, GroupInfo>::iterator I = + DiagsInGroup.find(DI->getDef()->getValueAsString("GroupName")); + assert(I != DiagsInGroup.end()); + OS << ", " << I->second.IDNo; } else { - OS << ", \"\""; + OS << ", 0"; } // SFINAE bit @@ -196,14 +239,6 @@ void ClangDiagsDefsEmitter::run(raw_ostream &OS) { // Category number. OS << ", " << CategoryIDs.getID(getDiagnosticCategory(&R, DGParentMap)); - - // Brief - OS << ", \""; - OS.write_escaped(R.getValueAsString("Brief")) << '"'; - - // Explanation - OS << ", \""; - OS.write_escaped(R.getValueAsString("Explanation")) << '"'; OS << ")\n"; } } @@ -215,56 +250,24 @@ void ClangDiagsDefsEmitter::run(raw_ostream &OS) { static std::string getDiagCategoryEnum(llvm::StringRef name) { if (name.empty()) return "DiagCat_None"; - llvm::SmallString<256> enumName = llvm::StringRef("DiagCat_"); + SmallString<256> enumName = llvm::StringRef("DiagCat_"); for (llvm::StringRef::iterator I = name.begin(), E = name.end(); I != E; ++I) enumName += isalnum(*I) ? *I : '_'; return enumName.str(); } -namespace { -struct GroupInfo { - std::vector<const Record*> DiagsInGroup; - std::vector<std::string> SubGroups; - unsigned IDNo; -}; -} // end anonymous namespace. - void ClangDiagGroupsEmitter::run(raw_ostream &OS) { // Compute a mapping from a DiagGroup to all of its parents. DiagGroupParentMap DGParentMap(Records); - // Invert the 1-[0/1] mapping of diags to group into a one to many mapping of - // groups to diags in the group. - std::map<std::string, GroupInfo> DiagsInGroup; - std::vector<Record*> Diags = Records.getAllDerivedDefinitions("Diagnostic"); - for (unsigned i = 0, e = Diags.size(); i != e; ++i) { - const Record *R = Diags[i]; - DefInit *DI = dynamic_cast<DefInit*>(R->getValueInit("Group")); - if (DI == 0) continue; - std::string GroupName = DI->getDef()->getValueAsString("GroupName"); - DiagsInGroup[GroupName].DiagsInGroup.push_back(R); - } - // Add all DiagGroup's to the DiagsInGroup list to make sure we pick up empty - // groups (these are warnings that GCC supports that clang never produces). std::vector<Record*> DiagGroups = Records.getAllDerivedDefinitions("DiagGroup"); - for (unsigned i = 0, e = DiagGroups.size(); i != e; ++i) { - Record *Group = DiagGroups[i]; - GroupInfo &GI = DiagsInGroup[Group->getValueAsString("GroupName")]; - - std::vector<Record*> SubGroups = Group->getValueAsListOfDefs("SubGroups"); - for (unsigned j = 0, e = SubGroups.size(); j != e; ++j) - GI.SubGroups.push_back(SubGroups[j]->getValueAsString("GroupName")); - } - - // Assign unique ID numbers to the groups. - unsigned IDNo = 0; - for (std::map<std::string, GroupInfo>::iterator - I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I, ++IDNo) - I->second.IDNo = IDNo; + + std::map<std::string, GroupInfo> DiagsInGroup; + groupDiagnostics(Diags, DiagGroups, DiagsInGroup); // Walk through the groups emitting an array for each diagnostic of the diags // that are mapped to. @@ -304,6 +307,10 @@ void ClangDiagGroupsEmitter::run(raw_ostream &OS) { OS << " { "; OS << I->first.size() << ", "; OS << "\""; + if (I->first.find_first_not_of("abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789!@#$%^*-+=:?")!=std::string::npos) + throw "Invalid character in diagnostic group '" + I->first + "'"; OS.write_escaped(I->first) << "\"," << std::string(MaxLen-I->first.size()+1, ' '); diff --git a/contrib/llvm/tools/clang/utils/TableGen/Makefile b/contrib/llvm/tools/clang/utils/TableGen/Makefile deleted file mode 100644 index 9790efc..0000000 --- a/contrib/llvm/tools/clang/utils/TableGen/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -##===- utils/TableGen/Makefile -----------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -TOOLNAME = clang-tblgen -USEDLIBS = LLVMTableGen.a LLVMSupport.a -REQUIRES_EH := 1 -REQUIRES_RTTI := 1 - -# This tool has no plugins, optimize startup time. -TOOL_NO_EXPORTS = 1 - -include $(LEVEL)/Makefile.common diff --git a/contrib/llvm/tools/clang/utils/TableGen/NeonEmitter.cpp b/contrib/llvm/tools/clang/utils/TableGen/NeonEmitter.cpp index 66845cc..e6f2e53 100644 --- a/contrib/llvm/tools/clang/utils/TableGen/NeonEmitter.cpp +++ b/contrib/llvm/tools/clang/utils/TableGen/NeonEmitter.cpp @@ -28,6 +28,7 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/Support/ErrorHandling.h" #include <string> using namespace llvm; @@ -56,7 +57,6 @@ static void ParseTypes(Record *r, std::string &s, default: throw TGError(r->getLoc(), "Unexpected letter: " + std::string(data + len, 1)); - break; } TV.push_back(StringRef(data, len + 1)); data += len + 1; @@ -78,7 +78,6 @@ static char Widen(const char t) { return 'f'; default: throw "unhandled type in widen!"; } - return '\0'; } /// Narrow - Convert a type code into the next smaller type. short -> char, @@ -95,7 +94,6 @@ static char Narrow(const char t) { return 'h'; default: throw "unhandled type in narrow!"; } - return '\0'; } /// For a particular StringRef, return the base type code, and whether it has @@ -266,7 +264,6 @@ static std::string TypeString(const char mod, StringRef typestr) { break; default: throw "unhandled type!"; - break; } if (mod == '2') @@ -449,7 +446,6 @@ static std::string MangleName(const std::string &name, StringRef typestr, break; default: throw "unhandled type!"; - break; } if (ck == ClassB) s += "_v"; @@ -526,12 +522,6 @@ static std::string GenMacroLocals(const std::string &proto, StringRef typestr) { for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) { // Do not create a temporary for an immediate argument. // That would defeat the whole point of using a macro! - // FIXME: For other (non-immediate) arguments that are used directly, a - // local temporary (or some other method) is still needed to get the - // correct type checking, even if that temporary is not used for anything. - // This is omitted for now because it turns out the the use of - // "__extension__" in the macro disables any warnings from the pointer - // assignment. if (MacroArgUsedDirectly(proto, i)) continue; generatedLocal = true; @@ -594,7 +584,6 @@ static unsigned GetNumElements(StringRef typestr, bool &quad) { case 'f': nElts = 2; break; default: throw "unhandled type!"; - break; } if (quad) nElts <<= 1; return nElts; @@ -826,14 +815,12 @@ static std::string GenOpString(OpKind op, const std::string &proto, } default: throw "unknown OpKind!"; - break; } return s; } static unsigned GetNeonEnum(const std::string &proto, StringRef typestr) { unsigned mod = proto[0]; - unsigned ret = 0; if (mod == 'v' || mod == 'f') mod = proto[1]; @@ -851,35 +838,31 @@ static unsigned GetNeonEnum(const std::string &proto, StringRef typestr) { // Based on the modifying character, change the type and width if necessary. type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr); - if (usgn) - ret |= 0x08; - if (quad && proto[1] != 'g') - ret |= 0x10; - + NeonTypeFlags::EltType ET; switch (type) { case 'c': - ret |= poly ? 5 : 0; + ET = poly ? NeonTypeFlags::Poly8 : NeonTypeFlags::Int8; break; case 's': - ret |= poly ? 6 : 1; + ET = poly ? NeonTypeFlags::Poly16 : NeonTypeFlags::Int16; break; case 'i': - ret |= 2; + ET = NeonTypeFlags::Int32; break; case 'l': - ret |= 3; + ET = NeonTypeFlags::Int64; break; case 'h': - ret |= 7; + ET = NeonTypeFlags::Float16; break; case 'f': - ret |= 4; + ET = NeonTypeFlags::Float32; break; default: throw "unhandled type!"; - break; } - return ret; + NeonTypeFlags Flags(ET, usgn, quad && proto[1] != 'g'); + return Flags.getFlags(); } // Generate the definition for this intrinsic, e.g. __builtin_neon_cls(a) @@ -1249,10 +1232,7 @@ static unsigned RangeFromType(const char mod, StringRef typestr) { return (1 << (int)quad) - 1; default: throw "unhandled type!"; - break; } - assert(0 && "unreachable"); - return 0; } /// runHeader - Emit a file with sections defining: @@ -1346,14 +1326,57 @@ void NeonEmitter::runHeader(raw_ostream &OS) { mask |= 1 << GetNeonEnum(Proto, TypeVec[ti]); } } - if (mask) + + // Check if the builtin function has a pointer or const pointer argument. + int PtrArgNum = -1; + bool HasConstPtr = false; + for (unsigned arg = 1, arge = Proto.size(); arg != arge; ++arg) { + char ArgType = Proto[arg]; + if (ArgType == 'c') { + HasConstPtr = true; + PtrArgNum = arg - 1; + break; + } + if (ArgType == 'p') { + PtrArgNum = arg - 1; + break; + } + } + // For sret builtins, adjust the pointer argument index. + if (PtrArgNum >= 0 && (Proto[0] >= '2' && Proto[0] <= '4')) + PtrArgNum += 1; + + // Omit type checking for the pointer arguments of vld1_lane, vld1_dup, + // and vst1_lane intrinsics. Using a pointer to the vector element + // type with one of those operations causes codegen to select an aligned + // load/store instruction. If you want an unaligned operation, + // the pointer argument needs to have less alignment than element type, + // so just accept any pointer type. + if (name == "vld1_lane" || name == "vld1_dup" || name == "vst1_lane") { + PtrArgNum = -1; + HasConstPtr = false; + } + + if (mask) { OS << "case ARM::BI__builtin_neon_" << MangleName(name, TypeVec[si], ClassB) - << ": mask = " << "0x" << utohexstr(mask) << "; break;\n"; - if (qmask) + << ": mask = " << "0x" << utohexstr(mask); + if (PtrArgNum >= 0) + OS << "; PtrArgNum = " << PtrArgNum; + if (HasConstPtr) + OS << "; HasConstPtr = true"; + OS << "; break;\n"; + } + if (qmask) { OS << "case ARM::BI__builtin_neon_" << MangleName(name, TypeVec[qi], ClassB) - << ": mask = " << "0x" << utohexstr(qmask) << "; break;\n"; + << ": mask = " << "0x" << utohexstr(qmask); + if (PtrArgNum >= 0) + OS << "; PtrArgNum = " << PtrArgNum; + if (HasConstPtr) + OS << "; HasConstPtr = true"; + OS << "; break;\n"; + } } OS << "#endif\n\n"; diff --git a/contrib/llvm/tools/clang/utils/TableGen/NeonEmitter.h b/contrib/llvm/tools/clang/utils/TableGen/NeonEmitter.h index 708ad3c..dec7451 100644 --- a/contrib/llvm/tools/clang/utils/TableGen/NeonEmitter.h +++ b/contrib/llvm/tools/clang/utils/TableGen/NeonEmitter.h @@ -86,6 +86,40 @@ enum ClassKind { 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 { diff --git a/contrib/llvm/tools/clang/utils/TableGen/TableGen.cpp b/contrib/llvm/tools/clang/utils/TableGen/TableGen.cpp index 5c016d3..5ff88db 100644 --- a/contrib/llvm/tools/clang/utils/TableGen/TableGen.cpp +++ b/contrib/llvm/tools/clang/utils/TableGen/TableGen.cpp @@ -36,6 +36,9 @@ enum ActionType { GenClangAttrPCHWrite, GenClangAttrSpellingList, GenClangAttrLateParsedList, + GenClangAttrTemplateInstantiate, + GenClangAttrParsedAttrList, + GenClangAttrParsedAttrKinds, GenClangDiagsDefs, GenClangDiagGroups, GenClangDiagsIndexName, @@ -71,6 +74,15 @@ namespace { clEnumValN(GenClangAttrLateParsedList, "gen-clang-attr-late-parsed-list", "Generate a clang attribute LateParsed list"), + clEnumValN(GenClangAttrTemplateInstantiate, + "gen-clang-attr-template-instantiate", + "Generate a clang template instantiate code"), + clEnumValN(GenClangAttrParsedAttrList, + "gen-clang-attr-parsed-attr-list", + "Generate a clang parsed attribute list"), + clEnumValN(GenClangAttrParsedAttrKinds, + "gen-clang-attr-parsed-attr-kinds", + "Generate a clang parsed attribute kinds"), clEnumValN(GenClangDiagsDefs, "gen-clang-diags-defs", "Generate Clang diagnostics definitions"), clEnumValN(GenClangDiagGroups, "gen-clang-diag-groups", @@ -96,7 +108,6 @@ namespace { ClangComponent("clang-component", cl::desc("Only use warnings from specified component"), cl::value_desc("component"), cl::Hidden); -} class ClangTableGenAction : public TableGenAction { public: @@ -123,6 +134,15 @@ public: case GenClangAttrLateParsedList: ClangAttrLateParsedListEmitter(Records).run(OS); break; + case GenClangAttrTemplateInstantiate: + ClangAttrTemplateInstantiateEmitter(Records).run(OS); + break; + case GenClangAttrParsedAttrList: + ClangAttrParsedAttrListEmitter(Records).run(OS); + break; + case GenClangAttrParsedAttrKinds: + ClangAttrParsedAttrKindsEmitter(Records).run(OS); + break; case GenClangDiagsDefs: ClangDiagsDefsEmitter(Records, ClangComponent).run(OS); break; @@ -157,14 +177,12 @@ public: case GenArmNeonTest: NeonEmitter(Records).runTests(OS); break; - default: - assert(1 && "Invalid Action"); - return true; } return false; } }; +} int main(int argc, char **argv) { sys::PrintStackTraceOnErrorSignal(); |