Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/utils/TableGen/ASTTableGen.cpp
35231 views
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-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This file defines some helper functions for working with tblegen reocrds
10
// 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/Record.h"
17
#include "llvm/TableGen/Error.h"
18
#include <optional>
19
20
using namespace llvm;
21
using namespace clang;
22
using namespace clang::tblgen;
23
24
llvm::StringRef clang::tblgen::HasProperties::getName() const {
25
if (auto node = getAs<ASTNode>()) {
26
return node.getName();
27
} else if (auto typeCase = getAs<TypeCase>()) {
28
return typeCase.getCaseName();
29
} else {
30
PrintFatalError(getLoc(), "unexpected node declaring properties");
31
}
32
}
33
34
static StringRef removeExpectedNodeNameSuffix(Record *node, 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 would
44
// be somewhat annoying to fix now. Conveniently, this means the ID matches
45
// is exactly the node name, and the class name is simply that plus Decl.
46
std::string clang::tblgen::DeclNode::getClassName() const {
47
return (Twine(getName()) + "Decl").str();
48
}
49
StringRef clang::tblgen::DeclNode::getId() const {
50
return getName();
51
}
52
53
// Type nodes are all named ending in Type, just like the corresponding
54
// C++ class, and the ID just strips this suffix.
55
StringRef clang::tblgen::TypeNode::getClassName() const {
56
return getName();
57
}
58
StringRef 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 regular
63
// naming convention (all the non-expression statements end in Stmt,
64
// and *many* expressions end in Expr, but there are also several
65
// core expression classes like IntegerLiteral and BinaryOperator with
66
// no standard suffix). The ID adds "Class" for historical reasons.
67
StringRef clang::tblgen::StmtNode::getClassName() const {
68
return getName();
69
}
70
std::string clang::tblgen::StmtNode::getId() const {
71
return (Twine(getName()) + "Class").str();
72
}
73
74
/// Emit a string spelling out the C++ value type.
75
void 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.
95
using ChildMap = std::multimap<ASTNode, ASTNode>;
96
97
static 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
108
static void visitHierarchy(RecordKeeper &records,
109
StringRef nodeClassName,
110
ASTNodeHierarchyVisitor<ASTNode> visit) {
111
// Check for the node class, just as a basic correctness check.
112
if (!records.getClass(nodeClassName)) {
113
PrintFatalError(Twine("cannot find definition for node class ")
114
+ nodeClassName);
115
}
116
117
// Find all the nodes in the hierarchy.
118
auto nodes = records.getAllDerivedDefinitions(nodeClassName);
119
120
// Derive the child map.
121
ChildMap hierarchy;
122
ASTNode root;
123
for (ASTNode node : nodes) {
124
if (auto base = node.getBase())
125
hierarchy.insert(std::make_pair(base, node));
126
else if (root)
127
PrintFatalError(node.getLoc(),
128
"multiple root nodes in " + nodeClassName + " hierarchy");
129
else
130
root = node;
131
}
132
if (!root)
133
PrintFatalError(Twine("no root node in ") + nodeClassName + " hierarchy");
134
135
// Now visit the map recursively, starting at the root node.
136
visitASTNodeRecursive(root, ASTNode(), hierarchy, visit);
137
}
138
139
void clang::tblgen::visitASTNodeHierarchyImpl(RecordKeeper &records,
140
StringRef nodeClassName,
141
ASTNodeHierarchyVisitor<ASTNode> visit) {
142
visitHierarchy(records, nodeClassName, visit);
143
}
144
145