ASTTableGen.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  1. //=== ASTTableGen.h - Common definitions for AST node tablegen --*- C++ -*-===//
  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. #ifndef CLANG_AST_TABLEGEN_H
  9. #define CLANG_AST_TABLEGEN_H
  10. #include "llvm/TableGen/Record.h"
  11. #include "llvm/ADT/STLExtras.h"
  12. // These are spellings in the tblgen files.
  13. #define HasPropertiesClassName "HasProperties"
  14. // ASTNodes and their common fields. `Base` is actually defined
  15. // in subclasses, but it's still common across the hierarchies.
  16. #define ASTNodeClassName "ASTNode"
  17. #define BaseFieldName "Base"
  18. #define AbstractFieldName "Abstract"
  19. // Comment node hierarchy.
  20. #define CommentNodeClassName "CommentNode"
  21. // Decl node hierarchy.
  22. #define DeclNodeClassName "DeclNode"
  23. #define DeclContextNodeClassName "DeclContext"
  24. // Stmt node hierarchy.
  25. #define StmtNodeClassName "StmtNode"
  26. // Type node hierarchy.
  27. #define TypeNodeClassName "TypeNode"
  28. #define AlwaysDependentClassName "AlwaysDependent"
  29. #define NeverCanonicalClassName "NeverCanonical"
  30. #define NeverCanonicalUnlessDependentClassName "NeverCanonicalUnlessDependent"
  31. #define LeafTypeClassName "LeafType"
  32. // Cases of various non-ASTNode structured types like DeclarationName.
  33. #define TypeKindClassName "PropertyTypeKind"
  34. #define KindTypeFieldName "KindType"
  35. #define KindPropertyNameFieldName "KindPropertyName"
  36. #define TypeCaseClassName "PropertyTypeCase"
  37. // Properties of AST nodes.
  38. #define PropertyClassName "Property"
  39. #define ClassFieldName "Class"
  40. #define NameFieldName "Name"
  41. #define TypeFieldName "Type"
  42. #define ReadFieldName "Read"
  43. // Types of properties.
  44. #define PropertyTypeClassName "PropertyType"
  45. #define CXXTypeNameFieldName "CXXName"
  46. #define PassByReferenceFieldName "PassByReference"
  47. #define ConstWhenWritingFieldName "ConstWhenWriting"
  48. #define ConditionalCodeFieldName "Conditional"
  49. #define PackOptionalCodeFieldName "PackOptional"
  50. #define UnpackOptionalCodeFieldName "UnpackOptional"
  51. #define BufferElementTypesFieldName "BufferElementTypes"
  52. #define ArrayTypeClassName "Array"
  53. #define ArrayElementTypeFieldName "Element"
  54. #define OptionalTypeClassName "Optional"
  55. #define OptionalElementTypeFieldName "Element"
  56. #define SubclassPropertyTypeClassName "SubclassPropertyType"
  57. #define SubclassBaseTypeFieldName "Base"
  58. #define SubclassClassNameFieldName "SubclassName"
  59. #define EnumPropertyTypeClassName "EnumPropertyType"
  60. // Write helper rules.
  61. #define ReadHelperRuleClassName "ReadHelper"
  62. #define HelperCodeFieldName "Code"
  63. // Creation rules.
  64. #define CreationRuleClassName "Creator"
  65. #define CreateFieldName "Create"
  66. // Override rules.
  67. #define OverrideRuleClassName "Override"
  68. #define IgnoredPropertiesFieldName "IgnoredProperties"
  69. namespace clang {
  70. namespace tblgen {
  71. class WrappedRecord {
  72. llvm::Record *Record;
  73. protected:
  74. WrappedRecord(llvm::Record *record = nullptr) : Record(record) {}
  75. llvm::Record *get() const {
  76. assert(Record && "accessing null record");
  77. return Record;
  78. }
  79. public:
  80. llvm::Record *getRecord() const { return Record; }
  81. explicit operator bool() const { return Record != nullptr; }
  82. llvm::ArrayRef<llvm::SMLoc> getLoc() const {
  83. return get()->getLoc();
  84. }
  85. /// Does the node inherit from the given TableGen class?
  86. bool isSubClassOf(llvm::StringRef className) const {
  87. return get()->isSubClassOf(className);
  88. }
  89. template <class NodeClass>
  90. NodeClass getAs() const {
  91. return (isSubClassOf(NodeClass::getTableGenNodeClassName())
  92. ? NodeClass(get()) : NodeClass());
  93. }
  94. friend bool operator<(WrappedRecord lhs, WrappedRecord rhs) {
  95. assert(lhs && rhs && "sorting null nodes");
  96. return lhs.get()->getName() < rhs.get()->getName();
  97. }
  98. friend bool operator>(WrappedRecord lhs, WrappedRecord rhs) {
  99. return rhs < lhs;
  100. }
  101. friend bool operator<=(WrappedRecord lhs, WrappedRecord rhs) {
  102. return !(rhs < lhs);
  103. }
  104. friend bool operator>=(WrappedRecord lhs, WrappedRecord rhs) {
  105. return !(lhs < rhs);
  106. }
  107. friend bool operator==(WrappedRecord lhs, WrappedRecord rhs) {
  108. // This should handle null nodes.
  109. return lhs.getRecord() == rhs.getRecord();
  110. }
  111. friend bool operator!=(WrappedRecord lhs, WrappedRecord rhs) {
  112. return !(lhs == rhs);
  113. }
  114. };
  115. /// Anything in the AST that has properties.
  116. class HasProperties : public WrappedRecord {
  117. public:
  118. static constexpr llvm::StringRef ClassName = HasPropertiesClassName;
  119. HasProperties(llvm::Record *record = nullptr) : WrappedRecord(record) {}
  120. llvm::StringRef getName() const;
  121. static llvm::StringRef getTableGenNodeClassName() {
  122. return HasPropertiesClassName;
  123. }
  124. };
  125. /// An (optional) reference to a TableGen node representing a class
  126. /// in one of Clang's AST hierarchies.
  127. class ASTNode : public HasProperties {
  128. public:
  129. ASTNode(llvm::Record *record = nullptr) : HasProperties(record) {}
  130. llvm::StringRef getName() const {
  131. return get()->getName();
  132. }
  133. /// Return the node for the base, if there is one.
  134. ASTNode getBase() const {
  135. return get()->getValueAsOptionalDef(BaseFieldName);
  136. }
  137. /// Is the corresponding class abstract?
  138. bool isAbstract() const {
  139. return get()->getValueAsBit(AbstractFieldName);
  140. }
  141. static llvm::StringRef getTableGenNodeClassName() {
  142. return ASTNodeClassName;
  143. }
  144. };
  145. class DeclNode : public ASTNode {
  146. public:
  147. DeclNode(llvm::Record *record = nullptr) : ASTNode(record) {}
  148. llvm::StringRef getId() const;
  149. std::string getClassName() const;
  150. DeclNode getBase() const { return DeclNode(ASTNode::getBase().getRecord()); }
  151. static llvm::StringRef getASTHierarchyName() {
  152. return "Decl";
  153. }
  154. static llvm::StringRef getASTIdTypeName() {
  155. return "Decl::Kind";
  156. }
  157. static llvm::StringRef getASTIdAccessorName() {
  158. return "getKind";
  159. }
  160. static llvm::StringRef getTableGenNodeClassName() {
  161. return DeclNodeClassName;
  162. }
  163. };
  164. class TypeNode : public ASTNode {
  165. public:
  166. TypeNode(llvm::Record *record = nullptr) : ASTNode(record) {}
  167. llvm::StringRef getId() const;
  168. llvm::StringRef getClassName() const;
  169. TypeNode getBase() const { return TypeNode(ASTNode::getBase().getRecord()); }
  170. static llvm::StringRef getASTHierarchyName() {
  171. return "Type";
  172. }
  173. static llvm::StringRef getASTIdTypeName() {
  174. return "Type::TypeClass";
  175. }
  176. static llvm::StringRef getASTIdAccessorName() {
  177. return "getTypeClass";
  178. }
  179. static llvm::StringRef getTableGenNodeClassName() {
  180. return TypeNodeClassName;
  181. }
  182. };
  183. class StmtNode : public ASTNode {
  184. public:
  185. StmtNode(llvm::Record *record = nullptr) : ASTNode(record) {}
  186. std::string getId() const;
  187. llvm::StringRef getClassName() const;
  188. StmtNode getBase() const { return StmtNode(ASTNode::getBase().getRecord()); }
  189. static llvm::StringRef getASTHierarchyName() {
  190. return "Stmt";
  191. }
  192. static llvm::StringRef getASTIdTypeName() {
  193. return "Stmt::StmtClass";
  194. }
  195. static llvm::StringRef getASTIdAccessorName() {
  196. return "getStmtClass";
  197. }
  198. static llvm::StringRef getTableGenNodeClassName() {
  199. return StmtNodeClassName;
  200. }
  201. };
  202. /// The type of a property.
  203. class PropertyType : public WrappedRecord {
  204. public:
  205. PropertyType(llvm::Record *record = nullptr) : WrappedRecord(record) {}
  206. /// Is this a generic specialization (i.e. `Array<T>` or `Optional<T>`)?
  207. bool isGenericSpecialization() const {
  208. return get()->isAnonymous();
  209. }
  210. /// The abstract type name of the property. Doesn't work for generic
  211. /// specializations.
  212. llvm::StringRef getAbstractTypeName() const {
  213. return get()->getName();
  214. }
  215. /// The C++ type name of the property. Doesn't work for generic
  216. /// specializations.
  217. llvm::StringRef getCXXTypeName() const {
  218. return get()->getValueAsString(CXXTypeNameFieldName);
  219. }
  220. void emitCXXValueTypeName(bool forRead, llvm::raw_ostream &out) const;
  221. /// Whether the C++ type should be passed around by reference.
  222. bool shouldPassByReference() const {
  223. return get()->getValueAsBit(PassByReferenceFieldName);
  224. }
  225. /// Whether the C++ type should have 'const' prepended when working with
  226. /// a value of the type being written.
  227. bool isConstWhenWriting() const {
  228. return get()->getValueAsBit(ConstWhenWritingFieldName);
  229. }
  230. /// If this is `Array<T>`, return `T`; otherwise return null.
  231. PropertyType getArrayElementType() const {
  232. if (isSubClassOf(ArrayTypeClassName))
  233. return get()->getValueAsDef(ArrayElementTypeFieldName);
  234. return nullptr;
  235. }
  236. /// If this is `Optional<T>`, return `T`; otherwise return null.
  237. PropertyType getOptionalElementType() const {
  238. if (isSubClassOf(OptionalTypeClassName))
  239. return get()->getValueAsDef(OptionalElementTypeFieldName);
  240. return nullptr;
  241. }
  242. /// If this is a subclass type, return its superclass type.
  243. PropertyType getSuperclassType() const {
  244. if (isSubClassOf(SubclassPropertyTypeClassName))
  245. return get()->getValueAsDef(SubclassBaseTypeFieldName);
  246. return nullptr;
  247. }
  248. // Given that this is a subclass type, return the C++ name of its
  249. // subclass type. This is just the bare class name, suitable for
  250. // use in `cast<>`.
  251. llvm::StringRef getSubclassClassName() const {
  252. return get()->getValueAsString(SubclassClassNameFieldName);
  253. }
  254. /// Does this represent an enum type?
  255. bool isEnum() const {
  256. return isSubClassOf(EnumPropertyTypeClassName);
  257. }
  258. llvm::StringRef getPackOptionalCode() const {
  259. return get()->getValueAsString(PackOptionalCodeFieldName);
  260. }
  261. llvm::StringRef getUnpackOptionalCode() const {
  262. return get()->getValueAsString(UnpackOptionalCodeFieldName);
  263. }
  264. std::vector<llvm::Record*> getBufferElementTypes() const {
  265. return get()->getValueAsListOfDefs(BufferElementTypesFieldName);
  266. }
  267. static llvm::StringRef getTableGenNodeClassName() {
  268. return PropertyTypeClassName;
  269. }
  270. };
  271. /// A rule for returning the kind of a type.
  272. class TypeKindRule : public WrappedRecord {
  273. public:
  274. TypeKindRule(llvm::Record *record = nullptr) : WrappedRecord(record) {}
  275. /// Return the type to which this applies.
  276. PropertyType getParentType() const {
  277. return get()->getValueAsDef(TypeFieldName);
  278. }
  279. /// Return the type of the kind.
  280. PropertyType getKindType() const {
  281. return get()->getValueAsDef(KindTypeFieldName);
  282. }
  283. /// Return the name to use for the kind property.
  284. llvm::StringRef getKindPropertyName() const {
  285. return get()->getValueAsString(KindPropertyNameFieldName);
  286. }
  287. /// Return the code for reading the kind value.
  288. llvm::StringRef getReadCode() const {
  289. return get()->getValueAsString(ReadFieldName);
  290. }
  291. static llvm::StringRef getTableGenNodeClassName() {
  292. return TypeKindClassName;
  293. }
  294. };
  295. /// An implementation case of a property type.
  296. class TypeCase : public HasProperties {
  297. public:
  298. TypeCase(llvm::Record *record = nullptr) : HasProperties(record) {}
  299. /// Return the name of this case.
  300. llvm::StringRef getCaseName() const {
  301. return get()->getValueAsString(NameFieldName);
  302. }
  303. /// Return the type of which this is a case.
  304. PropertyType getParentType() const {
  305. return get()->getValueAsDef(TypeFieldName);
  306. }
  307. static llvm::StringRef getTableGenNodeClassName() {
  308. return TypeCaseClassName;
  309. }
  310. };
  311. /// A property of an AST node.
  312. class Property : public WrappedRecord {
  313. public:
  314. Property(llvm::Record *record = nullptr) : WrappedRecord(record) {}
  315. /// Return the name of this property.
  316. llvm::StringRef getName() const {
  317. return get()->getValueAsString(NameFieldName);
  318. }
  319. /// Return the type of this property.
  320. PropertyType getType() const {
  321. return get()->getValueAsDef(TypeFieldName);
  322. }
  323. /// Return the class of which this is a property.
  324. HasProperties getClass() const {
  325. return get()->getValueAsDef(ClassFieldName);
  326. }
  327. /// Return the code for reading this property.
  328. llvm::StringRef getReadCode() const {
  329. return get()->getValueAsString(ReadFieldName);
  330. }
  331. /// Return the code for determining whether to add this property.
  332. llvm::StringRef getCondition() const {
  333. return get()->getValueAsString(ConditionalCodeFieldName);
  334. }
  335. static llvm::StringRef getTableGenNodeClassName() {
  336. return PropertyClassName;
  337. }
  338. };
  339. /// A rule for running some helper code for reading properties from
  340. /// a value (which is actually done when writing the value out).
  341. class ReadHelperRule : public WrappedRecord {
  342. public:
  343. ReadHelperRule(llvm::Record *record = nullptr) : WrappedRecord(record) {}
  344. /// Return the class for which this is a creation rule.
  345. /// Should never be abstract.
  346. HasProperties getClass() const {
  347. return get()->getValueAsDef(ClassFieldName);
  348. }
  349. llvm::StringRef getHelperCode() const {
  350. return get()->getValueAsString(HelperCodeFieldName);
  351. }
  352. static llvm::StringRef getTableGenNodeClassName() {
  353. return ReadHelperRuleClassName;
  354. }
  355. };
  356. /// A rule for how to create an AST node from its properties.
  357. class CreationRule : public WrappedRecord {
  358. public:
  359. CreationRule(llvm::Record *record = nullptr) : WrappedRecord(record) {}
  360. /// Return the class for which this is a creation rule.
  361. /// Should never be abstract.
  362. HasProperties getClass() const {
  363. return get()->getValueAsDef(ClassFieldName);
  364. }
  365. llvm::StringRef getCreationCode() const {
  366. return get()->getValueAsString(CreateFieldName);
  367. }
  368. static llvm::StringRef getTableGenNodeClassName() {
  369. return CreationRuleClassName;
  370. }
  371. };
  372. /// A rule which overrides the standard rules for serializing an AST node.
  373. class OverrideRule : public WrappedRecord {
  374. public:
  375. OverrideRule(llvm::Record *record = nullptr) : WrappedRecord(record) {}
  376. /// Return the class for which this is an override rule.
  377. /// Should never be abstract.
  378. HasProperties getClass() const {
  379. return get()->getValueAsDef(ClassFieldName);
  380. }
  381. /// Return a set of properties that are unnecessary when serializing
  382. /// this AST node. Generally this is used for inherited properties
  383. /// that are derived for this subclass.
  384. std::vector<llvm::StringRef> getIgnoredProperties() const {
  385. return get()->getValueAsListOfStrings(IgnoredPropertiesFieldName);
  386. }
  387. static llvm::StringRef getTableGenNodeClassName() {
  388. return OverrideRuleClassName;
  389. }
  390. };
  391. /// A visitor for an AST node hierarchy. Note that `base` can be null for
  392. /// the root class.
  393. template <class NodeClass>
  394. using ASTNodeHierarchyVisitor =
  395. llvm::function_ref<void(NodeClass node, NodeClass base)>;
  396. void visitASTNodeHierarchyImpl(llvm::RecordKeeper &records,
  397. llvm::StringRef nodeClassName,
  398. ASTNodeHierarchyVisitor<ASTNode> visit);
  399. template <class NodeClass>
  400. void visitASTNodeHierarchy(llvm::RecordKeeper &records,
  401. ASTNodeHierarchyVisitor<NodeClass> visit) {
  402. visitASTNodeHierarchyImpl(records, NodeClass::getTableGenNodeClassName(),
  403. [visit](ASTNode node, ASTNode base) {
  404. visit(NodeClass(node.getRecord()),
  405. NodeClass(base.getRecord()));
  406. });
  407. }
  408. } // end namespace clang::tblgen
  409. } // end namespace clang
  410. #endif