MLIR  14.0.0git
LocationSnapshot.cpp
Go to the documentation of this file.
1 //===- LocationSnapshot.cpp - Location Snapshot Utilities -----------------===//
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 
10 #include "PassDetail.h"
11 #include "mlir/IR/AsmState.h"
12 #include "mlir/IR/Builders.h"
14 #include "llvm/Support/FileSystem.h"
15 #include "llvm/Support/ToolOutputFile.h"
16 
17 using namespace mlir;
18 
19 /// This function generates new locations from the given IR by snapshotting the
20 /// IR to the given stream, and using the printed locations within that stream.
21 /// If a 'tag' is non-empty, the generated locations are represented as a
22 /// NameLoc with the given tag as the name, and then fused with the existing
23 /// locations. Otherwise, the existing locations are replaced.
24 static void generateLocationsFromIR(raw_ostream &os, StringRef fileName,
25  Operation *op, const OpPrintingFlags &flags,
26  StringRef tag) {
27  // Print the IR to the stream, and collect the raw line+column information.
28  AsmState::LocationMap opToLineCol;
29  AsmState state(op, flags, &opToLineCol);
30  op->print(os, state, flags);
31 
32  Builder builder(op->getContext());
33  Optional<StringAttr> tagIdentifier;
34  if (!tag.empty())
35  tagIdentifier = builder.getStringAttr(tag);
36 
37  // Walk and generate new locations for each of the operations.
38  StringAttr file = builder.getStringAttr(fileName);
39  op->walk([&](Operation *opIt) {
40  // Check to see if this operation has a mapped location. Some operations may
41  // be elided from the printed form, e.g. the body terminators of some region
42  // operations.
43  auto it = opToLineCol.find(opIt);
44  if (it == opToLineCol.end())
45  return;
46  const std::pair<unsigned, unsigned> &lineCol = it->second;
47  auto newLoc = FileLineColLoc::get(file, lineCol.first, lineCol.second);
48 
49  // If we don't have a tag, set the location directly
50  if (!tagIdentifier) {
51  opIt->setLoc(newLoc);
52  return;
53  }
54 
55  // Otherwise, build a fused location with the existing op loc.
56  opIt->setLoc(builder.getFusedLoc(
57  {opIt->getLoc(), NameLoc::get(*tagIdentifier, newLoc)}));
58  });
59 }
60 
61 /// This function generates new locations from the given IR by snapshotting the
62 /// IR to the given file, and using the printed locations within that file. If
63 /// `filename` is empty, a temporary file is generated instead.
64 static LogicalResult generateLocationsFromIR(StringRef fileName, Operation *op,
65  OpPrintingFlags flags,
66  StringRef tag) {
67  // If a filename wasn't provided, then generate one.
68  SmallString<32> filepath(fileName);
69  if (filepath.empty()) {
70  if (std::error_code error = llvm::sys::fs::createTemporaryFile(
71  "mlir_snapshot", "tmp.mlir", filepath)) {
72  return op->emitError()
73  << "failed to generate temporary file for location snapshot: "
74  << error.message();
75  }
76  }
77 
78  // Open the output file for emission.
79  std::string error;
80  std::unique_ptr<llvm::ToolOutputFile> outputFile =
81  openOutputFile(filepath, &error);
82  if (!outputFile)
83  return op->emitError() << error;
84 
85  // Generate the intermediate locations.
86  generateLocationsFromIR(outputFile->os(), filepath, op, flags, tag);
87  outputFile->keep();
88  return success();
89 }
90 
91 /// This function generates new locations from the given IR by snapshotting the
92 /// IR to the given stream, and using the printed locations within that stream.
93 /// The generated locations replace the current operation locations.
94 void mlir::generateLocationsFromIR(raw_ostream &os, StringRef fileName,
95  Operation *op, OpPrintingFlags flags) {
96  ::generateLocationsFromIR(os, fileName, op, flags, /*tag=*/StringRef());
97 }
98 /// This function generates new locations from the given IR by snapshotting the
99 /// IR to the given file, and using the printed locations within that file. If
100 /// `filename` is empty, a temporary file is generated instead.
102  OpPrintingFlags flags) {
103  return ::generateLocationsFromIR(fileName, op, flags, /*tag=*/StringRef());
104 }
105 
106 /// This function generates new locations from the given IR by snapshotting the
107 /// IR to the given stream, and using the printed locations within that stream.
108 /// The generated locations are represented as a NameLoc with the given tag as
109 /// the name, and then fused with the existing locations.
110 void mlir::generateLocationsFromIR(raw_ostream &os, StringRef fileName,
111  StringRef tag, Operation *op,
112  OpPrintingFlags flags) {
113  ::generateLocationsFromIR(os, fileName, op, flags, tag);
114 }
115 /// This function generates new locations from the given IR by snapshotting the
116 /// IR to the given file, and using the printed locations within that file. If
117 /// `filename` is empty, a temporary file is generated instead.
118 LogicalResult mlir::generateLocationsFromIR(StringRef fileName, StringRef tag,
119  Operation *op,
120  OpPrintingFlags flags) {
121  return ::generateLocationsFromIR(fileName, op, flags, tag);
122 }
123 
124 namespace {
125 struct LocationSnapshotPass
126  : public LocationSnapshotBase<LocationSnapshotPass> {
127  LocationSnapshotPass() = default;
128  LocationSnapshotPass(OpPrintingFlags flags, StringRef fileName, StringRef tag)
129  : flags(flags) {
130  this->fileName = fileName.str();
131  this->tag = tag.str();
132  }
133 
134  void runOnOperation() override {
135  Operation *op = getOperation();
136  if (failed(generateLocationsFromIR(fileName, op, OpPrintingFlags(), tag)))
137  return signalPassFailure();
138  }
139 
140  /// The printing flags to use when creating the snapshot.
141  OpPrintingFlags flags;
142 };
143 } // namespace
144 
146  StringRef fileName,
147  StringRef tag) {
148  return std::make_unique<LocationSnapshotPass>(flags, fileName, tag);
149 }
150 std::unique_ptr<Pass> mlir::createLocationSnapshotPass() {
151  return std::make_unique<LocationSnapshotPass>();
152 }
Include the generated interface declarations.
Operation is a basic unit of execution within MLIR.
Definition: Operation.h:28
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value...
Definition: LogicalResult.h:72
static void generateLocationsFromIR(raw_ostream &os, StringRef fileName, Operation *op, const OpPrintingFlags &flags, StringRef tag)
This function generates new locations from the given IR by snapshotting the IR to the given stream...
MLIRContext * getContext()
Return the context this operation is associated with.
Definition: Operation.h:99
std::unique_ptr< Pass > createLocationSnapshotPass(OpPrintingFlags flags, StringRef fileName="", StringRef tag="")
Create a pass to generate new locations by snapshotting the IR to the given file, and using the print...
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:56
std::enable_if< llvm::function_traits< std::decay_t< FnT > >::num_args==1, RetT >::type walk(FnT &&callback)
Walk the operation by calling the callback for each nested operation (including this one)...
Definition: Operation.h:515
This class represents an efficient way to signal success or failure.
Definition: LogicalResult.h:26
std::unique_ptr< llvm::ToolOutputFile > openOutputFile(llvm::StringRef outputFilename, std::string *errorMessage=nullptr)
Open the file specified by its name for writing.
void generateLocationsFromIR(raw_ostream &os, StringRef fileName, Operation *op, OpPrintingFlags flags)
This function generates new locations from the given IR by snapshotting the IR to the given stream...
void print(raw_ostream &os, const OpPrintingFlags &flags=llvm::None)
Set of flags used to control the behavior of the various IR print methods (e.g.
This class is a general helper class for creating context-global objects like types, attributes, and affine expressions.
Definition: Builders.h:49
void setLoc(Location loc)
Set the source location the operation was defined or derived from.
Definition: Operation.h:109
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
Definition: Operation.cpp:231
This class provides management for the lifetime of the state used when printing the IR...
Definition: AsmState.h:36