blob: 30de40dd54a09614df6a675b2d7adc1ce3bcf2d4 [file] [log] [blame]
Francis Visoiu Mistrih1c4bab32019-03-05 20:45:17 +00001//===- RemarkParser.cpp --------------------------------------------------===//
Francis Visoiu Mistrih2e76cab2018-10-10 18:43:42 +00002//
Chandler Carruth57b08b02019-01-19 10:56:40 +00003// 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
Francis Visoiu Mistrih2e76cab2018-10-10 18:43:42 +00006//
7//===----------------------------------------------------------------------===//
8//
9// This file provides utility methods used by clients that want to use the
Francis Visoiu Mistrih1c4bab32019-03-05 20:45:17 +000010// parser for remark diagnostics in LLVM.
Francis Visoiu Mistrih2e76cab2018-10-10 18:43:42 +000011//
12//===----------------------------------------------------------------------===//
13
Francis Visoiu Mistrih5a05cc02019-03-19 21:11:07 +000014#include "llvm/Remarks/RemarkParser.h"
15#include "YAMLRemarkParser.h"
Francis Visoiu Mistrih1c4bab32019-03-05 20:45:17 +000016#include "llvm-c/Remarks.h"
Francis Visoiu Mistrih2e76cab2018-10-10 18:43:42 +000017#include "llvm/ADT/STLExtras.h"
Francis Visoiu Mistrih5a05cc02019-03-19 21:11:07 +000018#include "llvm/Support/CBindingWrapping.h"
Francis Visoiu Mistrih2e76cab2018-10-10 18:43:42 +000019
20using namespace llvm;
Francis Visoiu Mistrih5a05cc02019-03-19 21:11:07 +000021using namespace llvm::remarks;
Francis Visoiu Mistrih2e76cab2018-10-10 18:43:42 +000022
Francis Visoiu Mistrih5a05cc02019-03-19 21:11:07 +000023Parser::Parser(StringRef Buf) : Impl(llvm::make_unique<YAMLParserImpl>(Buf)) {}
Francis Visoiu Mistrih2e76cab2018-10-10 18:43:42 +000024
Francis Visoiu Mistrih5a05cc02019-03-19 21:11:07 +000025Parser::~Parser() = default;
Francis Visoiu Mistrih2e76cab2018-10-10 18:43:42 +000026
Francis Visoiu Mistrih5a05cc02019-03-19 21:11:07 +000027static Expected<const Remark *> getNextYAML(YAMLParserImpl &Impl) {
28 YAMLRemarkParser &YAMLParser = Impl.YAMLParser;
Francis Visoiu Mistrih2e76cab2018-10-10 18:43:42 +000029 // Check for EOF.
Francis Visoiu Mistrih5a05cc02019-03-19 21:11:07 +000030 if (Impl.YAMLIt == Impl.YAMLParser.Stream.end())
Francis Visoiu Mistrih2e76cab2018-10-10 18:43:42 +000031 return nullptr;
32
Francis Visoiu Mistrih5a05cc02019-03-19 21:11:07 +000033 auto CurrentIt = Impl.YAMLIt;
34
Francis Visoiu Mistrih2e76cab2018-10-10 18:43:42 +000035 // Try to parse an entry.
Francis Visoiu Mistrih5a05cc02019-03-19 21:11:07 +000036 if (Error E = YAMLParser.parseYAMLElement(*CurrentIt)) {
37 // Set the iterator to the end, in case the user calls getNext again.
38 Impl.YAMLIt = Impl.YAMLParser.Stream.end();
39 return std::move(E);
Francis Visoiu Mistrih2e76cab2018-10-10 18:43:42 +000040 }
41
42 // Move on.
Francis Visoiu Mistrih5a05cc02019-03-19 21:11:07 +000043 ++Impl.YAMLIt;
Francis Visoiu Mistrih2e76cab2018-10-10 18:43:42 +000044
45 // Return the just-parsed remark.
Francis Visoiu Mistrih5a05cc02019-03-19 21:11:07 +000046 if (const Optional<YAMLRemarkParser::ParseState> &State = YAMLParser.State)
47 return &State->TheRemark;
48 else
49 return createStringError(std::make_error_code(std::errc::invalid_argument),
50 "unexpected error while parsing.");
51}
52
53Expected<const Remark *> Parser::getNext() const {
54 if (auto *Impl = dyn_cast<YAMLParserImpl>(this->Impl.get()))
55 return getNextYAML(*Impl);
56 llvm_unreachable("Get next called with an unknown parsing implementation.");
57}
58
59// Create wrappers for C Binding types (see CBindingWrapping.h).
60DEFINE_SIMPLE_CONVERSION_FUNCTIONS(remarks::Parser, LLVMRemarkParserRef)
61
62extern "C" LLVMRemarkParserRef LLVMRemarkParserCreateYAML(const void *Buf,
63 uint64_t Size) {
64 return wrap(
65 new remarks::Parser(StringRef(static_cast<const char *>(Buf), Size)));
66}
67
68static void handleYAMLError(remarks::YAMLParserImpl &Impl, Error E) {
69 handleAllErrors(
70 std::move(E),
71 [&](const YAMLParseError &PE) {
72 Impl.YAMLParser.Stream.printError(&PE.getNode(),
73 Twine(PE.getMessage()) + Twine('\n'));
74 },
75 [&](const ErrorInfoBase &EIB) { EIB.log(Impl.YAMLParser.ErrorStream); });
76 Impl.HasErrors = true;
77}
78
79extern "C" LLVMRemarkEntryRef
80LLVMRemarkParserGetNext(LLVMRemarkParserRef Parser) {
81 remarks::Parser &TheParser = *unwrap(Parser);
82
83 Expected<const remarks::Remark *> RemarkOrErr = TheParser.getNext();
84 if (!RemarkOrErr) {
85 // Error during parsing.
86 if (auto *Impl = dyn_cast<remarks::YAMLParserImpl>(TheParser.Impl.get()))
87 handleYAMLError(*Impl, RemarkOrErr.takeError());
88 else
89 llvm_unreachable("unkown parser implementation.");
90 return nullptr;
91 }
92
93 if (*RemarkOrErr == nullptr)
94 return nullptr;
95 // Valid remark.
96 return wrap(*RemarkOrErr);
Francis Visoiu Mistrih2e76cab2018-10-10 18:43:42 +000097}
98
Francis Visoiu Mistrih1c4bab32019-03-05 20:45:17 +000099extern "C" LLVMBool LLVMRemarkParserHasError(LLVMRemarkParserRef Parser) {
Francis Visoiu Mistrih5a05cc02019-03-19 21:11:07 +0000100 if (auto *Impl =
101 dyn_cast<remarks::YAMLParserImpl>(unwrap(Parser)->Impl.get()))
102 return Impl->HasErrors;
103 llvm_unreachable("unkown parser implementation.");
Francis Visoiu Mistrih2e76cab2018-10-10 18:43:42 +0000104}
105
106extern "C" const char *
Francis Visoiu Mistrih1c4bab32019-03-05 20:45:17 +0000107LLVMRemarkParserGetErrorMessage(LLVMRemarkParserRef Parser) {
Francis Visoiu Mistrih5a05cc02019-03-19 21:11:07 +0000108 if (auto *Impl =
109 dyn_cast<remarks::YAMLParserImpl>(unwrap(Parser)->Impl.get()))
110 return Impl->YAMLParser.ErrorStream.str().c_str();
111 llvm_unreachable("unkown parser implementation.");
Francis Visoiu Mistrih2e76cab2018-10-10 18:43:42 +0000112}
113
Francis Visoiu Mistrih1c4bab32019-03-05 20:45:17 +0000114extern "C" void LLVMRemarkParserDispose(LLVMRemarkParserRef Parser) {
Francis Visoiu Mistrih2e76cab2018-10-10 18:43:42 +0000115 delete unwrap(Parser);
116}