Path: blob/main/contrib/llvm-project/llvm/lib/Remarks/RemarkParser.cpp
35262 views
//===- RemarkParser.cpp --------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file provides utility methods used by clients that want to use the9// parser for remark diagnostics in LLVM.10//11//===----------------------------------------------------------------------===//1213#include "llvm/Remarks/RemarkParser.h"14#include "BitstreamRemarkParser.h"15#include "YAMLRemarkParser.h"16#include "llvm-c/Remarks.h"17#include "llvm/Support/CBindingWrapping.h"18#include <optional>1920using namespace llvm;21using namespace llvm::remarks;2223char EndOfFileError::ID = 0;2425ParsedStringTable::ParsedStringTable(StringRef InBuffer) : Buffer(InBuffer) {26while (!InBuffer.empty()) {27// Strings are separated by '\0' bytes.28std::pair<StringRef, StringRef> Split = InBuffer.split('\0');29// We only store the offset from the beginning of the buffer.30Offsets.push_back(Split.first.data() - Buffer.data());31InBuffer = Split.second;32}33}3435Expected<StringRef> ParsedStringTable::operator[](size_t Index) const {36if (Index >= Offsets.size())37return createStringError(38std::make_error_code(std::errc::invalid_argument),39"String with index %u is out of bounds (size = %u).", Index,40Offsets.size());4142size_t Offset = Offsets[Index];43// If it's the last offset, we can't use the next offset to know the size of44// the string.45size_t NextOffset =46(Index == Offsets.size() - 1) ? Buffer.size() : Offsets[Index + 1];47return StringRef(Buffer.data() + Offset, NextOffset - Offset - 1);48}4950Expected<std::unique_ptr<RemarkParser>>51llvm::remarks::createRemarkParser(Format ParserFormat, StringRef Buf) {52switch (ParserFormat) {53case Format::YAML:54return std::make_unique<YAMLRemarkParser>(Buf);55case Format::YAMLStrTab:56return createStringError(57std::make_error_code(std::errc::invalid_argument),58"The YAML with string table format requires a parsed string table.");59case Format::Bitstream:60return std::make_unique<BitstreamRemarkParser>(Buf);61case Format::Unknown:62return createStringError(std::make_error_code(std::errc::invalid_argument),63"Unknown remark parser format.");64}65llvm_unreachable("unhandled ParseFormat");66}6768Expected<std::unique_ptr<RemarkParser>>69llvm::remarks::createRemarkParser(Format ParserFormat, StringRef Buf,70ParsedStringTable StrTab) {71switch (ParserFormat) {72case Format::YAML:73return createStringError(std::make_error_code(std::errc::invalid_argument),74"The YAML format can't be used with a string "75"table. Use yaml-strtab instead.");76case Format::YAMLStrTab:77return std::make_unique<YAMLStrTabRemarkParser>(Buf, std::move(StrTab));78case Format::Bitstream:79return std::make_unique<BitstreamRemarkParser>(Buf, std::move(StrTab));80case Format::Unknown:81return createStringError(std::make_error_code(std::errc::invalid_argument),82"Unknown remark parser format.");83}84llvm_unreachable("unhandled ParseFormat");85}8687Expected<std::unique_ptr<RemarkParser>>88llvm::remarks::createRemarkParserFromMeta(89Format ParserFormat, StringRef Buf, std::optional<ParsedStringTable> StrTab,90std::optional<StringRef> ExternalFilePrependPath) {91switch (ParserFormat) {92// Depending on the metadata, the format can be either yaml or yaml-strtab,93// regardless of the input argument.94case Format::YAML:95case Format::YAMLStrTab:96return createYAMLParserFromMeta(Buf, std::move(StrTab),97std::move(ExternalFilePrependPath));98case Format::Bitstream:99return createBitstreamParserFromMeta(Buf, std::move(StrTab),100std::move(ExternalFilePrependPath));101case Format::Unknown:102return createStringError(std::make_error_code(std::errc::invalid_argument),103"Unknown remark parser format.");104}105llvm_unreachable("unhandled ParseFormat");106}107108namespace {109// Wrapper that holds the state needed to interact with the C API.110struct CParser {111std::unique_ptr<RemarkParser> TheParser;112std::optional<std::string> Err;113114CParser(Format ParserFormat, StringRef Buf,115std::optional<ParsedStringTable> StrTab = std::nullopt)116: TheParser(cantFail(117StrTab ? createRemarkParser(ParserFormat, Buf, std::move(*StrTab))118: createRemarkParser(ParserFormat, Buf))) {}119120void handleError(Error E) { Err.emplace(toString(std::move(E))); }121bool hasError() const { return Err.has_value(); }122const char *getMessage() const { return Err ? Err->c_str() : nullptr; };123};124} // namespace125126// Create wrappers for C Binding types (see CBindingWrapping.h).127DEFINE_SIMPLE_CONVERSION_FUNCTIONS(CParser, LLVMRemarkParserRef)128129extern "C" LLVMRemarkParserRef LLVMRemarkParserCreateYAML(const void *Buf,130uint64_t Size) {131return wrap(new CParser(Format::YAML,132StringRef(static_cast<const char *>(Buf), Size)));133}134135extern "C" LLVMRemarkParserRef LLVMRemarkParserCreateBitstream(const void *Buf,136uint64_t Size) {137return wrap(new CParser(Format::Bitstream,138StringRef(static_cast<const char *>(Buf), Size)));139}140141extern "C" LLVMRemarkEntryRef142LLVMRemarkParserGetNext(LLVMRemarkParserRef Parser) {143CParser &TheCParser = *unwrap(Parser);144remarks::RemarkParser &TheParser = *TheCParser.TheParser;145146Expected<std::unique_ptr<Remark>> MaybeRemark = TheParser.next();147if (Error E = MaybeRemark.takeError()) {148if (E.isA<EndOfFileError>()) {149consumeError(std::move(E));150return nullptr;151}152153// Handle the error. Allow it to be checked through HasError and154// GetErrorMessage.155TheCParser.handleError(std::move(E));156return nullptr;157}158159// Valid remark.160return wrap(MaybeRemark->release());161}162163extern "C" LLVMBool LLVMRemarkParserHasError(LLVMRemarkParserRef Parser) {164return unwrap(Parser)->hasError();165}166167extern "C" const char *168LLVMRemarkParserGetErrorMessage(LLVMRemarkParserRef Parser) {169return unwrap(Parser)->getMessage();170}171172extern "C" void LLVMRemarkParserDispose(LLVMRemarkParserRef Parser) {173delete unwrap(Parser);174}175176177