MLIR  19.0.0git
Parser.h
Go to the documentation of this file.
1 //===- Parser.h - MLIR Parser Library Interface -----------------*- C++ -*-===//
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 // This file is contains a unified interface for parsing serialized MLIR.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef MLIR_PARSER_PARSER_H
14 #define MLIR_PARSER_PARSER_H
15 
16 #include "mlir/IR/AsmState.h"
17 #include "mlir/IR/Builders.h"
18 #include "mlir/IR/OwningOpRef.h"
19 #include <cstddef>
20 
21 namespace llvm {
22 class SourceMgr;
23 class SMDiagnostic;
24 class StringRef;
25 } // namespace llvm
26 
27 namespace mlir {
28 namespace detail {
29 
30 /// Given a block containing operations that have just been parsed, if the block
31 /// contains a single operation of `ContainerOpT` type then remove it from the
32 /// block and return it. If the block does not contain just that operation,
33 /// create a new operation instance of `ContainerOpT` and move all of the
34 /// operations within `parsedBlock` into the first block of the first region.
35 /// `ContainerOpT` is required to have a single region containing a single
36 /// block, and must implement the `SingleBlockImplicitTerminator` trait.
37 template <typename ContainerOpT>
39  Block *parsedBlock, MLIRContext *context, Location sourceFileLoc) {
40 
41  // Check to see if we parsed a single instance of this operation.
42  if (llvm::hasSingleElement(*parsedBlock)) {
43  if (ContainerOpT op = dyn_cast<ContainerOpT>(&parsedBlock->front())) {
44  op->remove();
45  return op;
46  }
47  }
48 
49  // If not, then build a new top-level op if a concrete operation type was
50  // specified.
51  if constexpr (std::is_same_v<ContainerOpT, Operation *>) {
52  (void)context;
53  return emitError(sourceFileLoc)
54  << "source must contain a single top-level operation, found: "
55  << parsedBlock->getOperations().size(),
56  nullptr;
57  } else {
58  static_assert(
59  ContainerOpT::template hasTrait<OpTrait::OneRegion>() &&
60  (ContainerOpT::template hasTrait<OpTrait::NoTerminator>() ||
61  OpTrait::template hasSingleBlockImplicitTerminator<
62  ContainerOpT>::value),
63  "Expected `ContainerOpT` to have a single region with a single "
64  "block that has an implicit terminator or does not require one");
65 
66  OpBuilder builder(context);
67  ContainerOpT op = builder.create<ContainerOpT>(sourceFileLoc);
68  OwningOpRef<ContainerOpT> opRef(op);
69  assert(op->getNumRegions() == 1 &&
70  llvm::hasSingleElement(op->getRegion(0)) &&
71  "expected generated operation to have a single region with a single "
72  "block");
73  Block *opBlock = &op->getRegion(0).front();
74  opBlock->getOperations().splice(opBlock->begin(),
75  parsedBlock->getOperations());
76 
77  // After splicing, verify just this operation to ensure it can properly
78  // contain the operations inside of it.
79  if (failed(op.verifyInvariants()))
81  return opRef;
82  }
83 }
84 } // namespace detail
85 
86 /// This parses the file specified by the indicated SourceMgr and appends parsed
87 /// operations to the given block. If the block is non-empty, the operations are
88 /// placed before the current terminator. If parsing is successful, success is
89 /// returned. Otherwise, an error message is emitted through the error handler
90 /// registered in the context, and failure is returned. If `sourceFileLoc` is
91 /// non-null, it is populated with a file location representing the start of the
92 /// source file that is being parsed.
93 LogicalResult parseSourceFile(const llvm::SourceMgr &sourceMgr, Block *block,
94  const ParserConfig &config,
95  LocationAttr *sourceFileLoc = nullptr);
96 /// An overload with a source manager that may have references taken during the
97 /// parsing process, and whose lifetime can be freely extended (such that the
98 /// source manager is not destroyed before the parsed IR). This is useful, for
99 /// example, to avoid copying some large resources into the MLIRContext and
100 /// instead referencing the data directly from the input buffers.
101 LogicalResult parseSourceFile(const std::shared_ptr<llvm::SourceMgr> &sourceMgr,
102  Block *block, const ParserConfig &config,
103  LocationAttr *sourceFileLoc = nullptr);
104 
105 /// This parses the file specified by the indicated filename and appends parsed
106 /// operations to the given block. If the block is non-empty, the operations are
107 /// placed before the current terminator. If parsing is successful, success is
108 /// returned. Otherwise, an error message is emitted through the error handler
109 /// registered in the context, and failure is returned. If `sourceFileLoc` is
110 /// non-null, it is populated with a file location representing the start of the
111 /// source file that is being parsed.
112 LogicalResult parseSourceFile(llvm::StringRef filename, Block *block,
113  const ParserConfig &config,
114  LocationAttr *sourceFileLoc = nullptr);
115 
116 /// This parses the file specified by the indicated filename using the provided
117 /// SourceMgr and appends parsed operations to the given block. If the block is
118 /// non-empty, the operations are placed before the current terminator. If
119 /// parsing is successful, success is returned. Otherwise, an error message is
120 /// emitted through the error handler registered in the context, and failure is
121 /// returned. If `sourceFileLoc` is non-null, it is populated with a file
122 /// location representing the start of the source file that is being parsed.
123 LogicalResult parseSourceFile(llvm::StringRef filename,
124  llvm::SourceMgr &sourceMgr, Block *block,
125  const ParserConfig &config,
126  LocationAttr *sourceFileLoc = nullptr);
127 /// An overload with a source manager that may have references taken during the
128 /// parsing process, and whose lifetime can be freely extended (such that the
129 /// source manager is not destroyed before the parsed IR). This is useful, for
130 /// example, to avoid copying some large resources into the MLIRContext and
131 /// instead referencing the data directly from the input buffers.
132 LogicalResult parseSourceFile(llvm::StringRef filename,
133  const std::shared_ptr<llvm::SourceMgr> &sourceMgr,
134  Block *block, const ParserConfig &config,
135  LocationAttr *sourceFileLoc = nullptr);
136 
137 /// This parses the IR string and appends parsed operations to the given block.
138 /// If the block is non-empty, the operations are placed before the current
139 /// terminator. If parsing is successful, success is returned. Otherwise, an
140 /// error message is emitted through the error handler registered in the
141 /// context, and failure is returned.
142 /// `sourceName` is used as the file name of the source; any IR without
143 /// locations will get a `FileLineColLoc` location with `sourceName` as the file
144 /// name. If `sourceFileLoc` is non-null, it is populated with a file location
145 /// representing the start of the source file that is being parsed.
146 LogicalResult parseSourceString(llvm::StringRef sourceStr, Block *block,
147  const ParserConfig &config,
148  StringRef sourceName = "",
149  LocationAttr *sourceFileLoc = nullptr);
150 
151 namespace detail {
152 /// The internal implementation of the templated `parseSourceFile` methods
153 /// below, that simply forwards to the non-templated version.
154 template <typename ContainerOpT, typename... ParserArgs>
156  ParserArgs &&...args) {
157  LocationAttr sourceFileLoc;
158  Block block;
159  if (failed(parseSourceFile(std::forward<ParserArgs>(args)..., &block, config,
160  &sourceFileLoc)))
161  return OwningOpRef<ContainerOpT>();
162  return detail::constructContainerOpForParserIfNecessary<ContainerOpT>(
163  &block, config.getContext(), sourceFileLoc);
164 }
165 } // namespace detail
166 
167 /// This parses the file specified by the indicated SourceMgr. If the source IR
168 /// contained a single instance of `ContainerOpT`, it is returned. Otherwise, a
169 /// new instance of `ContainerOpT` is constructed containing all of the parsed
170 /// operations. If parsing was not successful, null is returned and an error
171 /// message is emitted through the error handler registered in the context, and
172 /// failure is returned. `ContainerOpT` is required to have a single region
173 /// containing a single block, and must implement the
174 /// `SingleBlockImplicitTerminator` trait.
175 template <typename ContainerOpT = Operation *>
176 inline OwningOpRef<ContainerOpT>
177 parseSourceFile(const llvm::SourceMgr &sourceMgr, const ParserConfig &config) {
178  return detail::parseSourceFile<ContainerOpT>(config, sourceMgr);
179 }
180 /// An overload with a source manager that may have references taken during the
181 /// parsing process, and whose lifetime can be freely extended (such that the
182 /// source manager is not destroyed before the parsed IR). This is useful, for
183 /// example, to avoid copying some large resources into the MLIRContext and
184 /// instead referencing the data directly from the input buffers.
185 template <typename ContainerOpT = Operation *>
186 inline OwningOpRef<ContainerOpT>
187 parseSourceFile(const std::shared_ptr<llvm::SourceMgr> &sourceMgr,
188  const ParserConfig &config) {
189  return detail::parseSourceFile<ContainerOpT>(config, sourceMgr);
190 }
191 
192 /// This parses the file specified by the indicated filename. If the source IR
193 /// contained a single instance of `ContainerOpT`, it is returned. Otherwise, a
194 /// new instance of `ContainerOpT` is constructed containing all of the parsed
195 /// operations. If parsing was not successful, null is returned and an error
196 /// message is emitted through the error handler registered in the context, and
197 /// failure is returned. `ContainerOpT` is required to have a single region
198 /// containing a single block, and must implement the
199 /// `SingleBlockImplicitTerminator` trait.
200 template <typename ContainerOpT = Operation *>
201 inline OwningOpRef<ContainerOpT> parseSourceFile(StringRef filename,
202  const ParserConfig &config) {
203  return detail::parseSourceFile<ContainerOpT>(config, filename);
204 }
205 
206 /// This parses the file specified by the indicated filename using the provided
207 /// SourceMgr. If the source IR contained a single instance of `ContainerOpT`,
208 /// it is returned. Otherwise, a new instance of `ContainerOpT` is constructed
209 /// containing all of the parsed operations. If parsing was not successful, null
210 /// is returned and an error message is emitted through the error handler
211 /// registered in the context, and failure is returned. `ContainerOpT` is
212 /// required to have a single region containing a single block, and must
213 /// implement the `SingleBlockImplicitTerminator` trait.
214 template <typename ContainerOpT = Operation *>
215 inline OwningOpRef<ContainerOpT> parseSourceFile(llvm::StringRef filename,
216  llvm::SourceMgr &sourceMgr,
217  const ParserConfig &config) {
218  return detail::parseSourceFile<ContainerOpT>(config, filename, sourceMgr);
219 }
220 /// An overload with a source manager that may have references taken during the
221 /// parsing process, and whose lifetime can be freely extended (such that the
222 /// source manager is not destroyed before the parsed IR). This is useful, for
223 /// example, to avoid copying some large resources into the MLIRContext and
224 /// instead referencing the data directly from the input buffers.
225 template <typename ContainerOpT = Operation *>
226 inline OwningOpRef<ContainerOpT>
227 parseSourceFile(llvm::StringRef filename,
228  const std::shared_ptr<llvm::SourceMgr> &sourceMgr,
229  const ParserConfig &config) {
230  return detail::parseSourceFile<ContainerOpT>(config, filename, sourceMgr);
231 }
232 
233 /// This parses the provided string containing MLIR. If the source IR contained
234 /// a single instance of `ContainerOpT`, it is returned. Otherwise, a new
235 /// instance of `ContainerOpT` is constructed containing all of the parsed
236 /// operations. If parsing was not successful, null is returned and an error
237 /// message is emitted through the error handler registered in the context, and
238 /// failure is returned. `ContainerOpT` is required to have a single region
239 /// containing a single block, and must implement the
240 /// `SingleBlockImplicitTerminator` trait.
241 /// `sourceName` is used as the file name of the source; any IR without
242 /// locations will get a `FileLineColLoc` location with `sourceName` as the file
243 /// name.
244 template <typename ContainerOpT = Operation *>
245 inline OwningOpRef<ContainerOpT> parseSourceString(llvm::StringRef sourceStr,
246  const ParserConfig &config,
247  StringRef sourceName = "") {
248  LocationAttr sourceFileLoc;
249  Block block;
250  if (failed(parseSourceString(sourceStr, &block, config, sourceName,
251  &sourceFileLoc)))
252  return OwningOpRef<ContainerOpT>();
253  return detail::constructContainerOpForParserIfNecessary<ContainerOpT>(
254  &block, config.getContext(), sourceFileLoc);
255 }
256 
257 } // namespace mlir
258 
259 #endif // MLIR_PARSER_PARSER_H
Block represents an ordered list of Operations.
Definition: Block.h:30
OpListType & getOperations()
Definition: Block.h:134
Operation & front()
Definition: Block.h:150
iterator begin()
Definition: Block.h:140
Location objects represent source locations information in MLIR.
Definition: Location.h:31
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:63
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:60
This class helps build Operations.
Definition: Builders.h:209
Operation * create(const OperationState &state)
Creates an operation given the fields represented as an OperationState.
Definition: Builders.cpp:464
This class acts as an owning reference to an op, and will automatically destroy the held op on destru...
Definition: OwningOpRef.h:29
This class represents a configuration for the MLIR assembly parser.
Definition: AsmState.h:460
MLIRContext * getContext() const
Return the MLIRContext to be used when parsing.
Definition: AsmState.h:474
Include the generated interface declarations.
Definition: CallGraph.h:229
OwningOpRef< ContainerOpT > constructContainerOpForParserIfNecessary(Block *parsedBlock, MLIRContext *context, Location sourceFileLoc)
Given a block containing operations that have just been parsed, if the block contains a single operat...
Definition: Parser.h:38
OwningOpRef< ContainerOpT > parseSourceFile(const ParserConfig &config, ParserArgs &&...args)
The internal implementation of the templated parseSourceFile methods below, that simply forwards to t...
Definition: Parser.h:155
Include the generated interface declarations.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
LogicalResult parseSourceString(llvm::StringRef sourceStr, Block *block, const ParserConfig &config, StringRef sourceName="", LocationAttr *sourceFileLoc=nullptr)
This parses the IR string and appends parsed operations to the given block.
Definition: Parser.cpp:90
LogicalResult parseSourceFile(const llvm::SourceMgr &sourceMgr, Block *block, const ParserConfig &config, LocationAttr *sourceFileLoc=nullptr)
This parses the file specified by the indicated SourceMgr and appends parsed operations to the given ...
Definition: Parser.cpp:20
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value.
Definition: LogicalResult.h:72