ClangASTPropertiesEmitter.cpp 30 KB

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