MLIR  21.0.0git
TemplatingUtils.h
Go to the documentation of this file.
1 //===- TemplatingUtils.h - Templater for text templates -----------------===//
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 #ifndef MLIR_LIB_TARGET_IRDLTOCPP_TEMPLATINGUTILS_H
10 #define MLIR_LIB_TARGET_IRDLTOCPP_TEMPLATINGUTILS_H
11 
12 #include "llvm/ADT/SmallString.h"
13 #include "llvm/ADT/StringMap.h"
14 #include "llvm/ADT/StringRef.h"
15 #include "llvm/Support/ErrorHandling.h"
16 #include "llvm/Support/raw_ostream.h"
17 #include <variant>
18 
19 namespace mlir::irdl::detail {
20 
21 /// A dictionary stores a mapping of template variable names to their assigned
22 /// string values.
23 using dictionary = llvm::StringMap<llvm::SmallString<8>>;
24 
25 /// Template Code as used by IRDL-to-Cpp.
26 ///
27 /// For efficiency, produces a bytecode representation of an input template.
28 /// - LiteralToken: A contiguous stream of characters to be printed
29 /// - ReplacementToken: A template variable that will be replaced
30 class Template {
31 public:
32  Template(llvm::StringRef str) {
33  bool processingReplacementToken = false;
34  while (!str.empty()) {
35  auto [token, remainder] = str.split("__");
36 
37  if (processingReplacementToken) {
38  assert(!token.empty() && "replacement name cannot be empty");
39  bytecode.emplace_back(ReplacementToken{token});
40  } else {
41  if (!token.empty())
42  bytecode.emplace_back(LiteralToken{token});
43  }
44 
45  processingReplacementToken = !processingReplacementToken;
46  str = remainder;
47  }
48  }
49 
50  /// Render will apply a dictionary to the Template and send the rendered
51  /// result to the specified output stream.
52  void render(llvm::raw_ostream &out, const dictionary &replacements) const {
53  for (auto instruction : bytecode) {
54  if (auto *inst = std::get_if<LiteralToken>(&instruction)) {
55  out << inst->text;
56  continue;
57  }
58 
59  if (auto *inst = std::get_if<ReplacementToken>(&instruction)) {
60  auto replacement = replacements.find(inst->keyName);
61 #ifndef NDEBUG
62  if (replacement == replacements.end()) {
63  llvm::errs() << "Missing template key: " << inst->keyName << "\n";
64  llvm_unreachable("Missing template key");
65  }
66 #endif
67  out << replacement->second;
68  continue;
69  }
70 
71  llvm_unreachable("non-exhaustive bytecode visit");
72  }
73  }
74 
75 private:
76  struct LiteralToken {
77  llvm::StringRef text;
78  };
79 
80  struct ReplacementToken {
81  llvm::StringRef keyName;
82  };
83 
84  std::vector<std::variant<LiteralToken, ReplacementToken>> bytecode;
85 };
86 
87 } // namespace mlir::irdl::detail
88 
89 #endif // MLIR_LIB_TARGET_IRDLTOCPP_TEMPLATINGUTILS_H
Template Code as used by IRDL-to-Cpp.
void render(llvm::raw_ostream &out, const dictionary &replacements) const
Render will apply a dictionary to the Template and send the rendered result to the specified output s...
Template(llvm::StringRef str)
llvm::StringMap< llvm::SmallString< 8 > > dictionary
A dictionary stores a mapping of template variable names to their assigned string values.