blob: 03d9b1d31bc52e9d2b46132b3a7be3479d5da399 [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);
MLIR Teamb61885d2018-07-18 16:29:21 -070053 void print(const Attribute *attr) const;
MLIR Team4718bc92018-07-17 16:56:54 -070054 void print(const Type *type) const;
MLIR Team54b55a22018-07-18 10:16:05 -070055 void print(const Function *fn);
56 void print(const ExtFunction *fn);
57 void print(const CFGFunction *fn);
58 void print(const MLFunction *fn);
MLIR Team4718bc92018-07-17 16:56:54 -070059
MLIR Team54b55a22018-07-18 10:16:05 -070060 void recordAffineMapReference(const AffineMap *affineMap) {
MLIR Team4718bc92018-07-17 16:56:54 -070061 if (affineMapIds.count(affineMap) == 0) {
62 affineMapIds[affineMap] = nextAffineMapId++;
63 }
64 }
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
MLIR Team54b55a22018-07-18 10:16:05 -070074private:
MLIR Team4718bc92018-07-17 16:56:54 -070075 // Visit functions.
76 void visitFunction(const Function *fn);
77 void visitExtFunction(const ExtFunction *fn);
78 void visitCFGFunction(const CFGFunction *fn);
79 void visitMLFunction(const MLFunction *fn);
80 void visitType(const Type *type);
MLIR Teamb61885d2018-07-18 16:29:21 -070081 void visitAttribute(const Attribute *attr);
82 void visitOperation(const Operation *op);
83
84 void printAffineMapId(int affineMapId) const;
85 void printAffineMapReference(const AffineMap* affineMap) const;
MLIR Team4718bc92018-07-17 16:56:54 -070086
87 raw_ostream &os;
MLIR Team54b55a22018-07-18 10:16:05 -070088 DenseMap<const AffineMap *, int> affineMapIds;
MLIR Team4718bc92018-07-17 16:56:54 -070089 int nextAffineMapId = 0;
90};
MLIR Team54b55a22018-07-18 10:16:05 -070091} // end anonymous namespace
MLIR Team4718bc92018-07-17 16:56:54 -070092
MLIR Team54b55a22018-07-18 10:16:05 -070093ModuleState::ModuleState(raw_ostream &os) : os(os) {}
MLIR Team4718bc92018-07-17 16:56:54 -070094
95// Initializes module state, populating affine map state.
96void ModuleState::initialize(const Module *module) {
97 for (auto fn : module->functionList) {
98 visitFunction(fn);
99 }
100}
101
102// TODO Support visiting other types/instructions when implemented.
103void ModuleState::visitType(const Type *type) {
104 if (type->getKind() == Type::Kind::Function) {
105 // Visit input and result types for functions.
106 auto *funcType = cast<FunctionType>(type);
MLIR Team54b55a22018-07-18 10:16:05 -0700107 for (auto *input : funcType->getInputs()) {
MLIR Team4718bc92018-07-17 16:56:54 -0700108 visitType(input);
109 }
MLIR Team54b55a22018-07-18 10:16:05 -0700110 for (auto *result : funcType->getResults()) {
MLIR Team4718bc92018-07-17 16:56:54 -0700111 visitType(result);
112 }
113 } else if (type->getKind() == Type::Kind::MemRef) {
114 // Visit affine maps in memref type.
115 auto *memref = cast<MemRefType>(type);
MLIR Team54b55a22018-07-18 10:16:05 -0700116 for (AffineMap *map : memref->getAffineMaps()) {
MLIR Team4718bc92018-07-17 16:56:54 -0700117 recordAffineMapReference(map);
118 }
119 }
120}
121
MLIR Teamb61885d2018-07-18 16:29:21 -0700122void ModuleState::visitAttribute(const Attribute *attr) {
123 if (isa<AffineMapAttr>(attr)) {
124 recordAffineMapReference(cast<AffineMapAttr>(attr)->getValue());
125 } else if (isa<ArrayAttr>(attr)) {
126 for (auto elt : cast<ArrayAttr>(attr)->getValue()) {
127 visitAttribute(elt);
128 }
129 }
130}
131
132void ModuleState::visitOperation(const Operation *op) {
133 for (auto elt : op->getAttrs()) {
134 visitAttribute(elt.second);
135 }
136}
137
MLIR Team4718bc92018-07-17 16:56:54 -0700138void ModuleState::visitExtFunction(const ExtFunction *fn) {
139 visitType(fn->getType());
140}
141
142void ModuleState::visitCFGFunction(const CFGFunction *fn) {
143 visitType(fn->getType());
144 // TODO Visit function body instructions.
MLIR Teamb61885d2018-07-18 16:29:21 -0700145 for (auto &block : *fn) {
146 for (auto &op : block.getOperations()) {
147 visitOperation(&op);
148 }
149 }
MLIR Team4718bc92018-07-17 16:56:54 -0700150}
151
152void ModuleState::visitMLFunction(const MLFunction *fn) {
153 visitType(fn->getType());
MLIR Teamb61885d2018-07-18 16:29:21 -0700154 // TODO Visit function body statements (and attributes if required).
MLIR Team4718bc92018-07-17 16:56:54 -0700155}
156
157void ModuleState::visitFunction(const Function *fn) {
158 switch (fn->getKind()) {
MLIR Team54b55a22018-07-18 10:16:05 -0700159 case Function::Kind::ExtFunc:
160 return visitExtFunction(cast<ExtFunction>(fn));
161 case Function::Kind::CFGFunc:
162 return visitCFGFunction(cast<CFGFunction>(fn));
163 case Function::Kind::MLFunc:
164 return visitMLFunction(cast<MLFunction>(fn));
MLIR Team4718bc92018-07-17 16:56:54 -0700165 }
166}
167
MLIR Team4718bc92018-07-17 16:56:54 -0700168// Prints function with initialized module state.
MLIR Team54b55a22018-07-18 10:16:05 -0700169void ModuleState::print(const Function *fn) {
MLIR Team4718bc92018-07-17 16:56:54 -0700170 switch (fn->getKind()) {
MLIR Team54b55a22018-07-18 10:16:05 -0700171 case Function::Kind::ExtFunc:
172 return print(cast<ExtFunction>(fn));
173 case Function::Kind::CFGFunc:
174 return print(cast<CFGFunction>(fn));
175 case Function::Kind::MLFunc:
176 return print(cast<MLFunction>(fn));
MLIR Team4718bc92018-07-17 16:56:54 -0700177 }
178}
179
180// Prints affine map identifier.
MLIR Teamb61885d2018-07-18 16:29:21 -0700181void ModuleState::printAffineMapId(int affineMapId) const {
MLIR Team4718bc92018-07-17 16:56:54 -0700182 os << "#map" << affineMapId;
183}
184
MLIR Teamb61885d2018-07-18 16:29:21 -0700185void ModuleState::printAffineMapReference(const AffineMap* affineMap) const {
186 const int mapId = getAffineMapId(affineMap);
187 if (mapId >= 0) {
188 // Map will be printed at top of module so print reference to its id.
189 printAffineMapId(mapId);
190 } else {
191 // Map not in module state so print inline.
192 affineMap->print(os);
193 }
194}
195
MLIR Team4718bc92018-07-17 16:56:54 -0700196void ModuleState::print(const Module *module) {
MLIR Team54b55a22018-07-18 10:16:05 -0700197 for (const auto &mapAndId : affineMapIds) {
MLIR Teamb61885d2018-07-18 16:29:21 -0700198 printAffineMapId(mapAndId.second);
MLIR Team4718bc92018-07-17 16:56:54 -0700199 os << " = ";
200 mapAndId.first->print(os);
201 os << '\n';
202 }
MLIR Team54b55a22018-07-18 10:16:05 -0700203 for (auto *fn : module->functionList) print(fn);
MLIR Team4718bc92018-07-17 16:56:54 -0700204}
205
MLIR Teamb61885d2018-07-18 16:29:21 -0700206void ModuleState::print(const Attribute *attr) const {
207 switch (attr->getKind()) {
208 case Attribute::Kind::Bool:
209 os << (cast<BoolAttr>(attr)->getValue() ? "true" : "false");
210 break;
211 case Attribute::Kind::Integer:
212 os << cast<IntegerAttr>(attr)->getValue();
213 break;
214 case Attribute::Kind::Float:
215 // FIXME: this isn't precise, we should print with a hex format.
216 os << cast<FloatAttr>(attr)->getValue();
217 break;
218 case Attribute::Kind::String:
219 // FIXME: should escape the string.
220 os << '"' << cast<StringAttr>(attr)->getValue() << '"';
221 break;
222 case Attribute::Kind::Array: {
223 auto elts = cast<ArrayAttr>(attr)->getValue();
224 os << '[';
225 interleave(elts,
226 [&](Attribute *attr) { print(attr); },
227 [&]() { os << ", "; });
228 os << ']';
229 break;
230 }
231 case Attribute::Kind::AffineMap:
232 printAffineMapReference(cast<AffineMapAttr>(attr)->getValue());
233 break;
234 }
235}
236
MLIR Team4718bc92018-07-17 16:56:54 -0700237void ModuleState::print(const Type *type) const {
238 switch (type->getKind()) {
MLIR Team54b55a22018-07-18 10:16:05 -0700239 case Type::Kind::AffineInt:
240 os << "affineint";
241 return;
242 case Type::Kind::BF16:
243 os << "bf16";
244 return;
245 case Type::Kind::F16:
246 os << "f16";
247 return;
248 case Type::Kind::F32:
249 os << "f32";
250 return;
251 case Type::Kind::F64:
252 os << "f64";
253 return;
MLIR Team4718bc92018-07-17 16:56:54 -0700254
255 case Type::Kind::Integer: {
256 auto *integer = cast<IntegerType>(type);
257 os << 'i' << integer->getWidth();
258 return;
259 }
260 case Type::Kind::Function: {
261 auto *func = cast<FunctionType>(type);
262 os << '(';
MLIR Team54b55a22018-07-18 10:16:05 -0700263 interleave(func->getInputs(), [&](Type *type) { os << *type; },
MLIR Team4718bc92018-07-17 16:56:54 -0700264 [&]() { os << ", "; });
265 os << ") -> ";
266 auto results = func->getResults();
267 if (results.size() == 1)
268 os << *results[0];
269 else {
270 os << '(';
MLIR Team54b55a22018-07-18 10:16:05 -0700271 interleave(results, [&](Type *type) { os << *type; },
MLIR Team4718bc92018-07-17 16:56:54 -0700272 [&]() { os << ", "; });
273 os << ')';
274 }
275 return;
276 }
277 case Type::Kind::Vector: {
278 auto *v = cast<VectorType>(type);
279 os << "vector<";
MLIR Team54b55a22018-07-18 10:16:05 -0700280 for (auto dim : v->getShape()) os << dim << 'x';
MLIR Team4718bc92018-07-17 16:56:54 -0700281 os << *v->getElementType() << '>';
282 return;
283 }
284 case Type::Kind::RankedTensor: {
285 auto *v = cast<RankedTensorType>(type);
286 os << "tensor<";
287 for (auto dim : v->getShape()) {
288 if (dim < 0)
289 os << '?';
290 else
291 os << dim;
292 os << 'x';
293 }
294 os << *v->getElementType() << '>';
295 return;
296 }
297 case Type::Kind::UnrankedTensor: {
298 auto *v = cast<UnrankedTensorType>(type);
299 os << "tensor<??" << *v->getElementType() << '>';
300 return;
301 }
302 case Type::Kind::MemRef: {
303 auto *v = cast<MemRefType>(type);
304 os << "memref<";
305 for (auto dim : v->getShape()) {
306 if (dim < 0)
307 os << '?';
308 else
309 os << dim;
310 os << 'x';
311 }
312 os << *v->getElementType();
313 for (auto map : v->getAffineMaps()) {
314 os << ", ";
MLIR Teamb61885d2018-07-18 16:29:21 -0700315 printAffineMapReference(map);
MLIR Team4718bc92018-07-17 16:56:54 -0700316 }
317 os << ", " << v->getMemorySpace();
318 os << '>';
319 return;
320 }
321 }
322}
323
324//===----------------------------------------------------------------------===//
Chris Lattner4c95a502018-06-23 16:03:42 -0700325// Function printing
326//===----------------------------------------------------------------------===//
327
MLIR Team4718bc92018-07-17 16:56:54 -0700328static void printFunctionSignature(const Function *fn,
329 const ModuleState *moduleState,
330 raw_ostream &os) {
Chris Lattner4c95a502018-06-23 16:03:42 -0700331 auto type = fn->getType();
332
333 os << "@" << fn->getName() << '(';
334 interleave(type->getInputs(),
MLIR Team4718bc92018-07-17 16:56:54 -0700335 [&](Type *eltType) { moduleState->print(eltType); },
Chris Lattner4c95a502018-06-23 16:03:42 -0700336 [&]() { os << ", "; });
337 os << ')';
338
339 switch (type->getResults().size()) {
MLIR Team54b55a22018-07-18 10:16:05 -0700340 case 0:
341 break;
Chris Lattner4c95a502018-06-23 16:03:42 -0700342 case 1:
MLIR Team4718bc92018-07-17 16:56:54 -0700343 os << " -> ";
344 moduleState->print(type->getResults()[0]);
Chris Lattner4c95a502018-06-23 16:03:42 -0700345 break;
346 default:
347 os << " -> (";
348 interleave(type->getResults(),
MLIR Team4718bc92018-07-17 16:56:54 -0700349 [&](Type *eltType) { moduleState->print(eltType); },
Chris Lattner4c95a502018-06-23 16:03:42 -0700350 [&]() { os << ", "; });
351 os << ')';
352 break;
353 }
354}
355
MLIR Team54b55a22018-07-18 10:16:05 -0700356void ModuleState::print(const ExtFunction *fn) {
Chris Lattner4c95a502018-06-23 16:03:42 -0700357 os << "extfunc ";
MLIR Team54b55a22018-07-18 10:16:05 -0700358 printFunctionSignature(fn, this, os);
359 os << '\n';
Chris Lattner4c95a502018-06-23 16:03:42 -0700360}
361
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700362namespace {
363
364// FunctionState contains common functionality for printing
365// CFG and ML functions.
366class FunctionState {
367public:
MLIR Team4718bc92018-07-17 16:56:54 -0700368 FunctionState(MLIRContext *context, const ModuleState *moduleState,
369 raw_ostream &os);
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700370
371 void printOperation(const Operation *op);
372
373protected:
374 raw_ostream &os;
MLIR Team4718bc92018-07-17 16:56:54 -0700375 const ModuleState *moduleState;
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700376 const OperationSet &operationSet;
377};
MLIR Team54b55a22018-07-18 10:16:05 -0700378} // end anonymous namespace
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700379
MLIR Team4718bc92018-07-17 16:56:54 -0700380FunctionState::FunctionState(MLIRContext *context,
MLIR Team54b55a22018-07-18 10:16:05 -0700381 const ModuleState *moduleState, raw_ostream &os)
382 : os(os),
383 moduleState(moduleState),
MLIR Team4718bc92018-07-17 16:56:54 -0700384 operationSet(OperationSet::get(context)) {}
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700385
386void FunctionState::printOperation(const Operation *op) {
387 // Check to see if this is a known operation. If so, use the registered
388 // custom printer hook.
389 if (auto opInfo = operationSet.lookup(op->getName().str())) {
390 os << " ";
391 opInfo->printAssembly(op, os);
392 return;
393 }
394
395 // TODO: escape name if necessary.
396 os << " \"" << op->getName().str() << "\"()";
397
Chris Lattner7f9cc272018-07-19 08:35:28 -0700398 // FIXME: Print operand references.
399
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700400 auto attrs = op->getAttrs();
401 if (!attrs.empty()) {
402 os << '{';
403 interleave(
404 attrs,
MLIR Teamb61885d2018-07-18 16:29:21 -0700405 [&](NamedAttribute attr) {
406 os << attr.first << ": ";
407 moduleState->print(attr.second); },
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700408 [&]() { os << ", "; });
409 os << '}';
410 }
Chris Lattner3b2ef762018-07-18 15:31:25 -0700411
412 // TODO: Print signature type once that is plumbed through to Operation.
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700413}
414
Chris Lattner4c95a502018-06-23 16:03:42 -0700415//===----------------------------------------------------------------------===//
416// CFG Function printing
417//===----------------------------------------------------------------------===//
418
419namespace {
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700420class CFGFunctionState : public FunctionState {
Chris Lattner4c95a502018-06-23 16:03:42 -0700421public:
MLIR Team4718bc92018-07-17 16:56:54 -0700422 CFGFunctionState(const CFGFunction *function, const ModuleState *moduleState,
423 raw_ostream &os);
Chris Lattner4c95a502018-06-23 16:03:42 -0700424
425 const CFGFunction *getFunction() const { return function; }
426
427 void print();
428 void print(const BasicBlock *block);
Chris Lattnered65a732018-06-28 20:45:33 -0700429
430 void print(const Instruction *inst);
431 void print(const OperationInst *inst);
432 void print(const ReturnInst *inst);
433 void print(const BranchInst *inst);
Chris Lattner4c95a502018-06-23 16:03:42 -0700434
435 unsigned getBBID(const BasicBlock *block) {
436 auto it = basicBlockIDs.find(block);
437 assert(it != basicBlockIDs.end() && "Block not in this function?");
438 return it->second;
439 }
440
441private:
442 const CFGFunction *function;
MLIR Team54b55a22018-07-18 10:16:05 -0700443 DenseMap<const BasicBlock *, unsigned> basicBlockIDs;
Chris Lattner4c95a502018-06-23 16:03:42 -0700444};
MLIR Team54b55a22018-07-18 10:16:05 -0700445} // end anonymous namespace
Chris Lattner4c95a502018-06-23 16:03:42 -0700446
MLIR Team4718bc92018-07-17 16:56:54 -0700447CFGFunctionState::CFGFunctionState(const CFGFunction *function,
448 const ModuleState *moduleState,
449 raw_ostream &os)
450 : FunctionState(function->getContext(), moduleState, os),
451 function(function) {
Chris Lattner4c95a502018-06-23 16:03:42 -0700452 // Each basic block gets a unique ID per function.
453 unsigned blockID = 0;
MLIR Team54b55a22018-07-18 10:16:05 -0700454 for (auto &block : *function) basicBlockIDs[&block] = blockID++;
Chris Lattner4c95a502018-06-23 16:03:42 -0700455}
456
457void CFGFunctionState::print() {
458 os << "cfgfunc ";
MLIR Team4718bc92018-07-17 16:56:54 -0700459 printFunctionSignature(this->getFunction(), moduleState, os);
Chris Lattner4c95a502018-06-23 16:03:42 -0700460 os << " {\n";
461
MLIR Team54b55a22018-07-18 10:16:05 -0700462 for (auto &block : *function) print(&block);
Chris Lattner4c95a502018-06-23 16:03:42 -0700463 os << "}\n\n";
464}
465
466void CFGFunctionState::print(const BasicBlock *block) {
467 os << "bb" << getBBID(block) << ":\n";
468
Chris Lattnered65a732018-06-28 20:45:33 -0700469 // TODO Print arguments.
Jacques Pienaarb020c542018-07-15 00:06:54 -0700470 for (auto &inst : block->getOperations()) {
Chris Lattner3a467cc2018-07-01 20:28:00 -0700471 print(&inst);
Jacques Pienaarb020c542018-07-15 00:06:54 -0700472 os << "\n";
473 }
Chris Lattner4c95a502018-06-23 16:03:42 -0700474
475 print(block->getTerminator());
Jacques Pienaarb020c542018-07-15 00:06:54 -0700476 os << "\n";
Chris Lattner4c95a502018-06-23 16:03:42 -0700477}
478
Chris Lattnered65a732018-06-28 20:45:33 -0700479void CFGFunctionState::print(const Instruction *inst) {
Chris Lattner4c95a502018-06-23 16:03:42 -0700480 switch (inst->getKind()) {
Chris Lattnered65a732018-06-28 20:45:33 -0700481 case Instruction::Kind::Operation:
482 return print(cast<OperationInst>(inst));
Chris Lattnerf6d80a02018-06-24 11:18:29 -0700483 case TerminatorInst::Kind::Branch:
Chris Lattnered65a732018-06-28 20:45:33 -0700484 return print(cast<BranchInst>(inst));
Chris Lattner4c95a502018-06-23 16:03:42 -0700485 case TerminatorInst::Kind::Return:
Chris Lattnered65a732018-06-28 20:45:33 -0700486 return print(cast<ReturnInst>(inst));
Chris Lattner4c95a502018-06-23 16:03:42 -0700487 }
488}
489
Chris Lattnered65a732018-06-28 20:45:33 -0700490void CFGFunctionState::print(const OperationInst *inst) {
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700491 printOperation(inst);
Chris Lattnered65a732018-06-28 20:45:33 -0700492
Chris Lattner3b2ef762018-07-18 15:31:25 -0700493 // FIXME: Move this into printOperation when Operation has operands and
494 // results
495
496 // Print the type signature of the operation.
497 os << " : (";
498 interleave(
499 inst->getOperands(),
500 [&](const InstOperand &op) { moduleState->print(op.get()->getType()); },
501 [&]() { os << ", "; });
502 os << ") -> ";
503
504 auto resultList = inst->getResults();
505 if (resultList.size() == 1) {
506 moduleState->print(resultList[0].getType());
507 } else {
508 os << '(';
509 interleave(
510 resultList,
511 [&](const InstResult &result) { moduleState->print(result.getType()); },
512 [&]() { os << ", "; });
513 os << ')';
514 }
515}
Chris Lattnered65a732018-06-28 20:45:33 -0700516void CFGFunctionState::print(const BranchInst *inst) {
Jacques Pienaarb020c542018-07-15 00:06:54 -0700517 os << " br bb" << getBBID(inst->getDest());
Chris Lattnered65a732018-06-28 20:45:33 -0700518}
MLIR Team54b55a22018-07-18 10:16:05 -0700519void CFGFunctionState::print(const ReturnInst *inst) { os << " return"; }
520
521void ModuleState::print(const CFGFunction *fn) {
522 CFGFunctionState state(fn, this, os);
523 state.print();
Chris Lattnered65a732018-06-28 20:45:33 -0700524}
525
Chris Lattner4c95a502018-06-23 16:03:42 -0700526//===----------------------------------------------------------------------===//
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700527// ML Function printing
Chris Lattner4c95a502018-06-23 16:03:42 -0700528//===----------------------------------------------------------------------===//
529
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700530namespace {
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700531class MLFunctionState : public FunctionState {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700532public:
MLIR Team4718bc92018-07-17 16:56:54 -0700533 MLFunctionState(const MLFunction *function, const ModuleState *moduleState,
534 raw_ostream &os);
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700535
536 const MLFunction *getFunction() const { return function; }
537
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700538 // Prints ML function
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700539 void print();
540
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700541 // Methods to print ML function statements
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700542 void print(const Statement *stmt);
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700543 void print(const OperationStmt *stmt);
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700544 void print(const ForStmt *stmt);
545 void print(const IfStmt *stmt);
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700546 void print(const StmtBlock *block);
547
548 // Number of spaces used for indenting nested statements
549 const static unsigned indentWidth = 2;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700550
551private:
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700552 const MLFunction *function;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700553 int numSpaces;
554};
MLIR Team54b55a22018-07-18 10:16:05 -0700555} // end anonymous namespace
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700556
MLIR Team4718bc92018-07-17 16:56:54 -0700557MLFunctionState::MLFunctionState(const MLFunction *function,
558 const ModuleState *moduleState,
559 raw_ostream &os)
560 : FunctionState(function->getContext(), moduleState, os),
MLIR Team54b55a22018-07-18 10:16:05 -0700561 function(function),
562 numSpaces(0) {}
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700563
564void MLFunctionState::print() {
565 os << "mlfunc ";
566 // FIXME: should print argument names rather than just signature
MLIR Team4718bc92018-07-17 16:56:54 -0700567 printFunctionSignature(function, moduleState, os);
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700568 os << " {\n";
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700569 print(function);
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700570 os << " return\n";
571 os << "}\n\n";
572}
573
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700574void MLFunctionState::print(const StmtBlock *block) {
575 numSpaces += indentWidth;
Jacques Pienaarb020c542018-07-15 00:06:54 -0700576 for (auto &stmt : block->getStatements()) {
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700577 print(&stmt);
Jacques Pienaarb020c542018-07-15 00:06:54 -0700578 os << "\n";
579 }
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700580 numSpaces -= indentWidth;
581}
582
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700583void MLFunctionState::print(const Statement *stmt) {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700584 switch (stmt->getKind()) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -0700585 case Statement::Kind::Operation:
586 return print(cast<OperationStmt>(stmt));
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700587 case Statement::Kind::For:
588 return print(cast<ForStmt>(stmt));
589 case Statement::Kind::If:
590 return print(cast<IfStmt>(stmt));
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700591 }
592}
593
MLIR Team54b55a22018-07-18 10:16:05 -0700594void MLFunctionState::print(const OperationStmt *stmt) { printOperation(stmt); }
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700595
596void MLFunctionState::print(const ForStmt *stmt) {
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -0700597 os.indent(numSpaces) << "for x = " << *stmt->getLowerBound();
598 os << " to " << *stmt->getUpperBound();
599 if (stmt->getStep()->getValue() != 1)
600 os << " step " << *stmt->getStep();
601
602 os << " {\n";
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700603 print(static_cast<const StmtBlock *>(stmt));
Tatiana Shpeisman565b9642018-07-16 11:47:09 -0700604 os.indent(numSpaces) << "}";
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700605}
606
607void MLFunctionState::print(const IfStmt *stmt) {
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700608 os.indent(numSpaces) << "if () {\n";
609 print(stmt->getThenClause());
610 os.indent(numSpaces) << "}";
611 if (stmt->hasElseClause()) {
612 os << " else {\n";
613 print(stmt->getElseClause());
614 os.indent(numSpaces) << "}";
615 }
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700616}
617
MLIR Team54b55a22018-07-18 10:16:05 -0700618void ModuleState::print(const MLFunction *fn) {
619 MLFunctionState state(fn, this, os);
MLIR Team4718bc92018-07-17 16:56:54 -0700620 state.print();
621}
622
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700623//===----------------------------------------------------------------------===//
624// print and dump methods
625//===----------------------------------------------------------------------===//
Chris Lattnered65a732018-06-28 20:45:33 -0700626
MLIR Teamb61885d2018-07-18 16:29:21 -0700627void Attribute::print(raw_ostream &os) const {
628 ModuleState moduleState(os);
629 moduleState.print(this);
630}
631
632void Attribute::dump() const {
633 print(llvm::errs());
634}
635
MLIR Team4718bc92018-07-17 16:56:54 -0700636void Type::print(raw_ostream &os) const {
637 ModuleState moduleState(os);
638 moduleState.print(this);
639}
640
MLIR Team54b55a22018-07-18 10:16:05 -0700641void Type::dump() const { print(llvm::errs()); }
MLIR Team4718bc92018-07-17 16:56:54 -0700642
Chris Lattnered65a732018-06-28 20:45:33 -0700643void Instruction::print(raw_ostream &os) const {
MLIR Team4718bc92018-07-17 16:56:54 -0700644 ModuleState moduleState(os);
645 CFGFunctionState state(getFunction(), &moduleState, os);
Chris Lattner4c95a502018-06-23 16:03:42 -0700646 state.print(this);
647}
648
Chris Lattnered65a732018-06-28 20:45:33 -0700649void Instruction::dump() const {
Chris Lattner4c95a502018-06-23 16:03:42 -0700650 print(llvm::errs());
Jacques Pienaarb020c542018-07-15 00:06:54 -0700651 llvm::errs() << "\n";
Chris Lattner4c95a502018-06-23 16:03:42 -0700652}
653
MLIR Team718c82f2018-07-16 09:45:22 -0700654void AffineMap::dump() const {
655 print(llvm::errs());
656 llvm::errs() << "\n";
657}
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700658
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700659void AffineExpr::dump() const {
660 print(llvm::errs());
661 llvm::errs() << "\n";
662}
663
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700664void AffineSymbolExpr::print(raw_ostream &os) const {
Uday Bondhugulac1faf662018-07-19 14:08:50 -0700665 os << 's' << getPosition();
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700666}
667
Uday Bondhugulac1faf662018-07-19 14:08:50 -0700668void AffineDimExpr::print(raw_ostream &os) const { os << 'd' << getPosition(); }
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700669
670void AffineConstantExpr::print(raw_ostream &os) const { os << getValue(); }
671
Uday Bondhugulac1faf662018-07-19 14:08:50 -0700672static void printAdd(const AffineBinaryOpExpr *addExpr, raw_ostream &os) {
673 os << '(' << *addExpr->getLHS();
674
675 // Pretty print addition to a product that has a negative operand as a
676 // subtraction.
677 if (auto *rhs = dyn_cast<AffineBinaryOpExpr>(addExpr->getRHS())) {
678 if (rhs->getKind() == AffineExpr::Kind::Mul) {
679 if (auto *rrhs = dyn_cast<AffineConstantExpr>(rhs->getRHS())) {
680 if (rrhs->getValue() < 0) {
681 os << " - (" << *rhs->getLHS() << " * " << -rrhs->getValue() << "))";
682 return;
683 }
684 }
685 }
686 }
687
688 // Pretty print addition to a negative number as a subtraction.
689 if (auto *rhs = dyn_cast<AffineConstantExpr>(addExpr->getRHS())) {
690 if (rhs->getValue() < 0) {
691 os << " - " << -rhs->getValue() << ")";
692 return;
693 }
694 }
695
696 os << " + " << *addExpr->getRHS() << ")";
697}
698
699void AffineBinaryOpExpr::print(raw_ostream &os) const {
700 switch (getKind()) {
701 case Kind::Add:
702 return printAdd(this, os);
703 case Kind::Mul:
704 os << "(" << *getLHS() << " * " << *getRHS() << ")";
705 return;
706 case Kind::FloorDiv:
707 os << "(" << *getLHS() << " floordiv " << *getRHS() << ")";
708 return;
709 case Kind::CeilDiv:
710 os << "(" << *getLHS() << " ceildiv " << *getRHS() << ")";
711 return;
712 case Kind::Mod:
713 os << "(" << *getLHS() << " mod " << *getRHS() << ")";
714 return;
715 default:
716 llvm_unreachable("unexpected affine binary op expression");
717 }
718}
719
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700720void AffineExpr::print(raw_ostream &os) const {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700721 switch (getKind()) {
722 case Kind::SymbolId:
723 return cast<AffineSymbolExpr>(this)->print(os);
724 case Kind::DimId:
725 return cast<AffineDimExpr>(this)->print(os);
726 case Kind::Constant:
727 return cast<AffineConstantExpr>(this)->print(os);
728 case Kind::Add:
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700729 case Kind::Mul:
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700730 case Kind::FloorDiv:
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700731 case Kind::CeilDiv:
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700732 case Kind::Mod:
Uday Bondhugulac1faf662018-07-19 14:08:50 -0700733 return cast<AffineBinaryOpExpr>(this)->print(os);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700734 }
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700735}
736
737void AffineMap::print(raw_ostream &os) const {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700738 // Dimension identifiers.
739 os << "(";
MLIR Team54b55a22018-07-18 10:16:05 -0700740 for (int i = 0; i < (int)getNumDims() - 1; i++) os << "d" << i << ", ";
741 if (getNumDims() >= 1) os << "d" << getNumDims() - 1;
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700742 os << ")";
743
744 // Symbolic identifiers.
745 if (getNumSymbols() >= 1) {
746 os << " [";
MLIR Team54b55a22018-07-18 10:16:05 -0700747 for (int i = 0; i < (int)getNumSymbols() - 1; i++) os << "s" << i << ", ";
748 if (getNumSymbols() >= 1) os << "s" << getNumSymbols() - 1;
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700749 os << "]";
750 }
751
752 // AffineMap should have at least one result.
753 assert(!getResults().empty());
754 // Result affine expressions.
755 os << " -> (";
756 interleave(getResults(), [&](AffineExpr *expr) { os << *expr; },
757 [&]() { os << ", "; });
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700758 os << ")";
759
760 if (!isBounded()) {
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700761 return;
762 }
763
764 // Print range sizes for bounded affine maps.
765 os << " size (";
766 interleave(getRangeSizes(), [&](AffineExpr *expr) { os << *expr; },
767 [&]() { os << ", "; });
MLIR Team718c82f2018-07-16 09:45:22 -0700768 os << ")";
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700769}
770
Chris Lattner4c95a502018-06-23 16:03:42 -0700771void BasicBlock::print(raw_ostream &os) const {
MLIR Team4718bc92018-07-17 16:56:54 -0700772 ModuleState moduleState(os);
773 CFGFunctionState state(getFunction(), &moduleState, os);
Chris Lattner4c95a502018-06-23 16:03:42 -0700774 state.print();
775}
776
MLIR Team54b55a22018-07-18 10:16:05 -0700777void BasicBlock::dump() const { print(llvm::errs()); }
Chris Lattner4c95a502018-06-23 16:03:42 -0700778
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700779void Statement::print(raw_ostream &os) const {
MLIR Team4718bc92018-07-17 16:56:54 -0700780 ModuleState moduleState(os);
781 MLFunctionState state(getFunction(), &moduleState, os);
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700782 state.print(this);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -0700783}
784
MLIR Team54b55a22018-07-18 10:16:05 -0700785void Statement::dump() const { print(llvm::errs()); }
Jacques Pienaarb020c542018-07-15 00:06:54 -0700786
Chris Lattner4c95a502018-06-23 16:03:42 -0700787void Function::print(raw_ostream &os) const {
788 switch (getKind()) {
MLIR Team54b55a22018-07-18 10:16:05 -0700789 case Kind::ExtFunc:
790 return cast<ExtFunction>(this)->print(os);
791 case Kind::CFGFunc:
792 return cast<CFGFunction>(this)->print(os);
793 case Kind::MLFunc:
794 return cast<MLFunction>(this)->print(os);
Chris Lattner4c95a502018-06-23 16:03:42 -0700795 }
796}
797
MLIR Team54b55a22018-07-18 10:16:05 -0700798void Function::dump() const { print(llvm::errs()); }
799
800void ExtFunction::print(raw_ostream &os) const {
801 ModuleState moduleState(os);
802 os << "extfunc ";
803 printFunctionSignature(this, &moduleState, os);
804 os << "\n";
Chris Lattner4c95a502018-06-23 16:03:42 -0700805}
806
807void CFGFunction::print(raw_ostream &os) const {
MLIR Team4718bc92018-07-17 16:56:54 -0700808 ModuleState moduleState(os);
809 CFGFunctionState state(this, &moduleState, os);
Chris Lattner4c95a502018-06-23 16:03:42 -0700810 state.print();
811}
812
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -0700813void MLFunction::print(raw_ostream &os) const {
MLIR Team4718bc92018-07-17 16:56:54 -0700814 ModuleState moduleState(os);
815 MLFunctionState state(this, &moduleState, os);
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700816 state.print();
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -0700817}
818
Chris Lattner4c95a502018-06-23 16:03:42 -0700819void Module::print(raw_ostream &os) const {
MLIR Team4718bc92018-07-17 16:56:54 -0700820 ModuleState moduleState(os);
821 moduleState.initialize(this);
822 moduleState.print(this);
Chris Lattner4c95a502018-06-23 16:03:42 -0700823}
824
MLIR Team54b55a22018-07-18 10:16:05 -0700825void Module::dump() const { print(llvm::errs()); }