LLZK 2.1.1
An open-source IR for Zero Knowledge (ZK) circuits
Loading...
Searching...
No Matches
InlineIncludesPass.cpp
Go to the documentation of this file.
1//===-- LLZKInlineIncludesPass.cpp - -llzk-inline-includes pass -*- 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//===----------------------------------------------------------------------===//
13//===----------------------------------------------------------------------===//
14
16
20#include <mlir/IR/BuiltinOps.h>
21
22#include <llvm/Support/LogicalResult.h>
23
24// Include the generated base pass class definitions.
25namespace llzk::include {
26#define GEN_PASS_DEF_INLINEINCLUDESPASS
28} // namespace llzk::include
30using namespace mlir;
31using namespace llzk::include;
33namespace {
34using IncludeStack = std::vector<std::pair<StringRef, Location>>;
35
36inline bool contains(IncludeStack &stack, StringRef &&loc) {
37 auto path_match = [loc](std::pair<StringRef, Location> &p) { return p.first == loc; };
38 return std::find_if(stack.begin(), stack.end(), path_match) != stack.end();
39}
41class PassImpl : public llzk::include::impl::InlineIncludesPassBase<PassImpl> {
43 using Base::Base;
44
45 void runOnOperation() override {
46 std::vector<std::pair<ModuleOp, IncludeStack>> currLevel = {
47 std::make_pair(getOperation(), IncludeStack())
48 };
49 do {
50 std::vector<std::pair<ModuleOp, IncludeStack>> nextLevel = {};
51 for (std::pair<ModuleOp, IncludeStack> &curr : currLevel) {
52 curr.first.walk([includeStack = std::move(curr.second),
53 &nextLevel](IncludeOp incOp) mutable {
54 // Check for cyclic includes
55 if (contains(includeStack, incOp.getPath())) {
56 auto err = incOp.emitError().append("found cyclic include");
57 for (auto it = includeStack.rbegin(); it != includeStack.rend(); ++it) {
58 err.attachNote(it->second).append("included from here");
59 }
60 err.report();
61 } else {
62 includeStack.push_back(std::make_pair(incOp.getPath(), incOp.getLoc()));
63 FailureOr<ModuleOp> result = incOp.inlineAndErase();
64 if (succeeded(result)) {
65 ModuleOp newMod = result.value();
66 assert(succeeded(newMod.verify()) && "newMod must pass verification");
67 nextLevel.push_back(make_pair(newMod, includeStack));
68 }
69 }
70 // Advance in either case so as many errors as possible are found in a single run.
71 return WalkResult::advance();
72 });
73 }
74 currLevel = nextLevel;
75 } while (!currLevel.empty());
76
77 if (failed(getOperation().verify())) {
78 signalPassFailure();
79 return;
80 }
81 markAllAnalysesPreserved();
82 }
83};
84
85} // namespace