Revert r354244 "[DAGCombiner] Eliminate dead stores to stack."
[llvm-complete.git] / include / llvm / BinaryFormat / MsgPackTypes.h
blobfcb11abd67664bed99e8a54e79e2b13cfdc75a4f
1 //===- MsgPackTypes.h - MsgPack Types ---------------------------*- 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 /// \file
10 /// This is a data structure for representing MessagePack "documents", with
11 /// methods to go to and from MessagePack. The types also specialize YAMLIO
12 /// traits in order to go to and from YAML.
14 //===----------------------------------------------------------------------===//
16 #include "llvm/ADT/Optional.h"
17 #include "llvm/BinaryFormat/MsgPackReader.h"
18 #include "llvm/BinaryFormat/MsgPackWriter.h"
19 #include "llvm/Support/Casting.h"
20 #include "llvm/Support/YAMLTraits.h"
21 #include <vector>
23 #ifndef LLVM_BINARYFORMAT_MSGPACKTYPES_H
24 #define LLVM_BINARYFORMAT_MSGPACKTYPES_H
26 namespace llvm {
27 namespace msgpack {
29 class Node;
31 /// Short-hand for a Node pointer.
32 using NodePtr = std::shared_ptr<Node>;
34 /// Short-hand for an Optional Node pointer.
35 using OptNodePtr = Optional<NodePtr>;
37 /// Abstract base-class which can be any MessagePack type.
38 class Node {
39 public:
40 enum NodeKind {
41 NK_Scalar,
42 NK_Array,
43 NK_Map,
46 private:
47 virtual void anchor() = 0;
48 const NodeKind Kind;
50 static Expected<OptNodePtr> readArray(Reader &MPReader, size_t Length);
51 static Expected<OptNodePtr> readMap(Reader &MPReader, size_t Length);
53 public:
54 NodeKind getKind() const { return Kind; }
56 /// Construct a Node. Used by derived classes to track kind information.
57 Node(NodeKind Kind) : Kind(Kind) {}
59 virtual ~Node() = default;
61 /// Read from a MessagePack reader \p MPReader, returning an error if one is
62 /// encountered, or None if \p MPReader is at the end of stream, or some Node
63 /// pointer if some type is read.
64 static Expected<OptNodePtr> read(Reader &MPReader);
66 /// Write to a MessagePack writer \p MPWriter.
67 virtual void write(Writer &MPWriter) = 0;
70 /// A MessagePack scalar.
71 class ScalarNode : public Node {
72 public:
73 enum ScalarKind {
74 SK_Int,
75 SK_UInt,
76 SK_Nil,
77 SK_Boolean,
78 SK_Float,
79 SK_String,
80 SK_Binary,
83 private:
84 void anchor() override;
86 void destroy();
88 ScalarKind SKind;
90 union {
91 int64_t IntValue;
92 uint64_t UIntValue;
93 bool BoolValue;
94 double FloatValue;
95 std::string StringValue;
98 public:
99 /// Construct an Int ScalarNode.
100 ScalarNode(int64_t IntValue);
101 /// Construct an Int ScalarNode.
102 ScalarNode(int32_t IntValue);
103 /// Construct an UInt ScalarNode.
104 ScalarNode(uint64_t UIntValue);
105 /// Construct an UInt ScalarNode.
106 ScalarNode(uint32_t UIntValue);
107 /// Construct a Nil ScalarNode.
108 ScalarNode();
109 /// Construct a Boolean ScalarNode.
110 ScalarNode(bool BoolValue);
111 /// Construct a Float ScalarNode.
112 ScalarNode(double FloatValue);
113 /// Construct a String ScalarNode.
114 ScalarNode(StringRef StringValue);
115 /// Construct a String ScalarNode.
116 ScalarNode(const char *StringValue);
117 /// Construct a String ScalarNode.
118 ScalarNode(std::string &&StringValue);
119 /// Construct a Binary ScalarNode.
120 ScalarNode(MemoryBufferRef BinaryValue);
122 ~ScalarNode();
124 ScalarNode &operator=(const ScalarNode &RHS) = delete;
125 /// A ScalarNode can only be move assigned.
126 ScalarNode &operator=(ScalarNode &&RHS);
128 /// Change the kind of this ScalarNode, zero initializing it to the new type.
129 void setScalarKind(ScalarKind SKind) {
130 switch (SKind) {
131 case SK_Int:
132 *this = int64_t(0);
133 break;
134 case SK_UInt:
135 *this = uint64_t(0);
136 break;
137 case SK_Boolean:
138 *this = false;
139 break;
140 case SK_Float:
141 *this = 0.0;
142 break;
143 case SK_String:
144 *this = StringRef();
145 break;
146 case SK_Binary:
147 *this = MemoryBufferRef("", "");
148 break;
149 case SK_Nil:
150 *this = ScalarNode();
151 break;
155 /// Get the current kind of ScalarNode.
156 ScalarKind getScalarKind() { return SKind; }
158 /// Get the value of an Int scalar.
160 /// \warning Assumes getScalarKind() == SK_Int
161 int64_t getInt() {
162 assert(SKind == SK_Int);
163 return IntValue;
166 /// Get the value of a UInt scalar.
168 /// \warning Assumes getScalarKind() == SK_UInt
169 uint64_t getUInt() {
170 assert(SKind == SK_UInt);
171 return UIntValue;
174 /// Get the value of an Boolean scalar.
176 /// \warning Assumes getScalarKind() == SK_Boolean
177 bool getBool() {
178 assert(SKind == SK_Boolean);
179 return BoolValue;
182 /// Get the value of an Float scalar.
184 /// \warning Assumes getScalarKind() == SK_Float
185 double getFloat() {
186 assert(SKind == SK_Float);
187 return FloatValue;
190 /// Get the value of a String scalar.
192 /// \warning Assumes getScalarKind() == SK_String
193 StringRef getString() {
194 assert(SKind == SK_String);
195 return StringValue;
198 /// Get the value of a Binary scalar.
200 /// \warning Assumes getScalarKind() == SK_Binary
201 StringRef getBinary() {
202 assert(SKind == SK_Binary);
203 return StringValue;
206 static bool classof(const Node *N) { return N->getKind() == NK_Scalar; }
208 void write(Writer &MPWriter) override;
210 /// Parse a YAML scalar of the current ScalarKind from \p ScalarStr.
212 /// \returns An empty string on success, otherwise an error message.
213 StringRef inputYAML(StringRef ScalarStr);
215 /// Output a YAML scalar of the current ScalarKind into \p OS.
216 void outputYAML(raw_ostream &OS) const;
218 /// Determine which YAML quoting type the current value would need when
219 /// output.
220 yaml::QuotingType mustQuoteYAML(StringRef ScalarStr) const;
222 /// Get the YAML tag for the current ScalarKind.
223 StringRef getYAMLTag() const;
225 /// Flag which affects how the type handles YAML tags when reading and
226 /// writing.
228 /// When false, tags are used when reading and writing. When reading, the tag
229 /// is used to decide the ScalarKind before parsing. When writing, the tag is
230 /// output along with the value.
232 /// When true, tags are ignored when reading and writing. When reading, the
233 /// ScalarKind is always assumed to be String. When writing, the tag is not
234 /// output.
235 bool IgnoreTag = false;
237 static const char *IntTag;
238 static const char *NilTag;
239 static const char *BooleanTag;
240 static const char *FloatTag;
241 static const char *StringTag;
242 static const char *BinaryTag;
245 class ArrayNode : public Node, public std::vector<NodePtr> {
246 void anchor() override;
248 public:
249 ArrayNode() : Node(NK_Array) {}
250 static bool classof(const Node *N) { return N->getKind() == NK_Array; }
252 void write(Writer &MPWriter) override {
253 MPWriter.writeArraySize(this->size());
254 for (auto &N : *this)
255 N->write(MPWriter);
259 class MapNode : public Node, public StringMap<NodePtr> {
260 void anchor() override;
262 public:
263 MapNode() : Node(NK_Map) {}
264 static bool classof(const Node *N) { return N->getKind() == NK_Map; }
266 void write(Writer &MPWriter) override {
267 MPWriter.writeMapSize(this->size());
268 for (auto &N : *this) {
269 MPWriter.write(N.first());
270 N.second->write(MPWriter);
275 } // end namespace msgpack
277 namespace yaml {
279 template <> struct PolymorphicTraits<msgpack::NodePtr> {
280 static NodeKind getKind(const msgpack::NodePtr &N) {
281 if (isa<msgpack::ScalarNode>(*N))
282 return NodeKind::Scalar;
283 if (isa<msgpack::MapNode>(*N))
284 return NodeKind::Map;
285 if (isa<msgpack::ArrayNode>(*N))
286 return NodeKind::Sequence;
287 llvm_unreachable("NodeKind not supported");
289 static msgpack::ScalarNode &getAsScalar(msgpack::NodePtr &N) {
290 if (!N || !isa<msgpack::ScalarNode>(*N))
291 N.reset(new msgpack::ScalarNode());
292 return *cast<msgpack::ScalarNode>(N.get());
294 static msgpack::MapNode &getAsMap(msgpack::NodePtr &N) {
295 if (!N || !isa<msgpack::MapNode>(*N))
296 N.reset(new msgpack::MapNode());
297 return *cast<msgpack::MapNode>(N.get());
299 static msgpack::ArrayNode &getAsSequence(msgpack::NodePtr &N) {
300 if (!N || !isa<msgpack::ArrayNode>(*N))
301 N.reset(new msgpack::ArrayNode());
302 return *cast<msgpack::ArrayNode>(N.get());
306 template <> struct TaggedScalarTraits<msgpack::ScalarNode> {
307 static void output(const msgpack::ScalarNode &S, void *Ctxt,
308 raw_ostream &ScalarOS, raw_ostream &TagOS) {
309 if (!S.IgnoreTag)
310 TagOS << S.getYAMLTag();
311 S.outputYAML(ScalarOS);
314 static StringRef input(StringRef ScalarStr, StringRef Tag, void *Ctxt,
315 msgpack::ScalarNode &S) {
316 if (Tag == msgpack::ScalarNode::IntTag) {
317 S.setScalarKind(msgpack::ScalarNode::SK_UInt);
318 if (S.inputYAML(ScalarStr) == StringRef())
319 return StringRef();
320 S.setScalarKind(msgpack::ScalarNode::SK_Int);
321 return S.inputYAML(ScalarStr);
324 if (S.IgnoreTag || Tag == msgpack::ScalarNode::StringTag ||
325 Tag == "tag:yaml.org,2002:str")
326 S.setScalarKind(msgpack::ScalarNode::SK_String);
327 else if (Tag == msgpack::ScalarNode::NilTag)
328 S.setScalarKind(msgpack::ScalarNode::SK_Nil);
329 else if (Tag == msgpack::ScalarNode::BooleanTag)
330 S.setScalarKind(msgpack::ScalarNode::SK_Boolean);
331 else if (Tag == msgpack::ScalarNode::FloatTag)
332 S.setScalarKind(msgpack::ScalarNode::SK_Float);
333 else if (Tag == msgpack::ScalarNode::StringTag)
334 S.setScalarKind(msgpack::ScalarNode::SK_String);
335 else if (Tag == msgpack::ScalarNode::BinaryTag)
336 S.setScalarKind(msgpack::ScalarNode::SK_Binary);
337 else
338 return "Unsupported messagepack tag";
340 return S.inputYAML(ScalarStr);
343 static QuotingType mustQuote(const msgpack::ScalarNode &S, StringRef Str) {
344 return S.mustQuoteYAML(Str);
348 template <> struct CustomMappingTraits<msgpack::MapNode> {
349 static void inputOne(IO &IO, StringRef Key, msgpack::MapNode &M) {
350 IO.mapRequired(Key.str().c_str(), M[Key]);
352 static void output(IO &IO, msgpack::MapNode &M) {
353 for (auto &N : M)
354 IO.mapRequired(N.getKey().str().c_str(), N.getValue());
358 template <> struct SequenceTraits<msgpack::ArrayNode> {
359 static size_t size(IO &IO, msgpack::ArrayNode &A) { return A.size(); }
360 static msgpack::NodePtr &element(IO &IO, msgpack::ArrayNode &A,
361 size_t Index) {
362 if (Index >= A.size())
363 A.resize(Index + 1);
364 return A[Index];
368 } // end namespace yaml
369 } // end namespace llvm
371 #endif // LLVM_BINARYFORMAT_MSGPACKTYPES_H