blob: 99fb1df3a10f1c1e9ada0f0aa4ae68a039ad0340 [file] [log] [blame]
Chris Lattner4c95a502018-06-23 16:03:42 -07001//===- AsmPrinter.cpp - MLIR Assembly Printer Implementation --------------===//
2//
3// Copyright 2019 The MLIR Authors.
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16// =============================================================================
17//
18// This file implements the MLIR AsmPrinter class, which is used to implement
19// the various print() methods on the core IR objects.
20//
21//===----------------------------------------------------------------------===//
22
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -070023#include "mlir/IR/AffineExpr.h"
24#include "mlir/IR/AffineMap.h"
Chris Lattner7121b802018-07-04 20:45:39 -070025#include "mlir/IR/Attributes.h"
Chris Lattner4c95a502018-06-23 16:03:42 -070026#include "mlir/IR/CFGFunction.h"
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -070027#include "mlir/IR/MLFunction.h"
Chris Lattner4c95a502018-06-23 16:03:42 -070028#include "mlir/IR/Module.h"
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -070029#include "mlir/IR/OpImplementation.h"
Chris Lattnerff0d5902018-07-05 09:12:11 -070030#include "mlir/IR/OperationSet.h"
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -070031#include "mlir/IR/Statements.h"
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -070032#include "mlir/IR/StmtVisitor.h"
Chris Lattner4c95a502018-06-23 16:03:42 -070033#include "mlir/IR/Types.h"
34#include "mlir/Support/STLExtras.h"
Chris Lattner4c95a502018-06-23 16:03:42 -070035#include "llvm/ADT/DenseMap.h"
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -070036#include "llvm/Support/raw_ostream.h"
Chris Lattner4c95a502018-06-23 16:03:42 -070037using namespace mlir;
38
MLIR Team54b55a22018-07-18 10:16:05 -070039void Identifier::print(raw_ostream &os) const { os << str(); }
Chris Lattner4c95a502018-06-23 16:03:42 -070040
MLIR Team54b55a22018-07-18 10:16:05 -070041void Identifier::dump() const { print(llvm::errs()); }
Chris Lattner7121b802018-07-04 20:45:39 -070042
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -070043OpAsmPrinter::~OpAsmPrinter() {}
44
Chris Lattner4c95a502018-06-23 16:03:42 -070045//===----------------------------------------------------------------------===//
Chris Lattner4fd59b02018-07-20 09:35:47 -070046// ModuleState
MLIR Team4718bc92018-07-17 16:56:54 -070047//===----------------------------------------------------------------------===//
48
49namespace {
MLIR Team54b55a22018-07-18 10:16:05 -070050class ModuleState {
51public:
Chris Lattner4fd59b02018-07-20 09:35:47 -070052 /// This is the operation set for the current context if it is knowable (a
53 /// context could be determined), otherwise this is null.
54 OperationSet *const operationSet;
MLIR Team4718bc92018-07-17 16:56:54 -070055
Chris Lattner4fd59b02018-07-20 09:35:47 -070056 explicit ModuleState(MLIRContext *context)
57 : operationSet(context ? &OperationSet::get(context) : nullptr) {}
58
59 // Initializes module state, populating affine map state.
MLIR Team4718bc92018-07-17 16:56:54 -070060 void initialize(const Module *module);
61
MLIR Team54b55a22018-07-18 10:16:05 -070062 int getAffineMapId(const AffineMap *affineMap) const {
MLIR Team4718bc92018-07-17 16:56:54 -070063 auto it = affineMapIds.find(affineMap);
64 if (it == affineMapIds.end()) {
65 return -1;
66 }
67 return it->second;
68 }
69
James Molloyc4666722018-07-24 09:48:31 -070070 ArrayRef<const AffineMap *> getAffineMapIds() const { return affineMapsById; }
Chris Lattner4fd59b02018-07-20 09:35:47 -070071
MLIR Team54b55a22018-07-18 10:16:05 -070072private:
Chris Lattner4fd59b02018-07-20 09:35:47 -070073 void recordAffineMapReference(const AffineMap *affineMap) {
74 if (affineMapIds.count(affineMap) == 0) {
James Molloyc4666722018-07-24 09:48:31 -070075 affineMapIds[affineMap] = affineMapsById.size();
76 affineMapsById.push_back(affineMap);
Chris Lattner4fd59b02018-07-20 09:35:47 -070077 }
78 }
79
MLIR Team4718bc92018-07-17 16:56:54 -070080 // Visit functions.
81 void visitFunction(const Function *fn);
82 void visitExtFunction(const ExtFunction *fn);
83 void visitCFGFunction(const CFGFunction *fn);
84 void visitMLFunction(const MLFunction *fn);
85 void visitType(const Type *type);
MLIR Teamb61885d2018-07-18 16:29:21 -070086 void visitAttribute(const Attribute *attr);
87 void visitOperation(const Operation *op);
88
MLIR Team54b55a22018-07-18 10:16:05 -070089 DenseMap<const AffineMap *, int> affineMapIds;
James Molloyc4666722018-07-24 09:48:31 -070090 std::vector<const AffineMap *> affineMapsById;
MLIR Team4718bc92018-07-17 16:56:54 -070091};
James Molloy87d81022018-07-23 11:44:40 -070092} // end anonymous namespace
MLIR Team4718bc92018-07-17 16:56:54 -070093
94// TODO Support visiting other types/instructions when implemented.
95void ModuleState::visitType(const Type *type) {
Chris Lattner3164ae62018-07-28 09:36:25 -070096 if (auto *funcType = dyn_cast<FunctionType>(type)) {
MLIR Team4718bc92018-07-17 16:56:54 -070097 // Visit input and result types for functions.
Chris Lattner3164ae62018-07-28 09:36:25 -070098 for (auto *input : funcType->getInputs())
MLIR Team4718bc92018-07-17 16:56:54 -070099 visitType(input);
Chris Lattner3164ae62018-07-28 09:36:25 -0700100 for (auto *result : funcType->getResults())
MLIR Team4718bc92018-07-17 16:56:54 -0700101 visitType(result);
Chris Lattner3164ae62018-07-28 09:36:25 -0700102 } else if (auto *memref = dyn_cast<MemRefType>(type)) {
MLIR Team4718bc92018-07-17 16:56:54 -0700103 // Visit affine maps in memref type.
Chris Lattner3164ae62018-07-28 09:36:25 -0700104 for (auto *map : memref->getAffineMaps()) {
MLIR Team4718bc92018-07-17 16:56:54 -0700105 recordAffineMapReference(map);
106 }
107 }
108}
109
MLIR Teamb61885d2018-07-18 16:29:21 -0700110void ModuleState::visitAttribute(const Attribute *attr) {
Chris Lattner3164ae62018-07-28 09:36:25 -0700111 if (auto *mapAttr = dyn_cast<AffineMapAttr>(attr)) {
112 recordAffineMapReference(mapAttr->getValue());
113 } else if (auto *array = dyn_cast<ArrayAttr>(attr)) {
114 for (auto elt : array->getValue()) {
MLIR Teamb61885d2018-07-18 16:29:21 -0700115 visitAttribute(elt);
116 }
117 }
118}
119
120void ModuleState::visitOperation(const Operation *op) {
Chris Lattnerca2ee872018-07-31 18:32:59 -0700121 // Visit all the types used in the operation.
122 for (auto *operand : op->getOperands())
123 visitType(operand->getType());
124 for (auto *result : op->getResults())
125 visitType(result->getType());
126
127 // Visit each of the attributes.
128 for (auto elt : op->getAttrs())
MLIR Teamb61885d2018-07-18 16:29:21 -0700129 visitAttribute(elt.second);
MLIR Teamb61885d2018-07-18 16:29:21 -0700130}
131
MLIR Team4718bc92018-07-17 16:56:54 -0700132void ModuleState::visitExtFunction(const ExtFunction *fn) {
133 visitType(fn->getType());
134}
135
136void ModuleState::visitCFGFunction(const CFGFunction *fn) {
137 visitType(fn->getType());
MLIR Teamb61885d2018-07-18 16:29:21 -0700138 for (auto &block : *fn) {
139 for (auto &op : block.getOperations()) {
140 visitOperation(&op);
141 }
142 }
MLIR Team4718bc92018-07-17 16:56:54 -0700143}
144
145void ModuleState::visitMLFunction(const MLFunction *fn) {
146 visitType(fn->getType());
MLIR Teamb61885d2018-07-18 16:29:21 -0700147 // TODO Visit function body statements (and attributes if required).
MLIR Team4718bc92018-07-17 16:56:54 -0700148}
149
150void ModuleState::visitFunction(const Function *fn) {
151 switch (fn->getKind()) {
MLIR Team54b55a22018-07-18 10:16:05 -0700152 case Function::Kind::ExtFunc:
153 return visitExtFunction(cast<ExtFunction>(fn));
154 case Function::Kind::CFGFunc:
155 return visitCFGFunction(cast<CFGFunction>(fn));
156 case Function::Kind::MLFunc:
157 return visitMLFunction(cast<MLFunction>(fn));
MLIR Team4718bc92018-07-17 16:56:54 -0700158 }
159}
160
Chris Lattner4fd59b02018-07-20 09:35:47 -0700161// Initializes module state, populating affine map state.
162void ModuleState::initialize(const Module *module) {
Chris Lattnera8e47672018-07-25 14:08:16 -0700163 for (auto &fn : *module) {
164 visitFunction(&fn);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700165 }
166}
167
168//===----------------------------------------------------------------------===//
169// ModulePrinter
170//===----------------------------------------------------------------------===//
171
172namespace {
173class ModulePrinter {
174public:
175 ModulePrinter(raw_ostream &os, ModuleState &state) : os(os), state(state) {}
176 explicit ModulePrinter(const ModulePrinter &printer)
177 : os(printer.os), state(printer.state) {}
178
179 template <typename Container, typename UnaryFunctor>
180 inline void interleaveComma(const Container &c, UnaryFunctor each_fn) const {
181 interleave(c.begin(), c.end(), each_fn, [&]() { os << ", "; });
182 }
183
184 void print(const Module *module);
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700185 void printAttribute(const Attribute *attr);
186 void printType(const Type *type);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700187 void print(const Function *fn);
188 void print(const ExtFunction *fn);
189 void print(const CFGFunction *fn);
190 void print(const MLFunction *fn);
191
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700192 void printAffineMap(const AffineMap *map);
193 void printAffineExpr(const AffineExpr *expr);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700194
195protected:
196 raw_ostream &os;
197 ModuleState &state;
198
199 void printFunctionSignature(const Function *fn);
200 void printAffineMapId(int affineMapId) const;
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700201 void printAffineMapReference(const AffineMap *affineMap);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700202
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700203 /// This enum is used to represent the binding stength of the enclosing
204 /// context that an AffineExpr is being printed in, so we can intelligently
205 /// produce parens.
206 enum class BindingStrength {
207 Weak, // + and -
208 Strong, // All other binary operators.
209 };
210 void printAffineExprInternal(const AffineExpr *expr,
211 BindingStrength enclosingTightness);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700212};
213} // end anonymous namespace
214
MLIR Team4718bc92018-07-17 16:56:54 -0700215// Prints function with initialized module state.
Chris Lattner4fd59b02018-07-20 09:35:47 -0700216void ModulePrinter::print(const Function *fn) {
MLIR Team4718bc92018-07-17 16:56:54 -0700217 switch (fn->getKind()) {
MLIR Team54b55a22018-07-18 10:16:05 -0700218 case Function::Kind::ExtFunc:
219 return print(cast<ExtFunction>(fn));
220 case Function::Kind::CFGFunc:
221 return print(cast<CFGFunction>(fn));
222 case Function::Kind::MLFunc:
223 return print(cast<MLFunction>(fn));
MLIR Team4718bc92018-07-17 16:56:54 -0700224 }
225}
226
227// Prints affine map identifier.
Chris Lattner4fd59b02018-07-20 09:35:47 -0700228void ModulePrinter::printAffineMapId(int affineMapId) const {
MLIR Team4718bc92018-07-17 16:56:54 -0700229 os << "#map" << affineMapId;
230}
231
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700232void ModulePrinter::printAffineMapReference(const AffineMap *affineMap) {
Chris Lattner4fd59b02018-07-20 09:35:47 -0700233 int mapId = state.getAffineMapId(affineMap);
MLIR Teamb61885d2018-07-18 16:29:21 -0700234 if (mapId >= 0) {
235 // Map will be printed at top of module so print reference to its id.
236 printAffineMapId(mapId);
237 } else {
238 // Map not in module state so print inline.
239 affineMap->print(os);
240 }
241}
242
Chris Lattner4fd59b02018-07-20 09:35:47 -0700243void ModulePrinter::print(const Module *module) {
James Molloyc4666722018-07-24 09:48:31 -0700244 for (const auto &map : state.getAffineMapIds()) {
245 printAffineMapId(state.getAffineMapId(map));
MLIR Team4718bc92018-07-17 16:56:54 -0700246 os << " = ";
James Molloyc4666722018-07-24 09:48:31 -0700247 map->print(os);
MLIR Team4718bc92018-07-17 16:56:54 -0700248 os << '\n';
249 }
Chris Lattnera8e47672018-07-25 14:08:16 -0700250 for (auto const &fn : *module)
251 print(&fn);
MLIR Team4718bc92018-07-17 16:56:54 -0700252}
253
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700254void ModulePrinter::printAttribute(const Attribute *attr) {
MLIR Teamb61885d2018-07-18 16:29:21 -0700255 switch (attr->getKind()) {
256 case Attribute::Kind::Bool:
257 os << (cast<BoolAttr>(attr)->getValue() ? "true" : "false");
258 break;
259 case Attribute::Kind::Integer:
260 os << cast<IntegerAttr>(attr)->getValue();
261 break;
262 case Attribute::Kind::Float:
263 // FIXME: this isn't precise, we should print with a hex format.
264 os << cast<FloatAttr>(attr)->getValue();
265 break;
266 case Attribute::Kind::String:
267 // FIXME: should escape the string.
268 os << '"' << cast<StringAttr>(attr)->getValue() << '"';
269 break;
270 case Attribute::Kind::Array: {
271 auto elts = cast<ArrayAttr>(attr)->getValue();
272 os << '[';
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700273 interleaveComma(elts, [&](Attribute *attr) { printAttribute(attr); });
MLIR Teamb61885d2018-07-18 16:29:21 -0700274 os << ']';
275 break;
276 }
277 case Attribute::Kind::AffineMap:
278 printAffineMapReference(cast<AffineMapAttr>(attr)->getValue());
279 break;
280 }
281}
282
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700283void ModulePrinter::printType(const Type *type) {
MLIR Team4718bc92018-07-17 16:56:54 -0700284 switch (type->getKind()) {
MLIR Team54b55a22018-07-18 10:16:05 -0700285 case Type::Kind::AffineInt:
286 os << "affineint";
287 return;
288 case Type::Kind::BF16:
289 os << "bf16";
290 return;
291 case Type::Kind::F16:
292 os << "f16";
293 return;
294 case Type::Kind::F32:
295 os << "f32";
296 return;
297 case Type::Kind::F64:
298 os << "f64";
299 return;
Jacques Pienaarc0d69302018-07-27 11:07:12 -0700300 case Type::Kind::TFControl:
301 os << "tf_control";
302 return;
MLIR Team4718bc92018-07-17 16:56:54 -0700303
304 case Type::Kind::Integer: {
305 auto *integer = cast<IntegerType>(type);
306 os << 'i' << integer->getWidth();
307 return;
308 }
309 case Type::Kind::Function: {
310 auto *func = cast<FunctionType>(type);
311 os << '(';
Chris Lattner413db6a2018-07-25 12:55:50 -0700312 interleaveComma(func->getInputs(), [&](Type *type) { printType(type); });
MLIR Team4718bc92018-07-17 16:56:54 -0700313 os << ") -> ";
314 auto results = func->getResults();
315 if (results.size() == 1)
316 os << *results[0];
317 else {
318 os << '(';
Chris Lattner413db6a2018-07-25 12:55:50 -0700319 interleaveComma(results, [&](Type *type) { printType(type); });
MLIR Team4718bc92018-07-17 16:56:54 -0700320 os << ')';
321 }
322 return;
323 }
324 case Type::Kind::Vector: {
325 auto *v = cast<VectorType>(type);
326 os << "vector<";
James Molloy87d81022018-07-23 11:44:40 -0700327 for (auto dim : v->getShape())
328 os << dim << 'x';
MLIR Team4718bc92018-07-17 16:56:54 -0700329 os << *v->getElementType() << '>';
330 return;
331 }
332 case Type::Kind::RankedTensor: {
333 auto *v = cast<RankedTensorType>(type);
334 os << "tensor<";
335 for (auto dim : v->getShape()) {
336 if (dim < 0)
337 os << '?';
338 else
339 os << dim;
340 os << 'x';
341 }
342 os << *v->getElementType() << '>';
343 return;
344 }
345 case Type::Kind::UnrankedTensor: {
346 auto *v = cast<UnrankedTensorType>(type);
Chris Lattner413db6a2018-07-25 12:55:50 -0700347 os << "tensor<??";
348 printType(v->getElementType());
349 os << '>';
MLIR Team4718bc92018-07-17 16:56:54 -0700350 return;
351 }
352 case Type::Kind::MemRef: {
353 auto *v = cast<MemRefType>(type);
354 os << "memref<";
355 for (auto dim : v->getShape()) {
356 if (dim < 0)
357 os << '?';
358 else
359 os << dim;
360 os << 'x';
361 }
Chris Lattner413db6a2018-07-25 12:55:50 -0700362 printType(v->getElementType());
MLIR Team4718bc92018-07-17 16:56:54 -0700363 for (auto map : v->getAffineMaps()) {
364 os << ", ";
MLIR Teamb61885d2018-07-18 16:29:21 -0700365 printAffineMapReference(map);
MLIR Team4718bc92018-07-17 16:56:54 -0700366 }
Chris Lattner413db6a2018-07-25 12:55:50 -0700367 // Only print the memory space if it is the non-default one.
368 if (v->getMemorySpace())
369 os << ", " << v->getMemorySpace();
MLIR Team4718bc92018-07-17 16:56:54 -0700370 os << '>';
371 return;
372 }
373 }
374}
375
376//===----------------------------------------------------------------------===//
Chris Lattner4fd59b02018-07-20 09:35:47 -0700377// Affine expressions and maps
378//===----------------------------------------------------------------------===//
379
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700380void ModulePrinter::printAffineExpr(const AffineExpr *expr) {
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700381 printAffineExprInternal(expr, BindingStrength::Weak);
382}
383
384void ModulePrinter::printAffineExprInternal(
385 const AffineExpr *expr, BindingStrength enclosingTightness) {
386 const char *binopSpelling = nullptr;
Chris Lattner4fd59b02018-07-20 09:35:47 -0700387 switch (expr->getKind()) {
388 case AffineExpr::Kind::SymbolId:
389 os << 's' << cast<AffineSymbolExpr>(expr)->getPosition();
390 return;
391 case AffineExpr::Kind::DimId:
392 os << 'd' << cast<AffineDimExpr>(expr)->getPosition();
393 return;
394 case AffineExpr::Kind::Constant:
395 os << cast<AffineConstantExpr>(expr)->getValue();
396 return;
397 case AffineExpr::Kind::Add:
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700398 binopSpelling = " + ";
399 break;
Chris Lattner4fd59b02018-07-20 09:35:47 -0700400 case AffineExpr::Kind::Mul:
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700401 binopSpelling = " * ";
402 break;
Chris Lattner4fd59b02018-07-20 09:35:47 -0700403 case AffineExpr::Kind::FloorDiv:
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700404 binopSpelling = " floordiv ";
405 break;
Chris Lattner4fd59b02018-07-20 09:35:47 -0700406 case AffineExpr::Kind::CeilDiv:
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700407 binopSpelling = " ceildiv ";
408 break;
Chris Lattner4fd59b02018-07-20 09:35:47 -0700409 case AffineExpr::Kind::Mod:
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700410 binopSpelling = " mod ";
411 break;
Chris Lattner4fd59b02018-07-20 09:35:47 -0700412 }
Chris Lattner4fd59b02018-07-20 09:35:47 -0700413
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700414 auto *binOp = cast<AffineBinaryOpExpr>(expr);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700415
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700416 // Handle tightly binding binary operators.
417 if (binOp->getKind() != AffineExpr::Kind::Add) {
418 if (enclosingTightness == BindingStrength::Strong)
419 os << '(';
420
421 printAffineExprInternal(binOp->getLHS(), BindingStrength::Strong);
422 os << binopSpelling;
423 printAffineExprInternal(binOp->getRHS(), BindingStrength::Strong);
424
425 if (enclosingTightness == BindingStrength::Strong)
426 os << ')';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700427 return;
428 }
429
430 // Print out special "pretty" forms for add.
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700431 if (enclosingTightness == BindingStrength::Strong)
432 os << '(';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700433
434 // Pretty print addition to a product that has a negative operand as a
435 // subtraction.
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700436 if (auto *rhs = dyn_cast<AffineBinaryOpExpr>(binOp->getRHS())) {
Chris Lattner4fd59b02018-07-20 09:35:47 -0700437 if (rhs->getKind() == AffineExpr::Kind::Mul) {
438 if (auto *rrhs = dyn_cast<AffineConstantExpr>(rhs->getRHS())) {
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700439 if (rrhs->getValue() == -1) {
440 printAffineExprInternal(binOp->getLHS(), BindingStrength::Weak);
441 os << " - ";
442 printAffineExprInternal(rhs->getLHS(), BindingStrength::Weak);
443
444 if (enclosingTightness == BindingStrength::Strong)
445 os << ')';
446 return;
447 }
448
449 if (rrhs->getValue() < -1) {
450 printAffineExprInternal(binOp->getLHS(), BindingStrength::Weak);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700451 os << " - (";
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700452 printAffineExprInternal(rhs->getLHS(), BindingStrength::Strong);
453 os << " * " << -rrhs->getValue() << ')';
454 if (enclosingTightness == BindingStrength::Strong)
455 os << ')';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700456 return;
457 }
458 }
459 }
460 }
461
462 // Pretty print addition to a negative number as a subtraction.
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700463 if (auto *rhs = dyn_cast<AffineConstantExpr>(binOp->getRHS())) {
Chris Lattner4fd59b02018-07-20 09:35:47 -0700464 if (rhs->getValue() < 0) {
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700465 printAffineExprInternal(binOp->getLHS(), BindingStrength::Weak);
466 os << " - " << -rhs->getValue() << ')';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700467 return;
468 }
469 }
470
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700471 printAffineExprInternal(binOp->getLHS(), BindingStrength::Weak);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700472 os << " + ";
Chris Lattner7d3b77c2018-07-31 16:21:36 -0700473 printAffineExprInternal(binOp->getRHS(), BindingStrength::Weak);
474
475 if (enclosingTightness == BindingStrength::Strong)
476 os << ')';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700477}
478
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700479void ModulePrinter::printAffineMap(const AffineMap *map) {
Chris Lattner4fd59b02018-07-20 09:35:47 -0700480 // Dimension identifiers.
481 os << '(';
Chris Lattnerdc3ba382018-07-29 14:13:03 -0700482 for (int i = 0; i < (int)map->getNumDims() - 1; ++i)
483 os << 'd' << i << ", ";
Chris Lattner4fd59b02018-07-20 09:35:47 -0700484 if (map->getNumDims() >= 1)
Chris Lattnerdc3ba382018-07-29 14:13:03 -0700485 os << 'd' << map->getNumDims() - 1;
486 os << ')';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700487
488 // Symbolic identifiers.
Chris Lattnerdc3ba382018-07-29 14:13:03 -0700489 if (map->getNumSymbols() != 0) {
490 os << '[';
491 for (unsigned i = 0; i < map->getNumSymbols() - 1; ++i)
492 os << 's' << i << ", ";
Chris Lattner4fd59b02018-07-20 09:35:47 -0700493 if (map->getNumSymbols() >= 1)
Chris Lattnerdc3ba382018-07-29 14:13:03 -0700494 os << 's' << map->getNumSymbols() - 1;
495 os << ']';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700496 }
497
498 // AffineMap should have at least one result.
499 assert(!map->getResults().empty());
500 // Result affine expressions.
501 os << " -> (";
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700502 interleaveComma(map->getResults(),
503 [&](AffineExpr *expr) { printAffineExpr(expr); });
Chris Lattnerdc3ba382018-07-29 14:13:03 -0700504 os << ')';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700505
506 if (!map->isBounded()) {
507 return;
508 }
509
510 // Print range sizes for bounded affine maps.
511 os << " size (";
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700512 interleaveComma(map->getRangeSizes(),
513 [&](AffineExpr *expr) { printAffineExpr(expr); });
Chris Lattnerdc3ba382018-07-29 14:13:03 -0700514 os << ')';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700515}
516
517//===----------------------------------------------------------------------===//
Chris Lattner4c95a502018-06-23 16:03:42 -0700518// Function printing
519//===----------------------------------------------------------------------===//
520
Chris Lattner4fd59b02018-07-20 09:35:47 -0700521void ModulePrinter::printFunctionSignature(const Function *fn) {
Chris Lattner4c95a502018-06-23 16:03:42 -0700522 auto type = fn->getType();
523
524 os << "@" << fn->getName() << '(';
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700525 interleaveComma(type->getInputs(),
526 [&](Type *eltType) { printType(eltType); });
Chris Lattner4c95a502018-06-23 16:03:42 -0700527 os << ')';
528
529 switch (type->getResults().size()) {
MLIR Team54b55a22018-07-18 10:16:05 -0700530 case 0:
531 break;
Chris Lattner4c95a502018-06-23 16:03:42 -0700532 case 1:
MLIR Team4718bc92018-07-17 16:56:54 -0700533 os << " -> ";
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700534 printType(type->getResults()[0]);
Chris Lattner4c95a502018-06-23 16:03:42 -0700535 break;
536 default:
537 os << " -> (";
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700538 interleaveComma(type->getResults(),
539 [&](Type *eltType) { printType(eltType); });
Chris Lattner4c95a502018-06-23 16:03:42 -0700540 os << ')';
541 break;
542 }
543}
544
Chris Lattner4fd59b02018-07-20 09:35:47 -0700545void ModulePrinter::print(const ExtFunction *fn) {
Chris Lattner4c95a502018-06-23 16:03:42 -0700546 os << "extfunc ";
Chris Lattner4fd59b02018-07-20 09:35:47 -0700547 printFunctionSignature(fn);
MLIR Team54b55a22018-07-18 10:16:05 -0700548 os << '\n';
Chris Lattner4c95a502018-06-23 16:03:42 -0700549}
550
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700551namespace {
552
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700553// FunctionPrinter contains common functionality for printing
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700554// CFG and ML functions.
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700555class FunctionPrinter : public ModulePrinter, private OpAsmPrinter {
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700556public:
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700557 FunctionPrinter(const ModulePrinter &other) : ModulePrinter(other) {}
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700558
559 void printOperation(const Operation *op);
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700560 void printDefaultOp(const Operation *op);
561
562 // Implement OpAsmPrinter.
563 raw_ostream &getStream() const { return os; }
564 void printType(const Type *type) { ModulePrinter::printType(type); }
565 void printAttribute(const Attribute *attr) {
566 ModulePrinter::printAttribute(attr);
567 }
568 void printAffineMap(const AffineMap *map) {
Chris Lattner3164ae62018-07-28 09:36:25 -0700569 return ModulePrinter::printAffineMapReference(map);
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700570 }
571 void printAffineExpr(const AffineExpr *expr) {
572 return ModulePrinter::printAffineExpr(expr);
573 }
574
575 void printOperand(const SSAValue *value) { printValueID(value); }
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700576
577protected:
Chris Lattnerf8cce872018-07-20 09:28:54 -0700578 void numberValueID(const SSAValue *value) {
579 assert(!valueIDs.count(value) && "Value numbered multiple times");
Tatiana Shpeisman3838db72018-07-30 15:18:10 -0700580 unsigned id;
581 switch (value->getKind()) {
582 case SSAValueKind::BBArgument:
583 case SSAValueKind::InstResult:
584 case SSAValueKind::StmtResult:
585 id = nextValueID++;
586 break;
587 case SSAValueKind::FnArgument:
588 id = nextFnArgumentID++;
589 break;
Tatiana Shpeismanc9c4b342018-07-31 07:40:14 -0700590 case SSAValueKind::ForStmt:
591 id = nextLoopID++;
Tatiana Shpeisman3838db72018-07-30 15:18:10 -0700592 break;
593 }
594 valueIDs[value] = id;
Chris Lattnerf8cce872018-07-20 09:28:54 -0700595 }
596
Tatiana Shpeisman3838db72018-07-30 15:18:10 -0700597 void printValueID(const SSAValue *value, bool printResultNo = true) const {
Chris Lattner6119d382018-07-20 18:41:34 -0700598 int resultNo = -1;
599 auto lookupValue = value;
600
Tatiana Shpeisman3838db72018-07-30 15:18:10 -0700601 // If this is a reference to the result of a multi-result instruction or
602 // statement, print out the # identifier and make sure to map our lookup
603 // to the first result of the instruction.
Chris Lattner6119d382018-07-20 18:41:34 -0700604 if (auto *result = dyn_cast<InstResult>(value)) {
605 if (result->getOwner()->getNumResults() != 1) {
606 resultNo = result->getResultNumber();
607 lookupValue = result->getOwner()->getResult(0);
608 }
Tatiana Shpeisman3838db72018-07-30 15:18:10 -0700609 } else if (auto *result = dyn_cast<StmtResult>(value)) {
610 if (result->getOwner()->getNumResults() != 1) {
611 resultNo = result->getResultNumber();
612 lookupValue = result->getOwner()->getResult(0);
613 }
Chris Lattner6119d382018-07-20 18:41:34 -0700614 }
615
616 auto it = valueIDs.find(lookupValue);
617 if (it == valueIDs.end()) {
Chris Lattnerf8cce872018-07-20 09:28:54 -0700618 os << "<<INVALID SSA VALUE>>";
Chris Lattner6119d382018-07-20 18:41:34 -0700619 return;
620 }
621
Tatiana Shpeisman3838db72018-07-30 15:18:10 -0700622 os << '%';
623 if (isa<ForStmt>(value))
624
625 os << 'i';
626 else if (isa<FnArgument>(value))
627 os << "arg";
628 os << it->getSecond();
629 if (resultNo != -1 && printResultNo)
Chris Lattner6119d382018-07-20 18:41:34 -0700630 os << '#' << resultNo;
Chris Lattnerf8cce872018-07-20 09:28:54 -0700631 }
632
633private:
634 /// This is the value ID for each SSA value in the current function.
635 DenseMap<const SSAValue *, unsigned> valueIDs;
636 unsigned nextValueID = 0;
Tatiana Shpeismanc9c4b342018-07-31 07:40:14 -0700637 unsigned nextLoopID = 0;
Tatiana Shpeisman3838db72018-07-30 15:18:10 -0700638 unsigned nextFnArgumentID = 0;
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700639};
James Molloy87d81022018-07-23 11:44:40 -0700640} // end anonymous namespace
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700641
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700642void FunctionPrinter::printOperation(const Operation *op) {
Chris Lattnerac591f12018-07-22 21:02:26 -0700643 if (op->getNumResults()) {
Tatiana Shpeisman3838db72018-07-30 15:18:10 -0700644 printValueID(op->getResult(0), /*printResultNo=*/false);
Chris Lattnerac591f12018-07-22 21:02:26 -0700645 os << " = ";
Chris Lattnerf8cce872018-07-20 09:28:54 -0700646 }
647
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700648 // Check to see if this is a known operation. If so, use the registered
649 // custom printer hook.
Chris Lattner4fd59b02018-07-20 09:35:47 -0700650 if (auto opInfo = state.operationSet->lookup(op->getName().str())) {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700651 opInfo->printAssembly(op, this);
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700652 return;
653 }
654
Chris Lattnerf8cce872018-07-20 09:28:54 -0700655 // Otherwise use the standard verbose printing approach.
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700656 printDefaultOp(op);
657}
Chris Lattnerf8cce872018-07-20 09:28:54 -0700658
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700659void FunctionPrinter::printDefaultOp(const Operation *op) {
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700660 // TODO: escape name if necessary.
Chris Lattnerf8cce872018-07-20 09:28:54 -0700661 os << "\"" << op->getName().str() << "\"(";
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700662
Chris Lattnerac591f12018-07-22 21:02:26 -0700663 interleaveComma(op->getOperands(),
664 [&](const SSAValue *value) { printValueID(value); });
Chris Lattner7f9cc272018-07-19 08:35:28 -0700665
Chris Lattnerf8cce872018-07-20 09:28:54 -0700666 os << ')';
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700667 auto attrs = op->getAttrs();
668 if (!attrs.empty()) {
669 os << '{';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700670 interleaveComma(attrs, [&](NamedAttribute attr) {
Chris Lattnerf8cce872018-07-20 09:28:54 -0700671 os << attr.first << ": ";
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700672 printAttribute(attr.second);
Chris Lattnerf8cce872018-07-20 09:28:54 -0700673 });
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700674 os << '}';
675 }
Chris Lattner3b2ef762018-07-18 15:31:25 -0700676
Chris Lattnerac591f12018-07-22 21:02:26 -0700677 // Print the type signature of the operation.
678 os << " : (";
679 interleaveComma(op->getOperands(),
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700680 [&](const SSAValue *value) { printType(value->getType()); });
Chris Lattnerac591f12018-07-22 21:02:26 -0700681 os << ") -> ";
Chris Lattnerf8cce872018-07-20 09:28:54 -0700682
Chris Lattnerac591f12018-07-22 21:02:26 -0700683 if (op->getNumResults() == 1) {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700684 printType(op->getResult(0)->getType());
Chris Lattnerac591f12018-07-22 21:02:26 -0700685 } else {
686 os << '(';
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700687 interleaveComma(op->getResults(), [&](const SSAValue *result) {
688 printType(result->getType());
689 });
Chris Lattnerac591f12018-07-22 21:02:26 -0700690 os << ')';
Chris Lattnerf8cce872018-07-20 09:28:54 -0700691 }
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700692}
693
Chris Lattner4c95a502018-06-23 16:03:42 -0700694//===----------------------------------------------------------------------===//
695// CFG Function printing
696//===----------------------------------------------------------------------===//
697
698namespace {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700699class CFGFunctionPrinter : public FunctionPrinter {
Chris Lattner4c95a502018-06-23 16:03:42 -0700700public:
Chris Lattner4fd59b02018-07-20 09:35:47 -0700701 CFGFunctionPrinter(const CFGFunction *function, const ModulePrinter &other);
Chris Lattner4c95a502018-06-23 16:03:42 -0700702
703 const CFGFunction *getFunction() const { return function; }
704
705 void print();
706 void print(const BasicBlock *block);
Chris Lattnered65a732018-06-28 20:45:33 -0700707
708 void print(const Instruction *inst);
709 void print(const OperationInst *inst);
710 void print(const ReturnInst *inst);
711 void print(const BranchInst *inst);
James Molloy4f788372018-07-24 15:01:27 -0700712 void print(const CondBranchInst *inst);
Chris Lattner4c95a502018-06-23 16:03:42 -0700713
714 unsigned getBBID(const BasicBlock *block) {
715 auto it = basicBlockIDs.find(block);
716 assert(it != basicBlockIDs.end() && "Block not in this function?");
717 return it->second;
718 }
719
720private:
721 const CFGFunction *function;
MLIR Team54b55a22018-07-18 10:16:05 -0700722 DenseMap<const BasicBlock *, unsigned> basicBlockIDs;
Chris Lattnerf8cce872018-07-20 09:28:54 -0700723
Chris Lattner4fd59b02018-07-20 09:35:47 -0700724 void numberValuesInBlock(const BasicBlock *block);
Chris Lattner4c95a502018-06-23 16:03:42 -0700725};
James Molloy87d81022018-07-23 11:44:40 -0700726} // end anonymous namespace
Chris Lattner4c95a502018-06-23 16:03:42 -0700727
Chris Lattner4fd59b02018-07-20 09:35:47 -0700728CFGFunctionPrinter::CFGFunctionPrinter(const CFGFunction *function,
729 const ModulePrinter &other)
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700730 : FunctionPrinter(other), function(function) {
Chris Lattner4c95a502018-06-23 16:03:42 -0700731 // Each basic block gets a unique ID per function.
732 unsigned blockID = 0;
Chris Lattnerf8cce872018-07-20 09:28:54 -0700733 for (auto &block : *function) {
734 basicBlockIDs[&block] = blockID++;
Chris Lattner4fd59b02018-07-20 09:35:47 -0700735 numberValuesInBlock(&block);
Chris Lattnerf8cce872018-07-20 09:28:54 -0700736 }
737}
738
739/// Number all of the SSA values in the specified basic block.
Chris Lattner4fd59b02018-07-20 09:35:47 -0700740void CFGFunctionPrinter::numberValuesInBlock(const BasicBlock *block) {
James Molloy61a656c2018-07-22 15:45:24 -0700741 for (auto *arg : block->getArguments()) {
742 numberValueID(arg);
743 }
Chris Lattnerf8cce872018-07-20 09:28:54 -0700744 for (auto &op : *block) {
745 // We number instruction that have results, and we only number the first
746 // result.
747 if (op.getNumResults() != 0)
748 numberValueID(op.getResult(0));
749 }
750
751 // Terminators do not define values.
Chris Lattner4c95a502018-06-23 16:03:42 -0700752}
753
Chris Lattner4fd59b02018-07-20 09:35:47 -0700754void CFGFunctionPrinter::print() {
Chris Lattner4c95a502018-06-23 16:03:42 -0700755 os << "cfgfunc ";
Chris Lattner4fd59b02018-07-20 09:35:47 -0700756 printFunctionSignature(getFunction());
Chris Lattner4c95a502018-06-23 16:03:42 -0700757 os << " {\n";
758
James Molloy87d81022018-07-23 11:44:40 -0700759 for (auto &block : *function)
760 print(&block);
Chris Lattner4c95a502018-06-23 16:03:42 -0700761 os << "}\n\n";
762}
763
Chris Lattner4fd59b02018-07-20 09:35:47 -0700764void CFGFunctionPrinter::print(const BasicBlock *block) {
James Molloy61a656c2018-07-22 15:45:24 -0700765 os << "bb" << getBBID(block);
Chris Lattner4c95a502018-06-23 16:03:42 -0700766
James Molloy61a656c2018-07-22 15:45:24 -0700767 if (!block->args_empty()) {
768 os << '(';
769 interleaveComma(block->getArguments(), [&](const BBArgument *arg) {
770 printValueID(arg);
771 os << ": ";
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700772 printType(arg->getType());
James Molloy61a656c2018-07-22 15:45:24 -0700773 });
774 os << ')';
775 }
Chris Lattner25ce3062018-07-27 11:10:12 -0700776 os << ':';
777
778 // Print out some context information about the predecessors of this block.
779 if (!block->getFunction()) {
780 os << "\t// block is not in a function!";
781 } else if (block->hasNoPredecessors()) {
782 // Don't print "no predecessors" for the entry block.
783 if (block != &block->getFunction()->front())
784 os << "\t// no predecessors";
785 } else if (auto *pred = block->getSinglePredecessor()) {
786 os << "\t// pred: bb" << getBBID(pred);
787 } else {
788 // We want to print the predecessors in increasing numeric order, not in
789 // whatever order the use-list is in, so gather and sort them.
790 SmallVector<unsigned, 4> predIDs;
791 for (auto *pred : block->getPredecessors())
792 predIDs.push_back(getBBID(pred));
793 llvm::array_pod_sort(predIDs.begin(), predIDs.end());
794
795 os << "\t// " << predIDs.size() << " preds: ";
796
797 interleaveComma(predIDs, [&](unsigned predID) { os << "bb" << predID; });
798 }
799 os << '\n';
James Molloy61a656c2018-07-22 15:45:24 -0700800
Jacques Pienaarb020c542018-07-15 00:06:54 -0700801 for (auto &inst : block->getOperations()) {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -0700802 os << " ";
Chris Lattner3a467cc2018-07-01 20:28:00 -0700803 print(&inst);
James Molloy61a656c2018-07-22 15:45:24 -0700804 os << '\n';
Jacques Pienaarb020c542018-07-15 00:06:54 -0700805 }
Chris Lattner4c95a502018-06-23 16:03:42 -0700806
807 print(block->getTerminator());
James Molloy61a656c2018-07-22 15:45:24 -0700808 os << '\n';
Chris Lattner4c95a502018-06-23 16:03:42 -0700809}
810
Chris Lattner4fd59b02018-07-20 09:35:47 -0700811void CFGFunctionPrinter::print(const Instruction *inst) {
Chris Lattner4c95a502018-06-23 16:03:42 -0700812 switch (inst->getKind()) {
Chris Lattnered65a732018-06-28 20:45:33 -0700813 case Instruction::Kind::Operation:
814 return print(cast<OperationInst>(inst));
Chris Lattnerf6d80a02018-06-24 11:18:29 -0700815 case TerminatorInst::Kind::Branch:
Chris Lattnered65a732018-06-28 20:45:33 -0700816 return print(cast<BranchInst>(inst));
James Molloy4f788372018-07-24 15:01:27 -0700817 case TerminatorInst::Kind::CondBranch:
818 return print(cast<CondBranchInst>(inst));
Chris Lattner4c95a502018-06-23 16:03:42 -0700819 case TerminatorInst::Kind::Return:
Chris Lattnered65a732018-06-28 20:45:33 -0700820 return print(cast<ReturnInst>(inst));
Chris Lattner4c95a502018-06-23 16:03:42 -0700821 }
822}
823
Chris Lattner4fd59b02018-07-20 09:35:47 -0700824void CFGFunctionPrinter::print(const OperationInst *inst) {
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700825 printOperation(inst);
Chris Lattner3b2ef762018-07-18 15:31:25 -0700826}
Chris Lattner1604e472018-07-23 08:42:19 -0700827
Chris Lattner4fd59b02018-07-20 09:35:47 -0700828void CFGFunctionPrinter::print(const BranchInst *inst) {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -0700829 os << "br bb" << getBBID(inst->getDest());
Chris Lattner1604e472018-07-23 08:42:19 -0700830
831 if (inst->getNumOperands() != 0) {
832 os << '(';
833 // TODO: Use getOperands() when we have it.
834 interleaveComma(inst->getInstOperands(), [&](const InstOperand &operand) {
835 printValueID(operand.get());
836 });
837 os << ") : ";
838 interleaveComma(inst->getInstOperands(), [&](const InstOperand &operand) {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700839 printType(operand.get()->getType());
Chris Lattner1604e472018-07-23 08:42:19 -0700840 });
841 }
Chris Lattnered65a732018-06-28 20:45:33 -0700842}
Chris Lattner1604e472018-07-23 08:42:19 -0700843
James Molloy4f788372018-07-24 15:01:27 -0700844void CFGFunctionPrinter::print(const CondBranchInst *inst) {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -0700845 os << "cond_br ";
James Molloy4f788372018-07-24 15:01:27 -0700846 printValueID(inst->getCondition());
847
848 os << ", bb" << getBBID(inst->getTrueDest());
849 if (inst->getNumTrueOperands() != 0) {
850 os << '(';
851 interleaveComma(inst->getTrueOperands(),
852 [&](const CFGValue *operand) { printValueID(operand); });
853 os << " : ";
854 interleaveComma(inst->getTrueOperands(), [&](const CFGValue *operand) {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700855 printType(operand->getType());
James Molloy4f788372018-07-24 15:01:27 -0700856 });
857 os << ")";
858 }
859
860 os << ", bb" << getBBID(inst->getFalseDest());
861 if (inst->getNumFalseOperands() != 0) {
862 os << '(';
863 interleaveComma(inst->getFalseOperands(),
864 [&](const CFGValue *operand) { printValueID(operand); });
865 os << " : ";
866 interleaveComma(inst->getFalseOperands(), [&](const CFGValue *operand) {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700867 printType(operand->getType());
James Molloy4f788372018-07-24 15:01:27 -0700868 });
869 os << ")";
870 }
871}
872
Chris Lattner40746442018-07-21 14:32:09 -0700873void CFGFunctionPrinter::print(const ReturnInst *inst) {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -0700874 os << "return";
Chris Lattner40746442018-07-21 14:32:09 -0700875
876 if (inst->getNumOperands() != 0)
877 os << ' ';
878
James Molloy4f788372018-07-24 15:01:27 -0700879 interleaveComma(inst->getOperands(),
880 [&](const CFGValue *operand) { printValueID(operand); });
881 os << " : ";
Chris Lattnerac591f12018-07-22 21:02:26 -0700882 interleaveComma(inst->getOperands(), [&](const CFGValue *operand) {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700883 printType(operand->getType());
Chris Lattner40746442018-07-21 14:32:09 -0700884 });
885}
MLIR Team54b55a22018-07-18 10:16:05 -0700886
Chris Lattner4fd59b02018-07-20 09:35:47 -0700887void ModulePrinter::print(const CFGFunction *fn) {
888 CFGFunctionPrinter(fn, *this).print();
Chris Lattnered65a732018-06-28 20:45:33 -0700889}
890
Chris Lattner4c95a502018-06-23 16:03:42 -0700891//===----------------------------------------------------------------------===//
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700892// ML Function printing
Chris Lattner4c95a502018-06-23 16:03:42 -0700893//===----------------------------------------------------------------------===//
894
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700895namespace {
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700896class MLFunctionPrinter : public FunctionPrinter {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700897public:
Chris Lattner4fd59b02018-07-20 09:35:47 -0700898 MLFunctionPrinter(const MLFunction *function, const ModulePrinter &other);
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700899
900 const MLFunction *getFunction() const { return function; }
901
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700902 // Prints ML function
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700903 void print();
904
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700905 // Methods to print ML function statements
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700906 void print(const Statement *stmt);
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700907 void print(const OperationStmt *stmt);
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700908 void print(const ForStmt *stmt);
909 void print(const IfStmt *stmt);
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700910 void print(const StmtBlock *block);
911
912 // Number of spaces used for indenting nested statements
913 const static unsigned indentWidth = 2;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700914
915private:
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -0700916 void numberValues();
917
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700918 const MLFunction *function;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700919 int numSpaces;
920};
James Molloy87d81022018-07-23 11:44:40 -0700921} // end anonymous namespace
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700922
Chris Lattner4fd59b02018-07-20 09:35:47 -0700923MLFunctionPrinter::MLFunctionPrinter(const MLFunction *function,
924 const ModulePrinter &other)
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -0700925 : FunctionPrinter(other), function(function), numSpaces(0) {
926 numberValues();
927}
928
929/// Number all of the SSA values in this ML function.
930void MLFunctionPrinter::numberValues() {
931 // Visits all operation statements and numbers the first result.
Uday Bondhugula081d9e72018-07-27 10:58:14 -0700932 struct NumberValuesPass : public StmtWalker<NumberValuesPass> {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -0700933 NumberValuesPass(MLFunctionPrinter *printer) : printer(printer) {}
934 void visitOperationStmt(OperationStmt *stmt) {
935 if (stmt->getNumResults() != 0)
936 printer->numberValueID(stmt->getResult(0));
937 }
Tatiana Shpeismanc9c4b342018-07-31 07:40:14 -0700938 void visitForStmt(ForStmt *stmt) { printer->numberValueID(stmt); }
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -0700939 MLFunctionPrinter *printer;
940 };
941
942 NumberValuesPass pass(this);
943 // TODO: it'd be cleaner to have constant visitor istead of using const_cast.
Uday Bondhugula081d9e72018-07-27 10:58:14 -0700944 pass.walk(const_cast<MLFunction *>(function));
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -0700945}
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700946
Chris Lattner4fd59b02018-07-20 09:35:47 -0700947void MLFunctionPrinter::print() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700948 os << "mlfunc ";
949 // FIXME: should print argument names rather than just signature
Chris Lattner4fd59b02018-07-20 09:35:47 -0700950 printFunctionSignature(function);
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700951 os << " {\n";
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700952 print(function);
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700953 os << " return\n";
954 os << "}\n\n";
955}
956
Chris Lattner4fd59b02018-07-20 09:35:47 -0700957void MLFunctionPrinter::print(const StmtBlock *block) {
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700958 numSpaces += indentWidth;
Jacques Pienaarb020c542018-07-15 00:06:54 -0700959 for (auto &stmt : block->getStatements()) {
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700960 print(&stmt);
Jacques Pienaarb020c542018-07-15 00:06:54 -0700961 os << "\n";
962 }
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700963 numSpaces -= indentWidth;
964}
965
Chris Lattner4fd59b02018-07-20 09:35:47 -0700966void MLFunctionPrinter::print(const Statement *stmt) {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700967 switch (stmt->getKind()) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -0700968 case Statement::Kind::Operation:
969 return print(cast<OperationStmt>(stmt));
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700970 case Statement::Kind::For:
971 return print(cast<ForStmt>(stmt));
972 case Statement::Kind::If:
973 return print(cast<IfStmt>(stmt));
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700974 }
975}
976
Chris Lattner4fd59b02018-07-20 09:35:47 -0700977void MLFunctionPrinter::print(const OperationStmt *stmt) {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -0700978 os.indent(numSpaces);
Chris Lattner4fd59b02018-07-20 09:35:47 -0700979 printOperation(stmt);
980}
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700981
Chris Lattner4fd59b02018-07-20 09:35:47 -0700982void MLFunctionPrinter::print(const ForStmt *stmt) {
Tatiana Shpeisman3838db72018-07-30 15:18:10 -0700983 os.indent(numSpaces) << "for ";
Tatiana Shpeismanc9c4b342018-07-31 07:40:14 -0700984 printOperand(stmt);
Tatiana Shpeisman3838db72018-07-30 15:18:10 -0700985 os << " = " << *stmt->getLowerBound();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -0700986 os << " to " << *stmt->getUpperBound();
987 if (stmt->getStep()->getValue() != 1)
988 os << " step " << *stmt->getStep();
989
990 os << " {\n";
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700991 print(static_cast<const StmtBlock *>(stmt));
Tatiana Shpeisman565b9642018-07-16 11:47:09 -0700992 os.indent(numSpaces) << "}";
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700993}
994
Chris Lattner4fd59b02018-07-20 09:35:47 -0700995void MLFunctionPrinter::print(const IfStmt *stmt) {
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700996 os.indent(numSpaces) << "if () {\n";
997 print(stmt->getThenClause());
998 os.indent(numSpaces) << "}";
999 if (stmt->hasElseClause()) {
1000 os << " else {\n";
1001 print(stmt->getElseClause());
1002 os.indent(numSpaces) << "}";
1003 }
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001004}
1005
Chris Lattner4fd59b02018-07-20 09:35:47 -07001006void ModulePrinter::print(const MLFunction *fn) {
1007 MLFunctionPrinter(fn, *this).print();
MLIR Team4718bc92018-07-17 16:56:54 -07001008}
1009
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001010//===----------------------------------------------------------------------===//
1011// print and dump methods
1012//===----------------------------------------------------------------------===//
Chris Lattnered65a732018-06-28 20:45:33 -07001013
MLIR Teamb61885d2018-07-18 16:29:21 -07001014void Attribute::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -07001015 ModuleState state(/*no context is known*/ nullptr);
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -07001016 ModulePrinter(os, state).printAttribute(this);
MLIR Teamb61885d2018-07-18 16:29:21 -07001017}
1018
James Molloy87d81022018-07-23 11:44:40 -07001019void Attribute::dump() const { print(llvm::errs()); }
MLIR Teamb61885d2018-07-18 16:29:21 -07001020
MLIR Team4718bc92018-07-17 16:56:54 -07001021void Type::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -07001022 ModuleState state(getContext());
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -07001023 ModulePrinter(os, state).printType(this);
MLIR Team4718bc92018-07-17 16:56:54 -07001024}
1025
MLIR Team54b55a22018-07-18 10:16:05 -07001026void Type::dump() const { print(llvm::errs()); }
MLIR Team4718bc92018-07-17 16:56:54 -07001027
MLIR Team718c82f2018-07-16 09:45:22 -07001028void AffineMap::dump() const {
1029 print(llvm::errs());
1030 llvm::errs() << "\n";
1031}
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001032
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001033void AffineExpr::dump() const {
1034 print(llvm::errs());
1035 llvm::errs() << "\n";
1036}
1037
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001038void AffineExpr::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -07001039 ModuleState state(/*no context is known*/ nullptr);
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -07001040 ModulePrinter(os, state).printAffineExpr(this);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001041}
1042
1043void AffineMap::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -07001044 ModuleState state(/*no context is known*/ nullptr);
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -07001045 ModulePrinter(os, state).printAffineMap(this);
Chris Lattner4fd59b02018-07-20 09:35:47 -07001046}
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001047
Chris Lattner4fd59b02018-07-20 09:35:47 -07001048void Instruction::print(raw_ostream &os) const {
1049 ModuleState state(getFunction()->getContext());
1050 ModulePrinter modulePrinter(os, state);
1051 CFGFunctionPrinter(getFunction(), modulePrinter).print(this);
1052}
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001053
Chris Lattner4fd59b02018-07-20 09:35:47 -07001054void Instruction::dump() const {
1055 print(llvm::errs());
1056 llvm::errs() << "\n";
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001057}
1058
Chris Lattner4c95a502018-06-23 16:03:42 -07001059void BasicBlock::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -07001060 ModuleState state(getFunction()->getContext());
1061 ModulePrinter modulePrinter(os, state);
1062 CFGFunctionPrinter(getFunction(), modulePrinter).print(this);
Chris Lattner4c95a502018-06-23 16:03:42 -07001063}
1064
MLIR Team54b55a22018-07-18 10:16:05 -07001065void BasicBlock::dump() const { print(llvm::errs()); }
Chris Lattner4c95a502018-06-23 16:03:42 -07001066
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001067void Statement::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -07001068 ModuleState state(getFunction()->getContext());
1069 ModulePrinter modulePrinter(os, state);
1070 MLFunctionPrinter(getFunction(), modulePrinter).print(this);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001071}
1072
MLIR Team54b55a22018-07-18 10:16:05 -07001073void Statement::dump() const { print(llvm::errs()); }
Jacques Pienaarb020c542018-07-15 00:06:54 -07001074
Chris Lattner4c95a502018-06-23 16:03:42 -07001075void Function::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -07001076 ModuleState state(getContext());
1077 ModulePrinter(os, state).print(this);
Chris Lattner4c95a502018-06-23 16:03:42 -07001078}
1079
MLIR Team54b55a22018-07-18 10:16:05 -07001080void Function::dump() const { print(llvm::errs()); }
1081
Chris Lattner4c95a502018-06-23 16:03:42 -07001082void Module::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -07001083 ModuleState state(getContext());
1084 state.initialize(this);
1085 ModulePrinter(os, state).print(this);
Chris Lattner4c95a502018-06-23 16:03:42 -07001086}
1087
MLIR Team54b55a22018-07-18 10:16:05 -07001088void Module::dump() const { print(llvm::errs()); }