1 //===- TestOpaqueLoc.cpp - Pass to test opaque locations ------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "mlir/Dialect/StandardOps/IR/Ops.h"
10 #include "mlir/IR/Builders.h"
11 #include "mlir/Pass/Pass.h"
12 
13 using namespace mlir;
14 
15 namespace {
16 /// Pass that changes locations to opaque locations for each operation.
17 /// It also takes all operations that are not function operations or
18 /// terminators and clones them with opaque locations which store the initial
19 /// locations.
20 struct TestOpaqueLoc
21     : public PassWrapper<TestOpaqueLoc, OperationPass<ModuleOp>> {
22 
23   /// A simple structure which is used for testing as an underlying location in
24   /// OpaqueLoc.
25   struct MyLocation {
MyLocation__anoncc17faef0111::TestOpaqueLoc::MyLocation26     MyLocation() : id(42) {}
MyLocation__anoncc17faef0111::TestOpaqueLoc::MyLocation27     MyLocation(int id) : id(id) {}
getId__anoncc17faef0111::TestOpaqueLoc::MyLocation28     int getId() { return id; }
29 
30     int id;
31   };
32 
runOnOperation__anoncc17faef0111::TestOpaqueLoc33   void runOnOperation() override {
34     std::vector<std::unique_ptr<MyLocation>> myLocs;
35     int last_it = 0;
36 
37     getOperation().walk([&](Operation *op) {
38       myLocs.push_back(std::make_unique<MyLocation>(last_it++));
39 
40       Location loc = op->getLoc();
41 
42       /// Set opaque location without fallback location to test the
43       /// corresponding get method.
44       op->setLoc(
45           OpaqueLoc::get<MyLocation *>(myLocs.back().get(), &getContext()));
46 
47       if (isa<FuncOp>(op) || op->isKnownTerminator())
48         return;
49 
50       OpBuilder builder(op);
51 
52       /// Add the same operation but with fallback location to test the
53       /// corresponding get method and serialization.
54       Operation *op_cloned_1 = builder.clone(*op);
55       op_cloned_1->setLoc(
56           OpaqueLoc::get<MyLocation *>(myLocs.back().get(), loc));
57 
58       /// Add the same operation but with void* instead of MyLocation* to test
59       /// getUnderlyingLocationOrNull method.
60       Operation *op_cloned_2 = builder.clone(*op);
61       op_cloned_2->setLoc(OpaqueLoc::get<void *>(nullptr, loc));
62     });
63 
64     ScopedDiagnosticHandler diagHandler(&getContext(), [](Diagnostic &diag) {
65       auto &os = llvm::outs();
66       if (diag.getLocation().isa<OpaqueLoc>()) {
67         MyLocation *loc = OpaqueLoc::getUnderlyingLocationOrNull<MyLocation *>(
68             diag.getLocation());
69         if (loc)
70           os << "MyLocation: " << loc->id;
71         else
72           os << "nullptr";
73       }
74       os << ": " << diag << '\n';
75       os.flush();
76     });
77 
78     getOperation().walk([&](Operation *op) { op->emitOpError(); });
79   }
80 };
81 
82 } // end anonymous namespace
83 
84 namespace mlir {
85 namespace test {
registerTestOpaqueLoc()86 void registerTestOpaqueLoc() {
87   PassRegistration<TestOpaqueLoc> pass(
88       "test-opaque-loc", "Changes all leaf locations to opaque locations");
89 }
90 } // namespace test
91 } // namespace mlir
92