11c4bab3bSFrancis Visoiu Mistrih //===- RemarkParser.cpp --------------------------------------------------===//
21c4bab3bSFrancis Visoiu Mistrih //
31c4bab3bSFrancis Visoiu Mistrih // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
41c4bab3bSFrancis Visoiu Mistrih // See https://llvm.org/LICENSE.txt for license information.
51c4bab3bSFrancis Visoiu Mistrih // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61c4bab3bSFrancis Visoiu Mistrih //
71c4bab3bSFrancis Visoiu Mistrih //===----------------------------------------------------------------------===//
81c4bab3bSFrancis Visoiu Mistrih //
91c4bab3bSFrancis Visoiu Mistrih // This file provides utility methods used by clients that want to use the
101c4bab3bSFrancis Visoiu Mistrih // parser for remark diagnostics in LLVM.
111c4bab3bSFrancis Visoiu Mistrih //
121c4bab3bSFrancis Visoiu Mistrih //===----------------------------------------------------------------------===//
131c4bab3bSFrancis Visoiu Mistrih
145a05cc0eSFrancis Visoiu Mistrih #include "llvm/Remarks/RemarkParser.h"
15a85d9ef1SFrancis Visoiu Mistrih #include "BitstreamRemarkParser.h"
165a05cc0eSFrancis Visoiu Mistrih #include "YAMLRemarkParser.h"
171c4bab3bSFrancis Visoiu Mistrih #include "llvm-c/Remarks.h"
185a05cc0eSFrancis Visoiu Mistrih #include "llvm/Support/CBindingWrapping.h"
191c4bab3bSFrancis Visoiu Mistrih
201c4bab3bSFrancis Visoiu Mistrih using namespace llvm;
215a05cc0eSFrancis Visoiu Mistrih using namespace llvm::remarks;
221c4bab3bSFrancis Visoiu Mistrih
2394bad22cSFrancis Visoiu Mistrih char EndOfFileError::ID = 0;
245a05cc0eSFrancis Visoiu Mistrih
ParsedStringTable(StringRef InBuffer)257fee2b89SFrancis Visoiu Mistrih ParsedStringTable::ParsedStringTable(StringRef InBuffer) : Buffer(InBuffer) {
267fee2b89SFrancis Visoiu Mistrih while (!InBuffer.empty()) {
277fee2b89SFrancis Visoiu Mistrih // Strings are separated by '\0' bytes.
287fee2b89SFrancis Visoiu Mistrih std::pair<StringRef, StringRef> Split = InBuffer.split('\0');
297fee2b89SFrancis Visoiu Mistrih // We only store the offset from the beginning of the buffer.
307fee2b89SFrancis Visoiu Mistrih Offsets.push_back(Split.first.data() - Buffer.data());
317fee2b89SFrancis Visoiu Mistrih InBuffer = Split.second;
327fee2b89SFrancis Visoiu Mistrih }
337fee2b89SFrancis Visoiu Mistrih }
347fee2b89SFrancis Visoiu Mistrih
operator [](size_t Index) const35e6ba313aSFrancis Visoiu Mistrih Expected<StringRef> ParsedStringTable::operator[](size_t Index) const {
367fee2b89SFrancis Visoiu Mistrih if (Index >= Offsets.size())
377fee2b89SFrancis Visoiu Mistrih return createStringError(
387fee2b89SFrancis Visoiu Mistrih std::make_error_code(std::errc::invalid_argument),
397fee2b89SFrancis Visoiu Mistrih "String with index %u is out of bounds (size = %u).", Index,
407fee2b89SFrancis Visoiu Mistrih Offsets.size());
417fee2b89SFrancis Visoiu Mistrih
427fee2b89SFrancis Visoiu Mistrih size_t Offset = Offsets[Index];
437fee2b89SFrancis Visoiu Mistrih // If it's the last offset, we can't use the next offset to know the size of
447fee2b89SFrancis Visoiu Mistrih // the string.
457fee2b89SFrancis Visoiu Mistrih size_t NextOffset =
467fee2b89SFrancis Visoiu Mistrih (Index == Offsets.size() - 1) ? Buffer.size() : Offsets[Index + 1];
477fee2b89SFrancis Visoiu Mistrih return StringRef(Buffer.data() + Offset, NextOffset - Offset - 1);
487fee2b89SFrancis Visoiu Mistrih }
497fee2b89SFrancis Visoiu Mistrih
50ab56cf89SFrancis Visoiu Mistrih Expected<std::unique_ptr<RemarkParser>>
createRemarkParser(Format ParserFormat,StringRef Buf)51c5b5cc45SFrancis Visoiu Mistrih llvm::remarks::createRemarkParser(Format ParserFormat, StringRef Buf) {
5294bad22cSFrancis Visoiu Mistrih switch (ParserFormat) {
5394bad22cSFrancis Visoiu Mistrih case Format::YAML:
540eaee545SJonas Devlieghere return std::make_unique<YAMLRemarkParser>(Buf);
55c5b5cc45SFrancis Visoiu Mistrih case Format::YAMLStrTab:
56c5b5cc45SFrancis Visoiu Mistrih return createStringError(
57c5b5cc45SFrancis Visoiu Mistrih std::make_error_code(std::errc::invalid_argument),
58c5b5cc45SFrancis Visoiu Mistrih "The YAML with string table format requires a parsed string table.");
5984e80979SFrancis Visoiu Mistrih case Format::Bitstream:
60a85d9ef1SFrancis Visoiu Mistrih return std::make_unique<BitstreamRemarkParser>(Buf);
6194bad22cSFrancis Visoiu Mistrih case Format::Unknown:
6294bad22cSFrancis Visoiu Mistrih return createStringError(std::make_error_code(std::errc::invalid_argument),
6394bad22cSFrancis Visoiu Mistrih "Unknown remark parser format.");
6494bad22cSFrancis Visoiu Mistrih }
65509ad30dSHaojian Wu llvm_unreachable("unhandled ParseFormat");
66c5b5cc45SFrancis Visoiu Mistrih }
67c5b5cc45SFrancis Visoiu Mistrih
68ab56cf89SFrancis Visoiu Mistrih Expected<std::unique_ptr<RemarkParser>>
createRemarkParser(Format ParserFormat,StringRef Buf,ParsedStringTable StrTab)69c5b5cc45SFrancis Visoiu Mistrih llvm::remarks::createRemarkParser(Format ParserFormat, StringRef Buf,
704287c95bSFrancis Visoiu Mistrih ParsedStringTable StrTab) {
71c5b5cc45SFrancis Visoiu Mistrih switch (ParserFormat) {
72c5b5cc45SFrancis Visoiu Mistrih case Format::YAML:
73c5b5cc45SFrancis Visoiu Mistrih return createStringError(std::make_error_code(std::errc::invalid_argument),
74c5b5cc45SFrancis Visoiu Mistrih "The YAML format can't be used with a string "
75c5b5cc45SFrancis Visoiu Mistrih "table. Use yaml-strtab instead.");
76c5b5cc45SFrancis Visoiu Mistrih case Format::YAMLStrTab:
770eaee545SJonas Devlieghere return std::make_unique<YAMLStrTabRemarkParser>(Buf, std::move(StrTab));
7884e80979SFrancis Visoiu Mistrih case Format::Bitstream:
79a85d9ef1SFrancis Visoiu Mistrih return std::make_unique<BitstreamRemarkParser>(Buf, std::move(StrTab));
80c5b5cc45SFrancis Visoiu Mistrih case Format::Unknown:
81c5b5cc45SFrancis Visoiu Mistrih return createStringError(std::make_error_code(std::errc::invalid_argument),
82c5b5cc45SFrancis Visoiu Mistrih "Unknown remark parser format.");
83c5b5cc45SFrancis Visoiu Mistrih }
84509ad30dSHaojian Wu llvm_unreachable("unhandled ParseFormat");
8594bad22cSFrancis Visoiu Mistrih }
8694bad22cSFrancis Visoiu Mistrih
8764a5f9e1SFrancis Visoiu Mistrih Expected<std::unique_ptr<RemarkParser>>
createRemarkParserFromMeta(Format ParserFormat,StringRef Buf,Optional<ParsedStringTable> StrTab,Optional<StringRef> ExternalFilePrependPath)88684605ecSFrancis Visoiu Mistrih llvm::remarks::createRemarkParserFromMeta(
89684605ecSFrancis Visoiu Mistrih Format ParserFormat, StringRef Buf, Optional<ParsedStringTable> StrTab,
90684605ecSFrancis Visoiu Mistrih Optional<StringRef> ExternalFilePrependPath) {
9164a5f9e1SFrancis Visoiu Mistrih switch (ParserFormat) {
9264a5f9e1SFrancis Visoiu Mistrih // Depending on the metadata, the format can be either yaml or yaml-strtab,
9364a5f9e1SFrancis Visoiu Mistrih // regardless of the input argument.
9464a5f9e1SFrancis Visoiu Mistrih case Format::YAML:
9564a5f9e1SFrancis Visoiu Mistrih case Format::YAMLStrTab:
96684605ecSFrancis Visoiu Mistrih return createYAMLParserFromMeta(Buf, std::move(StrTab),
97684605ecSFrancis Visoiu Mistrih std::move(ExternalFilePrependPath));
9884e80979SFrancis Visoiu Mistrih case Format::Bitstream:
99684605ecSFrancis Visoiu Mistrih return createBitstreamParserFromMeta(Buf, std::move(StrTab),
100684605ecSFrancis Visoiu Mistrih std::move(ExternalFilePrependPath));
10164a5f9e1SFrancis Visoiu Mistrih case Format::Unknown:
10264a5f9e1SFrancis Visoiu Mistrih return createStringError(std::make_error_code(std::errc::invalid_argument),
10364a5f9e1SFrancis Visoiu Mistrih "Unknown remark parser format.");
10464a5f9e1SFrancis Visoiu Mistrih }
105f5a33836SFrancis Visoiu Mistrih llvm_unreachable("unhandled ParseFormat");
10664a5f9e1SFrancis Visoiu Mistrih }
10764a5f9e1SFrancis Visoiu Mistrih
108dc5f805dSBenjamin Kramer namespace {
10994bad22cSFrancis Visoiu Mistrih // Wrapper that holds the state needed to interact with the C API.
11094bad22cSFrancis Visoiu Mistrih struct CParser {
111ab56cf89SFrancis Visoiu Mistrih std::unique_ptr<RemarkParser> TheParser;
11294bad22cSFrancis Visoiu Mistrih Optional<std::string> Err;
11394bad22cSFrancis Visoiu Mistrih
CParser__anon75aa8d330111::CParser11494bad22cSFrancis Visoiu Mistrih CParser(Format ParserFormat, StringRef Buf,
1154287c95bSFrancis Visoiu Mistrih Optional<ParsedStringTable> StrTab = None)
1164287c95bSFrancis Visoiu Mistrih : TheParser(cantFail(
1174287c95bSFrancis Visoiu Mistrih StrTab ? createRemarkParser(ParserFormat, Buf, std::move(*StrTab))
118c5b5cc45SFrancis Visoiu Mistrih : createRemarkParser(ParserFormat, Buf))) {}
11994bad22cSFrancis Visoiu Mistrih
handleError__anon75aa8d330111::CParser12094bad22cSFrancis Visoiu Mistrih void handleError(Error E) { Err.emplace(toString(std::move(E))); }
hasError__anon75aa8d330111::CParser121*064a08cdSKazu Hirata bool hasError() const { return Err.has_value(); }
getMessage__anon75aa8d330111::CParser12294bad22cSFrancis Visoiu Mistrih const char *getMessage() const { return Err ? Err->c_str() : nullptr; };
12394bad22cSFrancis Visoiu Mistrih };
124dc5f805dSBenjamin Kramer } // namespace
12594bad22cSFrancis Visoiu Mistrih
1265a05cc0eSFrancis Visoiu Mistrih // Create wrappers for C Binding types (see CBindingWrapping.h).
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(CParser,LLVMRemarkParserRef)12794bad22cSFrancis Visoiu Mistrih DEFINE_SIMPLE_CONVERSION_FUNCTIONS(CParser, LLVMRemarkParserRef)
1285a05cc0eSFrancis Visoiu Mistrih
1295a05cc0eSFrancis Visoiu Mistrih extern "C" LLVMRemarkParserRef LLVMRemarkParserCreateYAML(const void *Buf,
1305a05cc0eSFrancis Visoiu Mistrih uint64_t Size) {
13194bad22cSFrancis Visoiu Mistrih return wrap(new CParser(Format::YAML,
13294bad22cSFrancis Visoiu Mistrih StringRef(static_cast<const char *>(Buf), Size)));
1335a05cc0eSFrancis Visoiu Mistrih }
1345a05cc0eSFrancis Visoiu Mistrih
LLVMRemarkParserCreateBitstream(const void * Buf,uint64_t Size)135a85d9ef1SFrancis Visoiu Mistrih extern "C" LLVMRemarkParserRef LLVMRemarkParserCreateBitstream(const void *Buf,
136a85d9ef1SFrancis Visoiu Mistrih uint64_t Size) {
137a85d9ef1SFrancis Visoiu Mistrih return wrap(new CParser(Format::Bitstream,
138a85d9ef1SFrancis Visoiu Mistrih StringRef(static_cast<const char *>(Buf), Size)));
139a85d9ef1SFrancis Visoiu Mistrih }
140a85d9ef1SFrancis Visoiu Mistrih
1415a05cc0eSFrancis Visoiu Mistrih extern "C" LLVMRemarkEntryRef
LLVMRemarkParserGetNext(LLVMRemarkParserRef Parser)1425a05cc0eSFrancis Visoiu Mistrih LLVMRemarkParserGetNext(LLVMRemarkParserRef Parser) {
14394bad22cSFrancis Visoiu Mistrih CParser &TheCParser = *unwrap(Parser);
144ab56cf89SFrancis Visoiu Mistrih remarks::RemarkParser &TheParser = *TheCParser.TheParser;
1455a05cc0eSFrancis Visoiu Mistrih
14694bad22cSFrancis Visoiu Mistrih Expected<std::unique_ptr<Remark>> MaybeRemark = TheParser.next();
14794bad22cSFrancis Visoiu Mistrih if (Error E = MaybeRemark.takeError()) {
14894bad22cSFrancis Visoiu Mistrih if (E.isA<EndOfFileError>()) {
14994bad22cSFrancis Visoiu Mistrih consumeError(std::move(E));
1501c4bab3bSFrancis Visoiu Mistrih return nullptr;
1511c4bab3bSFrancis Visoiu Mistrih }
1521c4bab3bSFrancis Visoiu Mistrih
15394bad22cSFrancis Visoiu Mistrih // Handle the error. Allow it to be checked through HasError and
15494bad22cSFrancis Visoiu Mistrih // GetErrorMessage.
15594bad22cSFrancis Visoiu Mistrih TheCParser.handleError(std::move(E));
1565a05cc0eSFrancis Visoiu Mistrih return nullptr;
15794bad22cSFrancis Visoiu Mistrih }
15894bad22cSFrancis Visoiu Mistrih
1595a05cc0eSFrancis Visoiu Mistrih // Valid remark.
16094bad22cSFrancis Visoiu Mistrih return wrap(MaybeRemark->release());
1615a05cc0eSFrancis Visoiu Mistrih }
1625a05cc0eSFrancis Visoiu Mistrih
LLVMRemarkParserHasError(LLVMRemarkParserRef Parser)1631c4bab3bSFrancis Visoiu Mistrih extern "C" LLVMBool LLVMRemarkParserHasError(LLVMRemarkParserRef Parser) {
16494bad22cSFrancis Visoiu Mistrih return unwrap(Parser)->hasError();
1651c4bab3bSFrancis Visoiu Mistrih }
1661c4bab3bSFrancis Visoiu Mistrih
1671c4bab3bSFrancis Visoiu Mistrih extern "C" const char *
LLVMRemarkParserGetErrorMessage(LLVMRemarkParserRef Parser)1681c4bab3bSFrancis Visoiu Mistrih LLVMRemarkParserGetErrorMessage(LLVMRemarkParserRef Parser) {
16994bad22cSFrancis Visoiu Mistrih return unwrap(Parser)->getMessage();
1701c4bab3bSFrancis Visoiu Mistrih }
1711c4bab3bSFrancis Visoiu Mistrih
LLVMRemarkParserDispose(LLVMRemarkParserRef Parser)1721c4bab3bSFrancis Visoiu Mistrih extern "C" void LLVMRemarkParserDispose(LLVMRemarkParserRef Parser) {
1731c4bab3bSFrancis Visoiu Mistrih delete unwrap(Parser);
1741c4bab3bSFrancis Visoiu Mistrih }
175