From e76aee7e10ac7ef183d64e4f024a1791d6342ae5 Mon Sep 17 00:00:00 2001 From: Andi Drebes Date: Mon, 18 Oct 2021 11:20:29 +0200 Subject: [PATCH] feat(compiler): Add class StreamStringError with a stream interface for llvm::Error Composing error messages for `llvm::Error` is either done by using `llvm::createStringError()` with an appropriate format string and arguments or by writing to a `std::string`-backed `llvm::raw_string_ostream` and passing the result to `llvm::make_error()` verbatim. The new class `StreamStringError` encapsulates the latter solution into a class with an appropriate stream operator and implicit cast operators to `llvm::Error` and `llvm::Expected`. Example usage: llvm::Error foo(int i, size_t s, ...) { ... if(...) { return StreamStringError() << "Some error message with an integer: " << i << " and a size_t: " << s; } ... } --- compiler/include/zamalang/Support/Error.h | 53 +++++++++++++++++++++++ compiler/lib/Support/CMakeLists.txt | 1 + compiler/lib/Support/Error.cpp | 12 +++++ 3 files changed, 66 insertions(+) create mode 100644 compiler/include/zamalang/Support/Error.h create mode 100644 compiler/lib/Support/Error.cpp diff --git a/compiler/include/zamalang/Support/Error.h b/compiler/include/zamalang/Support/Error.h new file mode 100644 index 000000000..633b0e716 --- /dev/null +++ b/compiler/include/zamalang/Support/Error.h @@ -0,0 +1,53 @@ +#ifndef ZAMALANG_SUPPORT_STRING_ERROR_H +#define ZAMALANG_SUPPORT_STRING_ERROR_H + +#include + +namespace mlir { +namespace zamalang { + +// Internal error class that allows for composing `llvm::Error`s +// similar to `llvm::createStringError()`, but using stream-like +// composition with `operator<<`. +// +// Example: +// +// llvm::Error foo(int i, size_t s, ...) { +// ... +// if(...) { +// return StreamStringError() +// << "Some error message with an integer: " +// << i << " and a size_t: " << s; +// } +// ... +// } +class StreamStringError { +public: + StreamStringError(const llvm::StringRef &s) : buffer(s.str()), os(buffer){}; + StreamStringError() : buffer(""), os(buffer){}; + + template StreamStringError &operator<<(const T &v) { + this->os << v; + return *this; + } + + operator llvm::Error() { + return llvm::make_error(os.str(), + llvm::inconvertibleErrorCode()); + } + + template operator llvm::Expected() { + return this->operator llvm::Error(); + } + +protected: + std::string buffer; + llvm::raw_string_ostream os; +}; + +StreamStringError &operator<<(StreamStringError &se, llvm::Error &err); + +} // namespace zamalang +} // namespace mlir + +#endif diff --git a/compiler/lib/Support/CMakeLists.txt b/compiler/lib/Support/CMakeLists.txt index 82c3077ca..9694989d3 100644 --- a/compiler/lib/Support/CMakeLists.txt +++ b/compiler/lib/Support/CMakeLists.txt @@ -1,4 +1,5 @@ add_mlir_library(ZamalangSupport + Error.cpp Pipeline.cpp Jit.cpp CompilerEngine.cpp diff --git a/compiler/lib/Support/Error.cpp b/compiler/lib/Support/Error.cpp new file mode 100644 index 000000000..32cfa6399 --- /dev/null +++ b/compiler/lib/Support/Error.cpp @@ -0,0 +1,12 @@ +#include + +namespace mlir { +namespace zamalang { +// Specialized `operator<<` for `llvm::Error` that marks the error +// as checked through `std::move` and `llvm::toString` +StreamStringError &operator<<(StreamStringError &se, llvm::Error &err) { + se << llvm::toString(std::move(err)); + return se; +} +} // namespace zamalang +} // namespace mlir