LLZK 0.1.0
Veridise's ZK Language IR
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
18
19#include <mlir/IR/BuiltinOps.h>
21// Include the generated base pass class definitions.
22namespace llzk::include {
23#define GEN_PASS_DEF_INLINEINCLUDESPASS
25} // namespace llzk::include
27using namespace mlir;
28using namespace llzk::include;
30namespace {
31using IncludeStack = std::vector<std::pair<StringRef, Location>>;
33inline bool contains(IncludeStack &stack, StringRef &&loc) {
34 auto path_match = [loc](std::pair<StringRef, Location> &p) { return p.first == loc; };
35 return std::find_if(stack.begin(), stack.end(), path_match) != stack.end();
36}
38class InlineIncludesPass : public llzk::include::impl::InlineIncludesPassBase<InlineIncludesPass> {
39 void runOnOperation() override {
40 std::vector<std::pair<ModuleOp, IncludeStack>> currLevel = {
41 std::make_pair(getOperation(), IncludeStack())
42 };
43 do {
44 std::vector<std::pair<ModuleOp, IncludeStack>> nextLevel = {};
45 for (std::pair<ModuleOp, IncludeStack> &curr : currLevel) {
46 curr.first.walk([includeStack = std::move(curr.second),
47 &nextLevel](IncludeOp incOp) mutable {
48 // Check for cyclic includes
49 if (contains(includeStack, incOp.getPath())) {
50 auto err = incOp.emitError().append("found cyclic include");
51 for (auto it = includeStack.rbegin(); it != includeStack.rend(); ++it) {
52 err.attachNote(it->second).append("included from here");
53 }
54 err.report();
55 } else {
56 includeStack.push_back(std::make_pair(incOp.getPath(), incOp.getLoc()));
57 FailureOr<ModuleOp> result = incOp.inlineAndErase();
58 if (succeeded(result)) {
59 ModuleOp newMod = std::move(result.value());
60 nextLevel.push_back(make_pair(newMod, includeStack));
61 }
62 }
63 // Advance in either case so as many errors as possible are found in a single run.
64 return WalkResult::advance();
65 });
66 }
67 currLevel = nextLevel;
68 } while (!currLevel.empty());
69
70 markAllAnalysesPreserved();
71 }
72};
73
74} // namespace
75
76std::unique_ptr<mlir::Pass> llzk::include::createInlineIncludesPass() {
77 return std::make_unique<InlineIncludesPass>();
78};
std::unique_ptr< mlir::Pass > createInlineIncludesPass()