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<FuncOp>(op) || op->hasTrait<OpTrait::IsTerminator>()) 51 return; 52 53 OpBuilder builder(op); 54 55 /// Add the same operation but with fallback location to test the 56 /// corresponding get method and serialization. 57 Operation *opCloned1 = builder.clone(*op); 58 opCloned1->setLoc(OpaqueLoc::get<MyLocation *>(myLocs.back().get(), loc)); 59 60 /// Add the same operation but with void* instead of MyLocation* to test 61 /// getUnderlyingLocationOrNull method. 62 Operation *opCloned2 = builder.clone(*op); 63 opCloned2->setLoc(OpaqueLoc::get<void *>(nullptr, loc)); 64 }); 65 66 ScopedDiagnosticHandler diagHandler(&getContext(), [](Diagnostic &diag) { 67 auto &os = llvm::outs(); 68 if (diag.getLocation().isa<OpaqueLoc>()) { 69 MyLocation *loc = OpaqueLoc::getUnderlyingLocationOrNull<MyLocation *>( 70 diag.getLocation()); 71 if (loc) 72 os << "MyLocation: " << loc->id; 73 else 74 os << "nullptr"; 75 } 76 os << ": " << diag << '\n'; 77 os.flush(); 78 }); 79 80 getOperation().walk([&](Operation *op) { op->emitOpError(); }); 81 } 82 }; 83 84 } // namespace 85 86 namespace mlir { 87 namespace test { 88 void registerTestOpaqueLoc() { PassRegistration<TestOpaqueLoc>(); } 89 } // namespace test 90 } // namespace mlir 91