blob: cd90e3ee9157a5895c3f7a6393458134e2fc28b6 [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 Lattner0497c4b2018-08-15 09:09:54 -070037#include "llvm/ADT/APFloat.h"
Chris Lattner4c95a502018-06-23 16:03:42 -070038#include "llvm/ADT/DenseMap.h"
Chris Lattnerd4964212018-08-01 10:43:18 -070039#include "llvm/ADT/SmallString.h"
40#include "llvm/ADT/StringExtras.h"
41#include "llvm/ADT/StringSet.h"
Chris Lattner4c95a502018-06-23 16:03:42 -070042using namespace mlir;
43
MLIR Team54b55a22018-07-18 10:16:05 -070044void Identifier::print(raw_ostream &os) const { os << str(); }
Chris Lattner4c95a502018-06-23 16:03:42 -070045
MLIR Team54b55a22018-07-18 10:16:05 -070046void Identifier::dump() const { print(llvm::errs()); }
Chris Lattner7121b802018-07-04 20:45:39 -070047
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -070048OpAsmPrinter::~OpAsmPrinter() {}
49
Chris Lattner4c95a502018-06-23 16:03:42 -070050//===----------------------------------------------------------------------===//
Chris Lattner4fd59b02018-07-20 09:35:47 -070051// ModuleState
MLIR Team4718bc92018-07-17 16:56:54 -070052//===----------------------------------------------------------------------===//
53
54namespace {
MLIR Team54b55a22018-07-18 10:16:05 -070055class ModuleState {
56public:
Chris Lattner4fd59b02018-07-20 09:35:47 -070057 /// This is the operation set for the current context if it is knowable (a
58 /// context could be determined), otherwise this is null.
59 OperationSet *const operationSet;
MLIR Team4718bc92018-07-17 16:56:54 -070060
Chris Lattner4fd59b02018-07-20 09:35:47 -070061 explicit ModuleState(MLIRContext *context)
62 : operationSet(context ? &OperationSet::get(context) : nullptr) {}
63
64 // Initializes module state, populating affine map state.
MLIR Team4718bc92018-07-17 16:56:54 -070065 void initialize(const Module *module);
66
MLIR Team54b55a22018-07-18 10:16:05 -070067 int getAffineMapId(const AffineMap *affineMap) const {
MLIR Team4718bc92018-07-17 16:56:54 -070068 auto it = affineMapIds.find(affineMap);
69 if (it == affineMapIds.end()) {
70 return -1;
71 }
72 return it->second;
73 }
74
James Molloyc4666722018-07-24 09:48:31 -070075 ArrayRef<const AffineMap *> getAffineMapIds() const { return affineMapsById; }
Chris Lattner4fd59b02018-07-20 09:35:47 -070076
Uday Bondhugulabc535622018-08-07 14:24:38 -070077 int getIntegerSetId(const IntegerSet *integerSet) const {
78 auto it = integerSetIds.find(integerSet);
79 if (it == integerSetIds.end()) {
80 return -1;
81 }
82 return it->second;
83 }
84
85 ArrayRef<const IntegerSet *> getIntegerSetIds() const {
86 return integerSetsById;
87 }
88
MLIR Team54b55a22018-07-18 10:16:05 -070089private:
Chris Lattner4fd59b02018-07-20 09:35:47 -070090 void recordAffineMapReference(const AffineMap *affineMap) {
91 if (affineMapIds.count(affineMap) == 0) {
James Molloyc4666722018-07-24 09:48:31 -070092 affineMapIds[affineMap] = affineMapsById.size();
93 affineMapsById.push_back(affineMap);
Chris Lattner4fd59b02018-07-20 09:35:47 -070094 }
95 }
96
Uday Bondhugulabc535622018-08-07 14:24:38 -070097 void recordIntegerSetReference(const IntegerSet *integerSet) {
98 if (integerSetIds.count(integerSet) == 0) {
99 integerSetIds[integerSet] = integerSetsById.size();
100 integerSetsById.push_back(integerSet);
101 }
102 }
103
MLIR Team4718bc92018-07-17 16:56:54 -0700104 // Visit functions.
105 void visitFunction(const Function *fn);
106 void visitExtFunction(const ExtFunction *fn);
107 void visitCFGFunction(const CFGFunction *fn);
108 void visitMLFunction(const MLFunction *fn);
Uday Bondhugulabc535622018-08-07 14:24:38 -0700109 void visitStatement(const Statement *stmt);
110 void visitForStmt(const ForStmt *forStmt);
111 void visitIfStmt(const IfStmt *ifStmt);
112 void visitOperationStmt(const OperationStmt *opStmt);
MLIR Team4718bc92018-07-17 16:56:54 -0700113 void visitType(const Type *type);
MLIR Teamb61885d2018-07-18 16:29:21 -0700114 void visitAttribute(const Attribute *attr);
115 void visitOperation(const Operation *op);
116
MLIR Team54b55a22018-07-18 10:16:05 -0700117 DenseMap<const AffineMap *, int> affineMapIds;
James Molloyc4666722018-07-24 09:48:31 -0700118 std::vector<const AffineMap *> affineMapsById;
Uday Bondhugulabc535622018-08-07 14:24:38 -0700119
120 DenseMap<const IntegerSet *, int> integerSetIds;
121 std::vector<const IntegerSet *> integerSetsById;
MLIR Team4718bc92018-07-17 16:56:54 -0700122};
James Molloy87d81022018-07-23 11:44:40 -0700123} // end anonymous namespace
MLIR Team4718bc92018-07-17 16:56:54 -0700124
125// TODO Support visiting other types/instructions when implemented.
126void ModuleState::visitType(const Type *type) {
Chris Lattner3164ae62018-07-28 09:36:25 -0700127 if (auto *funcType = dyn_cast<FunctionType>(type)) {
MLIR Team4718bc92018-07-17 16:56:54 -0700128 // Visit input and result types for functions.
Chris Lattner3164ae62018-07-28 09:36:25 -0700129 for (auto *input : funcType->getInputs())
MLIR Team4718bc92018-07-17 16:56:54 -0700130 visitType(input);
Chris Lattner3164ae62018-07-28 09:36:25 -0700131 for (auto *result : funcType->getResults())
MLIR Team4718bc92018-07-17 16:56:54 -0700132 visitType(result);
Chris Lattner3164ae62018-07-28 09:36:25 -0700133 } else if (auto *memref = dyn_cast<MemRefType>(type)) {
MLIR Team4718bc92018-07-17 16:56:54 -0700134 // Visit affine maps in memref type.
Chris Lattner3164ae62018-07-28 09:36:25 -0700135 for (auto *map : memref->getAffineMaps()) {
MLIR Team4718bc92018-07-17 16:56:54 -0700136 recordAffineMapReference(map);
137 }
138 }
139}
140
MLIR Teamb61885d2018-07-18 16:29:21 -0700141void ModuleState::visitAttribute(const Attribute *attr) {
Chris Lattner3164ae62018-07-28 09:36:25 -0700142 if (auto *mapAttr = dyn_cast<AffineMapAttr>(attr)) {
143 recordAffineMapReference(mapAttr->getValue());
Uday Bondhugulabc535622018-08-07 14:24:38 -0700144 } else if (auto *arrayAttr = dyn_cast<ArrayAttr>(attr)) {
145 for (auto elt : arrayAttr->getValue()) {
MLIR Teamb61885d2018-07-18 16:29:21 -0700146 visitAttribute(elt);
147 }
148 }
149}
150
151void ModuleState::visitOperation(const Operation *op) {
Chris Lattnerca2ee872018-07-31 18:32:59 -0700152 // Visit all the types used in the operation.
153 for (auto *operand : op->getOperands())
154 visitType(operand->getType());
155 for (auto *result : op->getResults())
156 visitType(result->getType());
157
158 // Visit each of the attributes.
159 for (auto elt : op->getAttrs())
MLIR Teamb61885d2018-07-18 16:29:21 -0700160 visitAttribute(elt.second);
MLIR Teamb61885d2018-07-18 16:29:21 -0700161}
162
MLIR Team4718bc92018-07-17 16:56:54 -0700163void ModuleState::visitExtFunction(const ExtFunction *fn) {
164 visitType(fn->getType());
165}
166
167void ModuleState::visitCFGFunction(const CFGFunction *fn) {
168 visitType(fn->getType());
MLIR Teamb61885d2018-07-18 16:29:21 -0700169 for (auto &block : *fn) {
170 for (auto &op : block.getOperations()) {
171 visitOperation(&op);
172 }
173 }
MLIR Team4718bc92018-07-17 16:56:54 -0700174}
175
Uday Bondhugulabc535622018-08-07 14:24:38 -0700176void ModuleState::visitIfStmt(const IfStmt *ifStmt) {
177 recordIntegerSetReference(ifStmt->getCondition());
Chris Lattnere787b322018-08-08 11:14:57 -0700178 for (auto &childStmt : *ifStmt->getThen())
Uday Bondhugulabc535622018-08-07 14:24:38 -0700179 visitStatement(&childStmt);
Chris Lattnere787b322018-08-08 11:14:57 -0700180 if (ifStmt->hasElse())
181 for (auto &childStmt : *ifStmt->getElse())
Uday Bondhugulabc535622018-08-07 14:24:38 -0700182 visitStatement(&childStmt);
183}
184
185void ModuleState::visitForStmt(const ForStmt *forStmt) {
186 for (auto &childStmt : *forStmt)
187 visitStatement(&childStmt);
188}
189
190void ModuleState::visitOperationStmt(const OperationStmt *opStmt) {
Chris Lattner0497c4b2018-08-15 09:09:54 -0700191 for (auto attr : opStmt->getAttrs())
192 visitAttribute(attr.second);
Uday Bondhugulabc535622018-08-07 14:24:38 -0700193}
194
195void ModuleState::visitStatement(const Statement *stmt) {
196 switch (stmt->getKind()) {
197 case Statement::Kind::If:
198 return visitIfStmt(cast<IfStmt>(stmt));
199 case Statement::Kind::For:
200 return visitForStmt(cast<ForStmt>(stmt));
201 case Statement::Kind::Operation:
202 return visitOperationStmt(cast<OperationStmt>(stmt));
203 default:
204 return;
205 }
206}
207
MLIR Team4718bc92018-07-17 16:56:54 -0700208void ModuleState::visitMLFunction(const MLFunction *fn) {
209 visitType(fn->getType());
Uday Bondhugulabc535622018-08-07 14:24:38 -0700210 for (auto &stmt : *fn) {
211 ModuleState::visitStatement(&stmt);
212 }
MLIR Team4718bc92018-07-17 16:56:54 -0700213}
214
215void ModuleState::visitFunction(const Function *fn) {
216 switch (fn->getKind()) {
MLIR Team54b55a22018-07-18 10:16:05 -0700217 case Function::Kind::ExtFunc:
218 return visitExtFunction(cast<ExtFunction>(fn));
219 case Function::Kind::CFGFunc:
220 return visitCFGFunction(cast<CFGFunction>(fn));
221 case Function::Kind::MLFunc:
222 return visitMLFunction(cast<MLFunction>(fn));
MLIR Team4718bc92018-07-17 16:56:54 -0700223 }
224}
225
Uday Bondhugulabc535622018-08-07 14:24:38 -0700226// Initializes module state, populating affine map and integer set state.
Chris Lattner4fd59b02018-07-20 09:35:47 -0700227void ModuleState::initialize(const Module *module) {
Chris Lattnera8e47672018-07-25 14:08:16 -0700228 for (auto &fn : *module) {
229 visitFunction(&fn);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700230 }
231}
232
233//===----------------------------------------------------------------------===//
234// ModulePrinter
235//===----------------------------------------------------------------------===//
236
237namespace {
238class ModulePrinter {
239public:
240 ModulePrinter(raw_ostream &os, ModuleState &state) : os(os), state(state) {}
241 explicit ModulePrinter(const ModulePrinter &printer)
242 : os(printer.os), state(printer.state) {}
243
244 template <typename Container, typename UnaryFunctor>
245 inline void interleaveComma(const Container &c, UnaryFunctor each_fn) const {
246 interleave(c.begin(), c.end(), each_fn, [&]() { os << ", "; });
247 }
248
249 void print(const Module *module);
Chris Lattner1aa46322018-08-21 17:55:22 -0700250 void printFunctionReference(const Function *func);
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700251 void printAttribute(const Attribute *attr);
252 void printType(const Type *type);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700253 void print(const Function *fn);
254 void print(const ExtFunction *fn);
255 void print(const CFGFunction *fn);
256 void print(const MLFunction *fn);
257
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700258 void printAffineMap(const AffineMap *map);
259 void printAffineExpr(const AffineExpr *expr);
Uday Bondhugulabc535622018-08-07 14:24:38 -0700260 void printAffineConstraint(const AffineExpr *expr, bool isEq);
261 void printIntegerSet(const IntegerSet *set);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700262
263protected:
264 raw_ostream &os;
265 ModuleState &state;
266
267 void printFunctionSignature(const Function *fn);
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -0700268 void printFunctionResultType(const FunctionType *type);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700269 void printAffineMapId(int affineMapId) const;
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700270 void printAffineMapReference(const AffineMap *affineMap);
Uday Bondhugulabc535622018-08-07 14:24:38 -0700271 void printIntegerSetId(int integerSetId) const;
272 void printIntegerSetReference(const IntegerSet *integerSet);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700273
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700274 /// This enum is used to represent the binding stength of the enclosing
275 /// context that an AffineExpr is being printed in, so we can intelligently
276 /// produce parens.
277 enum class BindingStrength {
278 Weak, // + and -
279 Strong, // All other binary operators.
280 };
281 void printAffineExprInternal(const AffineExpr *expr,
282 BindingStrength enclosingTightness);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700283};
284} // end anonymous namespace
285
MLIR Team4718bc92018-07-17 16:56:54 -0700286// Prints function with initialized module state.
Chris Lattner4fd59b02018-07-20 09:35:47 -0700287void ModulePrinter::print(const Function *fn) {
MLIR Team4718bc92018-07-17 16:56:54 -0700288 switch (fn->getKind()) {
MLIR Team54b55a22018-07-18 10:16:05 -0700289 case Function::Kind::ExtFunc:
290 return print(cast<ExtFunction>(fn));
291 case Function::Kind::CFGFunc:
292 return print(cast<CFGFunction>(fn));
293 case Function::Kind::MLFunc:
294 return print(cast<MLFunction>(fn));
MLIR Team4718bc92018-07-17 16:56:54 -0700295 }
296}
297
298// Prints affine map identifier.
Chris Lattner4fd59b02018-07-20 09:35:47 -0700299void ModulePrinter::printAffineMapId(int affineMapId) const {
MLIR Team4718bc92018-07-17 16:56:54 -0700300 os << "#map" << affineMapId;
301}
302
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700303void ModulePrinter::printAffineMapReference(const AffineMap *affineMap) {
Chris Lattner4fd59b02018-07-20 09:35:47 -0700304 int mapId = state.getAffineMapId(affineMap);
MLIR Teamb61885d2018-07-18 16:29:21 -0700305 if (mapId >= 0) {
306 // Map will be printed at top of module so print reference to its id.
307 printAffineMapId(mapId);
308 } else {
309 // Map not in module state so print inline.
310 affineMap->print(os);
311 }
312}
313
Uday Bondhugulabc535622018-08-07 14:24:38 -0700314// Prints integer set identifier.
315void ModulePrinter::printIntegerSetId(int integerSetId) const {
316 os << "@@set" << integerSetId;
317}
318
319void ModulePrinter::printIntegerSetReference(const IntegerSet *integerSet) {
320 int setId;
321 if ((setId = state.getIntegerSetId(integerSet)) >= 0) {
322 // The set will be printed at top of module; so print reference to its id.
323 printIntegerSetId(setId);
324 } else {
325 // Set not in module state so print inline.
326 integerSet->print(os);
327 }
328}
329
Chris Lattner4fd59b02018-07-20 09:35:47 -0700330void ModulePrinter::print(const Module *module) {
James Molloyc4666722018-07-24 09:48:31 -0700331 for (const auto &map : state.getAffineMapIds()) {
332 printAffineMapId(state.getAffineMapId(map));
MLIR Team4718bc92018-07-17 16:56:54 -0700333 os << " = ";
James Molloyc4666722018-07-24 09:48:31 -0700334 map->print(os);
MLIR Team4718bc92018-07-17 16:56:54 -0700335 os << '\n';
336 }
Uday Bondhugulabc535622018-08-07 14:24:38 -0700337 for (const auto &set : state.getIntegerSetIds()) {
338 printIntegerSetId(state.getIntegerSetId(set));
339 os << " = ";
340 set->print(os);
341 os << '\n';
342 }
Chris Lattnera8e47672018-07-25 14:08:16 -0700343 for (auto const &fn : *module)
344 print(&fn);
MLIR Team4718bc92018-07-17 16:56:54 -0700345}
346
Chris Lattner0497c4b2018-08-15 09:09:54 -0700347/// Print a floating point value in a way that the parser will be able to
348/// round-trip losslessly.
349static void printFloatValue(double value, raw_ostream &os) {
350 APFloat apValue(value);
351
352 // We would like to output the FP constant value in exponential notation,
353 // but we cannot do this if doing so will lose precision. Check here to
354 // make sure that we only output it in exponential format if we can parse
355 // the value back and get the same value.
356 bool isInf = apValue.isInfinity();
357 bool isNaN = apValue.isNaN();
358 if (!isInf && !isNaN) {
359 SmallString<128> strValue;
360 apValue.toString(strValue, 6, 0, false);
361
362 // Check to make sure that the stringized number is not some string like
363 // "Inf" or NaN, that atof will accept, but the lexer will not. Check
364 // that the string matches the "[-+]?[0-9]" regex.
365 assert(((strValue[0] >= '0' && strValue[0] <= '9') ||
366 ((strValue[0] == '-' || strValue[0] == '+') &&
367 (strValue[1] >= '0' && strValue[1] <= '9'))) &&
368 "[-+]?[0-9] regex does not match!");
369 // Reparse stringized version!
370 if (APFloat(APFloat::IEEEdouble(), strValue).convertToDouble() == value) {
371 os << strValue;
372 return;
373 }
374 }
375
376 // Otherwise, print it in a hexadecimal form. Convert it to an integer so we
377 // can print it out using integer math.
378 union {
379 double doubleValue;
380 uint64_t integerValue;
381 };
382 doubleValue = value;
383 os << "0x";
384 // Print out 16 nibbles worth of hex digit.
385 for (unsigned i = 0; i != 16; ++i) {
386 os << llvm::hexdigit(integerValue >> 60);
387 integerValue <<= 4;
388 }
389}
390
Chris Lattner1aa46322018-08-21 17:55:22 -0700391void ModulePrinter::printFunctionReference(const Function *func) {
392 os << '@' << func->getName();
393}
394
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700395void ModulePrinter::printAttribute(const Attribute *attr) {
MLIR Teamb61885d2018-07-18 16:29:21 -0700396 switch (attr->getKind()) {
397 case Attribute::Kind::Bool:
398 os << (cast<BoolAttr>(attr)->getValue() ? "true" : "false");
399 break;
400 case Attribute::Kind::Integer:
401 os << cast<IntegerAttr>(attr)->getValue();
402 break;
403 case Attribute::Kind::Float:
Chris Lattner0497c4b2018-08-15 09:09:54 -0700404 printFloatValue(cast<FloatAttr>(attr)->getValue(), os);
MLIR Teamb61885d2018-07-18 16:29:21 -0700405 break;
406 case Attribute::Kind::String:
Chris Lattner0497c4b2018-08-15 09:09:54 -0700407 os << '"';
408 printEscapedString(cast<StringAttr>(attr)->getValue(), os);
409 os << '"';
MLIR Teamb61885d2018-07-18 16:29:21 -0700410 break;
Chris Lattner0497c4b2018-08-15 09:09:54 -0700411 case Attribute::Kind::Array:
MLIR Teamb61885d2018-07-18 16:29:21 -0700412 os << '[';
Chris Lattner0497c4b2018-08-15 09:09:54 -0700413 interleaveComma(cast<ArrayAttr>(attr)->getValue(),
414 [&](Attribute *attr) { printAttribute(attr); });
MLIR Teamb61885d2018-07-18 16:29:21 -0700415 os << ']';
416 break;
MLIR Teamb61885d2018-07-18 16:29:21 -0700417 case Attribute::Kind::AffineMap:
418 printAffineMapReference(cast<AffineMapAttr>(attr)->getValue());
419 break;
James Molloyf0d2f442018-08-03 01:54:46 -0700420 case Attribute::Kind::Type:
421 printType(cast<TypeAttr>(attr)->getValue());
422 break;
Chris Lattner4613d9e2018-08-19 21:17:22 -0700423 case Attribute::Kind::Function: {
424 auto *function = cast<FunctionAttr>(attr)->getValue();
425 if (!function) {
426 os << "<<FUNCTION ATTR FOR DELETED FUNCTION>>";
427 } else {
Chris Lattner1aa46322018-08-21 17:55:22 -0700428 printFunctionReference(function);
429 os << " : ";
Chris Lattner4613d9e2018-08-19 21:17:22 -0700430 printType(function->getType());
431 }
432 break;
433 }
MLIR Teamb61885d2018-07-18 16:29:21 -0700434 }
435}
436
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700437void ModulePrinter::printType(const Type *type) {
MLIR Team4718bc92018-07-17 16:56:54 -0700438 switch (type->getKind()) {
MLIR Team54b55a22018-07-18 10:16:05 -0700439 case Type::Kind::AffineInt:
440 os << "affineint";
441 return;
442 case Type::Kind::BF16:
443 os << "bf16";
444 return;
445 case Type::Kind::F16:
446 os << "f16";
447 return;
448 case Type::Kind::F32:
449 os << "f32";
450 return;
451 case Type::Kind::F64:
452 os << "f64";
453 return;
Jacques Pienaarc0d69302018-07-27 11:07:12 -0700454 case Type::Kind::TFControl:
455 os << "tf_control";
456 return;
James Molloy72b0cbe2018-08-01 12:55:27 -0700457 case Type::Kind::TFString:
458 os << "tf_string";
459 return;
MLIR Team4718bc92018-07-17 16:56:54 -0700460
461 case Type::Kind::Integer: {
462 auto *integer = cast<IntegerType>(type);
463 os << 'i' << integer->getWidth();
464 return;
465 }
466 case Type::Kind::Function: {
467 auto *func = cast<FunctionType>(type);
468 os << '(';
Chris Lattner413db6a2018-07-25 12:55:50 -0700469 interleaveComma(func->getInputs(), [&](Type *type) { printType(type); });
MLIR Team4718bc92018-07-17 16:56:54 -0700470 os << ") -> ";
471 auto results = func->getResults();
472 if (results.size() == 1)
473 os << *results[0];
474 else {
475 os << '(';
Chris Lattner413db6a2018-07-25 12:55:50 -0700476 interleaveComma(results, [&](Type *type) { printType(type); });
MLIR Team4718bc92018-07-17 16:56:54 -0700477 os << ')';
478 }
479 return;
480 }
481 case Type::Kind::Vector: {
482 auto *v = cast<VectorType>(type);
483 os << "vector<";
James Molloy87d81022018-07-23 11:44:40 -0700484 for (auto dim : v->getShape())
485 os << dim << 'x';
MLIR Team4718bc92018-07-17 16:56:54 -0700486 os << *v->getElementType() << '>';
487 return;
488 }
489 case Type::Kind::RankedTensor: {
490 auto *v = cast<RankedTensorType>(type);
491 os << "tensor<";
492 for (auto dim : v->getShape()) {
493 if (dim < 0)
494 os << '?';
495 else
496 os << dim;
497 os << 'x';
498 }
499 os << *v->getElementType() << '>';
500 return;
501 }
502 case Type::Kind::UnrankedTensor: {
503 auto *v = cast<UnrankedTensorType>(type);
Chris Lattner413db6a2018-07-25 12:55:50 -0700504 os << "tensor<??";
505 printType(v->getElementType());
506 os << '>';
MLIR Team4718bc92018-07-17 16:56:54 -0700507 return;
508 }
509 case Type::Kind::MemRef: {
510 auto *v = cast<MemRefType>(type);
511 os << "memref<";
512 for (auto dim : v->getShape()) {
513 if (dim < 0)
514 os << '?';
515 else
516 os << dim;
517 os << 'x';
518 }
Chris Lattner413db6a2018-07-25 12:55:50 -0700519 printType(v->getElementType());
MLIR Team4718bc92018-07-17 16:56:54 -0700520 for (auto map : v->getAffineMaps()) {
521 os << ", ";
MLIR Teamb61885d2018-07-18 16:29:21 -0700522 printAffineMapReference(map);
MLIR Team4718bc92018-07-17 16:56:54 -0700523 }
Chris Lattner413db6a2018-07-25 12:55:50 -0700524 // Only print the memory space if it is the non-default one.
525 if (v->getMemorySpace())
526 os << ", " << v->getMemorySpace();
MLIR Team4718bc92018-07-17 16:56:54 -0700527 os << '>';
528 return;
529 }
530 }
531}
532
533//===----------------------------------------------------------------------===//
Chris Lattner4fd59b02018-07-20 09:35:47 -0700534// Affine expressions and maps
535//===----------------------------------------------------------------------===//
536
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700537void ModulePrinter::printAffineExpr(const AffineExpr *expr) {
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700538 printAffineExprInternal(expr, BindingStrength::Weak);
539}
540
541void ModulePrinter::printAffineExprInternal(
542 const AffineExpr *expr, BindingStrength enclosingTightness) {
543 const char *binopSpelling = nullptr;
Chris Lattner4fd59b02018-07-20 09:35:47 -0700544 switch (expr->getKind()) {
545 case AffineExpr::Kind::SymbolId:
546 os << 's' << cast<AffineSymbolExpr>(expr)->getPosition();
547 return;
548 case AffineExpr::Kind::DimId:
549 os << 'd' << cast<AffineDimExpr>(expr)->getPosition();
550 return;
551 case AffineExpr::Kind::Constant:
552 os << cast<AffineConstantExpr>(expr)->getValue();
553 return;
554 case AffineExpr::Kind::Add:
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700555 binopSpelling = " + ";
556 break;
Chris Lattner4fd59b02018-07-20 09:35:47 -0700557 case AffineExpr::Kind::Mul:
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700558 binopSpelling = " * ";
559 break;
Chris Lattner4fd59b02018-07-20 09:35:47 -0700560 case AffineExpr::Kind::FloorDiv:
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700561 binopSpelling = " floordiv ";
562 break;
Chris Lattner4fd59b02018-07-20 09:35:47 -0700563 case AffineExpr::Kind::CeilDiv:
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700564 binopSpelling = " ceildiv ";
565 break;
Chris Lattner4fd59b02018-07-20 09:35:47 -0700566 case AffineExpr::Kind::Mod:
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700567 binopSpelling = " mod ";
568 break;
Chris Lattner4fd59b02018-07-20 09:35:47 -0700569 }
Chris Lattner4fd59b02018-07-20 09:35:47 -0700570
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700571 auto *binOp = cast<AffineBinaryOpExpr>(expr);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700572
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700573 // Handle tightly binding binary operators.
574 if (binOp->getKind() != AffineExpr::Kind::Add) {
575 if (enclosingTightness == BindingStrength::Strong)
576 os << '(';
577
578 printAffineExprInternal(binOp->getLHS(), BindingStrength::Strong);
579 os << binopSpelling;
580 printAffineExprInternal(binOp->getRHS(), BindingStrength::Strong);
581
582 if (enclosingTightness == BindingStrength::Strong)
583 os << ')';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700584 return;
585 }
586
587 // Print out special "pretty" forms for add.
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700588 if (enclosingTightness == BindingStrength::Strong)
589 os << '(';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700590
591 // Pretty print addition to a product that has a negative operand as a
592 // subtraction.
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700593 if (auto *rhs = dyn_cast<AffineBinaryOpExpr>(binOp->getRHS())) {
Chris Lattner4fd59b02018-07-20 09:35:47 -0700594 if (rhs->getKind() == AffineExpr::Kind::Mul) {
595 if (auto *rrhs = dyn_cast<AffineConstantExpr>(rhs->getRHS())) {
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700596 if (rrhs->getValue() == -1) {
597 printAffineExprInternal(binOp->getLHS(), BindingStrength::Weak);
598 os << " - ";
599 printAffineExprInternal(rhs->getLHS(), BindingStrength::Weak);
600
601 if (enclosingTightness == BindingStrength::Strong)
602 os << ')';
603 return;
604 }
605
606 if (rrhs->getValue() < -1) {
607 printAffineExprInternal(binOp->getLHS(), BindingStrength::Weak);
Uday Bondhugula970f5b82018-08-01 22:02:00 -0700608 os << " - ";
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700609 printAffineExprInternal(rhs->getLHS(), BindingStrength::Strong);
Uday Bondhugula970f5b82018-08-01 22:02:00 -0700610 os << " * " << -rrhs->getValue();
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700611 if (enclosingTightness == BindingStrength::Strong)
612 os << ')';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700613 return;
614 }
615 }
616 }
617 }
618
619 // Pretty print addition to a negative number as a subtraction.
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700620 if (auto *rhs = dyn_cast<AffineConstantExpr>(binOp->getRHS())) {
Chris Lattner4fd59b02018-07-20 09:35:47 -0700621 if (rhs->getValue() < 0) {
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700622 printAffineExprInternal(binOp->getLHS(), BindingStrength::Weak);
Uday Bondhugulabc535622018-08-07 14:24:38 -0700623 os << " - " << -rhs->getValue();
624 if (enclosingTightness == BindingStrength::Strong)
625 os << ')';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700626 return;
627 }
628 }
629
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700630 printAffineExprInternal(binOp->getLHS(), BindingStrength::Weak);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700631 os << " + ";
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700632 printAffineExprInternal(binOp->getRHS(), BindingStrength::Weak);
633
634 if (enclosingTightness == BindingStrength::Strong)
635 os << ')';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700636}
637
Uday Bondhugulabc535622018-08-07 14:24:38 -0700638void ModulePrinter::printAffineConstraint(const AffineExpr *expr, bool isEq) {
639 printAffineExprInternal(expr, BindingStrength::Weak);
640 isEq ? os << " == 0" : os << " >= 0";
641}
642
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700643void ModulePrinter::printAffineMap(const AffineMap *map) {
Chris Lattner4fd59b02018-07-20 09:35:47 -0700644 // Dimension identifiers.
645 os << '(';
Chris Lattnerdc3ba382018-07-29 14:13:03 -0700646 for (int i = 0; i < (int)map->getNumDims() - 1; ++i)
647 os << 'd' << i << ", ";
Chris Lattner4fd59b02018-07-20 09:35:47 -0700648 if (map->getNumDims() >= 1)
Chris Lattnerdc3ba382018-07-29 14:13:03 -0700649 os << 'd' << map->getNumDims() - 1;
650 os << ')';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700651
652 // Symbolic identifiers.
Chris Lattnerdc3ba382018-07-29 14:13:03 -0700653 if (map->getNumSymbols() != 0) {
654 os << '[';
655 for (unsigned i = 0; i < map->getNumSymbols() - 1; ++i)
656 os << 's' << i << ", ";
Chris Lattner4fd59b02018-07-20 09:35:47 -0700657 if (map->getNumSymbols() >= 1)
Chris Lattnerdc3ba382018-07-29 14:13:03 -0700658 os << 's' << map->getNumSymbols() - 1;
659 os << ']';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700660 }
661
662 // AffineMap should have at least one result.
663 assert(!map->getResults().empty());
664 // Result affine expressions.
665 os << " -> (";
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700666 interleaveComma(map->getResults(),
667 [&](AffineExpr *expr) { printAffineExpr(expr); });
Chris Lattnerdc3ba382018-07-29 14:13:03 -0700668 os << ')';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700669
670 if (!map->isBounded()) {
671 return;
672 }
673
674 // Print range sizes for bounded affine maps.
675 os << " size (";
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700676 interleaveComma(map->getRangeSizes(),
677 [&](AffineExpr *expr) { printAffineExpr(expr); });
Chris Lattnerdc3ba382018-07-29 14:13:03 -0700678 os << ')';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700679}
680
Uday Bondhugulabc535622018-08-07 14:24:38 -0700681void ModulePrinter::printIntegerSet(const IntegerSet *set) {
682 // Dimension identifiers.
683 os << '(';
684 for (unsigned i = 1; i < set->getNumDims(); ++i)
685 os << 'd' << i - 1 << ", ";
686 if (set->getNumDims() >= 1)
687 os << 'd' << set->getNumDims() - 1;
688 os << ')';
689
690 // Symbolic identifiers.
691 if (set->getNumSymbols() != 0) {
692 os << '[';
693 for (unsigned i = 0; i < set->getNumSymbols() - 1; ++i)
694 os << 's' << i << ", ";
695 if (set->getNumSymbols() >= 1)
696 os << 's' << set->getNumSymbols() - 1;
697 os << ']';
698 }
699
700 // Print constraints.
701 os << " : (";
702 auto numConstraints = set->getNumConstraints();
703 for (int i = 1; i < numConstraints; ++i) {
704 printAffineConstraint(set->getConstraint(i - 1), set->isEq(i - 1));
705 os << ", ";
706 }
707 if (numConstraints >= 1)
708 printAffineConstraint(set->getConstraint(numConstraints - 1),
709 set->isEq(numConstraints - 1));
710 os << ')';
711}
712
Chris Lattner4fd59b02018-07-20 09:35:47 -0700713//===----------------------------------------------------------------------===//
Chris Lattner4c95a502018-06-23 16:03:42 -0700714// Function printing
715//===----------------------------------------------------------------------===//
716
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -0700717void ModulePrinter::printFunctionResultType(const FunctionType *type) {
Chris Lattner4c95a502018-06-23 16:03:42 -0700718 switch (type->getResults().size()) {
MLIR Team54b55a22018-07-18 10:16:05 -0700719 case 0:
720 break;
Chris Lattner4c95a502018-06-23 16:03:42 -0700721 case 1:
MLIR Team4718bc92018-07-17 16:56:54 -0700722 os << " -> ";
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700723 printType(type->getResults()[0]);
Chris Lattner4c95a502018-06-23 16:03:42 -0700724 break;
725 default:
726 os << " -> (";
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700727 interleaveComma(type->getResults(),
728 [&](Type *eltType) { printType(eltType); });
Chris Lattner4c95a502018-06-23 16:03:42 -0700729 os << ')';
730 break;
731 }
732}
733
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -0700734void ModulePrinter::printFunctionSignature(const Function *fn) {
735 auto type = fn->getType();
736
737 os << "@" << fn->getName() << '(';
738 interleaveComma(type->getInputs(),
739 [&](Type *eltType) { printType(eltType); });
740 os << ')';
741
742 printFunctionResultType(type);
743}
744
Chris Lattner4fd59b02018-07-20 09:35:47 -0700745void ModulePrinter::print(const ExtFunction *fn) {
Chris Lattner4c95a502018-06-23 16:03:42 -0700746 os << "extfunc ";
Chris Lattner4fd59b02018-07-20 09:35:47 -0700747 printFunctionSignature(fn);
MLIR Team54b55a22018-07-18 10:16:05 -0700748 os << '\n';
Chris Lattner4c95a502018-06-23 16:03:42 -0700749}
750
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700751namespace {
752
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700753// FunctionPrinter contains common functionality for printing
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700754// CFG and ML functions.
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700755class FunctionPrinter : public ModulePrinter, private OpAsmPrinter {
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700756public:
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700757 FunctionPrinter(const ModulePrinter &other) : ModulePrinter(other) {}
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700758
759 void printOperation(const Operation *op);
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700760 void printDefaultOp(const Operation *op);
761
762 // Implement OpAsmPrinter.
763 raw_ostream &getStream() const { return os; }
764 void printType(const Type *type) { ModulePrinter::printType(type); }
765 void printAttribute(const Attribute *attr) {
766 ModulePrinter::printAttribute(attr);
767 }
768 void printAffineMap(const AffineMap *map) {
Chris Lattner3164ae62018-07-28 09:36:25 -0700769 return ModulePrinter::printAffineMapReference(map);
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700770 }
Uday Bondhugulabc535622018-08-07 14:24:38 -0700771 void printIntegerSet(const IntegerSet *set) {
772 return ModulePrinter::printIntegerSetReference(set);
773 }
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700774 void printAffineExpr(const AffineExpr *expr) {
775 return ModulePrinter::printAffineExpr(expr);
776 }
Chris Lattner1aa46322018-08-21 17:55:22 -0700777 void printFunctionReference(const Function *func) {
778 return ModulePrinter::printFunctionReference(func);
779 }
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700780
781 void printOperand(const SSAValue *value) { printValueID(value); }
Tatiana Shpeismanc335d182018-08-03 11:12:34 -0700782
Chris Lattner85cf26d2018-08-02 16:54:36 -0700783 void printOptionalAttrDict(ArrayRef<NamedAttribute> attrs,
784 ArrayRef<const char *> elidedAttrs = {}) override;
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700785
Chris Lattnerd4964212018-08-01 10:43:18 -0700786 enum { nameSentinel = ~0U };
787
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700788protected:
Chris Lattnerf8cce872018-07-20 09:28:54 -0700789 void numberValueID(const SSAValue *value) {
790 assert(!valueIDs.count(value) && "Value numbered multiple times");
Chris Lattnerd4964212018-08-01 10:43:18 -0700791
792 SmallString<32> specialNameBuffer;
793 llvm::raw_svector_ostream specialName(specialNameBuffer);
794
795 // Give constant integers special names.
796 if (auto *op = value->getDefiningOperation()) {
797 if (auto intOp = op->getAs<ConstantIntOp>()) {
Chris Lattner384da8c2018-08-02 17:16:58 -0700798 // i1 constants get special names.
799 if (intOp->getType()->isInteger(1)) {
800 specialName << (intOp->getValue() ? "true" : "false");
801 } else {
Chris Lattner992a1272018-08-07 12:02:37 -0700802 specialName << 'c' << intOp->getValue() << '_' << *intOp->getType();
Chris Lattner384da8c2018-08-02 17:16:58 -0700803 }
Chris Lattner992a1272018-08-07 12:02:37 -0700804 } else if (auto intOp = op->getAs<ConstantAffineIntOp>()) {
805 specialName << 'c' << intOp->getValue();
Chris Lattner4613d9e2018-08-19 21:17:22 -0700806 } else if (auto constant = op->getAs<ConstantOp>()) {
807 if (isa<FunctionAttr>(constant->getValue()))
808 specialName << 'f';
809 else
810 specialName << "cst";
Chris Lattnerd4964212018-08-01 10:43:18 -0700811 }
Tatiana Shpeisman3838db72018-07-30 15:18:10 -0700812 }
Chris Lattnerd4964212018-08-01 10:43:18 -0700813
814 if (specialNameBuffer.empty()) {
815 switch (value->getKind()) {
816 case SSAValueKind::BBArgument:
817 // If this is an argument to the function, give it an 'arg' name.
818 if (auto *bb = cast<BBArgument>(value)->getOwner())
819 if (auto *fn = bb->getFunction())
820 if (&fn->front() == bb) {
821 specialName << "arg" << nextArgumentID++;
822 break;
823 }
824 // Otherwise number it normally.
825 LLVM_FALLTHROUGH;
826 case SSAValueKind::InstResult:
827 case SSAValueKind::StmtResult:
828 // This is an uninteresting result, give it a boring number and be
829 // done with it.
830 valueIDs[value] = nextValueID++;
831 return;
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -0700832 case SSAValueKind::MLFuncArgument:
Chris Lattnerd4964212018-08-01 10:43:18 -0700833 specialName << "arg" << nextArgumentID++;
834 break;
835 case SSAValueKind::ForStmt:
836 specialName << 'i' << nextLoopID++;
837 break;
838 }
839 }
840
841 // Ok, this value had an interesting name. Remember it with a sentinel.
842 valueIDs[value] = nameSentinel;
843
844 // Remember that we've used this name, checking to see if we had a conflict.
845 auto insertRes = usedNames.insert(specialName.str());
846 if (insertRes.second) {
847 // If this is the first use of the name, then we're successful!
848 valueNames[value] = insertRes.first->first();
849 return;
850 }
851
852 // Otherwise, we had a conflict - probe until we find a unique name. This
853 // is guaranteed to terminate (and usually in a single iteration) because it
854 // generates new names by incrementing nextConflictID.
855 while (1) {
856 std::string probeName =
857 specialName.str().str() + "_" + llvm::utostr(nextConflictID++);
858 insertRes = usedNames.insert(probeName);
859 if (insertRes.second) {
860 // If this is the first use of the name, then we're successful!
861 valueNames[value] = insertRes.first->first();
862 return;
863 }
864 }
Chris Lattnerf8cce872018-07-20 09:28:54 -0700865 }
866
Tatiana Shpeisman3838db72018-07-30 15:18:10 -0700867 void printValueID(const SSAValue *value, bool printResultNo = true) const {
Chris Lattner6119d382018-07-20 18:41:34 -0700868 int resultNo = -1;
869 auto lookupValue = value;
870
Tatiana Shpeisman3838db72018-07-30 15:18:10 -0700871 // If this is a reference to the result of a multi-result instruction or
872 // statement, print out the # identifier and make sure to map our lookup
873 // to the first result of the instruction.
Chris Lattner6119d382018-07-20 18:41:34 -0700874 if (auto *result = dyn_cast<InstResult>(value)) {
875 if (result->getOwner()->getNumResults() != 1) {
876 resultNo = result->getResultNumber();
877 lookupValue = result->getOwner()->getResult(0);
878 }
Tatiana Shpeisman3838db72018-07-30 15:18:10 -0700879 } else if (auto *result = dyn_cast<StmtResult>(value)) {
880 if (result->getOwner()->getNumResults() != 1) {
881 resultNo = result->getResultNumber();
882 lookupValue = result->getOwner()->getResult(0);
883 }
Chris Lattner6119d382018-07-20 18:41:34 -0700884 }
885
886 auto it = valueIDs.find(lookupValue);
887 if (it == valueIDs.end()) {
Chris Lattnerf8cce872018-07-20 09:28:54 -0700888 os << "<<INVALID SSA VALUE>>";
Chris Lattner6119d382018-07-20 18:41:34 -0700889 return;
890 }
891
Tatiana Shpeisman3838db72018-07-30 15:18:10 -0700892 os << '%';
Chris Lattnerd4964212018-08-01 10:43:18 -0700893 if (it->second != nameSentinel) {
894 os << it->second;
895 } else {
896 auto nameIt = valueNames.find(lookupValue);
897 assert(nameIt != valueNames.end() && "Didn't have a name entry?");
898 os << nameIt->second;
899 }
Tatiana Shpeisman3838db72018-07-30 15:18:10 -0700900
Tatiana Shpeisman3838db72018-07-30 15:18:10 -0700901 if (resultNo != -1 && printResultNo)
Chris Lattner6119d382018-07-20 18:41:34 -0700902 os << '#' << resultNo;
Chris Lattnerf8cce872018-07-20 09:28:54 -0700903 }
904
905private:
Chris Lattnerd4964212018-08-01 10:43:18 -0700906 /// This is the value ID for each SSA value in the current function. If this
907 /// returns ~0, then the valueID has an entry in valueNames.
Chris Lattnerf8cce872018-07-20 09:28:54 -0700908 DenseMap<const SSAValue *, unsigned> valueIDs;
Chris Lattnerd4964212018-08-01 10:43:18 -0700909 DenseMap<const SSAValue *, StringRef> valueNames;
910
911 /// This keeps track of all of the non-numeric names that are in flight,
912 /// allowing us to check for duplicates.
913 llvm::StringSet<> usedNames;
914
915 /// This is the next value ID to assign in numbering.
Chris Lattnerf8cce872018-07-20 09:28:54 -0700916 unsigned nextValueID = 0;
Chris Lattnerd4964212018-08-01 10:43:18 -0700917 /// This is the ID to assign to the next induction variable.
Tatiana Shpeismanc9c4b342018-07-31 07:40:14 -0700918 unsigned nextLoopID = 0;
Chris Lattnerd4964212018-08-01 10:43:18 -0700919 /// This is the next ID to assign to an MLFunction argument.
920 unsigned nextArgumentID = 0;
921
922 /// This is the next ID to assign when a name conflict is detected.
923 unsigned nextConflictID = 0;
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700924};
James Molloy87d81022018-07-23 11:44:40 -0700925} // end anonymous namespace
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700926
Chris Lattner85cf26d2018-08-02 16:54:36 -0700927void FunctionPrinter::printOptionalAttrDict(
928 ArrayRef<NamedAttribute> attrs, ArrayRef<const char *> elidedAttrs) {
929 // If there are no attributes, then there is nothing to be done.
930 if (attrs.empty())
931 return;
932
933 // Filter out any attributes that shouldn't be included.
934 SmallVector<NamedAttribute, 8> filteredAttrs;
935 for (auto attr : attrs) {
Chris Lattner4613d9e2018-08-19 21:17:22 -0700936 auto attrName = attr.first.strref();
Chris Lattner85cf26d2018-08-02 16:54:36 -0700937 // Never print attributes that start with a colon. These are internal
938 // attributes that represent location or other internal metadata.
939 if (attrName.startswith(":"))
940 continue;
941
942 // If the caller has requested that this attribute be ignored, then drop it.
943 bool ignore = false;
944 for (const char *elide : elidedAttrs)
945 ignore |= attrName == StringRef(elide);
946
947 // Otherwise add it to our filteredAttrs list.
948 if (!ignore)
949 filteredAttrs.push_back(attr);
950 }
951
952 // If there are no attributes left to print after filtering, then we're done.
953 if (filteredAttrs.empty())
954 return;
955
956 // Otherwise, print them all out in braces.
957 os << " {";
958 interleaveComma(filteredAttrs, [&](NamedAttribute attr) {
959 os << attr.first << ": ";
960 printAttribute(attr.second);
961 });
962 os << '}';
963}
964
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700965void FunctionPrinter::printOperation(const Operation *op) {
Chris Lattnerac591f12018-07-22 21:02:26 -0700966 if (op->getNumResults()) {
Tatiana Shpeisman3838db72018-07-30 15:18:10 -0700967 printValueID(op->getResult(0), /*printResultNo=*/false);
Chris Lattnerac591f12018-07-22 21:02:26 -0700968 os << " = ";
Chris Lattnerf8cce872018-07-20 09:28:54 -0700969 }
970
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700971 // Check to see if this is a known operation. If so, use the registered
972 // custom printer hook.
Chris Lattner4613d9e2018-08-19 21:17:22 -0700973 if (auto *opInfo = state.operationSet->lookup(op->getName())) {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700974 opInfo->printAssembly(op, this);
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700975 return;
976 }
977
Chris Lattnerf8cce872018-07-20 09:28:54 -0700978 // Otherwise use the standard verbose printing approach.
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700979 printDefaultOp(op);
980}
Chris Lattnerf8cce872018-07-20 09:28:54 -0700981
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700982void FunctionPrinter::printDefaultOp(const Operation *op) {
Chris Lattner0497c4b2018-08-15 09:09:54 -0700983 os << '"';
Chris Lattner4613d9e2018-08-19 21:17:22 -0700984 printEscapedString(op->getName(), os);
Chris Lattner0497c4b2018-08-15 09:09:54 -0700985 os << "\"(";
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700986
Chris Lattnerac591f12018-07-22 21:02:26 -0700987 interleaveComma(op->getOperands(),
988 [&](const SSAValue *value) { printValueID(value); });
Chris Lattner7f9cc272018-07-19 08:35:28 -0700989
Chris Lattnerf8cce872018-07-20 09:28:54 -0700990 os << ')';
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700991 auto attrs = op->getAttrs();
Chris Lattner85cf26d2018-08-02 16:54:36 -0700992 printOptionalAttrDict(attrs);
Chris Lattner3b2ef762018-07-18 15:31:25 -0700993
Chris Lattnerac591f12018-07-22 21:02:26 -0700994 // Print the type signature of the operation.
995 os << " : (";
996 interleaveComma(op->getOperands(),
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700997 [&](const SSAValue *value) { printType(value->getType()); });
Chris Lattnerac591f12018-07-22 21:02:26 -0700998 os << ") -> ";
Chris Lattnerf8cce872018-07-20 09:28:54 -0700999
Chris Lattnerac591f12018-07-22 21:02:26 -07001000 if (op->getNumResults() == 1) {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -07001001 printType(op->getResult(0)->getType());
Chris Lattnerac591f12018-07-22 21:02:26 -07001002 } else {
1003 os << '(';
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -07001004 interleaveComma(op->getResults(), [&](const SSAValue *result) {
1005 printType(result->getType());
1006 });
Chris Lattnerac591f12018-07-22 21:02:26 -07001007 os << ')';
Chris Lattnerf8cce872018-07-20 09:28:54 -07001008 }
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -07001009}
1010
Chris Lattner4c95a502018-06-23 16:03:42 -07001011//===----------------------------------------------------------------------===//
1012// CFG Function printing
1013//===----------------------------------------------------------------------===//
1014
1015namespace {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -07001016class CFGFunctionPrinter : public FunctionPrinter {
Chris Lattner4c95a502018-06-23 16:03:42 -07001017public:
Chris Lattner4fd59b02018-07-20 09:35:47 -07001018 CFGFunctionPrinter(const CFGFunction *function, const ModulePrinter &other);
Chris Lattner4c95a502018-06-23 16:03:42 -07001019
1020 const CFGFunction *getFunction() const { return function; }
1021
1022 void print();
1023 void print(const BasicBlock *block);
Chris Lattnered65a732018-06-28 20:45:33 -07001024
1025 void print(const Instruction *inst);
1026 void print(const OperationInst *inst);
1027 void print(const ReturnInst *inst);
1028 void print(const BranchInst *inst);
James Molloy4f788372018-07-24 15:01:27 -07001029 void print(const CondBranchInst *inst);
Chris Lattner4c95a502018-06-23 16:03:42 -07001030
1031 unsigned getBBID(const BasicBlock *block) {
1032 auto it = basicBlockIDs.find(block);
1033 assert(it != basicBlockIDs.end() && "Block not in this function?");
1034 return it->second;
1035 }
1036
1037private:
1038 const CFGFunction *function;
MLIR Team54b55a22018-07-18 10:16:05 -07001039 DenseMap<const BasicBlock *, unsigned> basicBlockIDs;
Chris Lattnerf8cce872018-07-20 09:28:54 -07001040
Chris Lattner4fd59b02018-07-20 09:35:47 -07001041 void numberValuesInBlock(const BasicBlock *block);
Chris Lattner4c95a502018-06-23 16:03:42 -07001042};
James Molloy87d81022018-07-23 11:44:40 -07001043} // end anonymous namespace
Chris Lattner4c95a502018-06-23 16:03:42 -07001044
Chris Lattner4fd59b02018-07-20 09:35:47 -07001045CFGFunctionPrinter::CFGFunctionPrinter(const CFGFunction *function,
1046 const ModulePrinter &other)
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -07001047 : FunctionPrinter(other), function(function) {
Chris Lattner4c95a502018-06-23 16:03:42 -07001048 // Each basic block gets a unique ID per function.
1049 unsigned blockID = 0;
Chris Lattnerf8cce872018-07-20 09:28:54 -07001050 for (auto &block : *function) {
1051 basicBlockIDs[&block] = blockID++;
Chris Lattner4fd59b02018-07-20 09:35:47 -07001052 numberValuesInBlock(&block);
Chris Lattnerf8cce872018-07-20 09:28:54 -07001053 }
1054}
1055
1056/// Number all of the SSA values in the specified basic block.
Chris Lattner4fd59b02018-07-20 09:35:47 -07001057void CFGFunctionPrinter::numberValuesInBlock(const BasicBlock *block) {
James Molloy61a656c2018-07-22 15:45:24 -07001058 for (auto *arg : block->getArguments()) {
1059 numberValueID(arg);
1060 }
Chris Lattnerf8cce872018-07-20 09:28:54 -07001061 for (auto &op : *block) {
1062 // We number instruction that have results, and we only number the first
1063 // result.
1064 if (op.getNumResults() != 0)
1065 numberValueID(op.getResult(0));
1066 }
1067
1068 // Terminators do not define values.
Chris Lattner4c95a502018-06-23 16:03:42 -07001069}
1070
Chris Lattner4fd59b02018-07-20 09:35:47 -07001071void CFGFunctionPrinter::print() {
Chris Lattner4c95a502018-06-23 16:03:42 -07001072 os << "cfgfunc ";
Chris Lattner4fd59b02018-07-20 09:35:47 -07001073 printFunctionSignature(getFunction());
Chris Lattner4c95a502018-06-23 16:03:42 -07001074 os << " {\n";
1075
James Molloy87d81022018-07-23 11:44:40 -07001076 for (auto &block : *function)
1077 print(&block);
Chris Lattner4c95a502018-06-23 16:03:42 -07001078 os << "}\n\n";
1079}
1080
Chris Lattner4fd59b02018-07-20 09:35:47 -07001081void CFGFunctionPrinter::print(const BasicBlock *block) {
James Molloy61a656c2018-07-22 15:45:24 -07001082 os << "bb" << getBBID(block);
Chris Lattner4c95a502018-06-23 16:03:42 -07001083
James Molloy61a656c2018-07-22 15:45:24 -07001084 if (!block->args_empty()) {
1085 os << '(';
1086 interleaveComma(block->getArguments(), [&](const BBArgument *arg) {
1087 printValueID(arg);
1088 os << ": ";
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -07001089 printType(arg->getType());
James Molloy61a656c2018-07-22 15:45:24 -07001090 });
1091 os << ')';
1092 }
Chris Lattner25ce3062018-07-27 11:10:12 -07001093 os << ':';
1094
1095 // Print out some context information about the predecessors of this block.
1096 if (!block->getFunction()) {
1097 os << "\t// block is not in a function!";
1098 } else if (block->hasNoPredecessors()) {
1099 // Don't print "no predecessors" for the entry block.
1100 if (block != &block->getFunction()->front())
1101 os << "\t// no predecessors";
1102 } else if (auto *pred = block->getSinglePredecessor()) {
1103 os << "\t// pred: bb" << getBBID(pred);
1104 } else {
1105 // We want to print the predecessors in increasing numeric order, not in
1106 // whatever order the use-list is in, so gather and sort them.
1107 SmallVector<unsigned, 4> predIDs;
1108 for (auto *pred : block->getPredecessors())
1109 predIDs.push_back(getBBID(pred));
1110 llvm::array_pod_sort(predIDs.begin(), predIDs.end());
1111
1112 os << "\t// " << predIDs.size() << " preds: ";
1113
1114 interleaveComma(predIDs, [&](unsigned predID) { os << "bb" << predID; });
1115 }
1116 os << '\n';
James Molloy61a656c2018-07-22 15:45:24 -07001117
Jacques Pienaarb020c542018-07-15 00:06:54 -07001118 for (auto &inst : block->getOperations()) {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001119 os << " ";
Chris Lattner3a467cc2018-07-01 20:28:00 -07001120 print(&inst);
James Molloy61a656c2018-07-22 15:45:24 -07001121 os << '\n';
Jacques Pienaarb020c542018-07-15 00:06:54 -07001122 }
Chris Lattner4c95a502018-06-23 16:03:42 -07001123
James Molloy6e4519b2018-08-03 03:51:38 -07001124 os << " ";
Chris Lattner4c95a502018-06-23 16:03:42 -07001125 print(block->getTerminator());
James Molloy61a656c2018-07-22 15:45:24 -07001126 os << '\n';
Chris Lattner4c95a502018-06-23 16:03:42 -07001127}
1128
Chris Lattner4fd59b02018-07-20 09:35:47 -07001129void CFGFunctionPrinter::print(const Instruction *inst) {
Chris Lattner4c95a502018-06-23 16:03:42 -07001130 switch (inst->getKind()) {
Chris Lattnered65a732018-06-28 20:45:33 -07001131 case Instruction::Kind::Operation:
1132 return print(cast<OperationInst>(inst));
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001133 case TerminatorInst::Kind::Branch:
Chris Lattnered65a732018-06-28 20:45:33 -07001134 return print(cast<BranchInst>(inst));
James Molloy4f788372018-07-24 15:01:27 -07001135 case TerminatorInst::Kind::CondBranch:
1136 return print(cast<CondBranchInst>(inst));
Chris Lattner4c95a502018-06-23 16:03:42 -07001137 case TerminatorInst::Kind::Return:
Chris Lattnered65a732018-06-28 20:45:33 -07001138 return print(cast<ReturnInst>(inst));
Chris Lattner4c95a502018-06-23 16:03:42 -07001139 }
1140}
1141
Chris Lattner4fd59b02018-07-20 09:35:47 -07001142void CFGFunctionPrinter::print(const OperationInst *inst) {
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -07001143 printOperation(inst);
Chris Lattner3b2ef762018-07-18 15:31:25 -07001144}
Chris Lattner1604e472018-07-23 08:42:19 -07001145
Chris Lattner4fd59b02018-07-20 09:35:47 -07001146void CFGFunctionPrinter::print(const BranchInst *inst) {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001147 os << "br bb" << getBBID(inst->getDest());
Chris Lattner1604e472018-07-23 08:42:19 -07001148
1149 if (inst->getNumOperands() != 0) {
1150 os << '(';
Chris Lattner0497c4b2018-08-15 09:09:54 -07001151 interleaveComma(inst->getOperands(),
1152 [&](const CFGValue *operand) { printValueID(operand); });
Chris Lattner1604e472018-07-23 08:42:19 -07001153 os << ") : ";
Chris Lattner0497c4b2018-08-15 09:09:54 -07001154 interleaveComma(inst->getOperands(), [&](const CFGValue *operand) {
1155 printType(operand->getType());
Chris Lattner1604e472018-07-23 08:42:19 -07001156 });
1157 }
Chris Lattnered65a732018-06-28 20:45:33 -07001158}
Chris Lattner1604e472018-07-23 08:42:19 -07001159
James Molloy4f788372018-07-24 15:01:27 -07001160void CFGFunctionPrinter::print(const CondBranchInst *inst) {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001161 os << "cond_br ";
James Molloy4f788372018-07-24 15:01:27 -07001162 printValueID(inst->getCondition());
1163
1164 os << ", bb" << getBBID(inst->getTrueDest());
1165 if (inst->getNumTrueOperands() != 0) {
1166 os << '(';
1167 interleaveComma(inst->getTrueOperands(),
1168 [&](const CFGValue *operand) { printValueID(operand); });
1169 os << " : ";
1170 interleaveComma(inst->getTrueOperands(), [&](const CFGValue *operand) {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -07001171 printType(operand->getType());
James Molloy4f788372018-07-24 15:01:27 -07001172 });
1173 os << ")";
1174 }
1175
1176 os << ", bb" << getBBID(inst->getFalseDest());
1177 if (inst->getNumFalseOperands() != 0) {
1178 os << '(';
1179 interleaveComma(inst->getFalseOperands(),
1180 [&](const CFGValue *operand) { printValueID(operand); });
1181 os << " : ";
1182 interleaveComma(inst->getFalseOperands(), [&](const CFGValue *operand) {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -07001183 printType(operand->getType());
James Molloy4f788372018-07-24 15:01:27 -07001184 });
1185 os << ")";
1186 }
1187}
1188
Chris Lattner40746442018-07-21 14:32:09 -07001189void CFGFunctionPrinter::print(const ReturnInst *inst) {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001190 os << "return";
Chris Lattner40746442018-07-21 14:32:09 -07001191
James Molloy6bf60c22018-08-02 08:28:20 -07001192 if (inst->getNumOperands() == 0)
1193 return;
Chris Lattner40746442018-07-21 14:32:09 -07001194
James Molloy6bf60c22018-08-02 08:28:20 -07001195 os << ' ';
James Molloy4f788372018-07-24 15:01:27 -07001196 interleaveComma(inst->getOperands(),
1197 [&](const CFGValue *operand) { printValueID(operand); });
1198 os << " : ";
Chris Lattnerac591f12018-07-22 21:02:26 -07001199 interleaveComma(inst->getOperands(), [&](const CFGValue *operand) {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -07001200 printType(operand->getType());
Chris Lattner40746442018-07-21 14:32:09 -07001201 });
1202}
MLIR Team54b55a22018-07-18 10:16:05 -07001203
Chris Lattner4fd59b02018-07-20 09:35:47 -07001204void ModulePrinter::print(const CFGFunction *fn) {
1205 CFGFunctionPrinter(fn, *this).print();
Chris Lattnered65a732018-06-28 20:45:33 -07001206}
1207
Chris Lattner4c95a502018-06-23 16:03:42 -07001208//===----------------------------------------------------------------------===//
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001209// ML Function printing
Chris Lattner4c95a502018-06-23 16:03:42 -07001210//===----------------------------------------------------------------------===//
1211
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001212namespace {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -07001213class MLFunctionPrinter : public FunctionPrinter {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001214public:
Chris Lattner4fd59b02018-07-20 09:35:47 -07001215 MLFunctionPrinter(const MLFunction *function, const ModulePrinter &other);
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001216
1217 const MLFunction *getFunction() const { return function; }
1218
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001219 // Prints ML function
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001220 void print();
1221
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07001222 // Prints ML function signature
1223 void printFunctionSignature();
1224
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001225 // Methods to print ML function statements
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001226 void print(const Statement *stmt);
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -07001227 void print(const OperationStmt *stmt);
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001228 void print(const ForStmt *stmt);
1229 void print(const IfStmt *stmt);
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001230 void print(const StmtBlock *block);
1231
1232 // Number of spaces used for indenting nested statements
1233 const static unsigned indentWidth = 2;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001234
1235private:
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001236 void numberValues();
1237
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001238 const MLFunction *function;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001239 int numSpaces;
1240};
James Molloy87d81022018-07-23 11:44:40 -07001241} // end anonymous namespace
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001242
Chris Lattner4fd59b02018-07-20 09:35:47 -07001243MLFunctionPrinter::MLFunctionPrinter(const MLFunction *function,
1244 const ModulePrinter &other)
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001245 : FunctionPrinter(other), function(function), numSpaces(0) {
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07001246 assert(function && "Cannot print nullptr function");
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001247 numberValues();
1248}
1249
1250/// Number all of the SSA values in this ML function.
1251void MLFunctionPrinter::numberValues() {
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07001252 // Numbers ML function arguments
1253 for (auto *arg : function->getArguments())
1254 numberValueID(arg);
1255
1256 // Walks ML function statements and numbers for statements and
1257 // the first result of the operation statements.
Uday Bondhugula081d9e72018-07-27 10:58:14 -07001258 struct NumberValuesPass : public StmtWalker<NumberValuesPass> {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001259 NumberValuesPass(MLFunctionPrinter *printer) : printer(printer) {}
1260 void visitOperationStmt(OperationStmt *stmt) {
1261 if (stmt->getNumResults() != 0)
1262 printer->numberValueID(stmt->getResult(0));
1263 }
Tatiana Shpeismanc9c4b342018-07-31 07:40:14 -07001264 void visitForStmt(ForStmt *stmt) { printer->numberValueID(stmt); }
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001265 MLFunctionPrinter *printer;
1266 };
1267
1268 NumberValuesPass pass(this);
Chris Lattner0497c4b2018-08-15 09:09:54 -07001269 // TODO: it'd be cleaner to have constant visitor instead of using const_cast.
Uday Bondhugula081d9e72018-07-27 10:58:14 -07001270 pass.walk(const_cast<MLFunction *>(function));
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001271}
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001272
Chris Lattner4fd59b02018-07-20 09:35:47 -07001273void MLFunctionPrinter::print() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001274 os << "mlfunc ";
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07001275 printFunctionSignature();
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001276 os << " {\n";
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001277 print(function);
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001278 os << "}\n\n";
1279}
1280
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07001281void MLFunctionPrinter::printFunctionSignature() {
1282 auto type = function->getType();
1283
1284 os << "@" << function->getName() << '(';
1285
1286 for (unsigned i = 0, e = function->getNumArguments(); i != e; ++i) {
1287 if (i > 0)
1288 os << ", ";
1289 auto *arg = function->getArgument(i);
1290 printOperand(arg);
1291 os << " : ";
1292 printType(arg->getType());
1293 }
1294 os << ")";
1295 printFunctionResultType(type);
1296}
1297
Chris Lattner4fd59b02018-07-20 09:35:47 -07001298void MLFunctionPrinter::print(const StmtBlock *block) {
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001299 numSpaces += indentWidth;
Jacques Pienaarb020c542018-07-15 00:06:54 -07001300 for (auto &stmt : block->getStatements()) {
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001301 print(&stmt);
Jacques Pienaarb020c542018-07-15 00:06:54 -07001302 os << "\n";
1303 }
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001304 numSpaces -= indentWidth;
1305}
1306
Chris Lattner4fd59b02018-07-20 09:35:47 -07001307void MLFunctionPrinter::print(const Statement *stmt) {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001308 switch (stmt->getKind()) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001309 case Statement::Kind::Operation:
1310 return print(cast<OperationStmt>(stmt));
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001311 case Statement::Kind::For:
1312 return print(cast<ForStmt>(stmt));
1313 case Statement::Kind::If:
1314 return print(cast<IfStmt>(stmt));
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001315 }
1316}
1317
Chris Lattner4fd59b02018-07-20 09:35:47 -07001318void MLFunctionPrinter::print(const OperationStmt *stmt) {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001319 os.indent(numSpaces);
Chris Lattner4fd59b02018-07-20 09:35:47 -07001320 printOperation(stmt);
1321}
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001322
Chris Lattner4fd59b02018-07-20 09:35:47 -07001323void MLFunctionPrinter::print(const ForStmt *stmt) {
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07001324 os.indent(numSpaces) << "for ";
Tatiana Shpeismanc9c4b342018-07-31 07:40:14 -07001325 printOperand(stmt);
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07001326 os << " = " << *stmt->getLowerBound();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001327 os << " to " << *stmt->getUpperBound();
Uday Bondhugula67701712018-08-21 16:01:23 -07001328 if (stmt->getStep() != 1)
1329 os << " step " << stmt->getStep();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001330
1331 os << " {\n";
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001332 print(static_cast<const StmtBlock *>(stmt));
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001333 os.indent(numSpaces) << "}";
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001334}
1335
Chris Lattner4fd59b02018-07-20 09:35:47 -07001336void MLFunctionPrinter::print(const IfStmt *stmt) {
Uday Bondhugulabc535622018-08-07 14:24:38 -07001337 os.indent(numSpaces) << "if (";
1338 printIntegerSetReference(stmt->getCondition());
1339 os << ") {\n";
Chris Lattnere787b322018-08-08 11:14:57 -07001340 print(stmt->getThen());
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001341 os.indent(numSpaces) << "}";
Chris Lattnere787b322018-08-08 11:14:57 -07001342 if (stmt->hasElse()) {
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001343 os << " else {\n";
Chris Lattnere787b322018-08-08 11:14:57 -07001344 print(stmt->getElse());
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001345 os.indent(numSpaces) << "}";
1346 }
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001347}
1348
Chris Lattner4fd59b02018-07-20 09:35:47 -07001349void ModulePrinter::print(const MLFunction *fn) {
1350 MLFunctionPrinter(fn, *this).print();
MLIR Team4718bc92018-07-17 16:56:54 -07001351}
1352
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001353//===----------------------------------------------------------------------===//
1354// print and dump methods
1355//===----------------------------------------------------------------------===//
Chris Lattnered65a732018-06-28 20:45:33 -07001356
MLIR Teamb61885d2018-07-18 16:29:21 -07001357void Attribute::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -07001358 ModuleState state(/*no context is known*/ nullptr);
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -07001359 ModulePrinter(os, state).printAttribute(this);
MLIR Teamb61885d2018-07-18 16:29:21 -07001360}
1361
James Molloy87d81022018-07-23 11:44:40 -07001362void Attribute::dump() const { print(llvm::errs()); }
MLIR Teamb61885d2018-07-18 16:29:21 -07001363
MLIR Team4718bc92018-07-17 16:56:54 -07001364void Type::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -07001365 ModuleState state(getContext());
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -07001366 ModulePrinter(os, state).printType(this);
MLIR Team4718bc92018-07-17 16:56:54 -07001367}
1368
MLIR Team54b55a22018-07-18 10:16:05 -07001369void Type::dump() const { print(llvm::errs()); }
MLIR Team4718bc92018-07-17 16:56:54 -07001370
MLIR Team718c82f2018-07-16 09:45:22 -07001371void AffineMap::dump() const {
1372 print(llvm::errs());
1373 llvm::errs() << "\n";
1374}
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001375
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001376void AffineExpr::dump() const {
1377 print(llvm::errs());
1378 llvm::errs() << "\n";
1379}
1380
Uday Bondhugulabc535622018-08-07 14:24:38 -07001381void IntegerSet::dump() const {
1382 print(llvm::errs());
1383 llvm::errs() << "\n";
1384}
1385
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001386void AffineExpr::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -07001387 ModuleState state(/*no context is known*/ nullptr);
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -07001388 ModulePrinter(os, state).printAffineExpr(this);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001389}
1390
1391void AffineMap::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -07001392 ModuleState state(/*no context is known*/ nullptr);
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -07001393 ModulePrinter(os, state).printAffineMap(this);
Chris Lattner4fd59b02018-07-20 09:35:47 -07001394}
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001395
Uday Bondhugulabc535622018-08-07 14:24:38 -07001396void IntegerSet::print(raw_ostream &os) const {
1397 ModuleState state(/*no context is known*/ nullptr);
1398 ModulePrinter(os, state).printIntegerSet(this);
1399}
1400
Chris Lattner384da8c2018-08-02 17:16:58 -07001401void SSAValue::print(raw_ostream &os) const {
1402 switch (getKind()) {
1403 case SSAValueKind::BBArgument:
1404 // TODO: Improve this.
1405 os << "<bb argument>\n";
1406 return;
1407 case SSAValueKind::InstResult:
1408 return getDefiningInst()->print(os);
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07001409 case SSAValueKind::MLFuncArgument:
Chris Lattner384da8c2018-08-02 17:16:58 -07001410 // TODO: Improve this.
1411 os << "<function argument>\n";
1412 return;
1413 case SSAValueKind::StmtResult:
1414 return getDefiningStmt()->print(os);
1415 case SSAValueKind::ForStmt:
1416 return cast<ForStmt>(this)->print(os);
1417 }
1418}
1419
1420void SSAValue::dump() const { print(llvm::errs()); }
1421
Chris Lattner4fd59b02018-07-20 09:35:47 -07001422void Instruction::print(raw_ostream &os) const {
Tatiana Shpeismanc335d182018-08-03 11:12:34 -07001423 if (!getFunction()) {
1424 os << "<<UNLINKED INSTRUCTION>>\n";
1425 return;
1426 }
Chris Lattner4fd59b02018-07-20 09:35:47 -07001427 ModuleState state(getFunction()->getContext());
1428 ModulePrinter modulePrinter(os, state);
1429 CFGFunctionPrinter(getFunction(), modulePrinter).print(this);
1430}
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001431
Chris Lattner4fd59b02018-07-20 09:35:47 -07001432void Instruction::dump() const {
1433 print(llvm::errs());
1434 llvm::errs() << "\n";
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001435}
1436
Chris Lattner4c95a502018-06-23 16:03:42 -07001437void BasicBlock::print(raw_ostream &os) const {
Tatiana Shpeismanc335d182018-08-03 11:12:34 -07001438 if (!getFunction()) {
1439 os << "<<UNLINKED BLOCK>>\n";
1440 return;
1441 }
Chris Lattner4fd59b02018-07-20 09:35:47 -07001442 ModuleState state(getFunction()->getContext());
1443 ModulePrinter modulePrinter(os, state);
1444 CFGFunctionPrinter(getFunction(), modulePrinter).print(this);
Chris Lattner4c95a502018-06-23 16:03:42 -07001445}
1446
MLIR Team54b55a22018-07-18 10:16:05 -07001447void BasicBlock::dump() const { print(llvm::errs()); }
Chris Lattner4c95a502018-06-23 16:03:42 -07001448
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001449void Statement::print(raw_ostream &os) const {
Tatiana Shpeismand880b352018-07-31 23:14:16 -07001450 MLFunction *function = findFunction();
Tatiana Shpeismanc335d182018-08-03 11:12:34 -07001451 if (!function) {
1452 os << "<<UNLINKED STATEMENT>>\n";
1453 return;
1454 }
1455
Tatiana Shpeismand880b352018-07-31 23:14:16 -07001456 ModuleState state(function->getContext());
Chris Lattner4fd59b02018-07-20 09:35:47 -07001457 ModulePrinter modulePrinter(os, state);
Tatiana Shpeismand880b352018-07-31 23:14:16 -07001458 MLFunctionPrinter(function, modulePrinter).print(this);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001459}
1460
MLIR Team54b55a22018-07-18 10:16:05 -07001461void Statement::dump() const { print(llvm::errs()); }
Jacques Pienaarb020c542018-07-15 00:06:54 -07001462
Chris Lattnere787b322018-08-08 11:14:57 -07001463void StmtBlock::printBlock(raw_ostream &os) const {
Uday Bondhugula84b80952018-08-03 13:22:26 -07001464 MLFunction *function = findFunction();
1465 ModuleState state(function->getContext());
1466 ModulePrinter modulePrinter(os, state);
1467 MLFunctionPrinter(function, modulePrinter).print(this);
1468}
1469
Chris Lattnere787b322018-08-08 11:14:57 -07001470void StmtBlock::dumpBlock() const { printBlock(llvm::errs()); }
Uday Bondhugula84b80952018-08-03 13:22:26 -07001471
Chris Lattner4c95a502018-06-23 16:03:42 -07001472void Function::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -07001473 ModuleState state(getContext());
1474 ModulePrinter(os, state).print(this);
Chris Lattner4c95a502018-06-23 16:03:42 -07001475}
1476
MLIR Team54b55a22018-07-18 10:16:05 -07001477void Function::dump() const { print(llvm::errs()); }
1478
Chris Lattner4c95a502018-06-23 16:03:42 -07001479void Module::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -07001480 ModuleState state(getContext());
1481 state.initialize(this);
1482 ModulePrinter(os, state).print(this);
Chris Lattner4c95a502018-06-23 16:03:42 -07001483}
1484
MLIR Team54b55a22018-07-18 10:16:05 -07001485void Module::dump() const { print(llvm::errs()); }