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/IR/Builders.h" 10 #include "mlir/Pass/Pass.h" 11 12 using namespace mlir; 13 14 namespace { 15 /// Pass that changes locations to opaque locations for each operation. 16 /// It also takes all operations that are not function operations or 17 /// terminators and clones them with opaque locations which store the initial 18 /// locations. 19 struct TestOpaqueLoc 20 : public PassWrapper<TestOpaqueLoc, OperationPass<ModuleOp>> { 21 StringRef getArgument() const final { return "test-opaque-loc"; } 22 StringRef getDescription() const final { 23 return "Changes all leaf locations to opaque locations"; 24 } 25 26 /// A simple structure which is used for testing as an underlying location in 27 /// OpaqueLoc. 28 struct MyLocation { 29 MyLocation() = default; 30 MyLocation(int id) : id(id) {} 31 int getId() { return id; } 32 33 int id{42}; 34 }; 35 36 void runOnOperation() override { 37 std::vector<std::unique_ptr<MyLocation>> myLocs; 38 int lastIt = 0; 39 40 getOperation().getBody()->walk([&](Operation *op) { 41 myLocs.push_back(std::make_unique<MyLocation>(lastIt++)); 42 43 Location loc = op->getLoc(); 44 45 /// Set opaque location without fallback location to test the 46 /// corresponding get method. 47 op->setLoc( 48 OpaqueLoc::get<MyLocation *>(myLocs.back().get(), &getContext())); 49 50 if (isa<ModuleOp>(op->getParentOp()) || 51 op->hasTrait<OpTrait::IsTerminator>()) 52 return; 53 54 OpBuilder builder(op); 55 56 /// Add the same operation but with fallback location to test the 57 /// corresponding get method and serialization. 58 Operation *opCloned1 = builder.clone(*op); 59 opCloned1->setLoc(OpaqueLoc::get<MyLocation *>(myLocs.back().get(), loc)); 60 61 /// Add the same operation but with void* instead of MyLocation* to test 62 /// getUnderlyingLocationOrNull method. 63 Operation *opCloned2 = builder.clone(*op); 64 opCloned2->setLoc(OpaqueLoc::get<void *>(nullptr, loc)); 65 }); 66 67 ScopedDiagnosticHandler diagHandler(&getContext(), [](Diagnostic &diag) { 68 auto &os = llvm::outs(); 69 if (diag.getLocation().isa<OpaqueLoc>()) { 70 MyLocation *loc = OpaqueLoc::getUnderlyingLocationOrNull<MyLocation *>( 71 diag.getLocation()); 72 if (loc) 73 os << "MyLocation: " << loc->id; 74 else 75 os << "nullptr"; 76 } 77 os << ": " << diag << '\n'; 78 os.flush(); 79 }); 80 81 getOperation().walk([&](Operation *op) { op->emitOpError(); }); 82 } 83 }; 84 85 } // namespace 86 87 namespace mlir { 88 namespace test { 89 void registerTestOpaqueLoc() { PassRegistration<TestOpaqueLoc>(); } 90 } // namespace test 91 } // namespace mlir 92