LLZK 3.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 // Intentional hiding: std::visit dispatches using the concrete type,
45 // and the derived destructor explicitly calls this method.
46 // NOLINTNEXTLINE(bugprone-derived-method-shadowing-base-method)
47 void report() {
48 InFlightDiagnostic::report();
49 assert(false);
50 }
51 };
52
53 std::variant<mlir::InFlightDiagnostic, DefaultAndFailInFlightDiagnostic> inner;
54
55 explicit InFlightDiagnosticWrapper(DefaultAndFailInFlightDiagnostic &&diag)
56 : inner(std::move(diag)) {}
57
58public:
60 explicit InFlightDiagnosticWrapper(mlir::InFlightDiagnostic &&diag) : inner(std::move(diag)) {}
61
65 explicit InFlightDiagnosticWrapper(mlir::MLIRContext *ctx)
66 : InFlightDiagnosticWrapper(
67 DefaultAndFailInFlightDiagnostic(mlir::detail::getDefaultDiagnosticEmitFn(ctx)())
68 ) {}
69
73 explicit InFlightDiagnosticWrapper(const mlir::Location &loc)
74 : InFlightDiagnosticWrapper(loc.getContext()) {}
75
77 static InFlightDiagnosticWrapper createSilent(mlir::MLIRContext *ctx) {
78 mlir::InFlightDiagnostic d = mlir::emitRemark(mlir::UnknownLoc::get(ctx));
79 d.abandon();
80 return InFlightDiagnosticWrapper(std::move(d));
81 }
82
84 template <typename Arg> InFlightDiagnosticWrapper &operator<<(Arg &&arg) & {
85 return append(std::forward<Arg>(arg));
86 }
87
88 template <typename Arg> InFlightDiagnosticWrapper &&operator<<(Arg &&arg) && {
89 return std::move(append(std::forward<Arg>(arg)));
90 }
91
93 template <typename... Args> InFlightDiagnosticWrapper &append(Args &&...args) & {
94 std::visit([&](auto &diag) { diag.append(std::forward<Args>(args)...); }, inner);
95 return *this;
96 }
97
98 template <typename... Args> InFlightDiagnosticWrapper &&append(Args &&...args) && {
99 return std::move(append(std::forward<Args>(args)...));
100 }
101
103 mlir::Diagnostic &attachNote(std::optional<mlir::Location> noteLoc = std::nullopt) {
104 return std::visit([&](auto &diag) -> mlir::Diagnostic & {
105 return diag.attachNote(noteLoc);
106 }, inner);
107 }
108
110 mlir::Diagnostic *getUnderlyingDiagnostic() {
111 return std::visit([](auto &diag) -> mlir::Diagnostic * {
112 return diag.getUnderlyingDiagnostic();
113 }, inner);
114 }
115
117 void report() {
118 std::visit([](auto &diag) { diag.report(); }, inner);
119 }
120
122 void abandon() {
123 std::visit([](auto &diag) { diag.abandon(); }, inner);
124 }
125
128 operator mlir::LogicalResult() const {
129 return std::visit([](const auto &diag) -> mlir::LogicalResult { return diag; }, inner);
130 }
131
134 operator mlir::ParseResult() const { return mlir::ParseResult(mlir::LogicalResult(*this)); }
135
138 template <typename T> operator mlir::FailureOr<T>() const { return mlir::failure(); }
139
140 // Match move/copy semantics of InFlightDiagnostic
141 InFlightDiagnosticWrapper(InFlightDiagnosticWrapper &&) = default;
142 InFlightDiagnosticWrapper(const InFlightDiagnosticWrapper &) = delete;
143 InFlightDiagnosticWrapper &operator=(InFlightDiagnosticWrapper &&) = delete;
144 InFlightDiagnosticWrapper &operator=(const InFlightDiagnosticWrapper &) = delete;
145};
146
148using EmitErrorFn = llvm::function_ref<InFlightDiagnosticWrapper()>;
149
153
154inline OwningEmitErrorFn getEmitOpErrFn(mlir::Operation *op) {
155 return [op]() { return InFlightDiagnosticWrapper(op->emitOpError()); };
156}
157
158template <typename OpImplClass> inline OwningEmitErrorFn getEmitOpErrFn(OpImplClass *opImpl) {
159 return getEmitOpErrFn(opImpl->getOperation());
160}
161
162inline void ensure(bool condition, const llvm::Twine &errMsg) {
163 if (!condition) {
164 llvm::report_fatal_error(errMsg);
165 }
166}
167
179 llvm::function_ref<mlir::InFlightDiagnostic()> emitError, mlir::MLIRContext *ctx
180) {
181 if (emitError) {
182 return [emitError]() -> auto { return InFlightDiagnosticWrapper(emitError()); };
183 } else {
184 return [ctx]() -> auto { return InFlightDiagnosticWrapper(ctx); };
185 }
186}
187
189wrapNonNullableInFlightDiagnostic(llvm::function_ref<mlir::InFlightDiagnostic()> emitError) {
190 assert(emitError && "emitError must be non-null");
191 return [emitError]() -> auto { return InFlightDiagnosticWrapper(emitError()); };
192}
193
194} // 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:84
InFlightDiagnosticWrapper && append(Args &&...args) &&
Append arguments to the diagnostic.
Definition ErrorHelper.h:98
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:73
InFlightDiagnosticWrapper && operator<<(Arg &&arg) &&
Stream operator for new diagnostic arguments.
Definition ErrorHelper.h:88
static InFlightDiagnosticWrapper createSilent(mlir::MLIRContext *ctx)
Construct a silent diagnostic that does nothing when appended to or reported.
Definition ErrorHelper.h:77
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:60
InFlightDiagnosticWrapper(mlir::MLIRContext *ctx)
Constructor for DefaultAndFailInFlightDiagnostic from MLIRContext.
Definition ErrorHelper.h:65
InFlightDiagnosticWrapper(const InFlightDiagnosticWrapper &)=delete
InFlightDiagnosticWrapper & operator=(InFlightDiagnosticWrapper &&)=delete
InFlightDiagnosticWrapper & append(Args &&...args) &
Append arguments to the diagnostic.
Definition ErrorHelper.h:93
Common interface for constant parameter-like symbol operations that can be defined within a TemplateO...
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.