| Francis Visoiu Mistrih | 1c4bab3 | 2019-03-05 20:45:17 +0000 | [diff] [blame] | 1 | //===- RemarkParser.cpp --------------------------------------------------===// | 
| Francis Visoiu Mistrih | 2e76cab | 2018-10-10 18:43:42 +0000 | [diff] [blame] | 2 | // | 
| Chandler Carruth | 57b08b0 | 2019-01-19 10:56:40 +0000 | [diff] [blame] | 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 | 
| Francis Visoiu Mistrih | 2e76cab | 2018-10-10 18:43:42 +0000 | [diff] [blame] | 6 | // | 
|  | 7 | //===----------------------------------------------------------------------===// | 
|  | 8 | // | 
|  | 9 | // This file provides utility methods used by clients that want to use the | 
| Francis Visoiu Mistrih | 1c4bab3 | 2019-03-05 20:45:17 +0000 | [diff] [blame] | 10 | // parser for remark diagnostics in LLVM. | 
| Francis Visoiu Mistrih | 2e76cab | 2018-10-10 18:43:42 +0000 | [diff] [blame] | 11 | // | 
|  | 12 | //===----------------------------------------------------------------------===// | 
|  | 13 |  | 
| Francis Visoiu Mistrih | 5a05cc0 | 2019-03-19 21:11:07 +0000 | [diff] [blame] | 14 | #include "llvm/Remarks/RemarkParser.h" | 
|  | 15 | #include "YAMLRemarkParser.h" | 
| Francis Visoiu Mistrih | 1c4bab3 | 2019-03-05 20:45:17 +0000 | [diff] [blame] | 16 | #include "llvm-c/Remarks.h" | 
| Francis Visoiu Mistrih | 2e76cab | 2018-10-10 18:43:42 +0000 | [diff] [blame] | 17 | #include "llvm/ADT/STLExtras.h" | 
| Francis Visoiu Mistrih | 5a05cc0 | 2019-03-19 21:11:07 +0000 | [diff] [blame] | 18 | #include "llvm/Support/CBindingWrapping.h" | 
| Francis Visoiu Mistrih | 2e76cab | 2018-10-10 18:43:42 +0000 | [diff] [blame] | 19 |  | 
|  | 20 | using namespace llvm; | 
| Francis Visoiu Mistrih | 5a05cc0 | 2019-03-19 21:11:07 +0000 | [diff] [blame] | 21 | using namespace llvm::remarks; | 
| Francis Visoiu Mistrih | 2e76cab | 2018-10-10 18:43:42 +0000 | [diff] [blame] | 22 |  | 
| Francis Visoiu Mistrih | 94bad22 | 2019-07-16 15:25:05 +0000 | [diff] [blame^] | 23 | char EndOfFileError::ID = 0; | 
| Francis Visoiu Mistrih | 5a05cc0 | 2019-03-19 21:11:07 +0000 | [diff] [blame] | 24 |  | 
| Francis Visoiu Mistrih | 7fee2b8 | 2019-04-24 00:06:24 +0000 | [diff] [blame] | 25 | ParsedStringTable::ParsedStringTable(StringRef InBuffer) : Buffer(InBuffer) { | 
|  | 26 | while (!InBuffer.empty()) { | 
|  | 27 | // Strings are separated by '\0' bytes. | 
|  | 28 | std::pair<StringRef, StringRef> Split = InBuffer.split('\0'); | 
|  | 29 | // We only store the offset from the beginning of the buffer. | 
|  | 30 | Offsets.push_back(Split.first.data() - Buffer.data()); | 
|  | 31 | InBuffer = Split.second; | 
|  | 32 | } | 
|  | 33 | } | 
|  | 34 |  | 
| Francis Visoiu Mistrih | e6ba313 | 2019-07-04 00:30:58 +0000 | [diff] [blame] | 35 | Expected<StringRef> ParsedStringTable::operator[](size_t Index) const { | 
| Francis Visoiu Mistrih | 7fee2b8 | 2019-04-24 00:06:24 +0000 | [diff] [blame] | 36 | if (Index >= Offsets.size()) | 
|  | 37 | return createStringError( | 
|  | 38 | std::make_error_code(std::errc::invalid_argument), | 
|  | 39 | "String with index %u is out of bounds (size = %u).", Index, | 
|  | 40 | Offsets.size()); | 
|  | 41 |  | 
|  | 42 | size_t Offset = Offsets[Index]; | 
|  | 43 | // If it's the last offset, we can't use the next offset to know the size of | 
|  | 44 | // the string. | 
|  | 45 | size_t NextOffset = | 
|  | 46 | (Index == Offsets.size() - 1) ? Buffer.size() : Offsets[Index + 1]; | 
|  | 47 | return StringRef(Buffer.data() + Offset, NextOffset - Offset - 1); | 
|  | 48 | } | 
|  | 49 |  | 
| Francis Visoiu Mistrih | 94bad22 | 2019-07-16 15:25:05 +0000 | [diff] [blame^] | 50 | Expected<std::unique_ptr<Parser>> | 
|  | 51 | llvm::remarks::createRemarkParser(Format ParserFormat, StringRef Buf, | 
|  | 52 | Optional<const ParsedStringTable *> StrTab) { | 
|  | 53 | switch (ParserFormat) { | 
|  | 54 | case Format::YAML: | 
|  | 55 | return llvm::make_unique<YAMLRemarkParser>(Buf, StrTab); | 
|  | 56 | case Format::Unknown: | 
|  | 57 | return createStringError(std::make_error_code(std::errc::invalid_argument), | 
|  | 58 | "Unknown remark parser format."); | 
|  | 59 | } | 
|  | 60 | } | 
|  | 61 |  | 
|  | 62 | // Wrapper that holds the state needed to interact with the C API. | 
|  | 63 | struct CParser { | 
|  | 64 | std::unique_ptr<Parser> TheParser; | 
|  | 65 | Optional<std::string> Err; | 
|  | 66 |  | 
|  | 67 | CParser(Format ParserFormat, StringRef Buf, | 
|  | 68 | Optional<const ParsedStringTable *> StrTab = None) | 
|  | 69 | : TheParser(cantFail(createRemarkParser(ParserFormat, Buf, StrTab))) {} | 
|  | 70 |  | 
|  | 71 | void handleError(Error E) { Err.emplace(toString(std::move(E))); } | 
|  | 72 | bool hasError() const { return Err.hasValue(); } | 
|  | 73 | const char *getMessage() const { return Err ? Err->c_str() : nullptr; }; | 
|  | 74 | }; | 
|  | 75 |  | 
| Francis Visoiu Mistrih | 5a05cc0 | 2019-03-19 21:11:07 +0000 | [diff] [blame] | 76 | // Create wrappers for C Binding types (see CBindingWrapping.h). | 
| Francis Visoiu Mistrih | 94bad22 | 2019-07-16 15:25:05 +0000 | [diff] [blame^] | 77 | DEFINE_SIMPLE_CONVERSION_FUNCTIONS(CParser, LLVMRemarkParserRef) | 
| Francis Visoiu Mistrih | 5a05cc0 | 2019-03-19 21:11:07 +0000 | [diff] [blame] | 78 |  | 
|  | 79 | extern "C" LLVMRemarkParserRef LLVMRemarkParserCreateYAML(const void *Buf, | 
|  | 80 | uint64_t Size) { | 
| Francis Visoiu Mistrih | 94bad22 | 2019-07-16 15:25:05 +0000 | [diff] [blame^] | 81 | return wrap(new CParser(Format::YAML, | 
|  | 82 | StringRef(static_cast<const char *>(Buf), Size))); | 
| Francis Visoiu Mistrih | 5a05cc0 | 2019-03-19 21:11:07 +0000 | [diff] [blame] | 83 | } | 
|  | 84 |  | 
|  | 85 | extern "C" LLVMRemarkEntryRef | 
|  | 86 | LLVMRemarkParserGetNext(LLVMRemarkParserRef Parser) { | 
| Francis Visoiu Mistrih | 94bad22 | 2019-07-16 15:25:05 +0000 | [diff] [blame^] | 87 | CParser &TheCParser = *unwrap(Parser); | 
|  | 88 | remarks::Parser &TheParser = *TheCParser.TheParser; | 
| Francis Visoiu Mistrih | 5a05cc0 | 2019-03-19 21:11:07 +0000 | [diff] [blame] | 89 |  | 
| Francis Visoiu Mistrih | 94bad22 | 2019-07-16 15:25:05 +0000 | [diff] [blame^] | 90 | Expected<std::unique_ptr<Remark>> MaybeRemark = TheParser.next(); | 
|  | 91 | if (Error E = MaybeRemark.takeError()) { | 
|  | 92 | if (E.isA<EndOfFileError>()) { | 
|  | 93 | consumeError(std::move(E)); | 
|  | 94 | return nullptr; | 
|  | 95 | } | 
|  | 96 |  | 
|  | 97 | // Handle the error. Allow it to be checked through HasError and | 
|  | 98 | // GetErrorMessage. | 
|  | 99 | TheCParser.handleError(std::move(E)); | 
| Francis Visoiu Mistrih | 5a05cc0 | 2019-03-19 21:11:07 +0000 | [diff] [blame] | 100 | return nullptr; | 
|  | 101 | } | 
|  | 102 |  | 
| Francis Visoiu Mistrih | 5a05cc0 | 2019-03-19 21:11:07 +0000 | [diff] [blame] | 103 | // Valid remark. | 
| Francis Visoiu Mistrih | 94bad22 | 2019-07-16 15:25:05 +0000 | [diff] [blame^] | 104 | return wrap(MaybeRemark->release()); | 
| Francis Visoiu Mistrih | 2e76cab | 2018-10-10 18:43:42 +0000 | [diff] [blame] | 105 | } | 
|  | 106 |  | 
| Francis Visoiu Mistrih | 1c4bab3 | 2019-03-05 20:45:17 +0000 | [diff] [blame] | 107 | extern "C" LLVMBool LLVMRemarkParserHasError(LLVMRemarkParserRef Parser) { | 
| Francis Visoiu Mistrih | 94bad22 | 2019-07-16 15:25:05 +0000 | [diff] [blame^] | 108 | return unwrap(Parser)->hasError(); | 
| Francis Visoiu Mistrih | 2e76cab | 2018-10-10 18:43:42 +0000 | [diff] [blame] | 109 | } | 
|  | 110 |  | 
|  | 111 | extern "C" const char * | 
| Francis Visoiu Mistrih | 1c4bab3 | 2019-03-05 20:45:17 +0000 | [diff] [blame] | 112 | LLVMRemarkParserGetErrorMessage(LLVMRemarkParserRef Parser) { | 
| Francis Visoiu Mistrih | 94bad22 | 2019-07-16 15:25:05 +0000 | [diff] [blame^] | 113 | return unwrap(Parser)->getMessage(); | 
| Francis Visoiu Mistrih | 2e76cab | 2018-10-10 18:43:42 +0000 | [diff] [blame] | 114 | } | 
|  | 115 |  | 
| Francis Visoiu Mistrih | 1c4bab3 | 2019-03-05 20:45:17 +0000 | [diff] [blame] | 116 | extern "C" void LLVMRemarkParserDispose(LLVMRemarkParserRef Parser) { | 
| Francis Visoiu Mistrih | 2e76cab | 2018-10-10 18:43:42 +0000 | [diff] [blame] | 117 | delete unwrap(Parser); | 
|  | 118 | } |