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