LLZK 2.0.0
An open-source IR for Zero Knowledge (ZK) circuits
Loading...
Searching...
No Matches
ErrorHelper.h
Go to the documentation of this file.
1//===-- ErrorHelper.h -------------------------------------------*- C++ -*-===//
2//
3// Part of the LLZK Project, under the Apache License v2.0.
4// See LICENSE.txt for license information.
5// Copyright 2025 Veridise Inc.
6// SPDX-License-Identifier: Apache-2.0
7//
8//===----------------------------------------------------------------------===//
9
10#pragma once
11
12#include <mlir/IR/Diagnostics.h>
13#include <mlir/IR/Operation.h>
14
15#include <llvm/ADT/STLFunctionalExtras.h>
16#include <llvm/ADT/Twine.h>
17#include <llvm/Support/ErrorHandling.h>
18
19#include <variant>
20
21namespace llzk {
22
26class InFlightDiagnosticWrapper {
27private:
30 class DefaultAndFailInFlightDiagnostic : public mlir::InFlightDiagnostic {
31 public:
32 DefaultAndFailInFlightDiagnostic(mlir::InFlightDiagnostic &&base)
33 : mlir::InFlightDiagnostic(std::move(base)) {}
34
35 DefaultAndFailInFlightDiagnostic(DefaultAndFailInFlightDiagnostic &&other) noexcept
36 : mlir::InFlightDiagnostic(std::move(other)) {}
37
38 ~DefaultAndFailInFlightDiagnostic() {
40 report();
41 }
42 }
43
44 void report() {
45 InFlightDiagnostic::report();
46 assert(false);
47 }
48 };
49
50 std::variant<mlir::InFlightDiagnostic, DefaultAndFailInFlightDiagnostic> inner;
51
52 explicit InFlightDiagnosticWrapper(DefaultAndFailInFlightDiagnostic &&diag)
53 : inner(std::move(diag)) {}
54
55public:
57 explicit InFlightDiagnosticWrapper(mlir::InFlightDiagnostic &&diag) : inner(std::move(diag)) {}
58
62 explicit InFlightDiagnosticWrapper(mlir::MLIRContext *ctx)
63 : InFlightDiagnosticWrapper(
64 DefaultAndFailInFlightDiagnostic(mlir::detail::getDefaultDiagnosticEmitFn(ctx)())
65 ) {}
66
70 explicit InFlightDiagnosticWrapper(const mlir::Location &loc)
71 : InFlightDiagnosticWrapper(loc.getContext()) {}
72
74 static InFlightDiagnosticWrapper createSilent(mlir::MLIRContext *ctx) {
75 mlir::InFlightDiagnostic d = mlir::emitRemark(mlir::UnknownLoc::get(ctx));
76 d.abandon();
77 return InFlightDiagnosticWrapper(std::move(d));
78 }
79
81 template <typename Arg> InFlightDiagnosticWrapper &operator<<(Arg &&arg) & {
82 return append(std::forward<Arg>(arg));
83 }
84
85 template <typename Arg> InFlightDiagnosticWrapper &&operator<<(Arg &&arg) && {
86 return std::move(append(std::forward<Arg>(arg)));
87 }
88
90 template <typename... Args> InFlightDiagnosticWrapper &append(Args &&...args) & {
91 std::visit([&](auto &diag) { diag.append(std::forward<Args>(args)...); }, inner);
92 return *this;
93 }
94
95 template <typename... Args> InFlightDiagnosticWrapper &&append(Args &&...args) && {
96 return std::move(append(std::forward<Args>(args)...));
97 }
98
100 mlir::Diagnostic &attachNote(std::optional<mlir::Location> noteLoc = std::nullopt) {
101 return std::visit([&](auto &diag) -> mlir::Diagnostic & {
102 return diag.attachNote(noteLoc);
103 }, inner);
104 }
105
107 mlir::Diagnostic *getUnderlyingDiagnostic() {
108 return std::visit([](auto &diag) -> mlir::Diagnostic * {
109 return diag.getUnderlyingDiagnostic();
110 }, inner);
111 }
112
114 void report() {
115 std::visit([](auto &diag) { diag.report(); }, inner);
116 }
117
119 void abandon() {
120 std::visit([](auto &diag) { diag.abandon(); }, inner);
121 }
122
125 operator mlir::LogicalResult() const {
126 return std::visit([](const auto &diag) -> mlir::LogicalResult { return diag; }, inner);
127 }
128
131 operator mlir::ParseResult() const { return mlir::ParseResult(mlir::LogicalResult(*this)); }
132
135 template <typename T> operator mlir::FailureOr<T>() const { return mlir::failure(); }
136
137 // Match move/copy semantics of InFlightDiagnostic
138 InFlightDiagnosticWrapper(InFlightDiagnosticWrapper &&) = default;
139 InFlightDiagnosticWrapper(const InFlightDiagnosticWrapper &) = delete;
140 InFlightDiagnosticWrapper &operator=(InFlightDiagnosticWrapper &&) = delete;
141 InFlightDiagnosticWrapper &operator=(const InFlightDiagnosticWrapper &) = delete;
142};
143
145using EmitErrorFn = llvm::function_ref<InFlightDiagnosticWrapper()>;
146
150
151inline OwningEmitErrorFn getEmitOpErrFn(mlir::Operation *op) {
152 return [op]() { return InFlightDiagnosticWrapper(op->emitOpError()); };
153}
154
155template <typename OpImplClass> inline OwningEmitErrorFn getEmitOpErrFn(OpImplClass *opImpl) {
156 return getEmitOpErrFn(opImpl->getOperation());
157}
158
159inline void ensure(bool condition, const llvm::Twine &errMsg) {
160 if (!condition) {
161 llvm::report_fatal_error(errMsg);
162 }
163}
164
176 llvm::function_ref<mlir::InFlightDiagnostic()> emitError, mlir::MLIRContext *ctx
177) {
178 if (emitError) {
179 return [emitError]() -> auto { return InFlightDiagnosticWrapper(emitError()); };
180 } else {
181 return [ctx]() -> auto { return InFlightDiagnosticWrapper(ctx); };
182 }
183}
184
186wrapNonNullableInFlightDiagnostic(llvm::function_ref<mlir::InFlightDiagnostic()> emitError) {
187 assert(emitError && "emitError must be non-null");
188 return [emitError]() -> auto { return InFlightDiagnosticWrapper(emitError()); };
189}
190
191} // namespace llzk
Wrapper around InFlightDiagnostic that can either be a regular InFlightDiagnostic or a special versio...
Definition ErrorHelper.h:26
InFlightDiagnosticWrapper & operator=(const InFlightDiagnosticWrapper &)=delete
InFlightDiagnosticWrapper & operator<<(Arg &&arg) &
Stream operator for new diagnostic arguments.
Definition ErrorHelper.h:81
InFlightDiagnosticWrapper && append(Args &&...args) &&
Append arguments to the diagnostic.
Definition ErrorHelper.h:95
mlir::Diagnostic & attachNote(std::optional< mlir::Location > noteLoc=std::nullopt)
Attaches a note to this diagnostic.
InFlightDiagnosticWrapper(const mlir::Location &loc)
Constructor for DefaultAndFailInFlightDiagnostic from Location.
Definition ErrorHelper.h:70
InFlightDiagnosticWrapper && operator<<(Arg &&arg) &&
Stream operator for new diagnostic arguments.
Definition ErrorHelper.h:85
static InFlightDiagnosticWrapper createSilent(mlir::MLIRContext *ctx)
Construct a silent diagnostic that does nothing when appended to or reported.
Definition ErrorHelper.h:74
InFlightDiagnosticWrapper(InFlightDiagnosticWrapper &&)=default
void report()
Reports the diagnostic to the engine.
mlir::Diagnostic * getUnderlyingDiagnostic()
Returns the underlying diagnostic or nullptr if this diagnostic isn't active.
void abandon()
Abandons this diagnostic so that it will no longer be reported.
InFlightDiagnosticWrapper(mlir::InFlightDiagnostic &&diag)
Constructor for regular InFlightDiagnostic.
Definition ErrorHelper.h:57
InFlightDiagnosticWrapper(mlir::MLIRContext *ctx)
Constructor for DefaultAndFailInFlightDiagnostic from MLIRContext.
Definition ErrorHelper.h:62
InFlightDiagnosticWrapper(const InFlightDiagnosticWrapper &)=delete
InFlightDiagnosticWrapper & operator=(InFlightDiagnosticWrapper &&)=delete
InFlightDiagnosticWrapper & append(Args &&...args) &
Append arguments to the diagnostic.
Definition ErrorHelper.h:90
void ensure(bool condition, const llvm::Twine &errMsg)
llvm::function_ref< InFlightDiagnosticWrapper()> EmitErrorFn
Callback to produce an error diagnostic.
OwningEmitErrorFn getEmitOpErrFn(mlir::Operation *op)
OwningEmitErrorFn wrapNonNullableInFlightDiagnostic(llvm::function_ref< mlir::InFlightDiagnostic()> emitError)
std::function< InFlightDiagnosticWrapper()> OwningEmitErrorFn
This type is required in cases like the functions below to take ownership of the lambda so it is not ...
OwningEmitErrorFn wrapNullableInFlightDiagnostic(llvm::function_ref< mlir::InFlightDiagnostic()> emitError, mlir::MLIRContext *ctx)
If the given emitError is non-null, return it.