blob: 6a2d9321d0c3882378f3b863963778bcf816d782 [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
MLIR Team54b55a22018-07-18 10:16:05 -070037void Identifier::print(raw_ostream &os) const { os << str(); }
Chris Lattner4c95a502018-06-23 16:03:42 -070038
MLIR Team54b55a22018-07-18 10:16:05 -070039void Identifier::dump() const { print(llvm::errs()); }
Chris Lattner7121b802018-07-04 20:45:39 -070040
Chris Lattner4c95a502018-06-23 16:03:42 -070041//===----------------------------------------------------------------------===//
MLIR Team4718bc92018-07-17 16:56:54 -070042// Module printing
43//===----------------------------------------------------------------------===//
44
45namespace {
MLIR Team54b55a22018-07-18 10:16:05 -070046class ModuleState {
47public:
MLIR Team4718bc92018-07-17 16:56:54 -070048 ModuleState(raw_ostream &os);
49
50 void initialize(const Module *module);
51
52 void print(const Module *module);
53 void print(const Type *type) const;
MLIR Team54b55a22018-07-18 10:16:05 -070054 void print(const Function *fn);
55 void print(const ExtFunction *fn);
56 void print(const CFGFunction *fn);
57 void print(const MLFunction *fn);
MLIR Team4718bc92018-07-17 16:56:54 -070058
MLIR Team54b55a22018-07-18 10:16:05 -070059 void recordAffineMapReference(const AffineMap *affineMap) {
MLIR Team4718bc92018-07-17 16:56:54 -070060 if (affineMapIds.count(affineMap) == 0) {
61 affineMapIds[affineMap] = nextAffineMapId++;
62 }
63 }
64
MLIR Team54b55a22018-07-18 10:16:05 -070065 int getAffineMapId(const AffineMap *affineMap) const {
MLIR Team4718bc92018-07-17 16:56:54 -070066 auto it = affineMapIds.find(affineMap);
67 if (it == affineMapIds.end()) {
68 return -1;
69 }
70 return it->second;
71 }
72
MLIR Team54b55a22018-07-18 10:16:05 -070073private:
MLIR Team4718bc92018-07-17 16:56:54 -070074 // Visit functions.
75 void visitFunction(const Function *fn);
76 void visitExtFunction(const ExtFunction *fn);
77 void visitCFGFunction(const CFGFunction *fn);
78 void visitMLFunction(const MLFunction *fn);
79 void visitType(const Type *type);
80
81 raw_ostream &os;
MLIR Team54b55a22018-07-18 10:16:05 -070082 DenseMap<const AffineMap *, int> affineMapIds;
MLIR Team4718bc92018-07-17 16:56:54 -070083 int nextAffineMapId = 0;
84};
MLIR Team54b55a22018-07-18 10:16:05 -070085} // end anonymous namespace
MLIR Team4718bc92018-07-17 16:56:54 -070086
MLIR Team54b55a22018-07-18 10:16:05 -070087ModuleState::ModuleState(raw_ostream &os) : os(os) {}
MLIR Team4718bc92018-07-17 16:56:54 -070088
89// Initializes module state, populating affine map state.
90void ModuleState::initialize(const Module *module) {
91 for (auto fn : module->functionList) {
92 visitFunction(fn);
93 }
94}
95
96// TODO Support visiting other types/instructions when implemented.
97void ModuleState::visitType(const Type *type) {
98 if (type->getKind() == Type::Kind::Function) {
99 // Visit input and result types for functions.
100 auto *funcType = cast<FunctionType>(type);
MLIR Team54b55a22018-07-18 10:16:05 -0700101 for (auto *input : funcType->getInputs()) {
MLIR Team4718bc92018-07-17 16:56:54 -0700102 visitType(input);
103 }
MLIR Team54b55a22018-07-18 10:16:05 -0700104 for (auto *result : funcType->getResults()) {
MLIR Team4718bc92018-07-17 16:56:54 -0700105 visitType(result);
106 }
107 } else if (type->getKind() == Type::Kind::MemRef) {
108 // Visit affine maps in memref type.
109 auto *memref = cast<MemRefType>(type);
MLIR Team54b55a22018-07-18 10:16:05 -0700110 for (AffineMap *map : memref->getAffineMaps()) {
MLIR Team4718bc92018-07-17 16:56:54 -0700111 recordAffineMapReference(map);
112 }
113 }
114}
115
116void ModuleState::visitExtFunction(const ExtFunction *fn) {
117 visitType(fn->getType());
118}
119
120void ModuleState::visitCFGFunction(const CFGFunction *fn) {
121 visitType(fn->getType());
122 // TODO Visit function body instructions.
123}
124
125void ModuleState::visitMLFunction(const MLFunction *fn) {
126 visitType(fn->getType());
127 // TODO Visit function body statements.
128}
129
130void ModuleState::visitFunction(const Function *fn) {
131 switch (fn->getKind()) {
MLIR Team54b55a22018-07-18 10:16:05 -0700132 case Function::Kind::ExtFunc:
133 return visitExtFunction(cast<ExtFunction>(fn));
134 case Function::Kind::CFGFunc:
135 return visitCFGFunction(cast<CFGFunction>(fn));
136 case Function::Kind::MLFunc:
137 return visitMLFunction(cast<MLFunction>(fn));
MLIR Team4718bc92018-07-17 16:56:54 -0700138 }
139}
140
MLIR Team4718bc92018-07-17 16:56:54 -0700141// Prints function with initialized module state.
MLIR Team54b55a22018-07-18 10:16:05 -0700142void ModuleState::print(const Function *fn) {
MLIR Team4718bc92018-07-17 16:56:54 -0700143 switch (fn->getKind()) {
MLIR Team54b55a22018-07-18 10:16:05 -0700144 case Function::Kind::ExtFunc:
145 return print(cast<ExtFunction>(fn));
146 case Function::Kind::CFGFunc:
147 return print(cast<CFGFunction>(fn));
148 case Function::Kind::MLFunc:
149 return print(cast<MLFunction>(fn));
MLIR Team4718bc92018-07-17 16:56:54 -0700150 }
151}
152
153// Prints affine map identifier.
154static void printAffineMapId(unsigned affineMapId, raw_ostream &os) {
155 os << "#map" << affineMapId;
156}
157
158void ModuleState::print(const Module *module) {
MLIR Team54b55a22018-07-18 10:16:05 -0700159 for (const auto &mapAndId : affineMapIds) {
MLIR Team4718bc92018-07-17 16:56:54 -0700160 printAffineMapId(mapAndId.second, os);
161 os << " = ";
162 mapAndId.first->print(os);
163 os << '\n';
164 }
MLIR Team54b55a22018-07-18 10:16:05 -0700165 for (auto *fn : module->functionList) print(fn);
MLIR Team4718bc92018-07-17 16:56:54 -0700166}
167
168void ModuleState::print(const Type *type) const {
169 switch (type->getKind()) {
MLIR Team54b55a22018-07-18 10:16:05 -0700170 case Type::Kind::AffineInt:
171 os << "affineint";
172 return;
173 case Type::Kind::BF16:
174 os << "bf16";
175 return;
176 case Type::Kind::F16:
177 os << "f16";
178 return;
179 case Type::Kind::F32:
180 os << "f32";
181 return;
182 case Type::Kind::F64:
183 os << "f64";
184 return;
MLIR Team4718bc92018-07-17 16:56:54 -0700185
186 case Type::Kind::Integer: {
187 auto *integer = cast<IntegerType>(type);
188 os << 'i' << integer->getWidth();
189 return;
190 }
191 case Type::Kind::Function: {
192 auto *func = cast<FunctionType>(type);
193 os << '(';
MLIR Team54b55a22018-07-18 10:16:05 -0700194 interleave(func->getInputs(), [&](Type *type) { os << *type; },
MLIR Team4718bc92018-07-17 16:56:54 -0700195 [&]() { os << ", "; });
196 os << ") -> ";
197 auto results = func->getResults();
198 if (results.size() == 1)
199 os << *results[0];
200 else {
201 os << '(';
MLIR Team54b55a22018-07-18 10:16:05 -0700202 interleave(results, [&](Type *type) { os << *type; },
MLIR Team4718bc92018-07-17 16:56:54 -0700203 [&]() { os << ", "; });
204 os << ')';
205 }
206 return;
207 }
208 case Type::Kind::Vector: {
209 auto *v = cast<VectorType>(type);
210 os << "vector<";
MLIR Team54b55a22018-07-18 10:16:05 -0700211 for (auto dim : v->getShape()) os << dim << 'x';
MLIR Team4718bc92018-07-17 16:56:54 -0700212 os << *v->getElementType() << '>';
213 return;
214 }
215 case Type::Kind::RankedTensor: {
216 auto *v = cast<RankedTensorType>(type);
217 os << "tensor<";
218 for (auto dim : v->getShape()) {
219 if (dim < 0)
220 os << '?';
221 else
222 os << dim;
223 os << 'x';
224 }
225 os << *v->getElementType() << '>';
226 return;
227 }
228 case Type::Kind::UnrankedTensor: {
229 auto *v = cast<UnrankedTensorType>(type);
230 os << "tensor<??" << *v->getElementType() << '>';
231 return;
232 }
233 case Type::Kind::MemRef: {
234 auto *v = cast<MemRefType>(type);
235 os << "memref<";
236 for (auto dim : v->getShape()) {
237 if (dim < 0)
238 os << '?';
239 else
240 os << dim;
241 os << 'x';
242 }
243 os << *v->getElementType();
244 for (auto map : v->getAffineMaps()) {
245 os << ", ";
246 const int mapId = getAffineMapId(map);
247 if (mapId >= 0) {
248 // Map will be printed at top of module so print reference to its id.
249 printAffineMapId(mapId, os);
250 } else {
251 // Map not in module state so print inline.
252 map->print(os);
253 }
254 }
255 os << ", " << v->getMemorySpace();
256 os << '>';
257 return;
258 }
259 }
260}
261
262//===----------------------------------------------------------------------===//
Chris Lattner4c95a502018-06-23 16:03:42 -0700263// Function printing
264//===----------------------------------------------------------------------===//
265
MLIR Team4718bc92018-07-17 16:56:54 -0700266static void printFunctionSignature(const Function *fn,
267 const ModuleState *moduleState,
268 raw_ostream &os) {
Chris Lattner4c95a502018-06-23 16:03:42 -0700269 auto type = fn->getType();
270
271 os << "@" << fn->getName() << '(';
272 interleave(type->getInputs(),
MLIR Team4718bc92018-07-17 16:56:54 -0700273 [&](Type *eltType) { moduleState->print(eltType); },
Chris Lattner4c95a502018-06-23 16:03:42 -0700274 [&]() { os << ", "; });
275 os << ')';
276
277 switch (type->getResults().size()) {
MLIR Team54b55a22018-07-18 10:16:05 -0700278 case 0:
279 break;
Chris Lattner4c95a502018-06-23 16:03:42 -0700280 case 1:
MLIR Team4718bc92018-07-17 16:56:54 -0700281 os << " -> ";
282 moduleState->print(type->getResults()[0]);
Chris Lattner4c95a502018-06-23 16:03:42 -0700283 break;
284 default:
285 os << " -> (";
286 interleave(type->getResults(),
MLIR Team4718bc92018-07-17 16:56:54 -0700287 [&](Type *eltType) { moduleState->print(eltType); },
Chris Lattner4c95a502018-06-23 16:03:42 -0700288 [&]() { os << ", "; });
289 os << ')';
290 break;
291 }
292}
293
MLIR Team54b55a22018-07-18 10:16:05 -0700294void ModuleState::print(const ExtFunction *fn) {
Chris Lattner4c95a502018-06-23 16:03:42 -0700295 os << "extfunc ";
MLIR Team54b55a22018-07-18 10:16:05 -0700296 printFunctionSignature(fn, this, os);
297 os << '\n';
Chris Lattner4c95a502018-06-23 16:03:42 -0700298}
299
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700300namespace {
301
302// FunctionState contains common functionality for printing
303// CFG and ML functions.
304class FunctionState {
305public:
MLIR Team4718bc92018-07-17 16:56:54 -0700306 FunctionState(MLIRContext *context, const ModuleState *moduleState,
307 raw_ostream &os);
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700308
309 void printOperation(const Operation *op);
310
311protected:
312 raw_ostream &os;
MLIR Team4718bc92018-07-17 16:56:54 -0700313 const ModuleState *moduleState;
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700314 const OperationSet &operationSet;
315};
MLIR Team54b55a22018-07-18 10:16:05 -0700316} // end anonymous namespace
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700317
MLIR Team4718bc92018-07-17 16:56:54 -0700318FunctionState::FunctionState(MLIRContext *context,
MLIR Team54b55a22018-07-18 10:16:05 -0700319 const ModuleState *moduleState, raw_ostream &os)
320 : os(os),
321 moduleState(moduleState),
MLIR Team4718bc92018-07-17 16:56:54 -0700322 operationSet(OperationSet::get(context)) {}
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700323
324void FunctionState::printOperation(const Operation *op) {
325 // Check to see if this is a known operation. If so, use the registered
326 // custom printer hook.
327 if (auto opInfo = operationSet.lookup(op->getName().str())) {
328 os << " ";
329 opInfo->printAssembly(op, os);
330 return;
331 }
332
333 // TODO: escape name if necessary.
334 os << " \"" << op->getName().str() << "\"()";
335
336 auto attrs = op->getAttrs();
337 if (!attrs.empty()) {
338 os << '{';
339 interleave(
340 attrs,
341 [&](NamedAttribute attr) { os << attr.first << ": " << *attr.second; },
342 [&]() { os << ", "; });
343 os << '}';
344 }
Chris Lattner3b2ef762018-07-18 15:31:25 -0700345
346 // TODO: Print signature type once that is plumbed through to Operation.
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700347}
348
Chris Lattner4c95a502018-06-23 16:03:42 -0700349//===----------------------------------------------------------------------===//
350// CFG Function printing
351//===----------------------------------------------------------------------===//
352
353namespace {
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700354class CFGFunctionState : public FunctionState {
Chris Lattner4c95a502018-06-23 16:03:42 -0700355public:
MLIR Team4718bc92018-07-17 16:56:54 -0700356 CFGFunctionState(const CFGFunction *function, const ModuleState *moduleState,
357 raw_ostream &os);
Chris Lattner4c95a502018-06-23 16:03:42 -0700358
359 const CFGFunction *getFunction() const { return function; }
360
361 void print();
362 void print(const BasicBlock *block);
Chris Lattnered65a732018-06-28 20:45:33 -0700363
364 void print(const Instruction *inst);
365 void print(const OperationInst *inst);
366 void print(const ReturnInst *inst);
367 void print(const BranchInst *inst);
Chris Lattner4c95a502018-06-23 16:03:42 -0700368
369 unsigned getBBID(const BasicBlock *block) {
370 auto it = basicBlockIDs.find(block);
371 assert(it != basicBlockIDs.end() && "Block not in this function?");
372 return it->second;
373 }
374
375private:
376 const CFGFunction *function;
MLIR Team54b55a22018-07-18 10:16:05 -0700377 DenseMap<const BasicBlock *, unsigned> basicBlockIDs;
Chris Lattner4c95a502018-06-23 16:03:42 -0700378};
MLIR Team54b55a22018-07-18 10:16:05 -0700379} // end anonymous namespace
Chris Lattner4c95a502018-06-23 16:03:42 -0700380
MLIR Team4718bc92018-07-17 16:56:54 -0700381CFGFunctionState::CFGFunctionState(const CFGFunction *function,
382 const ModuleState *moduleState,
383 raw_ostream &os)
384 : FunctionState(function->getContext(), moduleState, os),
385 function(function) {
Chris Lattner4c95a502018-06-23 16:03:42 -0700386 // Each basic block gets a unique ID per function.
387 unsigned blockID = 0;
MLIR Team54b55a22018-07-18 10:16:05 -0700388 for (auto &block : *function) basicBlockIDs[&block] = blockID++;
Chris Lattner4c95a502018-06-23 16:03:42 -0700389}
390
391void CFGFunctionState::print() {
392 os << "cfgfunc ";
MLIR Team4718bc92018-07-17 16:56:54 -0700393 printFunctionSignature(this->getFunction(), moduleState, os);
Chris Lattner4c95a502018-06-23 16:03:42 -0700394 os << " {\n";
395
MLIR Team54b55a22018-07-18 10:16:05 -0700396 for (auto &block : *function) print(&block);
Chris Lattner4c95a502018-06-23 16:03:42 -0700397 os << "}\n\n";
398}
399
400void CFGFunctionState::print(const BasicBlock *block) {
401 os << "bb" << getBBID(block) << ":\n";
402
Chris Lattnered65a732018-06-28 20:45:33 -0700403 // TODO Print arguments.
Jacques Pienaarb020c542018-07-15 00:06:54 -0700404 for (auto &inst : block->getOperations()) {
Chris Lattner3a467cc2018-07-01 20:28:00 -0700405 print(&inst);
Jacques Pienaarb020c542018-07-15 00:06:54 -0700406 os << "\n";
407 }
Chris Lattner4c95a502018-06-23 16:03:42 -0700408
409 print(block->getTerminator());
Jacques Pienaarb020c542018-07-15 00:06:54 -0700410 os << "\n";
Chris Lattner4c95a502018-06-23 16:03:42 -0700411}
412
Chris Lattnered65a732018-06-28 20:45:33 -0700413void CFGFunctionState::print(const Instruction *inst) {
Chris Lattner4c95a502018-06-23 16:03:42 -0700414 switch (inst->getKind()) {
Chris Lattnered65a732018-06-28 20:45:33 -0700415 case Instruction::Kind::Operation:
416 return print(cast<OperationInst>(inst));
Chris Lattnerf6d80a02018-06-24 11:18:29 -0700417 case TerminatorInst::Kind::Branch:
Chris Lattnered65a732018-06-28 20:45:33 -0700418 return print(cast<BranchInst>(inst));
Chris Lattner4c95a502018-06-23 16:03:42 -0700419 case TerminatorInst::Kind::Return:
Chris Lattnered65a732018-06-28 20:45:33 -0700420 return print(cast<ReturnInst>(inst));
Chris Lattner4c95a502018-06-23 16:03:42 -0700421 }
422}
423
Chris Lattnered65a732018-06-28 20:45:33 -0700424void CFGFunctionState::print(const OperationInst *inst) {
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700425 printOperation(inst);
Chris Lattnered65a732018-06-28 20:45:33 -0700426
Chris Lattner3b2ef762018-07-18 15:31:25 -0700427 // FIXME: Move this into printOperation when Operation has operands and
428 // results
429
430 // Print the type signature of the operation.
431 os << " : (";
432 interleave(
433 inst->getOperands(),
434 [&](const InstOperand &op) { moduleState->print(op.get()->getType()); },
435 [&]() { os << ", "; });
436 os << ") -> ";
437
438 auto resultList = inst->getResults();
439 if (resultList.size() == 1) {
440 moduleState->print(resultList[0].getType());
441 } else {
442 os << '(';
443 interleave(
444 resultList,
445 [&](const InstResult &result) { moduleState->print(result.getType()); },
446 [&]() { os << ", "; });
447 os << ')';
448 }
449}
Chris Lattnered65a732018-06-28 20:45:33 -0700450void CFGFunctionState::print(const BranchInst *inst) {
Jacques Pienaarb020c542018-07-15 00:06:54 -0700451 os << " br bb" << getBBID(inst->getDest());
Chris Lattnered65a732018-06-28 20:45:33 -0700452}
MLIR Team54b55a22018-07-18 10:16:05 -0700453void CFGFunctionState::print(const ReturnInst *inst) { os << " return"; }
454
455void ModuleState::print(const CFGFunction *fn) {
456 CFGFunctionState state(fn, this, os);
457 state.print();
Chris Lattnered65a732018-06-28 20:45:33 -0700458}
459
Chris Lattner4c95a502018-06-23 16:03:42 -0700460//===----------------------------------------------------------------------===//
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700461// ML Function printing
Chris Lattner4c95a502018-06-23 16:03:42 -0700462//===----------------------------------------------------------------------===//
463
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700464namespace {
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700465class MLFunctionState : public FunctionState {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700466public:
MLIR Team4718bc92018-07-17 16:56:54 -0700467 MLFunctionState(const MLFunction *function, const ModuleState *moduleState,
468 raw_ostream &os);
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700469
470 const MLFunction *getFunction() const { return function; }
471
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700472 // Prints ML function
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700473 void print();
474
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700475 // Methods to print ML function statements
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700476 void print(const Statement *stmt);
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700477 void print(const OperationStmt *stmt);
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700478 void print(const ForStmt *stmt);
479 void print(const IfStmt *stmt);
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700480 void print(const StmtBlock *block);
481
482 // Number of spaces used for indenting nested statements
483 const static unsigned indentWidth = 2;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700484
485private:
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700486 const MLFunction *function;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700487 int numSpaces;
488};
MLIR Team54b55a22018-07-18 10:16:05 -0700489} // end anonymous namespace
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700490
MLIR Team4718bc92018-07-17 16:56:54 -0700491MLFunctionState::MLFunctionState(const MLFunction *function,
492 const ModuleState *moduleState,
493 raw_ostream &os)
494 : FunctionState(function->getContext(), moduleState, os),
MLIR Team54b55a22018-07-18 10:16:05 -0700495 function(function),
496 numSpaces(0) {}
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700497
498void MLFunctionState::print() {
499 os << "mlfunc ";
500 // FIXME: should print argument names rather than just signature
MLIR Team4718bc92018-07-17 16:56:54 -0700501 printFunctionSignature(function, moduleState, os);
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700502 os << " {\n";
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700503 print(function);
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700504 os << " return\n";
505 os << "}\n\n";
506}
507
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700508void MLFunctionState::print(const StmtBlock *block) {
509 numSpaces += indentWidth;
Jacques Pienaarb020c542018-07-15 00:06:54 -0700510 for (auto &stmt : block->getStatements()) {
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700511 print(&stmt);
Jacques Pienaarb020c542018-07-15 00:06:54 -0700512 os << "\n";
513 }
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700514 numSpaces -= indentWidth;
515}
516
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700517void MLFunctionState::print(const Statement *stmt) {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700518 switch (stmt->getKind()) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -0700519 case Statement::Kind::Operation:
520 return print(cast<OperationStmt>(stmt));
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700521 case Statement::Kind::For:
522 return print(cast<ForStmt>(stmt));
523 case Statement::Kind::If:
524 return print(cast<IfStmt>(stmt));
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700525 }
526}
527
MLIR Team54b55a22018-07-18 10:16:05 -0700528void MLFunctionState::print(const OperationStmt *stmt) { printOperation(stmt); }
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700529
530void MLFunctionState::print(const ForStmt *stmt) {
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700531 os.indent(numSpaces) << "for {\n";
532 print(static_cast<const StmtBlock *>(stmt));
Tatiana Shpeisman565b9642018-07-16 11:47:09 -0700533 os.indent(numSpaces) << "}";
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700534}
535
536void MLFunctionState::print(const IfStmt *stmt) {
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700537 os.indent(numSpaces) << "if () {\n";
538 print(stmt->getThenClause());
539 os.indent(numSpaces) << "}";
540 if (stmt->hasElseClause()) {
541 os << " else {\n";
542 print(stmt->getElseClause());
543 os.indent(numSpaces) << "}";
544 }
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700545}
546
MLIR Team54b55a22018-07-18 10:16:05 -0700547void ModuleState::print(const MLFunction *fn) {
548 MLFunctionState state(fn, this, os);
MLIR Team4718bc92018-07-17 16:56:54 -0700549 state.print();
550}
551
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700552//===----------------------------------------------------------------------===//
553// print and dump methods
554//===----------------------------------------------------------------------===//
Chris Lattnered65a732018-06-28 20:45:33 -0700555
MLIR Team4718bc92018-07-17 16:56:54 -0700556void Type::print(raw_ostream &os) const {
557 ModuleState moduleState(os);
558 moduleState.print(this);
559}
560
MLIR Team54b55a22018-07-18 10:16:05 -0700561void Type::dump() const { print(llvm::errs()); }
MLIR Team4718bc92018-07-17 16:56:54 -0700562
Chris Lattnered65a732018-06-28 20:45:33 -0700563void Instruction::print(raw_ostream &os) const {
MLIR Team4718bc92018-07-17 16:56:54 -0700564 ModuleState moduleState(os);
565 CFGFunctionState state(getFunction(), &moduleState, os);
Chris Lattner4c95a502018-06-23 16:03:42 -0700566 state.print(this);
567}
568
Chris Lattnered65a732018-06-28 20:45:33 -0700569void Instruction::dump() const {
Chris Lattner4c95a502018-06-23 16:03:42 -0700570 print(llvm::errs());
Jacques Pienaarb020c542018-07-15 00:06:54 -0700571 llvm::errs() << "\n";
Chris Lattner4c95a502018-06-23 16:03:42 -0700572}
573
MLIR Team718c82f2018-07-16 09:45:22 -0700574void AffineMap::dump() const {
575 print(llvm::errs());
576 llvm::errs() << "\n";
577}
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700578
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700579void AffineExpr::dump() const {
580 print(llvm::errs());
581 llvm::errs() << "\n";
582}
583
584void AffineAddExpr::print(raw_ostream &os) const {
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700585 os << "(" << *getLHS() << " + " << *getRHS() << ")";
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700586}
587
588void AffineSubExpr::print(raw_ostream &os) const {
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700589 os << "(" << *getLHS() << " - " << *getRHS() << ")";
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700590}
591
592void AffineMulExpr::print(raw_ostream &os) const {
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700593 os << "(" << *getLHS() << " * " << *getRHS() << ")";
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700594}
595
596void AffineModExpr::print(raw_ostream &os) const {
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700597 os << "(" << *getLHS() << " mod " << *getRHS() << ")";
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700598}
599
600void AffineFloorDivExpr::print(raw_ostream &os) const {
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700601 os << "(" << *getLHS() << " floordiv " << *getRHS() << ")";
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700602}
603
604void AffineCeilDivExpr::print(raw_ostream &os) const {
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700605 os << "(" << *getLHS() << " ceildiv " << *getRHS() << ")";
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700606}
607
608void AffineSymbolExpr::print(raw_ostream &os) const {
609 os << "s" << getPosition();
610}
611
612void AffineDimExpr::print(raw_ostream &os) const { os << "d" << getPosition(); }
613
614void AffineConstantExpr::print(raw_ostream &os) const { os << getValue(); }
615
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700616void AffineExpr::print(raw_ostream &os) const {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700617 switch (getKind()) {
618 case Kind::SymbolId:
619 return cast<AffineSymbolExpr>(this)->print(os);
620 case Kind::DimId:
621 return cast<AffineDimExpr>(this)->print(os);
622 case Kind::Constant:
623 return cast<AffineConstantExpr>(this)->print(os);
624 case Kind::Add:
625 return cast<AffineAddExpr>(this)->print(os);
626 case Kind::Sub:
627 return cast<AffineSubExpr>(this)->print(os);
628 case Kind::Mul:
629 return cast<AffineMulExpr>(this)->print(os);
630 case Kind::FloorDiv:
631 return cast<AffineFloorDivExpr>(this)->print(os);
632 case Kind::CeilDiv:
633 return cast<AffineCeilDivExpr>(this)->print(os);
634 case Kind::Mod:
635 return cast<AffineModExpr>(this)->print(os);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700636 }
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700637}
638
639void AffineMap::print(raw_ostream &os) const {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700640 // Dimension identifiers.
641 os << "(";
MLIR Team54b55a22018-07-18 10:16:05 -0700642 for (int i = 0; i < (int)getNumDims() - 1; i++) os << "d" << i << ", ";
643 if (getNumDims() >= 1) os << "d" << getNumDims() - 1;
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700644 os << ")";
645
646 // Symbolic identifiers.
647 if (getNumSymbols() >= 1) {
648 os << " [";
MLIR Team54b55a22018-07-18 10:16:05 -0700649 for (int i = 0; i < (int)getNumSymbols() - 1; i++) os << "s" << i << ", ";
650 if (getNumSymbols() >= 1) os << "s" << getNumSymbols() - 1;
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700651 os << "]";
652 }
653
654 // AffineMap should have at least one result.
655 assert(!getResults().empty());
656 // Result affine expressions.
657 os << " -> (";
658 interleave(getResults(), [&](AffineExpr *expr) { os << *expr; },
659 [&]() { os << ", "; });
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700660 os << ")";
661
662 if (!isBounded()) {
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700663 return;
664 }
665
666 // Print range sizes for bounded affine maps.
667 os << " size (";
668 interleave(getRangeSizes(), [&](AffineExpr *expr) { os << *expr; },
669 [&]() { os << ", "; });
MLIR Team718c82f2018-07-16 09:45:22 -0700670 os << ")";
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700671}
672
Chris Lattner4c95a502018-06-23 16:03:42 -0700673void BasicBlock::print(raw_ostream &os) const {
MLIR Team4718bc92018-07-17 16:56:54 -0700674 ModuleState moduleState(os);
675 CFGFunctionState state(getFunction(), &moduleState, os);
Chris Lattner4c95a502018-06-23 16:03:42 -0700676 state.print();
677}
678
MLIR Team54b55a22018-07-18 10:16:05 -0700679void BasicBlock::dump() const { print(llvm::errs()); }
Chris Lattner4c95a502018-06-23 16:03:42 -0700680
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700681void Statement::print(raw_ostream &os) const {
MLIR Team4718bc92018-07-17 16:56:54 -0700682 ModuleState moduleState(os);
683 MLFunctionState state(getFunction(), &moduleState, os);
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700684 state.print(this);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -0700685}
686
MLIR Team54b55a22018-07-18 10:16:05 -0700687void Statement::dump() const { print(llvm::errs()); }
Jacques Pienaarb020c542018-07-15 00:06:54 -0700688
Chris Lattner4c95a502018-06-23 16:03:42 -0700689void Function::print(raw_ostream &os) const {
690 switch (getKind()) {
MLIR Team54b55a22018-07-18 10:16:05 -0700691 case Kind::ExtFunc:
692 return cast<ExtFunction>(this)->print(os);
693 case Kind::CFGFunc:
694 return cast<CFGFunction>(this)->print(os);
695 case Kind::MLFunc:
696 return cast<MLFunction>(this)->print(os);
Chris Lattner4c95a502018-06-23 16:03:42 -0700697 }
698}
699
MLIR Team54b55a22018-07-18 10:16:05 -0700700void Function::dump() const { print(llvm::errs()); }
701
702void ExtFunction::print(raw_ostream &os) const {
703 ModuleState moduleState(os);
704 os << "extfunc ";
705 printFunctionSignature(this, &moduleState, os);
706 os << "\n";
Chris Lattner4c95a502018-06-23 16:03:42 -0700707}
708
709void CFGFunction::print(raw_ostream &os) const {
MLIR Team4718bc92018-07-17 16:56:54 -0700710 ModuleState moduleState(os);
711 CFGFunctionState state(this, &moduleState, os);
Chris Lattner4c95a502018-06-23 16:03:42 -0700712 state.print();
713}
714
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -0700715void MLFunction::print(raw_ostream &os) const {
MLIR Team4718bc92018-07-17 16:56:54 -0700716 ModuleState moduleState(os);
717 MLFunctionState state(this, &moduleState, os);
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700718 state.print();
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -0700719}
720
Chris Lattner4c95a502018-06-23 16:03:42 -0700721void Module::print(raw_ostream &os) const {
MLIR Team4718bc92018-07-17 16:56:54 -0700722 ModuleState moduleState(os);
723 moduleState.initialize(this);
724 moduleState.print(this);
Chris Lattner4c95a502018-06-23 16:03:42 -0700725}
726
MLIR Team54b55a22018-07-18 10:16:05 -0700727void Module::dump() const { print(llvm::errs()); }