blob: c2cd257b64f8015b368bf7bfd1a0ddf6de67c3bb [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"
Uday Bondhugulabc535622018-08-07 14:24:38 -070027#include "mlir/IR/IntegerSet.h"
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -070028#include "mlir/IR/MLFunction.h"
Chris Lattner4c95a502018-06-23 16:03:42 -070029#include "mlir/IR/Module.h"
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -070030#include "mlir/IR/OpImplementation.h"
Chris Lattnerff0d5902018-07-05 09:12:11 -070031#include "mlir/IR/OperationSet.h"
Chris Lattnerd4964212018-08-01 10:43:18 -070032#include "mlir/IR/StandardOps.h"
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -070033#include "mlir/IR/Statements.h"
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -070034#include "mlir/IR/StmtVisitor.h"
Chris Lattner4c95a502018-06-23 16:03:42 -070035#include "mlir/IR/Types.h"
36#include "mlir/Support/STLExtras.h"
Chris Lattner4c95a502018-06-23 16:03:42 -070037#include "llvm/ADT/DenseMap.h"
Chris Lattnerd4964212018-08-01 10:43:18 -070038#include "llvm/ADT/SmallString.h"
39#include "llvm/ADT/StringExtras.h"
40#include "llvm/ADT/StringSet.h"
Chris Lattner4c95a502018-06-23 16:03:42 -070041using namespace mlir;
42
MLIR Team54b55a22018-07-18 10:16:05 -070043void Identifier::print(raw_ostream &os) const { os << str(); }
Chris Lattner4c95a502018-06-23 16:03:42 -070044
MLIR Team54b55a22018-07-18 10:16:05 -070045void Identifier::dump() const { print(llvm::errs()); }
Chris Lattner7121b802018-07-04 20:45:39 -070046
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -070047OpAsmPrinter::~OpAsmPrinter() {}
48
Chris Lattner4c95a502018-06-23 16:03:42 -070049//===----------------------------------------------------------------------===//
Chris Lattner4fd59b02018-07-20 09:35:47 -070050// ModuleState
MLIR Team4718bc92018-07-17 16:56:54 -070051//===----------------------------------------------------------------------===//
52
53namespace {
MLIR Team54b55a22018-07-18 10:16:05 -070054class ModuleState {
55public:
Chris Lattner4fd59b02018-07-20 09:35:47 -070056 /// This is the operation set for the current context if it is knowable (a
57 /// context could be determined), otherwise this is null.
58 OperationSet *const operationSet;
MLIR Team4718bc92018-07-17 16:56:54 -070059
Chris Lattner4fd59b02018-07-20 09:35:47 -070060 explicit ModuleState(MLIRContext *context)
61 : operationSet(context ? &OperationSet::get(context) : nullptr) {}
62
63 // Initializes module state, populating affine map state.
MLIR Team4718bc92018-07-17 16:56:54 -070064 void initialize(const Module *module);
65
MLIR Team54b55a22018-07-18 10:16:05 -070066 int getAffineMapId(const AffineMap *affineMap) const {
MLIR Team4718bc92018-07-17 16:56:54 -070067 auto it = affineMapIds.find(affineMap);
68 if (it == affineMapIds.end()) {
69 return -1;
70 }
71 return it->second;
72 }
73
James Molloyc4666722018-07-24 09:48:31 -070074 ArrayRef<const AffineMap *> getAffineMapIds() const { return affineMapsById; }
Chris Lattner4fd59b02018-07-20 09:35:47 -070075
Uday Bondhugulabc535622018-08-07 14:24:38 -070076 int getIntegerSetId(const IntegerSet *integerSet) const {
77 auto it = integerSetIds.find(integerSet);
78 if (it == integerSetIds.end()) {
79 return -1;
80 }
81 return it->second;
82 }
83
84 ArrayRef<const IntegerSet *> getIntegerSetIds() const {
85 return integerSetsById;
86 }
87
MLIR Team54b55a22018-07-18 10:16:05 -070088private:
Chris Lattner4fd59b02018-07-20 09:35:47 -070089 void recordAffineMapReference(const AffineMap *affineMap) {
90 if (affineMapIds.count(affineMap) == 0) {
James Molloyc4666722018-07-24 09:48:31 -070091 affineMapIds[affineMap] = affineMapsById.size();
92 affineMapsById.push_back(affineMap);
Chris Lattner4fd59b02018-07-20 09:35:47 -070093 }
94 }
95
Uday Bondhugulabc535622018-08-07 14:24:38 -070096 void recordIntegerSetReference(const IntegerSet *integerSet) {
97 if (integerSetIds.count(integerSet) == 0) {
98 integerSetIds[integerSet] = integerSetsById.size();
99 integerSetsById.push_back(integerSet);
100 }
101 }
102
MLIR Team4718bc92018-07-17 16:56:54 -0700103 // Visit functions.
104 void visitFunction(const Function *fn);
105 void visitExtFunction(const ExtFunction *fn);
106 void visitCFGFunction(const CFGFunction *fn);
107 void visitMLFunction(const MLFunction *fn);
Uday Bondhugulabc535622018-08-07 14:24:38 -0700108 void visitStatement(const Statement *stmt);
109 void visitForStmt(const ForStmt *forStmt);
110 void visitIfStmt(const IfStmt *ifStmt);
111 void visitOperationStmt(const OperationStmt *opStmt);
MLIR Team4718bc92018-07-17 16:56:54 -0700112 void visitType(const Type *type);
MLIR Teamb61885d2018-07-18 16:29:21 -0700113 void visitAttribute(const Attribute *attr);
114 void visitOperation(const Operation *op);
115
MLIR Team54b55a22018-07-18 10:16:05 -0700116 DenseMap<const AffineMap *, int> affineMapIds;
James Molloyc4666722018-07-24 09:48:31 -0700117 std::vector<const AffineMap *> affineMapsById;
Uday Bondhugulabc535622018-08-07 14:24:38 -0700118
119 DenseMap<const IntegerSet *, int> integerSetIds;
120 std::vector<const IntegerSet *> integerSetsById;
MLIR Team4718bc92018-07-17 16:56:54 -0700121};
James Molloy87d81022018-07-23 11:44:40 -0700122} // end anonymous namespace
MLIR Team4718bc92018-07-17 16:56:54 -0700123
124// TODO Support visiting other types/instructions when implemented.
125void ModuleState::visitType(const Type *type) {
Chris Lattner3164ae62018-07-28 09:36:25 -0700126 if (auto *funcType = dyn_cast<FunctionType>(type)) {
MLIR Team4718bc92018-07-17 16:56:54 -0700127 // Visit input and result types for functions.
Chris Lattner3164ae62018-07-28 09:36:25 -0700128 for (auto *input : funcType->getInputs())
MLIR Team4718bc92018-07-17 16:56:54 -0700129 visitType(input);
Chris Lattner3164ae62018-07-28 09:36:25 -0700130 for (auto *result : funcType->getResults())
MLIR Team4718bc92018-07-17 16:56:54 -0700131 visitType(result);
Chris Lattner3164ae62018-07-28 09:36:25 -0700132 } else if (auto *memref = dyn_cast<MemRefType>(type)) {
MLIR Team4718bc92018-07-17 16:56:54 -0700133 // Visit affine maps in memref type.
Chris Lattner3164ae62018-07-28 09:36:25 -0700134 for (auto *map : memref->getAffineMaps()) {
MLIR Team4718bc92018-07-17 16:56:54 -0700135 recordAffineMapReference(map);
136 }
137 }
138}
139
MLIR Teamb61885d2018-07-18 16:29:21 -0700140void ModuleState::visitAttribute(const Attribute *attr) {
Chris Lattner3164ae62018-07-28 09:36:25 -0700141 if (auto *mapAttr = dyn_cast<AffineMapAttr>(attr)) {
142 recordAffineMapReference(mapAttr->getValue());
Uday Bondhugulabc535622018-08-07 14:24:38 -0700143 } else if (auto *arrayAttr = dyn_cast<ArrayAttr>(attr)) {
144 for (auto elt : arrayAttr->getValue()) {
MLIR Teamb61885d2018-07-18 16:29:21 -0700145 visitAttribute(elt);
146 }
147 }
148}
149
150void ModuleState::visitOperation(const Operation *op) {
Chris Lattnerca2ee872018-07-31 18:32:59 -0700151 // Visit all the types used in the operation.
152 for (auto *operand : op->getOperands())
153 visitType(operand->getType());
154 for (auto *result : op->getResults())
155 visitType(result->getType());
156
157 // Visit each of the attributes.
158 for (auto elt : op->getAttrs())
MLIR Teamb61885d2018-07-18 16:29:21 -0700159 visitAttribute(elt.second);
MLIR Teamb61885d2018-07-18 16:29:21 -0700160}
161
MLIR Team4718bc92018-07-17 16:56:54 -0700162void ModuleState::visitExtFunction(const ExtFunction *fn) {
163 visitType(fn->getType());
164}
165
166void ModuleState::visitCFGFunction(const CFGFunction *fn) {
167 visitType(fn->getType());
MLIR Teamb61885d2018-07-18 16:29:21 -0700168 for (auto &block : *fn) {
169 for (auto &op : block.getOperations()) {
170 visitOperation(&op);
171 }
172 }
MLIR Team4718bc92018-07-17 16:56:54 -0700173}
174
Uday Bondhugulabc535622018-08-07 14:24:38 -0700175void ModuleState::visitIfStmt(const IfStmt *ifStmt) {
176 recordIntegerSetReference(ifStmt->getCondition());
177 for (auto &childStmt : *ifStmt->getThenClause())
178 visitStatement(&childStmt);
179 if (ifStmt->hasElseClause())
180 for (auto &childStmt : *ifStmt->getElseClause())
181 visitStatement(&childStmt);
182}
183
184void ModuleState::visitForStmt(const ForStmt *forStmt) {
185 for (auto &childStmt : *forStmt)
186 visitStatement(&childStmt);
187}
188
189void ModuleState::visitOperationStmt(const OperationStmt *opStmt) {
190 // TODO: visit any attributes if necessary.
191}
192
193void ModuleState::visitStatement(const Statement *stmt) {
194 switch (stmt->getKind()) {
195 case Statement::Kind::If:
196 return visitIfStmt(cast<IfStmt>(stmt));
197 case Statement::Kind::For:
198 return visitForStmt(cast<ForStmt>(stmt));
199 case Statement::Kind::Operation:
200 return visitOperationStmt(cast<OperationStmt>(stmt));
201 default:
202 return;
203 }
204}
205
MLIR Team4718bc92018-07-17 16:56:54 -0700206void ModuleState::visitMLFunction(const MLFunction *fn) {
207 visitType(fn->getType());
Uday Bondhugulabc535622018-08-07 14:24:38 -0700208 for (auto &stmt : *fn) {
209 ModuleState::visitStatement(&stmt);
210 }
MLIR Team4718bc92018-07-17 16:56:54 -0700211}
212
213void ModuleState::visitFunction(const Function *fn) {
214 switch (fn->getKind()) {
MLIR Team54b55a22018-07-18 10:16:05 -0700215 case Function::Kind::ExtFunc:
216 return visitExtFunction(cast<ExtFunction>(fn));
217 case Function::Kind::CFGFunc:
218 return visitCFGFunction(cast<CFGFunction>(fn));
219 case Function::Kind::MLFunc:
220 return visitMLFunction(cast<MLFunction>(fn));
MLIR Team4718bc92018-07-17 16:56:54 -0700221 }
222}
223
Uday Bondhugulabc535622018-08-07 14:24:38 -0700224// Initializes module state, populating affine map and integer set state.
Chris Lattner4fd59b02018-07-20 09:35:47 -0700225void ModuleState::initialize(const Module *module) {
Chris Lattnera8e47672018-07-25 14:08:16 -0700226 for (auto &fn : *module) {
227 visitFunction(&fn);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700228 }
229}
230
231//===----------------------------------------------------------------------===//
232// ModulePrinter
233//===----------------------------------------------------------------------===//
234
235namespace {
236class ModulePrinter {
237public:
238 ModulePrinter(raw_ostream &os, ModuleState &state) : os(os), state(state) {}
239 explicit ModulePrinter(const ModulePrinter &printer)
240 : os(printer.os), state(printer.state) {}
241
242 template <typename Container, typename UnaryFunctor>
243 inline void interleaveComma(const Container &c, UnaryFunctor each_fn) const {
244 interleave(c.begin(), c.end(), each_fn, [&]() { os << ", "; });
245 }
246
247 void print(const Module *module);
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700248 void printAttribute(const Attribute *attr);
249 void printType(const Type *type);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700250 void print(const Function *fn);
251 void print(const ExtFunction *fn);
252 void print(const CFGFunction *fn);
253 void print(const MLFunction *fn);
254
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700255 void printAffineMap(const AffineMap *map);
256 void printAffineExpr(const AffineExpr *expr);
Uday Bondhugulabc535622018-08-07 14:24:38 -0700257 void printAffineConstraint(const AffineExpr *expr, bool isEq);
258 void printIntegerSet(const IntegerSet *set);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700259
260protected:
261 raw_ostream &os;
262 ModuleState &state;
263
264 void printFunctionSignature(const Function *fn);
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -0700265 void printFunctionResultType(const FunctionType *type);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700266 void printAffineMapId(int affineMapId) const;
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700267 void printAffineMapReference(const AffineMap *affineMap);
Uday Bondhugulabc535622018-08-07 14:24:38 -0700268 void printIntegerSetId(int integerSetId) const;
269 void printIntegerSetReference(const IntegerSet *integerSet);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700270
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700271 /// This enum is used to represent the binding stength of the enclosing
272 /// context that an AffineExpr is being printed in, so we can intelligently
273 /// produce parens.
274 enum class BindingStrength {
275 Weak, // + and -
276 Strong, // All other binary operators.
277 };
278 void printAffineExprInternal(const AffineExpr *expr,
279 BindingStrength enclosingTightness);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700280};
281} // end anonymous namespace
282
MLIR Team4718bc92018-07-17 16:56:54 -0700283// Prints function with initialized module state.
Chris Lattner4fd59b02018-07-20 09:35:47 -0700284void ModulePrinter::print(const Function *fn) {
MLIR Team4718bc92018-07-17 16:56:54 -0700285 switch (fn->getKind()) {
MLIR Team54b55a22018-07-18 10:16:05 -0700286 case Function::Kind::ExtFunc:
287 return print(cast<ExtFunction>(fn));
288 case Function::Kind::CFGFunc:
289 return print(cast<CFGFunction>(fn));
290 case Function::Kind::MLFunc:
291 return print(cast<MLFunction>(fn));
MLIR Team4718bc92018-07-17 16:56:54 -0700292 }
293}
294
295// Prints affine map identifier.
Chris Lattner4fd59b02018-07-20 09:35:47 -0700296void ModulePrinter::printAffineMapId(int affineMapId) const {
MLIR Team4718bc92018-07-17 16:56:54 -0700297 os << "#map" << affineMapId;
298}
299
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700300void ModulePrinter::printAffineMapReference(const AffineMap *affineMap) {
Chris Lattner4fd59b02018-07-20 09:35:47 -0700301 int mapId = state.getAffineMapId(affineMap);
MLIR Teamb61885d2018-07-18 16:29:21 -0700302 if (mapId >= 0) {
303 // Map will be printed at top of module so print reference to its id.
304 printAffineMapId(mapId);
305 } else {
306 // Map not in module state so print inline.
307 affineMap->print(os);
308 }
309}
310
Uday Bondhugulabc535622018-08-07 14:24:38 -0700311// Prints integer set identifier.
312void ModulePrinter::printIntegerSetId(int integerSetId) const {
313 os << "@@set" << integerSetId;
314}
315
316void ModulePrinter::printIntegerSetReference(const IntegerSet *integerSet) {
317 int setId;
318 if ((setId = state.getIntegerSetId(integerSet)) >= 0) {
319 // The set will be printed at top of module; so print reference to its id.
320 printIntegerSetId(setId);
321 } else {
322 // Set not in module state so print inline.
323 integerSet->print(os);
324 }
325}
326
Chris Lattner4fd59b02018-07-20 09:35:47 -0700327void ModulePrinter::print(const Module *module) {
James Molloyc4666722018-07-24 09:48:31 -0700328 for (const auto &map : state.getAffineMapIds()) {
329 printAffineMapId(state.getAffineMapId(map));
MLIR Team4718bc92018-07-17 16:56:54 -0700330 os << " = ";
James Molloyc4666722018-07-24 09:48:31 -0700331 map->print(os);
MLIR Team4718bc92018-07-17 16:56:54 -0700332 os << '\n';
333 }
Uday Bondhugulabc535622018-08-07 14:24:38 -0700334 for (const auto &set : state.getIntegerSetIds()) {
335 printIntegerSetId(state.getIntegerSetId(set));
336 os << " = ";
337 set->print(os);
338 os << '\n';
339 }
Chris Lattnera8e47672018-07-25 14:08:16 -0700340 for (auto const &fn : *module)
341 print(&fn);
MLIR Team4718bc92018-07-17 16:56:54 -0700342}
343
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700344void ModulePrinter::printAttribute(const Attribute *attr) {
MLIR Teamb61885d2018-07-18 16:29:21 -0700345 switch (attr->getKind()) {
346 case Attribute::Kind::Bool:
347 os << (cast<BoolAttr>(attr)->getValue() ? "true" : "false");
348 break;
349 case Attribute::Kind::Integer:
350 os << cast<IntegerAttr>(attr)->getValue();
351 break;
352 case Attribute::Kind::Float:
353 // FIXME: this isn't precise, we should print with a hex format.
354 os << cast<FloatAttr>(attr)->getValue();
355 break;
356 case Attribute::Kind::String:
357 // FIXME: should escape the string.
358 os << '"' << cast<StringAttr>(attr)->getValue() << '"';
359 break;
360 case Attribute::Kind::Array: {
361 auto elts = cast<ArrayAttr>(attr)->getValue();
362 os << '[';
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700363 interleaveComma(elts, [&](Attribute *attr) { printAttribute(attr); });
MLIR Teamb61885d2018-07-18 16:29:21 -0700364 os << ']';
365 break;
366 }
367 case Attribute::Kind::AffineMap:
368 printAffineMapReference(cast<AffineMapAttr>(attr)->getValue());
369 break;
James Molloyf0d2f442018-08-03 01:54:46 -0700370 case Attribute::Kind::Type:
371 printType(cast<TypeAttr>(attr)->getValue());
372 break;
MLIR Teamb61885d2018-07-18 16:29:21 -0700373 }
374}
375
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700376void ModulePrinter::printType(const Type *type) {
MLIR Team4718bc92018-07-17 16:56:54 -0700377 switch (type->getKind()) {
MLIR Team54b55a22018-07-18 10:16:05 -0700378 case Type::Kind::AffineInt:
379 os << "affineint";
380 return;
381 case Type::Kind::BF16:
382 os << "bf16";
383 return;
384 case Type::Kind::F16:
385 os << "f16";
386 return;
387 case Type::Kind::F32:
388 os << "f32";
389 return;
390 case Type::Kind::F64:
391 os << "f64";
392 return;
Jacques Pienaarc0d69302018-07-27 11:07:12 -0700393 case Type::Kind::TFControl:
394 os << "tf_control";
395 return;
James Molloy72b0cbe2018-08-01 12:55:27 -0700396 case Type::Kind::TFString:
397 os << "tf_string";
398 return;
MLIR Team4718bc92018-07-17 16:56:54 -0700399
400 case Type::Kind::Integer: {
401 auto *integer = cast<IntegerType>(type);
402 os << 'i' << integer->getWidth();
403 return;
404 }
405 case Type::Kind::Function: {
406 auto *func = cast<FunctionType>(type);
407 os << '(';
Chris Lattner413db6a2018-07-25 12:55:50 -0700408 interleaveComma(func->getInputs(), [&](Type *type) { printType(type); });
MLIR Team4718bc92018-07-17 16:56:54 -0700409 os << ") -> ";
410 auto results = func->getResults();
411 if (results.size() == 1)
412 os << *results[0];
413 else {
414 os << '(';
Chris Lattner413db6a2018-07-25 12:55:50 -0700415 interleaveComma(results, [&](Type *type) { printType(type); });
MLIR Team4718bc92018-07-17 16:56:54 -0700416 os << ')';
417 }
418 return;
419 }
420 case Type::Kind::Vector: {
421 auto *v = cast<VectorType>(type);
422 os << "vector<";
James Molloy87d81022018-07-23 11:44:40 -0700423 for (auto dim : v->getShape())
424 os << dim << 'x';
MLIR Team4718bc92018-07-17 16:56:54 -0700425 os << *v->getElementType() << '>';
426 return;
427 }
428 case Type::Kind::RankedTensor: {
429 auto *v = cast<RankedTensorType>(type);
430 os << "tensor<";
431 for (auto dim : v->getShape()) {
432 if (dim < 0)
433 os << '?';
434 else
435 os << dim;
436 os << 'x';
437 }
438 os << *v->getElementType() << '>';
439 return;
440 }
441 case Type::Kind::UnrankedTensor: {
442 auto *v = cast<UnrankedTensorType>(type);
Chris Lattner413db6a2018-07-25 12:55:50 -0700443 os << "tensor<??";
444 printType(v->getElementType());
445 os << '>';
MLIR Team4718bc92018-07-17 16:56:54 -0700446 return;
447 }
448 case Type::Kind::MemRef: {
449 auto *v = cast<MemRefType>(type);
450 os << "memref<";
451 for (auto dim : v->getShape()) {
452 if (dim < 0)
453 os << '?';
454 else
455 os << dim;
456 os << 'x';
457 }
Chris Lattner413db6a2018-07-25 12:55:50 -0700458 printType(v->getElementType());
MLIR Team4718bc92018-07-17 16:56:54 -0700459 for (auto map : v->getAffineMaps()) {
460 os << ", ";
MLIR Teamb61885d2018-07-18 16:29:21 -0700461 printAffineMapReference(map);
MLIR Team4718bc92018-07-17 16:56:54 -0700462 }
Chris Lattner413db6a2018-07-25 12:55:50 -0700463 // Only print the memory space if it is the non-default one.
464 if (v->getMemorySpace())
465 os << ", " << v->getMemorySpace();
MLIR Team4718bc92018-07-17 16:56:54 -0700466 os << '>';
467 return;
468 }
469 }
470}
471
472//===----------------------------------------------------------------------===//
Chris Lattner4fd59b02018-07-20 09:35:47 -0700473// Affine expressions and maps
474//===----------------------------------------------------------------------===//
475
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700476void ModulePrinter::printAffineExpr(const AffineExpr *expr) {
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700477 printAffineExprInternal(expr, BindingStrength::Weak);
478}
479
480void ModulePrinter::printAffineExprInternal(
481 const AffineExpr *expr, BindingStrength enclosingTightness) {
482 const char *binopSpelling = nullptr;
Chris Lattner4fd59b02018-07-20 09:35:47 -0700483 switch (expr->getKind()) {
484 case AffineExpr::Kind::SymbolId:
485 os << 's' << cast<AffineSymbolExpr>(expr)->getPosition();
486 return;
487 case AffineExpr::Kind::DimId:
488 os << 'd' << cast<AffineDimExpr>(expr)->getPosition();
489 return;
490 case AffineExpr::Kind::Constant:
491 os << cast<AffineConstantExpr>(expr)->getValue();
492 return;
493 case AffineExpr::Kind::Add:
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700494 binopSpelling = " + ";
495 break;
Chris Lattner4fd59b02018-07-20 09:35:47 -0700496 case AffineExpr::Kind::Mul:
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700497 binopSpelling = " * ";
498 break;
Chris Lattner4fd59b02018-07-20 09:35:47 -0700499 case AffineExpr::Kind::FloorDiv:
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700500 binopSpelling = " floordiv ";
501 break;
Chris Lattner4fd59b02018-07-20 09:35:47 -0700502 case AffineExpr::Kind::CeilDiv:
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700503 binopSpelling = " ceildiv ";
504 break;
Chris Lattner4fd59b02018-07-20 09:35:47 -0700505 case AffineExpr::Kind::Mod:
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700506 binopSpelling = " mod ";
507 break;
Chris Lattner4fd59b02018-07-20 09:35:47 -0700508 }
Chris Lattner4fd59b02018-07-20 09:35:47 -0700509
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700510 auto *binOp = cast<AffineBinaryOpExpr>(expr);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700511
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700512 // Handle tightly binding binary operators.
513 if (binOp->getKind() != AffineExpr::Kind::Add) {
514 if (enclosingTightness == BindingStrength::Strong)
515 os << '(';
516
517 printAffineExprInternal(binOp->getLHS(), BindingStrength::Strong);
518 os << binopSpelling;
519 printAffineExprInternal(binOp->getRHS(), BindingStrength::Strong);
520
521 if (enclosingTightness == BindingStrength::Strong)
522 os << ')';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700523 return;
524 }
525
526 // Print out special "pretty" forms for add.
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700527 if (enclosingTightness == BindingStrength::Strong)
528 os << '(';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700529
530 // Pretty print addition to a product that has a negative operand as a
531 // subtraction.
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700532 if (auto *rhs = dyn_cast<AffineBinaryOpExpr>(binOp->getRHS())) {
Chris Lattner4fd59b02018-07-20 09:35:47 -0700533 if (rhs->getKind() == AffineExpr::Kind::Mul) {
534 if (auto *rrhs = dyn_cast<AffineConstantExpr>(rhs->getRHS())) {
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700535 if (rrhs->getValue() == -1) {
536 printAffineExprInternal(binOp->getLHS(), BindingStrength::Weak);
537 os << " - ";
538 printAffineExprInternal(rhs->getLHS(), BindingStrength::Weak);
539
540 if (enclosingTightness == BindingStrength::Strong)
541 os << ')';
542 return;
543 }
544
545 if (rrhs->getValue() < -1) {
546 printAffineExprInternal(binOp->getLHS(), BindingStrength::Weak);
Uday Bondhugula970f5b82018-08-01 22:02:00 -0700547 os << " - ";
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700548 printAffineExprInternal(rhs->getLHS(), BindingStrength::Strong);
Uday Bondhugula970f5b82018-08-01 22:02:00 -0700549 os << " * " << -rrhs->getValue();
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700550 if (enclosingTightness == BindingStrength::Strong)
551 os << ')';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700552 return;
553 }
554 }
555 }
556 }
557
558 // Pretty print addition to a negative number as a subtraction.
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700559 if (auto *rhs = dyn_cast<AffineConstantExpr>(binOp->getRHS())) {
Chris Lattner4fd59b02018-07-20 09:35:47 -0700560 if (rhs->getValue() < 0) {
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700561 printAffineExprInternal(binOp->getLHS(), BindingStrength::Weak);
Uday Bondhugulabc535622018-08-07 14:24:38 -0700562 os << " - " << -rhs->getValue();
563 if (enclosingTightness == BindingStrength::Strong)
564 os << ')';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700565 return;
566 }
567 }
568
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700569 printAffineExprInternal(binOp->getLHS(), BindingStrength::Weak);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700570 os << " + ";
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700571 printAffineExprInternal(binOp->getRHS(), BindingStrength::Weak);
572
573 if (enclosingTightness == BindingStrength::Strong)
574 os << ')';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700575}
576
Uday Bondhugulabc535622018-08-07 14:24:38 -0700577void ModulePrinter::printAffineConstraint(const AffineExpr *expr, bool isEq) {
578 printAffineExprInternal(expr, BindingStrength::Weak);
579 isEq ? os << " == 0" : os << " >= 0";
580}
581
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700582void ModulePrinter::printAffineMap(const AffineMap *map) {
Chris Lattner4fd59b02018-07-20 09:35:47 -0700583 // Dimension identifiers.
584 os << '(';
Chris Lattnerdc3ba382018-07-29 14:13:03 -0700585 for (int i = 0; i < (int)map->getNumDims() - 1; ++i)
586 os << 'd' << i << ", ";
Chris Lattner4fd59b02018-07-20 09:35:47 -0700587 if (map->getNumDims() >= 1)
Chris Lattnerdc3ba382018-07-29 14:13:03 -0700588 os << 'd' << map->getNumDims() - 1;
589 os << ')';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700590
591 // Symbolic identifiers.
Chris Lattnerdc3ba382018-07-29 14:13:03 -0700592 if (map->getNumSymbols() != 0) {
593 os << '[';
594 for (unsigned i = 0; i < map->getNumSymbols() - 1; ++i)
595 os << 's' << i << ", ";
Chris Lattner4fd59b02018-07-20 09:35:47 -0700596 if (map->getNumSymbols() >= 1)
Chris Lattnerdc3ba382018-07-29 14:13:03 -0700597 os << 's' << map->getNumSymbols() - 1;
598 os << ']';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700599 }
600
601 // AffineMap should have at least one result.
602 assert(!map->getResults().empty());
603 // Result affine expressions.
604 os << " -> (";
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700605 interleaveComma(map->getResults(),
606 [&](AffineExpr *expr) { printAffineExpr(expr); });
Chris Lattnerdc3ba382018-07-29 14:13:03 -0700607 os << ')';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700608
609 if (!map->isBounded()) {
610 return;
611 }
612
613 // Print range sizes for bounded affine maps.
614 os << " size (";
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700615 interleaveComma(map->getRangeSizes(),
616 [&](AffineExpr *expr) { printAffineExpr(expr); });
Chris Lattnerdc3ba382018-07-29 14:13:03 -0700617 os << ')';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700618}
619
Uday Bondhugulabc535622018-08-07 14:24:38 -0700620void ModulePrinter::printIntegerSet(const IntegerSet *set) {
621 // Dimension identifiers.
622 os << '(';
623 for (unsigned i = 1; i < set->getNumDims(); ++i)
624 os << 'd' << i - 1 << ", ";
625 if (set->getNumDims() >= 1)
626 os << 'd' << set->getNumDims() - 1;
627 os << ')';
628
629 // Symbolic identifiers.
630 if (set->getNumSymbols() != 0) {
631 os << '[';
632 for (unsigned i = 0; i < set->getNumSymbols() - 1; ++i)
633 os << 's' << i << ", ";
634 if (set->getNumSymbols() >= 1)
635 os << 's' << set->getNumSymbols() - 1;
636 os << ']';
637 }
638
639 // Print constraints.
640 os << " : (";
641 auto numConstraints = set->getNumConstraints();
642 for (int i = 1; i < numConstraints; ++i) {
643 printAffineConstraint(set->getConstraint(i - 1), set->isEq(i - 1));
644 os << ", ";
645 }
646 if (numConstraints >= 1)
647 printAffineConstraint(set->getConstraint(numConstraints - 1),
648 set->isEq(numConstraints - 1));
649 os << ')';
650}
651
Chris Lattner4fd59b02018-07-20 09:35:47 -0700652//===----------------------------------------------------------------------===//
Chris Lattner4c95a502018-06-23 16:03:42 -0700653// Function printing
654//===----------------------------------------------------------------------===//
655
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -0700656void ModulePrinter::printFunctionResultType(const FunctionType *type) {
Chris Lattner4c95a502018-06-23 16:03:42 -0700657 switch (type->getResults().size()) {
MLIR Team54b55a22018-07-18 10:16:05 -0700658 case 0:
659 break;
Chris Lattner4c95a502018-06-23 16:03:42 -0700660 case 1:
MLIR Team4718bc92018-07-17 16:56:54 -0700661 os << " -> ";
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700662 printType(type->getResults()[0]);
Chris Lattner4c95a502018-06-23 16:03:42 -0700663 break;
664 default:
665 os << " -> (";
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700666 interleaveComma(type->getResults(),
667 [&](Type *eltType) { printType(eltType); });
Chris Lattner4c95a502018-06-23 16:03:42 -0700668 os << ')';
669 break;
670 }
671}
672
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -0700673void ModulePrinter::printFunctionSignature(const Function *fn) {
674 auto type = fn->getType();
675
676 os << "@" << fn->getName() << '(';
677 interleaveComma(type->getInputs(),
678 [&](Type *eltType) { printType(eltType); });
679 os << ')';
680
681 printFunctionResultType(type);
682}
683
Chris Lattner4fd59b02018-07-20 09:35:47 -0700684void ModulePrinter::print(const ExtFunction *fn) {
Chris Lattner4c95a502018-06-23 16:03:42 -0700685 os << "extfunc ";
Chris Lattner4fd59b02018-07-20 09:35:47 -0700686 printFunctionSignature(fn);
MLIR Team54b55a22018-07-18 10:16:05 -0700687 os << '\n';
Chris Lattner4c95a502018-06-23 16:03:42 -0700688}
689
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700690namespace {
691
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700692// FunctionPrinter contains common functionality for printing
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700693// CFG and ML functions.
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700694class FunctionPrinter : public ModulePrinter, private OpAsmPrinter {
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700695public:
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700696 FunctionPrinter(const ModulePrinter &other) : ModulePrinter(other) {}
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700697
698 void printOperation(const Operation *op);
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700699 void printDefaultOp(const Operation *op);
700
701 // Implement OpAsmPrinter.
702 raw_ostream &getStream() const { return os; }
703 void printType(const Type *type) { ModulePrinter::printType(type); }
704 void printAttribute(const Attribute *attr) {
705 ModulePrinter::printAttribute(attr);
706 }
707 void printAffineMap(const AffineMap *map) {
Chris Lattner3164ae62018-07-28 09:36:25 -0700708 return ModulePrinter::printAffineMapReference(map);
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700709 }
Uday Bondhugulabc535622018-08-07 14:24:38 -0700710 void printIntegerSet(const IntegerSet *set) {
711 return ModulePrinter::printIntegerSetReference(set);
712 }
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700713 void printAffineExpr(const AffineExpr *expr) {
714 return ModulePrinter::printAffineExpr(expr);
715 }
716
717 void printOperand(const SSAValue *value) { printValueID(value); }
Tatiana Shpeismanc335d182018-08-03 11:12:34 -0700718
Chris Lattner85cf26d2018-08-02 16:54:36 -0700719 void printOptionalAttrDict(ArrayRef<NamedAttribute> attrs,
720 ArrayRef<const char *> elidedAttrs = {}) override;
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700721
Chris Lattnerd4964212018-08-01 10:43:18 -0700722 enum { nameSentinel = ~0U };
723
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700724protected:
Chris Lattnerf8cce872018-07-20 09:28:54 -0700725 void numberValueID(const SSAValue *value) {
726 assert(!valueIDs.count(value) && "Value numbered multiple times");
Chris Lattnerd4964212018-08-01 10:43:18 -0700727
728 SmallString<32> specialNameBuffer;
729 llvm::raw_svector_ostream specialName(specialNameBuffer);
730
731 // Give constant integers special names.
732 if (auto *op = value->getDefiningOperation()) {
733 if (auto intOp = op->getAs<ConstantIntOp>()) {
Chris Lattner384da8c2018-08-02 17:16:58 -0700734 // i1 constants get special names.
735 if (intOp->getType()->isInteger(1)) {
736 specialName << (intOp->getValue() ? "true" : "false");
737 } else {
Chris Lattner992a1272018-08-07 12:02:37 -0700738 specialName << 'c' << intOp->getValue() << '_' << *intOp->getType();
Chris Lattner384da8c2018-08-02 17:16:58 -0700739 }
Chris Lattner992a1272018-08-07 12:02:37 -0700740 } else if (auto intOp = op->getAs<ConstantAffineIntOp>()) {
741 specialName << 'c' << intOp->getValue();
Chris Lattnerd4964212018-08-01 10:43:18 -0700742 }
Tatiana Shpeisman3838db72018-07-30 15:18:10 -0700743 }
Chris Lattnerd4964212018-08-01 10:43:18 -0700744
745 if (specialNameBuffer.empty()) {
746 switch (value->getKind()) {
747 case SSAValueKind::BBArgument:
748 // If this is an argument to the function, give it an 'arg' name.
749 if (auto *bb = cast<BBArgument>(value)->getOwner())
750 if (auto *fn = bb->getFunction())
751 if (&fn->front() == bb) {
752 specialName << "arg" << nextArgumentID++;
753 break;
754 }
755 // Otherwise number it normally.
756 LLVM_FALLTHROUGH;
757 case SSAValueKind::InstResult:
758 case SSAValueKind::StmtResult:
759 // This is an uninteresting result, give it a boring number and be
760 // done with it.
761 valueIDs[value] = nextValueID++;
762 return;
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -0700763 case SSAValueKind::MLFuncArgument:
Chris Lattnerd4964212018-08-01 10:43:18 -0700764 specialName << "arg" << nextArgumentID++;
765 break;
766 case SSAValueKind::ForStmt:
767 specialName << 'i' << nextLoopID++;
768 break;
769 }
770 }
771
772 // Ok, this value had an interesting name. Remember it with a sentinel.
773 valueIDs[value] = nameSentinel;
774
775 // Remember that we've used this name, checking to see if we had a conflict.
776 auto insertRes = usedNames.insert(specialName.str());
777 if (insertRes.second) {
778 // If this is the first use of the name, then we're successful!
779 valueNames[value] = insertRes.first->first();
780 return;
781 }
782
783 // Otherwise, we had a conflict - probe until we find a unique name. This
784 // is guaranteed to terminate (and usually in a single iteration) because it
785 // generates new names by incrementing nextConflictID.
786 while (1) {
787 std::string probeName =
788 specialName.str().str() + "_" + llvm::utostr(nextConflictID++);
789 insertRes = usedNames.insert(probeName);
790 if (insertRes.second) {
791 // If this is the first use of the name, then we're successful!
792 valueNames[value] = insertRes.first->first();
793 return;
794 }
795 }
Chris Lattnerf8cce872018-07-20 09:28:54 -0700796 }
797
Tatiana Shpeisman3838db72018-07-30 15:18:10 -0700798 void printValueID(const SSAValue *value, bool printResultNo = true) const {
Chris Lattner6119d382018-07-20 18:41:34 -0700799 int resultNo = -1;
800 auto lookupValue = value;
801
Tatiana Shpeisman3838db72018-07-30 15:18:10 -0700802 // If this is a reference to the result of a multi-result instruction or
803 // statement, print out the # identifier and make sure to map our lookup
804 // to the first result of the instruction.
Chris Lattner6119d382018-07-20 18:41:34 -0700805 if (auto *result = dyn_cast<InstResult>(value)) {
806 if (result->getOwner()->getNumResults() != 1) {
807 resultNo = result->getResultNumber();
808 lookupValue = result->getOwner()->getResult(0);
809 }
Tatiana Shpeisman3838db72018-07-30 15:18:10 -0700810 } else if (auto *result = dyn_cast<StmtResult>(value)) {
811 if (result->getOwner()->getNumResults() != 1) {
812 resultNo = result->getResultNumber();
813 lookupValue = result->getOwner()->getResult(0);
814 }
Chris Lattner6119d382018-07-20 18:41:34 -0700815 }
816
817 auto it = valueIDs.find(lookupValue);
818 if (it == valueIDs.end()) {
Chris Lattnerf8cce872018-07-20 09:28:54 -0700819 os << "<<INVALID SSA VALUE>>";
Chris Lattner6119d382018-07-20 18:41:34 -0700820 return;
821 }
822
Tatiana Shpeisman3838db72018-07-30 15:18:10 -0700823 os << '%';
Chris Lattnerd4964212018-08-01 10:43:18 -0700824 if (it->second != nameSentinel) {
825 os << it->second;
826 } else {
827 auto nameIt = valueNames.find(lookupValue);
828 assert(nameIt != valueNames.end() && "Didn't have a name entry?");
829 os << nameIt->second;
830 }
Tatiana Shpeisman3838db72018-07-30 15:18:10 -0700831
Tatiana Shpeisman3838db72018-07-30 15:18:10 -0700832 if (resultNo != -1 && printResultNo)
Chris Lattner6119d382018-07-20 18:41:34 -0700833 os << '#' << resultNo;
Chris Lattnerf8cce872018-07-20 09:28:54 -0700834 }
835
836private:
Chris Lattnerd4964212018-08-01 10:43:18 -0700837 /// This is the value ID for each SSA value in the current function. If this
838 /// returns ~0, then the valueID has an entry in valueNames.
Chris Lattnerf8cce872018-07-20 09:28:54 -0700839 DenseMap<const SSAValue *, unsigned> valueIDs;
Chris Lattnerd4964212018-08-01 10:43:18 -0700840 DenseMap<const SSAValue *, StringRef> valueNames;
841
842 /// This keeps track of all of the non-numeric names that are in flight,
843 /// allowing us to check for duplicates.
844 llvm::StringSet<> usedNames;
845
846 /// This is the next value ID to assign in numbering.
Chris Lattnerf8cce872018-07-20 09:28:54 -0700847 unsigned nextValueID = 0;
Chris Lattnerd4964212018-08-01 10:43:18 -0700848 /// This is the ID to assign to the next induction variable.
Tatiana Shpeismanc9c4b342018-07-31 07:40:14 -0700849 unsigned nextLoopID = 0;
Chris Lattnerd4964212018-08-01 10:43:18 -0700850 /// This is the next ID to assign to an MLFunction argument.
851 unsigned nextArgumentID = 0;
852
853 /// This is the next ID to assign when a name conflict is detected.
854 unsigned nextConflictID = 0;
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700855};
James Molloy87d81022018-07-23 11:44:40 -0700856} // end anonymous namespace
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700857
Chris Lattner85cf26d2018-08-02 16:54:36 -0700858void FunctionPrinter::printOptionalAttrDict(
859 ArrayRef<NamedAttribute> attrs, ArrayRef<const char *> elidedAttrs) {
860 // If there are no attributes, then there is nothing to be done.
861 if (attrs.empty())
862 return;
863
864 // Filter out any attributes that shouldn't be included.
865 SmallVector<NamedAttribute, 8> filteredAttrs;
866 for (auto attr : attrs) {
867 auto attrName = attr.first.str();
868 // Never print attributes that start with a colon. These are internal
869 // attributes that represent location or other internal metadata.
870 if (attrName.startswith(":"))
871 continue;
872
873 // If the caller has requested that this attribute be ignored, then drop it.
874 bool ignore = false;
875 for (const char *elide : elidedAttrs)
876 ignore |= attrName == StringRef(elide);
877
878 // Otherwise add it to our filteredAttrs list.
879 if (!ignore)
880 filteredAttrs.push_back(attr);
881 }
882
883 // If there are no attributes left to print after filtering, then we're done.
884 if (filteredAttrs.empty())
885 return;
886
887 // Otherwise, print them all out in braces.
888 os << " {";
889 interleaveComma(filteredAttrs, [&](NamedAttribute attr) {
890 os << attr.first << ": ";
891 printAttribute(attr.second);
892 });
893 os << '}';
894}
895
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700896void FunctionPrinter::printOperation(const Operation *op) {
Chris Lattnerac591f12018-07-22 21:02:26 -0700897 if (op->getNumResults()) {
Tatiana Shpeisman3838db72018-07-30 15:18:10 -0700898 printValueID(op->getResult(0), /*printResultNo=*/false);
Chris Lattnerac591f12018-07-22 21:02:26 -0700899 os << " = ";
Chris Lattnerf8cce872018-07-20 09:28:54 -0700900 }
901
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700902 // Check to see if this is a known operation. If so, use the registered
903 // custom printer hook.
Chris Lattner4fd59b02018-07-20 09:35:47 -0700904 if (auto opInfo = state.operationSet->lookup(op->getName().str())) {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700905 opInfo->printAssembly(op, this);
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700906 return;
907 }
908
Chris Lattnerf8cce872018-07-20 09:28:54 -0700909 // Otherwise use the standard verbose printing approach.
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700910 printDefaultOp(op);
911}
Chris Lattnerf8cce872018-07-20 09:28:54 -0700912
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700913void FunctionPrinter::printDefaultOp(const Operation *op) {
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700914 // TODO: escape name if necessary.
Chris Lattnerf8cce872018-07-20 09:28:54 -0700915 os << "\"" << op->getName().str() << "\"(";
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700916
Chris Lattnerac591f12018-07-22 21:02:26 -0700917 interleaveComma(op->getOperands(),
918 [&](const SSAValue *value) { printValueID(value); });
Chris Lattner7f9cc272018-07-19 08:35:28 -0700919
Chris Lattnerf8cce872018-07-20 09:28:54 -0700920 os << ')';
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700921 auto attrs = op->getAttrs();
Chris Lattner85cf26d2018-08-02 16:54:36 -0700922 printOptionalAttrDict(attrs);
Chris Lattner3b2ef762018-07-18 15:31:25 -0700923
Chris Lattnerac591f12018-07-22 21:02:26 -0700924 // Print the type signature of the operation.
925 os << " : (";
926 interleaveComma(op->getOperands(),
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700927 [&](const SSAValue *value) { printType(value->getType()); });
Chris Lattnerac591f12018-07-22 21:02:26 -0700928 os << ") -> ";
Chris Lattnerf8cce872018-07-20 09:28:54 -0700929
Chris Lattnerac591f12018-07-22 21:02:26 -0700930 if (op->getNumResults() == 1) {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700931 printType(op->getResult(0)->getType());
Chris Lattnerac591f12018-07-22 21:02:26 -0700932 } else {
933 os << '(';
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700934 interleaveComma(op->getResults(), [&](const SSAValue *result) {
935 printType(result->getType());
936 });
Chris Lattnerac591f12018-07-22 21:02:26 -0700937 os << ')';
Chris Lattnerf8cce872018-07-20 09:28:54 -0700938 }
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700939}
940
Chris Lattner4c95a502018-06-23 16:03:42 -0700941//===----------------------------------------------------------------------===//
942// CFG Function printing
943//===----------------------------------------------------------------------===//
944
945namespace {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700946class CFGFunctionPrinter : public FunctionPrinter {
Chris Lattner4c95a502018-06-23 16:03:42 -0700947public:
Chris Lattner4fd59b02018-07-20 09:35:47 -0700948 CFGFunctionPrinter(const CFGFunction *function, const ModulePrinter &other);
Chris Lattner4c95a502018-06-23 16:03:42 -0700949
950 const CFGFunction *getFunction() const { return function; }
951
952 void print();
953 void print(const BasicBlock *block);
Chris Lattnered65a732018-06-28 20:45:33 -0700954
955 void print(const Instruction *inst);
956 void print(const OperationInst *inst);
957 void print(const ReturnInst *inst);
958 void print(const BranchInst *inst);
James Molloy4f788372018-07-24 15:01:27 -0700959 void print(const CondBranchInst *inst);
Chris Lattner4c95a502018-06-23 16:03:42 -0700960
961 unsigned getBBID(const BasicBlock *block) {
962 auto it = basicBlockIDs.find(block);
963 assert(it != basicBlockIDs.end() && "Block not in this function?");
964 return it->second;
965 }
966
967private:
968 const CFGFunction *function;
MLIR Team54b55a22018-07-18 10:16:05 -0700969 DenseMap<const BasicBlock *, unsigned> basicBlockIDs;
Chris Lattnerf8cce872018-07-20 09:28:54 -0700970
Chris Lattner4fd59b02018-07-20 09:35:47 -0700971 void numberValuesInBlock(const BasicBlock *block);
Chris Lattner4c95a502018-06-23 16:03:42 -0700972};
James Molloy87d81022018-07-23 11:44:40 -0700973} // end anonymous namespace
Chris Lattner4c95a502018-06-23 16:03:42 -0700974
Chris Lattner4fd59b02018-07-20 09:35:47 -0700975CFGFunctionPrinter::CFGFunctionPrinter(const CFGFunction *function,
976 const ModulePrinter &other)
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700977 : FunctionPrinter(other), function(function) {
Chris Lattner4c95a502018-06-23 16:03:42 -0700978 // Each basic block gets a unique ID per function.
979 unsigned blockID = 0;
Chris Lattnerf8cce872018-07-20 09:28:54 -0700980 for (auto &block : *function) {
981 basicBlockIDs[&block] = blockID++;
Chris Lattner4fd59b02018-07-20 09:35:47 -0700982 numberValuesInBlock(&block);
Chris Lattnerf8cce872018-07-20 09:28:54 -0700983 }
984}
985
986/// Number all of the SSA values in the specified basic block.
Chris Lattner4fd59b02018-07-20 09:35:47 -0700987void CFGFunctionPrinter::numberValuesInBlock(const BasicBlock *block) {
James Molloy61a656c2018-07-22 15:45:24 -0700988 for (auto *arg : block->getArguments()) {
989 numberValueID(arg);
990 }
Chris Lattnerf8cce872018-07-20 09:28:54 -0700991 for (auto &op : *block) {
992 // We number instruction that have results, and we only number the first
993 // result.
994 if (op.getNumResults() != 0)
995 numberValueID(op.getResult(0));
996 }
997
998 // Terminators do not define values.
Chris Lattner4c95a502018-06-23 16:03:42 -0700999}
1000
Chris Lattner4fd59b02018-07-20 09:35:47 -07001001void CFGFunctionPrinter::print() {
Chris Lattner4c95a502018-06-23 16:03:42 -07001002 os << "cfgfunc ";
Chris Lattner4fd59b02018-07-20 09:35:47 -07001003 printFunctionSignature(getFunction());
Chris Lattner4c95a502018-06-23 16:03:42 -07001004 os << " {\n";
1005
James Molloy87d81022018-07-23 11:44:40 -07001006 for (auto &block : *function)
1007 print(&block);
Chris Lattner4c95a502018-06-23 16:03:42 -07001008 os << "}\n\n";
1009}
1010
Chris Lattner4fd59b02018-07-20 09:35:47 -07001011void CFGFunctionPrinter::print(const BasicBlock *block) {
James Molloy61a656c2018-07-22 15:45:24 -07001012 os << "bb" << getBBID(block);
Chris Lattner4c95a502018-06-23 16:03:42 -07001013
James Molloy61a656c2018-07-22 15:45:24 -07001014 if (!block->args_empty()) {
1015 os << '(';
1016 interleaveComma(block->getArguments(), [&](const BBArgument *arg) {
1017 printValueID(arg);
1018 os << ": ";
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -07001019 printType(arg->getType());
James Molloy61a656c2018-07-22 15:45:24 -07001020 });
1021 os << ')';
1022 }
Chris Lattner25ce3062018-07-27 11:10:12 -07001023 os << ':';
1024
1025 // Print out some context information about the predecessors of this block.
1026 if (!block->getFunction()) {
1027 os << "\t// block is not in a function!";
1028 } else if (block->hasNoPredecessors()) {
1029 // Don't print "no predecessors" for the entry block.
1030 if (block != &block->getFunction()->front())
1031 os << "\t// no predecessors";
1032 } else if (auto *pred = block->getSinglePredecessor()) {
1033 os << "\t// pred: bb" << getBBID(pred);
1034 } else {
1035 // We want to print the predecessors in increasing numeric order, not in
1036 // whatever order the use-list is in, so gather and sort them.
1037 SmallVector<unsigned, 4> predIDs;
1038 for (auto *pred : block->getPredecessors())
1039 predIDs.push_back(getBBID(pred));
1040 llvm::array_pod_sort(predIDs.begin(), predIDs.end());
1041
1042 os << "\t// " << predIDs.size() << " preds: ";
1043
1044 interleaveComma(predIDs, [&](unsigned predID) { os << "bb" << predID; });
1045 }
1046 os << '\n';
James Molloy61a656c2018-07-22 15:45:24 -07001047
Jacques Pienaarb020c542018-07-15 00:06:54 -07001048 for (auto &inst : block->getOperations()) {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001049 os << " ";
Chris Lattner3a467cc2018-07-01 20:28:00 -07001050 print(&inst);
James Molloy61a656c2018-07-22 15:45:24 -07001051 os << '\n';
Jacques Pienaarb020c542018-07-15 00:06:54 -07001052 }
Chris Lattner4c95a502018-06-23 16:03:42 -07001053
James Molloy6e4519b2018-08-03 03:51:38 -07001054 os << " ";
Chris Lattner4c95a502018-06-23 16:03:42 -07001055 print(block->getTerminator());
James Molloy61a656c2018-07-22 15:45:24 -07001056 os << '\n';
Chris Lattner4c95a502018-06-23 16:03:42 -07001057}
1058
Chris Lattner4fd59b02018-07-20 09:35:47 -07001059void CFGFunctionPrinter::print(const Instruction *inst) {
Chris Lattner4c95a502018-06-23 16:03:42 -07001060 switch (inst->getKind()) {
Chris Lattnered65a732018-06-28 20:45:33 -07001061 case Instruction::Kind::Operation:
1062 return print(cast<OperationInst>(inst));
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001063 case TerminatorInst::Kind::Branch:
Chris Lattnered65a732018-06-28 20:45:33 -07001064 return print(cast<BranchInst>(inst));
James Molloy4f788372018-07-24 15:01:27 -07001065 case TerminatorInst::Kind::CondBranch:
1066 return print(cast<CondBranchInst>(inst));
Chris Lattner4c95a502018-06-23 16:03:42 -07001067 case TerminatorInst::Kind::Return:
Chris Lattnered65a732018-06-28 20:45:33 -07001068 return print(cast<ReturnInst>(inst));
Chris Lattner4c95a502018-06-23 16:03:42 -07001069 }
1070}
1071
Chris Lattner4fd59b02018-07-20 09:35:47 -07001072void CFGFunctionPrinter::print(const OperationInst *inst) {
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -07001073 printOperation(inst);
Chris Lattner3b2ef762018-07-18 15:31:25 -07001074}
Chris Lattner1604e472018-07-23 08:42:19 -07001075
Chris Lattner4fd59b02018-07-20 09:35:47 -07001076void CFGFunctionPrinter::print(const BranchInst *inst) {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001077 os << "br bb" << getBBID(inst->getDest());
Chris Lattner1604e472018-07-23 08:42:19 -07001078
1079 if (inst->getNumOperands() != 0) {
1080 os << '(';
1081 // TODO: Use getOperands() when we have it.
1082 interleaveComma(inst->getInstOperands(), [&](const InstOperand &operand) {
1083 printValueID(operand.get());
1084 });
1085 os << ") : ";
1086 interleaveComma(inst->getInstOperands(), [&](const InstOperand &operand) {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -07001087 printType(operand.get()->getType());
Chris Lattner1604e472018-07-23 08:42:19 -07001088 });
1089 }
Chris Lattnered65a732018-06-28 20:45:33 -07001090}
Chris Lattner1604e472018-07-23 08:42:19 -07001091
James Molloy4f788372018-07-24 15:01:27 -07001092void CFGFunctionPrinter::print(const CondBranchInst *inst) {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001093 os << "cond_br ";
James Molloy4f788372018-07-24 15:01:27 -07001094 printValueID(inst->getCondition());
1095
1096 os << ", bb" << getBBID(inst->getTrueDest());
1097 if (inst->getNumTrueOperands() != 0) {
1098 os << '(';
1099 interleaveComma(inst->getTrueOperands(),
1100 [&](const CFGValue *operand) { printValueID(operand); });
1101 os << " : ";
1102 interleaveComma(inst->getTrueOperands(), [&](const CFGValue *operand) {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -07001103 printType(operand->getType());
James Molloy4f788372018-07-24 15:01:27 -07001104 });
1105 os << ")";
1106 }
1107
1108 os << ", bb" << getBBID(inst->getFalseDest());
1109 if (inst->getNumFalseOperands() != 0) {
1110 os << '(';
1111 interleaveComma(inst->getFalseOperands(),
1112 [&](const CFGValue *operand) { printValueID(operand); });
1113 os << " : ";
1114 interleaveComma(inst->getFalseOperands(), [&](const CFGValue *operand) {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -07001115 printType(operand->getType());
James Molloy4f788372018-07-24 15:01:27 -07001116 });
1117 os << ")";
1118 }
1119}
1120
Chris Lattner40746442018-07-21 14:32:09 -07001121void CFGFunctionPrinter::print(const ReturnInst *inst) {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001122 os << "return";
Chris Lattner40746442018-07-21 14:32:09 -07001123
James Molloy6bf60c22018-08-02 08:28:20 -07001124 if (inst->getNumOperands() == 0)
1125 return;
Chris Lattner40746442018-07-21 14:32:09 -07001126
James Molloy6bf60c22018-08-02 08:28:20 -07001127 os << ' ';
James Molloy4f788372018-07-24 15:01:27 -07001128 interleaveComma(inst->getOperands(),
1129 [&](const CFGValue *operand) { printValueID(operand); });
1130 os << " : ";
Chris Lattnerac591f12018-07-22 21:02:26 -07001131 interleaveComma(inst->getOperands(), [&](const CFGValue *operand) {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -07001132 printType(operand->getType());
Chris Lattner40746442018-07-21 14:32:09 -07001133 });
1134}
MLIR Team54b55a22018-07-18 10:16:05 -07001135
Chris Lattner4fd59b02018-07-20 09:35:47 -07001136void ModulePrinter::print(const CFGFunction *fn) {
1137 CFGFunctionPrinter(fn, *this).print();
Chris Lattnered65a732018-06-28 20:45:33 -07001138}
1139
Chris Lattner4c95a502018-06-23 16:03:42 -07001140//===----------------------------------------------------------------------===//
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001141// ML Function printing
Chris Lattner4c95a502018-06-23 16:03:42 -07001142//===----------------------------------------------------------------------===//
1143
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001144namespace {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -07001145class MLFunctionPrinter : public FunctionPrinter {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001146public:
Chris Lattner4fd59b02018-07-20 09:35:47 -07001147 MLFunctionPrinter(const MLFunction *function, const ModulePrinter &other);
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001148
1149 const MLFunction *getFunction() const { return function; }
1150
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001151 // Prints ML function
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001152 void print();
1153
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07001154 // Prints ML function signature
1155 void printFunctionSignature();
1156
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001157 // Methods to print ML function statements
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001158 void print(const Statement *stmt);
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -07001159 void print(const OperationStmt *stmt);
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001160 void print(const ForStmt *stmt);
1161 void print(const IfStmt *stmt);
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001162 void print(const StmtBlock *block);
1163
1164 // Number of spaces used for indenting nested statements
1165 const static unsigned indentWidth = 2;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001166
1167private:
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001168 void numberValues();
1169
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001170 const MLFunction *function;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001171 int numSpaces;
1172};
James Molloy87d81022018-07-23 11:44:40 -07001173} // end anonymous namespace
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001174
Chris Lattner4fd59b02018-07-20 09:35:47 -07001175MLFunctionPrinter::MLFunctionPrinter(const MLFunction *function,
1176 const ModulePrinter &other)
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001177 : FunctionPrinter(other), function(function), numSpaces(0) {
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07001178 assert(function && "Cannot print nullptr function");
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001179 numberValues();
1180}
1181
1182/// Number all of the SSA values in this ML function.
1183void MLFunctionPrinter::numberValues() {
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07001184 // Numbers ML function arguments
1185 for (auto *arg : function->getArguments())
1186 numberValueID(arg);
1187
1188 // Walks ML function statements and numbers for statements and
1189 // the first result of the operation statements.
Uday Bondhugula081d9e72018-07-27 10:58:14 -07001190 struct NumberValuesPass : public StmtWalker<NumberValuesPass> {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001191 NumberValuesPass(MLFunctionPrinter *printer) : printer(printer) {}
1192 void visitOperationStmt(OperationStmt *stmt) {
1193 if (stmt->getNumResults() != 0)
1194 printer->numberValueID(stmt->getResult(0));
1195 }
Tatiana Shpeismanc9c4b342018-07-31 07:40:14 -07001196 void visitForStmt(ForStmt *stmt) { printer->numberValueID(stmt); }
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001197 MLFunctionPrinter *printer;
1198 };
1199
1200 NumberValuesPass pass(this);
1201 // TODO: it'd be cleaner to have constant visitor istead of using const_cast.
Uday Bondhugula081d9e72018-07-27 10:58:14 -07001202 pass.walk(const_cast<MLFunction *>(function));
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001203}
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001204
Chris Lattner4fd59b02018-07-20 09:35:47 -07001205void MLFunctionPrinter::print() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001206 os << "mlfunc ";
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07001207 printFunctionSignature();
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001208 os << " {\n";
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001209 print(function);
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001210 os << " return\n";
1211 os << "}\n\n";
1212}
1213
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07001214void MLFunctionPrinter::printFunctionSignature() {
1215 auto type = function->getType();
1216
1217 os << "@" << function->getName() << '(';
1218
1219 for (unsigned i = 0, e = function->getNumArguments(); i != e; ++i) {
1220 if (i > 0)
1221 os << ", ";
1222 auto *arg = function->getArgument(i);
1223 printOperand(arg);
1224 os << " : ";
1225 printType(arg->getType());
1226 }
1227 os << ")";
1228 printFunctionResultType(type);
1229}
1230
Chris Lattner4fd59b02018-07-20 09:35:47 -07001231void MLFunctionPrinter::print(const StmtBlock *block) {
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001232 numSpaces += indentWidth;
Jacques Pienaarb020c542018-07-15 00:06:54 -07001233 for (auto &stmt : block->getStatements()) {
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001234 print(&stmt);
Jacques Pienaarb020c542018-07-15 00:06:54 -07001235 os << "\n";
1236 }
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001237 numSpaces -= indentWidth;
1238}
1239
Chris Lattner4fd59b02018-07-20 09:35:47 -07001240void MLFunctionPrinter::print(const Statement *stmt) {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001241 switch (stmt->getKind()) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001242 case Statement::Kind::Operation:
1243 return print(cast<OperationStmt>(stmt));
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001244 case Statement::Kind::For:
1245 return print(cast<ForStmt>(stmt));
1246 case Statement::Kind::If:
1247 return print(cast<IfStmt>(stmt));
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001248 }
1249}
1250
Chris Lattner4fd59b02018-07-20 09:35:47 -07001251void MLFunctionPrinter::print(const OperationStmt *stmt) {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001252 os.indent(numSpaces);
Chris Lattner4fd59b02018-07-20 09:35:47 -07001253 printOperation(stmt);
1254}
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001255
Chris Lattner4fd59b02018-07-20 09:35:47 -07001256void MLFunctionPrinter::print(const ForStmt *stmt) {
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07001257 os.indent(numSpaces) << "for ";
Tatiana Shpeismanc9c4b342018-07-31 07:40:14 -07001258 printOperand(stmt);
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07001259 os << " = " << *stmt->getLowerBound();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001260 os << " to " << *stmt->getUpperBound();
1261 if (stmt->getStep()->getValue() != 1)
1262 os << " step " << *stmt->getStep();
1263
1264 os << " {\n";
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001265 print(static_cast<const StmtBlock *>(stmt));
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001266 os.indent(numSpaces) << "}";
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001267}
1268
Chris Lattner4fd59b02018-07-20 09:35:47 -07001269void MLFunctionPrinter::print(const IfStmt *stmt) {
Uday Bondhugulabc535622018-08-07 14:24:38 -07001270 os.indent(numSpaces) << "if (";
1271 printIntegerSetReference(stmt->getCondition());
1272 os << ") {\n";
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001273 print(stmt->getThenClause());
1274 os.indent(numSpaces) << "}";
1275 if (stmt->hasElseClause()) {
1276 os << " else {\n";
1277 print(stmt->getElseClause());
1278 os.indent(numSpaces) << "}";
1279 }
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001280}
1281
Chris Lattner4fd59b02018-07-20 09:35:47 -07001282void ModulePrinter::print(const MLFunction *fn) {
1283 MLFunctionPrinter(fn, *this).print();
MLIR Team4718bc92018-07-17 16:56:54 -07001284}
1285
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001286//===----------------------------------------------------------------------===//
1287// print and dump methods
1288//===----------------------------------------------------------------------===//
Chris Lattnered65a732018-06-28 20:45:33 -07001289
MLIR Teamb61885d2018-07-18 16:29:21 -07001290void Attribute::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -07001291 ModuleState state(/*no context is known*/ nullptr);
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -07001292 ModulePrinter(os, state).printAttribute(this);
MLIR Teamb61885d2018-07-18 16:29:21 -07001293}
1294
James Molloy87d81022018-07-23 11:44:40 -07001295void Attribute::dump() const { print(llvm::errs()); }
MLIR Teamb61885d2018-07-18 16:29:21 -07001296
MLIR Team4718bc92018-07-17 16:56:54 -07001297void Type::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -07001298 ModuleState state(getContext());
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -07001299 ModulePrinter(os, state).printType(this);
MLIR Team4718bc92018-07-17 16:56:54 -07001300}
1301
MLIR Team54b55a22018-07-18 10:16:05 -07001302void Type::dump() const { print(llvm::errs()); }
MLIR Team4718bc92018-07-17 16:56:54 -07001303
MLIR Team718c82f2018-07-16 09:45:22 -07001304void AffineMap::dump() const {
1305 print(llvm::errs());
1306 llvm::errs() << "\n";
1307}
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001308
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001309void AffineExpr::dump() const {
1310 print(llvm::errs());
1311 llvm::errs() << "\n";
1312}
1313
Uday Bondhugulabc535622018-08-07 14:24:38 -07001314void IntegerSet::dump() const {
1315 print(llvm::errs());
1316 llvm::errs() << "\n";
1317}
1318
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001319void AffineExpr::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -07001320 ModuleState state(/*no context is known*/ nullptr);
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -07001321 ModulePrinter(os, state).printAffineExpr(this);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001322}
1323
1324void AffineMap::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -07001325 ModuleState state(/*no context is known*/ nullptr);
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -07001326 ModulePrinter(os, state).printAffineMap(this);
Chris Lattner4fd59b02018-07-20 09:35:47 -07001327}
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001328
Uday Bondhugulabc535622018-08-07 14:24:38 -07001329void IntegerSet::print(raw_ostream &os) const {
1330 ModuleState state(/*no context is known*/ nullptr);
1331 ModulePrinter(os, state).printIntegerSet(this);
1332}
1333
Chris Lattner384da8c2018-08-02 17:16:58 -07001334void SSAValue::print(raw_ostream &os) const {
1335 switch (getKind()) {
1336 case SSAValueKind::BBArgument:
1337 // TODO: Improve this.
1338 os << "<bb argument>\n";
1339 return;
1340 case SSAValueKind::InstResult:
1341 return getDefiningInst()->print(os);
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07001342 case SSAValueKind::MLFuncArgument:
Chris Lattner384da8c2018-08-02 17:16:58 -07001343 // TODO: Improve this.
1344 os << "<function argument>\n";
1345 return;
1346 case SSAValueKind::StmtResult:
1347 return getDefiningStmt()->print(os);
1348 case SSAValueKind::ForStmt:
1349 return cast<ForStmt>(this)->print(os);
1350 }
1351}
1352
1353void SSAValue::dump() const { print(llvm::errs()); }
1354
Chris Lattner4fd59b02018-07-20 09:35:47 -07001355void Instruction::print(raw_ostream &os) const {
Tatiana Shpeismanc335d182018-08-03 11:12:34 -07001356 if (!getFunction()) {
1357 os << "<<UNLINKED INSTRUCTION>>\n";
1358 return;
1359 }
Chris Lattner4fd59b02018-07-20 09:35:47 -07001360 ModuleState state(getFunction()->getContext());
1361 ModulePrinter modulePrinter(os, state);
1362 CFGFunctionPrinter(getFunction(), modulePrinter).print(this);
1363}
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001364
Chris Lattner4fd59b02018-07-20 09:35:47 -07001365void Instruction::dump() const {
1366 print(llvm::errs());
1367 llvm::errs() << "\n";
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001368}
1369
Chris Lattner4c95a502018-06-23 16:03:42 -07001370void BasicBlock::print(raw_ostream &os) const {
Tatiana Shpeismanc335d182018-08-03 11:12:34 -07001371 if (!getFunction()) {
1372 os << "<<UNLINKED BLOCK>>\n";
1373 return;
1374 }
Chris Lattner4fd59b02018-07-20 09:35:47 -07001375 ModuleState state(getFunction()->getContext());
1376 ModulePrinter modulePrinter(os, state);
1377 CFGFunctionPrinter(getFunction(), modulePrinter).print(this);
Chris Lattner4c95a502018-06-23 16:03:42 -07001378}
1379
MLIR Team54b55a22018-07-18 10:16:05 -07001380void BasicBlock::dump() const { print(llvm::errs()); }
Chris Lattner4c95a502018-06-23 16:03:42 -07001381
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001382void Statement::print(raw_ostream &os) const {
Tatiana Shpeismand880b352018-07-31 23:14:16 -07001383 MLFunction *function = findFunction();
Tatiana Shpeismanc335d182018-08-03 11:12:34 -07001384 if (!function) {
1385 os << "<<UNLINKED STATEMENT>>\n";
1386 return;
1387 }
1388
Tatiana Shpeismand880b352018-07-31 23:14:16 -07001389 ModuleState state(function->getContext());
Chris Lattner4fd59b02018-07-20 09:35:47 -07001390 ModulePrinter modulePrinter(os, state);
Tatiana Shpeismand880b352018-07-31 23:14:16 -07001391 MLFunctionPrinter(function, modulePrinter).print(this);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001392}
1393
MLIR Team54b55a22018-07-18 10:16:05 -07001394void Statement::dump() const { print(llvm::errs()); }
Jacques Pienaarb020c542018-07-15 00:06:54 -07001395
Uday Bondhugula84b80952018-08-03 13:22:26 -07001396void StmtBlock::print(raw_ostream &os) const {
1397 MLFunction *function = findFunction();
1398 ModuleState state(function->getContext());
1399 ModulePrinter modulePrinter(os, state);
1400 MLFunctionPrinter(function, modulePrinter).print(this);
1401}
1402
1403void StmtBlock::dump() const { print(llvm::errs()); }
1404
Chris Lattner4c95a502018-06-23 16:03:42 -07001405void Function::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -07001406 ModuleState state(getContext());
1407 ModulePrinter(os, state).print(this);
Chris Lattner4c95a502018-06-23 16:03:42 -07001408}
1409
MLIR Team54b55a22018-07-18 10:16:05 -07001410void Function::dump() const { print(llvm::errs()); }
1411
Chris Lattner4c95a502018-06-23 16:03:42 -07001412void Module::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -07001413 ModuleState state(getContext());
1414 state.initialize(this);
1415 ModulePrinter(os, state).print(this);
Chris Lattner4c95a502018-06-23 16:03:42 -07001416}
1417
MLIR Team54b55a22018-07-18 10:16:05 -07001418void Module::dump() const { print(llvm::errs()); }