brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.1 KiB · 038fc1d Raw
155 lines · cpp
1//===- RemarkParser.cpp --------------------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8//9// This file provides utility methods used by clients that want to use the10// parser for remark diagnostics in LLVM.11//12//===----------------------------------------------------------------------===//13 14#include "llvm/Remarks/RemarkParser.h"15#include "BitstreamRemarkParser.h"16#include "YAMLRemarkParser.h"17#include "llvm-c/Remarks.h"18#include "llvm/Remarks/RemarkFormat.h"19#include "llvm/Support/CBindingWrapping.h"20#include <optional>21 22using namespace llvm;23using namespace llvm::remarks;24 25char EndOfFileError::ID = 0;26 27ParsedStringTable::ParsedStringTable(StringRef InBuffer) : Buffer(InBuffer) {28  while (!InBuffer.empty()) {29    // Strings are separated by '\0' bytes.30    std::pair<StringRef, StringRef> Split = InBuffer.split('\0');31    // We only store the offset from the beginning of the buffer.32    Offsets.push_back(Split.first.data() - Buffer.data());33    InBuffer = Split.second;34  }35}36 37Expected<StringRef> ParsedStringTable::operator[](size_t Index) const {38  if (Index >= Offsets.size())39    return createStringError(40        std::make_error_code(std::errc::invalid_argument),41        "String with index %u is out of bounds (size = %u).", Index,42        Offsets.size());43 44  size_t Offset = Offsets[Index];45  // If it's the last offset, we can't use the next offset to know the size of46  // the string.47  size_t NextOffset =48      (Index == Offsets.size() - 1) ? Buffer.size() : Offsets[Index + 1];49  return StringRef(Buffer.data() + Offset, NextOffset - Offset - 1);50}51 52Expected<std::unique_ptr<RemarkParser>>53llvm::remarks::createRemarkParser(Format ParserFormat, StringRef Buf) {54  auto DetectedFormat = detectFormat(ParserFormat, Buf);55  if (!DetectedFormat)56    return DetectedFormat.takeError();57 58  switch (*DetectedFormat) {59  case Format::YAML:60    return std::make_unique<YAMLRemarkParser>(Buf);61  case Format::Bitstream:62    return std::make_unique<BitstreamRemarkParser>(Buf);63  case Format::Unknown:64  case Format::Auto:65    break;66  }67  llvm_unreachable("unhandled ParseFormat");68}69 70Expected<std::unique_ptr<RemarkParser>>71llvm::remarks::createRemarkParserFromMeta(72    Format ParserFormat, StringRef Buf,73    std::optional<StringRef> ExternalFilePrependPath) {74  auto DetectedFormat = detectFormat(ParserFormat, Buf);75  if (!DetectedFormat)76    return DetectedFormat.takeError();77 78  switch (*DetectedFormat) {79  case Format::YAML:80    return createYAMLParserFromMeta(Buf, std::move(ExternalFilePrependPath));81  case Format::Bitstream:82    return createBitstreamParserFromMeta(Buf,83                                         std::move(ExternalFilePrependPath));84  case Format::Unknown:85  case Format::Auto:86    break;87  }88  llvm_unreachable("unhandled ParseFormat");89}90 91namespace {92// Wrapper that holds the state needed to interact with the C API.93struct CParser {94  std::unique_ptr<RemarkParser> TheParser;95  std::optional<std::string> Err;96 97  CParser(Format ParserFormat, StringRef Buf)98      : TheParser(cantFail(createRemarkParser(ParserFormat, Buf))) {}99 100  void handleError(Error E) { Err.emplace(toString(std::move(E))); }101  bool hasError() const { return Err.has_value(); }102  const char *getMessage() const { return Err ? Err->c_str() : nullptr; };103};104} // namespace105 106// Create wrappers for C Binding types (see CBindingWrapping.h).107DEFINE_SIMPLE_CONVERSION_FUNCTIONS(CParser, LLVMRemarkParserRef)108 109extern "C" LLVMRemarkParserRef LLVMRemarkParserCreateYAML(const void *Buf,110                                                          uint64_t Size) {111  return wrap(new CParser(Format::YAML,112                          StringRef(static_cast<const char *>(Buf), Size)));113}114 115extern "C" LLVMRemarkParserRef LLVMRemarkParserCreateBitstream(const void *Buf,116                                                               uint64_t Size) {117  return wrap(new CParser(Format::Bitstream,118                          StringRef(static_cast<const char *>(Buf), Size)));119}120 121extern "C" LLVMRemarkEntryRef122LLVMRemarkParserGetNext(LLVMRemarkParserRef Parser) {123  CParser &TheCParser = *unwrap(Parser);124  remarks::RemarkParser &TheParser = *TheCParser.TheParser;125 126  Expected<std::unique_ptr<Remark>> MaybeRemark = TheParser.next();127  if (Error E = MaybeRemark.takeError()) {128    if (E.isA<EndOfFileError>()) {129      consumeError(std::move(E));130      return nullptr;131    }132 133    // Handle the error. Allow it to be checked through HasError and134    // GetErrorMessage.135    TheCParser.handleError(std::move(E));136    return nullptr;137  }138 139  // Valid remark.140  return wrap(MaybeRemark->release());141}142 143extern "C" LLVMBool LLVMRemarkParserHasError(LLVMRemarkParserRef Parser) {144  return unwrap(Parser)->hasError();145}146 147extern "C" const char *148LLVMRemarkParserGetErrorMessage(LLVMRemarkParserRef Parser) {149  return unwrap(Parser)->getMessage();150}151 152extern "C" void LLVMRemarkParserDispose(LLVMRemarkParserRef Parser) {153  delete unwrap(Parser);154}155