[cfe-commits] r141291 - in /cfe/trunk: ./ utils/TableGen/

Peter Collingbourne peter at pcc.me.uk
Thu Oct 6 06:03:14 PDT 2011


Author: pcc
Date: Thu Oct  6 08:03:08 2011
New Revision: 141291

URL: http://llvm.org/viewvc/llvm-project?rev=141291&view=rev
Log:
Add the Clang tblgen backends to Clang, and flip the switch to cause
the build systems to use clang-tblgen.

Added:
    cfe/trunk/utils/TableGen/
    cfe/trunk/utils/TableGen/CMakeLists.txt
    cfe/trunk/utils/TableGen/ClangASTNodesEmitter.cpp
    cfe/trunk/utils/TableGen/ClangASTNodesEmitter.h
    cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp
    cfe/trunk/utils/TableGen/ClangAttrEmitter.h
    cfe/trunk/utils/TableGen/ClangDiagnosticsEmitter.cpp
    cfe/trunk/utils/TableGen/ClangDiagnosticsEmitter.h
    cfe/trunk/utils/TableGen/ClangSACheckersEmitter.cpp
    cfe/trunk/utils/TableGen/ClangSACheckersEmitter.h
    cfe/trunk/utils/TableGen/Makefile
    cfe/trunk/utils/TableGen/NeonEmitter.cpp
    cfe/trunk/utils/TableGen/NeonEmitter.h
    cfe/trunk/utils/TableGen/OptParserEmitter.cpp
    cfe/trunk/utils/TableGen/OptParserEmitter.h
    cfe/trunk/utils/TableGen/TableGen.cpp
Modified:
    cfe/trunk/CMakeLists.txt
    cfe/trunk/Makefile

Modified: cfe/trunk/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/CMakeLists.txt?rev=141291&r1=141290&r2=141291&view=diff
==============================================================================
--- cfe/trunk/CMakeLists.txt (original)
+++ cfe/trunk/CMakeLists.txt Thu Oct  6 08:03:08 2011
@@ -153,7 +153,7 @@
   endif()
 
   set( LLVM_TARGET_DEFINITIONS ${CTG_SOURCE} )
-  tablegen( LLVM ${CTG_DEFAULT_ARGS} )
+  tablegen( CLANG ${CTG_DEFAULT_ARGS} )
 
   list( GET CTG_DEFAULT_ARGS 0 output_file )
   if( CTG_TARGET )
@@ -244,6 +244,7 @@
     "Version number that will be placed into the libclang library , in the form XX.YY")
 mark_as_advanced(CLANG_EXECUTABLE_VERSION LIBCLANG_LIBRARY_VERSION)
 
+add_subdirectory(utils/TableGen)
 
 option(CLANG_BUILD_EXAMPLES "Build CLANG example programs." OFF)
 if(CLANG_BUILD_EXAMPLES)

Modified: cfe/trunk/Makefile
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Makefile?rev=141291&r1=141290&r2=141291&view=diff
==============================================================================
--- cfe/trunk/Makefile (original)
+++ cfe/trunk/Makefile Thu Oct  6 08:03:08 2011
@@ -14,7 +14,7 @@
 
 IS_TOP_LEVEL := 1
 CLANG_LEVEL := .
-DIRS := include lib tools runtime docs unittests
+DIRS := utils/TableGen include lib tools runtime docs unittests
 
 PARALLEL_DIRS :=
 
@@ -63,9 +63,9 @@
 # Set up Clang's tblgen.
 ifndef CLANG_TBLGEN
   ifeq ($(LLVM_CROSS_COMPILING),1)
-    CLANG_TBLGEN := $(BuildLLVMToolDir)/llvm-tblgen$(BUILD_EXEEXT)
+    CLANG_TBLGEN := $(BuildLLVMToolDir)/clang-tblgen$(BUILD_EXEEXT)
   else
-    CLANG_TBLGEN := $(LLVMToolDir)/llvm-tblgen$(EXEEXT)
+    CLANG_TBLGEN := $(LLVMToolDir)/clang-tblgen$(EXEEXT)
   endif
 endif
 ClangTableGen = $(CLANG_TBLGEN) $(TableGen.Flags)

Added: cfe/trunk/utils/TableGen/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/CMakeLists.txt?rev=141291&view=auto
==============================================================================
--- cfe/trunk/utils/TableGen/CMakeLists.txt (added)
+++ cfe/trunk/utils/TableGen/CMakeLists.txt Thu Oct  6 08:03:08 2011
@@ -0,0 +1,12 @@
+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
+  )

Added: cfe/trunk/utils/TableGen/ClangASTNodesEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangASTNodesEmitter.cpp?rev=141291&view=auto
==============================================================================
--- cfe/trunk/utils/TableGen/ClangASTNodesEmitter.cpp (added)
+++ cfe/trunk/utils/TableGen/ClangASTNodesEmitter.cpp Thu Oct  6 08:03:08 2011
@@ -0,0 +1,168 @@
+//=== ClangASTNodesEmitter.cpp - Generate Clang AST node tables -*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// These tablegen backends emit Clang AST node tables
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangASTNodesEmitter.h"
+#include <set>
+using namespace llvm;
+
+//===----------------------------------------------------------------------===//
+// Statement Node Tables (.inc file) generation.
+//===----------------------------------------------------------------------===//
+
+// Returns the first and last non-abstract subrecords
+// Called recursively to ensure that nodes remain contiguous
+std::pair<Record *, Record *> ClangASTNodesEmitter::EmitNode(
+                                                           const ChildMap &Tree,
+                                                           raw_ostream &OS,
+                                                           Record *Base) {
+  std::string BaseName = macroName(Base->getName());
+
+  ChildIterator i = Tree.lower_bound(Base), e = Tree.upper_bound(Base);
+
+  Record *First = 0, *Last = 0;
+  // This might be the pseudo-node for Stmt; don't assume it has an Abstract
+  // bit
+  if (Base->getValue("Abstract") && !Base->getValueAsBit("Abstract"))
+    First = Last = Base;
+
+  for (; i != e; ++i) {
+    Record *R = i->second;
+    bool Abstract = R->getValueAsBit("Abstract");
+    std::string NodeName = macroName(R->getName());
+
+    OS << "#ifndef " << NodeName << "\n";
+    OS << "#  define " << NodeName << "(Type, Base) "
+        << BaseName << "(Type, Base)\n";
+    OS << "#endif\n";
+
+    if (Abstract)
+      OS << "ABSTRACT_" << macroName(Root.getName()) << "(" << NodeName << "("
+          << R->getName() << ", " << baseName(*Base) << "))\n";
+    else
+      OS << NodeName << "(" << R->getName() << ", "
+          << baseName(*Base) << ")\n";
+
+    if (Tree.find(R) != Tree.end()) {
+      const std::pair<Record *, Record *> &Result
+        = EmitNode(Tree, OS, R);
+      if (!First && Result.first)
+        First = Result.first;
+      if (Result.second)
+        Last = Result.second;
+    } else {
+      if (!Abstract) {
+        Last = R;
+
+        if (!First)
+          First = R;
+      }
+    }
+
+    OS << "#undef " << NodeName << "\n\n";
+  }
+
+  if (First) {
+    assert (Last && "Got a first node but not a last node for a range!");
+    if (Base == &Root)
+      OS << "LAST_" << macroName(Root.getName()) << "_RANGE(";
+    else
+      OS << macroName(Root.getName()) << "_RANGE(";
+    OS << Base->getName() << ", " << First->getName() << ", "
+       << Last->getName() << ")\n\n";
+  }
+
+  return std::make_pair(First, Last);
+}
+
+void ClangASTNodesEmitter::run(raw_ostream &OS) {
+  // Write the preamble
+  OS << "#ifndef ABSTRACT_" << macroName(Root.getName()) << "\n";
+  OS << "#  define ABSTRACT_" << macroName(Root.getName()) << "(Type) Type\n";
+  OS << "#endif\n";
+
+  OS << "#ifndef " << macroName(Root.getName()) << "_RANGE\n";
+  OS << "#  define "
+     << macroName(Root.getName()) << "_RANGE(Base, First, Last)\n";
+  OS << "#endif\n\n";
+
+  OS << "#ifndef LAST_" << macroName(Root.getName()) << "_RANGE\n";
+  OS << "#  define LAST_" 
+     << macroName(Root.getName()) << "_RANGE(Base, First, Last) " 
+     << macroName(Root.getName()) << "_RANGE(Base, First, Last)\n";
+  OS << "#endif\n\n";
+ 
+  // Emit statements
+  const std::vector<Record*> Stmts
+    = Records.getAllDerivedDefinitions(Root.getName());
+
+  ChildMap Tree;
+
+  for (unsigned i = 0, e = Stmts.size(); i != e; ++i) {
+    Record *R = Stmts[i];
+
+    if (R->getValue("Base"))
+      Tree.insert(std::make_pair(R->getValueAsDef("Base"), R));
+    else
+      Tree.insert(std::make_pair(&Root, R));
+  }
+
+  EmitNode(Tree, OS, &Root);
+
+  OS << "#undef " << macroName(Root.getName()) << "\n";
+  OS << "#undef " << macroName(Root.getName()) << "_RANGE\n";
+  OS << "#undef LAST_" << macroName(Root.getName()) << "_RANGE\n";
+  OS << "#undef ABSTRACT_" << macroName(Root.getName()) << "\n";
+}
+
+void ClangDeclContextEmitter::run(raw_ostream &OS) {
+  // FIXME: Find a .td file format to allow for this to be represented better.
+
+  OS << "#ifndef DECL_CONTEXT\n";
+  OS << "#  define DECL_CONTEXT(DECL)\n";
+  OS << "#endif\n";
+  
+  OS << "#ifndef DECL_CONTEXT_BASE\n";
+  OS << "#  define DECL_CONTEXT_BASE(DECL) DECL_CONTEXT(DECL)\n";
+  OS << "#endif\n";
+  
+  typedef std::set<Record*> RecordSet;
+  typedef std::vector<Record*> RecordVector;
+  
+  RecordVector DeclContextsVector
+    = Records.getAllDerivedDefinitions("DeclContext");
+  RecordVector Decls = Records.getAllDerivedDefinitions("Decl");
+  RecordSet DeclContexts (DeclContextsVector.begin(), DeclContextsVector.end());
+   
+  for (RecordVector::iterator i = Decls.begin(), e = Decls.end(); i != e; ++i) {
+    Record *R = *i;
+
+    if (R->getValue("Base")) {
+      Record *B = R->getValueAsDef("Base");
+      if (DeclContexts.find(B) != DeclContexts.end()) {
+        OS << "DECL_CONTEXT_BASE(" << B->getName() << ")\n";
+        DeclContexts.erase(B);
+      }
+    }
+  }
+
+  // To keep identical order, RecordVector may be used
+  // instead of RecordSet.
+  for (RecordVector::iterator
+         i = DeclContextsVector.begin(), e = DeclContextsVector.end();
+       i != e; ++i)
+    if (DeclContexts.find(*i) != DeclContexts.end())
+      OS << "DECL_CONTEXT(" << (*i)->getName() << ")\n";
+
+  OS << "#undef DECL_CONTEXT\n";
+  OS << "#undef DECL_CONTEXT_BASE\n";
+}

Added: cfe/trunk/utils/TableGen/ClangASTNodesEmitter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangASTNodesEmitter.h?rev=141291&view=auto
==============================================================================
--- cfe/trunk/utils/TableGen/ClangASTNodesEmitter.h (added)
+++ cfe/trunk/utils/TableGen/ClangASTNodesEmitter.h Thu Oct  6 08:03:08 2011
@@ -0,0 +1,84 @@
+//===- 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

Added: cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?rev=141291&view=auto
==============================================================================
--- cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp (added)
+++ cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp Thu Oct  6 08:03:08 2011
@@ -0,0 +1,788 @@
+//===- ClangAttrEmitter.cpp - Generate Clang attribute handling =-*- C++ -*--=//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// These tablegen backends emit Clang attribute processing code
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangAttrEmitter.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/TableGen/Record.h"
+#include <algorithm>
+#include <cctype>
+
+using namespace llvm;
+
+static const std::vector<StringRef>
+getValueAsListOfStrings(Record &R, StringRef FieldName) {
+  ListInit *List = R.getValueAsListInit(FieldName);
+  assert (List && "Got a null ListInit");
+
+  std::vector<StringRef> Strings;
+  Strings.reserve(List->getSize());
+
+  for (ListInit::const_iterator i = List->begin(), e = List->end();
+       i != e;
+       ++i) {
+    assert(*i && "Got a null element in a ListInit");
+    if (StringInit *S = dynamic_cast<StringInit *>(*i))
+      Strings.push_back(S->getValue());
+    else if (CodeInit *C = dynamic_cast<CodeInit *>(*i))
+      Strings.push_back(C->getValue());
+    else
+      assert(false && "Got a non-string, non-code element in a ListInit");
+  }
+
+  return Strings;
+}
+
+static std::string ReadPCHRecord(StringRef type) {
+  return StringSwitch<std::string>(type)
+    .EndsWith("Decl *", "GetLocalDeclAs<" 
+              + std::string(type, 0, type.size()-1) + ">(F, Record[Idx++])")
+    .Case("QualType", "getLocalType(F, Record[Idx++])")
+    .Case("Expr *", "ReadSubExpr()")
+    .Case("IdentifierInfo *", "GetIdentifierInfo(F, Record, Idx)")
+    .Case("SourceLocation", "ReadSourceLocation(F, Record, Idx)")
+    .Default("Record[Idx++]");
+}
+
+// Assumes that the way to get the value is SA->getname()
+static std::string WritePCHRecord(StringRef type, StringRef name) {
+  return StringSwitch<std::string>(type)
+    .EndsWith("Decl *", "AddDeclRef(" + std::string(name) +
+                        ", Record);\n")
+    .Case("QualType", "AddTypeRef(" + std::string(name) + ", Record);\n")
+    .Case("Expr *", "AddStmt(" + std::string(name) + ");\n")
+    .Case("IdentifierInfo *", 
+          "AddIdentifierRef(" + std::string(name) + ", Record);\n")
+    .Case("SourceLocation", 
+          "AddSourceLocation(" + std::string(name) + ", Record);\n")
+    .Default("Record.push_back(" + std::string(name) + ");\n");
+}
+
+namespace {
+  class Argument {
+    std::string lowerName, upperName;
+    StringRef attrName;
+
+  public:
+    Argument(Record &Arg, StringRef Attr)
+      : lowerName(Arg.getValueAsString("Name")), upperName(lowerName),
+        attrName(Attr) {
+      if (!lowerName.empty()) {
+        lowerName[0] = std::tolower(lowerName[0]);
+        upperName[0] = std::toupper(upperName[0]);
+      }
+    }
+    virtual ~Argument() {}
+
+    StringRef getLowerName() const { return lowerName; }
+    StringRef getUpperName() const { return upperName; }
+    StringRef getAttrName() const { return attrName; }
+
+    // These functions print the argument contents formatted in different ways.
+    virtual void writeAccessors(raw_ostream &OS) const = 0;
+    virtual void writeAccessorDefinitions(raw_ostream &OS) const {}
+    virtual void writeCloneArgs(raw_ostream &OS) const = 0;
+    virtual void writeCtorBody(raw_ostream &OS) const {}
+    virtual void writeCtorInitializers(raw_ostream &OS) const = 0;
+    virtual void writeCtorParameters(raw_ostream &OS) const = 0;
+    virtual void writeDeclarations(raw_ostream &OS) const = 0;
+    virtual void writePCHReadArgs(raw_ostream &OS) const = 0;
+    virtual void writePCHReadDecls(raw_ostream &OS) const = 0;
+    virtual void writePCHWrite(raw_ostream &OS) const = 0;
+  };
+
+  class SimpleArgument : public Argument {
+    std::string type;
+
+  public:
+    SimpleArgument(Record &Arg, StringRef Attr, std::string T)
+      : Argument(Arg, Attr), type(T)
+    {}
+
+    void writeAccessors(raw_ostream &OS) const {
+      OS << "  " << type << " get" << getUpperName() << "() const {\n";
+      OS << "    return " << getLowerName() << ";\n";
+      OS << "  }";
+    }
+    void writeCloneArgs(raw_ostream &OS) const {
+      OS << getLowerName();
+    }
+    void writeCtorInitializers(raw_ostream &OS) const {
+      OS << getLowerName() << "(" << getUpperName() << ")";
+    }
+    void writeCtorParameters(raw_ostream &OS) const {
+      OS << type << " " << getUpperName();
+    }
+    void writeDeclarations(raw_ostream &OS) const {
+      OS << type << " " << getLowerName() << ";";
+    }
+    void writePCHReadDecls(raw_ostream &OS) const {
+      std::string read = ReadPCHRecord(type);
+      OS << "    " << type << " " << getLowerName() << " = " << read << ";\n";
+    }
+    void writePCHReadArgs(raw_ostream &OS) const {
+      OS << getLowerName();
+    }
+    void writePCHWrite(raw_ostream &OS) const {
+      OS << "    " << WritePCHRecord(type, "SA->get" +
+                                           std::string(getUpperName()) + "()");
+    }
+  };
+
+  class StringArgument : public Argument {
+  public:
+    StringArgument(Record &Arg, StringRef Attr)
+      : Argument(Arg, Attr)
+    {}
+
+    void writeAccessors(raw_ostream &OS) const {
+      OS << "  llvm::StringRef get" << getUpperName() << "() const {\n";
+      OS << "    return llvm::StringRef(" << getLowerName() << ", "
+         << getLowerName() << "Length);\n";
+      OS << "  }\n";
+      OS << "  unsigned get" << getUpperName() << "Length() const {\n";
+      OS << "    return " << getLowerName() << "Length;\n";
+      OS << "  }\n";
+      OS << "  void set" << getUpperName()
+         << "(ASTContext &C, llvm::StringRef S) {\n";
+      OS << "    " << getLowerName() << "Length = S.size();\n";
+      OS << "    this->" << getLowerName() << " = new (C, 1) char ["
+         << getLowerName() << "Length];\n";
+      OS << "    std::memcpy(this->" << getLowerName() << ", S.data(), "
+         << getLowerName() << "Length);\n";
+      OS << "  }";
+    }
+    void writeCloneArgs(raw_ostream &OS) const {
+      OS << "get" << getUpperName() << "()";
+    }
+    void writeCtorBody(raw_ostream &OS) const {
+      OS << "      std::memcpy(" << getLowerName() << ", " << getUpperName()
+         << ".data(), " << getLowerName() << "Length);";
+    }
+    void writeCtorInitializers(raw_ostream &OS) const {
+      OS << getLowerName() << "Length(" << getUpperName() << ".size()),"
+         << getLowerName() << "(new (Ctx, 1) char[" << getLowerName()
+         << "Length])";
+    }
+    void writeCtorParameters(raw_ostream &OS) const {
+      OS << "llvm::StringRef " << getUpperName();
+    }
+    void writeDeclarations(raw_ostream &OS) const {
+      OS << "unsigned " << getLowerName() << "Length;\n";
+      OS << "char *" << getLowerName() << ";";
+    }
+    void writePCHReadDecls(raw_ostream &OS) const {
+      OS << "    std::string " << getLowerName()
+         << "= ReadString(Record, Idx);\n";
+    }
+    void writePCHReadArgs(raw_ostream &OS) const {
+      OS << getLowerName();
+    }
+    void writePCHWrite(raw_ostream &OS) const {
+      OS << "    AddString(SA->get" << getUpperName() << "(), Record);\n";
+    }
+  };
+
+  class AlignedArgument : public Argument {
+  public:
+    AlignedArgument(Record &Arg, StringRef Attr)
+      : Argument(Arg, Attr)
+    {}
+
+    void writeAccessors(raw_ostream &OS) const {
+      OS << "  bool is" << getUpperName() << "Dependent() const;\n";
+
+      OS << "  unsigned get" << getUpperName() << "(ASTContext &Ctx) const;\n";
+
+      OS << "  bool is" << getUpperName() << "Expr() const {\n";
+      OS << "    return is" << getLowerName() << "Expr;\n";
+      OS << "  }\n";
+
+      OS << "  Expr *get" << getUpperName() << "Expr() const {\n";
+      OS << "    assert(is" << getLowerName() << "Expr);\n";
+      OS << "    return " << getLowerName() << "Expr;\n";
+      OS << "  }\n";
+
+      OS << "  TypeSourceInfo *get" << getUpperName() << "Type() const {\n";
+      OS << "    assert(!is" << getLowerName() << "Expr);\n";
+      OS << "    return " << getLowerName() << "Type;\n";
+      OS << "  }";
+    }
+    void writeAccessorDefinitions(raw_ostream &OS) const {
+      OS << "bool " << getAttrName() << "Attr::is" << getUpperName()
+         << "Dependent() const {\n";
+      OS << "  if (is" << getLowerName() << "Expr)\n";
+      OS << "    return " << getLowerName() << "Expr && (" << getLowerName()
+         << "Expr->isValueDependent() || " << getLowerName()
+         << "Expr->isTypeDependent());\n"; 
+      OS << "  else\n";
+      OS << "    return " << getLowerName()
+         << "Type->getType()->isDependentType();\n";
+      OS << "}\n";
+
+      // FIXME: Do not do the calculation here
+      // FIXME: Handle types correctly
+      // A null pointer means maximum alignment
+      // FIXME: Load the platform-specific maximum alignment, rather than
+      //        16, the x86 max.
+      OS << "unsigned " << getAttrName() << "Attr::get" << getUpperName()
+         << "(ASTContext &Ctx) const {\n";
+      OS << "  assert(!is" << getUpperName() << "Dependent());\n";
+      OS << "  if (is" << getLowerName() << "Expr)\n";
+      OS << "    return (" << getLowerName() << "Expr ? " << getLowerName()
+         << "Expr->EvaluateAsInt(Ctx).getZExtValue() : 16)"
+         << "* Ctx.getCharWidth();\n";
+      OS << "  else\n";
+      OS << "    return 0; // FIXME\n";
+      OS << "}\n";
+    }
+    void writeCloneArgs(raw_ostream &OS) const {
+      OS << "is" << getLowerName() << "Expr, is" << getLowerName()
+         << "Expr ? static_cast<void*>(" << getLowerName()
+         << "Expr) : " << getLowerName()
+         << "Type";
+    }
+    void writeCtorBody(raw_ostream &OS) const {
+      OS << "    if (is" << getLowerName() << "Expr)\n";
+      OS << "       " << getLowerName() << "Expr = reinterpret_cast<Expr *>("
+         << getUpperName() << ");\n";
+      OS << "    else\n";
+      OS << "       " << getLowerName()
+         << "Type = reinterpret_cast<TypeSourceInfo *>(" << getUpperName()
+         << ");";
+    }
+    void writeCtorInitializers(raw_ostream &OS) const {
+      OS << "is" << getLowerName() << "Expr(Is" << getUpperName() << "Expr)";
+    }
+    void writeCtorParameters(raw_ostream &OS) const {
+      OS << "bool Is" << getUpperName() << "Expr, void *" << getUpperName();
+    }
+    void writeDeclarations(raw_ostream &OS) const {
+      OS << "bool is" << getLowerName() << "Expr;\n";
+      OS << "union {\n";
+      OS << "Expr *" << getLowerName() << "Expr;\n";
+      OS << "TypeSourceInfo *" << getLowerName() << "Type;\n";
+      OS << "};";
+    }
+    void writePCHReadArgs(raw_ostream &OS) const {
+      OS << "is" << getLowerName() << "Expr, " << getLowerName() << "Ptr";
+    }
+    void writePCHReadDecls(raw_ostream &OS) const {
+      OS << "    bool is" << getLowerName() << "Expr = Record[Idx++];\n";
+      OS << "    void *" << getLowerName() << "Ptr;\n";
+      OS << "    if (is" << getLowerName() << "Expr)\n";
+      OS << "      " << getLowerName() << "Ptr = ReadExpr(F);\n";
+      OS << "    else\n";
+      OS << "      " << getLowerName()
+         << "Ptr = GetTypeSourceInfo(F, Record, Idx);\n";
+    }
+    void writePCHWrite(raw_ostream &OS) const {
+      OS << "    Record.push_back(SA->is" << getUpperName() << "Expr());\n";
+      OS << "    if (SA->is" << getUpperName() << "Expr())\n";
+      OS << "      AddStmt(SA->get" << getUpperName() << "Expr());\n";
+      OS << "    else\n";
+      OS << "      AddTypeSourceInfo(SA->get" << getUpperName()
+         << "Type(), Record);\n";
+    }
+  };
+
+  class VariadicArgument : public Argument {
+    std::string type;
+
+  public:
+    VariadicArgument(Record &Arg, StringRef Attr, std::string T)
+      : Argument(Arg, Attr), type(T)
+    {}
+
+    std::string getType() const { return type; }
+
+    void writeAccessors(raw_ostream &OS) const {
+      OS << "  typedef " << type << "* " << getLowerName() << "_iterator;\n";
+      OS << "  " << getLowerName() << "_iterator " << getLowerName()
+         << "_begin() const {\n";
+      OS << "    return " << getLowerName() << ";\n";
+      OS << "  }\n";
+      OS << "  " << getLowerName() << "_iterator " << getLowerName()
+         << "_end() const {\n";
+      OS << "    return " << getLowerName() << " + " << getLowerName()
+         << "Size;\n";
+      OS << "  }\n";
+      OS << "  unsigned " << getLowerName() << "_size() const {\n"
+         << "    return " << getLowerName() << "Size;\n;";
+      OS << "  }";
+    }
+    void writeCloneArgs(raw_ostream &OS) const {
+      OS << getLowerName() << ", " << getLowerName() << "Size";
+    }
+    void writeCtorBody(raw_ostream &OS) const {
+      // FIXME: memcpy is not safe on non-trivial types.
+      OS << "    std::memcpy(" << getLowerName() << ", " << getUpperName()
+         << ", " << getLowerName() << "Size * sizeof(" << getType() << "));\n";
+    }
+    void writeCtorInitializers(raw_ostream &OS) const {
+      OS << getLowerName() << "Size(" << getUpperName() << "Size), "
+         << getLowerName() << "(new (Ctx, 16) " << getType() << "["
+         << getLowerName() << "Size])";
+    }
+    void writeCtorParameters(raw_ostream &OS) const {
+      OS << getType() << " *" << getUpperName() << ", unsigned "
+         << getUpperName() << "Size";
+    }
+    void writeDeclarations(raw_ostream &OS) const {
+      OS << "  unsigned " << getLowerName() << "Size;\n";
+      OS << "  " << getType() << " *" << getLowerName() << ";";
+    }
+    void writePCHReadDecls(raw_ostream &OS) const {
+      OS << "  unsigned " << getLowerName() << "Size = Record[Idx++];\n";
+      OS << "  llvm::SmallVector<" << type << ", 4> " << getLowerName()
+         << ";\n";
+      OS << "  " << getLowerName() << ".reserve(" << getLowerName()
+         << "Size);\n";
+      OS << "  for (unsigned i = " << getLowerName() << "Size; i; --i)\n";
+      
+      std::string read = ReadPCHRecord(type);
+      OS << "    " << getLowerName() << ".push_back(" << read << ");\n";
+    }
+    void writePCHReadArgs(raw_ostream &OS) const {
+      OS << getLowerName() << ".data(), " << getLowerName() << "Size";
+    }
+    void writePCHWrite(raw_ostream &OS) const{
+      OS << "    Record.push_back(SA->" << getLowerName() << "_size());\n";
+      OS << "    for (" << getAttrName() << "Attr::" << getLowerName()
+         << "_iterator i = SA->" << getLowerName() << "_begin(), e = SA->"
+         << getLowerName() << "_end(); i != e; ++i)\n";
+      OS << "      " << WritePCHRecord(type, "(*i)");
+    }
+  };
+
+  class EnumArgument : public Argument {
+    std::string type;
+    std::vector<StringRef> values, enums;
+  public:
+    EnumArgument(Record &Arg, StringRef Attr)
+      : Argument(Arg, Attr), type(Arg.getValueAsString("Type")),
+        values(getValueAsListOfStrings(Arg, "Values")),
+        enums(getValueAsListOfStrings(Arg, "Enums"))
+    {}
+
+    void writeAccessors(raw_ostream &OS) const {
+      OS << "  " << type << " get" << getUpperName() << "() const {\n";
+      OS << "    return " << getLowerName() << ";\n";
+      OS << "  }";
+    }
+    void writeCloneArgs(raw_ostream &OS) const {
+      OS << getLowerName();
+    }
+    void writeCtorInitializers(raw_ostream &OS) const {
+      OS << getLowerName() << "(" << getUpperName() << ")";
+    }
+    void writeCtorParameters(raw_ostream &OS) const {
+      OS << type << " " << getUpperName();
+    }
+    void writeDeclarations(raw_ostream &OS) const {
+      // Calculate the various enum values
+      std::vector<StringRef> uniques(enums);
+      std::sort(uniques.begin(), uniques.end());
+      uniques.erase(std::unique(uniques.begin(), uniques.end()),
+                    uniques.end());
+      // FIXME: Emit a proper error
+      assert(!uniques.empty());
+
+      std::vector<StringRef>::iterator i = uniques.begin(),
+                                       e = uniques.end();
+      // The last one needs to not have a comma.
+      --e;
+
+      OS << "public:\n";
+      OS << "  enum " << type << " {\n";
+      for (; i != e; ++i)
+        OS << "    " << *i << ",\n";
+      OS << "    " << *e << "\n";
+      OS << "  };\n";
+      OS << "private:\n";
+      OS << "  " << type << " " << getLowerName() << ";";
+    }
+    void writePCHReadDecls(raw_ostream &OS) const {
+      OS << "    " << getAttrName() << "Attr::" << type << " " << getLowerName()
+         << "(static_cast<" << getAttrName() << "Attr::" << type
+         << ">(Record[Idx++]));\n";
+    }
+    void writePCHReadArgs(raw_ostream &OS) const {
+      OS << getLowerName();
+    }
+    void writePCHWrite(raw_ostream &OS) const {
+      OS << "Record.push_back(SA->get" << getUpperName() << "());\n";
+    }
+  };
+
+  class VersionArgument : public Argument {
+  public:
+    VersionArgument(Record &Arg, StringRef Attr)
+      : Argument(Arg, Attr)
+    {}
+
+    void writeAccessors(raw_ostream &OS) const {
+      OS << "  VersionTuple get" << getUpperName() << "() const {\n";
+      OS << "    return " << getLowerName() << ";\n";
+      OS << "  }\n";
+      OS << "  void set" << getUpperName() 
+         << "(ASTContext &C, VersionTuple V) {\n";
+      OS << "    " << getLowerName() << " = V;\n";
+      OS << "  }";
+    }
+    void writeCloneArgs(raw_ostream &OS) const {
+      OS << "get" << getUpperName() << "()";
+    }
+    void writeCtorBody(raw_ostream &OS) const {
+    }
+    void writeCtorInitializers(raw_ostream &OS) const {
+      OS << getLowerName() << "(" << getUpperName() << ")";
+    }
+    void writeCtorParameters(raw_ostream &OS) const {
+      OS << "VersionTuple " << getUpperName();
+    }
+    void writeDeclarations(raw_ostream &OS) const {
+      OS << "VersionTuple " << getLowerName() << ";\n";
+    }
+    void writePCHReadDecls(raw_ostream &OS) const {
+      OS << "    VersionTuple " << getLowerName()
+         << "= ReadVersionTuple(Record, Idx);\n";
+    }
+    void writePCHReadArgs(raw_ostream &OS) const {
+      OS << getLowerName();
+    }
+    void writePCHWrite(raw_ostream &OS) const {
+      OS << "    AddVersionTuple(SA->get" << getUpperName() << "(), Record);\n";
+    }
+  };
+}
+
+static Argument *createArgument(Record &Arg, StringRef Attr,
+                                Record *Search = 0) {
+  if (!Search)
+    Search = &Arg;
+
+  Argument *Ptr = 0;
+  llvm::StringRef ArgName = Search->getName();
+
+  if (ArgName == "AlignedArgument") Ptr = new AlignedArgument(Arg, Attr);
+  else if (ArgName == "EnumArgument") Ptr = new EnumArgument(Arg, Attr);
+  else if (ArgName == "ExprArgument") Ptr = new SimpleArgument(Arg, Attr,
+                                                               "Expr *");
+  else if (ArgName == "FunctionArgument")
+    Ptr = new SimpleArgument(Arg, Attr, "FunctionDecl *");
+  else if (ArgName == "IdentifierArgument")
+    Ptr = new SimpleArgument(Arg, Attr, "IdentifierInfo *");
+  else if (ArgName == "BoolArgument") Ptr = new SimpleArgument(Arg, Attr, 
+                                                               "bool");
+  else if (ArgName == "IntArgument") Ptr = new SimpleArgument(Arg, Attr, "int");
+  else if (ArgName == "StringArgument") Ptr = new StringArgument(Arg, Attr);
+  else if (ArgName == "TypeArgument")
+    Ptr = new SimpleArgument(Arg, Attr, "QualType");
+  else if (ArgName == "UnsignedArgument")
+    Ptr = new SimpleArgument(Arg, Attr, "unsigned");
+  else if (ArgName == "SourceLocArgument")
+    Ptr = new SimpleArgument(Arg, Attr, "SourceLocation");
+  else if (ArgName == "VariadicUnsignedArgument")
+    Ptr = new VariadicArgument(Arg, Attr, "unsigned");
+  else if (ArgName == "VariadicExprArgument")
+    Ptr = new VariadicArgument(Arg, Attr, "Expr *");
+  else if (ArgName == "VersionArgument")
+    Ptr = new VersionArgument(Arg, Attr);
+
+  if (!Ptr) {
+    std::vector<Record*> Bases = Search->getSuperClasses();
+    for (std::vector<Record*>::iterator i = Bases.begin(), e = Bases.end();
+         i != e; ++i) {
+      Ptr = createArgument(Arg, Attr, *i);
+      if (Ptr)
+        break;
+    }
+  }
+  return Ptr;
+}
+
+void ClangAttrClassEmitter::run(raw_ostream &OS) {
+  OS << "// This file is generated by TableGen. Do not edit.\n\n";
+  OS << "#ifndef LLVM_CLANG_ATTR_CLASSES_INC\n";
+  OS << "#define LLVM_CLANG_ATTR_CLASSES_INC\n\n";
+
+  std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
+
+  for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end();
+       i != e; ++i) {
+    Record &R = **i;
+    const std::string &SuperName = R.getSuperClasses().back()->getName();
+
+    OS << "class " << R.getName() << "Attr : public " << SuperName << " {\n";
+
+    std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
+    std::vector<Argument*> Args;
+    std::vector<Argument*>::iterator ai, ae;
+    Args.reserve(ArgRecords.size());
+
+    for (std::vector<Record*>::iterator ri = ArgRecords.begin(),
+                                        re = ArgRecords.end();
+         ri != re; ++ri) {
+      Record &ArgRecord = **ri;
+      Argument *Arg = createArgument(ArgRecord, R.getName());
+      assert(Arg);
+      Args.push_back(Arg);
+
+      Arg->writeDeclarations(OS);
+      OS << "\n\n";
+    }
+
+    ae = Args.end();
+
+    OS << "\n public:\n";
+    OS << "  " << R.getName() << "Attr(SourceRange R, ASTContext &Ctx\n";
+    
+    for (ai = Args.begin(); ai != ae; ++ai) {
+      OS << "              , ";
+      (*ai)->writeCtorParameters(OS);
+      OS << "\n";
+    }
+    
+    OS << "             )\n";
+    OS << "    : " << SuperName << "(attr::" << R.getName() << ", R)\n";
+
+    for (ai = Args.begin(); ai != ae; ++ai) {
+      OS << "              , ";
+      (*ai)->writeCtorInitializers(OS);
+      OS << "\n";
+    }
+
+    OS << "  {\n";
+  
+    for (ai = Args.begin(); ai != ae; ++ai) {
+      (*ai)->writeCtorBody(OS);
+      OS << "\n";
+    }
+    OS << "  }\n\n";
+
+    OS << "  virtual " << R.getName() << "Attr *clone (ASTContext &C) const;\n";
+
+    for (ai = Args.begin(); ai != ae; ++ai) {
+      (*ai)->writeAccessors(OS);
+      OS << "\n\n";
+    }
+
+    OS << R.getValueAsCode("AdditionalMembers");
+    OS << "\n\n";
+
+    OS << "  static bool classof(const Attr *A) { return A->getKind() == "
+       << "attr::" << R.getName() << "; }\n";
+    OS << "  static bool classof(const " << R.getName()
+       << "Attr *) { return true; }\n";
+    OS << "};\n\n";
+  }
+
+  OS << "#endif\n";
+}
+
+void ClangAttrImplEmitter::run(raw_ostream &OS) {
+  OS << "// This file is generated by TableGen. Do not edit.\n\n";
+
+  std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
+  std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ri, re;
+  std::vector<Argument*>::iterator ai, ae;
+
+  for (; i != e; ++i) {
+    Record &R = **i;
+    std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
+    std::vector<Argument*> Args;
+    for (ri = ArgRecords.begin(), re = ArgRecords.end(); ri != re; ++ri)
+      Args.push_back(createArgument(**ri, R.getName()));
+
+    for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai)
+      (*ai)->writeAccessorDefinitions(OS);
+
+    OS << R.getName() << "Attr *" << R.getName()
+       << "Attr::clone(ASTContext &C) const {\n";
+    OS << "  return new (C) " << R.getName() << "Attr(getLocation(), C";
+    for (ai = Args.begin(); ai != ae; ++ai) {
+      OS << ", ";
+      (*ai)->writeCloneArgs(OS);
+    }
+    OS << ");\n}\n\n";
+  }
+}
+
+static void EmitAttrList(raw_ostream &OS, StringRef Class,
+                         const std::vector<Record*> &AttrList) {
+  std::vector<Record*>::const_iterator i = AttrList.begin(), e = AttrList.end();
+
+  if (i != e) {
+    // Move the end iterator back to emit the last attribute.
+    for(--e; i != e; ++i)
+      OS << Class << "(" << (*i)->getName() << ")\n";
+    
+    OS << "LAST_" << Class << "(" << (*i)->getName() << ")\n\n";
+  }
+}
+
+void ClangAttrListEmitter::run(raw_ostream &OS) {
+  OS << "// This file is generated by TableGen. Do not edit.\n\n";
+
+  OS << "#ifndef LAST_ATTR\n";
+  OS << "#define LAST_ATTR(NAME) ATTR(NAME)\n";
+  OS << "#endif\n\n";
+
+  OS << "#ifndef INHERITABLE_ATTR\n";
+  OS << "#define INHERITABLE_ATTR(NAME) ATTR(NAME)\n";
+  OS << "#endif\n\n";
+
+  OS << "#ifndef LAST_INHERITABLE_ATTR\n";
+  OS << "#define LAST_INHERITABLE_ATTR(NAME) INHERITABLE_ATTR(NAME)\n";
+  OS << "#endif\n\n";
+
+  OS << "#ifndef INHERITABLE_PARAM_ATTR\n";
+  OS << "#define INHERITABLE_PARAM_ATTR(NAME) ATTR(NAME)\n";
+  OS << "#endif\n\n";
+
+  OS << "#ifndef LAST_INHERITABLE_PARAM_ATTR\n";
+  OS << "#define LAST_INHERITABLE_PARAM_ATTR(NAME)"
+        " INHERITABLE_PARAM_ATTR(NAME)\n";
+  OS << "#endif\n\n";
+
+  Record *InhClass = Records.getClass("InheritableAttr");
+  Record *InhParamClass = Records.getClass("InheritableParamAttr");
+  std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
+                       NonInhAttrs, InhAttrs, InhParamAttrs;
+  for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end();
+       i != e; ++i) {
+    if ((*i)->isSubClassOf(InhParamClass))
+      InhParamAttrs.push_back(*i);
+    else if ((*i)->isSubClassOf(InhClass))
+      InhAttrs.push_back(*i);
+    else
+      NonInhAttrs.push_back(*i);
+  }
+
+  EmitAttrList(OS, "INHERITABLE_PARAM_ATTR", InhParamAttrs);
+  EmitAttrList(OS, "INHERITABLE_ATTR", InhAttrs);
+  EmitAttrList(OS, "ATTR", NonInhAttrs);
+
+  OS << "#undef LAST_ATTR\n";
+  OS << "#undef INHERITABLE_ATTR\n";
+  OS << "#undef LAST_INHERITABLE_ATTR\n";
+  OS << "#undef LAST_INHERITABLE_PARAM_ATTR\n";
+  OS << "#undef ATTR\n";
+}
+
+void ClangAttrPCHReadEmitter::run(raw_ostream &OS) {
+  OS << "// This file is generated by TableGen. Do not edit.\n\n";
+
+  Record *InhClass = Records.getClass("InheritableAttr");
+  std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
+                       ArgRecords;
+  std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae;
+  std::vector<Argument*> Args;
+  std::vector<Argument*>::iterator ri, re;
+
+  OS << "  switch (Kind) {\n";
+  OS << "  default:\n";
+  OS << "    assert(0 && \"Unknown attribute!\");\n";
+  OS << "    break;\n";
+  for (; i != e; ++i) {
+    Record &R = **i;
+    OS << "  case attr::" << R.getName() << ": {\n";
+    if (R.isSubClassOf(InhClass))
+      OS << "    bool isInherited = Record[Idx++];\n";
+    ArgRecords = R.getValueAsListOfDefs("Args");
+    Args.clear();
+    for (ai = ArgRecords.begin(), ae = ArgRecords.end(); ai != ae; ++ai) {
+      Argument *A = createArgument(**ai, R.getName());
+      Args.push_back(A);
+      A->writePCHReadDecls(OS);
+    }
+    OS << "    New = new (Context) " << R.getName() << "Attr(Range, Context";
+    for (ri = Args.begin(), re = Args.end(); ri != re; ++ri) {
+      OS << ", ";
+      (*ri)->writePCHReadArgs(OS);
+    }
+    OS << ");\n";
+    if (R.isSubClassOf(InhClass))
+      OS << "    cast<InheritableAttr>(New)->setInherited(isInherited);\n";
+    OS << "    break;\n";
+    OS << "  }\n";
+  }
+  OS << "  }\n";
+}
+
+void ClangAttrPCHWriteEmitter::run(raw_ostream &OS) {
+  Record *InhClass = Records.getClass("InheritableAttr");
+  std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;
+  std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae;
+
+  OS << "  switch (A->getKind()) {\n";
+  OS << "  default:\n";
+  OS << "    llvm_unreachable(\"Unknown attribute kind!\");\n";
+  OS << "    break;\n";
+  for (; i != e; ++i) {
+    Record &R = **i;
+    OS << "  case attr::" << R.getName() << ": {\n";
+    Args = R.getValueAsListOfDefs("Args");
+    if (R.isSubClassOf(InhClass) || !Args.empty())
+      OS << "    const " << R.getName() << "Attr *SA = cast<" << R.getName()
+         << "Attr>(A);\n";
+    if (R.isSubClassOf(InhClass))
+      OS << "    Record.push_back(SA->isInherited());\n";
+    for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai)
+      createArgument(**ai, R.getName())->writePCHWrite(OS);
+    OS << "    break;\n";
+    OS << "  }\n";
+  }
+  OS << "  }\n";
+}
+
+void ClangAttrSpellingListEmitter::run(raw_ostream &OS) {
+  OS << "// This file is generated by TableGen. Do not edit.\n\n";
+
+  std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
+  
+  for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); I != E; ++I) {
+    Record &Attr = **I;
+
+    std::vector<StringRef> Spellings = getValueAsListOfStrings(Attr, "Spellings");
+
+    for (std::vector<StringRef>::const_iterator I = Spellings.begin(), E = Spellings.end(); I != E; ++I) {
+      StringRef Spelling = *I;
+      OS << ".Case(\"" << Spelling << "\", true)\n";
+    }
+  }
+
+}
+
+void ClangAttrLateParsedListEmitter::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 LateParsed = Attr.getValueAsBit("LateParsed");
+
+    if (LateParsed) {
+      std::vector<StringRef> Spellings =
+        getValueAsListOfStrings(Attr, "Spellings");
+
+      for (std::vector<StringRef>::const_iterator I = Spellings.begin(),
+           E = Spellings.end(); I != E; ++I) {
+        OS << ".Case(\"" << (*I) << "\", " << LateParsed << ")\n";
+      }
+    }
+  }
+}

Added: cfe/trunk/utils/TableGen/ClangAttrEmitter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.h?rev=141291&view=auto
==============================================================================
--- cfe/trunk/utils/TableGen/ClangAttrEmitter.h (added)
+++ cfe/trunk/utils/TableGen/ClangAttrEmitter.h Thu Oct  6 08:03:08 2011
@@ -0,0 +1,114 @@
+//===- 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);
+};
+
+}
+
+#endif

Added: cfe/trunk/utils/TableGen/ClangDiagnosticsEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangDiagnosticsEmitter.cpp?rev=141291&view=auto
==============================================================================
--- cfe/trunk/utils/TableGen/ClangDiagnosticsEmitter.cpp (added)
+++ cfe/trunk/utils/TableGen/ClangDiagnosticsEmitter.cpp Thu Oct  6 08:03:08 2011
@@ -0,0 +1,378 @@
+//=- ClangDiagnosticsEmitter.cpp - Generate Clang diagnostics tables -*- C++ -*-
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// These tablegen backends emit Clang diagnostics tables.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangDiagnosticsEmitter.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/VectorExtras.h"
+#include <map>
+#include <algorithm>
+#include <functional>
+using namespace llvm;
+
+//===----------------------------------------------------------------------===//
+// Diagnostic category computation code.
+//===----------------------------------------------------------------------===//
+
+namespace {
+class DiagGroupParentMap {
+  RecordKeeper &Records;
+  std::map<const Record*, std::vector<Record*> > Mapping;
+public:
+  DiagGroupParentMap(RecordKeeper &records) : Records(records) {
+    std::vector<Record*> DiagGroups
+      = Records.getAllDerivedDefinitions("DiagGroup");
+    for (unsigned i = 0, e = DiagGroups.size(); i != e; ++i) {
+      std::vector<Record*> SubGroups =
+        DiagGroups[i]->getValueAsListOfDefs("SubGroups");
+      for (unsigned j = 0, e = SubGroups.size(); j != e; ++j)
+        Mapping[SubGroups[j]].push_back(DiagGroups[i]);
+    }
+  }
+  
+  const std::vector<Record*> &getParents(const Record *Group) {
+    return Mapping[Group];
+  }
+};
+} // end anonymous namespace.
+
+
+static std::string
+getCategoryFromDiagGroup(const Record *Group,
+                         DiagGroupParentMap &DiagGroupParents) {
+  // If the DiagGroup has a category, return it.
+  std::string CatName = Group->getValueAsString("CategoryName");
+  if (!CatName.empty()) return CatName;
+  
+  // The diag group may the subgroup of one or more other diagnostic groups,
+  // check these for a category as well.
+  const std::vector<Record*> &Parents = DiagGroupParents.getParents(Group);
+  for (unsigned i = 0, e = Parents.size(); i != e; ++i) {
+    CatName = getCategoryFromDiagGroup(Parents[i], DiagGroupParents);
+    if (!CatName.empty()) return CatName;
+  }
+  return "";
+}
+
+/// getDiagnosticCategory - Return the category that the specified diagnostic
+/// lives in.
+static std::string getDiagnosticCategory(const Record *R,
+                                         DiagGroupParentMap &DiagGroupParents) {
+  // If the diagnostic is in a group, and that group has a category, use it.
+  if (DefInit *Group = dynamic_cast<DefInit*>(R->getValueInit("Group"))) {
+    // Check the diagnostic's diag group for a category.
+    std::string CatName = getCategoryFromDiagGroup(Group->getDef(),
+                                                   DiagGroupParents);
+    if (!CatName.empty()) return CatName;
+  }
+  
+  // If the diagnostic itself has a category, get it.
+  return R->getValueAsString("CategoryName");
+}
+
+namespace {
+  class DiagCategoryIDMap {
+    RecordKeeper &Records;
+    StringMap<unsigned> CategoryIDs;
+    std::vector<std::string> CategoryStrings;
+  public:
+    DiagCategoryIDMap(RecordKeeper &records) : Records(records) {
+      DiagGroupParentMap ParentInfo(Records);
+      
+      // The zero'th category is "".
+      CategoryStrings.push_back("");
+      CategoryIDs[""] = 0;
+      
+      std::vector<Record*> Diags =
+      Records.getAllDerivedDefinitions("Diagnostic");
+      for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
+        std::string Category = getDiagnosticCategory(Diags[i], ParentInfo);
+        if (Category.empty()) continue;  // Skip diags with no category.
+        
+        unsigned &ID = CategoryIDs[Category];
+        if (ID != 0) continue;  // Already seen.
+        
+        ID = CategoryStrings.size();
+        CategoryStrings.push_back(Category);
+      }
+    }
+    
+    unsigned getID(StringRef CategoryString) {
+      return CategoryIDs[CategoryString];
+    }
+    
+    typedef std::vector<std::string>::iterator iterator;
+    iterator begin() { return CategoryStrings.begin(); }
+    iterator end() { return CategoryStrings.end(); }
+  };
+} // end anonymous namespace.
+
+
+//===----------------------------------------------------------------------===//
+// Warning Tables (.inc file) generation.
+//===----------------------------------------------------------------------===//
+
+void ClangDiagsDefsEmitter::run(raw_ostream &OS) {
+  // Write the #if guard
+  if (!Component.empty()) {
+    std::string ComponentName = UppercaseString(Component);
+    OS << "#ifdef " << ComponentName << "START\n";
+    OS << "__" << ComponentName << "START = DIAG_START_" << ComponentName
+       << ",\n";
+    OS << "#undef " << ComponentName << "START\n";
+    OS << "#endif\n\n";
+  }
+
+  const std::vector<Record*> &Diags =
+    Records.getAllDerivedDefinitions("Diagnostic");
+  
+  DiagCategoryIDMap CategoryIDs(Records);
+  DiagGroupParentMap DGParentMap(Records);
+
+  for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
+    const Record &R = *Diags[i];
+    // Filter by component.
+    if (!Component.empty() && Component != R.getValueAsString("Component"))
+      continue;
+
+    OS << "DIAG(" << R.getName() << ", ";
+    OS << R.getValueAsDef("Class")->getName();
+    OS << ", diag::" << R.getValueAsDef("DefaultMapping")->getName();
+    
+    // Description string.
+    OS << ", \"";
+    OS.write_escaped(R.getValueAsString("Text")) << '"';
+    
+    // Warning associated with the diagnostic.
+    if (DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("Group"))) {
+      OS << ", \"";
+      OS.write_escaped(DI->getDef()->getValueAsString("GroupName")) << '"';
+    } else {
+      OS << ", \"\"";
+    }
+
+    // SFINAE bit
+    if (R.getValueAsBit("SFINAE"))
+      OS << ", true";
+    else
+      OS << ", false";
+
+    // Access control bit
+    if (R.getValueAsBit("AccessControl"))
+      OS << ", true";
+    else
+      OS << ", false";
+
+    // FIXME: This condition is just to avoid temporary revlock, it can be
+    // removed.
+    if (R.getValue("WarningNoWerror")) {
+      // Default warning has no Werror bit.
+      if (R.getValueAsBit("WarningNoWerror"))
+        OS << ", true";
+      else
+        OS << ", false";
+  
+      // Default warning show in system header bit.
+      if (R.getValueAsBit("WarningShowInSystemHeader"))
+        OS << ", true";
+      else
+        OS << ", false";
+    }
+  
+    // Category number.
+    OS << ", " << CategoryIDs.getID(getDiagnosticCategory(&R, DGParentMap));
+
+    // Brief
+    OS << ", \"";
+    OS.write_escaped(R.getValueAsString("Brief")) << '"';
+
+    // Explanation 
+    OS << ", \"";
+    OS.write_escaped(R.getValueAsString("Explanation")) << '"';
+    OS << ")\n";
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// Warning Group Tables generation
+//===----------------------------------------------------------------------===//
+
+static std::string getDiagCategoryEnum(llvm::StringRef name) {
+  if (name.empty())
+    return "DiagCat_None";
+  llvm::SmallString<256> enumName = llvm::StringRef("DiagCat_");
+  for (llvm::StringRef::iterator I = name.begin(), E = name.end(); I != E; ++I)
+    enumName += isalnum(*I) ? *I : '_';
+  return enumName.str();
+}
+
+namespace {
+struct GroupInfo {
+  std::vector<const Record*> DiagsInGroup;
+  std::vector<std::string> SubGroups;
+  unsigned IDNo;
+};
+} // end anonymous namespace.
+
+void ClangDiagGroupsEmitter::run(raw_ostream &OS) {
+  // Compute a mapping from a DiagGroup to all of its parents.
+  DiagGroupParentMap DGParentMap(Records);
+  
+  // Invert the 1-[0/1] mapping of diags to group into a one to many mapping of
+  // groups to diags in the group.
+  std::map<std::string, GroupInfo> DiagsInGroup;
+  
+  std::vector<Record*> Diags =
+    Records.getAllDerivedDefinitions("Diagnostic");
+  for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
+    const Record *R = Diags[i];
+    DefInit *DI = dynamic_cast<DefInit*>(R->getValueInit("Group"));
+    if (DI == 0) continue;
+    std::string GroupName = DI->getDef()->getValueAsString("GroupName");
+    DiagsInGroup[GroupName].DiagsInGroup.push_back(R);
+  }
+  
+  // Add all DiagGroup's to the DiagsInGroup list to make sure we pick up empty
+  // groups (these are warnings that GCC supports that clang never produces).
+  std::vector<Record*> DiagGroups
+    = Records.getAllDerivedDefinitions("DiagGroup");
+  for (unsigned i = 0, e = DiagGroups.size(); i != e; ++i) {
+    Record *Group = DiagGroups[i];
+    GroupInfo &GI = DiagsInGroup[Group->getValueAsString("GroupName")];
+    
+    std::vector<Record*> SubGroups = Group->getValueAsListOfDefs("SubGroups");
+    for (unsigned j = 0, e = SubGroups.size(); j != e; ++j)
+      GI.SubGroups.push_back(SubGroups[j]->getValueAsString("GroupName"));
+  }
+  
+  // Assign unique ID numbers to the groups.
+  unsigned IDNo = 0;
+  for (std::map<std::string, GroupInfo>::iterator
+       I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I, ++IDNo)
+    I->second.IDNo = IDNo;
+  
+  // Walk through the groups emitting an array for each diagnostic of the diags
+  // that are mapped to.
+  OS << "\n#ifdef GET_DIAG_ARRAYS\n";
+  unsigned MaxLen = 0;
+  for (std::map<std::string, GroupInfo>::iterator
+       I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I) {
+    MaxLen = std::max(MaxLen, (unsigned)I->first.size());
+    
+    std::vector<const Record*> &V = I->second.DiagsInGroup;
+    if (!V.empty()) {
+      OS << "static const short DiagArray" << I->second.IDNo << "[] = { ";
+      for (unsigned i = 0, e = V.size(); i != e; ++i)
+        OS << "diag::" << V[i]->getName() << ", ";
+      OS << "-1 };\n";
+    }
+    
+    const std::vector<std::string> &SubGroups = I->second.SubGroups;
+    if (!SubGroups.empty()) {
+      OS << "static const short DiagSubGroup" << I->second.IDNo << "[] = { ";
+      for (unsigned i = 0, e = SubGroups.size(); i != e; ++i) {
+        std::map<std::string, GroupInfo>::iterator RI =
+          DiagsInGroup.find(SubGroups[i]);
+        assert(RI != DiagsInGroup.end() && "Referenced without existing?");
+        OS << RI->second.IDNo << ", ";
+      }
+      OS << "-1 };\n";
+    }
+  }
+  OS << "#endif // GET_DIAG_ARRAYS\n\n";
+  
+  // Emit the table now.
+  OS << "\n#ifdef GET_DIAG_TABLE\n";
+  for (std::map<std::string, GroupInfo>::iterator
+       I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I) {
+    // Group option string.
+    OS << "  { ";
+    OS << I->first.size() << ", ";
+    OS << "\"";
+    OS.write_escaped(I->first) << "\","
+                               << std::string(MaxLen-I->first.size()+1, ' ');
+    
+    // Diagnostics in the group.
+    if (I->second.DiagsInGroup.empty())
+      OS << "0, ";
+    else
+      OS << "DiagArray" << I->second.IDNo << ", ";
+    
+    // Subgroups.
+    if (I->second.SubGroups.empty())
+      OS << 0;
+    else
+      OS << "DiagSubGroup" << I->second.IDNo;
+    OS << " },\n";
+  }
+  OS << "#endif // GET_DIAG_TABLE\n\n";
+  
+  // Emit the category table next.
+  DiagCategoryIDMap CategoriesByID(Records);
+  OS << "\n#ifdef GET_CATEGORY_TABLE\n";
+  for (DiagCategoryIDMap::iterator I = CategoriesByID.begin(),
+       E = CategoriesByID.end(); I != E; ++I)
+    OS << "CATEGORY(\"" << *I << "\", " << getDiagCategoryEnum(*I) << ")\n";
+  OS << "#endif // GET_CATEGORY_TABLE\n\n";
+}
+
+//===----------------------------------------------------------------------===//
+// Diagnostic name index generation
+//===----------------------------------------------------------------------===//
+
+namespace {
+struct RecordIndexElement
+{
+  RecordIndexElement() {}
+  explicit RecordIndexElement(Record const &R):
+    Name(R.getName()) {}
+  
+  std::string Name;
+};
+
+struct RecordIndexElementSorter :
+  public std::binary_function<RecordIndexElement, RecordIndexElement, bool> {
+  
+  bool operator()(RecordIndexElement const &Lhs,
+                  RecordIndexElement const &Rhs) const {
+    return Lhs.Name < Rhs.Name;
+  }
+  
+};
+
+} // end anonymous namespace.
+
+void ClangDiagsIndexNameEmitter::run(raw_ostream &OS) {
+  const std::vector<Record*> &Diags =
+    Records.getAllDerivedDefinitions("Diagnostic");
+  
+  std::vector<RecordIndexElement> Index;
+  Index.reserve(Diags.size());
+  for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
+    const Record &R = *(Diags[i]);    
+    Index.push_back(RecordIndexElement(R));
+  }
+  
+  std::sort(Index.begin(), Index.end(), RecordIndexElementSorter());
+  
+  for (unsigned i = 0, e = Index.size(); i != e; ++i) {
+    const RecordIndexElement &R = Index[i];
+    
+    OS << "DIAG_NAME_INDEX(" << R.Name << ")\n";
+  }
+}

Added: cfe/trunk/utils/TableGen/ClangDiagnosticsEmitter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangDiagnosticsEmitter.h?rev=141291&view=auto
==============================================================================
--- cfe/trunk/utils/TableGen/ClangDiagnosticsEmitter.h (added)
+++ cfe/trunk/utils/TableGen/ClangDiagnosticsEmitter.h Thu Oct  6 08:03:08 2011
@@ -0,0 +1,54 @@
+//===- 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

Added: cfe/trunk/utils/TableGen/ClangSACheckersEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangSACheckersEmitter.cpp?rev=141291&view=auto
==============================================================================
--- cfe/trunk/utils/TableGen/ClangSACheckersEmitter.cpp (added)
+++ cfe/trunk/utils/TableGen/ClangSACheckersEmitter.cpp Thu Oct  6 08:03:08 2011
@@ -0,0 +1,319 @@
+//=- ClangSACheckersEmitter.cpp - Generate Clang SA checkers tables -*- C++ -*-
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend emits Clang Static Analyzer checkers tables.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckersEmitter.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/ADT/DenseSet.h"
+#include <map>
+#include <string>
+using namespace llvm;
+
+//===----------------------------------------------------------------------===//
+// Static Analyzer Checkers Tables generation
+//===----------------------------------------------------------------------===//
+
+/// \brief True if it is specified hidden or a parent package is specified
+/// as hidden, otherwise false.
+static bool isHidden(const Record &R) {
+  if (R.getValueAsBit("Hidden"))
+    return true;
+  // Not declared as hidden, check the parent package if it is hidden.
+  if (DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("ParentPackage")))
+    return isHidden(*DI->getDef());
+
+  return false;
+}
+
+static bool isCheckerNamed(const Record *R) {
+  return !R->getValueAsString("CheckerName").empty();
+}
+
+static std::string getPackageFullName(const Record *R);
+
+static std::string getParentPackageFullName(const Record *R) {
+  std::string name;
+  if (DefInit *DI = dynamic_cast<DefInit*>(R->getValueInit("ParentPackage")))
+    name = getPackageFullName(DI->getDef());
+  return name;
+}
+
+static std::string getPackageFullName(const Record *R) {
+  std::string name = getParentPackageFullName(R);
+  if (!name.empty()) name += ".";
+  return name + R->getValueAsString("PackageName");
+}
+
+static std::string getCheckerFullName(const Record *R) {
+  std::string name = getParentPackageFullName(R);
+  if (isCheckerNamed(R)) {
+    if (!name.empty()) name += ".";
+    name += R->getValueAsString("CheckerName");
+  }
+  return name;
+}
+
+static std::string getStringValue(const Record &R, StringRef field) {
+  if (StringInit *
+        SI = dynamic_cast<StringInit*>(R.getValueInit(field)))
+    return SI->getValue();
+  return std::string();
+}
+
+namespace {
+struct GroupInfo {
+  llvm::DenseSet<const Record*> Checkers;
+  llvm::DenseSet<const Record *> SubGroups;
+  bool Hidden;
+  unsigned Index;
+
+  GroupInfo() : Hidden(false) { }
+};
+}
+
+static void addPackageToCheckerGroup(const Record *package, const Record *group,
+                  llvm::DenseMap<const Record *, GroupInfo *> &recordGroupMap) {
+  llvm::DenseSet<const Record *> &checkers = recordGroupMap[package]->Checkers;
+  for (llvm::DenseSet<const Record *>::iterator
+         I = checkers.begin(), E = checkers.end(); I != E; ++I)
+    recordGroupMap[group]->Checkers.insert(*I);
+
+  llvm::DenseSet<const Record *> &subGroups = recordGroupMap[package]->SubGroups;
+  for (llvm::DenseSet<const Record *>::iterator
+         I = subGroups.begin(), E = subGroups.end(); I != E; ++I)
+    addPackageToCheckerGroup(*I, group, recordGroupMap);
+}
+
+void ClangSACheckersEmitter::run(raw_ostream &OS) {
+  std::vector<Record*> checkers = Records.getAllDerivedDefinitions("Checker");
+  llvm::DenseMap<const Record *, unsigned> checkerRecIndexMap;
+  for (unsigned i = 0, e = checkers.size(); i != e; ++i)
+    checkerRecIndexMap[checkers[i]] = i;
+
+  // Invert the mapping of checkers to package/group into a one to many
+  // mapping of packages/groups to checkers.
+  std::map<std::string, GroupInfo> groupInfoByName;
+  llvm::DenseMap<const Record *, GroupInfo *> recordGroupMap;
+
+  std::vector<Record*> packages = Records.getAllDerivedDefinitions("Package");
+  for (unsigned i = 0, e = packages.size(); i != e; ++i) {
+    Record *R = packages[i];
+    std::string fullName = getPackageFullName(R);
+    if (!fullName.empty()) {
+      GroupInfo &info = groupInfoByName[fullName];
+      info.Hidden = isHidden(*R);
+      recordGroupMap[R] = &info;
+    }
+  }
+
+  std::vector<Record*>
+      checkerGroups = Records.getAllDerivedDefinitions("CheckerGroup");
+  for (unsigned i = 0, e = checkerGroups.size(); i != e; ++i) {
+    Record *R = checkerGroups[i];
+    std::string name = R->getValueAsString("GroupName");
+    if (!name.empty()) {
+      GroupInfo &info = groupInfoByName[name];
+      recordGroupMap[R] = &info;
+    }
+  }
+
+  for (unsigned i = 0, e = checkers.size(); i != e; ++i) {
+    Record *R = checkers[i];
+    Record *package = 0;
+    if (DefInit *
+          DI = dynamic_cast<DefInit*>(R->getValueInit("ParentPackage")))
+      package = DI->getDef();
+    if (!isCheckerNamed(R) && !package)
+      throw "Checker '" + R->getName() + "' is neither named, nor in a package!";
+
+    if (isCheckerNamed(R)) {
+      // Create a pseudo-group to hold this checker.
+      std::string fullName = getCheckerFullName(R);
+      GroupInfo &info = groupInfoByName[fullName];
+      info.Hidden = R->getValueAsBit("Hidden");
+      recordGroupMap[R] = &info;
+      info.Checkers.insert(R);
+    } else {
+      recordGroupMap[package]->Checkers.insert(R);
+    }
+
+    Record *currR = isCheckerNamed(R) ? R : package;
+    // Insert the checker and its parent packages into the subgroups set of
+    // the corresponding parent package.
+    while (DefInit *DI
+             = dynamic_cast<DefInit*>(currR->getValueInit("ParentPackage"))) {
+      Record *parentPackage = DI->getDef();
+      recordGroupMap[parentPackage]->SubGroups.insert(currR);
+      currR = parentPackage;
+    }
+    // Insert the checker into the set of its group.
+    if (DefInit *DI = dynamic_cast<DefInit*>(R->getValueInit("Group")))
+      recordGroupMap[DI->getDef()]->Checkers.insert(R);
+  }
+
+  // If a package is in group, add all its checkers and its sub-packages
+  // checkers into the group.
+  for (unsigned i = 0, e = packages.size(); i != e; ++i)
+    if (DefInit *DI = dynamic_cast<DefInit*>(packages[i]->getValueInit("Group")))
+      addPackageToCheckerGroup(packages[i], DI->getDef(), recordGroupMap);
+
+  typedef std::map<std::string, const Record *> SortedRecords;
+  typedef llvm::DenseMap<const Record *, unsigned> RecToSortIndex;
+
+  SortedRecords sortedGroups;
+  RecToSortIndex groupToSortIndex;
+  OS << "\n#ifdef GET_GROUPS\n";
+  {
+    for (unsigned i = 0, e = checkerGroups.size(); i != e; ++i)
+      sortedGroups[checkerGroups[i]->getValueAsString("GroupName")]
+                   = checkerGroups[i];
+
+    unsigned sortIndex = 0;
+    for (SortedRecords::iterator
+           I = sortedGroups.begin(), E = sortedGroups.end(); I != E; ++I) {
+      const Record *R = I->second;
+  
+      OS << "GROUP(" << "\"";
+      OS.write_escaped(R->getValueAsString("GroupName")) << "\"";
+      OS << ")\n";
+
+      groupToSortIndex[R] = sortIndex++;
+    }
+  }
+  OS << "#endif // GET_GROUPS\n\n";
+
+  OS << "\n#ifdef GET_PACKAGES\n";
+  {
+    SortedRecords sortedPackages;
+    for (unsigned i = 0, e = packages.size(); i != e; ++i)
+      sortedPackages[getPackageFullName(packages[i])] = packages[i];
+  
+    for (SortedRecords::iterator
+           I = sortedPackages.begin(), E = sortedPackages.end(); I != E; ++I) {
+      const Record &R = *I->second;
+  
+      OS << "PACKAGE(" << "\"";
+      OS.write_escaped(getPackageFullName(&R)) << "\", ";
+      // Group index
+      if (DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("Group")))
+        OS << groupToSortIndex[DI->getDef()] << ", ";
+      else
+        OS << "-1, ";
+      // Hidden bit
+      if (isHidden(R))
+        OS << "true";
+      else
+        OS << "false";
+      OS << ")\n";
+    }
+  }
+  OS << "#endif // GET_PACKAGES\n\n";
+  
+  OS << "\n#ifdef GET_CHECKERS\n";
+  for (unsigned i = 0, e = checkers.size(); i != e; ++i) {
+    const Record &R = *checkers[i];
+
+    OS << "CHECKER(" << "\"";
+    std::string name;
+    if (isCheckerNamed(&R))
+      name = getCheckerFullName(&R);
+    OS.write_escaped(name) << "\", ";
+    OS << R.getName() << ", ";
+    OS << getStringValue(R, "DescFile") << ", ";
+    OS << "\"";
+    OS.write_escaped(getStringValue(R, "HelpText")) << "\", ";
+    // Group index
+    if (DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("Group")))
+      OS << groupToSortIndex[DI->getDef()] << ", ";
+    else
+      OS << "-1, ";
+    // Hidden bit
+    if (isHidden(R))
+      OS << "true";
+    else
+      OS << "false";
+    OS << ")\n";
+  }
+  OS << "#endif // GET_CHECKERS\n\n";
+
+  unsigned index = 0;
+  for (std::map<std::string, GroupInfo>::iterator
+         I = groupInfoByName.begin(), E = groupInfoByName.end(); I != E; ++I)
+    I->second.Index = index++;
+
+  // Walk through the packages/groups/checkers emitting an array for each
+  // set of checkers and an array for each set of subpackages.
+
+  OS << "\n#ifdef GET_MEMBER_ARRAYS\n";
+  unsigned maxLen = 0;
+  for (std::map<std::string, GroupInfo>::iterator
+         I = groupInfoByName.begin(), E = groupInfoByName.end(); I != E; ++I) {
+    maxLen = std::max(maxLen, (unsigned)I->first.size());
+
+    llvm::DenseSet<const Record *> &checkers = I->second.Checkers;
+    if (!checkers.empty()) {
+      OS << "static const short CheckerArray" << I->second.Index << "[] = { ";
+      // Make the output order deterministic.
+      std::map<int, const Record *> sorted;
+      for (llvm::DenseSet<const Record *>::iterator
+             I = checkers.begin(), E = checkers.end(); I != E; ++I)
+        sorted[(*I)->getID()] = *I;
+
+      for (std::map<int, const Record *>::iterator
+             I = sorted.begin(), E = sorted.end(); I != E; ++I)
+        OS << checkerRecIndexMap[I->second] << ", ";
+      OS << "-1 };\n";
+    }
+    
+    llvm::DenseSet<const Record *> &subGroups = I->second.SubGroups;
+    if (!subGroups.empty()) {
+      OS << "static const short SubPackageArray" << I->second.Index << "[] = { ";
+      // Make the output order deterministic.
+      std::map<int, const Record *> sorted;
+      for (llvm::DenseSet<const Record *>::iterator
+             I = subGroups.begin(), E = subGroups.end(); I != E; ++I)
+        sorted[(*I)->getID()] = *I;
+
+      for (std::map<int, const Record *>::iterator
+             I = sorted.begin(), E = sorted.end(); I != E; ++I) {
+        OS << recordGroupMap[I->second]->Index << ", ";
+      }
+      OS << "-1 };\n";
+    }
+  }
+  OS << "#endif // GET_MEMBER_ARRAYS\n\n";
+
+  OS << "\n#ifdef GET_CHECKNAME_TABLE\n";
+  for (std::map<std::string, GroupInfo>::iterator
+         I = groupInfoByName.begin(), E = groupInfoByName.end(); I != E; ++I) {
+    // Group option string.
+    OS << "  { \"";
+    OS.write_escaped(I->first) << "\","
+                               << std::string(maxLen-I->first.size()+1, ' ');
+    
+    if (I->second.Checkers.empty())
+      OS << "0, ";
+    else
+      OS << "CheckerArray" << I->second.Index << ", ";
+    
+    // Subgroups.
+    if (I->second.SubGroups.empty())
+      OS << "0, ";
+    else
+      OS << "SubPackageArray" << I->second.Index << ", ";
+
+    OS << (I->second.Hidden ? "true" : "false");
+
+    OS << " },\n";
+  }
+  OS << "#endif // GET_CHECKNAME_TABLE\n\n";
+}

Added: cfe/trunk/utils/TableGen/ClangSACheckersEmitter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangSACheckersEmitter.h?rev=141291&view=auto
==============================================================================
--- cfe/trunk/utils/TableGen/ClangSACheckersEmitter.h (added)
+++ cfe/trunk/utils/TableGen/ClangSACheckersEmitter.h Thu Oct  6 08:03:08 2011
@@ -0,0 +1,31 @@
+//===- 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

Added: cfe/trunk/utils/TableGen/Makefile
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/Makefile?rev=141291&view=auto
==============================================================================
--- cfe/trunk/utils/TableGen/Makefile (added)
+++ cfe/trunk/utils/TableGen/Makefile Thu Oct  6 08:03:08 2011
@@ -0,0 +1,19 @@
+##===- 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.
+#
+##===----------------------------------------------------------------------===##
+
+CLANG_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 $(CLANG_LEVEL)/Makefile

Added: cfe/trunk/utils/TableGen/NeonEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/NeonEmitter.cpp?rev=141291&view=auto
==============================================================================
--- cfe/trunk/utils/TableGen/NeonEmitter.cpp (added)
+++ cfe/trunk/utils/TableGen/NeonEmitter.cpp Thu Oct  6 08:03:08 2011
@@ -0,0 +1,1551 @@
+//===- NeonEmitter.cpp - Generate arm_neon.h for use with clang -*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend is responsible for emitting arm_neon.h, which includes
+// a declaration and definition of each function specified by the ARM NEON
+// compiler interface.  See ARM document DUI0348B.
+//
+// Each NEON instruction is implemented in terms of 1 or more functions which
+// are suffixed with the element type of the input vectors.  Functions may be
+// implemented in terms of generic vector operations such as +, *, -, etc. or
+// by calling a __builtin_-prefixed function which will be handled by clang's
+// CodeGen library.
+//
+// Additional validation code can be generated by this file when runHeader() is
+// called, rather than the normal run() entry point.  A complete set of tests
+// for Neon intrinsics can be generated by calling the runTests() entry point.
+//
+//===----------------------------------------------------------------------===//
+
+#include "NeonEmitter.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
+#include <string>
+
+using namespace llvm;
+
+/// ParseTypes - break down a string such as "fQf" into a vector of StringRefs,
+/// which each StringRef representing a single type declared in the string.
+/// for "fQf" we would end up with 2 StringRefs, "f", and "Qf", representing
+/// 2xfloat and 4xfloat respectively.
+static void ParseTypes(Record *r, std::string &s,
+                       SmallVectorImpl<StringRef> &TV) {
+  const char *data = s.data();
+  int len = 0;
+
+  for (unsigned i = 0, e = s.size(); i != e; ++i, ++len) {
+    if (data[len] == 'P' || data[len] == 'Q' || data[len] == 'U')
+      continue;
+
+    switch (data[len]) {
+      case 'c':
+      case 's':
+      case 'i':
+      case 'l':
+      case 'h':
+      case 'f':
+        break;
+      default:
+        throw TGError(r->getLoc(),
+                      "Unexpected letter: " + std::string(data + len, 1));
+        break;
+    }
+    TV.push_back(StringRef(data, len + 1));
+    data += len + 1;
+    len = -1;
+  }
+}
+
+/// Widen - Convert a type code into the next wider type.  char -> short,
+/// short -> int, etc.
+static char Widen(const char t) {
+  switch (t) {
+    case 'c':
+      return 's';
+    case 's':
+      return 'i';
+    case 'i':
+      return 'l';
+    case 'h':
+      return 'f';
+    default: throw "unhandled type in widen!";
+  }
+  return '\0';
+}
+
+/// Narrow - Convert a type code into the next smaller type.  short -> char,
+/// float -> half float, etc.
+static char Narrow(const char t) {
+  switch (t) {
+    case 's':
+      return 'c';
+    case 'i':
+      return 's';
+    case 'l':
+      return 'i';
+    case 'f':
+      return 'h';
+    default: throw "unhandled type in narrow!";
+  }
+  return '\0';
+}
+
+/// For a particular StringRef, return the base type code, and whether it has
+/// the quad-vector, polynomial, or unsigned modifiers set.
+static char ClassifyType(StringRef ty, bool &quad, bool &poly, bool &usgn) {
+  unsigned off = 0;
+
+  // remember quad.
+  if (ty[off] == 'Q') {
+    quad = true;
+    ++off;
+  }
+
+  // remember poly.
+  if (ty[off] == 'P') {
+    poly = true;
+    ++off;
+  }
+
+  // remember unsigned.
+  if (ty[off] == 'U') {
+    usgn = true;
+    ++off;
+  }
+
+  // base type to get the type string for.
+  return ty[off];
+}
+
+/// ModType - Transform a type code and its modifiers based on a mod code. The
+/// mod code definitions may be found at the top of arm_neon.td.
+static char ModType(const char mod, char type, bool &quad, bool &poly,
+                    bool &usgn, bool &scal, bool &cnst, bool &pntr) {
+  switch (mod) {
+    case 't':
+      if (poly) {
+        poly = false;
+        usgn = true;
+      }
+      break;
+    case 'u':
+      usgn = true;
+      poly = false;
+      if (type == 'f')
+        type = 'i';
+      break;
+    case 'x':
+      usgn = false;
+      poly = false;
+      if (type == 'f')
+        type = 'i';
+      break;
+    case 'f':
+      if (type == 'h')
+        quad = true;
+      type = 'f';
+      usgn = false;
+      break;
+    case 'g':
+      quad = false;
+      break;
+    case 'w':
+      type = Widen(type);
+      quad = true;
+      break;
+    case 'n':
+      type = Widen(type);
+      break;
+    case 'i':
+      type = 'i';
+      scal = true;
+      break;
+    case 'l':
+      type = 'l';
+      scal = true;
+      usgn = true;
+      break;
+    case 's':
+    case 'a':
+      scal = true;
+      break;
+    case 'k':
+      quad = true;
+      break;
+    case 'c':
+      cnst = true;
+    case 'p':
+      pntr = true;
+      scal = true;
+      break;
+    case 'h':
+      type = Narrow(type);
+      if (type == 'h')
+        quad = false;
+      break;
+    case 'e':
+      type = Narrow(type);
+      usgn = true;
+      break;
+    default:
+      break;
+  }
+  return type;
+}
+
+/// TypeString - for a modifier and type, generate the name of the typedef for
+/// that type.  QUc -> uint8x8_t.
+static std::string TypeString(const char mod, StringRef typestr) {
+  bool quad = false;
+  bool poly = false;
+  bool usgn = false;
+  bool scal = false;
+  bool cnst = false;
+  bool pntr = false;
+
+  if (mod == 'v')
+    return "void";
+  if (mod == 'i')
+    return "int";
+
+  // base type to get the type string for.
+  char type = ClassifyType(typestr, quad, poly, usgn);
+
+  // Based on the modifying character, change the type and width if necessary.
+  type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
+
+  SmallString<128> s;
+
+  if (usgn)
+    s.push_back('u');
+
+  switch (type) {
+    case 'c':
+      s += poly ? "poly8" : "int8";
+      if (scal)
+        break;
+      s += quad ? "x16" : "x8";
+      break;
+    case 's':
+      s += poly ? "poly16" : "int16";
+      if (scal)
+        break;
+      s += quad ? "x8" : "x4";
+      break;
+    case 'i':
+      s += "int32";
+      if (scal)
+        break;
+      s += quad ? "x4" : "x2";
+      break;
+    case 'l':
+      s += "int64";
+      if (scal)
+        break;
+      s += quad ? "x2" : "x1";
+      break;
+    case 'h':
+      s += "float16";
+      if (scal)
+        break;
+      s += quad ? "x8" : "x4";
+      break;
+    case 'f':
+      s += "float32";
+      if (scal)
+        break;
+      s += quad ? "x4" : "x2";
+      break;
+    default:
+      throw "unhandled type!";
+      break;
+  }
+
+  if (mod == '2')
+    s += "x2";
+  if (mod == '3')
+    s += "x3";
+  if (mod == '4')
+    s += "x4";
+
+  // Append _t, finishing the type string typedef type.
+  s += "_t";
+
+  if (cnst)
+    s += " const";
+
+  if (pntr)
+    s += " *";
+
+  return s.str();
+}
+
+/// BuiltinTypeString - for a modifier and type, generate the clang
+/// BuiltinsARM.def prototype code for the function.  See the top of clang's
+/// Builtins.def for a description of the type strings.
+static std::string BuiltinTypeString(const char mod, StringRef typestr,
+                                     ClassKind ck, bool ret) {
+  bool quad = false;
+  bool poly = false;
+  bool usgn = false;
+  bool scal = false;
+  bool cnst = false;
+  bool pntr = false;
+
+  if (mod == 'v')
+    return "v"; // void
+  if (mod == 'i')
+    return "i"; // int
+
+  // base type to get the type string for.
+  char type = ClassifyType(typestr, quad, poly, usgn);
+
+  // Based on the modifying character, change the type and width if necessary.
+  type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
+
+  // All pointers are void* pointers.  Change type to 'v' now.
+  if (pntr) {
+    usgn = false;
+    poly = false;
+    type = 'v';
+  }
+  // Treat half-float ('h') types as unsigned short ('s') types.
+  if (type == 'h') {
+    type = 's';
+    usgn = true;
+  }
+  usgn = usgn | poly | ((ck == ClassI || ck == ClassW) && scal && type != 'f');
+
+  if (scal) {
+    SmallString<128> s;
+
+    if (usgn)
+      s.push_back('U');
+    else if (type == 'c')
+      s.push_back('S'); // make chars explicitly signed
+
+    if (type == 'l') // 64-bit long
+      s += "LLi";
+    else
+      s.push_back(type);
+
+    if (cnst)
+      s.push_back('C');
+    if (pntr)
+      s.push_back('*');
+    return s.str();
+  }
+
+  // Since the return value must be one type, return a vector type of the
+  // appropriate width which we will bitcast.  An exception is made for
+  // returning structs of 2, 3, or 4 vectors which are returned in a sret-like
+  // fashion, storing them to a pointer arg.
+  if (ret) {
+    if (mod >= '2' && mod <= '4')
+      return "vv*"; // void result with void* first argument
+    if (mod == 'f' || (ck != ClassB && type == 'f'))
+      return quad ? "V4f" : "V2f";
+    if (ck != ClassB && type == 's')
+      return quad ? "V8s" : "V4s";
+    if (ck != ClassB && type == 'i')
+      return quad ? "V4i" : "V2i";
+    if (ck != ClassB && type == 'l')
+      return quad ? "V2LLi" : "V1LLi";
+
+    return quad ? "V16Sc" : "V8Sc";
+  }
+
+  // Non-return array types are passed as individual vectors.
+  if (mod == '2')
+    return quad ? "V16ScV16Sc" : "V8ScV8Sc";
+  if (mod == '3')
+    return quad ? "V16ScV16ScV16Sc" : "V8ScV8ScV8Sc";
+  if (mod == '4')
+    return quad ? "V16ScV16ScV16ScV16Sc" : "V8ScV8ScV8ScV8Sc";
+
+  if (mod == 'f' || (ck != ClassB && type == 'f'))
+    return quad ? "V4f" : "V2f";
+  if (ck != ClassB && type == 's')
+    return quad ? "V8s" : "V4s";
+  if (ck != ClassB && type == 'i')
+    return quad ? "V4i" : "V2i";
+  if (ck != ClassB && type == 'l')
+    return quad ? "V2LLi" : "V1LLi";
+
+  return quad ? "V16Sc" : "V8Sc";
+}
+
+/// MangleName - Append a type or width suffix to a base neon function name,
+/// and insert a 'q' in the appropriate location if the operation works on
+/// 128b rather than 64b.   E.g. turn "vst2_lane" into "vst2q_lane_f32", etc.
+static std::string MangleName(const std::string &name, StringRef typestr,
+                              ClassKind ck) {
+  if (name == "vcvt_f32_f16")
+    return name;
+
+  bool quad = false;
+  bool poly = false;
+  bool usgn = false;
+  char type = ClassifyType(typestr, quad, poly, usgn);
+
+  std::string s = name;
+
+  switch (type) {
+  case 'c':
+    switch (ck) {
+    case ClassS: s += poly ? "_p8" : usgn ? "_u8" : "_s8"; break;
+    case ClassI: s += "_i8"; break;
+    case ClassW: s += "_8"; break;
+    default: break;
+    }
+    break;
+  case 's':
+    switch (ck) {
+    case ClassS: s += poly ? "_p16" : usgn ? "_u16" : "_s16"; break;
+    case ClassI: s += "_i16"; break;
+    case ClassW: s += "_16"; break;
+    default: break;
+    }
+    break;
+  case 'i':
+    switch (ck) {
+    case ClassS: s += usgn ? "_u32" : "_s32"; break;
+    case ClassI: s += "_i32"; break;
+    case ClassW: s += "_32"; break;
+    default: break;
+    }
+    break;
+  case 'l':
+    switch (ck) {
+    case ClassS: s += usgn ? "_u64" : "_s64"; break;
+    case ClassI: s += "_i64"; break;
+    case ClassW: s += "_64"; break;
+    default: break;
+    }
+    break;
+  case 'h':
+    switch (ck) {
+    case ClassS:
+    case ClassI: s += "_f16"; break;
+    case ClassW: s += "_16"; break;
+    default: break;
+    }
+    break;
+  case 'f':
+    switch (ck) {
+    case ClassS:
+    case ClassI: s += "_f32"; break;
+    case ClassW: s += "_32"; break;
+    default: break;
+    }
+    break;
+  default:
+    throw "unhandled type!";
+    break;
+  }
+  if (ck == ClassB)
+    s += "_v";
+
+  // Insert a 'q' before the first '_' character so that it ends up before
+  // _lane or _n on vector-scalar operations.
+  if (quad) {
+    size_t pos = s.find('_');
+    s = s.insert(pos, "q");
+  }
+  return s;
+}
+
+/// UseMacro - Examine the prototype string to determine if the intrinsic
+/// should be defined as a preprocessor macro instead of an inline function.
+static bool UseMacro(const std::string &proto) {
+  // If this builtin takes an immediate argument, we need to #define it rather
+  // than use a standard declaration, so that SemaChecking can range check
+  // the immediate passed by the user.
+  if (proto.find('i') != std::string::npos)
+    return true;
+
+  // Pointer arguments need to use macros to avoid hiding aligned attributes
+  // from the pointer type.
+  if (proto.find('p') != std::string::npos ||
+      proto.find('c') != std::string::npos)
+    return true;
+
+  return false;
+}
+
+/// MacroArgUsedDirectly - Return true if argument i for an intrinsic that is
+/// defined as a macro should be accessed directly instead of being first
+/// assigned to a local temporary.
+static bool MacroArgUsedDirectly(const std::string &proto, unsigned i) {
+  // True for constant ints (i), pointers (p) and const pointers (c).
+  return (proto[i] == 'i' || proto[i] == 'p' || proto[i] == 'c');
+}
+
+// Generate the string "(argtype a, argtype b, ...)"
+static std::string GenArgs(const std::string &proto, StringRef typestr) {
+  bool define = UseMacro(proto);
+  char arg = 'a';
+
+  std::string s;
+  s += "(";
+
+  for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
+    if (define) {
+      // Some macro arguments are used directly instead of being assigned
+      // to local temporaries; prepend an underscore prefix to make their
+      // names consistent with the local temporaries.
+      if (MacroArgUsedDirectly(proto, i))
+        s += "__";
+    } else {
+      s += TypeString(proto[i], typestr) + " __";
+    }
+    s.push_back(arg);
+    if ((i + 1) < e)
+      s += ", ";
+  }
+
+  s += ")";
+  return s;
+}
+
+// Macro arguments are not type-checked like inline function arguments, so
+// assign them to local temporaries to get the right type checking.
+static std::string GenMacroLocals(const std::string &proto, StringRef typestr) {
+  char arg = 'a';
+  std::string s;
+  bool generatedLocal = false;
+
+  for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
+    // Do not create a temporary for an immediate argument.
+    // That would defeat the whole point of using a macro!
+    // 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;
+
+    s += TypeString(proto[i], typestr) + " __";
+    s.push_back(arg);
+    s += " = (";
+    s.push_back(arg);
+    s += "); ";
+  }
+
+  if (generatedLocal)
+    s += "\\\n  ";
+  return s;
+}
+
+// Use the vmovl builtin to sign-extend or zero-extend a vector.
+static std::string Extend(StringRef typestr, const std::string &a) {
+  std::string s;
+  s = MangleName("vmovl", typestr, ClassS);
+  s += "(" + a + ")";
+  return s;
+}
+
+static std::string Duplicate(unsigned nElts, StringRef typestr,
+                             const std::string &a) {
+  std::string s;
+
+  s = "(" + TypeString('d', typestr) + "){ ";
+  for (unsigned i = 0; i != nElts; ++i) {
+    s += a;
+    if ((i + 1) < nElts)
+      s += ", ";
+  }
+  s += " }";
+
+  return s;
+}
+
+static std::string SplatLane(unsigned nElts, const std::string &vec,
+                             const std::string &lane) {
+  std::string s = "__builtin_shufflevector(" + vec + ", " + vec;
+  for (unsigned i = 0; i < nElts; ++i)
+    s += ", " + lane;
+  s += ")";
+  return s;
+}
+
+static unsigned GetNumElements(StringRef typestr, bool &quad) {
+  quad = false;
+  bool dummy = false;
+  char type = ClassifyType(typestr, quad, dummy, dummy);
+  unsigned nElts = 0;
+  switch (type) {
+  case 'c': nElts = 8; break;
+  case 's': nElts = 4; break;
+  case 'i': nElts = 2; break;
+  case 'l': nElts = 1; break;
+  case 'h': nElts = 4; break;
+  case 'f': nElts = 2; break;
+  default:
+    throw "unhandled type!";
+    break;
+  }
+  if (quad) nElts <<= 1;
+  return nElts;
+}
+
+// Generate the definition for this intrinsic, e.g. "a + b" for OpAdd.
+static std::string GenOpString(OpKind op, const std::string &proto,
+                               StringRef typestr) {
+  bool quad;
+  unsigned nElts = GetNumElements(typestr, quad);
+  bool define = UseMacro(proto);
+
+  std::string ts = TypeString(proto[0], typestr);
+  std::string s;
+  if (!define) {
+    s = "return ";
+  }
+
+  switch(op) {
+  case OpAdd:
+    s += "__a + __b;";
+    break;
+  case OpAddl:
+    s += Extend(typestr, "__a") + " + " + Extend(typestr, "__b") + ";";
+    break;
+  case OpAddw:
+    s += "__a + " + Extend(typestr, "__b") + ";";
+    break;
+  case OpSub:
+    s += "__a - __b;";
+    break;
+  case OpSubl:
+    s += Extend(typestr, "__a") + " - " + Extend(typestr, "__b") + ";";
+    break;
+  case OpSubw:
+    s += "__a - " + Extend(typestr, "__b") + ";";
+    break;
+  case OpMulN:
+    s += "__a * " + Duplicate(nElts, typestr, "__b") + ";";
+    break;
+  case OpMulLane:
+    s += "__a * " + SplatLane(nElts, "__b", "__c") + ";";
+    break;
+  case OpMul:
+    s += "__a * __b;";
+    break;
+  case OpMullLane:
+    s += MangleName("vmull", typestr, ClassS) + "(__a, " +
+      SplatLane(nElts, "__b", "__c") + ");";
+    break;
+  case OpMlaN:
+    s += "__a + (__b * " + Duplicate(nElts, typestr, "__c") + ");";
+    break;
+  case OpMlaLane:
+    s += "__a + (__b * " + SplatLane(nElts, "__c", "__d") + ");";
+    break;
+  case OpMla:
+    s += "__a + (__b * __c);";
+    break;
+  case OpMlalN:
+    s += "__a + " + MangleName("vmull", typestr, ClassS) + "(__b, " +
+      Duplicate(nElts, typestr, "__c") + ");";
+    break;
+  case OpMlalLane:
+    s += "__a + " + MangleName("vmull", typestr, ClassS) + "(__b, " +
+      SplatLane(nElts, "__c", "__d") + ");";
+    break;
+  case OpMlal:
+    s += "__a + " + MangleName("vmull", typestr, ClassS) + "(__b, __c);";
+    break;
+  case OpMlsN:
+    s += "__a - (__b * " + Duplicate(nElts, typestr, "__c") + ");";
+    break;
+  case OpMlsLane:
+    s += "__a - (__b * " + SplatLane(nElts, "__c", "__d") + ");";
+    break;
+  case OpMls:
+    s += "__a - (__b * __c);";
+    break;
+  case OpMlslN:
+    s += "__a - " + MangleName("vmull", typestr, ClassS) + "(__b, " +
+      Duplicate(nElts, typestr, "__c") + ");";
+    break;
+  case OpMlslLane:
+    s += "__a - " + MangleName("vmull", typestr, ClassS) + "(__b, " +
+      SplatLane(nElts, "__c", "__d") + ");";
+    break;
+  case OpMlsl:
+    s += "__a - " + MangleName("vmull", typestr, ClassS) + "(__b, __c);";
+    break;
+  case OpQDMullLane:
+    s += MangleName("vqdmull", typestr, ClassS) + "(__a, " +
+      SplatLane(nElts, "__b", "__c") + ");";
+    break;
+  case OpQDMlalLane:
+    s += MangleName("vqdmlal", typestr, ClassS) + "(__a, __b, " +
+      SplatLane(nElts, "__c", "__d") + ");";
+    break;
+  case OpQDMlslLane:
+    s += MangleName("vqdmlsl", typestr, ClassS) + "(__a, __b, " +
+      SplatLane(nElts, "__c", "__d") + ");";
+    break;
+  case OpQDMulhLane:
+    s += MangleName("vqdmulh", typestr, ClassS) + "(__a, " +
+      SplatLane(nElts, "__b", "__c") + ");";
+    break;
+  case OpQRDMulhLane:
+    s += MangleName("vqrdmulh", typestr, ClassS) + "(__a, " +
+      SplatLane(nElts, "__b", "__c") + ");";
+    break;
+  case OpEq:
+    s += "(" + ts + ")(__a == __b);";
+    break;
+  case OpGe:
+    s += "(" + ts + ")(__a >= __b);";
+    break;
+  case OpLe:
+    s += "(" + ts + ")(__a <= __b);";
+    break;
+  case OpGt:
+    s += "(" + ts + ")(__a > __b);";
+    break;
+  case OpLt:
+    s += "(" + ts + ")(__a < __b);";
+    break;
+  case OpNeg:
+    s += " -__a;";
+    break;
+  case OpNot:
+    s += " ~__a;";
+    break;
+  case OpAnd:
+    s += "__a & __b;";
+    break;
+  case OpOr:
+    s += "__a | __b;";
+    break;
+  case OpXor:
+    s += "__a ^ __b;";
+    break;
+  case OpAndNot:
+    s += "__a & ~__b;";
+    break;
+  case OpOrNot:
+    s += "__a | ~__b;";
+    break;
+  case OpCast:
+    s += "(" + ts + ")__a;";
+    break;
+  case OpConcat:
+    s += "(" + ts + ")__builtin_shufflevector((int64x1_t)__a";
+    s += ", (int64x1_t)__b, 0, 1);";
+    break;
+  case OpHi:
+    s += "(" + ts +
+      ")__builtin_shufflevector((int64x2_t)__a, (int64x2_t)__a, 1);";
+    break;
+  case OpLo:
+    s += "(" + ts +
+      ")__builtin_shufflevector((int64x2_t)__a, (int64x2_t)__a, 0);";
+    break;
+  case OpDup:
+    s += Duplicate(nElts, typestr, "__a") + ";";
+    break;
+  case OpDupLane:
+    s += SplatLane(nElts, "__a", "__b") + ";";
+    break;
+  case OpSelect:
+    // ((0 & 1) | (~0 & 2))
+    s += "(" + ts + ")";
+    ts = TypeString(proto[1], typestr);
+    s += "((__a & (" + ts + ")__b) | ";
+    s += "(~__a & (" + ts + ")__c));";
+    break;
+  case OpRev16:
+    s += "__builtin_shufflevector(__a, __a";
+    for (unsigned i = 2; i <= nElts; i += 2)
+      for (unsigned j = 0; j != 2; ++j)
+        s += ", " + utostr(i - j - 1);
+    s += ");";
+    break;
+  case OpRev32: {
+    unsigned WordElts = nElts >> (1 + (int)quad);
+    s += "__builtin_shufflevector(__a, __a";
+    for (unsigned i = WordElts; i <= nElts; i += WordElts)
+      for (unsigned j = 0; j != WordElts; ++j)
+        s += ", " + utostr(i - j - 1);
+    s += ");";
+    break;
+  }
+  case OpRev64: {
+    unsigned DblWordElts = nElts >> (int)quad;
+    s += "__builtin_shufflevector(__a, __a";
+    for (unsigned i = DblWordElts; i <= nElts; i += DblWordElts)
+      for (unsigned j = 0; j != DblWordElts; ++j)
+        s += ", " + utostr(i - j - 1);
+    s += ");";
+    break;
+  }
+  case OpAbdl: {
+    std::string abd = MangleName("vabd", typestr, ClassS) + "(__a, __b)";
+    if (typestr[0] != 'U') {
+      // vabd results are always unsigned and must be zero-extended.
+      std::string utype = "U" + typestr.str();
+      s += "(" + TypeString(proto[0], typestr) + ")";
+      abd = "(" + TypeString('d', utype) + ")" + abd;
+      s += Extend(utype, abd) + ";";
+    } else {
+      s += Extend(typestr, abd) + ";";
+    }
+    break;
+  }
+  case OpAba:
+    s += "__a + " + MangleName("vabd", typestr, ClassS) + "(__b, __c);";
+    break;
+  case OpAbal: {
+    s += "__a + ";
+    std::string abd = MangleName("vabd", typestr, ClassS) + "(__b, __c)";
+    if (typestr[0] != 'U') {
+      // vabd results are always unsigned and must be zero-extended.
+      std::string utype = "U" + typestr.str();
+      s += "(" + TypeString(proto[0], typestr) + ")";
+      abd = "(" + TypeString('d', utype) + ")" + abd;
+      s += Extend(utype, abd) + ";";
+    } else {
+      s += Extend(typestr, abd) + ";";
+    }
+    break;
+  }
+  default:
+    throw "unknown OpKind!";
+    break;
+  }
+  return s;
+}
+
+static unsigned GetNeonEnum(const std::string &proto, StringRef typestr) {
+  unsigned mod = proto[0];
+  unsigned ret = 0;
+
+  if (mod == 'v' || mod == 'f')
+    mod = proto[1];
+
+  bool quad = false;
+  bool poly = false;
+  bool usgn = false;
+  bool scal = false;
+  bool cnst = false;
+  bool pntr = false;
+
+  // Base type to get the type string for.
+  char type = ClassifyType(typestr, quad, poly, usgn);
+
+  // Based on the modifying character, change the type and width if necessary.
+  type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
+
+  if (usgn)
+    ret |= 0x08;
+  if (quad && proto[1] != 'g')
+    ret |= 0x10;
+
+  switch (type) {
+    case 'c':
+      ret |= poly ? 5 : 0;
+      break;
+    case 's':
+      ret |= poly ? 6 : 1;
+      break;
+    case 'i':
+      ret |= 2;
+      break;
+    case 'l':
+      ret |= 3;
+      break;
+    case 'h':
+      ret |= 7;
+      break;
+    case 'f':
+      ret |= 4;
+      break;
+    default:
+      throw "unhandled type!";
+      break;
+  }
+  return ret;
+}
+
+// Generate the definition for this intrinsic, e.g. __builtin_neon_cls(a)
+static std::string GenBuiltin(const std::string &name, const std::string &proto,
+                              StringRef typestr, ClassKind ck) {
+  std::string s;
+
+  // If this builtin returns a struct 2, 3, or 4 vectors, pass it as an implicit
+  // sret-like argument.
+  bool sret = (proto[0] >= '2' && proto[0] <= '4');
+
+  bool define = UseMacro(proto);
+
+  // Check if the prototype has a scalar operand with the type of the vector
+  // elements.  If not, bitcasting the args will take care of arg checking.
+  // The actual signedness etc. will be taken care of with special enums.
+  if (proto.find('s') == std::string::npos)
+    ck = ClassB;
+
+  if (proto[0] != 'v') {
+    std::string ts = TypeString(proto[0], typestr);
+
+    if (define) {
+      if (sret)
+        s += ts + " r; ";
+      else
+        s += "(" + ts + ")";
+    } else if (sret) {
+      s += ts + " r; ";
+    } else {
+      s += "return (" + ts + ")";
+    }
+  }
+
+  bool splat = proto.find('a') != std::string::npos;
+
+  s += "__builtin_neon_";
+  if (splat) {
+    // Call the non-splat builtin: chop off the "_n" suffix from the name.
+    std::string vname(name, 0, name.size()-2);
+    s += MangleName(vname, typestr, ck);
+  } else {
+    s += MangleName(name, typestr, ck);
+  }
+  s += "(";
+
+  // Pass the address of the return variable as the first argument to sret-like
+  // builtins.
+  if (sret)
+    s += "&r, ";
+
+  char arg = 'a';
+  for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
+    std::string args = std::string(&arg, 1);
+
+    // Use the local temporaries instead of the macro arguments.
+    args = "__" + args;
+
+    bool argQuad = false;
+    bool argPoly = false;
+    bool argUsgn = false;
+    bool argScalar = false;
+    bool dummy = false;
+    char argType = ClassifyType(typestr, argQuad, argPoly, argUsgn);
+    argType = ModType(proto[i], argType, argQuad, argPoly, argUsgn, argScalar,
+                      dummy, dummy);
+
+    // Handle multiple-vector values specially, emitting each subvector as an
+    // argument to the __builtin.
+    if (proto[i] >= '2' && proto[i] <= '4') {
+      // Check if an explicit cast is needed.
+      if (argType != 'c' || argPoly || argUsgn)
+        args = (argQuad ? "(int8x16_t)" : "(int8x8_t)") + args;
+
+      for (unsigned vi = 0, ve = proto[i] - '0'; vi != ve; ++vi) {
+        s += args + ".val[" + utostr(vi) + "]";
+        if ((vi + 1) < ve)
+          s += ", ";
+      }
+      if ((i + 1) < e)
+        s += ", ";
+
+      continue;
+    }
+
+    if (splat && (i + 1) == e)
+      args = Duplicate(GetNumElements(typestr, argQuad), typestr, args);
+
+    // Check if an explicit cast is needed.
+    if ((splat || !argScalar) &&
+        ((ck == ClassB && argType != 'c') || argPoly || argUsgn)) {
+      std::string argTypeStr = "c";
+      if (ck != ClassB)
+        argTypeStr = argType;
+      if (argQuad)
+        argTypeStr = "Q" + argTypeStr;
+      args = "(" + TypeString('d', argTypeStr) + ")" + args;
+    }
+
+    s += args;
+    if ((i + 1) < e)
+      s += ", ";
+  }
+
+  // Extra constant integer to hold type class enum for this function, e.g. s8
+  if (ck == ClassB)
+    s += ", " + utostr(GetNeonEnum(proto, typestr));
+
+  s += ");";
+
+  if (proto[0] != 'v' && sret) {
+    if (define)
+      s += " r;";
+    else
+      s += " return r;";
+  }
+  return s;
+}
+
+static std::string GenBuiltinDef(const std::string &name,
+                                 const std::string &proto,
+                                 StringRef typestr, ClassKind ck) {
+  std::string s("BUILTIN(__builtin_neon_");
+
+  // If all types are the same size, bitcasting the args will take care
+  // of arg checking.  The actual signedness etc. will be taken care of with
+  // special enums.
+  if (proto.find('s') == std::string::npos)
+    ck = ClassB;
+
+  s += MangleName(name, typestr, ck);
+  s += ", \"";
+
+  for (unsigned i = 0, e = proto.size(); i != e; ++i)
+    s += BuiltinTypeString(proto[i], typestr, ck, i == 0);
+
+  // Extra constant integer to hold type class enum for this function, e.g. s8
+  if (ck == ClassB)
+    s += "i";
+
+  s += "\", \"n\")";
+  return s;
+}
+
+static std::string GenIntrinsic(const std::string &name,
+                                const std::string &proto,
+                                StringRef outTypeStr, StringRef inTypeStr,
+                                OpKind kind, ClassKind classKind) {
+  assert(!proto.empty() && "");
+  bool define = UseMacro(proto);
+  std::string s;
+
+  // static always inline + return type
+  if (define)
+    s += "#define ";
+  else
+    s += "__ai " + TypeString(proto[0], outTypeStr) + " ";
+
+  // Function name with type suffix
+  std::string mangledName = MangleName(name, outTypeStr, ClassS);
+  if (outTypeStr != inTypeStr) {
+    // If the input type is different (e.g., for vreinterpret), append a suffix
+    // for the input type.  String off a "Q" (quad) prefix so that MangleName
+    // does not insert another "q" in the name.
+    unsigned typeStrOff = (inTypeStr[0] == 'Q' ? 1 : 0);
+    StringRef inTypeNoQuad = inTypeStr.substr(typeStrOff);
+    mangledName = MangleName(mangledName, inTypeNoQuad, ClassS);
+  }
+  s += mangledName;
+
+  // Function arguments
+  s += GenArgs(proto, inTypeStr);
+
+  // Definition.
+  if (define) {
+    s += " __extension__ ({ \\\n  ";
+    s += GenMacroLocals(proto, inTypeStr);
+  } else {
+    s += " { \\\n  ";
+  }
+
+  if (kind != OpNone)
+    s += GenOpString(kind, proto, outTypeStr);
+  else
+    s += GenBuiltin(name, proto, outTypeStr, classKind);
+  if (define)
+    s += " })";
+  else
+    s += " }";
+  s += "\n";
+  return s;
+}
+
+/// run - Read the records in arm_neon.td and output arm_neon.h.  arm_neon.h
+/// is comprised of type definitions and function declarations.
+void NeonEmitter::run(raw_ostream &OS) {
+  OS << 
+    "/*===---- arm_neon.h - ARM Neon intrinsics ------------------------------"
+    "---===\n"
+    " *\n"
+    " * Permission is hereby granted, free of charge, to any person obtaining "
+    "a copy\n"
+    " * of this software and associated documentation files (the \"Software\"),"
+    " to deal\n"
+    " * in the Software without restriction, including without limitation the "
+    "rights\n"
+    " * to use, copy, modify, merge, publish, distribute, sublicense, "
+    "and/or sell\n"
+    " * copies of the Software, and to permit persons to whom the Software is\n"
+    " * furnished to do so, subject to the following conditions:\n"
+    " *\n"
+    " * The above copyright notice and this permission notice shall be "
+    "included in\n"
+    " * all copies or substantial portions of the Software.\n"
+    " *\n"
+    " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, "
+    "EXPRESS OR\n"
+    " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF "
+    "MERCHANTABILITY,\n"
+    " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT "
+    "SHALL THE\n"
+    " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR "
+    "OTHER\n"
+    " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, "
+    "ARISING FROM,\n"
+    " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER "
+    "DEALINGS IN\n"
+    " * THE SOFTWARE.\n"
+    " *\n"
+    " *===--------------------------------------------------------------------"
+    "---===\n"
+    " */\n\n";
+
+  OS << "#ifndef __ARM_NEON_H\n";
+  OS << "#define __ARM_NEON_H\n\n";
+
+  OS << "#ifndef __ARM_NEON__\n";
+  OS << "#error \"NEON support not enabled\"\n";
+  OS << "#endif\n\n";
+
+  OS << "#include <stdint.h>\n\n";
+
+  // Emit NEON-specific scalar typedefs.
+  OS << "typedef float float32_t;\n";
+  OS << "typedef int8_t poly8_t;\n";
+  OS << "typedef int16_t poly16_t;\n";
+  OS << "typedef uint16_t float16_t;\n";
+
+  // Emit Neon vector typedefs.
+  std::string TypedefTypes("cQcsQsiQilQlUcQUcUsQUsUiQUiUlQUlhQhfQfPcQPcPsQPs");
+  SmallVector<StringRef, 24> TDTypeVec;
+  ParseTypes(0, TypedefTypes, TDTypeVec);
+
+  // Emit vector typedefs.
+  for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) {
+    bool dummy, quad = false, poly = false;
+    (void) ClassifyType(TDTypeVec[i], quad, poly, dummy);
+    if (poly)
+      OS << "typedef __attribute__((neon_polyvector_type(";
+    else
+      OS << "typedef __attribute__((neon_vector_type(";
+
+    unsigned nElts = GetNumElements(TDTypeVec[i], quad);
+    OS << utostr(nElts) << "))) ";
+    if (nElts < 10)
+      OS << " ";
+
+    OS << TypeString('s', TDTypeVec[i]);
+    OS << " " << TypeString('d', TDTypeVec[i]) << ";\n";
+  }
+  OS << "\n";
+
+  // Emit struct typedefs.
+  for (unsigned vi = 2; vi != 5; ++vi) {
+    for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) {
+      std::string ts = TypeString('d', TDTypeVec[i]);
+      std::string vs = TypeString('0' + vi, TDTypeVec[i]);
+      OS << "typedef struct " << vs << " {\n";
+      OS << "  " << ts << " val";
+      OS << "[" << utostr(vi) << "]";
+      OS << ";\n} ";
+      OS << vs << ";\n\n";
+    }
+  }
+
+  OS << "#define __ai static __attribute__((__always_inline__))\n\n";
+
+  std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
+
+  // Emit vmovl, vmull and vabd intrinsics first so they can be used by other
+  // intrinsics.  (Some of the saturating multiply instructions are also
+  // used to implement the corresponding "_lane" variants, but tablegen
+  // sorts the records into alphabetical order so that the "_lane" variants
+  // come after the intrinsics they use.)
+  emitIntrinsic(OS, Records.getDef("VMOVL"));
+  emitIntrinsic(OS, Records.getDef("VMULL"));
+  emitIntrinsic(OS, Records.getDef("VABD"));
+
+  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
+    Record *R = RV[i];
+    if (R->getName() != "VMOVL" &&
+        R->getName() != "VMULL" &&
+        R->getName() != "VABD")
+      emitIntrinsic(OS, R);
+  }
+
+  OS << "#undef __ai\n\n";
+  OS << "#endif /* __ARM_NEON_H */\n";
+}
+
+/// emitIntrinsic - Write out the arm_neon.h header file definitions for the
+/// intrinsics specified by record R.
+void NeonEmitter::emitIntrinsic(raw_ostream &OS, Record *R) {
+  std::string name = R->getValueAsString("Name");
+  std::string Proto = R->getValueAsString("Prototype");
+  std::string Types = R->getValueAsString("Types");
+
+  SmallVector<StringRef, 16> TypeVec;
+  ParseTypes(R, Types, TypeVec);
+
+  OpKind kind = OpMap[R->getValueAsDef("Operand")->getName()];
+
+  ClassKind classKind = ClassNone;
+  if (R->getSuperClasses().size() >= 2)
+    classKind = ClassMap[R->getSuperClasses()[1]];
+  if (classKind == ClassNone && kind == OpNone)
+    throw TGError(R->getLoc(), "Builtin has no class kind");
+
+  for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
+    if (kind == OpReinterpret) {
+      bool outQuad = false;
+      bool dummy = false;
+      (void)ClassifyType(TypeVec[ti], outQuad, dummy, dummy);
+      for (unsigned srcti = 0, srcte = TypeVec.size();
+           srcti != srcte; ++srcti) {
+        bool inQuad = false;
+        (void)ClassifyType(TypeVec[srcti], inQuad, dummy, dummy);
+        if (srcti == ti || inQuad != outQuad)
+          continue;
+        OS << GenIntrinsic(name, Proto, TypeVec[ti], TypeVec[srcti],
+                           OpCast, ClassS);
+      }
+    } else {
+      OS << GenIntrinsic(name, Proto, TypeVec[ti], TypeVec[ti],
+                         kind, classKind);
+    }
+  }
+  OS << "\n";
+}
+
+static unsigned RangeFromType(const char mod, StringRef typestr) {
+  // base type to get the type string for.
+  bool quad = false, dummy = false;
+  char type = ClassifyType(typestr, quad, dummy, dummy);
+  type = ModType(mod, type, quad, dummy, dummy, dummy, dummy, dummy);
+
+  switch (type) {
+    case 'c':
+      return (8 << (int)quad) - 1;
+    case 'h':
+    case 's':
+      return (4 << (int)quad) - 1;
+    case 'f':
+    case 'i':
+      return (2 << (int)quad) - 1;
+    case 'l':
+      return (1 << (int)quad) - 1;
+    default:
+      throw "unhandled type!";
+      break;
+  }
+  assert(0 && "unreachable");
+  return 0;
+}
+
+/// runHeader - Emit a file with sections defining:
+/// 1. the NEON section of BuiltinsARM.def.
+/// 2. the SemaChecking code for the type overload checking.
+/// 3. the SemaChecking code for validation of intrinsic immedate arguments.
+void NeonEmitter::runHeader(raw_ostream &OS) {
+  std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
+
+  StringMap<OpKind> EmittedMap;
+
+  // Generate BuiltinsARM.def for NEON
+  OS << "#ifdef GET_NEON_BUILTINS\n";
+  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
+    Record *R = RV[i];
+    OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
+    if (k != OpNone)
+      continue;
+
+    std::string Proto = R->getValueAsString("Prototype");
+
+    // Functions with 'a' (the splat code) in the type prototype should not get
+    // their own builtin as they use the non-splat variant.
+    if (Proto.find('a') != std::string::npos)
+      continue;
+
+    std::string Types = R->getValueAsString("Types");
+    SmallVector<StringRef, 16> TypeVec;
+    ParseTypes(R, Types, TypeVec);
+
+    if (R->getSuperClasses().size() < 2)
+      throw TGError(R->getLoc(), "Builtin has no class kind");
+
+    std::string name = R->getValueAsString("Name");
+    ClassKind ck = ClassMap[R->getSuperClasses()[1]];
+
+    for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
+      // Generate the BuiltinsARM.def declaration for this builtin, ensuring
+      // that each unique BUILTIN() macro appears only once in the output
+      // stream.
+      std::string bd = GenBuiltinDef(name, Proto, TypeVec[ti], ck);
+      if (EmittedMap.count(bd))
+        continue;
+
+      EmittedMap[bd] = OpNone;
+      OS << bd << "\n";
+    }
+  }
+  OS << "#endif\n\n";
+
+  // Generate the overloaded type checking code for SemaChecking.cpp
+  OS << "#ifdef GET_NEON_OVERLOAD_CHECK\n";
+  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
+    Record *R = RV[i];
+    OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
+    if (k != OpNone)
+      continue;
+
+    std::string Proto = R->getValueAsString("Prototype");
+    std::string Types = R->getValueAsString("Types");
+    std::string name = R->getValueAsString("Name");
+
+    // Functions with 'a' (the splat code) in the type prototype should not get
+    // their own builtin as they use the non-splat variant.
+    if (Proto.find('a') != std::string::npos)
+      continue;
+
+    // Functions which have a scalar argument cannot be overloaded, no need to
+    // check them if we are emitting the type checking code.
+    if (Proto.find('s') != std::string::npos)
+      continue;
+
+    SmallVector<StringRef, 16> TypeVec;
+    ParseTypes(R, Types, TypeVec);
+
+    if (R->getSuperClasses().size() < 2)
+      throw TGError(R->getLoc(), "Builtin has no class kind");
+
+    int si = -1, qi = -1;
+    unsigned mask = 0, qmask = 0;
+    for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
+      // Generate the switch case(s) for this builtin for the type validation.
+      bool quad = false, poly = false, usgn = false;
+      (void) ClassifyType(TypeVec[ti], quad, poly, usgn);
+
+      if (quad) {
+        qi = ti;
+        qmask |= 1 << GetNeonEnum(Proto, TypeVec[ti]);
+      } else {
+        si = ti;
+        mask |= 1 << GetNeonEnum(Proto, TypeVec[ti]);
+      }
+    }
+    if (mask)
+      OS << "case ARM::BI__builtin_neon_"
+         << MangleName(name, TypeVec[si], ClassB)
+         << ": mask = " << "0x" << utohexstr(mask) << "; break;\n";
+    if (qmask)
+      OS << "case ARM::BI__builtin_neon_"
+         << MangleName(name, TypeVec[qi], ClassB)
+         << ": mask = " << "0x" << utohexstr(qmask) << "; break;\n";
+  }
+  OS << "#endif\n\n";
+
+  // Generate the intrinsic range checking code for shift/lane immediates.
+  OS << "#ifdef GET_NEON_IMMEDIATE_CHECK\n";
+  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
+    Record *R = RV[i];
+
+    OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
+    if (k != OpNone)
+      continue;
+
+    std::string name = R->getValueAsString("Name");
+    std::string Proto = R->getValueAsString("Prototype");
+    std::string Types = R->getValueAsString("Types");
+
+    // Functions with 'a' (the splat code) in the type prototype should not get
+    // their own builtin as they use the non-splat variant.
+    if (Proto.find('a') != std::string::npos)
+      continue;
+
+    // Functions which do not have an immediate do not need to have range
+    // checking code emitted.
+    size_t immPos = Proto.find('i');
+    if (immPos == std::string::npos)
+      continue;
+
+    SmallVector<StringRef, 16> TypeVec;
+    ParseTypes(R, Types, TypeVec);
+
+    if (R->getSuperClasses().size() < 2)
+      throw TGError(R->getLoc(), "Builtin has no class kind");
+
+    ClassKind ck = ClassMap[R->getSuperClasses()[1]];
+
+    for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
+      std::string namestr, shiftstr, rangestr;
+
+      if (R->getValueAsBit("isVCVT_N")) {
+        // VCVT between floating- and fixed-point values takes an immediate
+        // in the range 1 to 32.
+        ck = ClassB;
+        rangestr = "l = 1; u = 31"; // upper bound = l + u
+      } else if (Proto.find('s') == std::string::npos) {
+        // Builtins which are overloaded by type will need to have their upper
+        // bound computed at Sema time based on the type constant.
+        ck = ClassB;
+        if (R->getValueAsBit("isShift")) {
+          shiftstr = ", true";
+
+          // Right shifts have an 'r' in the name, left shifts do not.
+          if (name.find('r') != std::string::npos)
+            rangestr = "l = 1; ";
+        }
+        rangestr += "u = RFT(TV" + shiftstr + ")";
+      } else {
+        // The immediate generally refers to a lane in the preceding argument.
+        assert(immPos > 0 && "unexpected immediate operand");
+        rangestr = "u = " + utostr(RangeFromType(Proto[immPos-1], TypeVec[ti]));
+      }
+      // Make sure cases appear only once by uniquing them in a string map.
+      namestr = MangleName(name, TypeVec[ti], ck);
+      if (EmittedMap.count(namestr))
+        continue;
+      EmittedMap[namestr] = OpNone;
+
+      // Calculate the index of the immediate that should be range checked.
+      unsigned immidx = 0;
+
+      // Builtins that return a struct of multiple vectors have an extra
+      // leading arg for the struct return.
+      if (Proto[0] >= '2' && Proto[0] <= '4')
+        ++immidx;
+
+      // Add one to the index for each argument until we reach the immediate
+      // to be checked.  Structs of vectors are passed as multiple arguments.
+      for (unsigned ii = 1, ie = Proto.size(); ii != ie; ++ii) {
+        switch (Proto[ii]) {
+          default:  immidx += 1; break;
+          case '2': immidx += 2; break;
+          case '3': immidx += 3; break;
+          case '4': immidx += 4; break;
+          case 'i': ie = ii + 1; break;
+        }
+      }
+      OS << "case ARM::BI__builtin_neon_" << MangleName(name, TypeVec[ti], ck)
+         << ": i = " << immidx << "; " << rangestr << "; break;\n";
+    }
+  }
+  OS << "#endif\n\n";
+}
+
+/// GenTest - Write out a test for the intrinsic specified by the name and
+/// type strings, including the embedded patterns for FileCheck to match.
+static std::string GenTest(const std::string &name,
+                           const std::string &proto,
+                           StringRef outTypeStr, StringRef inTypeStr,
+                           bool isShift) {
+  assert(!proto.empty() && "");
+  std::string s;
+
+  // Function name with type suffix
+  std::string mangledName = MangleName(name, outTypeStr, ClassS);
+  if (outTypeStr != inTypeStr) {
+    // If the input type is different (e.g., for vreinterpret), append a suffix
+    // for the input type.  String off a "Q" (quad) prefix so that MangleName
+    // does not insert another "q" in the name.
+    unsigned typeStrOff = (inTypeStr[0] == 'Q' ? 1 : 0);
+    StringRef inTypeNoQuad = inTypeStr.substr(typeStrOff);
+    mangledName = MangleName(mangledName, inTypeNoQuad, ClassS);
+  }
+
+  // Emit the FileCheck patterns.
+  s += "// CHECK: test_" + mangledName + "\n";
+  // s += "// CHECK: \n"; // FIXME: + expected instruction opcode.
+
+  // Emit the start of the test function.
+  s += TypeString(proto[0], outTypeStr) + " test_" + mangledName + "(";
+  char arg = 'a';
+  std::string comma;
+  for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
+    // Do not create arguments for values that must be immediate constants.
+    if (proto[i] == 'i')
+      continue;
+    s += comma + TypeString(proto[i], inTypeStr) + " ";
+    s.push_back(arg);
+    comma = ", ";
+  }
+  s += ") { \\\n  ";
+
+  if (proto[0] != 'v')
+    s += "return ";
+  s += mangledName + "(";
+  arg = 'a';
+  for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
+    if (proto[i] == 'i') {
+      // For immediate operands, test the maximum value.
+      if (isShift)
+        s += "1"; // FIXME
+      else
+        // The immediate generally refers to a lane in the preceding argument.
+        s += utostr(RangeFromType(proto[i-1], inTypeStr));
+    } else {
+      s.push_back(arg);
+    }
+    if ((i + 1) < e)
+      s += ", ";
+  }
+  s += ");\n}\n\n";
+  return s;
+}
+
+/// runTests - Write out a complete set of tests for all of the Neon
+/// intrinsics.
+void NeonEmitter::runTests(raw_ostream &OS) {
+  OS <<
+    "// RUN: %clang_cc1 -triple thumbv7-apple-darwin \\\n"
+    "// RUN:  -target-cpu cortex-a9 -ffreestanding -S -o - %s | FileCheck %s\n"
+    "\n"
+    "#include <arm_neon.h>\n"
+    "\n";
+
+  std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
+  for (unsigned i = 0, e = RV.size(); i != e; ++i) {
+    Record *R = RV[i];
+    std::string name = R->getValueAsString("Name");
+    std::string Proto = R->getValueAsString("Prototype");
+    std::string Types = R->getValueAsString("Types");
+    bool isShift = R->getValueAsBit("isShift");
+
+    SmallVector<StringRef, 16> TypeVec;
+    ParseTypes(R, Types, TypeVec);
+
+    OpKind kind = OpMap[R->getValueAsDef("Operand")->getName()];
+    for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
+      if (kind == OpReinterpret) {
+        bool outQuad = false;
+        bool dummy = false;
+        (void)ClassifyType(TypeVec[ti], outQuad, dummy, dummy);
+        for (unsigned srcti = 0, srcte = TypeVec.size();
+             srcti != srcte; ++srcti) {
+          bool inQuad = false;
+          (void)ClassifyType(TypeVec[srcti], inQuad, dummy, dummy);
+          if (srcti == ti || inQuad != outQuad)
+            continue;
+          OS << GenTest(name, Proto, TypeVec[ti], TypeVec[srcti], isShift);
+        }
+      } else {
+        OS << GenTest(name, Proto, TypeVec[ti], TypeVec[ti], isShift);
+      }
+    }
+    OS << "\n";
+  }
+}
+

Added: cfe/trunk/utils/TableGen/NeonEmitter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/NeonEmitter.h?rev=141291&view=auto
==============================================================================
--- cfe/trunk/utils/TableGen/NeonEmitter.h (added)
+++ cfe/trunk/utils/TableGen/NeonEmitter.h Thu Oct  6 08:03:08 2011
@@ -0,0 +1,176 @@
+//===- 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
+};
+
+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

Added: cfe/trunk/utils/TableGen/OptParserEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/OptParserEmitter.cpp?rev=141291&view=auto
==============================================================================
--- cfe/trunk/utils/TableGen/OptParserEmitter.cpp (added)
+++ cfe/trunk/utils/TableGen/OptParserEmitter.cpp Thu Oct  6 08:03:08 2011
@@ -0,0 +1,194 @@
+//===- OptParserEmitter.cpp - Table Driven Command Line Parsing -----------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "OptParserEmitter.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/ADT/STLExtras.h"
+using namespace llvm;
+
+static int StrCmpOptionName(const char *A, const char *B) {
+  char a = *A, b = *B;
+  while (a == b) {
+    if (a == '\0')
+      return 0;
+
+    a = *++A;
+    b = *++B;
+  }
+
+  if (a == '\0') // A is a prefix of B.
+    return 1;
+  if (b == '\0') // B is a prefix of A.
+    return -1;
+
+  // Otherwise lexicographic.
+  return (a < b) ? -1 : 1;
+}
+
+static int CompareOptionRecords(const void *Av, const void *Bv) {
+  const Record *A = *(Record**) Av;
+  const Record *B = *(Record**) Bv;
+
+  // Sentinel options precede all others and are only ordered by precedence.
+  bool ASent = A->getValueAsDef("Kind")->getValueAsBit("Sentinel");
+  bool BSent = B->getValueAsDef("Kind")->getValueAsBit("Sentinel");
+  if (ASent != BSent)
+    return ASent ? -1 : 1;
+
+  // Compare options by name, unless they are sentinels.
+  if (!ASent)
+    if (int Cmp = StrCmpOptionName(A->getValueAsString("Name").c_str(),
+                                   B->getValueAsString("Name").c_str()))
+    return Cmp;
+
+  // Then by the kind precedence;
+  int APrec = A->getValueAsDef("Kind")->getValueAsInt("Precedence");
+  int BPrec = B->getValueAsDef("Kind")->getValueAsInt("Precedence");
+  assert(APrec != BPrec && "Options are equivalent!");
+  return APrec < BPrec ? -1 : 1;
+}
+
+static const std::string getOptionName(const Record &R) {
+  // Use the record name unless EnumName is defined.
+  if (dynamic_cast<UnsetInit*>(R.getValueInit("EnumName")))
+    return R.getName();
+
+  return R.getValueAsString("EnumName");
+}
+
+static raw_ostream &write_cstring(raw_ostream &OS, llvm::StringRef Str) {
+  OS << '"';
+  OS.write_escaped(Str);
+  OS << '"';
+  return OS;
+}
+
+void OptParserEmitter::run(raw_ostream &OS) {
+  // Get the option groups and options.
+  const std::vector<Record*> &Groups =
+    Records.getAllDerivedDefinitions("OptionGroup");
+  std::vector<Record*> Opts = Records.getAllDerivedDefinitions("Option");
+
+  if (GenDefs)
+    EmitSourceFileHeader("Option Parsing Definitions", OS);
+  else
+    EmitSourceFileHeader("Option Parsing Table", OS);
+
+  array_pod_sort(Opts.begin(), Opts.end(), CompareOptionRecords);
+  if (GenDefs) {
+    OS << "#ifndef OPTION\n";
+    OS << "#error \"Define OPTION prior to including this file!\"\n";
+    OS << "#endif\n\n";
+
+    OS << "/////////\n";
+    OS << "// Groups\n\n";
+    for (unsigned i = 0, e = Groups.size(); i != e; ++i) {
+      const Record &R = *Groups[i];
+
+      // Start a single option entry.
+      OS << "OPTION(";
+
+      // The option string.
+      OS << '"' << R.getValueAsString("Name") << '"';
+
+      // The option identifier name.
+      OS  << ", "<< getOptionName(R);
+
+      // The option kind.
+      OS << ", Group";
+
+      // The containing option group (if any).
+      OS << ", ";
+      if (const DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("Group")))
+        OS << getOptionName(*DI->getDef());
+      else
+        OS << "INVALID";
+
+      // The other option arguments (unused for groups).
+      OS << ", INVALID, 0, 0";
+
+      // The option help text.
+      if (!dynamic_cast<UnsetInit*>(R.getValueInit("HelpText"))) {
+        OS << ",\n";
+        OS << "       ";
+        write_cstring(OS, R.getValueAsString("HelpText"));
+      } else
+        OS << ", 0";
+
+      // The option meta-variable name (unused).
+      OS << ", 0)\n";
+    }
+    OS << "\n";
+
+    OS << "//////////\n";
+    OS << "// Options\n\n";
+    for (unsigned i = 0, e = Opts.size(); i != e; ++i) {
+      const Record &R = *Opts[i];
+
+      // Start a single option entry.
+      OS << "OPTION(";
+
+      // The option string.
+      write_cstring(OS, R.getValueAsString("Name"));
+
+      // The option identifier name.
+      OS  << ", "<< getOptionName(R);
+
+      // The option kind.
+      OS << ", " << R.getValueAsDef("Kind")->getValueAsString("Name");
+
+      // The containing option group (if any).
+      OS << ", ";
+      if (const DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("Group")))
+        OS << getOptionName(*DI->getDef());
+      else
+        OS << "INVALID";
+
+      // The option alias (if any).
+      OS << ", ";
+      if (const DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("Alias")))
+        OS << getOptionName(*DI->getDef());
+      else
+        OS << "INVALID";
+
+      // The option flags.
+      const ListInit *LI = R.getValueAsListInit("Flags");
+      if (LI->empty()) {
+        OS << ", 0";
+      } else {
+        OS << ", ";
+        for (unsigned i = 0, e = LI->size(); i != e; ++i) {
+          if (i)
+            OS << " | ";
+          OS << dynamic_cast<DefInit*>(LI->getElement(i))->getDef()->getName();
+        }
+      }
+
+      // The option parameter field.
+      OS << ", " << R.getValueAsInt("NumArgs");
+
+      // The option help text.
+      if (!dynamic_cast<UnsetInit*>(R.getValueInit("HelpText"))) {
+        OS << ",\n";
+        OS << "       ";
+        write_cstring(OS, R.getValueAsString("HelpText"));
+      } else
+        OS << ", 0";
+
+      // The option meta-variable name.
+      OS << ", ";
+      if (!dynamic_cast<UnsetInit*>(R.getValueInit("MetaVarName")))
+        write_cstring(OS, R.getValueAsString("MetaVarName"));
+      else
+        OS << "0";
+
+      OS << ")\n";
+    }
+  }
+}

Added: cfe/trunk/utils/TableGen/OptParserEmitter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/OptParserEmitter.h?rev=141291&view=auto
==============================================================================
--- cfe/trunk/utils/TableGen/OptParserEmitter.h (added)
+++ cfe/trunk/utils/TableGen/OptParserEmitter.h Thu Oct  6 08:03:08 2011
@@ -0,0 +1,34 @@
+//===- 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

Added: cfe/trunk/utils/TableGen/TableGen.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/TableGen.cpp?rev=141291&view=auto
==============================================================================
--- cfe/trunk/utils/TableGen/TableGen.cpp (added)
+++ cfe/trunk/utils/TableGen/TableGen.cpp Thu Oct  6 08:03:08 2011
@@ -0,0 +1,176 @@
+//===- TableGen.cpp - Top-Level TableGen implementation for Clang ---------===//
+//
+//                     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 main function for Clang's TableGen.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangASTNodesEmitter.h"
+#include "ClangAttrEmitter.h"
+#include "ClangDiagnosticsEmitter.h"
+#include "ClangSACheckersEmitter.h"
+#include "NeonEmitter.h"
+#include "OptParserEmitter.h"
+
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Main.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/TableGenAction.h"
+
+using namespace llvm;
+
+enum ActionType {
+  GenClangAttrClasses,
+  GenClangAttrImpl,
+  GenClangAttrList,
+  GenClangAttrPCHRead,
+  GenClangAttrPCHWrite,
+  GenClangAttrSpellingList,
+  GenClangAttrLateParsedList,
+  GenClangDiagsDefs,
+  GenClangDiagGroups,
+  GenClangDiagsIndexName,
+  GenClangDeclNodes,
+  GenClangStmtNodes,
+  GenClangSACheckers,
+  GenOptParserDefs, GenOptParserImpl,
+  GenArmNeon,
+  GenArmNeonSema,
+  GenArmNeonTest
+};
+
+namespace {
+  cl::opt<ActionType>
+  Action(cl::desc("Action to perform:"),
+         cl::values(clEnumValN(GenOptParserDefs, "gen-opt-parser-defs",
+                               "Generate option definitions"),
+                    clEnumValN(GenOptParserImpl, "gen-opt-parser-impl",
+                               "Generate option parser implementation"),
+                    clEnumValN(GenClangAttrClasses, "gen-clang-attr-classes",
+                               "Generate clang attribute clases"),
+                    clEnumValN(GenClangAttrImpl, "gen-clang-attr-impl",
+                               "Generate clang attribute implementations"),
+                    clEnumValN(GenClangAttrList, "gen-clang-attr-list",
+                               "Generate a clang attribute list"),
+                    clEnumValN(GenClangAttrPCHRead, "gen-clang-attr-pch-read",
+                               "Generate clang PCH attribute reader"),
+                    clEnumValN(GenClangAttrPCHWrite, "gen-clang-attr-pch-write",
+                               "Generate clang PCH attribute writer"),
+                    clEnumValN(GenClangAttrSpellingList,
+                               "gen-clang-attr-spelling-list",
+                               "Generate a clang attribute spelling list"),
+                    clEnumValN(GenClangAttrLateParsedList,
+                               "gen-clang-attr-late-parsed-list",
+                               "Generate a clang attribute LateParsed list"),
+                    clEnumValN(GenClangDiagsDefs, "gen-clang-diags-defs",
+                               "Generate Clang diagnostics definitions"),
+                    clEnumValN(GenClangDiagGroups, "gen-clang-diag-groups",
+                               "Generate Clang diagnostic groups"),
+                    clEnumValN(GenClangDiagsIndexName,
+                               "gen-clang-diags-index-name",
+                               "Generate Clang diagnostic name index"),
+                    clEnumValN(GenClangDeclNodes, "gen-clang-decl-nodes",
+                               "Generate Clang AST declaration nodes"),
+                    clEnumValN(GenClangStmtNodes, "gen-clang-stmt-nodes",
+                               "Generate Clang AST statement nodes"),
+                    clEnumValN(GenClangSACheckers, "gen-clang-sa-checkers",
+                               "Generate Clang Static Analyzer checkers"),
+                    clEnumValN(GenArmNeon, "gen-arm-neon",
+                               "Generate arm_neon.h for clang"),
+                    clEnumValN(GenArmNeonSema, "gen-arm-neon-sema",
+                               "Generate ARM NEON sema support for clang"),
+                    clEnumValN(GenArmNeonTest, "gen-arm-neon-test",
+                               "Generate ARM NEON tests for clang"),
+                    clEnumValEnd));
+
+  cl::opt<std::string>
+  ClangComponent("clang-component",
+                 cl::desc("Only use warnings from specified component"),
+                 cl::value_desc("component"), cl::Hidden);
+}
+
+class ClangTableGenAction : public TableGenAction {
+public:
+  bool operator()(raw_ostream &OS, RecordKeeper &Records) {
+    switch (Action) {
+    case GenClangAttrClasses:
+      ClangAttrClassEmitter(Records).run(OS);
+      break;
+    case GenClangAttrImpl:
+      ClangAttrImplEmitter(Records).run(OS);
+      break;
+    case GenClangAttrList:
+      ClangAttrListEmitter(Records).run(OS);
+      break;
+    case GenClangAttrPCHRead:
+      ClangAttrPCHReadEmitter(Records).run(OS);
+      break;
+    case GenClangAttrPCHWrite:
+      ClangAttrPCHWriteEmitter(Records).run(OS);
+      break;
+    case GenClangAttrSpellingList:
+      ClangAttrSpellingListEmitter(Records).run(OS);
+      break;
+    case GenClangAttrLateParsedList:
+      ClangAttrLateParsedListEmitter(Records).run(OS);
+      break;
+    case GenClangDiagsDefs:
+      ClangDiagsDefsEmitter(Records, ClangComponent).run(OS);
+      break;
+    case GenClangDiagGroups:
+      ClangDiagGroupsEmitter(Records).run(OS);
+      break;
+    case GenClangDiagsIndexName:
+      ClangDiagsIndexNameEmitter(Records).run(OS);
+      break;
+    case GenClangDeclNodes:
+      ClangASTNodesEmitter(Records, "Decl", "Decl").run(OS);
+      ClangDeclContextEmitter(Records).run(OS);
+      break;
+    case GenClangStmtNodes:
+      ClangASTNodesEmitter(Records, "Stmt", "").run(OS);
+      break;
+    case GenClangSACheckers:
+      ClangSACheckersEmitter(Records).run(OS);
+      break;
+    case GenOptParserDefs:
+      OptParserEmitter(Records, true).run(OS);
+      break;
+    case GenOptParserImpl:
+      OptParserEmitter(Records, false).run(OS);
+      break;
+    case GenArmNeon:
+      NeonEmitter(Records).run(OS);
+      break;
+    case GenArmNeonSema:
+      NeonEmitter(Records).runHeader(OS);
+      break;
+    case GenArmNeonTest:
+      NeonEmitter(Records).runTests(OS);
+      break;
+    default:
+      assert(1 && "Invalid Action");
+      return true;
+    }
+
+    return false;
+  }
+};
+
+int main(int argc, char **argv) {
+  sys::PrintStackTraceOnErrorSignal();
+  PrettyStackTraceProgram X(argc, argv);
+  cl::ParseCommandLineOptions(argc, argv);
+
+  ClangTableGenAction Action;
+  return TableGenMain(argv[0], Action);
+}





More information about the cfe-commits mailing list