ClangASTPropertiesEmitter.cpp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870
  1. //=== ClangASTPropsEmitter.cpp - Generate Clang AST properties --*- 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. //
  9. // This tablegen backend emits code for working with Clang AST properties.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "ASTTableGen.h"
  13. #include "TableGenBackends.h"
  14. #include "llvm/ADT/STLExtras.h"
  15. #include "llvm/ADT/Twine.h"
  16. #include "llvm/TableGen/Error.h"
  17. #include "llvm/TableGen/Record.h"
  18. #include "llvm/TableGen/TableGenBackend.h"
  19. #include <cctype>
  20. #include <map>
  21. #include <optional>
  22. #include <set>
  23. #include <string>
  24. using namespace llvm;
  25. using namespace clang;
  26. using namespace clang::tblgen;
  27. static StringRef getReaderResultType(TypeNode _) { return "QualType"; }
  28. namespace {
  29. struct ReaderWriterInfo {
  30. bool IsReader;
  31. /// The name of the node hierarchy. Not actually sensitive to IsReader,
  32. /// but useful to cache here anyway.
  33. StringRef HierarchyName;
  34. /// The suffix on classes: Reader/Writer
  35. StringRef ClassSuffix;
  36. /// The base name of methods: read/write
  37. StringRef MethodPrefix;
  38. /// The name of the property helper member: R/W
  39. StringRef HelperVariable;
  40. /// The result type of methods on the class.
  41. StringRef ResultType;
  42. template <class NodeClass>
  43. static ReaderWriterInfo forReader() {
  44. return ReaderWriterInfo{
  45. true,
  46. NodeClass::getASTHierarchyName(),
  47. "Reader",
  48. "read",
  49. "R",
  50. getReaderResultType(NodeClass())
  51. };
  52. }
  53. template <class NodeClass>
  54. static ReaderWriterInfo forWriter() {
  55. return ReaderWriterInfo{
  56. false,
  57. NodeClass::getASTHierarchyName(),
  58. "Writer",
  59. "write",
  60. "W",
  61. "void"
  62. };
  63. }
  64. };
  65. struct NodeInfo {
  66. std::vector<Property> Properties;
  67. CreationRule Creator = nullptr;
  68. OverrideRule Override = nullptr;
  69. ReadHelperRule ReadHelper = nullptr;
  70. };
  71. struct CasedTypeInfo {
  72. TypeKindRule KindRule;
  73. std::vector<TypeCase> Cases;
  74. };
  75. class ASTPropsEmitter {
  76. raw_ostream &Out;
  77. RecordKeeper &Records;
  78. std::map<HasProperties, NodeInfo> NodeInfos;
  79. std::vector<PropertyType> AllPropertyTypes;
  80. std::map<PropertyType, CasedTypeInfo> CasedTypeInfos;
  81. public:
  82. ASTPropsEmitter(RecordKeeper &records, raw_ostream &out)
  83. : Out(out), Records(records) {
  84. // Find all the properties.
  85. for (Property property :
  86. records.getAllDerivedDefinitions(PropertyClassName)) {
  87. HasProperties node = property.getClass();
  88. NodeInfos[node].Properties.push_back(property);
  89. }
  90. // Find all the creation rules.
  91. for (CreationRule creationRule :
  92. records.getAllDerivedDefinitions(CreationRuleClassName)) {
  93. HasProperties node = creationRule.getClass();
  94. auto &info = NodeInfos[node];
  95. if (info.Creator) {
  96. PrintFatalError(creationRule.getLoc(),
  97. "multiple creator rules for \"" + node.getName()
  98. + "\"");
  99. }
  100. info.Creator = creationRule;
  101. }
  102. // Find all the override rules.
  103. for (OverrideRule overrideRule :
  104. records.getAllDerivedDefinitions(OverrideRuleClassName)) {
  105. HasProperties node = overrideRule.getClass();
  106. auto &info = NodeInfos[node];
  107. if (info.Override) {
  108. PrintFatalError(overrideRule.getLoc(),
  109. "multiple override rules for \"" + node.getName()
  110. + "\"");
  111. }
  112. info.Override = overrideRule;
  113. }
  114. // Find all the write helper rules.
  115. for (ReadHelperRule helperRule :
  116. records.getAllDerivedDefinitions(ReadHelperRuleClassName)) {
  117. HasProperties node = helperRule.getClass();
  118. auto &info = NodeInfos[node];
  119. if (info.ReadHelper) {
  120. PrintFatalError(helperRule.getLoc(),
  121. "multiple write helper rules for \"" + node.getName()
  122. + "\"");
  123. }
  124. info.ReadHelper = helperRule;
  125. }
  126. // Find all the concrete property types.
  127. for (PropertyType type :
  128. records.getAllDerivedDefinitions(PropertyTypeClassName)) {
  129. // Ignore generic specializations; they're generally not useful when
  130. // emitting basic emitters etc.
  131. if (type.isGenericSpecialization()) continue;
  132. AllPropertyTypes.push_back(type);
  133. }
  134. // Find all the type kind rules.
  135. for (TypeKindRule kindRule :
  136. records.getAllDerivedDefinitions(TypeKindClassName)) {
  137. PropertyType type = kindRule.getParentType();
  138. auto &info = CasedTypeInfos[type];
  139. if (info.KindRule) {
  140. PrintFatalError(kindRule.getLoc(),
  141. "multiple kind rules for \""
  142. + type.getCXXTypeName() + "\"");
  143. }
  144. info.KindRule = kindRule;
  145. }
  146. // Find all the type cases.
  147. for (TypeCase typeCase :
  148. records.getAllDerivedDefinitions(TypeCaseClassName)) {
  149. CasedTypeInfos[typeCase.getParentType()].Cases.push_back(typeCase);
  150. }
  151. Validator(*this).validate();
  152. }
  153. void visitAllProperties(HasProperties derived, const NodeInfo &derivedInfo,
  154. function_ref<void (Property)> visit) {
  155. std::set<StringRef> ignoredProperties;
  156. auto overrideRule = derivedInfo.Override;
  157. if (overrideRule) {
  158. auto list = overrideRule.getIgnoredProperties();
  159. ignoredProperties.insert(list.begin(), list.end());
  160. }
  161. // TODO: we should sort the properties in various ways
  162. // - put arrays at the end to enable abbreviations
  163. // - put conditional properties after properties used in the condition
  164. visitAllNodesWithInfo(derived, derivedInfo,
  165. [&](HasProperties node, const NodeInfo &info) {
  166. for (Property prop : info.Properties) {
  167. if (ignoredProperties.count(prop.getName()))
  168. continue;
  169. visit(prop);
  170. }
  171. });
  172. }
  173. void visitAllNodesWithInfo(HasProperties derivedNode,
  174. const NodeInfo &derivedNodeInfo,
  175. llvm::function_ref<void (HasProperties node,
  176. const NodeInfo &info)>
  177. visit) {
  178. visit(derivedNode, derivedNodeInfo);
  179. // Also walk the bases if appropriate.
  180. if (ASTNode base = derivedNode.getAs<ASTNode>()) {
  181. for (base = base.getBase(); base; base = base.getBase()) {
  182. auto it = NodeInfos.find(base);
  183. // Ignore intermediate nodes that don't add interesting properties.
  184. if (it == NodeInfos.end()) continue;
  185. auto &baseInfo = it->second;
  186. visit(base, baseInfo);
  187. }
  188. }
  189. }
  190. template <class NodeClass>
  191. void emitNodeReaderClass() {
  192. auto info = ReaderWriterInfo::forReader<NodeClass>();
  193. emitNodeReaderWriterClass<NodeClass>(info);
  194. }
  195. template <class NodeClass>
  196. void emitNodeWriterClass() {
  197. auto info = ReaderWriterInfo::forWriter<NodeClass>();
  198. emitNodeReaderWriterClass<NodeClass>(info);
  199. }
  200. template <class NodeClass>
  201. void emitNodeReaderWriterClass(const ReaderWriterInfo &info);
  202. template <class NodeClass>
  203. void emitNodeReaderWriterMethod(NodeClass node,
  204. const ReaderWriterInfo &info);
  205. void emitPropertiedReaderWriterBody(HasProperties node,
  206. const ReaderWriterInfo &info);
  207. void emitReadOfProperty(StringRef readerName, Property property);
  208. void emitReadOfProperty(StringRef readerName, StringRef name,
  209. PropertyType type, StringRef condition = "");
  210. void emitWriteOfProperty(StringRef writerName, Property property);
  211. void emitWriteOfProperty(StringRef writerName, StringRef name,
  212. PropertyType type, StringRef readCode,
  213. StringRef condition = "");
  214. void emitBasicReaderWriterFile(const ReaderWriterInfo &info);
  215. void emitDispatcherTemplate(const ReaderWriterInfo &info);
  216. void emitPackUnpackOptionalTemplate(const ReaderWriterInfo &info);
  217. void emitBasicReaderWriterTemplate(const ReaderWriterInfo &info);
  218. void emitCasedReaderWriterMethodBody(PropertyType type,
  219. const CasedTypeInfo &typeCases,
  220. const ReaderWriterInfo &info);
  221. private:
  222. class Validator {
  223. ASTPropsEmitter &Emitter;
  224. std::set<HasProperties> ValidatedNodes;
  225. public:
  226. Validator(ASTPropsEmitter &emitter) : Emitter(emitter) {}
  227. void validate();
  228. private:
  229. void validateNode(HasProperties node, const NodeInfo &nodeInfo);
  230. void validateType(PropertyType type, WrappedRecord context);
  231. };
  232. };
  233. } // end anonymous namespace
  234. void ASTPropsEmitter::Validator::validate() {
  235. for (auto &entry : Emitter.NodeInfos) {
  236. validateNode(entry.first, entry.second);
  237. }
  238. if (ErrorsPrinted > 0) {
  239. PrintFatalError("property validation failed");
  240. }
  241. }
  242. void ASTPropsEmitter::Validator::validateNode(HasProperties derivedNode,
  243. const NodeInfo &derivedNodeInfo) {
  244. if (!ValidatedNodes.insert(derivedNode).second) return;
  245. // A map from property name to property.
  246. std::map<StringRef, Property> allProperties;
  247. Emitter.visitAllNodesWithInfo(derivedNode, derivedNodeInfo,
  248. [&](HasProperties node,
  249. const NodeInfo &nodeInfo) {
  250. for (Property property : nodeInfo.Properties) {
  251. validateType(property.getType(), property);
  252. auto result = allProperties.insert(
  253. std::make_pair(property.getName(), property));
  254. // Diagnose non-unique properties.
  255. if (!result.second) {
  256. // The existing property is more likely to be associated with a
  257. // derived node, so use it as the error.
  258. Property existingProperty = result.first->second;
  259. PrintError(existingProperty.getLoc(),
  260. "multiple properties named \"" + property.getName()
  261. + "\" in hierarchy of " + derivedNode.getName());
  262. PrintNote(property.getLoc(), "existing property");
  263. }
  264. }
  265. });
  266. }
  267. void ASTPropsEmitter::Validator::validateType(PropertyType type,
  268. WrappedRecord context) {
  269. if (!type.isGenericSpecialization()) {
  270. if (type.getCXXTypeName() == "") {
  271. PrintError(type.getLoc(),
  272. "type is not generic but has no C++ type name");
  273. if (context) PrintNote(context.getLoc(), "type used here");
  274. }
  275. } else if (auto eltType = type.getArrayElementType()) {
  276. validateType(eltType, context);
  277. } else if (auto valueType = type.getOptionalElementType()) {
  278. validateType(valueType, context);
  279. if (valueType.getPackOptionalCode().empty()) {
  280. PrintError(valueType.getLoc(),
  281. "type doesn't provide optional-packing code");
  282. if (context) PrintNote(context.getLoc(), "type used here");
  283. } else if (valueType.getUnpackOptionalCode().empty()) {
  284. PrintError(valueType.getLoc(),
  285. "type doesn't provide optional-unpacking code");
  286. if (context) PrintNote(context.getLoc(), "type used here");
  287. }
  288. } else {
  289. PrintError(type.getLoc(), "unknown generic property type");
  290. if (context) PrintNote(context.getLoc(), "type used here");
  291. }
  292. }
  293. /****************************************************************************/
  294. /**************************** AST READER/WRITERS ****************************/
  295. /****************************************************************************/
  296. template <class NodeClass>
  297. void ASTPropsEmitter::emitNodeReaderWriterClass(const ReaderWriterInfo &info) {
  298. StringRef suffix = info.ClassSuffix;
  299. StringRef var = info.HelperVariable;
  300. // Enter the class declaration.
  301. Out << "template <class Property" << suffix << ">\n"
  302. "class Abstract" << info.HierarchyName << suffix << " {\n"
  303. "public:\n"
  304. " Property" << suffix << " &" << var << ";\n\n";
  305. // Emit the constructor.
  306. Out << " Abstract" << info.HierarchyName << suffix
  307. << "(Property" << suffix << " &" << var << ") : "
  308. << var << "(" << var << ") {}\n\n";
  309. // Emit a method that dispatches on a kind to the appropriate node-specific
  310. // method.
  311. Out << " " << info.ResultType << " " << info.MethodPrefix << "(";
  312. if (info.IsReader)
  313. Out << NodeClass::getASTIdTypeName() << " kind";
  314. else
  315. Out << "const " << info.HierarchyName << " *node";
  316. Out << ") {\n"
  317. " switch (";
  318. if (info.IsReader)
  319. Out << "kind";
  320. else
  321. Out << "node->" << NodeClass::getASTIdAccessorName() << "()";
  322. Out << ") {\n";
  323. visitASTNodeHierarchy<NodeClass>(Records, [&](NodeClass node, NodeClass _) {
  324. if (node.isAbstract()) return;
  325. Out << " case " << info.HierarchyName << "::" << node.getId() << ":\n"
  326. " return " << info.MethodPrefix << node.getClassName() << "(";
  327. if (!info.IsReader)
  328. Out << "static_cast<const " << node.getClassName()
  329. << " *>(node)";
  330. Out << ");\n";
  331. });
  332. Out << " }\n"
  333. " llvm_unreachable(\"bad kind\");\n"
  334. " }\n\n";
  335. // Emit node-specific methods for all the concrete nodes.
  336. visitASTNodeHierarchy<NodeClass>(Records,
  337. [&](NodeClass node, NodeClass base) {
  338. if (node.isAbstract()) return;
  339. emitNodeReaderWriterMethod(node, info);
  340. });
  341. // Finish the class.
  342. Out << "};\n\n";
  343. }
  344. /// Emit a reader method for the given concrete AST node class.
  345. template <class NodeClass>
  346. void ASTPropsEmitter::emitNodeReaderWriterMethod(NodeClass node,
  347. const ReaderWriterInfo &info) {
  348. // Declare and start the method.
  349. Out << " " << info.ResultType << " "
  350. << info.MethodPrefix << node.getClassName() << "(";
  351. if (!info.IsReader)
  352. Out << "const " << node.getClassName() << " *node";
  353. Out << ") {\n";
  354. if (info.IsReader)
  355. Out << " auto &ctx = " << info.HelperVariable << ".getASTContext();\n";
  356. emitPropertiedReaderWriterBody(node, info);
  357. // Finish the method declaration.
  358. Out << " }\n\n";
  359. }
  360. void ASTPropsEmitter::emitPropertiedReaderWriterBody(HasProperties node,
  361. const ReaderWriterInfo &info) {
  362. // Find the information for this node.
  363. auto it = NodeInfos.find(node);
  364. if (it == NodeInfos.end())
  365. PrintFatalError(node.getLoc(),
  366. "no information about how to deserialize \""
  367. + node.getName() + "\"");
  368. auto &nodeInfo = it->second;
  369. StringRef creationCode;
  370. if (info.IsReader) {
  371. // We should have a creation rule.
  372. if (!nodeInfo.Creator)
  373. PrintFatalError(node.getLoc(),
  374. "no " CreationRuleClassName " for \""
  375. + node.getName() + "\"");
  376. creationCode = nodeInfo.Creator.getCreationCode();
  377. }
  378. // Emit the ReadHelper code, if present.
  379. if (!info.IsReader && nodeInfo.ReadHelper) {
  380. Out << " " << nodeInfo.ReadHelper.getHelperCode() << "\n";
  381. }
  382. // Emit code to read all the properties.
  383. visitAllProperties(node, nodeInfo, [&](Property prop) {
  384. // Verify that the creation code refers to this property.
  385. if (info.IsReader && !creationCode.contains(prop.getName()))
  386. PrintFatalError(nodeInfo.Creator.getLoc(),
  387. "creation code for " + node.getName()
  388. + " doesn't refer to property \""
  389. + prop.getName() + "\"");
  390. // Emit code to read or write this property.
  391. if (info.IsReader)
  392. emitReadOfProperty(info.HelperVariable, prop);
  393. else
  394. emitWriteOfProperty(info.HelperVariable, prop);
  395. });
  396. // Emit the final creation code.
  397. if (info.IsReader)
  398. Out << " " << creationCode << "\n";
  399. }
  400. static void emitBasicReaderWriterMethodSuffix(raw_ostream &out,
  401. PropertyType type,
  402. bool isForRead) {
  403. if (!type.isGenericSpecialization()) {
  404. out << type.getAbstractTypeName();
  405. } else if (auto eltType = type.getArrayElementType()) {
  406. out << "Array";
  407. // We only include an explicit template argument for reads so that
  408. // we don't cause spurious const mismatches.
  409. if (isForRead) {
  410. out << "<";
  411. eltType.emitCXXValueTypeName(isForRead, out);
  412. out << ">";
  413. }
  414. } else if (auto valueType = type.getOptionalElementType()) {
  415. out << "Optional";
  416. // We only include an explicit template argument for reads so that
  417. // we don't cause spurious const mismatches.
  418. if (isForRead) {
  419. out << "<";
  420. valueType.emitCXXValueTypeName(isForRead, out);
  421. out << ">";
  422. }
  423. } else {
  424. PrintFatalError(type.getLoc(), "unexpected generic property type");
  425. }
  426. }
  427. /// Emit code to read the given property in a node-reader method.
  428. void ASTPropsEmitter::emitReadOfProperty(StringRef readerName,
  429. Property property) {
  430. emitReadOfProperty(readerName, property.getName(), property.getType(),
  431. property.getCondition());
  432. }
  433. void ASTPropsEmitter::emitReadOfProperty(StringRef readerName,
  434. StringRef name,
  435. PropertyType type,
  436. StringRef condition) {
  437. // Declare all the necessary buffers.
  438. auto bufferTypes = type.getBufferElementTypes();
  439. for (size_t i = 0, e = bufferTypes.size(); i != e; ++i) {
  440. Out << " llvm::SmallVector<";
  441. PropertyType(bufferTypes[i]).emitCXXValueTypeName(/*for read*/ true, Out);
  442. Out << ", 8> " << name << "_buffer_" << i << ";\n";
  443. }
  444. // T prop = R.find("prop").read##ValueType(buffers...);
  445. // We intentionally ignore shouldPassByReference here: we're going to
  446. // get a pr-value back from read(), and we should be able to forward
  447. // that in the creation rule.
  448. Out << " ";
  449. if (!condition.empty())
  450. Out << "std::optional<";
  451. type.emitCXXValueTypeName(true, Out);
  452. if (!condition.empty()) Out << ">";
  453. Out << " " << name;
  454. if (condition.empty()) {
  455. Out << " = ";
  456. } else {
  457. Out << ";\n"
  458. " if (" << condition << ") {\n"
  459. " " << name << ".emplace(";
  460. }
  461. Out << readerName << ".find(\"" << name << "\")."
  462. << (type.isGenericSpecialization() ? "template " : "") << "read";
  463. emitBasicReaderWriterMethodSuffix(Out, type, /*for read*/ true);
  464. Out << "(";
  465. for (size_t i = 0, e = bufferTypes.size(); i != e; ++i) {
  466. Out << (i > 0 ? ", " : "") << name << "_buffer_" << i;
  467. }
  468. Out << ")";
  469. if (condition.empty()) {
  470. Out << ";\n";
  471. } else {
  472. Out << ");\n"
  473. " }\n";
  474. }
  475. }
  476. /// Emit code to write the given property in a node-writer method.
  477. void ASTPropsEmitter::emitWriteOfProperty(StringRef writerName,
  478. Property property) {
  479. emitWriteOfProperty(writerName, property.getName(), property.getType(),
  480. property.getReadCode(), property.getCondition());
  481. }
  482. void ASTPropsEmitter::emitWriteOfProperty(StringRef writerName,
  483. StringRef name,
  484. PropertyType type,
  485. StringRef readCode,
  486. StringRef condition) {
  487. if (!condition.empty()) {
  488. Out << " if (" << condition << ") {\n";
  489. }
  490. // Focus down to the property:
  491. // T prop = <READ>;
  492. // W.find("prop").write##ValueType(prop);
  493. Out << " ";
  494. type.emitCXXValueTypeName(false, Out);
  495. Out << " " << name << " = (" << readCode << ");\n"
  496. " " << writerName << ".find(\"" << name << "\").write";
  497. emitBasicReaderWriterMethodSuffix(Out, type, /*for read*/ false);
  498. Out << "(" << name << ");\n";
  499. if (!condition.empty()) {
  500. Out << " }\n";
  501. }
  502. }
  503. /// Emit an .inc file that defines the AbstractFooReader class
  504. /// for the given AST class hierarchy.
  505. template <class NodeClass>
  506. static void emitASTReader(RecordKeeper &records, raw_ostream &out,
  507. StringRef description) {
  508. emitSourceFileHeader(description, out);
  509. ASTPropsEmitter(records, out).emitNodeReaderClass<NodeClass>();
  510. }
  511. void clang::EmitClangTypeReader(RecordKeeper &records, raw_ostream &out) {
  512. emitASTReader<TypeNode>(records, out, "A CRTP reader for Clang Type nodes");
  513. }
  514. /// Emit an .inc file that defines the AbstractFooWriter class
  515. /// for the given AST class hierarchy.
  516. template <class NodeClass>
  517. static void emitASTWriter(RecordKeeper &records, raw_ostream &out,
  518. StringRef description) {
  519. emitSourceFileHeader(description, out);
  520. ASTPropsEmitter(records, out).emitNodeWriterClass<NodeClass>();
  521. }
  522. void clang::EmitClangTypeWriter(RecordKeeper &records, raw_ostream &out) {
  523. emitASTWriter<TypeNode>(records, out, "A CRTP writer for Clang Type nodes");
  524. }
  525. /****************************************************************************/
  526. /*************************** BASIC READER/WRITERS ***************************/
  527. /****************************************************************************/
  528. void
  529. ASTPropsEmitter::emitDispatcherTemplate(const ReaderWriterInfo &info) {
  530. // Declare the {Read,Write}Dispatcher template.
  531. StringRef dispatcherPrefix = (info.IsReader ? "Read" : "Write");
  532. Out << "template <class ValueType>\n"
  533. "struct " << dispatcherPrefix << "Dispatcher;\n";
  534. // Declare a specific specialization of the dispatcher template.
  535. auto declareSpecialization =
  536. [&](StringRef specializationParameters,
  537. const Twine &cxxTypeName,
  538. StringRef methodSuffix) {
  539. StringRef var = info.HelperVariable;
  540. Out << "template " << specializationParameters << "\n"
  541. "struct " << dispatcherPrefix << "Dispatcher<"
  542. << cxxTypeName << "> {\n";
  543. Out << " template <class Basic" << info.ClassSuffix << ", class... Args>\n"
  544. " static " << (info.IsReader ? cxxTypeName : "void") << " "
  545. << info.MethodPrefix
  546. << "(Basic" << info.ClassSuffix << " &" << var
  547. << ", Args &&... args) {\n"
  548. " return " << var << "."
  549. << info.MethodPrefix << methodSuffix
  550. << "(std::forward<Args>(args)...);\n"
  551. " }\n"
  552. "};\n";
  553. };
  554. // Declare explicit specializations for each of the concrete types.
  555. for (PropertyType type : AllPropertyTypes) {
  556. declareSpecialization("<>",
  557. type.getCXXTypeName(),
  558. type.getAbstractTypeName());
  559. // Also declare a specialization for the const type when appropriate.
  560. if (!info.IsReader && type.isConstWhenWriting()) {
  561. declareSpecialization("<>",
  562. "const " + type.getCXXTypeName(),
  563. type.getAbstractTypeName());
  564. }
  565. }
  566. // Declare partial specializations for ArrayRef and Optional.
  567. declareSpecialization("<class T>",
  568. "llvm::ArrayRef<T>",
  569. "Array");
  570. declareSpecialization("<class T>", "std::optional<T>", "Optional");
  571. Out << "\n";
  572. }
  573. void
  574. ASTPropsEmitter::emitPackUnpackOptionalTemplate(const ReaderWriterInfo &info) {
  575. StringRef classPrefix = (info.IsReader ? "Unpack" : "Pack");
  576. StringRef methodName = (info.IsReader ? "unpack" : "pack");
  577. // Declare the {Pack,Unpack}OptionalValue template.
  578. Out << "template <class ValueType>\n"
  579. "struct " << classPrefix << "OptionalValue;\n";
  580. auto declareSpecialization = [&](const Twine &typeName, StringRef code) {
  581. Out << "template <>\n"
  582. "struct "
  583. << classPrefix << "OptionalValue<" << typeName
  584. << "> {\n"
  585. " static "
  586. << (info.IsReader ? "std::optional<" : "") << typeName
  587. << (info.IsReader ? "> " : " ") << methodName << "("
  588. << (info.IsReader ? "" : "std::optional<") << typeName
  589. << (info.IsReader ? "" : ">")
  590. << " value) {\n"
  591. " return "
  592. << code
  593. << ";\n"
  594. " }\n"
  595. "};\n";
  596. };
  597. for (PropertyType type : AllPropertyTypes) {
  598. StringRef code = (info.IsReader ? type.getUnpackOptionalCode()
  599. : type.getPackOptionalCode());
  600. if (code.empty()) continue;
  601. StringRef typeName = type.getCXXTypeName();
  602. declareSpecialization(typeName, code);
  603. if (type.isConstWhenWriting() && !info.IsReader)
  604. declareSpecialization("const " + typeName, code);
  605. }
  606. Out << "\n";
  607. }
  608. void
  609. ASTPropsEmitter::emitBasicReaderWriterTemplate(const ReaderWriterInfo &info) {
  610. // Emit the Basic{Reader,Writer}Base template.
  611. Out << "template <class Impl>\n"
  612. "class Basic" << info.ClassSuffix << "Base {\n";
  613. Out << " ASTContext &C;\n";
  614. Out << "protected:\n"
  615. " Basic"
  616. << info.ClassSuffix << "Base" << ("(ASTContext &ctx) : C(ctx)")
  617. << " {}\n"
  618. "public:\n";
  619. Out << " ASTContext &getASTContext() { return C; }\n";
  620. Out << " Impl &asImpl() { return static_cast<Impl&>(*this); }\n";
  621. auto enterReaderWriterMethod = [&](StringRef cxxTypeName,
  622. StringRef abstractTypeName,
  623. bool shouldPassByReference,
  624. bool constWhenWriting,
  625. StringRef paramName) {
  626. Out << " " << (info.IsReader ? cxxTypeName : "void")
  627. << " " << info.MethodPrefix << abstractTypeName << "(";
  628. if (!info.IsReader)
  629. Out << (shouldPassByReference || constWhenWriting ? "const " : "")
  630. << cxxTypeName
  631. << (shouldPassByReference ? " &" : "") << " " << paramName;
  632. Out << ") {\n";
  633. };
  634. // Emit {read,write}ValueType methods for all the enum and subclass types
  635. // that default to using the integer/base-class implementations.
  636. for (PropertyType type : AllPropertyTypes) {
  637. auto enterMethod = [&](StringRef paramName) {
  638. enterReaderWriterMethod(type.getCXXTypeName(),
  639. type.getAbstractTypeName(),
  640. type.shouldPassByReference(),
  641. type.isConstWhenWriting(),
  642. paramName);
  643. };
  644. auto exitMethod = [&] {
  645. Out << " }\n";
  646. };
  647. // Handled cased types.
  648. auto casedIter = CasedTypeInfos.find(type);
  649. if (casedIter != CasedTypeInfos.end()) {
  650. enterMethod("node");
  651. emitCasedReaderWriterMethodBody(type, casedIter->second, info);
  652. exitMethod();
  653. } else if (type.isEnum()) {
  654. enterMethod("value");
  655. if (info.IsReader)
  656. Out << " return asImpl().template readEnum<"
  657. << type.getCXXTypeName() << ">();\n";
  658. else
  659. Out << " asImpl().writeEnum(value);\n";
  660. exitMethod();
  661. } else if (PropertyType superclass = type.getSuperclassType()) {
  662. enterMethod("value");
  663. if (info.IsReader)
  664. Out << " return cast_or_null<" << type.getSubclassClassName()
  665. << ">(asImpl().read"
  666. << superclass.getAbstractTypeName()
  667. << "());\n";
  668. else
  669. Out << " asImpl().write" << superclass.getAbstractTypeName()
  670. << "(value);\n";
  671. exitMethod();
  672. } else {
  673. // The other types can't be handled as trivially.
  674. }
  675. }
  676. Out << "};\n\n";
  677. }
  678. void ASTPropsEmitter::emitCasedReaderWriterMethodBody(PropertyType type,
  679. const CasedTypeInfo &typeCases,
  680. const ReaderWriterInfo &info) {
  681. if (typeCases.Cases.empty()) {
  682. assert(typeCases.KindRule);
  683. PrintFatalError(typeCases.KindRule.getLoc(),
  684. "no cases found for \"" + type.getCXXTypeName() + "\"");
  685. }
  686. if (!typeCases.KindRule) {
  687. assert(!typeCases.Cases.empty());
  688. PrintFatalError(typeCases.Cases.front().getLoc(),
  689. "no kind rule for \"" + type.getCXXTypeName() + "\"");
  690. }
  691. auto var = info.HelperVariable;
  692. std::string subvar = ("sub" + var).str();
  693. // Bind `ctx` for readers.
  694. if (info.IsReader)
  695. Out << " auto &ctx = asImpl().getASTContext();\n";
  696. // Start an object.
  697. Out << " auto &&" << subvar << " = asImpl()."
  698. << info.MethodPrefix << "Object();\n";
  699. // Read/write the kind property;
  700. TypeKindRule kindRule = typeCases.KindRule;
  701. StringRef kindProperty = kindRule.getKindPropertyName();
  702. PropertyType kindType = kindRule.getKindType();
  703. if (info.IsReader) {
  704. emitReadOfProperty(subvar, kindProperty, kindType);
  705. } else {
  706. // Write the property. Note that this will implicitly read the
  707. // kind into a local variable with the right name.
  708. emitWriteOfProperty(subvar, kindProperty, kindType,
  709. kindRule.getReadCode());
  710. }
  711. // Prepare a ReaderWriterInfo with a helper variable that will use
  712. // the sub-reader/writer.
  713. ReaderWriterInfo subInfo = info;
  714. subInfo.HelperVariable = subvar;
  715. // Switch on the kind.
  716. Out << " switch (" << kindProperty << ") {\n";
  717. for (TypeCase typeCase : typeCases.Cases) {
  718. Out << " case " << type.getCXXTypeName() << "::"
  719. << typeCase.getCaseName() << ": {\n";
  720. emitPropertiedReaderWriterBody(typeCase, subInfo);
  721. if (!info.IsReader)
  722. Out << " return;\n";
  723. Out << " }\n\n";
  724. }
  725. Out << " }\n"
  726. " llvm_unreachable(\"bad " << kindType.getCXXTypeName()
  727. << "\");\n";
  728. }
  729. void ASTPropsEmitter::emitBasicReaderWriterFile(const ReaderWriterInfo &info) {
  730. emitDispatcherTemplate(info);
  731. emitPackUnpackOptionalTemplate(info);
  732. emitBasicReaderWriterTemplate(info);
  733. }
  734. /// Emit an .inc file that defines some helper classes for reading
  735. /// basic values.
  736. void clang::EmitClangBasicReader(RecordKeeper &records, raw_ostream &out) {
  737. emitSourceFileHeader("Helper classes for BasicReaders", out);
  738. // Use any property, we won't be using those properties.
  739. auto info = ReaderWriterInfo::forReader<TypeNode>();
  740. ASTPropsEmitter(records, out).emitBasicReaderWriterFile(info);
  741. }
  742. /// Emit an .inc file that defines some helper classes for writing
  743. /// basic values.
  744. void clang::EmitClangBasicWriter(RecordKeeper &records, raw_ostream &out) {
  745. emitSourceFileHeader("Helper classes for BasicWriters", out);
  746. // Use any property, we won't be using those properties.
  747. auto info = ReaderWriterInfo::forWriter<TypeNode>();
  748. ASTPropsEmitter(records, out).emitBasicReaderWriterFile(info);
  749. }