My Project
Format.h
Go to the documentation of this file.
1 //===- Format.h - Utilities for String Format -------------------*- C++ -*-===//
2 //
3 // Part of the MLIR 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 file declares utilities for formatting strings. They are specially
10 // tailored to the needs of TableGen'ing op definitions and rewrite rules,
11 // so they are not expected to be used as widely applicable utilities.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef MLIR_TABLEGEN_FORMAT_H_
16 #define MLIR_TABLEGEN_FORMAT_H_
17 
18 #include "mlir/Support/LLVM.h"
19 #include "llvm/ADT/DenseMap.h"
20 #include "llvm/ADT/StringMap.h"
21 #include "llvm/Support/FormatVariadic.h"
22 
23 namespace mlir {
24 namespace tblgen {
25 
37 //
40 class FmtContext {
41 public:
42  // Placeholder kinds
43  enum class PHKind : char {
44  None,
45  Custom, // For custom placeholders
46  Builder, // For the $_builder placeholder
47  Op, // For the $_op placeholder
48  Self, // For the $_self placeholder
49  };
50 
51  FmtContext() = default;
52 
53  // Setter for custom placeholders
54  FmtContext &addSubst(StringRef placeholder, Twine subst);
55 
56  // Setters for builtin placeholders
57  FmtContext &withBuilder(Twine subst);
58  FmtContext &withOp(Twine subst);
59  FmtContext &withSelf(Twine subst);
60 
61  Optional<StringRef> getSubstFor(PHKind placeholder) const;
62  Optional<StringRef> getSubstFor(StringRef placeholder) const;
63 
64  static PHKind getPlaceHolderKind(StringRef str);
65 
66 private:
67  struct PHKindInfo : DenseMapInfo<PHKind> {
68  using CharInfo = DenseMapInfo<char>;
69 
70  static inline PHKind getEmptyKey() {
71  return static_cast<PHKind>(CharInfo::getEmptyKey());
72  }
73  static inline PHKind getTombstoneKey() {
74  return static_cast<PHKind>(CharInfo::getTombstoneKey());
75  }
76  static unsigned getHashValue(const PHKind &val) {
77  return CharInfo::getHashValue(static_cast<char>(val));
78  }
79 
80  static bool isEqual(const PHKind &lhs, const PHKind &rhs) {
81  return lhs == rhs;
82  }
83  };
84 
85  llvm::SmallDenseMap<PHKind, std::string, 4, PHKindInfo> builtinSubstMap;
86  llvm::StringMap<std::string> customSubstMap;
87 };
88 
93  enum class Type { Empty, Literal, PositionalPH, SpecialPH };
94 
95  FmtReplacement() = default;
96  explicit FmtReplacement(StringRef literal)
97  : type(Type::Literal), spec(literal) {}
98  FmtReplacement(StringRef spec, size_t index)
99  : type(Type::PositionalPH), spec(spec), index(index) {}
100  FmtReplacement(StringRef spec, FmtContext::PHKind placeholder)
101  : type(Type::SpecialPH), spec(spec), placeholder(placeholder) {}
102 
103  Type type = Type::Empty;
104  StringRef spec;
105  size_t index = 0;
107 };
108 
110 private:
111  static std::pair<FmtReplacement, StringRef> splitFmtSegment(StringRef fmt);
112  static std::vector<FmtReplacement> parseFormatString(StringRef fmt);
113 
114 protected:
115  // The parameters are stored in a std::tuple, which does not provide runtime
116  // indexing capabilities. In order to enable runtime indexing, we use this
117  // structure to put the parameters into a std::vector. Since the parameters
118  // are not all the same type, we use some type-erasure by wrapping the
119  // parameters in a template class that derives from a non-template superclass.
120  // Essentially, we are converting a std::tuple<Derived<Ts...>> to a
121  // std::vector<Base*>.
122  struct CreateAdapters {
123  template <typename... Ts>
124  std::vector<llvm::detail::format_adapter *> operator()(Ts &... items) {
125  return std::vector<llvm::detail::format_adapter *>{&items...};
126  }
127  };
128 
129  StringRef fmt;
131  std::vector<llvm::detail::format_adapter *> adapters;
132  std::vector<FmtReplacement> replacements;
133 
134 public:
135  FmtObjectBase(StringRef fmt, const FmtContext *ctx, size_t numParams)
136  : fmt(fmt), context(ctx), replacements(parseFormatString(fmt)) {}
137 
138  FmtObjectBase(const FmtObjectBase &that) = delete;
139 
141  : fmt(std::move(that.fmt)), context(that.context),
142  adapters(), // adapters are initialized by FmtObject
143  replacements(std::move(that.replacements)) {}
144 
145  void format(llvm::raw_ostream &s) const;
146 
147  std::string str() const {
148  std::string result;
149  llvm::raw_string_ostream s(result);
150  format(s);
151  return s.str();
152  }
153 
154  template <unsigned N> SmallString<N> sstr() const {
155  SmallString<N> result;
156  llvm::raw_svector_ostream s(result);
157  format(s);
158  return result;
159  }
160 
161  template <unsigned N> operator SmallString<N>() const { return sstr<N>(); }
162 
163  operator std::string() const { return str(); }
164 };
165 
166 template <typename Tuple> class FmtObject : public FmtObjectBase {
167  // Storage for the parameter adapters. Since the base class erases the type
168  // of the parameters, we have to own the storage for the parameters here, and
169  // have the base class store type-erased pointers into this tuple.
170  Tuple parameters;
171 
172 public:
173  FmtObject(StringRef fmt, const FmtContext *ctx, Tuple &&params)
174  : FmtObjectBase(fmt, ctx, std::tuple_size<Tuple>::value),
175  parameters(std::move(params)) {
176  adapters.reserve(std::tuple_size<Tuple>::value);
177  adapters = llvm::apply_tuple(CreateAdapters(), parameters);
178  }
179 
180  FmtObject(FmtObject const &that) = delete;
181 
183  : FmtObjectBase(std::move(that)), parameters(std::move(that.parameters)) {
184  adapters.reserve(that.adapters.size());
185  adapters = llvm::apply_tuple(CreateAdapters(), parameters);
186  }
187 };
188 
225 template <typename... Ts>
226 inline auto tgfmt(StringRef fmt, const FmtContext *ctx, Ts &&... vals)
227  -> FmtObject<decltype(std::make_tuple(
228  llvm::detail::build_format_adapter(std::forward<Ts>(vals))...))> {
229  using ParamTuple = decltype(std::make_tuple(
230  llvm::detail::build_format_adapter(std::forward<Ts>(vals))...));
231  return FmtObject<ParamTuple>(
232  fmt, ctx,
233  std::make_tuple(
234  llvm::detail::build_format_adapter(std::forward<Ts>(vals))...));
235 }
236 
237 } // end namespace tblgen
238 } // end namespace mlir
239 
240 #endif // MLIR_TABLEGEN_FORMAT_H_
Type
Definition: Format.h:93
Definition: InferTypeOpInterface.cpp:20
PHKind
Definition: Format.h:43
const FmtContext * context
Definition: Format.h:130
Definition: LLVM.h:45
Definition: Format.h:92
Definition: LLVM.h:40
static PHKind getPlaceHolderKind(StringRef str)
Definition: Format.cpp:63
StringRef fmt
Definition: Format.h:129
Definition: Format.h:40
FmtContext & addSubst(StringRef placeholder, Twine subst)
Definition: Format.cpp:24
Definition: LLVM.h:36
FmtContext & withSelf(Twine subst)
Definition: Format.cpp:39
FmtObject(FmtObject &&that)
Definition: Format.h:182
std::vector< FmtReplacement > replacements
Definition: Format.h:132
std::string str() const
Definition: Format.h:147
Definition: Format.h:166
Definition: StandardTypes.h:62
SmallString< N > sstr() const
Definition: Format.h:154
std::vector< llvm::detail::format_adapter * > operator()(Ts &... items)
Definition: Format.h:124
std::vector< llvm::detail::format_adapter * > adapters
Definition: Format.h:131
auto tgfmt(StringRef fmt, const FmtContext *ctx, Ts &&... vals) -> FmtObject< decltype(std::make_tuple(llvm::detail::build_format_adapter(std::forward< Ts >(vals))...))>
Definition: Format.h:226
FmtReplacement(StringRef literal)
Definition: Format.h:96
FmtReplacement(StringRef spec, FmtContext::PHKind placeholder)
Definition: Format.h:100
FmtObject(StringRef fmt, const FmtContext *ctx, Tuple &&params)
Definition: Format.h:173
FmtObjectBase(FmtObjectBase &&that)
Definition: Format.h:140
Definition: Format.h:109
FmtContext & withBuilder(Twine subst)
Definition: Format.cpp:29
StringRef spec
Definition: Format.h:104
FmtObjectBase(StringRef fmt, const FmtContext *ctx, size_t numParams)
Definition: Format.h:135
Optional< StringRef > getSubstFor(PHKind placeholder) const
Definition: Format.cpp:45
FmtReplacement(StringRef spec, size_t index)
Definition: Format.h:98
FmtContext & withOp(Twine subst)
Definition: Format.cpp:34