blob: 9e4dd65b912403d98f3604770cc0997f948e27c5 [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 Lattnerdd0c2ca2018-07-24 16:07:22 -0700250 void printAttribute(const Attribute *attr);
251 void printType(const Type *type);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700252 void print(const Function *fn);
253 void print(const ExtFunction *fn);
254 void print(const CFGFunction *fn);
255 void print(const MLFunction *fn);
256
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700257 void printAffineMap(const AffineMap *map);
258 void printAffineExpr(const AffineExpr *expr);
Uday Bondhugulabc535622018-08-07 14:24:38 -0700259 void printAffineConstraint(const AffineExpr *expr, bool isEq);
260 void printIntegerSet(const IntegerSet *set);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700261
262protected:
263 raw_ostream &os;
264 ModuleState &state;
265
266 void printFunctionSignature(const Function *fn);
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -0700267 void printFunctionResultType(const FunctionType *type);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700268 void printAffineMapId(int affineMapId) const;
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700269 void printAffineMapReference(const AffineMap *affineMap);
Uday Bondhugulabc535622018-08-07 14:24:38 -0700270 void printIntegerSetId(int integerSetId) const;
271 void printIntegerSetReference(const IntegerSet *integerSet);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700272
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700273 /// This enum is used to represent the binding stength of the enclosing
274 /// context that an AffineExpr is being printed in, so we can intelligently
275 /// produce parens.
276 enum class BindingStrength {
277 Weak, // + and -
278 Strong, // All other binary operators.
279 };
280 void printAffineExprInternal(const AffineExpr *expr,
281 BindingStrength enclosingTightness);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700282};
283} // end anonymous namespace
284
MLIR Team4718bc92018-07-17 16:56:54 -0700285// Prints function with initialized module state.
Chris Lattner4fd59b02018-07-20 09:35:47 -0700286void ModulePrinter::print(const Function *fn) {
MLIR Team4718bc92018-07-17 16:56:54 -0700287 switch (fn->getKind()) {
MLIR Team54b55a22018-07-18 10:16:05 -0700288 case Function::Kind::ExtFunc:
289 return print(cast<ExtFunction>(fn));
290 case Function::Kind::CFGFunc:
291 return print(cast<CFGFunction>(fn));
292 case Function::Kind::MLFunc:
293 return print(cast<MLFunction>(fn));
MLIR Team4718bc92018-07-17 16:56:54 -0700294 }
295}
296
297// Prints affine map identifier.
Chris Lattner4fd59b02018-07-20 09:35:47 -0700298void ModulePrinter::printAffineMapId(int affineMapId) const {
MLIR Team4718bc92018-07-17 16:56:54 -0700299 os << "#map" << affineMapId;
300}
301
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700302void ModulePrinter::printAffineMapReference(const AffineMap *affineMap) {
Chris Lattner4fd59b02018-07-20 09:35:47 -0700303 int mapId = state.getAffineMapId(affineMap);
MLIR Teamb61885d2018-07-18 16:29:21 -0700304 if (mapId >= 0) {
305 // Map will be printed at top of module so print reference to its id.
306 printAffineMapId(mapId);
307 } else {
308 // Map not in module state so print inline.
309 affineMap->print(os);
310 }
311}
312
Uday Bondhugulabc535622018-08-07 14:24:38 -0700313// Prints integer set identifier.
314void ModulePrinter::printIntegerSetId(int integerSetId) const {
315 os << "@@set" << integerSetId;
316}
317
318void ModulePrinter::printIntegerSetReference(const IntegerSet *integerSet) {
319 int setId;
320 if ((setId = state.getIntegerSetId(integerSet)) >= 0) {
321 // The set will be printed at top of module; so print reference to its id.
322 printIntegerSetId(setId);
323 } else {
324 // Set not in module state so print inline.
325 integerSet->print(os);
326 }
327}
328
Chris Lattner4fd59b02018-07-20 09:35:47 -0700329void ModulePrinter::print(const Module *module) {
James Molloyc4666722018-07-24 09:48:31 -0700330 for (const auto &map : state.getAffineMapIds()) {
331 printAffineMapId(state.getAffineMapId(map));
MLIR Team4718bc92018-07-17 16:56:54 -0700332 os << " = ";
James Molloyc4666722018-07-24 09:48:31 -0700333 map->print(os);
MLIR Team4718bc92018-07-17 16:56:54 -0700334 os << '\n';
335 }
Uday Bondhugulabc535622018-08-07 14:24:38 -0700336 for (const auto &set : state.getIntegerSetIds()) {
337 printIntegerSetId(state.getIntegerSetId(set));
338 os << " = ";
339 set->print(os);
340 os << '\n';
341 }
Chris Lattnera8e47672018-07-25 14:08:16 -0700342 for (auto const &fn : *module)
343 print(&fn);
MLIR Team4718bc92018-07-17 16:56:54 -0700344}
345
Chris Lattner0497c4b2018-08-15 09:09:54 -0700346/// Print a floating point value in a way that the parser will be able to
347/// round-trip losslessly.
348static void printFloatValue(double value, raw_ostream &os) {
349 APFloat apValue(value);
350
351 // We would like to output the FP constant value in exponential notation,
352 // but we cannot do this if doing so will lose precision. Check here to
353 // make sure that we only output it in exponential format if we can parse
354 // the value back and get the same value.
355 bool isInf = apValue.isInfinity();
356 bool isNaN = apValue.isNaN();
357 if (!isInf && !isNaN) {
358 SmallString<128> strValue;
359 apValue.toString(strValue, 6, 0, false);
360
361 // Check to make sure that the stringized number is not some string like
362 // "Inf" or NaN, that atof will accept, but the lexer will not. Check
363 // that the string matches the "[-+]?[0-9]" regex.
364 assert(((strValue[0] >= '0' && strValue[0] <= '9') ||
365 ((strValue[0] == '-' || strValue[0] == '+') &&
366 (strValue[1] >= '0' && strValue[1] <= '9'))) &&
367 "[-+]?[0-9] regex does not match!");
368 // Reparse stringized version!
369 if (APFloat(APFloat::IEEEdouble(), strValue).convertToDouble() == value) {
370 os << strValue;
371 return;
372 }
373 }
374
375 // Otherwise, print it in a hexadecimal form. Convert it to an integer so we
376 // can print it out using integer math.
377 union {
378 double doubleValue;
379 uint64_t integerValue;
380 };
381 doubleValue = value;
382 os << "0x";
383 // Print out 16 nibbles worth of hex digit.
384 for (unsigned i = 0; i != 16; ++i) {
385 os << llvm::hexdigit(integerValue >> 60);
386 integerValue <<= 4;
387 }
388}
389
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700390void ModulePrinter::printAttribute(const Attribute *attr) {
MLIR Teamb61885d2018-07-18 16:29:21 -0700391 switch (attr->getKind()) {
392 case Attribute::Kind::Bool:
393 os << (cast<BoolAttr>(attr)->getValue() ? "true" : "false");
394 break;
395 case Attribute::Kind::Integer:
396 os << cast<IntegerAttr>(attr)->getValue();
397 break;
398 case Attribute::Kind::Float:
Chris Lattner0497c4b2018-08-15 09:09:54 -0700399 printFloatValue(cast<FloatAttr>(attr)->getValue(), os);
MLIR Teamb61885d2018-07-18 16:29:21 -0700400 break;
401 case Attribute::Kind::String:
Chris Lattner0497c4b2018-08-15 09:09:54 -0700402 os << '"';
403 printEscapedString(cast<StringAttr>(attr)->getValue(), os);
404 os << '"';
MLIR Teamb61885d2018-07-18 16:29:21 -0700405 break;
Chris Lattner0497c4b2018-08-15 09:09:54 -0700406 case Attribute::Kind::Array:
MLIR Teamb61885d2018-07-18 16:29:21 -0700407 os << '[';
Chris Lattner0497c4b2018-08-15 09:09:54 -0700408 interleaveComma(cast<ArrayAttr>(attr)->getValue(),
409 [&](Attribute *attr) { printAttribute(attr); });
MLIR Teamb61885d2018-07-18 16:29:21 -0700410 os << ']';
411 break;
MLIR Teamb61885d2018-07-18 16:29:21 -0700412 case Attribute::Kind::AffineMap:
413 printAffineMapReference(cast<AffineMapAttr>(attr)->getValue());
414 break;
James Molloyf0d2f442018-08-03 01:54:46 -0700415 case Attribute::Kind::Type:
416 printType(cast<TypeAttr>(attr)->getValue());
417 break;
MLIR Teamb61885d2018-07-18 16:29:21 -0700418 }
419}
420
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700421void ModulePrinter::printType(const Type *type) {
MLIR Team4718bc92018-07-17 16:56:54 -0700422 switch (type->getKind()) {
MLIR Team54b55a22018-07-18 10:16:05 -0700423 case Type::Kind::AffineInt:
424 os << "affineint";
425 return;
426 case Type::Kind::BF16:
427 os << "bf16";
428 return;
429 case Type::Kind::F16:
430 os << "f16";
431 return;
432 case Type::Kind::F32:
433 os << "f32";
434 return;
435 case Type::Kind::F64:
436 os << "f64";
437 return;
Jacques Pienaarc0d69302018-07-27 11:07:12 -0700438 case Type::Kind::TFControl:
439 os << "tf_control";
440 return;
James Molloy72b0cbe2018-08-01 12:55:27 -0700441 case Type::Kind::TFString:
442 os << "tf_string";
443 return;
MLIR Team4718bc92018-07-17 16:56:54 -0700444
445 case Type::Kind::Integer: {
446 auto *integer = cast<IntegerType>(type);
447 os << 'i' << integer->getWidth();
448 return;
449 }
450 case Type::Kind::Function: {
451 auto *func = cast<FunctionType>(type);
452 os << '(';
Chris Lattner413db6a2018-07-25 12:55:50 -0700453 interleaveComma(func->getInputs(), [&](Type *type) { printType(type); });
MLIR Team4718bc92018-07-17 16:56:54 -0700454 os << ") -> ";
455 auto results = func->getResults();
456 if (results.size() == 1)
457 os << *results[0];
458 else {
459 os << '(';
Chris Lattner413db6a2018-07-25 12:55:50 -0700460 interleaveComma(results, [&](Type *type) { printType(type); });
MLIR Team4718bc92018-07-17 16:56:54 -0700461 os << ')';
462 }
463 return;
464 }
465 case Type::Kind::Vector: {
466 auto *v = cast<VectorType>(type);
467 os << "vector<";
James Molloy87d81022018-07-23 11:44:40 -0700468 for (auto dim : v->getShape())
469 os << dim << 'x';
MLIR Team4718bc92018-07-17 16:56:54 -0700470 os << *v->getElementType() << '>';
471 return;
472 }
473 case Type::Kind::RankedTensor: {
474 auto *v = cast<RankedTensorType>(type);
475 os << "tensor<";
476 for (auto dim : v->getShape()) {
477 if (dim < 0)
478 os << '?';
479 else
480 os << dim;
481 os << 'x';
482 }
483 os << *v->getElementType() << '>';
484 return;
485 }
486 case Type::Kind::UnrankedTensor: {
487 auto *v = cast<UnrankedTensorType>(type);
Chris Lattner413db6a2018-07-25 12:55:50 -0700488 os << "tensor<??";
489 printType(v->getElementType());
490 os << '>';
MLIR Team4718bc92018-07-17 16:56:54 -0700491 return;
492 }
493 case Type::Kind::MemRef: {
494 auto *v = cast<MemRefType>(type);
495 os << "memref<";
496 for (auto dim : v->getShape()) {
497 if (dim < 0)
498 os << '?';
499 else
500 os << dim;
501 os << 'x';
502 }
Chris Lattner413db6a2018-07-25 12:55:50 -0700503 printType(v->getElementType());
MLIR Team4718bc92018-07-17 16:56:54 -0700504 for (auto map : v->getAffineMaps()) {
505 os << ", ";
MLIR Teamb61885d2018-07-18 16:29:21 -0700506 printAffineMapReference(map);
MLIR Team4718bc92018-07-17 16:56:54 -0700507 }
Chris Lattner413db6a2018-07-25 12:55:50 -0700508 // Only print the memory space if it is the non-default one.
509 if (v->getMemorySpace())
510 os << ", " << v->getMemorySpace();
MLIR Team4718bc92018-07-17 16:56:54 -0700511 os << '>';
512 return;
513 }
514 }
515}
516
517//===----------------------------------------------------------------------===//
Chris Lattner4fd59b02018-07-20 09:35:47 -0700518// Affine expressions and maps
519//===----------------------------------------------------------------------===//
520
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700521void ModulePrinter::printAffineExpr(const AffineExpr *expr) {
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700522 printAffineExprInternal(expr, BindingStrength::Weak);
523}
524
525void ModulePrinter::printAffineExprInternal(
526 const AffineExpr *expr, BindingStrength enclosingTightness) {
527 const char *binopSpelling = nullptr;
Chris Lattner4fd59b02018-07-20 09:35:47 -0700528 switch (expr->getKind()) {
529 case AffineExpr::Kind::SymbolId:
530 os << 's' << cast<AffineSymbolExpr>(expr)->getPosition();
531 return;
532 case AffineExpr::Kind::DimId:
533 os << 'd' << cast<AffineDimExpr>(expr)->getPosition();
534 return;
535 case AffineExpr::Kind::Constant:
536 os << cast<AffineConstantExpr>(expr)->getValue();
537 return;
538 case AffineExpr::Kind::Add:
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700539 binopSpelling = " + ";
540 break;
Chris Lattner4fd59b02018-07-20 09:35:47 -0700541 case AffineExpr::Kind::Mul:
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700542 binopSpelling = " * ";
543 break;
Chris Lattner4fd59b02018-07-20 09:35:47 -0700544 case AffineExpr::Kind::FloorDiv:
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700545 binopSpelling = " floordiv ";
546 break;
Chris Lattner4fd59b02018-07-20 09:35:47 -0700547 case AffineExpr::Kind::CeilDiv:
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700548 binopSpelling = " ceildiv ";
549 break;
Chris Lattner4fd59b02018-07-20 09:35:47 -0700550 case AffineExpr::Kind::Mod:
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700551 binopSpelling = " mod ";
552 break;
Chris Lattner4fd59b02018-07-20 09:35:47 -0700553 }
Chris Lattner4fd59b02018-07-20 09:35:47 -0700554
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700555 auto *binOp = cast<AffineBinaryOpExpr>(expr);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700556
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700557 // Handle tightly binding binary operators.
558 if (binOp->getKind() != AffineExpr::Kind::Add) {
559 if (enclosingTightness == BindingStrength::Strong)
560 os << '(';
561
562 printAffineExprInternal(binOp->getLHS(), BindingStrength::Strong);
563 os << binopSpelling;
564 printAffineExprInternal(binOp->getRHS(), BindingStrength::Strong);
565
566 if (enclosingTightness == BindingStrength::Strong)
567 os << ')';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700568 return;
569 }
570
571 // Print out special "pretty" forms for add.
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700572 if (enclosingTightness == BindingStrength::Strong)
573 os << '(';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700574
575 // Pretty print addition to a product that has a negative operand as a
576 // subtraction.
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700577 if (auto *rhs = dyn_cast<AffineBinaryOpExpr>(binOp->getRHS())) {
Chris Lattner4fd59b02018-07-20 09:35:47 -0700578 if (rhs->getKind() == AffineExpr::Kind::Mul) {
579 if (auto *rrhs = dyn_cast<AffineConstantExpr>(rhs->getRHS())) {
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700580 if (rrhs->getValue() == -1) {
581 printAffineExprInternal(binOp->getLHS(), BindingStrength::Weak);
582 os << " - ";
583 printAffineExprInternal(rhs->getLHS(), BindingStrength::Weak);
584
585 if (enclosingTightness == BindingStrength::Strong)
586 os << ')';
587 return;
588 }
589
590 if (rrhs->getValue() < -1) {
591 printAffineExprInternal(binOp->getLHS(), BindingStrength::Weak);
Uday Bondhugula970f5b82018-08-01 22:02:00 -0700592 os << " - ";
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700593 printAffineExprInternal(rhs->getLHS(), BindingStrength::Strong);
Uday Bondhugula970f5b82018-08-01 22:02:00 -0700594 os << " * " << -rrhs->getValue();
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700595 if (enclosingTightness == BindingStrength::Strong)
596 os << ')';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700597 return;
598 }
599 }
600 }
601 }
602
603 // Pretty print addition to a negative number as a subtraction.
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700604 if (auto *rhs = dyn_cast<AffineConstantExpr>(binOp->getRHS())) {
Chris Lattner4fd59b02018-07-20 09:35:47 -0700605 if (rhs->getValue() < 0) {
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700606 printAffineExprInternal(binOp->getLHS(), BindingStrength::Weak);
Uday Bondhugulabc535622018-08-07 14:24:38 -0700607 os << " - " << -rhs->getValue();
608 if (enclosingTightness == BindingStrength::Strong)
609 os << ')';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700610 return;
611 }
612 }
613
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700614 printAffineExprInternal(binOp->getLHS(), BindingStrength::Weak);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700615 os << " + ";
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700616 printAffineExprInternal(binOp->getRHS(), BindingStrength::Weak);
617
618 if (enclosingTightness == BindingStrength::Strong)
619 os << ')';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700620}
621
Uday Bondhugulabc535622018-08-07 14:24:38 -0700622void ModulePrinter::printAffineConstraint(const AffineExpr *expr, bool isEq) {
623 printAffineExprInternal(expr, BindingStrength::Weak);
624 isEq ? os << " == 0" : os << " >= 0";
625}
626
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700627void ModulePrinter::printAffineMap(const AffineMap *map) {
Chris Lattner4fd59b02018-07-20 09:35:47 -0700628 // Dimension identifiers.
629 os << '(';
Chris Lattnerdc3ba382018-07-29 14:13:03 -0700630 for (int i = 0; i < (int)map->getNumDims() - 1; ++i)
631 os << 'd' << i << ", ";
Chris Lattner4fd59b02018-07-20 09:35:47 -0700632 if (map->getNumDims() >= 1)
Chris Lattnerdc3ba382018-07-29 14:13:03 -0700633 os << 'd' << map->getNumDims() - 1;
634 os << ')';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700635
636 // Symbolic identifiers.
Chris Lattnerdc3ba382018-07-29 14:13:03 -0700637 if (map->getNumSymbols() != 0) {
638 os << '[';
639 for (unsigned i = 0; i < map->getNumSymbols() - 1; ++i)
640 os << 's' << i << ", ";
Chris Lattner4fd59b02018-07-20 09:35:47 -0700641 if (map->getNumSymbols() >= 1)
Chris Lattnerdc3ba382018-07-29 14:13:03 -0700642 os << 's' << map->getNumSymbols() - 1;
643 os << ']';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700644 }
645
646 // AffineMap should have at least one result.
647 assert(!map->getResults().empty());
648 // Result affine expressions.
649 os << " -> (";
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700650 interleaveComma(map->getResults(),
651 [&](AffineExpr *expr) { printAffineExpr(expr); });
Chris Lattnerdc3ba382018-07-29 14:13:03 -0700652 os << ')';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700653
654 if (!map->isBounded()) {
655 return;
656 }
657
658 // Print range sizes for bounded affine maps.
659 os << " size (";
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700660 interleaveComma(map->getRangeSizes(),
661 [&](AffineExpr *expr) { printAffineExpr(expr); });
Chris Lattnerdc3ba382018-07-29 14:13:03 -0700662 os << ')';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700663}
664
Uday Bondhugulabc535622018-08-07 14:24:38 -0700665void ModulePrinter::printIntegerSet(const IntegerSet *set) {
666 // Dimension identifiers.
667 os << '(';
668 for (unsigned i = 1; i < set->getNumDims(); ++i)
669 os << 'd' << i - 1 << ", ";
670 if (set->getNumDims() >= 1)
671 os << 'd' << set->getNumDims() - 1;
672 os << ')';
673
674 // Symbolic identifiers.
675 if (set->getNumSymbols() != 0) {
676 os << '[';
677 for (unsigned i = 0; i < set->getNumSymbols() - 1; ++i)
678 os << 's' << i << ", ";
679 if (set->getNumSymbols() >= 1)
680 os << 's' << set->getNumSymbols() - 1;
681 os << ']';
682 }
683
684 // Print constraints.
685 os << " : (";
686 auto numConstraints = set->getNumConstraints();
687 for (int i = 1; i < numConstraints; ++i) {
688 printAffineConstraint(set->getConstraint(i - 1), set->isEq(i - 1));
689 os << ", ";
690 }
691 if (numConstraints >= 1)
692 printAffineConstraint(set->getConstraint(numConstraints - 1),
693 set->isEq(numConstraints - 1));
694 os << ')';
695}
696
Chris Lattner4fd59b02018-07-20 09:35:47 -0700697//===----------------------------------------------------------------------===//
Chris Lattner4c95a502018-06-23 16:03:42 -0700698// Function printing
699//===----------------------------------------------------------------------===//
700
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -0700701void ModulePrinter::printFunctionResultType(const FunctionType *type) {
Chris Lattner4c95a502018-06-23 16:03:42 -0700702 switch (type->getResults().size()) {
MLIR Team54b55a22018-07-18 10:16:05 -0700703 case 0:
704 break;
Chris Lattner4c95a502018-06-23 16:03:42 -0700705 case 1:
MLIR Team4718bc92018-07-17 16:56:54 -0700706 os << " -> ";
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700707 printType(type->getResults()[0]);
Chris Lattner4c95a502018-06-23 16:03:42 -0700708 break;
709 default:
710 os << " -> (";
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700711 interleaveComma(type->getResults(),
712 [&](Type *eltType) { printType(eltType); });
Chris Lattner4c95a502018-06-23 16:03:42 -0700713 os << ')';
714 break;
715 }
716}
717
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -0700718void ModulePrinter::printFunctionSignature(const Function *fn) {
719 auto type = fn->getType();
720
721 os << "@" << fn->getName() << '(';
722 interleaveComma(type->getInputs(),
723 [&](Type *eltType) { printType(eltType); });
724 os << ')';
725
726 printFunctionResultType(type);
727}
728
Chris Lattner4fd59b02018-07-20 09:35:47 -0700729void ModulePrinter::print(const ExtFunction *fn) {
Chris Lattner4c95a502018-06-23 16:03:42 -0700730 os << "extfunc ";
Chris Lattner4fd59b02018-07-20 09:35:47 -0700731 printFunctionSignature(fn);
MLIR Team54b55a22018-07-18 10:16:05 -0700732 os << '\n';
Chris Lattner4c95a502018-06-23 16:03:42 -0700733}
734
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700735namespace {
736
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700737// FunctionPrinter contains common functionality for printing
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700738// CFG and ML functions.
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700739class FunctionPrinter : public ModulePrinter, private OpAsmPrinter {
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700740public:
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700741 FunctionPrinter(const ModulePrinter &other) : ModulePrinter(other) {}
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700742
743 void printOperation(const Operation *op);
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700744 void printDefaultOp(const Operation *op);
745
746 // Implement OpAsmPrinter.
747 raw_ostream &getStream() const { return os; }
748 void printType(const Type *type) { ModulePrinter::printType(type); }
749 void printAttribute(const Attribute *attr) {
750 ModulePrinter::printAttribute(attr);
751 }
752 void printAffineMap(const AffineMap *map) {
Chris Lattner3164ae62018-07-28 09:36:25 -0700753 return ModulePrinter::printAffineMapReference(map);
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700754 }
Uday Bondhugulabc535622018-08-07 14:24:38 -0700755 void printIntegerSet(const IntegerSet *set) {
756 return ModulePrinter::printIntegerSetReference(set);
757 }
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700758 void printAffineExpr(const AffineExpr *expr) {
759 return ModulePrinter::printAffineExpr(expr);
760 }
761
762 void printOperand(const SSAValue *value) { printValueID(value); }
Tatiana Shpeismanc335d182018-08-03 11:12:34 -0700763
Chris Lattner85cf26d2018-08-02 16:54:36 -0700764 void printOptionalAttrDict(ArrayRef<NamedAttribute> attrs,
765 ArrayRef<const char *> elidedAttrs = {}) override;
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700766
Chris Lattnerd4964212018-08-01 10:43:18 -0700767 enum { nameSentinel = ~0U };
768
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700769protected:
Chris Lattnerf8cce872018-07-20 09:28:54 -0700770 void numberValueID(const SSAValue *value) {
771 assert(!valueIDs.count(value) && "Value numbered multiple times");
Chris Lattnerd4964212018-08-01 10:43:18 -0700772
773 SmallString<32> specialNameBuffer;
774 llvm::raw_svector_ostream specialName(specialNameBuffer);
775
776 // Give constant integers special names.
777 if (auto *op = value->getDefiningOperation()) {
778 if (auto intOp = op->getAs<ConstantIntOp>()) {
Chris Lattner384da8c2018-08-02 17:16:58 -0700779 // i1 constants get special names.
780 if (intOp->getType()->isInteger(1)) {
781 specialName << (intOp->getValue() ? "true" : "false");
782 } else {
Chris Lattner992a1272018-08-07 12:02:37 -0700783 specialName << 'c' << intOp->getValue() << '_' << *intOp->getType();
Chris Lattner384da8c2018-08-02 17:16:58 -0700784 }
Chris Lattner992a1272018-08-07 12:02:37 -0700785 } else if (auto intOp = op->getAs<ConstantAffineIntOp>()) {
786 specialName << 'c' << intOp->getValue();
Chris Lattnerd4964212018-08-01 10:43:18 -0700787 }
Tatiana Shpeisman3838db72018-07-30 15:18:10 -0700788 }
Chris Lattnerd4964212018-08-01 10:43:18 -0700789
790 if (specialNameBuffer.empty()) {
791 switch (value->getKind()) {
792 case SSAValueKind::BBArgument:
793 // If this is an argument to the function, give it an 'arg' name.
794 if (auto *bb = cast<BBArgument>(value)->getOwner())
795 if (auto *fn = bb->getFunction())
796 if (&fn->front() == bb) {
797 specialName << "arg" << nextArgumentID++;
798 break;
799 }
800 // Otherwise number it normally.
801 LLVM_FALLTHROUGH;
802 case SSAValueKind::InstResult:
803 case SSAValueKind::StmtResult:
804 // This is an uninteresting result, give it a boring number and be
805 // done with it.
806 valueIDs[value] = nextValueID++;
807 return;
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -0700808 case SSAValueKind::MLFuncArgument:
Chris Lattnerd4964212018-08-01 10:43:18 -0700809 specialName << "arg" << nextArgumentID++;
810 break;
811 case SSAValueKind::ForStmt:
812 specialName << 'i' << nextLoopID++;
813 break;
814 }
815 }
816
817 // Ok, this value had an interesting name. Remember it with a sentinel.
818 valueIDs[value] = nameSentinel;
819
820 // Remember that we've used this name, checking to see if we had a conflict.
821 auto insertRes = usedNames.insert(specialName.str());
822 if (insertRes.second) {
823 // If this is the first use of the name, then we're successful!
824 valueNames[value] = insertRes.first->first();
825 return;
826 }
827
828 // Otherwise, we had a conflict - probe until we find a unique name. This
829 // is guaranteed to terminate (and usually in a single iteration) because it
830 // generates new names by incrementing nextConflictID.
831 while (1) {
832 std::string probeName =
833 specialName.str().str() + "_" + llvm::utostr(nextConflictID++);
834 insertRes = usedNames.insert(probeName);
835 if (insertRes.second) {
836 // If this is the first use of the name, then we're successful!
837 valueNames[value] = insertRes.first->first();
838 return;
839 }
840 }
Chris Lattnerf8cce872018-07-20 09:28:54 -0700841 }
842
Tatiana Shpeisman3838db72018-07-30 15:18:10 -0700843 void printValueID(const SSAValue *value, bool printResultNo = true) const {
Chris Lattner6119d382018-07-20 18:41:34 -0700844 int resultNo = -1;
845 auto lookupValue = value;
846
Tatiana Shpeisman3838db72018-07-30 15:18:10 -0700847 // If this is a reference to the result of a multi-result instruction or
848 // statement, print out the # identifier and make sure to map our lookup
849 // to the first result of the instruction.
Chris Lattner6119d382018-07-20 18:41:34 -0700850 if (auto *result = dyn_cast<InstResult>(value)) {
851 if (result->getOwner()->getNumResults() != 1) {
852 resultNo = result->getResultNumber();
853 lookupValue = result->getOwner()->getResult(0);
854 }
Tatiana Shpeisman3838db72018-07-30 15:18:10 -0700855 } else if (auto *result = dyn_cast<StmtResult>(value)) {
856 if (result->getOwner()->getNumResults() != 1) {
857 resultNo = result->getResultNumber();
858 lookupValue = result->getOwner()->getResult(0);
859 }
Chris Lattner6119d382018-07-20 18:41:34 -0700860 }
861
862 auto it = valueIDs.find(lookupValue);
863 if (it == valueIDs.end()) {
Chris Lattnerf8cce872018-07-20 09:28:54 -0700864 os << "<<INVALID SSA VALUE>>";
Chris Lattner6119d382018-07-20 18:41:34 -0700865 return;
866 }
867
Tatiana Shpeisman3838db72018-07-30 15:18:10 -0700868 os << '%';
Chris Lattnerd4964212018-08-01 10:43:18 -0700869 if (it->second != nameSentinel) {
870 os << it->second;
871 } else {
872 auto nameIt = valueNames.find(lookupValue);
873 assert(nameIt != valueNames.end() && "Didn't have a name entry?");
874 os << nameIt->second;
875 }
Tatiana Shpeisman3838db72018-07-30 15:18:10 -0700876
Tatiana Shpeisman3838db72018-07-30 15:18:10 -0700877 if (resultNo != -1 && printResultNo)
Chris Lattner6119d382018-07-20 18:41:34 -0700878 os << '#' << resultNo;
Chris Lattnerf8cce872018-07-20 09:28:54 -0700879 }
880
881private:
Chris Lattnerd4964212018-08-01 10:43:18 -0700882 /// This is the value ID for each SSA value in the current function. If this
883 /// returns ~0, then the valueID has an entry in valueNames.
Chris Lattnerf8cce872018-07-20 09:28:54 -0700884 DenseMap<const SSAValue *, unsigned> valueIDs;
Chris Lattnerd4964212018-08-01 10:43:18 -0700885 DenseMap<const SSAValue *, StringRef> valueNames;
886
887 /// This keeps track of all of the non-numeric names that are in flight,
888 /// allowing us to check for duplicates.
889 llvm::StringSet<> usedNames;
890
891 /// This is the next value ID to assign in numbering.
Chris Lattnerf8cce872018-07-20 09:28:54 -0700892 unsigned nextValueID = 0;
Chris Lattnerd4964212018-08-01 10:43:18 -0700893 /// This is the ID to assign to the next induction variable.
Tatiana Shpeismanc9c4b342018-07-31 07:40:14 -0700894 unsigned nextLoopID = 0;
Chris Lattnerd4964212018-08-01 10:43:18 -0700895 /// This is the next ID to assign to an MLFunction argument.
896 unsigned nextArgumentID = 0;
897
898 /// This is the next ID to assign when a name conflict is detected.
899 unsigned nextConflictID = 0;
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700900};
James Molloy87d81022018-07-23 11:44:40 -0700901} // end anonymous namespace
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700902
Chris Lattner85cf26d2018-08-02 16:54:36 -0700903void FunctionPrinter::printOptionalAttrDict(
904 ArrayRef<NamedAttribute> attrs, ArrayRef<const char *> elidedAttrs) {
905 // If there are no attributes, then there is nothing to be done.
906 if (attrs.empty())
907 return;
908
909 // Filter out any attributes that shouldn't be included.
910 SmallVector<NamedAttribute, 8> filteredAttrs;
911 for (auto attr : attrs) {
912 auto attrName = attr.first.str();
913 // Never print attributes that start with a colon. These are internal
914 // attributes that represent location or other internal metadata.
915 if (attrName.startswith(":"))
916 continue;
917
918 // If the caller has requested that this attribute be ignored, then drop it.
919 bool ignore = false;
920 for (const char *elide : elidedAttrs)
921 ignore |= attrName == StringRef(elide);
922
923 // Otherwise add it to our filteredAttrs list.
924 if (!ignore)
925 filteredAttrs.push_back(attr);
926 }
927
928 // If there are no attributes left to print after filtering, then we're done.
929 if (filteredAttrs.empty())
930 return;
931
932 // Otherwise, print them all out in braces.
933 os << " {";
934 interleaveComma(filteredAttrs, [&](NamedAttribute attr) {
935 os << attr.first << ": ";
936 printAttribute(attr.second);
937 });
938 os << '}';
939}
940
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700941void FunctionPrinter::printOperation(const Operation *op) {
Chris Lattnerac591f12018-07-22 21:02:26 -0700942 if (op->getNumResults()) {
Tatiana Shpeisman3838db72018-07-30 15:18:10 -0700943 printValueID(op->getResult(0), /*printResultNo=*/false);
Chris Lattnerac591f12018-07-22 21:02:26 -0700944 os << " = ";
Chris Lattnerf8cce872018-07-20 09:28:54 -0700945 }
946
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700947 // Check to see if this is a known operation. If so, use the registered
948 // custom printer hook.
Chris Lattner4fd59b02018-07-20 09:35:47 -0700949 if (auto opInfo = state.operationSet->lookup(op->getName().str())) {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700950 opInfo->printAssembly(op, this);
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700951 return;
952 }
953
Chris Lattnerf8cce872018-07-20 09:28:54 -0700954 // Otherwise use the standard verbose printing approach.
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700955 printDefaultOp(op);
956}
Chris Lattnerf8cce872018-07-20 09:28:54 -0700957
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700958void FunctionPrinter::printDefaultOp(const Operation *op) {
Chris Lattner0497c4b2018-08-15 09:09:54 -0700959 os << '"';
960 printEscapedString(op->getName().str(), os);
961 os << "\"(";
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700962
Chris Lattnerac591f12018-07-22 21:02:26 -0700963 interleaveComma(op->getOperands(),
964 [&](const SSAValue *value) { printValueID(value); });
Chris Lattner7f9cc272018-07-19 08:35:28 -0700965
Chris Lattnerf8cce872018-07-20 09:28:54 -0700966 os << ')';
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700967 auto attrs = op->getAttrs();
Chris Lattner85cf26d2018-08-02 16:54:36 -0700968 printOptionalAttrDict(attrs);
Chris Lattner3b2ef762018-07-18 15:31:25 -0700969
Chris Lattnerac591f12018-07-22 21:02:26 -0700970 // Print the type signature of the operation.
971 os << " : (";
972 interleaveComma(op->getOperands(),
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700973 [&](const SSAValue *value) { printType(value->getType()); });
Chris Lattnerac591f12018-07-22 21:02:26 -0700974 os << ") -> ";
Chris Lattnerf8cce872018-07-20 09:28:54 -0700975
Chris Lattnerac591f12018-07-22 21:02:26 -0700976 if (op->getNumResults() == 1) {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700977 printType(op->getResult(0)->getType());
Chris Lattnerac591f12018-07-22 21:02:26 -0700978 } else {
979 os << '(';
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700980 interleaveComma(op->getResults(), [&](const SSAValue *result) {
981 printType(result->getType());
982 });
Chris Lattnerac591f12018-07-22 21:02:26 -0700983 os << ')';
Chris Lattnerf8cce872018-07-20 09:28:54 -0700984 }
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700985}
986
Chris Lattner4c95a502018-06-23 16:03:42 -0700987//===----------------------------------------------------------------------===//
988// CFG Function printing
989//===----------------------------------------------------------------------===//
990
991namespace {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700992class CFGFunctionPrinter : public FunctionPrinter {
Chris Lattner4c95a502018-06-23 16:03:42 -0700993public:
Chris Lattner4fd59b02018-07-20 09:35:47 -0700994 CFGFunctionPrinter(const CFGFunction *function, const ModulePrinter &other);
Chris Lattner4c95a502018-06-23 16:03:42 -0700995
996 const CFGFunction *getFunction() const { return function; }
997
998 void print();
999 void print(const BasicBlock *block);
Chris Lattnered65a732018-06-28 20:45:33 -07001000
1001 void print(const Instruction *inst);
1002 void print(const OperationInst *inst);
1003 void print(const ReturnInst *inst);
1004 void print(const BranchInst *inst);
James Molloy4f788372018-07-24 15:01:27 -07001005 void print(const CondBranchInst *inst);
Chris Lattner4c95a502018-06-23 16:03:42 -07001006
1007 unsigned getBBID(const BasicBlock *block) {
1008 auto it = basicBlockIDs.find(block);
1009 assert(it != basicBlockIDs.end() && "Block not in this function?");
1010 return it->second;
1011 }
1012
1013private:
1014 const CFGFunction *function;
MLIR Team54b55a22018-07-18 10:16:05 -07001015 DenseMap<const BasicBlock *, unsigned> basicBlockIDs;
Chris Lattnerf8cce872018-07-20 09:28:54 -07001016
Chris Lattner4fd59b02018-07-20 09:35:47 -07001017 void numberValuesInBlock(const BasicBlock *block);
Chris Lattner4c95a502018-06-23 16:03:42 -07001018};
James Molloy87d81022018-07-23 11:44:40 -07001019} // end anonymous namespace
Chris Lattner4c95a502018-06-23 16:03:42 -07001020
Chris Lattner4fd59b02018-07-20 09:35:47 -07001021CFGFunctionPrinter::CFGFunctionPrinter(const CFGFunction *function,
1022 const ModulePrinter &other)
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -07001023 : FunctionPrinter(other), function(function) {
Chris Lattner4c95a502018-06-23 16:03:42 -07001024 // Each basic block gets a unique ID per function.
1025 unsigned blockID = 0;
Chris Lattnerf8cce872018-07-20 09:28:54 -07001026 for (auto &block : *function) {
1027 basicBlockIDs[&block] = blockID++;
Chris Lattner4fd59b02018-07-20 09:35:47 -07001028 numberValuesInBlock(&block);
Chris Lattnerf8cce872018-07-20 09:28:54 -07001029 }
1030}
1031
1032/// Number all of the SSA values in the specified basic block.
Chris Lattner4fd59b02018-07-20 09:35:47 -07001033void CFGFunctionPrinter::numberValuesInBlock(const BasicBlock *block) {
James Molloy61a656c2018-07-22 15:45:24 -07001034 for (auto *arg : block->getArguments()) {
1035 numberValueID(arg);
1036 }
Chris Lattnerf8cce872018-07-20 09:28:54 -07001037 for (auto &op : *block) {
1038 // We number instruction that have results, and we only number the first
1039 // result.
1040 if (op.getNumResults() != 0)
1041 numberValueID(op.getResult(0));
1042 }
1043
1044 // Terminators do not define values.
Chris Lattner4c95a502018-06-23 16:03:42 -07001045}
1046
Chris Lattner4fd59b02018-07-20 09:35:47 -07001047void CFGFunctionPrinter::print() {
Chris Lattner4c95a502018-06-23 16:03:42 -07001048 os << "cfgfunc ";
Chris Lattner4fd59b02018-07-20 09:35:47 -07001049 printFunctionSignature(getFunction());
Chris Lattner4c95a502018-06-23 16:03:42 -07001050 os << " {\n";
1051
James Molloy87d81022018-07-23 11:44:40 -07001052 for (auto &block : *function)
1053 print(&block);
Chris Lattner4c95a502018-06-23 16:03:42 -07001054 os << "}\n\n";
1055}
1056
Chris Lattner4fd59b02018-07-20 09:35:47 -07001057void CFGFunctionPrinter::print(const BasicBlock *block) {
James Molloy61a656c2018-07-22 15:45:24 -07001058 os << "bb" << getBBID(block);
Chris Lattner4c95a502018-06-23 16:03:42 -07001059
James Molloy61a656c2018-07-22 15:45:24 -07001060 if (!block->args_empty()) {
1061 os << '(';
1062 interleaveComma(block->getArguments(), [&](const BBArgument *arg) {
1063 printValueID(arg);
1064 os << ": ";
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -07001065 printType(arg->getType());
James Molloy61a656c2018-07-22 15:45:24 -07001066 });
1067 os << ')';
1068 }
Chris Lattner25ce3062018-07-27 11:10:12 -07001069 os << ':';
1070
1071 // Print out some context information about the predecessors of this block.
1072 if (!block->getFunction()) {
1073 os << "\t// block is not in a function!";
1074 } else if (block->hasNoPredecessors()) {
1075 // Don't print "no predecessors" for the entry block.
1076 if (block != &block->getFunction()->front())
1077 os << "\t// no predecessors";
1078 } else if (auto *pred = block->getSinglePredecessor()) {
1079 os << "\t// pred: bb" << getBBID(pred);
1080 } else {
1081 // We want to print the predecessors in increasing numeric order, not in
1082 // whatever order the use-list is in, so gather and sort them.
1083 SmallVector<unsigned, 4> predIDs;
1084 for (auto *pred : block->getPredecessors())
1085 predIDs.push_back(getBBID(pred));
1086 llvm::array_pod_sort(predIDs.begin(), predIDs.end());
1087
1088 os << "\t// " << predIDs.size() << " preds: ";
1089
1090 interleaveComma(predIDs, [&](unsigned predID) { os << "bb" << predID; });
1091 }
1092 os << '\n';
James Molloy61a656c2018-07-22 15:45:24 -07001093
Jacques Pienaarb020c542018-07-15 00:06:54 -07001094 for (auto &inst : block->getOperations()) {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001095 os << " ";
Chris Lattner3a467cc2018-07-01 20:28:00 -07001096 print(&inst);
James Molloy61a656c2018-07-22 15:45:24 -07001097 os << '\n';
Jacques Pienaarb020c542018-07-15 00:06:54 -07001098 }
Chris Lattner4c95a502018-06-23 16:03:42 -07001099
James Molloy6e4519b2018-08-03 03:51:38 -07001100 os << " ";
Chris Lattner4c95a502018-06-23 16:03:42 -07001101 print(block->getTerminator());
James Molloy61a656c2018-07-22 15:45:24 -07001102 os << '\n';
Chris Lattner4c95a502018-06-23 16:03:42 -07001103}
1104
Chris Lattner4fd59b02018-07-20 09:35:47 -07001105void CFGFunctionPrinter::print(const Instruction *inst) {
Chris Lattner4c95a502018-06-23 16:03:42 -07001106 switch (inst->getKind()) {
Chris Lattnered65a732018-06-28 20:45:33 -07001107 case Instruction::Kind::Operation:
1108 return print(cast<OperationInst>(inst));
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001109 case TerminatorInst::Kind::Branch:
Chris Lattnered65a732018-06-28 20:45:33 -07001110 return print(cast<BranchInst>(inst));
James Molloy4f788372018-07-24 15:01:27 -07001111 case TerminatorInst::Kind::CondBranch:
1112 return print(cast<CondBranchInst>(inst));
Chris Lattner4c95a502018-06-23 16:03:42 -07001113 case TerminatorInst::Kind::Return:
Chris Lattnered65a732018-06-28 20:45:33 -07001114 return print(cast<ReturnInst>(inst));
Chris Lattner4c95a502018-06-23 16:03:42 -07001115 }
1116}
1117
Chris Lattner4fd59b02018-07-20 09:35:47 -07001118void CFGFunctionPrinter::print(const OperationInst *inst) {
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -07001119 printOperation(inst);
Chris Lattner3b2ef762018-07-18 15:31:25 -07001120}
Chris Lattner1604e472018-07-23 08:42:19 -07001121
Chris Lattner4fd59b02018-07-20 09:35:47 -07001122void CFGFunctionPrinter::print(const BranchInst *inst) {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001123 os << "br bb" << getBBID(inst->getDest());
Chris Lattner1604e472018-07-23 08:42:19 -07001124
1125 if (inst->getNumOperands() != 0) {
1126 os << '(';
Chris Lattner0497c4b2018-08-15 09:09:54 -07001127 interleaveComma(inst->getOperands(),
1128 [&](const CFGValue *operand) { printValueID(operand); });
Chris Lattner1604e472018-07-23 08:42:19 -07001129 os << ") : ";
Chris Lattner0497c4b2018-08-15 09:09:54 -07001130 interleaveComma(inst->getOperands(), [&](const CFGValue *operand) {
1131 printType(operand->getType());
Chris Lattner1604e472018-07-23 08:42:19 -07001132 });
1133 }
Chris Lattnered65a732018-06-28 20:45:33 -07001134}
Chris Lattner1604e472018-07-23 08:42:19 -07001135
James Molloy4f788372018-07-24 15:01:27 -07001136void CFGFunctionPrinter::print(const CondBranchInst *inst) {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001137 os << "cond_br ";
James Molloy4f788372018-07-24 15:01:27 -07001138 printValueID(inst->getCondition());
1139
1140 os << ", bb" << getBBID(inst->getTrueDest());
1141 if (inst->getNumTrueOperands() != 0) {
1142 os << '(';
1143 interleaveComma(inst->getTrueOperands(),
1144 [&](const CFGValue *operand) { printValueID(operand); });
1145 os << " : ";
1146 interleaveComma(inst->getTrueOperands(), [&](const CFGValue *operand) {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -07001147 printType(operand->getType());
James Molloy4f788372018-07-24 15:01:27 -07001148 });
1149 os << ")";
1150 }
1151
1152 os << ", bb" << getBBID(inst->getFalseDest());
1153 if (inst->getNumFalseOperands() != 0) {
1154 os << '(';
1155 interleaveComma(inst->getFalseOperands(),
1156 [&](const CFGValue *operand) { printValueID(operand); });
1157 os << " : ";
1158 interleaveComma(inst->getFalseOperands(), [&](const CFGValue *operand) {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -07001159 printType(operand->getType());
James Molloy4f788372018-07-24 15:01:27 -07001160 });
1161 os << ")";
1162 }
1163}
1164
Chris Lattner40746442018-07-21 14:32:09 -07001165void CFGFunctionPrinter::print(const ReturnInst *inst) {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001166 os << "return";
Chris Lattner40746442018-07-21 14:32:09 -07001167
James Molloy6bf60c22018-08-02 08:28:20 -07001168 if (inst->getNumOperands() == 0)
1169 return;
Chris Lattner40746442018-07-21 14:32:09 -07001170
James Molloy6bf60c22018-08-02 08:28:20 -07001171 os << ' ';
James Molloy4f788372018-07-24 15:01:27 -07001172 interleaveComma(inst->getOperands(),
1173 [&](const CFGValue *operand) { printValueID(operand); });
1174 os << " : ";
Chris Lattnerac591f12018-07-22 21:02:26 -07001175 interleaveComma(inst->getOperands(), [&](const CFGValue *operand) {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -07001176 printType(operand->getType());
Chris Lattner40746442018-07-21 14:32:09 -07001177 });
1178}
MLIR Team54b55a22018-07-18 10:16:05 -07001179
Chris Lattner4fd59b02018-07-20 09:35:47 -07001180void ModulePrinter::print(const CFGFunction *fn) {
1181 CFGFunctionPrinter(fn, *this).print();
Chris Lattnered65a732018-06-28 20:45:33 -07001182}
1183
Chris Lattner4c95a502018-06-23 16:03:42 -07001184//===----------------------------------------------------------------------===//
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001185// ML Function printing
Chris Lattner4c95a502018-06-23 16:03:42 -07001186//===----------------------------------------------------------------------===//
1187
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001188namespace {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -07001189class MLFunctionPrinter : public FunctionPrinter {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001190public:
Chris Lattner4fd59b02018-07-20 09:35:47 -07001191 MLFunctionPrinter(const MLFunction *function, const ModulePrinter &other);
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001192
1193 const MLFunction *getFunction() const { return function; }
1194
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001195 // Prints ML function
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001196 void print();
1197
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07001198 // Prints ML function signature
1199 void printFunctionSignature();
1200
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001201 // Methods to print ML function statements
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001202 void print(const Statement *stmt);
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -07001203 void print(const OperationStmt *stmt);
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001204 void print(const ForStmt *stmt);
1205 void print(const IfStmt *stmt);
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001206 void print(const StmtBlock *block);
1207
1208 // Number of spaces used for indenting nested statements
1209 const static unsigned indentWidth = 2;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001210
1211private:
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001212 void numberValues();
1213
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001214 const MLFunction *function;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001215 int numSpaces;
1216};
James Molloy87d81022018-07-23 11:44:40 -07001217} // end anonymous namespace
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001218
Chris Lattner4fd59b02018-07-20 09:35:47 -07001219MLFunctionPrinter::MLFunctionPrinter(const MLFunction *function,
1220 const ModulePrinter &other)
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001221 : FunctionPrinter(other), function(function), numSpaces(0) {
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07001222 assert(function && "Cannot print nullptr function");
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001223 numberValues();
1224}
1225
1226/// Number all of the SSA values in this ML function.
1227void MLFunctionPrinter::numberValues() {
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07001228 // Numbers ML function arguments
1229 for (auto *arg : function->getArguments())
1230 numberValueID(arg);
1231
1232 // Walks ML function statements and numbers for statements and
1233 // the first result of the operation statements.
Uday Bondhugula081d9e72018-07-27 10:58:14 -07001234 struct NumberValuesPass : public StmtWalker<NumberValuesPass> {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001235 NumberValuesPass(MLFunctionPrinter *printer) : printer(printer) {}
1236 void visitOperationStmt(OperationStmt *stmt) {
1237 if (stmt->getNumResults() != 0)
1238 printer->numberValueID(stmt->getResult(0));
1239 }
Tatiana Shpeismanc9c4b342018-07-31 07:40:14 -07001240 void visitForStmt(ForStmt *stmt) { printer->numberValueID(stmt); }
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001241 MLFunctionPrinter *printer;
1242 };
1243
1244 NumberValuesPass pass(this);
Chris Lattner0497c4b2018-08-15 09:09:54 -07001245 // TODO: it'd be cleaner to have constant visitor instead of using const_cast.
Uday Bondhugula081d9e72018-07-27 10:58:14 -07001246 pass.walk(const_cast<MLFunction *>(function));
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001247}
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001248
Chris Lattner4fd59b02018-07-20 09:35:47 -07001249void MLFunctionPrinter::print() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001250 os << "mlfunc ";
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07001251 printFunctionSignature();
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001252 os << " {\n";
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001253 print(function);
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001254 os << "}\n\n";
1255}
1256
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07001257void MLFunctionPrinter::printFunctionSignature() {
1258 auto type = function->getType();
1259
1260 os << "@" << function->getName() << '(';
1261
1262 for (unsigned i = 0, e = function->getNumArguments(); i != e; ++i) {
1263 if (i > 0)
1264 os << ", ";
1265 auto *arg = function->getArgument(i);
1266 printOperand(arg);
1267 os << " : ";
1268 printType(arg->getType());
1269 }
1270 os << ")";
1271 printFunctionResultType(type);
1272}
1273
Chris Lattner4fd59b02018-07-20 09:35:47 -07001274void MLFunctionPrinter::print(const StmtBlock *block) {
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001275 numSpaces += indentWidth;
Jacques Pienaarb020c542018-07-15 00:06:54 -07001276 for (auto &stmt : block->getStatements()) {
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001277 print(&stmt);
Jacques Pienaarb020c542018-07-15 00:06:54 -07001278 os << "\n";
1279 }
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001280 numSpaces -= indentWidth;
1281}
1282
Chris Lattner4fd59b02018-07-20 09:35:47 -07001283void MLFunctionPrinter::print(const Statement *stmt) {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001284 switch (stmt->getKind()) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001285 case Statement::Kind::Operation:
1286 return print(cast<OperationStmt>(stmt));
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001287 case Statement::Kind::For:
1288 return print(cast<ForStmt>(stmt));
1289 case Statement::Kind::If:
1290 return print(cast<IfStmt>(stmt));
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001291 }
1292}
1293
Chris Lattner4fd59b02018-07-20 09:35:47 -07001294void MLFunctionPrinter::print(const OperationStmt *stmt) {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001295 os.indent(numSpaces);
Chris Lattner4fd59b02018-07-20 09:35:47 -07001296 printOperation(stmt);
1297}
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001298
Chris Lattner4fd59b02018-07-20 09:35:47 -07001299void MLFunctionPrinter::print(const ForStmt *stmt) {
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07001300 os.indent(numSpaces) << "for ";
Tatiana Shpeismanc9c4b342018-07-31 07:40:14 -07001301 printOperand(stmt);
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07001302 os << " = " << *stmt->getLowerBound();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001303 os << " to " << *stmt->getUpperBound();
1304 if (stmt->getStep()->getValue() != 1)
1305 os << " step " << *stmt->getStep();
1306
1307 os << " {\n";
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001308 print(static_cast<const StmtBlock *>(stmt));
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001309 os.indent(numSpaces) << "}";
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001310}
1311
Chris Lattner4fd59b02018-07-20 09:35:47 -07001312void MLFunctionPrinter::print(const IfStmt *stmt) {
Uday Bondhugulabc535622018-08-07 14:24:38 -07001313 os.indent(numSpaces) << "if (";
1314 printIntegerSetReference(stmt->getCondition());
1315 os << ") {\n";
Chris Lattnere787b322018-08-08 11:14:57 -07001316 print(stmt->getThen());
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001317 os.indent(numSpaces) << "}";
Chris Lattnere787b322018-08-08 11:14:57 -07001318 if (stmt->hasElse()) {
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001319 os << " else {\n";
Chris Lattnere787b322018-08-08 11:14:57 -07001320 print(stmt->getElse());
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001321 os.indent(numSpaces) << "}";
1322 }
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001323}
1324
Chris Lattner4fd59b02018-07-20 09:35:47 -07001325void ModulePrinter::print(const MLFunction *fn) {
1326 MLFunctionPrinter(fn, *this).print();
MLIR Team4718bc92018-07-17 16:56:54 -07001327}
1328
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001329//===----------------------------------------------------------------------===//
1330// print and dump methods
1331//===----------------------------------------------------------------------===//
Chris Lattnered65a732018-06-28 20:45:33 -07001332
MLIR Teamb61885d2018-07-18 16:29:21 -07001333void Attribute::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -07001334 ModuleState state(/*no context is known*/ nullptr);
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -07001335 ModulePrinter(os, state).printAttribute(this);
MLIR Teamb61885d2018-07-18 16:29:21 -07001336}
1337
James Molloy87d81022018-07-23 11:44:40 -07001338void Attribute::dump() const { print(llvm::errs()); }
MLIR Teamb61885d2018-07-18 16:29:21 -07001339
MLIR Team4718bc92018-07-17 16:56:54 -07001340void Type::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -07001341 ModuleState state(getContext());
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -07001342 ModulePrinter(os, state).printType(this);
MLIR Team4718bc92018-07-17 16:56:54 -07001343}
1344
MLIR Team54b55a22018-07-18 10:16:05 -07001345void Type::dump() const { print(llvm::errs()); }
MLIR Team4718bc92018-07-17 16:56:54 -07001346
MLIR Team718c82f2018-07-16 09:45:22 -07001347void AffineMap::dump() const {
1348 print(llvm::errs());
1349 llvm::errs() << "\n";
1350}
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001351
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001352void AffineExpr::dump() const {
1353 print(llvm::errs());
1354 llvm::errs() << "\n";
1355}
1356
Uday Bondhugulabc535622018-08-07 14:24:38 -07001357void IntegerSet::dump() const {
1358 print(llvm::errs());
1359 llvm::errs() << "\n";
1360}
1361
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001362void AffineExpr::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -07001363 ModuleState state(/*no context is known*/ nullptr);
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -07001364 ModulePrinter(os, state).printAffineExpr(this);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001365}
1366
1367void AffineMap::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -07001368 ModuleState state(/*no context is known*/ nullptr);
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -07001369 ModulePrinter(os, state).printAffineMap(this);
Chris Lattner4fd59b02018-07-20 09:35:47 -07001370}
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001371
Uday Bondhugulabc535622018-08-07 14:24:38 -07001372void IntegerSet::print(raw_ostream &os) const {
1373 ModuleState state(/*no context is known*/ nullptr);
1374 ModulePrinter(os, state).printIntegerSet(this);
1375}
1376
Chris Lattner384da8c2018-08-02 17:16:58 -07001377void SSAValue::print(raw_ostream &os) const {
1378 switch (getKind()) {
1379 case SSAValueKind::BBArgument:
1380 // TODO: Improve this.
1381 os << "<bb argument>\n";
1382 return;
1383 case SSAValueKind::InstResult:
1384 return getDefiningInst()->print(os);
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07001385 case SSAValueKind::MLFuncArgument:
Chris Lattner384da8c2018-08-02 17:16:58 -07001386 // TODO: Improve this.
1387 os << "<function argument>\n";
1388 return;
1389 case SSAValueKind::StmtResult:
1390 return getDefiningStmt()->print(os);
1391 case SSAValueKind::ForStmt:
1392 return cast<ForStmt>(this)->print(os);
1393 }
1394}
1395
1396void SSAValue::dump() const { print(llvm::errs()); }
1397
Chris Lattner4fd59b02018-07-20 09:35:47 -07001398void Instruction::print(raw_ostream &os) const {
Tatiana Shpeismanc335d182018-08-03 11:12:34 -07001399 if (!getFunction()) {
1400 os << "<<UNLINKED INSTRUCTION>>\n";
1401 return;
1402 }
Chris Lattner4fd59b02018-07-20 09:35:47 -07001403 ModuleState state(getFunction()->getContext());
1404 ModulePrinter modulePrinter(os, state);
1405 CFGFunctionPrinter(getFunction(), modulePrinter).print(this);
1406}
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001407
Chris Lattner4fd59b02018-07-20 09:35:47 -07001408void Instruction::dump() const {
1409 print(llvm::errs());
1410 llvm::errs() << "\n";
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001411}
1412
Chris Lattner4c95a502018-06-23 16:03:42 -07001413void BasicBlock::print(raw_ostream &os) const {
Tatiana Shpeismanc335d182018-08-03 11:12:34 -07001414 if (!getFunction()) {
1415 os << "<<UNLINKED BLOCK>>\n";
1416 return;
1417 }
Chris Lattner4fd59b02018-07-20 09:35:47 -07001418 ModuleState state(getFunction()->getContext());
1419 ModulePrinter modulePrinter(os, state);
1420 CFGFunctionPrinter(getFunction(), modulePrinter).print(this);
Chris Lattner4c95a502018-06-23 16:03:42 -07001421}
1422
MLIR Team54b55a22018-07-18 10:16:05 -07001423void BasicBlock::dump() const { print(llvm::errs()); }
Chris Lattner4c95a502018-06-23 16:03:42 -07001424
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001425void Statement::print(raw_ostream &os) const {
Tatiana Shpeismand880b352018-07-31 23:14:16 -07001426 MLFunction *function = findFunction();
Tatiana Shpeismanc335d182018-08-03 11:12:34 -07001427 if (!function) {
1428 os << "<<UNLINKED STATEMENT>>\n";
1429 return;
1430 }
1431
Tatiana Shpeismand880b352018-07-31 23:14:16 -07001432 ModuleState state(function->getContext());
Chris Lattner4fd59b02018-07-20 09:35:47 -07001433 ModulePrinter modulePrinter(os, state);
Tatiana Shpeismand880b352018-07-31 23:14:16 -07001434 MLFunctionPrinter(function, modulePrinter).print(this);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001435}
1436
MLIR Team54b55a22018-07-18 10:16:05 -07001437void Statement::dump() const { print(llvm::errs()); }
Jacques Pienaarb020c542018-07-15 00:06:54 -07001438
Chris Lattnere787b322018-08-08 11:14:57 -07001439void StmtBlock::printBlock(raw_ostream &os) const {
Uday Bondhugula84b80952018-08-03 13:22:26 -07001440 MLFunction *function = findFunction();
1441 ModuleState state(function->getContext());
1442 ModulePrinter modulePrinter(os, state);
1443 MLFunctionPrinter(function, modulePrinter).print(this);
1444}
1445
Chris Lattnere787b322018-08-08 11:14:57 -07001446void StmtBlock::dumpBlock() const { printBlock(llvm::errs()); }
Uday Bondhugula84b80952018-08-03 13:22:26 -07001447
Chris Lattner4c95a502018-06-23 16:03:42 -07001448void Function::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -07001449 ModuleState state(getContext());
1450 ModulePrinter(os, state).print(this);
Chris Lattner4c95a502018-06-23 16:03:42 -07001451}
1452
MLIR Team54b55a22018-07-18 10:16:05 -07001453void Function::dump() const { print(llvm::errs()); }
1454
Chris Lattner4c95a502018-06-23 16:03:42 -07001455void Module::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -07001456 ModuleState state(getContext());
1457 state.initialize(this);
1458 ModulePrinter(os, state).print(this);
Chris Lattner4c95a502018-06-23 16:03:42 -07001459}
1460
MLIR Team54b55a22018-07-18 10:16:05 -07001461void Module::dump() const { print(llvm::errs()); }