LLZK 3.0.0
An open-source IR for Zero Knowledge (ZK) circuits
Loading...
Searching...
No Matches
Parsers.h
Go to the documentation of this file.
1//===-- Parsers.h -----------------------------------------------*- C++ -*-===//
2//
3// Command line parsers for LLZK transformation passes.
4//
5// Part of the LLZK Project, under the Apache License v2.0.
6// See LICENSE.txt for license information.
7// Copyright 2025 Veridise Inc.
8// Copyright 2026 Project LLZK
9// SPDX-License-Identifier: Apache-2.0
10//
11//===----------------------------------------------------------------------===//
12
13#pragma once
14
15#include "llzk/Util/Compare.h"
16
17#include <mlir/Pass/Pass.h>
18
19#include <llvm/ADT/APInt.h>
20#include <llvm/ADT/StringExtras.h>
21#include <llvm/Support/CommandLine.h>
22#include <llvm/Support/ErrorHandling.h>
23#include <llvm/Support/raw_ostream.h>
24
25#include <string>
26
27namespace llzk {
28
29namespace detail {
30
34 std::string str;
35
41 template <typename ValueT, typename CreateFnT, typename InitializeFnT>
42 std::unique_ptr<ValueT> createValidatedValue(
43 CreateFnT &&createValue, llvm::StringRef kind, InitializeFnT &&initializeValue
44 ) const {
45 auto value = createValue();
46 if (str.empty()) {
47 return value;
48 }
49
50 std::string error;
51 if (failed(initializeValue(*value, str, error))) {
52 llvm::report_fatal_error(
53 llvm::Twine("failed to initialize previously-validated nested ") + kind +
54 " options: " + error
55 );
56 }
57 return value;
58 }
59};
60
61} // namespace detail
62
65template <auto CreatePass> struct NestedPassOptions : detail::NestedTextualOptions {
67 std::unique_ptr<mlir::Pass> createPass() const {
68 return this->createValidatedValue<mlir::Pass>(CreatePass, "pass", initializePass);
69 }
70
71 static mlir::LogicalResult
72 initializePass(mlir::Pass &pass, llvm::StringRef options, std::string &error) {
73 return pass.initializeOptions(options, [&error](const llvm::Twine &message) {
74 error = message.str();
75 return mlir::failure();
76 });
77 }
78};
79
82template <typename PipelineOptionsT> struct NestedPipelineOptions : detail::NestedTextualOptions {
84 std::unique_ptr<PipelineOptionsT> createOptions() const {
86 std::make_unique<PipelineOptionsT>, "pipeline", initializeOptions
87 );
88 }
89
90 static mlir::LogicalResult
91 initializeOptions(PipelineOptionsT &options, llvm::StringRef value, std::string &error) {
92 llvm::raw_string_ostream errorStream(error);
93 return options.parseFromString(value, errorStream);
94 }
95};
96
97} // namespace llzk
98
99// Custom command line parsers
100namespace llvm {
101namespace cl {
102
103template <typename OptionsT> class NestedOptionsParserBase : public basic_parser<OptionsT> {
104public:
105 NestedOptionsParserBase(Option &O) : basic_parser<OptionsT>(O) {}
106
107protected:
110 bool parseNestedOptions(Option &O, StringRef Arg, StringRef kind, StringRef &options) const {
111 options = Arg;
112 if (options.consume_front("{") && !options.consume_back("}")) {
113 return O.error(llvm::Twine("expected nested ") + kind + " options to end with '}'");
114 }
115 return false;
116 }
117
118public:
119 static void print(llvm::raw_ostream &OS, const OptionsT &Val) { OS << '{' << Val.str << '}'; }
120
122 const Option &O, const OptionsT &V, const OptionValue<OptionsT> &Default, size_t GlobalWidth
123 ) const {
124 this->printOptionName(O, GlobalWidth);
125 print(llvm::outs(), V);
126 llvm::outs() << " (default: ";
127 if (Default.hasValue()) {
128 print(llvm::outs(), Default.getValue());
129 } else {
130 llvm::outs() << "<unspecified>";
131 }
132 llvm::outs() << ")\n";
133 }
134};
135
137template <auto CreatePass>
138class parser<llzk::NestedPassOptions<CreatePass>>
139 : public NestedOptionsParserBase<llzk::NestedPassOptions<CreatePass>> {
140public:
143
144 parser(Option &O) : Base(O) {}
145
146 bool parse(Option &O, StringRef, StringRef Arg, OptionsT &Val) {
147 StringRef options;
148 if (this->parseNestedOptions(O, Arg, "pass", options)) {
149 return true;
150 }
151
152 auto pass = CreatePass();
153 std::string error;
154 if (failed(OptionsT::initializePass(*pass, options, error))) {
155 return O.error(error);
156 }
157
158 Val.str = options.str();
159 return false;
160 }
161};
162
165template <typename PipelineOptionsT>
166class parser<llzk::NestedPipelineOptions<PipelineOptionsT>>
167 : public NestedOptionsParserBase<llzk::NestedPipelineOptions<PipelineOptionsT>> {
168public:
171
172 parser(Option &O) : Base(O) {}
173
174 bool parse(Option &O, StringRef, StringRef Arg, OptionsT &Val) {
175 StringRef options;
176 if (this->parseNestedOptions(O, Arg, "pipeline", options)) {
177 return true;
178 }
179
180 PipelineOptionsT pipelineOptions;
181 std::string error;
182 if (failed(OptionsT::initializeOptions(pipelineOptions, options, error))) {
183 return O.error(error);
184 }
185
186 Val.str = options.str();
187 return false;
188 }
189};
190
191// Parser for APInt
192template <> class parser<APInt> : public basic_parser<APInt> {
193public:
194 parser(Option &O) : basic_parser(O) {}
195
196 bool parse(Option &O, StringRef, StringRef Arg, APInt &Val) {
197 if (Arg.empty()) {
198 return O.error("empty integer literal");
199 }
200 if (!all_of(Arg, [](char c) { return isDigit(c); })) {
201 return O.error("arg must be in base 10 (digits).");
202 }
203 // Decimal-only: allocate a safe width then shrink.
204 unsigned bits = std::max(1u, 4u * llzk::checkedCast<unsigned>(Arg.size()));
205 APInt tmp(bits, Arg, 10);
206 unsigned active = tmp.getActiveBits();
207 if (active == 0) {
208 active = 1;
209 }
210 Val = tmp.zextOrTrunc(active);
211 return false;
212 }
213
214 // Prints how the passed option differs from the default one specified in the pass
215 // For example, if V = 17 and Default = 11 then it should print
216 // [OptionName] 17 (default: 11)
218 const Option &O, const APInt &V, const OptionValue<APInt> &Default, size_t GlobalWidth
219 ) const {
220 std::string Cur = llvm::toString(V, 10, false);
221
222 std::string Def = "<unspecified>";
223 if (Default.hasValue()) {
224 const APInt &D = Default.getValue();
225 Def = llvm::toString(D, 10, false);
226 }
227
228 printOptionName(O, GlobalWidth);
229 llvm::outs() << Cur << " (default: " << Def << ")\n";
230 }
231};
232
233} // namespace cl
234} // namespace llvm
bool parseNestedOptions(Option &O, StringRef Arg, StringRef kind, StringRef &options) const
Parse a nested pass or pipeline option payload, optionally stripping a surrounding {....
Definition Parsers.h:110
void printOptionDiff(const Option &O, const OptionsT &V, const OptionValue< OptionsT > &Default, size_t GlobalWidth) const
Definition Parsers.h:121
static void print(llvm::raw_ostream &OS, const OptionsT &Val)
Definition Parsers.h:119
void printOptionDiff(const Option &O, const APInt &V, const OptionValue< APInt > &Default, size_t GlobalWidth) const
Definition Parsers.h:217
bool parse(Option &O, StringRef, StringRef Arg, APInt &Val)
Definition Parsers.h:196
llzk::NestedPassOptions< CreatePass > OptionsT
Definition Parsers.h:141
bool parse(Option &O, StringRef, StringRef Arg, OptionsT &Val)
Definition Parsers.h:146
NestedOptionsParserBase< OptionsT > Base
Definition Parsers.h:142
llzk::NestedPipelineOptions< PipelineOptionsT > OptionsT
Definition Parsers.h:169
bool parse(Option &O, StringRef, StringRef Arg, OptionsT &Val)
Definition Parsers.h:174
constexpr T checkedCast(U u) noexcept
Definition Compare.h:81
Stores textual options for a constituent pass after validating them against that pass' native MLIR op...
Definition Parsers.h:65
static mlir::LogicalResult initializePass(mlir::Pass &pass, llvm::StringRef options, std::string &error)
Definition Parsers.h:72
std::unique_ptr< mlir::Pass > createPass() const
Build a fresh pass instance with the validated options applied.
Definition Parsers.h:67
Stores textual options for a constituent pipeline after validating them against that pipeline's nativ...
Definition Parsers.h:82
std::unique_ptr< PipelineOptionsT > createOptions() const
Build a fresh options object with the validated options applied.
Definition Parsers.h:84
static mlir::LogicalResult initializeOptions(StructInliningFlatteningOptions &options, llvm::StringRef value, std::string &error)
Definition Parsers.h:91
Shared storage and helpers for nested textual pass and pipeline options.
Definition Parsers.h:32
std::string str
The validated textual form without the outer {...} delimiters.
Definition Parsers.h:34
std::unique_ptr< ValueT > createValidatedValue(CreateFnT &&createValue, llvm::StringRef kind, InitializeFnT &&initializeValue) const
Recreate a nested value from the stored option string and re-validate it.
Definition Parsers.h:42