1 //===-- YAMLRemarkParser.h - Parser for YAML remarks ------------*- 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 file provides the impementation of the YAML remark parser.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_REMARKS_YAML_REMARK_PARSER_H
14 #define LLVM_REMARKS_YAML_REMARK_PARSER_H
15 
16 #include "llvm/ADT/Optional.h"
17 #include "llvm/ADT/SmallVector.h"
18 #include "llvm/Remarks/Remark.h"
19 #include "llvm/Remarks/RemarkParser.h"
20 #include "llvm/Support/Error.h"
21 #include "llvm/Support/MemoryBuffer.h"
22 #include "llvm/Support/SourceMgr.h"
23 #include "llvm/Support/YAMLParser.h"
24 #include "llvm/Support/YAMLTraits.h"
25 #include "llvm/Support/raw_ostream.h"
26 #include <string>
27 
28 namespace llvm {
29 namespace remarks {
30 
31 class YAMLParseError : public ErrorInfo<YAMLParseError> {
32 public:
33   static char ID;
34 
35   YAMLParseError(StringRef Message, SourceMgr &SM, yaml::Stream &Stream,
36                  yaml::Node &Node);
37 
38   YAMLParseError(StringRef Message) : Message(Message) {}
39 
40   void log(raw_ostream &OS) const override { OS << Message; }
41   std::error_code convertToErrorCode() const override {
42     return inconvertibleErrorCode();
43   }
44 
45 private:
46   std::string Message;
47 };
48 
49 /// Regular YAML to Remark parser.
50 struct YAMLRemarkParser : public RemarkParser {
51   /// The string table used for parsing strings.
52   Optional<ParsedStringTable> StrTab;
53   /// Last error message that can come from the YAML parser diagnostics.
54   /// We need this for catching errors in the constructor.
55   std::string LastErrorMessage;
56   /// Source manager for better error messages.
57   SourceMgr SM;
58   /// Stream for yaml parsing.
59   yaml::Stream Stream;
60   /// Iterator in the YAML stream.
61   yaml::document_iterator YAMLIt;
62   /// If we parse remark metadata in separate mode, we need to open a new file
63   /// and parse that.
64   std::unique_ptr<MemoryBuffer> SeparateBuf;
65 
66   YAMLRemarkParser(StringRef Buf);
67 
68   Expected<std::unique_ptr<Remark>> next() override;
69 
70   static bool classof(const RemarkParser *P) {
71     return P->ParserFormat == Format::YAML;
72   }
73 
74 protected:
75   YAMLRemarkParser(StringRef Buf, Optional<ParsedStringTable> StrTab);
76   /// Create a YAMLParseError error from an existing error generated by the YAML
77   /// parser.
78   /// If there is no error, this returns Success.
79   Error error();
80   /// Create a YAMLParseError error referencing a specific node.
81   Error error(StringRef Message, yaml::Node &Node);
82   /// Parse a YAML remark to a remarks::Remark object.
83   Expected<std::unique_ptr<Remark>> parseRemark(yaml::Document &Remark);
84   /// Parse the type of a remark to an enum type.
85   Expected<Type> parseType(yaml::MappingNode &Node);
86   /// Parse one key to a string.
87   Expected<StringRef> parseKey(yaml::KeyValueNode &Node);
88   /// Parse one value to a string.
89   virtual Expected<StringRef> parseStr(yaml::KeyValueNode &Node);
90   /// Parse one value to an unsigned.
91   Expected<unsigned> parseUnsigned(yaml::KeyValueNode &Node);
92   /// Parse a debug location.
93   Expected<RemarkLocation> parseDebugLoc(yaml::KeyValueNode &Node);
94   /// Parse an argument.
95   Expected<Argument> parseArg(yaml::Node &Node);
96 };
97 
98 /// YAML with a string table to Remark parser.
99 struct YAMLStrTabRemarkParser : public YAMLRemarkParser {
100   YAMLStrTabRemarkParser(StringRef Buf, ParsedStringTable StrTab)
101       : YAMLRemarkParser(Buf, std::move(StrTab)) {}
102 
103   static bool classof(const RemarkParser *P) {
104     return P->ParserFormat == Format::YAMLStrTab;
105   }
106 
107 protected:
108   /// Parse one value to a string.
109   Expected<StringRef> parseStr(yaml::KeyValueNode &Node) override;
110 };
111 
112 Expected<std::unique_ptr<YAMLRemarkParser>>
113 createYAMLParserFromMeta(StringRef Buf,
114                          Optional<ParsedStringTable> StrTab = None,
115                          Optional<StringRef> ExternalFilePrependPath = None);
116 
117 } // end namespace remarks
118 } // end namespace llvm
119 
120 #endif /* LLVM_REMARKS_YAML_REMARK_PARSER_H */
121