blob: 0103e6a65e6495cd0798d535ff655283c210752d [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 Lattnerff0d5902018-07-05 09:12:11 -070029#include "mlir/IR/OperationSet.h"
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -070030#include "mlir/IR/Statements.h"
Chris Lattner4c95a502018-06-23 16:03:42 -070031#include "mlir/IR/Types.h"
32#include "mlir/Support/STLExtras.h"
Chris Lattner4c95a502018-06-23 16:03:42 -070033#include "llvm/ADT/DenseMap.h"
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -070034#include "llvm/Support/raw_ostream.h"
Chris Lattner4c95a502018-06-23 16:03:42 -070035using namespace mlir;
36
37
Chris Lattner7121b802018-07-04 20:45:39 -070038void Identifier::print(raw_ostream &os) const {
39 os << str();
40}
41
42void Identifier::dump() const {
43 print(llvm::errs());
44}
45
Chris Lattner4c95a502018-06-23 16:03:42 -070046//===----------------------------------------------------------------------===//
47// Function printing
48//===----------------------------------------------------------------------===//
49
50static void printFunctionSignature(const Function *fn, raw_ostream &os) {
51 auto type = fn->getType();
52
53 os << "@" << fn->getName() << '(';
54 interleave(type->getInputs(),
55 [&](Type *eltType) { os << *eltType; },
56 [&]() { os << ", "; });
57 os << ')';
58
59 switch (type->getResults().size()) {
60 case 0: break;
61 case 1:
62 os << " -> " << *type->getResults()[0];
63 break;
64 default:
65 os << " -> (";
66 interleave(type->getResults(),
67 [&](Type *eltType) { os << *eltType; },
68 [&]() { os << ", "; });
69 os << ')';
70 break;
71 }
72}
73
74void ExtFunction::print(raw_ostream &os) const {
75 os << "extfunc ";
76 printFunctionSignature(this, os);
77 os << "\n";
78}
79
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -070080namespace {
81
82// FunctionState contains common functionality for printing
83// CFG and ML functions.
84class FunctionState {
85public:
86 FunctionState(MLIRContext *context, raw_ostream &os);
87
88 void printOperation(const Operation *op);
89
90protected:
91 raw_ostream &os;
92 const OperationSet &operationSet;
93};
94} // end anonymous namespace
95
96FunctionState::FunctionState(MLIRContext *context, raw_ostream &os)
97 : os(os), operationSet(OperationSet::get(context)) {}
98
99void FunctionState::printOperation(const Operation *op) {
100 // Check to see if this is a known operation. If so, use the registered
101 // custom printer hook.
102 if (auto opInfo = operationSet.lookup(op->getName().str())) {
103 os << " ";
104 opInfo->printAssembly(op, os);
105 return;
106 }
107
108 // TODO: escape name if necessary.
109 os << " \"" << op->getName().str() << "\"()";
110
111 auto attrs = op->getAttrs();
112 if (!attrs.empty()) {
113 os << '{';
114 interleave(
115 attrs,
116 [&](NamedAttribute attr) { os << attr.first << ": " << *attr.second; },
117 [&]() { os << ", "; });
118 os << '}';
119 }
120
121 os << '\n';
122}
123
Chris Lattner4c95a502018-06-23 16:03:42 -0700124//===----------------------------------------------------------------------===//
125// CFG Function printing
126//===----------------------------------------------------------------------===//
127
128namespace {
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700129class CFGFunctionState : public FunctionState {
Chris Lattner4c95a502018-06-23 16:03:42 -0700130public:
131 CFGFunctionState(const CFGFunction *function, raw_ostream &os);
132
133 const CFGFunction *getFunction() const { return function; }
134
135 void print();
136 void print(const BasicBlock *block);
Chris Lattnered65a732018-06-28 20:45:33 -0700137
138 void print(const Instruction *inst);
139 void print(const OperationInst *inst);
140 void print(const ReturnInst *inst);
141 void print(const BranchInst *inst);
Chris Lattner4c95a502018-06-23 16:03:42 -0700142
143 unsigned getBBID(const BasicBlock *block) {
144 auto it = basicBlockIDs.find(block);
145 assert(it != basicBlockIDs.end() && "Block not in this function?");
146 return it->second;
147 }
148
149private:
150 const CFGFunction *function;
Chris Lattner3a467cc2018-07-01 20:28:00 -0700151 DenseMap<const BasicBlock*, unsigned> basicBlockIDs;
Chris Lattner4c95a502018-06-23 16:03:42 -0700152};
153} // end anonymous namespace
154
155CFGFunctionState::CFGFunctionState(const CFGFunction *function, raw_ostream &os)
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700156 : FunctionState(function->getContext(), os), function(function) {
Chris Lattner4c95a502018-06-23 16:03:42 -0700157 // Each basic block gets a unique ID per function.
158 unsigned blockID = 0;
Chris Lattner3a467cc2018-07-01 20:28:00 -0700159 for (auto &block : *function)
160 basicBlockIDs[&block] = blockID++;
Chris Lattner4c95a502018-06-23 16:03:42 -0700161}
162
163void CFGFunctionState::print() {
164 os << "cfgfunc ";
165 printFunctionSignature(this->getFunction(), os);
166 os << " {\n";
167
Chris Lattner3a467cc2018-07-01 20:28:00 -0700168 for (auto &block : *function)
169 print(&block);
Chris Lattner4c95a502018-06-23 16:03:42 -0700170 os << "}\n\n";
171}
172
173void CFGFunctionState::print(const BasicBlock *block) {
174 os << "bb" << getBBID(block) << ":\n";
175
Chris Lattnered65a732018-06-28 20:45:33 -0700176 // TODO Print arguments.
Chris Lattner3a467cc2018-07-01 20:28:00 -0700177 for (auto &inst : block->getOperations())
178 print(&inst);
Chris Lattner4c95a502018-06-23 16:03:42 -0700179
180 print(block->getTerminator());
181}
182
Chris Lattnered65a732018-06-28 20:45:33 -0700183void CFGFunctionState::print(const Instruction *inst) {
Chris Lattner4c95a502018-06-23 16:03:42 -0700184 switch (inst->getKind()) {
Chris Lattnered65a732018-06-28 20:45:33 -0700185 case Instruction::Kind::Operation:
186 return print(cast<OperationInst>(inst));
Chris Lattnerf6d80a02018-06-24 11:18:29 -0700187 case TerminatorInst::Kind::Branch:
Chris Lattnered65a732018-06-28 20:45:33 -0700188 return print(cast<BranchInst>(inst));
Chris Lattner4c95a502018-06-23 16:03:42 -0700189 case TerminatorInst::Kind::Return:
Chris Lattnered65a732018-06-28 20:45:33 -0700190 return print(cast<ReturnInst>(inst));
Chris Lattner4c95a502018-06-23 16:03:42 -0700191 }
192}
193
Chris Lattnered65a732018-06-28 20:45:33 -0700194void CFGFunctionState::print(const OperationInst *inst) {
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700195 printOperation(inst);
Chris Lattnered65a732018-06-28 20:45:33 -0700196}
197
198void CFGFunctionState::print(const BranchInst *inst) {
199 os << " br bb" << getBBID(inst->getDest()) << "\n";
200}
201void CFGFunctionState::print(const ReturnInst *inst) {
202 os << " return\n";
203}
204
Chris Lattner4c95a502018-06-23 16:03:42 -0700205//===----------------------------------------------------------------------===//
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700206// ML Function printing
Chris Lattner4c95a502018-06-23 16:03:42 -0700207//===----------------------------------------------------------------------===//
208
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700209namespace {
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700210class MLFunctionState : public FunctionState {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700211public:
212 MLFunctionState(const MLFunction *function, raw_ostream &os);
213
214 const MLFunction *getFunction() const { return function; }
215
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700216 // Prints ML function
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700217 void print();
218
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700219 // Methods to print ML function statements
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700220 void print(const Statement *stmt);
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700221 void print(const OperationStmt *stmt);
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700222 void print(const ForStmt *stmt);
223 void print(const IfStmt *stmt);
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700224 void print(const StmtBlock *block);
225
226 // Number of spaces used for indenting nested statements
227 const static unsigned indentWidth = 2;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700228
229private:
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700230 const MLFunction *function;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700231 int numSpaces;
232};
233} // end anonymous namespace
234
235MLFunctionState::MLFunctionState(const MLFunction *function, raw_ostream &os)
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700236 : FunctionState(function->getContext(), os), function(function),
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700237 numSpaces(0) {}
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700238
239void MLFunctionState::print() {
240 os << "mlfunc ";
241 // FIXME: should print argument names rather than just signature
242 printFunctionSignature(function, os);
243 os << " {\n";
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700244 print(function);
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700245 os << " return\n";
246 os << "}\n\n";
247}
248
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700249void MLFunctionState::print(const StmtBlock *block) {
250 numSpaces += indentWidth;
251 for (auto &stmt : block->getStatements())
252 print(&stmt);
253 numSpaces -= indentWidth;
254}
255
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700256void MLFunctionState::print(const Statement *stmt) {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700257 switch (stmt->getKind()) {
258 case Statement::Kind::Operation: // TODO
Jacques Pienaar16916002018-07-07 15:48:05 -0700259 llvm_unreachable("Operation statement is not yet implemented");
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700260 case Statement::Kind::For:
261 return print(cast<ForStmt>(stmt));
262 case Statement::Kind::If:
263 return print(cast<IfStmt>(stmt));
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700264 }
265}
266
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700267void MLFunctionState::print(const OperationStmt *stmt) {
268 printOperation(stmt);
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700269}
270
271void MLFunctionState::print(const ForStmt *stmt) {
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700272 os.indent(numSpaces) << "for {\n";
273 print(static_cast<const StmtBlock *>(stmt));
274 os.indent(numSpaces) << "}\n";
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700275}
276
277void MLFunctionState::print(const IfStmt *stmt) {
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700278 os.indent(numSpaces) << "if () {\n";
279 print(stmt->getThenClause());
280 os.indent(numSpaces) << "}";
281 if (stmt->hasElseClause()) {
282 os << " else {\n";
283 print(stmt->getElseClause());
284 os.indent(numSpaces) << "}";
285 }
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700286 os << "\n";
287}
288
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700289//===----------------------------------------------------------------------===//
290// print and dump methods
291//===----------------------------------------------------------------------===//
Chris Lattnered65a732018-06-28 20:45:33 -0700292
293void Instruction::print(raw_ostream &os) const {
Chris Lattner4c95a502018-06-23 16:03:42 -0700294 CFGFunctionState state(getFunction(), os);
295 state.print(this);
296}
297
Chris Lattnered65a732018-06-28 20:45:33 -0700298void Instruction::dump() const {
Chris Lattner4c95a502018-06-23 16:03:42 -0700299 print(llvm::errs());
300}
301
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700302void AffineMap::dump() const { print(llvm::errs()); }
303
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700304void AffineExpr::dump() const {
305 print(llvm::errs());
306 llvm::errs() << "\n";
307}
308
309void AffineAddExpr::print(raw_ostream &os) const {
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700310 os << "(" << *getLHS() << " + " << *getRHS() << ")";
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700311}
312
313void AffineSubExpr::print(raw_ostream &os) const {
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700314 os << "(" << *getLHS() << " - " << *getRHS() << ")";
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700315}
316
317void AffineMulExpr::print(raw_ostream &os) const {
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700318 os << "(" << *getLHS() << " * " << *getRHS() << ")";
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700319}
320
321void AffineModExpr::print(raw_ostream &os) const {
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700322 os << "(" << *getLHS() << " mod " << *getRHS() << ")";
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700323}
324
325void AffineFloorDivExpr::print(raw_ostream &os) const {
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700326 os << "(" << *getLHS() << " floordiv " << *getRHS() << ")";
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700327}
328
329void AffineCeilDivExpr::print(raw_ostream &os) const {
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700330 os << "(" << *getLHS() << " ceildiv " << *getRHS() << ")";
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700331}
332
333void AffineSymbolExpr::print(raw_ostream &os) const {
334 os << "s" << getPosition();
335}
336
337void AffineDimExpr::print(raw_ostream &os) const { os << "d" << getPosition(); }
338
339void AffineConstantExpr::print(raw_ostream &os) const { os << getValue(); }
340
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700341void AffineExpr::print(raw_ostream &os) const {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700342 switch (getKind()) {
343 case Kind::SymbolId:
344 return cast<AffineSymbolExpr>(this)->print(os);
345 case Kind::DimId:
346 return cast<AffineDimExpr>(this)->print(os);
347 case Kind::Constant:
348 return cast<AffineConstantExpr>(this)->print(os);
349 case Kind::Add:
350 return cast<AffineAddExpr>(this)->print(os);
351 case Kind::Sub:
352 return cast<AffineSubExpr>(this)->print(os);
353 case Kind::Mul:
354 return cast<AffineMulExpr>(this)->print(os);
355 case Kind::FloorDiv:
356 return cast<AffineFloorDivExpr>(this)->print(os);
357 case Kind::CeilDiv:
358 return cast<AffineCeilDivExpr>(this)->print(os);
359 case Kind::Mod:
360 return cast<AffineModExpr>(this)->print(os);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700361 }
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700362}
363
364void AffineMap::print(raw_ostream &os) const {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700365 // Dimension identifiers.
366 os << "(";
367 for (int i = 0; i < (int)getNumDims() - 1; i++)
368 os << "d" << i << ", ";
369 if (getNumDims() >= 1)
370 os << "d" << getNumDims() - 1;
371 os << ")";
372
373 // Symbolic identifiers.
374 if (getNumSymbols() >= 1) {
375 os << " [";
376 for (int i = 0; i < (int)getNumSymbols() - 1; i++)
377 os << "s" << i << ", ";
378 if (getNumSymbols() >= 1)
379 os << "s" << getNumSymbols() - 1;
380 os << "]";
381 }
382
383 // AffineMap should have at least one result.
384 assert(!getResults().empty());
385 // Result affine expressions.
386 os << " -> (";
387 interleave(getResults(), [&](AffineExpr *expr) { os << *expr; },
388 [&]() { os << ", "; });
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700389 os << ")";
390
391 if (!isBounded()) {
392 os << "\n";
393 return;
394 }
395
396 // Print range sizes for bounded affine maps.
397 os << " size (";
398 interleave(getRangeSizes(), [&](AffineExpr *expr) { os << *expr; },
399 [&]() { os << ", "; });
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700400 os << ")\n";
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700401}
402
Chris Lattner4c95a502018-06-23 16:03:42 -0700403void BasicBlock::print(raw_ostream &os) const {
404 CFGFunctionState state(getFunction(), os);
405 state.print();
406}
407
408void BasicBlock::dump() const {
409 print(llvm::errs());
410}
411
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700412void Statement::print(raw_ostream &os) const {
413 MLFunctionState state(getFunction(), os);
414 state.print(this);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -0700415}
416
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700417void Statement::dump() const {
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -0700418 print(llvm::errs());
419}
Chris Lattner4c95a502018-06-23 16:03:42 -0700420void Function::print(raw_ostream &os) const {
421 switch (getKind()) {
422 case Kind::ExtFunc: return cast<ExtFunction>(this)->print(os);
423 case Kind::CFGFunc: return cast<CFGFunction>(this)->print(os);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -0700424 case Kind::MLFunc: return cast<MLFunction>(this)->print(os);
Chris Lattner4c95a502018-06-23 16:03:42 -0700425 }
426}
427
428void Function::dump() const {
429 print(llvm::errs());
430}
431
432void CFGFunction::print(raw_ostream &os) const {
433 CFGFunctionState state(this, os);
434 state.print();
435}
436
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -0700437void MLFunction::print(raw_ostream &os) const {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700438 MLFunctionState state(this, os);
439 state.print();
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -0700440}
441
Chris Lattner4c95a502018-06-23 16:03:42 -0700442void Module::print(raw_ostream &os) const {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700443 unsigned id = 0;
444 for (auto *map : affineMapList) {
445 os << "#" << id++ << " = ";
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700446 map->print(os);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700447 }
Chris Lattner4c95a502018-06-23 16:03:42 -0700448 for (auto *fn : functionList)
449 fn->print(os);
450}
451
452void Module::dump() const {
453 print(llvm::errs());
454}