brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.0 KiB · 6fa744f Raw
140 lines · cpp
1//===-- ASTTableGen.cpp - Helper functions for working with AST records ---===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file defines some helper functions for working with tblegen reocrds10// for the Clang AST: that is, the contents of files such as DeclNodes.td,11// StmtNodes.td, and TypeNodes.td.12//13//===----------------------------------------------------------------------===//14 15#include "ASTTableGen.h"16#include "llvm/TableGen/Error.h"17#include "llvm/TableGen/Record.h"18 19using namespace llvm;20using namespace clang;21using namespace clang::tblgen;22 23StringRef clang::tblgen::HasProperties::getName() const {24  if (auto node = getAs<ASTNode>()) {25    return node.getName();26  } else if (auto typeCase = getAs<TypeCase>()) {27    return typeCase.getCaseName();28  } else {29    PrintFatalError(getLoc(), "unexpected node declaring properties");30  }31}32 33static StringRef removeExpectedNodeNameSuffix(const Record *node,34                                              StringRef suffix) {35  StringRef nodeName = node->getName();36  if (!nodeName.ends_with(suffix)) {37    PrintFatalError(node->getLoc(),38                    Twine("name of node doesn't end in ") + suffix);39  }40  return nodeName.drop_back(suffix.size());41}42 43// Decl node names don't end in Decl for historical reasons, and it would44// be somewhat annoying to fix now.  Conveniently, this means the ID matches45// is exactly the node name, and the class name is simply that plus Decl.46std::string clang::tblgen::DeclNode::getClassName() const {47  return (Twine(getName()) + "Decl").str();48}49StringRef clang::tblgen::DeclNode::getId() const {50  return getName();51}52 53// Type nodes are all named ending in Type, just like the corresponding54// C++ class, and the ID just strips this suffix.55StringRef clang::tblgen::TypeNode::getClassName() const {56  return getName();57}58StringRef clang::tblgen::TypeNode::getId() const {59  return removeExpectedNodeNameSuffix(getRecord(), "Type");60}61 62// Stmt nodes are named the same as the C++ class, which has no regular63// naming convention (all the non-expression statements end in Stmt,64// and *many* expressions end in Expr, but there are also several65// core expression classes like IntegerLiteral and BinaryOperator with66// no standard suffix).  The ID adds "Class" for historical reasons.67StringRef clang::tblgen::StmtNode::getClassName() const {68  return getName();69}70std::string clang::tblgen::StmtNode::getId() const {71  return (Twine(getName()) + "Class").str();72}73 74/// Emit a string spelling out the C++ value type.75void PropertyType::emitCXXValueTypeName(bool forRead, raw_ostream &out) const {76  if (!isGenericSpecialization()) {77    if (!forRead && isConstWhenWriting())78      out << "const ";79    out << getCXXTypeName();80  } else if (auto elementType = getArrayElementType()) {81    out << "llvm::ArrayRef<";82    elementType.emitCXXValueTypeName(forRead, out);83    out << ">";84  } else if (auto valueType = getOptionalElementType()) {85    out << "std::optional<";86    valueType.emitCXXValueTypeName(forRead, out);87    out << ">";88  } else {89    //PrintFatalError(getLoc(), "unexpected generic property type");90    abort();91  }92}93 94// A map from a node to each of its child nodes.95using ChildMap = std::multimap<ASTNode, ASTNode>;96 97static void visitASTNodeRecursive(ASTNode node, ASTNode base,98                                  const ChildMap &map,99                                  ASTNodeHierarchyVisitor<ASTNode> visit) {100  visit(node, base);101 102  auto i = map.lower_bound(node), e = map.upper_bound(node);103  for (; i != e; ++i) {104    visitASTNodeRecursive(i->second, node, map, visit);105  }106}107 108static void visitHierarchy(const RecordKeeper &records, StringRef nodeClassName,109                           ASTNodeHierarchyVisitor<ASTNode> visit) {110  // Check for the node class, just as a basic correctness check.111  if (!records.getClass(nodeClassName)) {112    PrintFatalError(Twine("cannot find definition for node class ")113                      + nodeClassName);114  }115 116  // Derive the child map for all nodes in the hierarchy.117  ChildMap hierarchy;118  ASTNode root;119  for (ASTNode node : records.getAllDerivedDefinitions(nodeClassName)) {120    if (auto base = node.getBase())121      hierarchy.insert(std::make_pair(base, node));122    else if (root)123      PrintFatalError(node.getLoc(),124                      "multiple root nodes in " + nodeClassName + " hierarchy");125    else126      root = node;127  }128  if (!root)129    PrintFatalError(Twine("no root node in ") + nodeClassName + " hierarchy");130 131  // Now visit the map recursively, starting at the root node.132  visitASTNodeRecursive(root, ASTNode(), hierarchy, visit);133}134 135void clang::tblgen::visitASTNodeHierarchyImpl(136    const RecordKeeper &records, StringRef nodeClassName,137    ASTNodeHierarchyVisitor<ASTNode> visit) {138  visitHierarchy(records, nodeClassName, visit);139}140