#include "ASTTableGen.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/Error.h"
using namespace llvm;
using namespace clang;
using namespace clang::tblgen;
llvm::StringRef clang::tblgen::HasProperties::getName() const {
if (auto node = getAs<ASTNode>()) {
return node.getName();
} else if (auto typeCase = getAs<TypeCase>()) {
return typeCase.getCaseName();
} else {
PrintFatalError(getLoc(), "unexpected node declaring properties");
}
}
static StringRef removeExpectedNodeNameSuffix(Record *node, StringRef suffix) {
StringRef nodeName = node->getName();
if (!nodeName.endswith(suffix)) {
PrintFatalError(node->getLoc(),
Twine("name of node doesn't end in ") + suffix);
}
return nodeName.drop_back(suffix.size());
}
std::string clang::tblgen::DeclNode::getClassName() const {
return (Twine(getName()) + "Decl").str();
}
StringRef clang::tblgen::DeclNode::getId() const {
return getName();
}
StringRef clang::tblgen::TypeNode::getClassName() const {
return getName();
}
StringRef clang::tblgen::TypeNode::getId() const {
return removeExpectedNodeNameSuffix(getRecord(), "Type");
}
StringRef clang::tblgen::StmtNode::getClassName() const {
return getName();
}
std::string clang::tblgen::StmtNode::getId() const {
return (Twine(getName()) + "Class").str();
}
void PropertyType::emitCXXValueTypeName(bool forRead, raw_ostream &out) const {
if (!isGenericSpecialization()) {
if (!forRead && isConstWhenWriting())
out << "const ";
out << getCXXTypeName();
} else if (auto elementType = getArrayElementType()) {
out << "llvm::ArrayRef<";
elementType.emitCXXValueTypeName(forRead, out);
out << ">";
} else if (auto valueType = getOptionalElementType()) {
out << "llvm::Optional<";
valueType.emitCXXValueTypeName(forRead, out);
out << ">";
} else {
abort();
}
}
using ChildMap = std::multimap<ASTNode, ASTNode>;
static void visitASTNodeRecursive(ASTNode node, ASTNode base,
const ChildMap &map,
ASTNodeHierarchyVisitor<ASTNode> visit) {
visit(node, base);
auto i = map.lower_bound(node), e = map.upper_bound(node);
for (; i != e; ++i) {
visitASTNodeRecursive(i->second, node, map, visit);
}
}
static void visitHierarchy(RecordKeeper &records,
StringRef nodeClassName,
ASTNodeHierarchyVisitor<ASTNode> visit) {
if (!records.getClass(nodeClassName)) {
PrintFatalError(Twine("cannot find definition for node class ")
+ nodeClassName);
}
auto nodes = records.getAllDerivedDefinitions(nodeClassName);
ChildMap hierarchy;
ASTNode root;
for (ASTNode node : nodes) {
if (auto base = node.getBase())
hierarchy.insert(std::make_pair(base, node));
else if (root)
PrintFatalError(node.getLoc(),
"multiple root nodes in " + nodeClassName + " hierarchy");
else
root = node;
}
if (!root)
PrintFatalError(Twine("no root node in ") + nodeClassName + " hierarchy");
visitASTNodeRecursive(root, ASTNode(), hierarchy, visit);
}
void clang::tblgen::visitASTNodeHierarchyImpl(RecordKeeper &records,
StringRef nodeClassName,
ASTNodeHierarchyVisitor<ASTNode> visit) {
visitHierarchy(records, nodeClassName, visit);
}