blob: 2f67c2722a927d6a96ea7ee5000c2679800ccf0f [file] [log] [blame]
Chris Lattner4c95a502018-06-23 16:03:42 -07001//===- AsmPrinter.cpp - MLIR Assembly Printer Implementation --------------===//
2//
3// Copyright 2019 The MLIR Authors.
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16// =============================================================================
17//
18// This file implements the MLIR AsmPrinter class, which is used to implement
19// the various print() methods on the core IR objects.
20//
21//===----------------------------------------------------------------------===//
22
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -070023#include "mlir/IR/AffineExpr.h"
24#include "mlir/IR/AffineMap.h"
Chris Lattner7121b802018-07-04 20:45:39 -070025#include "mlir/IR/Attributes.h"
Chris Lattner4c95a502018-06-23 16:03:42 -070026#include "mlir/IR/CFGFunction.h"
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -070027#include "mlir/IR/MLFunction.h"
Chris Lattner4c95a502018-06-23 16:03:42 -070028#include "mlir/IR/Module.h"
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -070029#include "mlir/IR/OpImplementation.h"
Chris Lattnerff0d5902018-07-05 09:12:11 -070030#include "mlir/IR/OperationSet.h"
Chris Lattnerd4964212018-08-01 10:43:18 -070031#include "mlir/IR/StandardOps.h"
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -070032#include "mlir/IR/Statements.h"
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -070033#include "mlir/IR/StmtVisitor.h"
Chris Lattner4c95a502018-06-23 16:03:42 -070034#include "mlir/IR/Types.h"
35#include "mlir/Support/STLExtras.h"
Chris Lattner4c95a502018-06-23 16:03:42 -070036#include "llvm/ADT/DenseMap.h"
Chris Lattnerd4964212018-08-01 10:43:18 -070037#include "llvm/ADT/SmallString.h"
38#include "llvm/ADT/StringExtras.h"
39#include "llvm/ADT/StringSet.h"
Chris Lattner4c95a502018-06-23 16:03:42 -070040using namespace mlir;
41
MLIR Team54b55a22018-07-18 10:16:05 -070042void Identifier::print(raw_ostream &os) const { os << str(); }
Chris Lattner4c95a502018-06-23 16:03:42 -070043
MLIR Team54b55a22018-07-18 10:16:05 -070044void Identifier::dump() const { print(llvm::errs()); }
Chris Lattner7121b802018-07-04 20:45:39 -070045
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -070046OpAsmPrinter::~OpAsmPrinter() {}
47
Chris Lattner4c95a502018-06-23 16:03:42 -070048//===----------------------------------------------------------------------===//
Chris Lattner4fd59b02018-07-20 09:35:47 -070049// ModuleState
MLIR Team4718bc92018-07-17 16:56:54 -070050//===----------------------------------------------------------------------===//
51
52namespace {
MLIR Team54b55a22018-07-18 10:16:05 -070053class ModuleState {
54public:
Chris Lattner4fd59b02018-07-20 09:35:47 -070055 /// This is the operation set for the current context if it is knowable (a
56 /// context could be determined), otherwise this is null.
57 OperationSet *const operationSet;
MLIR Team4718bc92018-07-17 16:56:54 -070058
Chris Lattner4fd59b02018-07-20 09:35:47 -070059 explicit ModuleState(MLIRContext *context)
60 : operationSet(context ? &OperationSet::get(context) : nullptr) {}
61
62 // Initializes module state, populating affine map state.
MLIR Team4718bc92018-07-17 16:56:54 -070063 void initialize(const Module *module);
64
MLIR Team54b55a22018-07-18 10:16:05 -070065 int getAffineMapId(const AffineMap *affineMap) const {
MLIR Team4718bc92018-07-17 16:56:54 -070066 auto it = affineMapIds.find(affineMap);
67 if (it == affineMapIds.end()) {
68 return -1;
69 }
70 return it->second;
71 }
72
James Molloyc4666722018-07-24 09:48:31 -070073 ArrayRef<const AffineMap *> getAffineMapIds() const { return affineMapsById; }
Chris Lattner4fd59b02018-07-20 09:35:47 -070074
MLIR Team54b55a22018-07-18 10:16:05 -070075private:
Chris Lattner4fd59b02018-07-20 09:35:47 -070076 void recordAffineMapReference(const AffineMap *affineMap) {
77 if (affineMapIds.count(affineMap) == 0) {
James Molloyc4666722018-07-24 09:48:31 -070078 affineMapIds[affineMap] = affineMapsById.size();
79 affineMapsById.push_back(affineMap);
Chris Lattner4fd59b02018-07-20 09:35:47 -070080 }
81 }
82
MLIR Team4718bc92018-07-17 16:56:54 -070083 // Visit functions.
84 void visitFunction(const Function *fn);
85 void visitExtFunction(const ExtFunction *fn);
86 void visitCFGFunction(const CFGFunction *fn);
87 void visitMLFunction(const MLFunction *fn);
88 void visitType(const Type *type);
MLIR Teamb61885d2018-07-18 16:29:21 -070089 void visitAttribute(const Attribute *attr);
90 void visitOperation(const Operation *op);
91
MLIR Team54b55a22018-07-18 10:16:05 -070092 DenseMap<const AffineMap *, int> affineMapIds;
James Molloyc4666722018-07-24 09:48:31 -070093 std::vector<const AffineMap *> affineMapsById;
MLIR Team4718bc92018-07-17 16:56:54 -070094};
James Molloy87d81022018-07-23 11:44:40 -070095} // end anonymous namespace
MLIR Team4718bc92018-07-17 16:56:54 -070096
97// TODO Support visiting other types/instructions when implemented.
98void ModuleState::visitType(const Type *type) {
Chris Lattner3164ae62018-07-28 09:36:25 -070099 if (auto *funcType = dyn_cast<FunctionType>(type)) {
MLIR Team4718bc92018-07-17 16:56:54 -0700100 // Visit input and result types for functions.
Chris Lattner3164ae62018-07-28 09:36:25 -0700101 for (auto *input : funcType->getInputs())
MLIR Team4718bc92018-07-17 16:56:54 -0700102 visitType(input);
Chris Lattner3164ae62018-07-28 09:36:25 -0700103 for (auto *result : funcType->getResults())
MLIR Team4718bc92018-07-17 16:56:54 -0700104 visitType(result);
Chris Lattner3164ae62018-07-28 09:36:25 -0700105 } else if (auto *memref = dyn_cast<MemRefType>(type)) {
MLIR Team4718bc92018-07-17 16:56:54 -0700106 // Visit affine maps in memref type.
Chris Lattner3164ae62018-07-28 09:36:25 -0700107 for (auto *map : memref->getAffineMaps()) {
MLIR Team4718bc92018-07-17 16:56:54 -0700108 recordAffineMapReference(map);
109 }
110 }
111}
112
MLIR Teamb61885d2018-07-18 16:29:21 -0700113void ModuleState::visitAttribute(const Attribute *attr) {
Chris Lattner3164ae62018-07-28 09:36:25 -0700114 if (auto *mapAttr = dyn_cast<AffineMapAttr>(attr)) {
115 recordAffineMapReference(mapAttr->getValue());
116 } else if (auto *array = dyn_cast<ArrayAttr>(attr)) {
117 for (auto elt : array->getValue()) {
MLIR Teamb61885d2018-07-18 16:29:21 -0700118 visitAttribute(elt);
119 }
120 }
121}
122
123void ModuleState::visitOperation(const Operation *op) {
Chris Lattnerca2ee872018-07-31 18:32:59 -0700124 // Visit all the types used in the operation.
125 for (auto *operand : op->getOperands())
126 visitType(operand->getType());
127 for (auto *result : op->getResults())
128 visitType(result->getType());
129
130 // Visit each of the attributes.
131 for (auto elt : op->getAttrs())
MLIR Teamb61885d2018-07-18 16:29:21 -0700132 visitAttribute(elt.second);
MLIR Teamb61885d2018-07-18 16:29:21 -0700133}
134
MLIR Team4718bc92018-07-17 16:56:54 -0700135void ModuleState::visitExtFunction(const ExtFunction *fn) {
136 visitType(fn->getType());
137}
138
139void ModuleState::visitCFGFunction(const CFGFunction *fn) {
140 visitType(fn->getType());
MLIR Teamb61885d2018-07-18 16:29:21 -0700141 for (auto &block : *fn) {
142 for (auto &op : block.getOperations()) {
143 visitOperation(&op);
144 }
145 }
MLIR Team4718bc92018-07-17 16:56:54 -0700146}
147
148void ModuleState::visitMLFunction(const MLFunction *fn) {
149 visitType(fn->getType());
MLIR Teamb61885d2018-07-18 16:29:21 -0700150 // TODO Visit function body statements (and attributes if required).
MLIR Team4718bc92018-07-17 16:56:54 -0700151}
152
153void ModuleState::visitFunction(const Function *fn) {
154 switch (fn->getKind()) {
MLIR Team54b55a22018-07-18 10:16:05 -0700155 case Function::Kind::ExtFunc:
156 return visitExtFunction(cast<ExtFunction>(fn));
157 case Function::Kind::CFGFunc:
158 return visitCFGFunction(cast<CFGFunction>(fn));
159 case Function::Kind::MLFunc:
160 return visitMLFunction(cast<MLFunction>(fn));
MLIR Team4718bc92018-07-17 16:56:54 -0700161 }
162}
163
Chris Lattner4fd59b02018-07-20 09:35:47 -0700164// Initializes module state, populating affine map state.
165void ModuleState::initialize(const Module *module) {
Chris Lattnera8e47672018-07-25 14:08:16 -0700166 for (auto &fn : *module) {
167 visitFunction(&fn);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700168 }
169}
170
171//===----------------------------------------------------------------------===//
172// ModulePrinter
173//===----------------------------------------------------------------------===//
174
175namespace {
176class ModulePrinter {
177public:
178 ModulePrinter(raw_ostream &os, ModuleState &state) : os(os), state(state) {}
179 explicit ModulePrinter(const ModulePrinter &printer)
180 : os(printer.os), state(printer.state) {}
181
182 template <typename Container, typename UnaryFunctor>
183 inline void interleaveComma(const Container &c, UnaryFunctor each_fn) const {
184 interleave(c.begin(), c.end(), each_fn, [&]() { os << ", "; });
185 }
186
187 void print(const Module *module);
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700188 void printAttribute(const Attribute *attr);
189 void printType(const Type *type);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700190 void print(const Function *fn);
191 void print(const ExtFunction *fn);
192 void print(const CFGFunction *fn);
193 void print(const MLFunction *fn);
194
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700195 void printAffineMap(const AffineMap *map);
196 void printAffineExpr(const AffineExpr *expr);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700197
198protected:
199 raw_ostream &os;
200 ModuleState &state;
201
202 void printFunctionSignature(const Function *fn);
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -0700203 void printFunctionResultType(const FunctionType *type);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700204 void printAffineMapId(int affineMapId) const;
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700205 void printAffineMapReference(const AffineMap *affineMap);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700206
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700207 /// This enum is used to represent the binding stength of the enclosing
208 /// context that an AffineExpr is being printed in, so we can intelligently
209 /// produce parens.
210 enum class BindingStrength {
211 Weak, // + and -
212 Strong, // All other binary operators.
213 };
214 void printAffineExprInternal(const AffineExpr *expr,
215 BindingStrength enclosingTightness);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700216};
217} // end anonymous namespace
218
MLIR Team4718bc92018-07-17 16:56:54 -0700219// Prints function with initialized module state.
Chris Lattner4fd59b02018-07-20 09:35:47 -0700220void ModulePrinter::print(const Function *fn) {
MLIR Team4718bc92018-07-17 16:56:54 -0700221 switch (fn->getKind()) {
MLIR Team54b55a22018-07-18 10:16:05 -0700222 case Function::Kind::ExtFunc:
223 return print(cast<ExtFunction>(fn));
224 case Function::Kind::CFGFunc:
225 return print(cast<CFGFunction>(fn));
226 case Function::Kind::MLFunc:
227 return print(cast<MLFunction>(fn));
MLIR Team4718bc92018-07-17 16:56:54 -0700228 }
229}
230
231// Prints affine map identifier.
Chris Lattner4fd59b02018-07-20 09:35:47 -0700232void ModulePrinter::printAffineMapId(int affineMapId) const {
MLIR Team4718bc92018-07-17 16:56:54 -0700233 os << "#map" << affineMapId;
234}
235
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700236void ModulePrinter::printAffineMapReference(const AffineMap *affineMap) {
Chris Lattner4fd59b02018-07-20 09:35:47 -0700237 int mapId = state.getAffineMapId(affineMap);
MLIR Teamb61885d2018-07-18 16:29:21 -0700238 if (mapId >= 0) {
239 // Map will be printed at top of module so print reference to its id.
240 printAffineMapId(mapId);
241 } else {
242 // Map not in module state so print inline.
243 affineMap->print(os);
244 }
245}
246
Chris Lattner4fd59b02018-07-20 09:35:47 -0700247void ModulePrinter::print(const Module *module) {
James Molloyc4666722018-07-24 09:48:31 -0700248 for (const auto &map : state.getAffineMapIds()) {
249 printAffineMapId(state.getAffineMapId(map));
MLIR Team4718bc92018-07-17 16:56:54 -0700250 os << " = ";
James Molloyc4666722018-07-24 09:48:31 -0700251 map->print(os);
MLIR Team4718bc92018-07-17 16:56:54 -0700252 os << '\n';
253 }
Chris Lattnera8e47672018-07-25 14:08:16 -0700254 for (auto const &fn : *module)
255 print(&fn);
MLIR Team4718bc92018-07-17 16:56:54 -0700256}
257
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700258void ModulePrinter::printAttribute(const Attribute *attr) {
MLIR Teamb61885d2018-07-18 16:29:21 -0700259 switch (attr->getKind()) {
260 case Attribute::Kind::Bool:
261 os << (cast<BoolAttr>(attr)->getValue() ? "true" : "false");
262 break;
263 case Attribute::Kind::Integer:
264 os << cast<IntegerAttr>(attr)->getValue();
265 break;
266 case Attribute::Kind::Float:
267 // FIXME: this isn't precise, we should print with a hex format.
268 os << cast<FloatAttr>(attr)->getValue();
269 break;
270 case Attribute::Kind::String:
271 // FIXME: should escape the string.
272 os << '"' << cast<StringAttr>(attr)->getValue() << '"';
273 break;
274 case Attribute::Kind::Array: {
275 auto elts = cast<ArrayAttr>(attr)->getValue();
276 os << '[';
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700277 interleaveComma(elts, [&](Attribute *attr) { printAttribute(attr); });
MLIR Teamb61885d2018-07-18 16:29:21 -0700278 os << ']';
279 break;
280 }
281 case Attribute::Kind::AffineMap:
282 printAffineMapReference(cast<AffineMapAttr>(attr)->getValue());
283 break;
James Molloyf0d2f442018-08-03 01:54:46 -0700284 case Attribute::Kind::Type:
285 printType(cast<TypeAttr>(attr)->getValue());
286 break;
MLIR Teamb61885d2018-07-18 16:29:21 -0700287 }
288}
289
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700290void ModulePrinter::printType(const Type *type) {
MLIR Team4718bc92018-07-17 16:56:54 -0700291 switch (type->getKind()) {
MLIR Team54b55a22018-07-18 10:16:05 -0700292 case Type::Kind::AffineInt:
293 os << "affineint";
294 return;
295 case Type::Kind::BF16:
296 os << "bf16";
297 return;
298 case Type::Kind::F16:
299 os << "f16";
300 return;
301 case Type::Kind::F32:
302 os << "f32";
303 return;
304 case Type::Kind::F64:
305 os << "f64";
306 return;
Jacques Pienaarc0d69302018-07-27 11:07:12 -0700307 case Type::Kind::TFControl:
308 os << "tf_control";
309 return;
James Molloy72b0cbe2018-08-01 12:55:27 -0700310 case Type::Kind::TFString:
311 os << "tf_string";
312 return;
MLIR Team4718bc92018-07-17 16:56:54 -0700313
314 case Type::Kind::Integer: {
315 auto *integer = cast<IntegerType>(type);
316 os << 'i' << integer->getWidth();
317 return;
318 }
319 case Type::Kind::Function: {
320 auto *func = cast<FunctionType>(type);
321 os << '(';
Chris Lattner413db6a2018-07-25 12:55:50 -0700322 interleaveComma(func->getInputs(), [&](Type *type) { printType(type); });
MLIR Team4718bc92018-07-17 16:56:54 -0700323 os << ") -> ";
324 auto results = func->getResults();
325 if (results.size() == 1)
326 os << *results[0];
327 else {
328 os << '(';
Chris Lattner413db6a2018-07-25 12:55:50 -0700329 interleaveComma(results, [&](Type *type) { printType(type); });
MLIR Team4718bc92018-07-17 16:56:54 -0700330 os << ')';
331 }
332 return;
333 }
334 case Type::Kind::Vector: {
335 auto *v = cast<VectorType>(type);
336 os << "vector<";
James Molloy87d81022018-07-23 11:44:40 -0700337 for (auto dim : v->getShape())
338 os << dim << 'x';
MLIR Team4718bc92018-07-17 16:56:54 -0700339 os << *v->getElementType() << '>';
340 return;
341 }
342 case Type::Kind::RankedTensor: {
343 auto *v = cast<RankedTensorType>(type);
344 os << "tensor<";
345 for (auto dim : v->getShape()) {
346 if (dim < 0)
347 os << '?';
348 else
349 os << dim;
350 os << 'x';
351 }
352 os << *v->getElementType() << '>';
353 return;
354 }
355 case Type::Kind::UnrankedTensor: {
356 auto *v = cast<UnrankedTensorType>(type);
Chris Lattner413db6a2018-07-25 12:55:50 -0700357 os << "tensor<??";
358 printType(v->getElementType());
359 os << '>';
MLIR Team4718bc92018-07-17 16:56:54 -0700360 return;
361 }
362 case Type::Kind::MemRef: {
363 auto *v = cast<MemRefType>(type);
364 os << "memref<";
365 for (auto dim : v->getShape()) {
366 if (dim < 0)
367 os << '?';
368 else
369 os << dim;
370 os << 'x';
371 }
Chris Lattner413db6a2018-07-25 12:55:50 -0700372 printType(v->getElementType());
MLIR Team4718bc92018-07-17 16:56:54 -0700373 for (auto map : v->getAffineMaps()) {
374 os << ", ";
MLIR Teamb61885d2018-07-18 16:29:21 -0700375 printAffineMapReference(map);
MLIR Team4718bc92018-07-17 16:56:54 -0700376 }
Chris Lattner413db6a2018-07-25 12:55:50 -0700377 // Only print the memory space if it is the non-default one.
378 if (v->getMemorySpace())
379 os << ", " << v->getMemorySpace();
MLIR Team4718bc92018-07-17 16:56:54 -0700380 os << '>';
381 return;
382 }
383 }
384}
385
386//===----------------------------------------------------------------------===//
Chris Lattner4fd59b02018-07-20 09:35:47 -0700387// Affine expressions and maps
388//===----------------------------------------------------------------------===//
389
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700390void ModulePrinter::printAffineExpr(const AffineExpr *expr) {
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700391 printAffineExprInternal(expr, BindingStrength::Weak);
392}
393
394void ModulePrinter::printAffineExprInternal(
395 const AffineExpr *expr, BindingStrength enclosingTightness) {
396 const char *binopSpelling = nullptr;
Chris Lattner4fd59b02018-07-20 09:35:47 -0700397 switch (expr->getKind()) {
398 case AffineExpr::Kind::SymbolId:
399 os << 's' << cast<AffineSymbolExpr>(expr)->getPosition();
400 return;
401 case AffineExpr::Kind::DimId:
402 os << 'd' << cast<AffineDimExpr>(expr)->getPosition();
403 return;
404 case AffineExpr::Kind::Constant:
405 os << cast<AffineConstantExpr>(expr)->getValue();
406 return;
407 case AffineExpr::Kind::Add:
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700408 binopSpelling = " + ";
409 break;
Chris Lattner4fd59b02018-07-20 09:35:47 -0700410 case AffineExpr::Kind::Mul:
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700411 binopSpelling = " * ";
412 break;
Chris Lattner4fd59b02018-07-20 09:35:47 -0700413 case AffineExpr::Kind::FloorDiv:
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700414 binopSpelling = " floordiv ";
415 break;
Chris Lattner4fd59b02018-07-20 09:35:47 -0700416 case AffineExpr::Kind::CeilDiv:
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700417 binopSpelling = " ceildiv ";
418 break;
Chris Lattner4fd59b02018-07-20 09:35:47 -0700419 case AffineExpr::Kind::Mod:
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700420 binopSpelling = " mod ";
421 break;
Chris Lattner4fd59b02018-07-20 09:35:47 -0700422 }
Chris Lattner4fd59b02018-07-20 09:35:47 -0700423
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700424 auto *binOp = cast<AffineBinaryOpExpr>(expr);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700425
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700426 // Handle tightly binding binary operators.
427 if (binOp->getKind() != AffineExpr::Kind::Add) {
428 if (enclosingTightness == BindingStrength::Strong)
429 os << '(';
430
431 printAffineExprInternal(binOp->getLHS(), BindingStrength::Strong);
432 os << binopSpelling;
433 printAffineExprInternal(binOp->getRHS(), BindingStrength::Strong);
434
435 if (enclosingTightness == BindingStrength::Strong)
436 os << ')';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700437 return;
438 }
439
440 // Print out special "pretty" forms for add.
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700441 if (enclosingTightness == BindingStrength::Strong)
442 os << '(';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700443
444 // Pretty print addition to a product that has a negative operand as a
445 // subtraction.
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700446 if (auto *rhs = dyn_cast<AffineBinaryOpExpr>(binOp->getRHS())) {
Chris Lattner4fd59b02018-07-20 09:35:47 -0700447 if (rhs->getKind() == AffineExpr::Kind::Mul) {
448 if (auto *rrhs = dyn_cast<AffineConstantExpr>(rhs->getRHS())) {
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700449 if (rrhs->getValue() == -1) {
450 printAffineExprInternal(binOp->getLHS(), BindingStrength::Weak);
451 os << " - ";
452 printAffineExprInternal(rhs->getLHS(), BindingStrength::Weak);
453
454 if (enclosingTightness == BindingStrength::Strong)
455 os << ')';
456 return;
457 }
458
459 if (rrhs->getValue() < -1) {
460 printAffineExprInternal(binOp->getLHS(), BindingStrength::Weak);
Uday Bondhugula970f5b82018-08-01 22:02:00 -0700461 os << " - ";
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700462 printAffineExprInternal(rhs->getLHS(), BindingStrength::Strong);
Uday Bondhugula970f5b82018-08-01 22:02:00 -0700463 os << " * " << -rrhs->getValue();
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700464 if (enclosingTightness == BindingStrength::Strong)
465 os << ')';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700466 return;
467 }
468 }
469 }
470 }
471
472 // Pretty print addition to a negative number as a subtraction.
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700473 if (auto *rhs = dyn_cast<AffineConstantExpr>(binOp->getRHS())) {
Chris Lattner4fd59b02018-07-20 09:35:47 -0700474 if (rhs->getValue() < 0) {
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700475 printAffineExprInternal(binOp->getLHS(), BindingStrength::Weak);
476 os << " - " << -rhs->getValue() << ')';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700477 return;
478 }
479 }
480
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700481 printAffineExprInternal(binOp->getLHS(), BindingStrength::Weak);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700482 os << " + ";
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700483 printAffineExprInternal(binOp->getRHS(), BindingStrength::Weak);
484
485 if (enclosingTightness == BindingStrength::Strong)
486 os << ')';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700487}
488
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700489void ModulePrinter::printAffineMap(const AffineMap *map) {
Chris Lattner4fd59b02018-07-20 09:35:47 -0700490 // Dimension identifiers.
491 os << '(';
Chris Lattnerdc3ba382018-07-29 14:13:03 -0700492 for (int i = 0; i < (int)map->getNumDims() - 1; ++i)
493 os << 'd' << i << ", ";
Chris Lattner4fd59b02018-07-20 09:35:47 -0700494 if (map->getNumDims() >= 1)
Chris Lattnerdc3ba382018-07-29 14:13:03 -0700495 os << 'd' << map->getNumDims() - 1;
496 os << ')';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700497
498 // Symbolic identifiers.
Chris Lattnerdc3ba382018-07-29 14:13:03 -0700499 if (map->getNumSymbols() != 0) {
500 os << '[';
501 for (unsigned i = 0; i < map->getNumSymbols() - 1; ++i)
502 os << 's' << i << ", ";
Chris Lattner4fd59b02018-07-20 09:35:47 -0700503 if (map->getNumSymbols() >= 1)
Chris Lattnerdc3ba382018-07-29 14:13:03 -0700504 os << 's' << map->getNumSymbols() - 1;
505 os << ']';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700506 }
507
508 // AffineMap should have at least one result.
509 assert(!map->getResults().empty());
510 // Result affine expressions.
511 os << " -> (";
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700512 interleaveComma(map->getResults(),
513 [&](AffineExpr *expr) { printAffineExpr(expr); });
Chris Lattnerdc3ba382018-07-29 14:13:03 -0700514 os << ')';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700515
516 if (!map->isBounded()) {
517 return;
518 }
519
520 // Print range sizes for bounded affine maps.
521 os << " size (";
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700522 interleaveComma(map->getRangeSizes(),
523 [&](AffineExpr *expr) { printAffineExpr(expr); });
Chris Lattnerdc3ba382018-07-29 14:13:03 -0700524 os << ')';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700525}
526
527//===----------------------------------------------------------------------===//
Chris Lattner4c95a502018-06-23 16:03:42 -0700528// Function printing
529//===----------------------------------------------------------------------===//
530
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -0700531void ModulePrinter::printFunctionResultType(const FunctionType *type) {
Chris Lattner4c95a502018-06-23 16:03:42 -0700532 switch (type->getResults().size()) {
MLIR Team54b55a22018-07-18 10:16:05 -0700533 case 0:
534 break;
Chris Lattner4c95a502018-06-23 16:03:42 -0700535 case 1:
MLIR Team4718bc92018-07-17 16:56:54 -0700536 os << " -> ";
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700537 printType(type->getResults()[0]);
Chris Lattner4c95a502018-06-23 16:03:42 -0700538 break;
539 default:
540 os << " -> (";
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700541 interleaveComma(type->getResults(),
542 [&](Type *eltType) { printType(eltType); });
Chris Lattner4c95a502018-06-23 16:03:42 -0700543 os << ')';
544 break;
545 }
546}
547
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -0700548void ModulePrinter::printFunctionSignature(const Function *fn) {
549 auto type = fn->getType();
550
551 os << "@" << fn->getName() << '(';
552 interleaveComma(type->getInputs(),
553 [&](Type *eltType) { printType(eltType); });
554 os << ')';
555
556 printFunctionResultType(type);
557}
558
Chris Lattner4fd59b02018-07-20 09:35:47 -0700559void ModulePrinter::print(const ExtFunction *fn) {
Chris Lattner4c95a502018-06-23 16:03:42 -0700560 os << "extfunc ";
Chris Lattner4fd59b02018-07-20 09:35:47 -0700561 printFunctionSignature(fn);
MLIR Team54b55a22018-07-18 10:16:05 -0700562 os << '\n';
Chris Lattner4c95a502018-06-23 16:03:42 -0700563}
564
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700565namespace {
566
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700567// FunctionPrinter contains common functionality for printing
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700568// CFG and ML functions.
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700569class FunctionPrinter : public ModulePrinter, private OpAsmPrinter {
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700570public:
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700571 FunctionPrinter(const ModulePrinter &other) : ModulePrinter(other) {}
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700572
573 void printOperation(const Operation *op);
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700574 void printDefaultOp(const Operation *op);
575
576 // Implement OpAsmPrinter.
577 raw_ostream &getStream() const { return os; }
578 void printType(const Type *type) { ModulePrinter::printType(type); }
579 void printAttribute(const Attribute *attr) {
580 ModulePrinter::printAttribute(attr);
581 }
582 void printAffineMap(const AffineMap *map) {
Chris Lattner3164ae62018-07-28 09:36:25 -0700583 return ModulePrinter::printAffineMapReference(map);
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700584 }
585 void printAffineExpr(const AffineExpr *expr) {
586 return ModulePrinter::printAffineExpr(expr);
587 }
588
589 void printOperand(const SSAValue *value) { printValueID(value); }
Tatiana Shpeismanc335d182018-08-03 11:12:34 -0700590
Chris Lattner85cf26d2018-08-02 16:54:36 -0700591 void printOptionalAttrDict(ArrayRef<NamedAttribute> attrs,
592 ArrayRef<const char *> elidedAttrs = {}) override;
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700593
Chris Lattnerd4964212018-08-01 10:43:18 -0700594 enum { nameSentinel = ~0U };
595
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700596protected:
Chris Lattnerf8cce872018-07-20 09:28:54 -0700597 void numberValueID(const SSAValue *value) {
598 assert(!valueIDs.count(value) && "Value numbered multiple times");
Chris Lattnerd4964212018-08-01 10:43:18 -0700599
600 SmallString<32> specialNameBuffer;
601 llvm::raw_svector_ostream specialName(specialNameBuffer);
602
603 // Give constant integers special names.
604 if (auto *op = value->getDefiningOperation()) {
605 if (auto intOp = op->getAs<ConstantIntOp>()) {
Chris Lattner384da8c2018-08-02 17:16:58 -0700606 // i1 constants get special names.
607 if (intOp->getType()->isInteger(1)) {
608 specialName << (intOp->getValue() ? "true" : "false");
609 } else {
Chris Lattner992a1272018-08-07 12:02:37 -0700610 specialName << 'c' << intOp->getValue() << '_' << *intOp->getType();
Chris Lattner384da8c2018-08-02 17:16:58 -0700611 }
Chris Lattner992a1272018-08-07 12:02:37 -0700612 } else if (auto intOp = op->getAs<ConstantAffineIntOp>()) {
613 specialName << 'c' << intOp->getValue();
Chris Lattnerd4964212018-08-01 10:43:18 -0700614 }
Tatiana Shpeisman3838db72018-07-30 15:18:10 -0700615 }
Chris Lattnerd4964212018-08-01 10:43:18 -0700616
617 if (specialNameBuffer.empty()) {
618 switch (value->getKind()) {
619 case SSAValueKind::BBArgument:
620 // If this is an argument to the function, give it an 'arg' name.
621 if (auto *bb = cast<BBArgument>(value)->getOwner())
622 if (auto *fn = bb->getFunction())
623 if (&fn->front() == bb) {
624 specialName << "arg" << nextArgumentID++;
625 break;
626 }
627 // Otherwise number it normally.
628 LLVM_FALLTHROUGH;
629 case SSAValueKind::InstResult:
630 case SSAValueKind::StmtResult:
631 // This is an uninteresting result, give it a boring number and be
632 // done with it.
633 valueIDs[value] = nextValueID++;
634 return;
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -0700635 case SSAValueKind::MLFuncArgument:
Chris Lattnerd4964212018-08-01 10:43:18 -0700636 specialName << "arg" << nextArgumentID++;
637 break;
638 case SSAValueKind::ForStmt:
639 specialName << 'i' << nextLoopID++;
640 break;
641 }
642 }
643
644 // Ok, this value had an interesting name. Remember it with a sentinel.
645 valueIDs[value] = nameSentinel;
646
647 // Remember that we've used this name, checking to see if we had a conflict.
648 auto insertRes = usedNames.insert(specialName.str());
649 if (insertRes.second) {
650 // If this is the first use of the name, then we're successful!
651 valueNames[value] = insertRes.first->first();
652 return;
653 }
654
655 // Otherwise, we had a conflict - probe until we find a unique name. This
656 // is guaranteed to terminate (and usually in a single iteration) because it
657 // generates new names by incrementing nextConflictID.
658 while (1) {
659 std::string probeName =
660 specialName.str().str() + "_" + llvm::utostr(nextConflictID++);
661 insertRes = usedNames.insert(probeName);
662 if (insertRes.second) {
663 // If this is the first use of the name, then we're successful!
664 valueNames[value] = insertRes.first->first();
665 return;
666 }
667 }
Chris Lattnerf8cce872018-07-20 09:28:54 -0700668 }
669
Tatiana Shpeisman3838db72018-07-30 15:18:10 -0700670 void printValueID(const SSAValue *value, bool printResultNo = true) const {
Chris Lattner6119d382018-07-20 18:41:34 -0700671 int resultNo = -1;
672 auto lookupValue = value;
673
Tatiana Shpeisman3838db72018-07-30 15:18:10 -0700674 // If this is a reference to the result of a multi-result instruction or
675 // statement, print out the # identifier and make sure to map our lookup
676 // to the first result of the instruction.
Chris Lattner6119d382018-07-20 18:41:34 -0700677 if (auto *result = dyn_cast<InstResult>(value)) {
678 if (result->getOwner()->getNumResults() != 1) {
679 resultNo = result->getResultNumber();
680 lookupValue = result->getOwner()->getResult(0);
681 }
Tatiana Shpeisman3838db72018-07-30 15:18:10 -0700682 } else if (auto *result = dyn_cast<StmtResult>(value)) {
683 if (result->getOwner()->getNumResults() != 1) {
684 resultNo = result->getResultNumber();
685 lookupValue = result->getOwner()->getResult(0);
686 }
Chris Lattner6119d382018-07-20 18:41:34 -0700687 }
688
689 auto it = valueIDs.find(lookupValue);
690 if (it == valueIDs.end()) {
Chris Lattnerf8cce872018-07-20 09:28:54 -0700691 os << "<<INVALID SSA VALUE>>";
Chris Lattner6119d382018-07-20 18:41:34 -0700692 return;
693 }
694
Tatiana Shpeisman3838db72018-07-30 15:18:10 -0700695 os << '%';
Chris Lattnerd4964212018-08-01 10:43:18 -0700696 if (it->second != nameSentinel) {
697 os << it->second;
698 } else {
699 auto nameIt = valueNames.find(lookupValue);
700 assert(nameIt != valueNames.end() && "Didn't have a name entry?");
701 os << nameIt->second;
702 }
Tatiana Shpeisman3838db72018-07-30 15:18:10 -0700703
Tatiana Shpeisman3838db72018-07-30 15:18:10 -0700704 if (resultNo != -1 && printResultNo)
Chris Lattner6119d382018-07-20 18:41:34 -0700705 os << '#' << resultNo;
Chris Lattnerf8cce872018-07-20 09:28:54 -0700706 }
707
708private:
Chris Lattnerd4964212018-08-01 10:43:18 -0700709 /// This is the value ID for each SSA value in the current function. If this
710 /// returns ~0, then the valueID has an entry in valueNames.
Chris Lattnerf8cce872018-07-20 09:28:54 -0700711 DenseMap<const SSAValue *, unsigned> valueIDs;
Chris Lattnerd4964212018-08-01 10:43:18 -0700712 DenseMap<const SSAValue *, StringRef> valueNames;
713
714 /// This keeps track of all of the non-numeric names that are in flight,
715 /// allowing us to check for duplicates.
716 llvm::StringSet<> usedNames;
717
718 /// This is the next value ID to assign in numbering.
Chris Lattnerf8cce872018-07-20 09:28:54 -0700719 unsigned nextValueID = 0;
Chris Lattnerd4964212018-08-01 10:43:18 -0700720 /// This is the ID to assign to the next induction variable.
Tatiana Shpeismanc9c4b342018-07-31 07:40:14 -0700721 unsigned nextLoopID = 0;
Chris Lattnerd4964212018-08-01 10:43:18 -0700722 /// This is the next ID to assign to an MLFunction argument.
723 unsigned nextArgumentID = 0;
724
725 /// This is the next ID to assign when a name conflict is detected.
726 unsigned nextConflictID = 0;
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700727};
James Molloy87d81022018-07-23 11:44:40 -0700728} // end anonymous namespace
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700729
Chris Lattner85cf26d2018-08-02 16:54:36 -0700730void FunctionPrinter::printOptionalAttrDict(
731 ArrayRef<NamedAttribute> attrs, ArrayRef<const char *> elidedAttrs) {
732 // If there are no attributes, then there is nothing to be done.
733 if (attrs.empty())
734 return;
735
736 // Filter out any attributes that shouldn't be included.
737 SmallVector<NamedAttribute, 8> filteredAttrs;
738 for (auto attr : attrs) {
739 auto attrName = attr.first.str();
740 // Never print attributes that start with a colon. These are internal
741 // attributes that represent location or other internal metadata.
742 if (attrName.startswith(":"))
743 continue;
744
745 // If the caller has requested that this attribute be ignored, then drop it.
746 bool ignore = false;
747 for (const char *elide : elidedAttrs)
748 ignore |= attrName == StringRef(elide);
749
750 // Otherwise add it to our filteredAttrs list.
751 if (!ignore)
752 filteredAttrs.push_back(attr);
753 }
754
755 // If there are no attributes left to print after filtering, then we're done.
756 if (filteredAttrs.empty())
757 return;
758
759 // Otherwise, print them all out in braces.
760 os << " {";
761 interleaveComma(filteredAttrs, [&](NamedAttribute attr) {
762 os << attr.first << ": ";
763 printAttribute(attr.second);
764 });
765 os << '}';
766}
767
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700768void FunctionPrinter::printOperation(const Operation *op) {
Chris Lattnerac591f12018-07-22 21:02:26 -0700769 if (op->getNumResults()) {
Tatiana Shpeisman3838db72018-07-30 15:18:10 -0700770 printValueID(op->getResult(0), /*printResultNo=*/false);
Chris Lattnerac591f12018-07-22 21:02:26 -0700771 os << " = ";
Chris Lattnerf8cce872018-07-20 09:28:54 -0700772 }
773
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700774 // Check to see if this is a known operation. If so, use the registered
775 // custom printer hook.
Chris Lattner4fd59b02018-07-20 09:35:47 -0700776 if (auto opInfo = state.operationSet->lookup(op->getName().str())) {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700777 opInfo->printAssembly(op, this);
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700778 return;
779 }
780
Chris Lattnerf8cce872018-07-20 09:28:54 -0700781 // Otherwise use the standard verbose printing approach.
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700782 printDefaultOp(op);
783}
Chris Lattnerf8cce872018-07-20 09:28:54 -0700784
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700785void FunctionPrinter::printDefaultOp(const Operation *op) {
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700786 // TODO: escape name if necessary.
Chris Lattnerf8cce872018-07-20 09:28:54 -0700787 os << "\"" << op->getName().str() << "\"(";
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700788
Chris Lattnerac591f12018-07-22 21:02:26 -0700789 interleaveComma(op->getOperands(),
790 [&](const SSAValue *value) { printValueID(value); });
Chris Lattner7f9cc272018-07-19 08:35:28 -0700791
Chris Lattnerf8cce872018-07-20 09:28:54 -0700792 os << ')';
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700793 auto attrs = op->getAttrs();
Chris Lattner85cf26d2018-08-02 16:54:36 -0700794 printOptionalAttrDict(attrs);
Chris Lattner3b2ef762018-07-18 15:31:25 -0700795
Chris Lattnerac591f12018-07-22 21:02:26 -0700796 // Print the type signature of the operation.
797 os << " : (";
798 interleaveComma(op->getOperands(),
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700799 [&](const SSAValue *value) { printType(value->getType()); });
Chris Lattnerac591f12018-07-22 21:02:26 -0700800 os << ") -> ";
Chris Lattnerf8cce872018-07-20 09:28:54 -0700801
Chris Lattnerac591f12018-07-22 21:02:26 -0700802 if (op->getNumResults() == 1) {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700803 printType(op->getResult(0)->getType());
Chris Lattnerac591f12018-07-22 21:02:26 -0700804 } else {
805 os << '(';
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700806 interleaveComma(op->getResults(), [&](const SSAValue *result) {
807 printType(result->getType());
808 });
Chris Lattnerac591f12018-07-22 21:02:26 -0700809 os << ')';
Chris Lattnerf8cce872018-07-20 09:28:54 -0700810 }
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700811}
812
Chris Lattner4c95a502018-06-23 16:03:42 -0700813//===----------------------------------------------------------------------===//
814// CFG Function printing
815//===----------------------------------------------------------------------===//
816
817namespace {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700818class CFGFunctionPrinter : public FunctionPrinter {
Chris Lattner4c95a502018-06-23 16:03:42 -0700819public:
Chris Lattner4fd59b02018-07-20 09:35:47 -0700820 CFGFunctionPrinter(const CFGFunction *function, const ModulePrinter &other);
Chris Lattner4c95a502018-06-23 16:03:42 -0700821
822 const CFGFunction *getFunction() const { return function; }
823
824 void print();
825 void print(const BasicBlock *block);
Chris Lattnered65a732018-06-28 20:45:33 -0700826
827 void print(const Instruction *inst);
828 void print(const OperationInst *inst);
829 void print(const ReturnInst *inst);
830 void print(const BranchInst *inst);
James Molloy4f788372018-07-24 15:01:27 -0700831 void print(const CondBranchInst *inst);
Chris Lattner4c95a502018-06-23 16:03:42 -0700832
833 unsigned getBBID(const BasicBlock *block) {
834 auto it = basicBlockIDs.find(block);
835 assert(it != basicBlockIDs.end() && "Block not in this function?");
836 return it->second;
837 }
838
839private:
840 const CFGFunction *function;
MLIR Team54b55a22018-07-18 10:16:05 -0700841 DenseMap<const BasicBlock *, unsigned> basicBlockIDs;
Chris Lattnerf8cce872018-07-20 09:28:54 -0700842
Chris Lattner4fd59b02018-07-20 09:35:47 -0700843 void numberValuesInBlock(const BasicBlock *block);
Chris Lattner4c95a502018-06-23 16:03:42 -0700844};
James Molloy87d81022018-07-23 11:44:40 -0700845} // end anonymous namespace
Chris Lattner4c95a502018-06-23 16:03:42 -0700846
Chris Lattner4fd59b02018-07-20 09:35:47 -0700847CFGFunctionPrinter::CFGFunctionPrinter(const CFGFunction *function,
848 const ModulePrinter &other)
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700849 : FunctionPrinter(other), function(function) {
Chris Lattner4c95a502018-06-23 16:03:42 -0700850 // Each basic block gets a unique ID per function.
851 unsigned blockID = 0;
Chris Lattnerf8cce872018-07-20 09:28:54 -0700852 for (auto &block : *function) {
853 basicBlockIDs[&block] = blockID++;
Chris Lattner4fd59b02018-07-20 09:35:47 -0700854 numberValuesInBlock(&block);
Chris Lattnerf8cce872018-07-20 09:28:54 -0700855 }
856}
857
858/// Number all of the SSA values in the specified basic block.
Chris Lattner4fd59b02018-07-20 09:35:47 -0700859void CFGFunctionPrinter::numberValuesInBlock(const BasicBlock *block) {
James Molloy61a656c2018-07-22 15:45:24 -0700860 for (auto *arg : block->getArguments()) {
861 numberValueID(arg);
862 }
Chris Lattnerf8cce872018-07-20 09:28:54 -0700863 for (auto &op : *block) {
864 // We number instruction that have results, and we only number the first
865 // result.
866 if (op.getNumResults() != 0)
867 numberValueID(op.getResult(0));
868 }
869
870 // Terminators do not define values.
Chris Lattner4c95a502018-06-23 16:03:42 -0700871}
872
Chris Lattner4fd59b02018-07-20 09:35:47 -0700873void CFGFunctionPrinter::print() {
Chris Lattner4c95a502018-06-23 16:03:42 -0700874 os << "cfgfunc ";
Chris Lattner4fd59b02018-07-20 09:35:47 -0700875 printFunctionSignature(getFunction());
Chris Lattner4c95a502018-06-23 16:03:42 -0700876 os << " {\n";
877
James Molloy87d81022018-07-23 11:44:40 -0700878 for (auto &block : *function)
879 print(&block);
Chris Lattner4c95a502018-06-23 16:03:42 -0700880 os << "}\n\n";
881}
882
Chris Lattner4fd59b02018-07-20 09:35:47 -0700883void CFGFunctionPrinter::print(const BasicBlock *block) {
James Molloy61a656c2018-07-22 15:45:24 -0700884 os << "bb" << getBBID(block);
Chris Lattner4c95a502018-06-23 16:03:42 -0700885
James Molloy61a656c2018-07-22 15:45:24 -0700886 if (!block->args_empty()) {
887 os << '(';
888 interleaveComma(block->getArguments(), [&](const BBArgument *arg) {
889 printValueID(arg);
890 os << ": ";
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700891 printType(arg->getType());
James Molloy61a656c2018-07-22 15:45:24 -0700892 });
893 os << ')';
894 }
Chris Lattner25ce3062018-07-27 11:10:12 -0700895 os << ':';
896
897 // Print out some context information about the predecessors of this block.
898 if (!block->getFunction()) {
899 os << "\t// block is not in a function!";
900 } else if (block->hasNoPredecessors()) {
901 // Don't print "no predecessors" for the entry block.
902 if (block != &block->getFunction()->front())
903 os << "\t// no predecessors";
904 } else if (auto *pred = block->getSinglePredecessor()) {
905 os << "\t// pred: bb" << getBBID(pred);
906 } else {
907 // We want to print the predecessors in increasing numeric order, not in
908 // whatever order the use-list is in, so gather and sort them.
909 SmallVector<unsigned, 4> predIDs;
910 for (auto *pred : block->getPredecessors())
911 predIDs.push_back(getBBID(pred));
912 llvm::array_pod_sort(predIDs.begin(), predIDs.end());
913
914 os << "\t// " << predIDs.size() << " preds: ";
915
916 interleaveComma(predIDs, [&](unsigned predID) { os << "bb" << predID; });
917 }
918 os << '\n';
James Molloy61a656c2018-07-22 15:45:24 -0700919
Jacques Pienaarb020c542018-07-15 00:06:54 -0700920 for (auto &inst : block->getOperations()) {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -0700921 os << " ";
Chris Lattner3a467cc2018-07-01 20:28:00 -0700922 print(&inst);
James Molloy61a656c2018-07-22 15:45:24 -0700923 os << '\n';
Jacques Pienaarb020c542018-07-15 00:06:54 -0700924 }
Chris Lattner4c95a502018-06-23 16:03:42 -0700925
James Molloy6e4519b2018-08-03 03:51:38 -0700926 os << " ";
Chris Lattner4c95a502018-06-23 16:03:42 -0700927 print(block->getTerminator());
James Molloy61a656c2018-07-22 15:45:24 -0700928 os << '\n';
Chris Lattner4c95a502018-06-23 16:03:42 -0700929}
930
Chris Lattner4fd59b02018-07-20 09:35:47 -0700931void CFGFunctionPrinter::print(const Instruction *inst) {
Chris Lattner4c95a502018-06-23 16:03:42 -0700932 switch (inst->getKind()) {
Chris Lattnered65a732018-06-28 20:45:33 -0700933 case Instruction::Kind::Operation:
934 return print(cast<OperationInst>(inst));
Chris Lattnerf6d80a02018-06-24 11:18:29 -0700935 case TerminatorInst::Kind::Branch:
Chris Lattnered65a732018-06-28 20:45:33 -0700936 return print(cast<BranchInst>(inst));
James Molloy4f788372018-07-24 15:01:27 -0700937 case TerminatorInst::Kind::CondBranch:
938 return print(cast<CondBranchInst>(inst));
Chris Lattner4c95a502018-06-23 16:03:42 -0700939 case TerminatorInst::Kind::Return:
Chris Lattnered65a732018-06-28 20:45:33 -0700940 return print(cast<ReturnInst>(inst));
Chris Lattner4c95a502018-06-23 16:03:42 -0700941 }
942}
943
Chris Lattner4fd59b02018-07-20 09:35:47 -0700944void CFGFunctionPrinter::print(const OperationInst *inst) {
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700945 printOperation(inst);
Chris Lattner3b2ef762018-07-18 15:31:25 -0700946}
Chris Lattner1604e472018-07-23 08:42:19 -0700947
Chris Lattner4fd59b02018-07-20 09:35:47 -0700948void CFGFunctionPrinter::print(const BranchInst *inst) {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -0700949 os << "br bb" << getBBID(inst->getDest());
Chris Lattner1604e472018-07-23 08:42:19 -0700950
951 if (inst->getNumOperands() != 0) {
952 os << '(';
953 // TODO: Use getOperands() when we have it.
954 interleaveComma(inst->getInstOperands(), [&](const InstOperand &operand) {
955 printValueID(operand.get());
956 });
957 os << ") : ";
958 interleaveComma(inst->getInstOperands(), [&](const InstOperand &operand) {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700959 printType(operand.get()->getType());
Chris Lattner1604e472018-07-23 08:42:19 -0700960 });
961 }
Chris Lattnered65a732018-06-28 20:45:33 -0700962}
Chris Lattner1604e472018-07-23 08:42:19 -0700963
James Molloy4f788372018-07-24 15:01:27 -0700964void CFGFunctionPrinter::print(const CondBranchInst *inst) {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -0700965 os << "cond_br ";
James Molloy4f788372018-07-24 15:01:27 -0700966 printValueID(inst->getCondition());
967
968 os << ", bb" << getBBID(inst->getTrueDest());
969 if (inst->getNumTrueOperands() != 0) {
970 os << '(';
971 interleaveComma(inst->getTrueOperands(),
972 [&](const CFGValue *operand) { printValueID(operand); });
973 os << " : ";
974 interleaveComma(inst->getTrueOperands(), [&](const CFGValue *operand) {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700975 printType(operand->getType());
James Molloy4f788372018-07-24 15:01:27 -0700976 });
977 os << ")";
978 }
979
980 os << ", bb" << getBBID(inst->getFalseDest());
981 if (inst->getNumFalseOperands() != 0) {
982 os << '(';
983 interleaveComma(inst->getFalseOperands(),
984 [&](const CFGValue *operand) { printValueID(operand); });
985 os << " : ";
986 interleaveComma(inst->getFalseOperands(), [&](const CFGValue *operand) {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700987 printType(operand->getType());
James Molloy4f788372018-07-24 15:01:27 -0700988 });
989 os << ")";
990 }
991}
992
Chris Lattner40746442018-07-21 14:32:09 -0700993void CFGFunctionPrinter::print(const ReturnInst *inst) {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -0700994 os << "return";
Chris Lattner40746442018-07-21 14:32:09 -0700995
James Molloy6bf60c22018-08-02 08:28:20 -0700996 if (inst->getNumOperands() == 0)
997 return;
Chris Lattner40746442018-07-21 14:32:09 -0700998
James Molloy6bf60c22018-08-02 08:28:20 -0700999 os << ' ';
James Molloy4f788372018-07-24 15:01:27 -07001000 interleaveComma(inst->getOperands(),
1001 [&](const CFGValue *operand) { printValueID(operand); });
1002 os << " : ";
Chris Lattnerac591f12018-07-22 21:02:26 -07001003 interleaveComma(inst->getOperands(), [&](const CFGValue *operand) {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -07001004 printType(operand->getType());
Chris Lattner40746442018-07-21 14:32:09 -07001005 });
1006}
MLIR Team54b55a22018-07-18 10:16:05 -07001007
Chris Lattner4fd59b02018-07-20 09:35:47 -07001008void ModulePrinter::print(const CFGFunction *fn) {
1009 CFGFunctionPrinter(fn, *this).print();
Chris Lattnered65a732018-06-28 20:45:33 -07001010}
1011
Chris Lattner4c95a502018-06-23 16:03:42 -07001012//===----------------------------------------------------------------------===//
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001013// ML Function printing
Chris Lattner4c95a502018-06-23 16:03:42 -07001014//===----------------------------------------------------------------------===//
1015
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001016namespace {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -07001017class MLFunctionPrinter : public FunctionPrinter {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001018public:
Chris Lattner4fd59b02018-07-20 09:35:47 -07001019 MLFunctionPrinter(const MLFunction *function, const ModulePrinter &other);
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001020
1021 const MLFunction *getFunction() const { return function; }
1022
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001023 // Prints ML function
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001024 void print();
1025
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07001026 // Prints ML function signature
1027 void printFunctionSignature();
1028
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001029 // Methods to print ML function statements
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001030 void print(const Statement *stmt);
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -07001031 void print(const OperationStmt *stmt);
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001032 void print(const ForStmt *stmt);
1033 void print(const IfStmt *stmt);
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001034 void print(const StmtBlock *block);
1035
1036 // Number of spaces used for indenting nested statements
1037 const static unsigned indentWidth = 2;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001038
1039private:
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001040 void numberValues();
1041
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001042 const MLFunction *function;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001043 int numSpaces;
1044};
James Molloy87d81022018-07-23 11:44:40 -07001045} // end anonymous namespace
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001046
Chris Lattner4fd59b02018-07-20 09:35:47 -07001047MLFunctionPrinter::MLFunctionPrinter(const MLFunction *function,
1048 const ModulePrinter &other)
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001049 : FunctionPrinter(other), function(function), numSpaces(0) {
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07001050 assert(function && "Cannot print nullptr function");
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001051 numberValues();
1052}
1053
1054/// Number all of the SSA values in this ML function.
1055void MLFunctionPrinter::numberValues() {
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07001056 // Numbers ML function arguments
1057 for (auto *arg : function->getArguments())
1058 numberValueID(arg);
1059
1060 // Walks ML function statements and numbers for statements and
1061 // the first result of the operation statements.
Uday Bondhugula081d9e72018-07-27 10:58:14 -07001062 struct NumberValuesPass : public StmtWalker<NumberValuesPass> {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001063 NumberValuesPass(MLFunctionPrinter *printer) : printer(printer) {}
1064 void visitOperationStmt(OperationStmt *stmt) {
1065 if (stmt->getNumResults() != 0)
1066 printer->numberValueID(stmt->getResult(0));
1067 }
Tatiana Shpeismanc9c4b342018-07-31 07:40:14 -07001068 void visitForStmt(ForStmt *stmt) { printer->numberValueID(stmt); }
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001069 MLFunctionPrinter *printer;
1070 };
1071
1072 NumberValuesPass pass(this);
1073 // TODO: it'd be cleaner to have constant visitor istead of using const_cast.
Uday Bondhugula081d9e72018-07-27 10:58:14 -07001074 pass.walk(const_cast<MLFunction *>(function));
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001075}
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001076
Chris Lattner4fd59b02018-07-20 09:35:47 -07001077void MLFunctionPrinter::print() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001078 os << "mlfunc ";
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07001079 printFunctionSignature();
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001080 os << " {\n";
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001081 print(function);
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001082 os << " return\n";
1083 os << "}\n\n";
1084}
1085
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07001086void MLFunctionPrinter::printFunctionSignature() {
1087 auto type = function->getType();
1088
1089 os << "@" << function->getName() << '(';
1090
1091 for (unsigned i = 0, e = function->getNumArguments(); i != e; ++i) {
1092 if (i > 0)
1093 os << ", ";
1094 auto *arg = function->getArgument(i);
1095 printOperand(arg);
1096 os << " : ";
1097 printType(arg->getType());
1098 }
1099 os << ")";
1100 printFunctionResultType(type);
1101}
1102
Chris Lattner4fd59b02018-07-20 09:35:47 -07001103void MLFunctionPrinter::print(const StmtBlock *block) {
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001104 numSpaces += indentWidth;
Jacques Pienaarb020c542018-07-15 00:06:54 -07001105 for (auto &stmt : block->getStatements()) {
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001106 print(&stmt);
Jacques Pienaarb020c542018-07-15 00:06:54 -07001107 os << "\n";
1108 }
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001109 numSpaces -= indentWidth;
1110}
1111
Chris Lattner4fd59b02018-07-20 09:35:47 -07001112void MLFunctionPrinter::print(const Statement *stmt) {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001113 switch (stmt->getKind()) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001114 case Statement::Kind::Operation:
1115 return print(cast<OperationStmt>(stmt));
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001116 case Statement::Kind::For:
1117 return print(cast<ForStmt>(stmt));
1118 case Statement::Kind::If:
1119 return print(cast<IfStmt>(stmt));
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001120 }
1121}
1122
Chris Lattner4fd59b02018-07-20 09:35:47 -07001123void MLFunctionPrinter::print(const OperationStmt *stmt) {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001124 os.indent(numSpaces);
Chris Lattner4fd59b02018-07-20 09:35:47 -07001125 printOperation(stmt);
1126}
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001127
Chris Lattner4fd59b02018-07-20 09:35:47 -07001128void MLFunctionPrinter::print(const ForStmt *stmt) {
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07001129 os.indent(numSpaces) << "for ";
Tatiana Shpeismanc9c4b342018-07-31 07:40:14 -07001130 printOperand(stmt);
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07001131 os << " = " << *stmt->getLowerBound();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001132 os << " to " << *stmt->getUpperBound();
1133 if (stmt->getStep()->getValue() != 1)
1134 os << " step " << *stmt->getStep();
1135
1136 os << " {\n";
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001137 print(static_cast<const StmtBlock *>(stmt));
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001138 os.indent(numSpaces) << "}";
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001139}
1140
Chris Lattner4fd59b02018-07-20 09:35:47 -07001141void MLFunctionPrinter::print(const IfStmt *stmt) {
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001142 os.indent(numSpaces) << "if () {\n";
1143 print(stmt->getThenClause());
1144 os.indent(numSpaces) << "}";
1145 if (stmt->hasElseClause()) {
1146 os << " else {\n";
1147 print(stmt->getElseClause());
1148 os.indent(numSpaces) << "}";
1149 }
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001150}
1151
Chris Lattner4fd59b02018-07-20 09:35:47 -07001152void ModulePrinter::print(const MLFunction *fn) {
1153 MLFunctionPrinter(fn, *this).print();
MLIR Team4718bc92018-07-17 16:56:54 -07001154}
1155
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001156//===----------------------------------------------------------------------===//
1157// print and dump methods
1158//===----------------------------------------------------------------------===//
Chris Lattnered65a732018-06-28 20:45:33 -07001159
MLIR Teamb61885d2018-07-18 16:29:21 -07001160void Attribute::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -07001161 ModuleState state(/*no context is known*/ nullptr);
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -07001162 ModulePrinter(os, state).printAttribute(this);
MLIR Teamb61885d2018-07-18 16:29:21 -07001163}
1164
James Molloy87d81022018-07-23 11:44:40 -07001165void Attribute::dump() const { print(llvm::errs()); }
MLIR Teamb61885d2018-07-18 16:29:21 -07001166
MLIR Team4718bc92018-07-17 16:56:54 -07001167void Type::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -07001168 ModuleState state(getContext());
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -07001169 ModulePrinter(os, state).printType(this);
MLIR Team4718bc92018-07-17 16:56:54 -07001170}
1171
MLIR Team54b55a22018-07-18 10:16:05 -07001172void Type::dump() const { print(llvm::errs()); }
MLIR Team4718bc92018-07-17 16:56:54 -07001173
MLIR Team718c82f2018-07-16 09:45:22 -07001174void AffineMap::dump() const {
1175 print(llvm::errs());
1176 llvm::errs() << "\n";
1177}
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001178
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001179void AffineExpr::dump() const {
1180 print(llvm::errs());
1181 llvm::errs() << "\n";
1182}
1183
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001184void AffineExpr::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -07001185 ModuleState state(/*no context is known*/ nullptr);
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -07001186 ModulePrinter(os, state).printAffineExpr(this);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001187}
1188
1189void AffineMap::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -07001190 ModuleState state(/*no context is known*/ nullptr);
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -07001191 ModulePrinter(os, state).printAffineMap(this);
Chris Lattner4fd59b02018-07-20 09:35:47 -07001192}
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001193
Chris Lattner384da8c2018-08-02 17:16:58 -07001194void SSAValue::print(raw_ostream &os) const {
1195 switch (getKind()) {
1196 case SSAValueKind::BBArgument:
1197 // TODO: Improve this.
1198 os << "<bb argument>\n";
1199 return;
1200 case SSAValueKind::InstResult:
1201 return getDefiningInst()->print(os);
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07001202 case SSAValueKind::MLFuncArgument:
Chris Lattner384da8c2018-08-02 17:16:58 -07001203 // TODO: Improve this.
1204 os << "<function argument>\n";
1205 return;
1206 case SSAValueKind::StmtResult:
1207 return getDefiningStmt()->print(os);
1208 case SSAValueKind::ForStmt:
1209 return cast<ForStmt>(this)->print(os);
1210 }
1211}
1212
1213void SSAValue::dump() const { print(llvm::errs()); }
1214
Chris Lattner4fd59b02018-07-20 09:35:47 -07001215void Instruction::print(raw_ostream &os) const {
Tatiana Shpeismanc335d182018-08-03 11:12:34 -07001216 if (!getFunction()) {
1217 os << "<<UNLINKED INSTRUCTION>>\n";
1218 return;
1219 }
Chris Lattner4fd59b02018-07-20 09:35:47 -07001220 ModuleState state(getFunction()->getContext());
1221 ModulePrinter modulePrinter(os, state);
1222 CFGFunctionPrinter(getFunction(), modulePrinter).print(this);
1223}
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001224
Chris Lattner4fd59b02018-07-20 09:35:47 -07001225void Instruction::dump() const {
1226 print(llvm::errs());
1227 llvm::errs() << "\n";
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001228}
1229
Chris Lattner4c95a502018-06-23 16:03:42 -07001230void BasicBlock::print(raw_ostream &os) const {
Tatiana Shpeismanc335d182018-08-03 11:12:34 -07001231 if (!getFunction()) {
1232 os << "<<UNLINKED BLOCK>>\n";
1233 return;
1234 }
Chris Lattner4fd59b02018-07-20 09:35:47 -07001235 ModuleState state(getFunction()->getContext());
1236 ModulePrinter modulePrinter(os, state);
1237 CFGFunctionPrinter(getFunction(), modulePrinter).print(this);
Chris Lattner4c95a502018-06-23 16:03:42 -07001238}
1239
MLIR Team54b55a22018-07-18 10:16:05 -07001240void BasicBlock::dump() const { print(llvm::errs()); }
Chris Lattner4c95a502018-06-23 16:03:42 -07001241
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001242void Statement::print(raw_ostream &os) const {
Tatiana Shpeismand880b352018-07-31 23:14:16 -07001243 MLFunction *function = findFunction();
Tatiana Shpeismanc335d182018-08-03 11:12:34 -07001244 if (!function) {
1245 os << "<<UNLINKED STATEMENT>>\n";
1246 return;
1247 }
1248
Tatiana Shpeismand880b352018-07-31 23:14:16 -07001249 ModuleState state(function->getContext());
Chris Lattner4fd59b02018-07-20 09:35:47 -07001250 ModulePrinter modulePrinter(os, state);
Tatiana Shpeismand880b352018-07-31 23:14:16 -07001251 MLFunctionPrinter(function, modulePrinter).print(this);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001252}
1253
MLIR Team54b55a22018-07-18 10:16:05 -07001254void Statement::dump() const { print(llvm::errs()); }
Jacques Pienaarb020c542018-07-15 00:06:54 -07001255
Uday Bondhugula84b80952018-08-03 13:22:26 -07001256void StmtBlock::print(raw_ostream &os) const {
1257 MLFunction *function = findFunction();
1258 ModuleState state(function->getContext());
1259 ModulePrinter modulePrinter(os, state);
1260 MLFunctionPrinter(function, modulePrinter).print(this);
1261}
1262
1263void StmtBlock::dump() const { print(llvm::errs()); }
1264
Chris Lattner4c95a502018-06-23 16:03:42 -07001265void Function::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -07001266 ModuleState state(getContext());
1267 ModulePrinter(os, state).print(this);
Chris Lattner4c95a502018-06-23 16:03:42 -07001268}
1269
MLIR Team54b55a22018-07-18 10:16:05 -07001270void Function::dump() const { print(llvm::errs()); }
1271
Chris Lattner4c95a502018-06-23 16:03:42 -07001272void Module::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -07001273 ModuleState state(getContext());
1274 state.initialize(this);
1275 ModulePrinter(os, state).print(this);
Chris Lattner4c95a502018-06-23 16:03:42 -07001276}
1277
MLIR Team54b55a22018-07-18 10:16:05 -07001278void Module::dump() const { print(llvm::errs()); }