blob: e23964ddc8fcc03b2d92ed5cbda4535aee9a58de [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"
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -070031#include "mlir/IR/Statements.h"
Chris Lattner4c95a502018-06-23 16:03:42 -070032#include "mlir/IR/Types.h"
33#include "mlir/Support/STLExtras.h"
Chris Lattner4c95a502018-06-23 16:03:42 -070034#include "llvm/ADT/DenseMap.h"
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -070035#include "llvm/Support/raw_ostream.h"
Chris Lattner4c95a502018-06-23 16:03:42 -070036using namespace mlir;
37
MLIR Team54b55a22018-07-18 10:16:05 -070038void Identifier::print(raw_ostream &os) const { os << str(); }
Chris Lattner4c95a502018-06-23 16:03:42 -070039
MLIR Team54b55a22018-07-18 10:16:05 -070040void Identifier::dump() const { print(llvm::errs()); }
Chris Lattner7121b802018-07-04 20:45:39 -070041
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -070042OpAsmPrinter::~OpAsmPrinter() {}
43
Chris Lattner4c95a502018-06-23 16:03:42 -070044//===----------------------------------------------------------------------===//
Chris Lattner4fd59b02018-07-20 09:35:47 -070045// ModuleState
MLIR Team4718bc92018-07-17 16:56:54 -070046//===----------------------------------------------------------------------===//
47
48namespace {
MLIR Team54b55a22018-07-18 10:16:05 -070049class ModuleState {
50public:
Chris Lattner4fd59b02018-07-20 09:35:47 -070051 /// This is the operation set for the current context if it is knowable (a
52 /// context could be determined), otherwise this is null.
53 OperationSet *const operationSet;
MLIR Team4718bc92018-07-17 16:56:54 -070054
Chris Lattner4fd59b02018-07-20 09:35:47 -070055 explicit ModuleState(MLIRContext *context)
56 : operationSet(context ? &OperationSet::get(context) : nullptr) {}
57
58 // Initializes module state, populating affine map state.
MLIR Team4718bc92018-07-17 16:56:54 -070059 void initialize(const Module *module);
60
MLIR Team54b55a22018-07-18 10:16:05 -070061 int getAffineMapId(const AffineMap *affineMap) const {
MLIR Team4718bc92018-07-17 16:56:54 -070062 auto it = affineMapIds.find(affineMap);
63 if (it == affineMapIds.end()) {
64 return -1;
65 }
66 return it->second;
67 }
68
James Molloyc4666722018-07-24 09:48:31 -070069 ArrayRef<const AffineMap *> getAffineMapIds() const { return affineMapsById; }
Chris Lattner4fd59b02018-07-20 09:35:47 -070070
MLIR Team54b55a22018-07-18 10:16:05 -070071private:
Chris Lattner4fd59b02018-07-20 09:35:47 -070072 void recordAffineMapReference(const AffineMap *affineMap) {
73 if (affineMapIds.count(affineMap) == 0) {
James Molloyc4666722018-07-24 09:48:31 -070074 affineMapIds[affineMap] = affineMapsById.size();
75 affineMapsById.push_back(affineMap);
Chris Lattner4fd59b02018-07-20 09:35:47 -070076 }
77 }
78
MLIR Team4718bc92018-07-17 16:56:54 -070079 // Visit functions.
80 void visitFunction(const Function *fn);
81 void visitExtFunction(const ExtFunction *fn);
82 void visitCFGFunction(const CFGFunction *fn);
83 void visitMLFunction(const MLFunction *fn);
84 void visitType(const Type *type);
MLIR Teamb61885d2018-07-18 16:29:21 -070085 void visitAttribute(const Attribute *attr);
86 void visitOperation(const Operation *op);
87
MLIR Team54b55a22018-07-18 10:16:05 -070088 DenseMap<const AffineMap *, int> affineMapIds;
James Molloyc4666722018-07-24 09:48:31 -070089 std::vector<const AffineMap *> affineMapsById;
MLIR Team4718bc92018-07-17 16:56:54 -070090};
James Molloy87d81022018-07-23 11:44:40 -070091} // end anonymous namespace
MLIR Team4718bc92018-07-17 16:56:54 -070092
93// TODO Support visiting other types/instructions when implemented.
94void ModuleState::visitType(const Type *type) {
95 if (type->getKind() == Type::Kind::Function) {
96 // Visit input and result types for functions.
97 auto *funcType = cast<FunctionType>(type);
MLIR Team54b55a22018-07-18 10:16:05 -070098 for (auto *input : funcType->getInputs()) {
MLIR Team4718bc92018-07-17 16:56:54 -070099 visitType(input);
100 }
MLIR Team54b55a22018-07-18 10:16:05 -0700101 for (auto *result : funcType->getResults()) {
MLIR Team4718bc92018-07-17 16:56:54 -0700102 visitType(result);
103 }
104 } else if (type->getKind() == Type::Kind::MemRef) {
105 // Visit affine maps in memref type.
106 auto *memref = cast<MemRefType>(type);
MLIR Team54b55a22018-07-18 10:16:05 -0700107 for (AffineMap *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) {
114 if (isa<AffineMapAttr>(attr)) {
115 recordAffineMapReference(cast<AffineMapAttr>(attr)->getValue());
116 } else if (isa<ArrayAttr>(attr)) {
117 for (auto elt : cast<ArrayAttr>(attr)->getValue()) {
118 visitAttribute(elt);
119 }
120 }
121}
122
123void ModuleState::visitOperation(const Operation *op) {
124 for (auto elt : op->getAttrs()) {
125 visitAttribute(elt.second);
126 }
127}
128
MLIR Team4718bc92018-07-17 16:56:54 -0700129void ModuleState::visitExtFunction(const ExtFunction *fn) {
130 visitType(fn->getType());
131}
132
133void ModuleState::visitCFGFunction(const CFGFunction *fn) {
134 visitType(fn->getType());
MLIR Teamb61885d2018-07-18 16:29:21 -0700135 for (auto &block : *fn) {
136 for (auto &op : block.getOperations()) {
137 visitOperation(&op);
138 }
139 }
MLIR Team4718bc92018-07-17 16:56:54 -0700140}
141
142void ModuleState::visitMLFunction(const MLFunction *fn) {
143 visitType(fn->getType());
MLIR Teamb61885d2018-07-18 16:29:21 -0700144 // TODO Visit function body statements (and attributes if required).
MLIR Team4718bc92018-07-17 16:56:54 -0700145}
146
147void ModuleState::visitFunction(const Function *fn) {
148 switch (fn->getKind()) {
MLIR Team54b55a22018-07-18 10:16:05 -0700149 case Function::Kind::ExtFunc:
150 return visitExtFunction(cast<ExtFunction>(fn));
151 case Function::Kind::CFGFunc:
152 return visitCFGFunction(cast<CFGFunction>(fn));
153 case Function::Kind::MLFunc:
154 return visitMLFunction(cast<MLFunction>(fn));
MLIR Team4718bc92018-07-17 16:56:54 -0700155 }
156}
157
Chris Lattner4fd59b02018-07-20 09:35:47 -0700158// Initializes module state, populating affine map state.
159void ModuleState::initialize(const Module *module) {
160 for (auto fn : module->functionList) {
161 visitFunction(fn);
162 }
163}
164
165//===----------------------------------------------------------------------===//
166// ModulePrinter
167//===----------------------------------------------------------------------===//
168
169namespace {
170class ModulePrinter {
171public:
172 ModulePrinter(raw_ostream &os, ModuleState &state) : os(os), state(state) {}
173 explicit ModulePrinter(const ModulePrinter &printer)
174 : os(printer.os), state(printer.state) {}
175
176 template <typename Container, typename UnaryFunctor>
177 inline void interleaveComma(const Container &c, UnaryFunctor each_fn) const {
178 interleave(c.begin(), c.end(), each_fn, [&]() { os << ", "; });
179 }
180
181 void print(const Module *module);
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700182 void printAttribute(const Attribute *attr);
183 void printType(const Type *type);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700184 void print(const Function *fn);
185 void print(const ExtFunction *fn);
186 void print(const CFGFunction *fn);
187 void print(const MLFunction *fn);
188
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700189 void printAffineMap(const AffineMap *map);
190 void printAffineExpr(const AffineExpr *expr);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700191
192protected:
193 raw_ostream &os;
194 ModuleState &state;
195
196 void printFunctionSignature(const Function *fn);
197 void printAffineMapId(int affineMapId) const;
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700198 void printAffineMapReference(const AffineMap *affineMap);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700199
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700200 void printAffineBinaryOpExpr(const AffineBinaryOpExpr *expr);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700201};
202} // end anonymous namespace
203
MLIR Team4718bc92018-07-17 16:56:54 -0700204// Prints function with initialized module state.
Chris Lattner4fd59b02018-07-20 09:35:47 -0700205void ModulePrinter::print(const Function *fn) {
MLIR Team4718bc92018-07-17 16:56:54 -0700206 switch (fn->getKind()) {
MLIR Team54b55a22018-07-18 10:16:05 -0700207 case Function::Kind::ExtFunc:
208 return print(cast<ExtFunction>(fn));
209 case Function::Kind::CFGFunc:
210 return print(cast<CFGFunction>(fn));
211 case Function::Kind::MLFunc:
212 return print(cast<MLFunction>(fn));
MLIR Team4718bc92018-07-17 16:56:54 -0700213 }
214}
215
216// Prints affine map identifier.
Chris Lattner4fd59b02018-07-20 09:35:47 -0700217void ModulePrinter::printAffineMapId(int affineMapId) const {
MLIR Team4718bc92018-07-17 16:56:54 -0700218 os << "#map" << affineMapId;
219}
220
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700221void ModulePrinter::printAffineMapReference(const AffineMap *affineMap) {
Chris Lattner4fd59b02018-07-20 09:35:47 -0700222 int mapId = state.getAffineMapId(affineMap);
MLIR Teamb61885d2018-07-18 16:29:21 -0700223 if (mapId >= 0) {
224 // Map will be printed at top of module so print reference to its id.
225 printAffineMapId(mapId);
226 } else {
227 // Map not in module state so print inline.
228 affineMap->print(os);
229 }
230}
231
Chris Lattner4fd59b02018-07-20 09:35:47 -0700232void ModulePrinter::print(const Module *module) {
James Molloyc4666722018-07-24 09:48:31 -0700233 for (const auto &map : state.getAffineMapIds()) {
234 printAffineMapId(state.getAffineMapId(map));
MLIR Team4718bc92018-07-17 16:56:54 -0700235 os << " = ";
James Molloyc4666722018-07-24 09:48:31 -0700236 map->print(os);
MLIR Team4718bc92018-07-17 16:56:54 -0700237 os << '\n';
238 }
James Molloy87d81022018-07-23 11:44:40 -0700239 for (auto *fn : module->functionList)
240 print(fn);
MLIR Team4718bc92018-07-17 16:56:54 -0700241}
242
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700243void ModulePrinter::printAttribute(const Attribute *attr) {
MLIR Teamb61885d2018-07-18 16:29:21 -0700244 switch (attr->getKind()) {
245 case Attribute::Kind::Bool:
246 os << (cast<BoolAttr>(attr)->getValue() ? "true" : "false");
247 break;
248 case Attribute::Kind::Integer:
249 os << cast<IntegerAttr>(attr)->getValue();
250 break;
251 case Attribute::Kind::Float:
252 // FIXME: this isn't precise, we should print with a hex format.
253 os << cast<FloatAttr>(attr)->getValue();
254 break;
255 case Attribute::Kind::String:
256 // FIXME: should escape the string.
257 os << '"' << cast<StringAttr>(attr)->getValue() << '"';
258 break;
259 case Attribute::Kind::Array: {
260 auto elts = cast<ArrayAttr>(attr)->getValue();
261 os << '[';
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700262 interleaveComma(elts, [&](Attribute *attr) { printAttribute(attr); });
MLIR Teamb61885d2018-07-18 16:29:21 -0700263 os << ']';
264 break;
265 }
266 case Attribute::Kind::AffineMap:
267 printAffineMapReference(cast<AffineMapAttr>(attr)->getValue());
268 break;
269 }
270}
271
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700272void ModulePrinter::printType(const Type *type) {
MLIR Team4718bc92018-07-17 16:56:54 -0700273 switch (type->getKind()) {
MLIR Team54b55a22018-07-18 10:16:05 -0700274 case Type::Kind::AffineInt:
275 os << "affineint";
276 return;
277 case Type::Kind::BF16:
278 os << "bf16";
279 return;
280 case Type::Kind::F16:
281 os << "f16";
282 return;
283 case Type::Kind::F32:
284 os << "f32";
285 return;
286 case Type::Kind::F64:
287 os << "f64";
288 return;
MLIR Team4718bc92018-07-17 16:56:54 -0700289
290 case Type::Kind::Integer: {
291 auto *integer = cast<IntegerType>(type);
292 os << 'i' << integer->getWidth();
293 return;
294 }
295 case Type::Kind::Function: {
296 auto *func = cast<FunctionType>(type);
297 os << '(';
Chris Lattner413db6a2018-07-25 12:55:50 -0700298 interleaveComma(func->getInputs(), [&](Type *type) { printType(type); });
MLIR Team4718bc92018-07-17 16:56:54 -0700299 os << ") -> ";
300 auto results = func->getResults();
301 if (results.size() == 1)
302 os << *results[0];
303 else {
304 os << '(';
Chris Lattner413db6a2018-07-25 12:55:50 -0700305 interleaveComma(results, [&](Type *type) { printType(type); });
MLIR Team4718bc92018-07-17 16:56:54 -0700306 os << ')';
307 }
308 return;
309 }
310 case Type::Kind::Vector: {
311 auto *v = cast<VectorType>(type);
312 os << "vector<";
James Molloy87d81022018-07-23 11:44:40 -0700313 for (auto dim : v->getShape())
314 os << dim << 'x';
MLIR Team4718bc92018-07-17 16:56:54 -0700315 os << *v->getElementType() << '>';
316 return;
317 }
318 case Type::Kind::RankedTensor: {
319 auto *v = cast<RankedTensorType>(type);
320 os << "tensor<";
321 for (auto dim : v->getShape()) {
322 if (dim < 0)
323 os << '?';
324 else
325 os << dim;
326 os << 'x';
327 }
328 os << *v->getElementType() << '>';
329 return;
330 }
331 case Type::Kind::UnrankedTensor: {
332 auto *v = cast<UnrankedTensorType>(type);
Chris Lattner413db6a2018-07-25 12:55:50 -0700333 os << "tensor<??";
334 printType(v->getElementType());
335 os << '>';
MLIR Team4718bc92018-07-17 16:56:54 -0700336 return;
337 }
338 case Type::Kind::MemRef: {
339 auto *v = cast<MemRefType>(type);
340 os << "memref<";
341 for (auto dim : v->getShape()) {
342 if (dim < 0)
343 os << '?';
344 else
345 os << dim;
346 os << 'x';
347 }
Chris Lattner413db6a2018-07-25 12:55:50 -0700348 printType(v->getElementType());
MLIR Team4718bc92018-07-17 16:56:54 -0700349 for (auto map : v->getAffineMaps()) {
350 os << ", ";
MLIR Teamb61885d2018-07-18 16:29:21 -0700351 printAffineMapReference(map);
MLIR Team4718bc92018-07-17 16:56:54 -0700352 }
Chris Lattner413db6a2018-07-25 12:55:50 -0700353 // Only print the memory space if it is the non-default one.
354 if (v->getMemorySpace())
355 os << ", " << v->getMemorySpace();
MLIR Team4718bc92018-07-17 16:56:54 -0700356 os << '>';
357 return;
358 }
359 }
360}
361
362//===----------------------------------------------------------------------===//
Chris Lattner4fd59b02018-07-20 09:35:47 -0700363// Affine expressions and maps
364//===----------------------------------------------------------------------===//
365
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700366void ModulePrinter::printAffineExpr(const AffineExpr *expr) {
Chris Lattner4fd59b02018-07-20 09:35:47 -0700367 switch (expr->getKind()) {
368 case AffineExpr::Kind::SymbolId:
369 os << 's' << cast<AffineSymbolExpr>(expr)->getPosition();
370 return;
371 case AffineExpr::Kind::DimId:
372 os << 'd' << cast<AffineDimExpr>(expr)->getPosition();
373 return;
374 case AffineExpr::Kind::Constant:
375 os << cast<AffineConstantExpr>(expr)->getValue();
376 return;
377 case AffineExpr::Kind::Add:
378 case AffineExpr::Kind::Mul:
379 case AffineExpr::Kind::FloorDiv:
380 case AffineExpr::Kind::CeilDiv:
381 case AffineExpr::Kind::Mod:
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700382 return printAffineBinaryOpExpr(cast<AffineBinaryOpExpr>(expr));
Chris Lattner4fd59b02018-07-20 09:35:47 -0700383 }
384}
385
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700386void ModulePrinter::printAffineBinaryOpExpr(const AffineBinaryOpExpr *expr) {
Chris Lattner4fd59b02018-07-20 09:35:47 -0700387 if (expr->getKind() != AffineExpr::Kind::Add) {
388 os << '(';
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700389 printAffineExpr(expr->getLHS());
Chris Lattner4fd59b02018-07-20 09:35:47 -0700390 switch (expr->getKind()) {
391 case AffineExpr::Kind::Mul:
392 os << " * ";
393 break;
394 case AffineExpr::Kind::FloorDiv:
395 os << " floordiv ";
396 break;
397 case AffineExpr::Kind::CeilDiv:
398 os << " ceildiv ";
399 break;
400 case AffineExpr::Kind::Mod:
401 os << " mod ";
402 break;
403 default:
404 llvm_unreachable("unexpected affine binary op expression");
405 }
406
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700407 printAffineExpr(expr->getRHS());
Chris Lattner4fd59b02018-07-20 09:35:47 -0700408 os << ')';
409 return;
410 }
411
412 // Print out special "pretty" forms for add.
413 os << '(';
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700414 printAffineExpr(expr->getLHS());
Chris Lattner4fd59b02018-07-20 09:35:47 -0700415
416 // Pretty print addition to a product that has a negative operand as a
417 // subtraction.
418 if (auto *rhs = dyn_cast<AffineBinaryOpExpr>(expr->getRHS())) {
419 if (rhs->getKind() == AffineExpr::Kind::Mul) {
420 if (auto *rrhs = dyn_cast<AffineConstantExpr>(rhs->getRHS())) {
421 if (rrhs->getValue() < 0) {
422 os << " - (";
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700423 printAffineExpr(rhs->getLHS());
Chris Lattner4fd59b02018-07-20 09:35:47 -0700424 os << " * " << -rrhs->getValue() << "))";
425 return;
426 }
427 }
428 }
429 }
430
431 // Pretty print addition to a negative number as a subtraction.
432 if (auto *rhs = dyn_cast<AffineConstantExpr>(expr->getRHS())) {
433 if (rhs->getValue() < 0) {
434 os << " - " << -rhs->getValue() << ")";
435 return;
436 }
437 }
438
439 os << " + ";
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700440 printAffineExpr(expr->getRHS());
Chris Lattner4fd59b02018-07-20 09:35:47 -0700441 os << ')';
442}
443
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700444void ModulePrinter::printAffineMap(const AffineMap *map) {
Chris Lattner4fd59b02018-07-20 09:35:47 -0700445 // Dimension identifiers.
446 os << '(';
447 for (int i = 0; i < (int)map->getNumDims() - 1; i++)
448 os << "d" << i << ", ";
449 if (map->getNumDims() >= 1)
450 os << "d" << map->getNumDims() - 1;
451 os << ")";
452
453 // Symbolic identifiers.
454 if (map->getNumSymbols() >= 1) {
455 os << " [";
456 for (int i = 0; i < (int)map->getNumSymbols() - 1; i++)
457 os << "s" << i << ", ";
458 if (map->getNumSymbols() >= 1)
459 os << "s" << map->getNumSymbols() - 1;
460 os << "]";
461 }
462
463 // AffineMap should have at least one result.
464 assert(!map->getResults().empty());
465 // Result affine expressions.
466 os << " -> (";
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700467 interleaveComma(map->getResults(),
468 [&](AffineExpr *expr) { printAffineExpr(expr); });
Chris Lattner4fd59b02018-07-20 09:35:47 -0700469 os << ")";
470
471 if (!map->isBounded()) {
472 return;
473 }
474
475 // Print range sizes for bounded affine maps.
476 os << " size (";
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700477 interleaveComma(map->getRangeSizes(),
478 [&](AffineExpr *expr) { printAffineExpr(expr); });
Chris Lattner4fd59b02018-07-20 09:35:47 -0700479 os << ")";
480}
481
482//===----------------------------------------------------------------------===//
Chris Lattner4c95a502018-06-23 16:03:42 -0700483// Function printing
484//===----------------------------------------------------------------------===//
485
Chris Lattner4fd59b02018-07-20 09:35:47 -0700486void ModulePrinter::printFunctionSignature(const Function *fn) {
Chris Lattner4c95a502018-06-23 16:03:42 -0700487 auto type = fn->getType();
488
489 os << "@" << fn->getName() << '(';
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700490 interleaveComma(type->getInputs(),
491 [&](Type *eltType) { printType(eltType); });
Chris Lattner4c95a502018-06-23 16:03:42 -0700492 os << ')';
493
494 switch (type->getResults().size()) {
MLIR Team54b55a22018-07-18 10:16:05 -0700495 case 0:
496 break;
Chris Lattner4c95a502018-06-23 16:03:42 -0700497 case 1:
MLIR Team4718bc92018-07-17 16:56:54 -0700498 os << " -> ";
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700499 printType(type->getResults()[0]);
Chris Lattner4c95a502018-06-23 16:03:42 -0700500 break;
501 default:
502 os << " -> (";
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700503 interleaveComma(type->getResults(),
504 [&](Type *eltType) { printType(eltType); });
Chris Lattner4c95a502018-06-23 16:03:42 -0700505 os << ')';
506 break;
507 }
508}
509
Chris Lattner4fd59b02018-07-20 09:35:47 -0700510void ModulePrinter::print(const ExtFunction *fn) {
Chris Lattner4c95a502018-06-23 16:03:42 -0700511 os << "extfunc ";
Chris Lattner4fd59b02018-07-20 09:35:47 -0700512 printFunctionSignature(fn);
MLIR Team54b55a22018-07-18 10:16:05 -0700513 os << '\n';
Chris Lattner4c95a502018-06-23 16:03:42 -0700514}
515
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700516namespace {
517
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700518// FunctionPrinter contains common functionality for printing
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700519// CFG and ML functions.
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700520class FunctionPrinter : public ModulePrinter, private OpAsmPrinter {
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700521public:
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700522 FunctionPrinter(const ModulePrinter &other) : ModulePrinter(other) {}
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700523
524 void printOperation(const Operation *op);
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700525 void printDefaultOp(const Operation *op);
526
527 // Implement OpAsmPrinter.
528 raw_ostream &getStream() const { return os; }
529 void printType(const Type *type) { ModulePrinter::printType(type); }
530 void printAttribute(const Attribute *attr) {
531 ModulePrinter::printAttribute(attr);
532 }
533 void printAffineMap(const AffineMap *map) {
534 return ModulePrinter::printAffineMap(map);
535 }
536 void printAffineExpr(const AffineExpr *expr) {
537 return ModulePrinter::printAffineExpr(expr);
538 }
539
540 void printOperand(const SSAValue *value) { printValueID(value); }
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700541
542protected:
Chris Lattnerf8cce872018-07-20 09:28:54 -0700543 void numberValueID(const SSAValue *value) {
544 assert(!valueIDs.count(value) && "Value numbered multiple times");
545 valueIDs[value] = nextValueID++;
546 }
547
Chris Lattner6119d382018-07-20 18:41:34 -0700548 void printValueID(const SSAValue *value,
549 bool dontPrintResultNo = false) const {
550 int resultNo = -1;
551 auto lookupValue = value;
552
553 // If this is a reference to the result of a multi-result instruction, print
554 // out the # identifier and make sure to map our lookup to the first result
555 // of the instruction.
556 if (auto *result = dyn_cast<InstResult>(value)) {
557 if (result->getOwner()->getNumResults() != 1) {
558 resultNo = result->getResultNumber();
559 lookupValue = result->getOwner()->getResult(0);
560 }
561 }
562
563 auto it = valueIDs.find(lookupValue);
564 if (it == valueIDs.end()) {
Chris Lattnerf8cce872018-07-20 09:28:54 -0700565 os << "<<INVALID SSA VALUE>>";
Chris Lattner6119d382018-07-20 18:41:34 -0700566 return;
567 }
568
569 os << '%' << it->getSecond();
570 if (resultNo != -1 && !dontPrintResultNo)
571 os << '#' << resultNo;
Chris Lattnerf8cce872018-07-20 09:28:54 -0700572 }
573
574private:
575 /// This is the value ID for each SSA value in the current function.
576 DenseMap<const SSAValue *, unsigned> valueIDs;
577 unsigned nextValueID = 0;
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700578};
James Molloy87d81022018-07-23 11:44:40 -0700579} // end anonymous namespace
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700580
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700581void FunctionPrinter::printOperation(const Operation *op) {
Chris Lattnerf8cce872018-07-20 09:28:54 -0700582 os << " ";
583
Chris Lattnerac591f12018-07-22 21:02:26 -0700584 if (op->getNumResults()) {
585 printValueID(op->getResult(0), /*dontPrintResultNo*/ true);
586 os << " = ";
Chris Lattnerf8cce872018-07-20 09:28:54 -0700587 }
588
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700589 // Check to see if this is a known operation. If so, use the registered
590 // custom printer hook.
Chris Lattner4fd59b02018-07-20 09:35:47 -0700591 if (auto opInfo = state.operationSet->lookup(op->getName().str())) {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700592 opInfo->printAssembly(op, this);
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700593 return;
594 }
595
Chris Lattnerf8cce872018-07-20 09:28:54 -0700596 // Otherwise use the standard verbose printing approach.
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700597 printDefaultOp(op);
598}
Chris Lattnerf8cce872018-07-20 09:28:54 -0700599
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700600void FunctionPrinter::printDefaultOp(const Operation *op) {
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700601 // TODO: escape name if necessary.
Chris Lattnerf8cce872018-07-20 09:28:54 -0700602 os << "\"" << op->getName().str() << "\"(";
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700603
Chris Lattnerac591f12018-07-22 21:02:26 -0700604 interleaveComma(op->getOperands(),
605 [&](const SSAValue *value) { printValueID(value); });
Chris Lattner7f9cc272018-07-19 08:35:28 -0700606
Chris Lattnerf8cce872018-07-20 09:28:54 -0700607 os << ')';
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700608 auto attrs = op->getAttrs();
609 if (!attrs.empty()) {
610 os << '{';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700611 interleaveComma(attrs, [&](NamedAttribute attr) {
Chris Lattnerf8cce872018-07-20 09:28:54 -0700612 os << attr.first << ": ";
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700613 printAttribute(attr.second);
Chris Lattnerf8cce872018-07-20 09:28:54 -0700614 });
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700615 os << '}';
616 }
Chris Lattner3b2ef762018-07-18 15:31:25 -0700617
Chris Lattnerac591f12018-07-22 21:02:26 -0700618 // Print the type signature of the operation.
619 os << " : (";
620 interleaveComma(op->getOperands(),
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700621 [&](const SSAValue *value) { printType(value->getType()); });
Chris Lattnerac591f12018-07-22 21:02:26 -0700622 os << ") -> ";
Chris Lattnerf8cce872018-07-20 09:28:54 -0700623
Chris Lattnerac591f12018-07-22 21:02:26 -0700624 if (op->getNumResults() == 1) {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700625 printType(op->getResult(0)->getType());
Chris Lattnerac591f12018-07-22 21:02:26 -0700626 } else {
627 os << '(';
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700628 interleaveComma(op->getResults(), [&](const SSAValue *result) {
629 printType(result->getType());
630 });
Chris Lattnerac591f12018-07-22 21:02:26 -0700631 os << ')';
Chris Lattnerf8cce872018-07-20 09:28:54 -0700632 }
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700633}
634
Chris Lattner4c95a502018-06-23 16:03:42 -0700635//===----------------------------------------------------------------------===//
636// CFG Function printing
637//===----------------------------------------------------------------------===//
638
639namespace {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700640class CFGFunctionPrinter : public FunctionPrinter {
Chris Lattner4c95a502018-06-23 16:03:42 -0700641public:
Chris Lattner4fd59b02018-07-20 09:35:47 -0700642 CFGFunctionPrinter(const CFGFunction *function, const ModulePrinter &other);
Chris Lattner4c95a502018-06-23 16:03:42 -0700643
644 const CFGFunction *getFunction() const { return function; }
645
646 void print();
647 void print(const BasicBlock *block);
Chris Lattnered65a732018-06-28 20:45:33 -0700648
649 void print(const Instruction *inst);
650 void print(const OperationInst *inst);
651 void print(const ReturnInst *inst);
652 void print(const BranchInst *inst);
James Molloy4f788372018-07-24 15:01:27 -0700653 void print(const CondBranchInst *inst);
Chris Lattner4c95a502018-06-23 16:03:42 -0700654
655 unsigned getBBID(const BasicBlock *block) {
656 auto it = basicBlockIDs.find(block);
657 assert(it != basicBlockIDs.end() && "Block not in this function?");
658 return it->second;
659 }
660
661private:
662 const CFGFunction *function;
MLIR Team54b55a22018-07-18 10:16:05 -0700663 DenseMap<const BasicBlock *, unsigned> basicBlockIDs;
Chris Lattnerf8cce872018-07-20 09:28:54 -0700664
Chris Lattner4fd59b02018-07-20 09:35:47 -0700665 void numberValuesInBlock(const BasicBlock *block);
Chris Lattner4c95a502018-06-23 16:03:42 -0700666};
James Molloy87d81022018-07-23 11:44:40 -0700667} // end anonymous namespace
Chris Lattner4c95a502018-06-23 16:03:42 -0700668
Chris Lattner4fd59b02018-07-20 09:35:47 -0700669CFGFunctionPrinter::CFGFunctionPrinter(const CFGFunction *function,
670 const ModulePrinter &other)
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700671 : FunctionPrinter(other), function(function) {
Chris Lattner4c95a502018-06-23 16:03:42 -0700672 // Each basic block gets a unique ID per function.
673 unsigned blockID = 0;
Chris Lattnerf8cce872018-07-20 09:28:54 -0700674 for (auto &block : *function) {
675 basicBlockIDs[&block] = blockID++;
Chris Lattner4fd59b02018-07-20 09:35:47 -0700676 numberValuesInBlock(&block);
Chris Lattnerf8cce872018-07-20 09:28:54 -0700677 }
678}
679
680/// Number all of the SSA values in the specified basic block.
Chris Lattner4fd59b02018-07-20 09:35:47 -0700681void CFGFunctionPrinter::numberValuesInBlock(const BasicBlock *block) {
James Molloy61a656c2018-07-22 15:45:24 -0700682 for (auto *arg : block->getArguments()) {
683 numberValueID(arg);
684 }
Chris Lattnerf8cce872018-07-20 09:28:54 -0700685 for (auto &op : *block) {
686 // We number instruction that have results, and we only number the first
687 // result.
688 if (op.getNumResults() != 0)
689 numberValueID(op.getResult(0));
690 }
691
692 // Terminators do not define values.
Chris Lattner4c95a502018-06-23 16:03:42 -0700693}
694
Chris Lattner4fd59b02018-07-20 09:35:47 -0700695void CFGFunctionPrinter::print() {
Chris Lattner4c95a502018-06-23 16:03:42 -0700696 os << "cfgfunc ";
Chris Lattner4fd59b02018-07-20 09:35:47 -0700697 printFunctionSignature(getFunction());
Chris Lattner4c95a502018-06-23 16:03:42 -0700698 os << " {\n";
699
James Molloy87d81022018-07-23 11:44:40 -0700700 for (auto &block : *function)
701 print(&block);
Chris Lattner4c95a502018-06-23 16:03:42 -0700702 os << "}\n\n";
703}
704
Chris Lattner4fd59b02018-07-20 09:35:47 -0700705void CFGFunctionPrinter::print(const BasicBlock *block) {
James Molloy61a656c2018-07-22 15:45:24 -0700706 os << "bb" << getBBID(block);
Chris Lattner4c95a502018-06-23 16:03:42 -0700707
James Molloy61a656c2018-07-22 15:45:24 -0700708 if (!block->args_empty()) {
709 os << '(';
710 interleaveComma(block->getArguments(), [&](const BBArgument *arg) {
711 printValueID(arg);
712 os << ": ";
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700713 printType(arg->getType());
James Molloy61a656c2018-07-22 15:45:24 -0700714 });
715 os << ')';
716 }
717 os << ":\n";
718
Jacques Pienaarb020c542018-07-15 00:06:54 -0700719 for (auto &inst : block->getOperations()) {
Chris Lattner3a467cc2018-07-01 20:28:00 -0700720 print(&inst);
James Molloy61a656c2018-07-22 15:45:24 -0700721 os << '\n';
Jacques Pienaarb020c542018-07-15 00:06:54 -0700722 }
Chris Lattner4c95a502018-06-23 16:03:42 -0700723
724 print(block->getTerminator());
James Molloy61a656c2018-07-22 15:45:24 -0700725 os << '\n';
Chris Lattner4c95a502018-06-23 16:03:42 -0700726}
727
Chris Lattner4fd59b02018-07-20 09:35:47 -0700728void CFGFunctionPrinter::print(const Instruction *inst) {
Chris Lattner4c95a502018-06-23 16:03:42 -0700729 switch (inst->getKind()) {
Chris Lattnered65a732018-06-28 20:45:33 -0700730 case Instruction::Kind::Operation:
731 return print(cast<OperationInst>(inst));
Chris Lattnerf6d80a02018-06-24 11:18:29 -0700732 case TerminatorInst::Kind::Branch:
Chris Lattnered65a732018-06-28 20:45:33 -0700733 return print(cast<BranchInst>(inst));
James Molloy4f788372018-07-24 15:01:27 -0700734 case TerminatorInst::Kind::CondBranch:
735 return print(cast<CondBranchInst>(inst));
Chris Lattner4c95a502018-06-23 16:03:42 -0700736 case TerminatorInst::Kind::Return:
Chris Lattnered65a732018-06-28 20:45:33 -0700737 return print(cast<ReturnInst>(inst));
Chris Lattner4c95a502018-06-23 16:03:42 -0700738 }
739}
740
Chris Lattner4fd59b02018-07-20 09:35:47 -0700741void CFGFunctionPrinter::print(const OperationInst *inst) {
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700742 printOperation(inst);
Chris Lattner3b2ef762018-07-18 15:31:25 -0700743}
Chris Lattner1604e472018-07-23 08:42:19 -0700744
Chris Lattner4fd59b02018-07-20 09:35:47 -0700745void CFGFunctionPrinter::print(const BranchInst *inst) {
Jacques Pienaarb020c542018-07-15 00:06:54 -0700746 os << " br bb" << getBBID(inst->getDest());
Chris Lattner1604e472018-07-23 08:42:19 -0700747
748 if (inst->getNumOperands() != 0) {
749 os << '(';
750 // TODO: Use getOperands() when we have it.
751 interleaveComma(inst->getInstOperands(), [&](const InstOperand &operand) {
752 printValueID(operand.get());
753 });
754 os << ") : ";
755 interleaveComma(inst->getInstOperands(), [&](const InstOperand &operand) {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700756 printType(operand.get()->getType());
Chris Lattner1604e472018-07-23 08:42:19 -0700757 });
758 }
Chris Lattnered65a732018-06-28 20:45:33 -0700759}
Chris Lattner1604e472018-07-23 08:42:19 -0700760
James Molloy4f788372018-07-24 15:01:27 -0700761void CFGFunctionPrinter::print(const CondBranchInst *inst) {
762 os << " cond_br ";
763 printValueID(inst->getCondition());
764
765 os << ", bb" << getBBID(inst->getTrueDest());
766 if (inst->getNumTrueOperands() != 0) {
767 os << '(';
768 interleaveComma(inst->getTrueOperands(),
769 [&](const CFGValue *operand) { printValueID(operand); });
770 os << " : ";
771 interleaveComma(inst->getTrueOperands(), [&](const CFGValue *operand) {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700772 printType(operand->getType());
James Molloy4f788372018-07-24 15:01:27 -0700773 });
774 os << ")";
775 }
776
777 os << ", bb" << getBBID(inst->getFalseDest());
778 if (inst->getNumFalseOperands() != 0) {
779 os << '(';
780 interleaveComma(inst->getFalseOperands(),
781 [&](const CFGValue *operand) { printValueID(operand); });
782 os << " : ";
783 interleaveComma(inst->getFalseOperands(), [&](const CFGValue *operand) {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700784 printType(operand->getType());
James Molloy4f788372018-07-24 15:01:27 -0700785 });
786 os << ")";
787 }
788}
789
Chris Lattner40746442018-07-21 14:32:09 -0700790void CFGFunctionPrinter::print(const ReturnInst *inst) {
791 os << " return";
792
793 if (inst->getNumOperands() != 0)
794 os << ' ';
795
James Molloy4f788372018-07-24 15:01:27 -0700796 interleaveComma(inst->getOperands(),
797 [&](const CFGValue *operand) { printValueID(operand); });
798 os << " : ";
Chris Lattnerac591f12018-07-22 21:02:26 -0700799 interleaveComma(inst->getOperands(), [&](const CFGValue *operand) {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700800 printType(operand->getType());
Chris Lattner40746442018-07-21 14:32:09 -0700801 });
802}
MLIR Team54b55a22018-07-18 10:16:05 -0700803
Chris Lattner4fd59b02018-07-20 09:35:47 -0700804void ModulePrinter::print(const CFGFunction *fn) {
805 CFGFunctionPrinter(fn, *this).print();
Chris Lattnered65a732018-06-28 20:45:33 -0700806}
807
Chris Lattner4c95a502018-06-23 16:03:42 -0700808//===----------------------------------------------------------------------===//
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700809// ML Function printing
Chris Lattner4c95a502018-06-23 16:03:42 -0700810//===----------------------------------------------------------------------===//
811
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700812namespace {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700813class MLFunctionPrinter : public FunctionPrinter {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700814public:
Chris Lattner4fd59b02018-07-20 09:35:47 -0700815 MLFunctionPrinter(const MLFunction *function, const ModulePrinter &other);
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700816
817 const MLFunction *getFunction() const { return function; }
818
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700819 // Prints ML function
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700820 void print();
821
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700822 // Methods to print ML function statements
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700823 void print(const Statement *stmt);
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700824 void print(const OperationStmt *stmt);
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700825 void print(const ForStmt *stmt);
826 void print(const IfStmt *stmt);
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700827 void print(const StmtBlock *block);
828
829 // Number of spaces used for indenting nested statements
830 const static unsigned indentWidth = 2;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700831
832private:
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700833 const MLFunction *function;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700834 int numSpaces;
835};
James Molloy87d81022018-07-23 11:44:40 -0700836} // end anonymous namespace
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700837
Chris Lattner4fd59b02018-07-20 09:35:47 -0700838MLFunctionPrinter::MLFunctionPrinter(const MLFunction *function,
839 const ModulePrinter &other)
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700840 : FunctionPrinter(other), function(function), numSpaces(0) {}
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700841
Chris Lattner4fd59b02018-07-20 09:35:47 -0700842void MLFunctionPrinter::print() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700843 os << "mlfunc ";
844 // FIXME: should print argument names rather than just signature
Chris Lattner4fd59b02018-07-20 09:35:47 -0700845 printFunctionSignature(function);
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700846 os << " {\n";
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700847 print(function);
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700848 os << " return\n";
849 os << "}\n\n";
850}
851
Chris Lattner4fd59b02018-07-20 09:35:47 -0700852void MLFunctionPrinter::print(const StmtBlock *block) {
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700853 numSpaces += indentWidth;
Jacques Pienaarb020c542018-07-15 00:06:54 -0700854 for (auto &stmt : block->getStatements()) {
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700855 print(&stmt);
Jacques Pienaarb020c542018-07-15 00:06:54 -0700856 os << "\n";
857 }
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700858 numSpaces -= indentWidth;
859}
860
Chris Lattner4fd59b02018-07-20 09:35:47 -0700861void MLFunctionPrinter::print(const Statement *stmt) {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700862 switch (stmt->getKind()) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -0700863 case Statement::Kind::Operation:
864 return print(cast<OperationStmt>(stmt));
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700865 case Statement::Kind::For:
866 return print(cast<ForStmt>(stmt));
867 case Statement::Kind::If:
868 return print(cast<IfStmt>(stmt));
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700869 }
870}
871
Chris Lattner4fd59b02018-07-20 09:35:47 -0700872void MLFunctionPrinter::print(const OperationStmt *stmt) {
873 printOperation(stmt);
874}
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700875
Chris Lattner4fd59b02018-07-20 09:35:47 -0700876void MLFunctionPrinter::print(const ForStmt *stmt) {
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -0700877 os.indent(numSpaces) << "for x = " << *stmt->getLowerBound();
878 os << " to " << *stmt->getUpperBound();
879 if (stmt->getStep()->getValue() != 1)
880 os << " step " << *stmt->getStep();
881
882 os << " {\n";
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700883 print(static_cast<const StmtBlock *>(stmt));
Tatiana Shpeisman565b9642018-07-16 11:47:09 -0700884 os.indent(numSpaces) << "}";
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700885}
886
Chris Lattner4fd59b02018-07-20 09:35:47 -0700887void MLFunctionPrinter::print(const IfStmt *stmt) {
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700888 os.indent(numSpaces) << "if () {\n";
889 print(stmt->getThenClause());
890 os.indent(numSpaces) << "}";
891 if (stmt->hasElseClause()) {
892 os << " else {\n";
893 print(stmt->getElseClause());
894 os.indent(numSpaces) << "}";
895 }
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700896}
897
Chris Lattner4fd59b02018-07-20 09:35:47 -0700898void ModulePrinter::print(const MLFunction *fn) {
899 MLFunctionPrinter(fn, *this).print();
MLIR Team4718bc92018-07-17 16:56:54 -0700900}
901
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700902//===----------------------------------------------------------------------===//
903// print and dump methods
904//===----------------------------------------------------------------------===//
Chris Lattnered65a732018-06-28 20:45:33 -0700905
MLIR Teamb61885d2018-07-18 16:29:21 -0700906void Attribute::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -0700907 ModuleState state(/*no context is known*/ nullptr);
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700908 ModulePrinter(os, state).printAttribute(this);
MLIR Teamb61885d2018-07-18 16:29:21 -0700909}
910
James Molloy87d81022018-07-23 11:44:40 -0700911void Attribute::dump() const { print(llvm::errs()); }
MLIR Teamb61885d2018-07-18 16:29:21 -0700912
MLIR Team4718bc92018-07-17 16:56:54 -0700913void Type::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -0700914 ModuleState state(getContext());
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700915 ModulePrinter(os, state).printType(this);
MLIR Team4718bc92018-07-17 16:56:54 -0700916}
917
MLIR Team54b55a22018-07-18 10:16:05 -0700918void Type::dump() const { print(llvm::errs()); }
MLIR Team4718bc92018-07-17 16:56:54 -0700919
MLIR Team718c82f2018-07-16 09:45:22 -0700920void AffineMap::dump() const {
921 print(llvm::errs());
922 llvm::errs() << "\n";
923}
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700924
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700925void AffineExpr::dump() const {
926 print(llvm::errs());
927 llvm::errs() << "\n";
928}
929
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700930void AffineExpr::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -0700931 ModuleState state(/*no context is known*/ nullptr);
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700932 ModulePrinter(os, state).printAffineExpr(this);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700933}
934
935void AffineMap::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -0700936 ModuleState state(/*no context is known*/ nullptr);
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700937 ModulePrinter(os, state).printAffineMap(this);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700938}
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700939
Chris Lattner4fd59b02018-07-20 09:35:47 -0700940void Instruction::print(raw_ostream &os) const {
941 ModuleState state(getFunction()->getContext());
942 ModulePrinter modulePrinter(os, state);
943 CFGFunctionPrinter(getFunction(), modulePrinter).print(this);
944}
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700945
Chris Lattner4fd59b02018-07-20 09:35:47 -0700946void Instruction::dump() const {
947 print(llvm::errs());
948 llvm::errs() << "\n";
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700949}
950
Chris Lattner4c95a502018-06-23 16:03:42 -0700951void BasicBlock::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -0700952 ModuleState state(getFunction()->getContext());
953 ModulePrinter modulePrinter(os, state);
954 CFGFunctionPrinter(getFunction(), modulePrinter).print(this);
Chris Lattner4c95a502018-06-23 16:03:42 -0700955}
956
MLIR Team54b55a22018-07-18 10:16:05 -0700957void BasicBlock::dump() const { print(llvm::errs()); }
Chris Lattner4c95a502018-06-23 16:03:42 -0700958
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700959void Statement::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -0700960 ModuleState state(getFunction()->getContext());
961 ModulePrinter modulePrinter(os, state);
962 MLFunctionPrinter(getFunction(), modulePrinter).print(this);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -0700963}
964
MLIR Team54b55a22018-07-18 10:16:05 -0700965void Statement::dump() const { print(llvm::errs()); }
Jacques Pienaarb020c542018-07-15 00:06:54 -0700966
Chris Lattner4c95a502018-06-23 16:03:42 -0700967void Function::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -0700968 ModuleState state(getContext());
969 ModulePrinter(os, state).print(this);
Chris Lattner4c95a502018-06-23 16:03:42 -0700970}
971
MLIR Team54b55a22018-07-18 10:16:05 -0700972void Function::dump() const { print(llvm::errs()); }
973
Chris Lattner4c95a502018-06-23 16:03:42 -0700974void Module::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -0700975 ModuleState state(getContext());
976 state.initialize(this);
977 ModulePrinter(os, state).print(this);
Chris Lattner4c95a502018-06-23 16:03:42 -0700978}
979
MLIR Team54b55a22018-07-18 10:16:05 -0700980void Module::dump() const { print(llvm::errs()); }