1 //===- AsmParserState.h -----------------------------------------*- 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 #ifndef MLIR_ASMPARSER_ASMPARSERSTATE_H
10 #define MLIR_ASMPARSER_ASMPARSERSTATE_H
11 
12 #include "mlir/Support/LLVM.h"
13 #include "llvm/ADT/ArrayRef.h"
14 #include "llvm/ADT/SmallVector.h"
15 #include "llvm/Support/SMLoc.h"
16 #include <cstddef>
17 
18 namespace mlir {
19 class Block;
20 class BlockArgument;
21 class FileLineColLoc;
22 class Operation;
23 class OperationName;
24 class SymbolRefAttr;
25 class Value;
26 
27 /// This class represents state from a parsed MLIR textual format string. It is
28 /// useful for building additional analysis and language utilities on top of
29 /// textual MLIR. This should generally not be used for traditional compilation.
30 class AsmParserState {
31 public:
32   /// This class represents a definition within the source manager, containing
33   /// it's defining location and locations of any uses. SMDefinitions are only
34   /// provided for entities that have uses within an input file, e.g. SSA
35   /// values, Blocks, and Symbols.
36   struct SMDefinition {
37     SMDefinition() = default;
SMDefinitionSMDefinition38     SMDefinition(SMRange loc) : loc(loc) {}
39 
40     /// The source location of the definition.
41     SMRange loc;
42     /// The source location of all uses of the definition.
43     SmallVector<SMRange> uses;
44   };
45 
46   /// This class represents the information for an operation definition within
47   /// an input file.
48   struct OperationDefinition {
49     struct ResultGroupDefinition {
ResultGroupDefinitionOperationDefinition::ResultGroupDefinition50       ResultGroupDefinition(unsigned index, SMRange loc)
51           : startIndex(index), definition(loc) {}
52 
53       /// The result number that starts this group.
54       unsigned startIndex;
55       /// The source definition of the result group.
56       SMDefinition definition;
57     };
58 
OperationDefinitionOperationDefinition59     OperationDefinition(Operation *op, SMRange loc, SMLoc endLoc)
60         : op(op), loc(loc), scopeLoc(loc.Start, endLoc) {}
61 
62     /// The operation representing this definition.
63     Operation *op;
64 
65     /// The source location for the operation, i.e. the location of its name.
66     SMRange loc;
67 
68     /// The full source range of the operation definition, i.e. a range
69     /// encompassing the start and end of the full operation definition.
70     SMRange scopeLoc;
71 
72     /// Source definitions for any result groups of this operation.
73     SmallVector<ResultGroupDefinition> resultGroups;
74 
75     /// If this operation is a symbol operation, this vector contains symbol
76     /// uses of this operation.
77     SmallVector<SMRange> symbolUses;
78   };
79 
80   /// This class represents the information for a block definition within the
81   /// input file.
82   struct BlockDefinition {
83     BlockDefinition(Block *block, SMRange loc = {})
blockBlockDefinition84         : block(block), definition(loc) {}
85 
86     /// The block representing this definition.
87     Block *block;
88 
89     /// The source location for the block, i.e. the location of its name, and
90     /// any uses it has.
91     SMDefinition definition;
92 
93     /// Source definitions for any arguments of this block.
94     SmallVector<SMDefinition> arguments;
95   };
96 
97   AsmParserState();
98   ~AsmParserState();
99   AsmParserState &operator=(AsmParserState &&other);
100 
101   //===--------------------------------------------------------------------===//
102   // Access State
103   //===--------------------------------------------------------------------===//
104 
105   using BlockDefIterator = llvm::pointee_iterator<
106       ArrayRef<std::unique_ptr<BlockDefinition>>::iterator>;
107   using OperationDefIterator = llvm::pointee_iterator<
108       ArrayRef<std::unique_ptr<OperationDefinition>>::iterator>;
109 
110   /// Return a range of the BlockDefinitions held by the current parser state.
111   iterator_range<BlockDefIterator> getBlockDefs() const;
112 
113   /// Return the definition for the given block, or nullptr if the given
114   /// block does not have a definition.
115   const BlockDefinition *getBlockDef(Block *block) const;
116 
117   /// Return a range of the OperationDefinitions held by the current parser
118   /// state.
119   iterator_range<OperationDefIterator> getOpDefs() const;
120 
121   /// Return the definition for the given operation, or nullptr if the given
122   /// operation does not have a definition.
123   const OperationDefinition *getOpDef(Operation *op) const;
124 
125   /// Returns (heuristically) the range of an identifier given a SMLoc
126   /// corresponding to the start of an identifier location.
127   static SMRange convertIdLocToRange(SMLoc loc);
128 
129   //===--------------------------------------------------------------------===//
130   // Populate State
131   //===--------------------------------------------------------------------===//
132 
133   /// Initialize the state in preparation for populating more parser state under
134   /// the given top-level operation.
135   void initialize(Operation *topLevelOp);
136 
137   /// Finalize any in-progress parser state under the given top-level operation.
138   void finalize(Operation *topLevelOp);
139 
140   /// Start a definition for an operation with the given name.
141   void startOperationDefinition(const OperationName &opName);
142 
143   /// Finalize the most recently started operation definition.
144   void finalizeOperationDefinition(
145       Operation *op, SMRange nameLoc, SMLoc endLoc,
146       ArrayRef<std::pair<unsigned, SMLoc>> resultGroups = llvm::None);
147 
148   /// Start a definition for a region nested under the current operation.
149   void startRegionDefinition();
150 
151   /// Finalize the most recently started region definition.
152   void finalizeRegionDefinition();
153 
154   /// Add a definition of the given entity.
155   void addDefinition(Block *block, SMLoc location);
156   void addDefinition(BlockArgument blockArg, SMLoc location);
157 
158   /// Add a source uses of the given value.
159   void addUses(Value value, ArrayRef<SMLoc> locations);
160   void addUses(Block *block, ArrayRef<SMLoc> locations);
161 
162   /// Add source uses for all the references nested under `refAttr`. The
163   /// provided `locations` should match 1-1 with the number of references in
164   /// `refAttr`, i.e.:
165   ///   nestedReferences.size() + /*leafReference=*/1 == refLocations.size()
166   void addUses(SymbolRefAttr refAttr, ArrayRef<SMRange> refLocations);
167 
168   /// Refine the `oldValue` to the `newValue`. This is used to indicate that
169   /// `oldValue` was a placeholder, and the uses of it should really refer to
170   /// `newValue`.
171   void refineDefinition(Value oldValue, Value newValue);
172 
173 private:
174   struct Impl;
175 
176   /// A pointer to the internal implementation of this class.
177   std::unique_ptr<Impl> impl;
178 };
179 
180 } // namespace mlir
181 
182 #endif // MLIR_ASMPARSER_ASMPARSERSTATE_H
183