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