/home/arjun/llvm-project/mlir/include/mlir/IR/Module.h
Line | Count | Source (jump to first uncovered line) |
1 | | //===- Module.h - MLIR Module Class -----------------------------*- 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 | | // Module is the top-level container for code in an MLIR program. |
10 | | // |
11 | | //===----------------------------------------------------------------------===// |
12 | | |
13 | | #ifndef MLIR_IR_MODULE_H |
14 | | #define MLIR_IR_MODULE_H |
15 | | |
16 | | #include "mlir/IR/SymbolTable.h" |
17 | | #include "llvm/Support/PointerLikeTypeTraits.h" |
18 | | |
19 | | namespace mlir { |
20 | | class ModuleTerminatorOp; |
21 | | |
22 | | //===----------------------------------------------------------------------===// |
23 | | // Module Operation. |
24 | | //===----------------------------------------------------------------------===// |
25 | | |
26 | | /// ModuleOp represents a module, or an operation containing one region with a |
27 | | /// single block containing opaque operations. The region of a module is not |
28 | | /// allowed to implicitly capture global values, and all external references |
29 | | /// must use symbolic references via attributes(e.g. via a string name). |
30 | | class ModuleOp |
31 | | : public Op< |
32 | | ModuleOp, OpTrait::ZeroOperands, OpTrait::ZeroResult, |
33 | | OpTrait::IsIsolatedFromAbove, OpTrait::AffineScope, |
34 | | OpTrait::SymbolTable, |
35 | | OpTrait::SingleBlockImplicitTerminator<ModuleTerminatorOp>::Impl, |
36 | | SymbolOpInterface::Trait> { |
37 | | public: |
38 | | using Op::Op; |
39 | | using Op::print; |
40 | | |
41 | 0 | static StringRef getOperationName() { return "module"; } |
42 | | |
43 | | static void build(OpBuilder &builder, OperationState &result, |
44 | | Optional<StringRef> name = llvm::None); |
45 | | |
46 | | /// Construct a module from the given location with an optional name. |
47 | | static ModuleOp create(Location loc, Optional<StringRef> name = llvm::None); |
48 | | |
49 | | /// Operation hooks. |
50 | | static ParseResult parse(OpAsmParser &parser, OperationState &result); |
51 | | void print(OpAsmPrinter &p); |
52 | | LogicalResult verify(); |
53 | | |
54 | | /// Return body of this module. |
55 | | Region &getBodyRegion(); |
56 | | Block *getBody(); |
57 | | |
58 | | /// Return the name of this module if present. |
59 | | Optional<StringRef> getName(); |
60 | | |
61 | | /// Print the this module in the custom top-level form. |
62 | | void print(raw_ostream &os, OpPrintingFlags flags = llvm::None); |
63 | | void print(raw_ostream &os, AsmState &state, |
64 | | OpPrintingFlags flags = llvm::None); |
65 | | void dump(); |
66 | | |
67 | | //===--------------------------------------------------------------------===// |
68 | | // Body Management. |
69 | | //===--------------------------------------------------------------------===// |
70 | | |
71 | | /// Iteration over the operations in the module. |
72 | | using iterator = Block::iterator; |
73 | | |
74 | 0 | iterator begin() { return getBody()->begin(); } |
75 | 0 | iterator end() { return getBody()->end(); } |
76 | 0 | Operation &front() { return *begin(); } |
77 | | |
78 | | /// This returns a range of operations of the given type 'T' held within the |
79 | | /// module. |
80 | | template <typename T> iterator_range<Block::op_iterator<T>> getOps() { |
81 | | return getBody()->getOps<T>(); |
82 | | } |
83 | | |
84 | | /// Insert the operation into the back of the body, before the terminator. |
85 | 0 | void push_back(Operation *op) { |
86 | 0 | insert(Block::iterator(getBody()->getTerminator()), op); |
87 | 0 | } |
88 | | |
89 | | /// Insert the operation at the given insertion point. Note: The operation is |
90 | | /// never inserted after the terminator, even if the insertion point is end(). |
91 | 0 | void insert(Operation *insertPt, Operation *op) { |
92 | 0 | insert(Block::iterator(insertPt), op); |
93 | 0 | } |
94 | 0 | void insert(Block::iterator insertPt, Operation *op) { |
95 | 0 | auto *body = getBody(); |
96 | 0 | if (insertPt == body->end()) |
97 | 0 | insertPt = Block::iterator(body->getTerminator()); |
98 | 0 | body->getOperations().insert(insertPt, op); |
99 | 0 | } |
100 | | |
101 | | //===--------------------------------------------------------------------===// |
102 | | // SymbolOpInterface Methods |
103 | | //===--------------------------------------------------------------------===// |
104 | | |
105 | | /// A ModuleOp may optionally define a symbol. |
106 | 0 | bool isOptionalSymbol() { return true; } |
107 | | }; |
108 | | |
109 | | /// The ModuleTerminatorOp is a special terminator operation for the body of a |
110 | | /// ModuleOp, it has no semantic meaning beyond keeping the body of a ModuleOp |
111 | | /// well-formed. |
112 | | /// |
113 | | /// This operation does _not_ have a custom syntax. However, ModuleOp will omit |
114 | | /// the terminator in their custom syntax for brevity. |
115 | | class ModuleTerminatorOp |
116 | | : public Op<ModuleTerminatorOp, OpTrait::ZeroOperands, OpTrait::ZeroResult, |
117 | | OpTrait::HasParent<ModuleOp>::Impl, OpTrait::IsTerminator> { |
118 | | public: |
119 | | using Op::Op; |
120 | 0 | static StringRef getOperationName() { return "module_terminator"; } |
121 | 0 | static void build(OpBuilder &, OperationState &) {} |
122 | | }; |
123 | | |
124 | | /// This class acts as an owning reference to a module, and will automatically |
125 | | /// destroy the held module if valid. |
126 | | class OwningModuleRef { |
127 | | public: |
128 | 0 | OwningModuleRef(std::nullptr_t = nullptr) {} |
129 | 0 | OwningModuleRef(ModuleOp module) : module(module) {} |
130 | 0 | OwningModuleRef(OwningModuleRef &&other) : module(other.release()) {} |
131 | 0 | ~OwningModuleRef() { |
132 | 0 | if (module) |
133 | 0 | module.erase(); |
134 | 0 | } |
135 | | |
136 | | // Assign from another module reference. |
137 | 0 | OwningModuleRef &operator=(OwningModuleRef &&other) { |
138 | 0 | if (module) |
139 | 0 | module.erase(); |
140 | 0 | module = other.release(); |
141 | 0 | return *this; |
142 | 0 | } |
143 | | |
144 | | /// Allow accessing the internal module. |
145 | 0 | ModuleOp get() const { return module; } |
146 | 0 | ModuleOp operator*() const { return module; } |
147 | 0 | ModuleOp *operator->() { return &module; } |
148 | 0 | explicit operator bool() const { return module; } |
149 | | |
150 | | /// Release the referenced module. |
151 | 0 | ModuleOp release() { |
152 | 0 | ModuleOp released; |
153 | 0 | std::swap(released, module); |
154 | 0 | return released; |
155 | 0 | } |
156 | | |
157 | | private: |
158 | | ModuleOp module; |
159 | | }; |
160 | | |
161 | | } // end namespace mlir |
162 | | |
163 | | namespace llvm { |
164 | | |
165 | | /// Allow stealing the low bits of ModuleOp. |
166 | | template <> struct PointerLikeTypeTraits<mlir::ModuleOp> { |
167 | | public: |
168 | 0 | static inline void *getAsVoidPointer(mlir::ModuleOp I) { |
169 | 0 | return const_cast<void *>(I.getAsOpaquePointer()); |
170 | 0 | } |
171 | 0 | static inline mlir::ModuleOp getFromVoidPointer(void *P) { |
172 | 0 | return mlir::ModuleOp::getFromOpaquePointer(P); |
173 | 0 | } |
174 | | static constexpr int NumLowBitsAvailable = 3; |
175 | | }; |
176 | | |
177 | | } // end namespace llvm |
178 | | |
179 | | #endif // MLIR_IR_MODULE_H |