freebsd-dev/contrib/llvm/utils/TableGen/ClangASTNodesEmitter.cpp
Ed Schouten ffd1746d03 Upgrade our Clang in base to r108428.
This commit merges the latest LLVM sources from the vendor space. It
also updates the build glue to match the new sources. Clang's version
number is changed to match LLVM's, which means /usr/include/clang/2.0
has been renamed to /usr/include/clang/2.8.

Obtained from:	projects/clangbsd
2010-07-20 17:16:57 +00:00

166 lines
5.3 KiB
C++

//=== 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);
}
}
}
for (RecordSet::iterator i = DeclContexts.begin(), e = DeclContexts.end();
i != e; ++i) {
OS << "DECL_CONTEXT(" << (*i)->getName() << ")\n";
}
OS << "#undef DECL_CONTEXT\n";
OS << "#undef DECL_CONTEXT_BASE\n";
}