blob: 1d61213b94d3446c91a7691a31901ae3ac6dc96a [file] [log] [blame]
Chris Lattner4c95a502018-06-23 16:03:42 -07001//===- AsmPrinter.cpp - MLIR Assembly Printer Implementation --------------===//
2//
3// Copyright 2019 The MLIR Authors.
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16// =============================================================================
17//
18// This file implements the MLIR AsmPrinter class, which is used to implement
19// the various print() methods on the core IR objects.
20//
21//===----------------------------------------------------------------------===//
22
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -070023#include "mlir/IR/AffineExpr.h"
24#include "mlir/IR/AffineMap.h"
Chris Lattner7121b802018-07-04 20:45:39 -070025#include "mlir/IR/Attributes.h"
Chris Lattner4c95a502018-06-23 16:03:42 -070026#include "mlir/IR/CFGFunction.h"
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -070027#include "mlir/IR/MLFunction.h"
Chris Lattner4c95a502018-06-23 16:03:42 -070028#include "mlir/IR/Module.h"
Chris Lattnerff0d5902018-07-05 09:12:11 -070029#include "mlir/IR/OperationSet.h"
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -070030#include "mlir/IR/Statements.h"
Chris Lattner4c95a502018-06-23 16:03:42 -070031#include "mlir/IR/Types.h"
32#include "mlir/Support/STLExtras.h"
Chris Lattner4c95a502018-06-23 16:03:42 -070033#include "llvm/ADT/DenseMap.h"
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -070034#include "llvm/Support/raw_ostream.h"
Chris Lattner4c95a502018-06-23 16:03:42 -070035using namespace mlir;
36
MLIR Team54b55a22018-07-18 10:16:05 -070037void Identifier::print(raw_ostream &os) const { os << str(); }
Chris Lattner4c95a502018-06-23 16:03:42 -070038
MLIR Team54b55a22018-07-18 10:16:05 -070039void Identifier::dump() const { print(llvm::errs()); }
Chris Lattner7121b802018-07-04 20:45:39 -070040
Chris Lattner4c95a502018-06-23 16:03:42 -070041//===----------------------------------------------------------------------===//
Chris Lattner4fd59b02018-07-20 09:35:47 -070042// ModuleState
MLIR Team4718bc92018-07-17 16:56:54 -070043//===----------------------------------------------------------------------===//
44
45namespace {
MLIR Team54b55a22018-07-18 10:16:05 -070046class ModuleState {
47public:
Chris Lattner4fd59b02018-07-20 09:35:47 -070048 /// This is the operation set for the current context if it is knowable (a
49 /// context could be determined), otherwise this is null.
50 OperationSet *const operationSet;
MLIR Team4718bc92018-07-17 16:56:54 -070051
Chris Lattner4fd59b02018-07-20 09:35:47 -070052 explicit ModuleState(MLIRContext *context)
53 : operationSet(context ? &OperationSet::get(context) : nullptr) {}
54
55 // Initializes module state, populating affine map state.
MLIR Team4718bc92018-07-17 16:56:54 -070056 void initialize(const Module *module);
57
MLIR Team54b55a22018-07-18 10:16:05 -070058 int getAffineMapId(const AffineMap *affineMap) const {
MLIR Team4718bc92018-07-17 16:56:54 -070059 auto it = affineMapIds.find(affineMap);
60 if (it == affineMapIds.end()) {
61 return -1;
62 }
63 return it->second;
64 }
65
James Molloyc4666722018-07-24 09:48:31 -070066 ArrayRef<const AffineMap *> getAffineMapIds() const { return affineMapsById; }
Chris Lattner4fd59b02018-07-20 09:35:47 -070067
MLIR Team54b55a22018-07-18 10:16:05 -070068private:
Chris Lattner4fd59b02018-07-20 09:35:47 -070069 void recordAffineMapReference(const AffineMap *affineMap) {
70 if (affineMapIds.count(affineMap) == 0) {
James Molloyc4666722018-07-24 09:48:31 -070071 affineMapIds[affineMap] = affineMapsById.size();
72 affineMapsById.push_back(affineMap);
Chris Lattner4fd59b02018-07-20 09:35:47 -070073 }
74 }
75
MLIR Team4718bc92018-07-17 16:56:54 -070076 // Visit functions.
77 void visitFunction(const Function *fn);
78 void visitExtFunction(const ExtFunction *fn);
79 void visitCFGFunction(const CFGFunction *fn);
80 void visitMLFunction(const MLFunction *fn);
81 void visitType(const Type *type);
MLIR Teamb61885d2018-07-18 16:29:21 -070082 void visitAttribute(const Attribute *attr);
83 void visitOperation(const Operation *op);
84
MLIR Team54b55a22018-07-18 10:16:05 -070085 DenseMap<const AffineMap *, int> affineMapIds;
James Molloyc4666722018-07-24 09:48:31 -070086 std::vector<const AffineMap *> affineMapsById;
MLIR Team4718bc92018-07-17 16:56:54 -070087};
James Molloy87d81022018-07-23 11:44:40 -070088} // end anonymous namespace
MLIR Team4718bc92018-07-17 16:56:54 -070089
90// TODO Support visiting other types/instructions when implemented.
91void ModuleState::visitType(const Type *type) {
92 if (type->getKind() == Type::Kind::Function) {
93 // Visit input and result types for functions.
94 auto *funcType = cast<FunctionType>(type);
MLIR Team54b55a22018-07-18 10:16:05 -070095 for (auto *input : funcType->getInputs()) {
MLIR Team4718bc92018-07-17 16:56:54 -070096 visitType(input);
97 }
MLIR Team54b55a22018-07-18 10:16:05 -070098 for (auto *result : funcType->getResults()) {
MLIR Team4718bc92018-07-17 16:56:54 -070099 visitType(result);
100 }
101 } else if (type->getKind() == Type::Kind::MemRef) {
102 // Visit affine maps in memref type.
103 auto *memref = cast<MemRefType>(type);
MLIR Team54b55a22018-07-18 10:16:05 -0700104 for (AffineMap *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) {
111 if (isa<AffineMapAttr>(attr)) {
112 recordAffineMapReference(cast<AffineMapAttr>(attr)->getValue());
113 } else if (isa<ArrayAttr>(attr)) {
114 for (auto elt : cast<ArrayAttr>(attr)->getValue()) {
115 visitAttribute(elt);
116 }
117 }
118}
119
120void ModuleState::visitOperation(const Operation *op) {
121 for (auto elt : op->getAttrs()) {
122 visitAttribute(elt.second);
123 }
124}
125
MLIR Team4718bc92018-07-17 16:56:54 -0700126void ModuleState::visitExtFunction(const ExtFunction *fn) {
127 visitType(fn->getType());
128}
129
130void ModuleState::visitCFGFunction(const CFGFunction *fn) {
131 visitType(fn->getType());
MLIR Teamb61885d2018-07-18 16:29:21 -0700132 for (auto &block : *fn) {
133 for (auto &op : block.getOperations()) {
134 visitOperation(&op);
135 }
136 }
MLIR Team4718bc92018-07-17 16:56:54 -0700137}
138
139void ModuleState::visitMLFunction(const MLFunction *fn) {
140 visitType(fn->getType());
MLIR Teamb61885d2018-07-18 16:29:21 -0700141 // TODO Visit function body statements (and attributes if required).
MLIR Team4718bc92018-07-17 16:56:54 -0700142}
143
144void ModuleState::visitFunction(const Function *fn) {
145 switch (fn->getKind()) {
MLIR Team54b55a22018-07-18 10:16:05 -0700146 case Function::Kind::ExtFunc:
147 return visitExtFunction(cast<ExtFunction>(fn));
148 case Function::Kind::CFGFunc:
149 return visitCFGFunction(cast<CFGFunction>(fn));
150 case Function::Kind::MLFunc:
151 return visitMLFunction(cast<MLFunction>(fn));
MLIR Team4718bc92018-07-17 16:56:54 -0700152 }
153}
154
Chris Lattner4fd59b02018-07-20 09:35:47 -0700155// Initializes module state, populating affine map state.
156void ModuleState::initialize(const Module *module) {
157 for (auto fn : module->functionList) {
158 visitFunction(fn);
159 }
160}
161
162//===----------------------------------------------------------------------===//
163// ModulePrinter
164//===----------------------------------------------------------------------===//
165
166namespace {
167class ModulePrinter {
168public:
169 ModulePrinter(raw_ostream &os, ModuleState &state) : os(os), state(state) {}
170 explicit ModulePrinter(const ModulePrinter &printer)
171 : os(printer.os), state(printer.state) {}
172
173 template <typename Container, typename UnaryFunctor>
174 inline void interleaveComma(const Container &c, UnaryFunctor each_fn) const {
175 interleave(c.begin(), c.end(), each_fn, [&]() { os << ", "; });
176 }
177
178 void print(const Module *module);
179 void print(const Attribute *attr) const;
180 void print(const Type *type) const;
181 void print(const Function *fn);
182 void print(const ExtFunction *fn);
183 void print(const CFGFunction *fn);
184 void print(const MLFunction *fn);
185
186 void print(const AffineMap *map);
187 void print(const AffineExpr *expr) const;
188
189protected:
190 raw_ostream &os;
191 ModuleState &state;
192
193 void printFunctionSignature(const Function *fn);
194 void printAffineMapId(int affineMapId) const;
195 void printAffineMapReference(const AffineMap *affineMap) const;
196
197 void print(const AffineBinaryOpExpr *expr) const;
198};
199} // end anonymous namespace
200
MLIR Team4718bc92018-07-17 16:56:54 -0700201// Prints function with initialized module state.
Chris Lattner4fd59b02018-07-20 09:35:47 -0700202void ModulePrinter::print(const Function *fn) {
MLIR Team4718bc92018-07-17 16:56:54 -0700203 switch (fn->getKind()) {
MLIR Team54b55a22018-07-18 10:16:05 -0700204 case Function::Kind::ExtFunc:
205 return print(cast<ExtFunction>(fn));
206 case Function::Kind::CFGFunc:
207 return print(cast<CFGFunction>(fn));
208 case Function::Kind::MLFunc:
209 return print(cast<MLFunction>(fn));
MLIR Team4718bc92018-07-17 16:56:54 -0700210 }
211}
212
213// Prints affine map identifier.
Chris Lattner4fd59b02018-07-20 09:35:47 -0700214void ModulePrinter::printAffineMapId(int affineMapId) const {
MLIR Team4718bc92018-07-17 16:56:54 -0700215 os << "#map" << affineMapId;
216}
217
Chris Lattner4fd59b02018-07-20 09:35:47 -0700218void ModulePrinter::printAffineMapReference(const AffineMap *affineMap) const {
219 int mapId = state.getAffineMapId(affineMap);
MLIR Teamb61885d2018-07-18 16:29:21 -0700220 if (mapId >= 0) {
221 // Map will be printed at top of module so print reference to its id.
222 printAffineMapId(mapId);
223 } else {
224 // Map not in module state so print inline.
225 affineMap->print(os);
226 }
227}
228
Chris Lattner4fd59b02018-07-20 09:35:47 -0700229void ModulePrinter::print(const Module *module) {
James Molloyc4666722018-07-24 09:48:31 -0700230 for (const auto &map : state.getAffineMapIds()) {
231 printAffineMapId(state.getAffineMapId(map));
MLIR Team4718bc92018-07-17 16:56:54 -0700232 os << " = ";
James Molloyc4666722018-07-24 09:48:31 -0700233 map->print(os);
MLIR Team4718bc92018-07-17 16:56:54 -0700234 os << '\n';
235 }
James Molloy87d81022018-07-23 11:44:40 -0700236 for (auto *fn : module->functionList)
237 print(fn);
MLIR Team4718bc92018-07-17 16:56:54 -0700238}
239
Chris Lattner4fd59b02018-07-20 09:35:47 -0700240void ModulePrinter::print(const Attribute *attr) const {
MLIR Teamb61885d2018-07-18 16:29:21 -0700241 switch (attr->getKind()) {
242 case Attribute::Kind::Bool:
243 os << (cast<BoolAttr>(attr)->getValue() ? "true" : "false");
244 break;
245 case Attribute::Kind::Integer:
246 os << cast<IntegerAttr>(attr)->getValue();
247 break;
248 case Attribute::Kind::Float:
249 // FIXME: this isn't precise, we should print with a hex format.
250 os << cast<FloatAttr>(attr)->getValue();
251 break;
252 case Attribute::Kind::String:
253 // FIXME: should escape the string.
254 os << '"' << cast<StringAttr>(attr)->getValue() << '"';
255 break;
256 case Attribute::Kind::Array: {
257 auto elts = cast<ArrayAttr>(attr)->getValue();
258 os << '[';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700259 interleaveComma(elts, [&](Attribute *attr) { print(attr); });
MLIR Teamb61885d2018-07-18 16:29:21 -0700260 os << ']';
261 break;
262 }
263 case Attribute::Kind::AffineMap:
264 printAffineMapReference(cast<AffineMapAttr>(attr)->getValue());
265 break;
266 }
267}
268
Chris Lattner4fd59b02018-07-20 09:35:47 -0700269void ModulePrinter::print(const Type *type) const {
MLIR Team4718bc92018-07-17 16:56:54 -0700270 switch (type->getKind()) {
MLIR Team54b55a22018-07-18 10:16:05 -0700271 case Type::Kind::AffineInt:
272 os << "affineint";
273 return;
274 case Type::Kind::BF16:
275 os << "bf16";
276 return;
277 case Type::Kind::F16:
278 os << "f16";
279 return;
280 case Type::Kind::F32:
281 os << "f32";
282 return;
283 case Type::Kind::F64:
284 os << "f64";
285 return;
MLIR Team4718bc92018-07-17 16:56:54 -0700286
287 case Type::Kind::Integer: {
288 auto *integer = cast<IntegerType>(type);
289 os << 'i' << integer->getWidth();
290 return;
291 }
292 case Type::Kind::Function: {
293 auto *func = cast<FunctionType>(type);
294 os << '(';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700295 interleaveComma(func->getInputs(), [&](Type *type) { os << *type; });
MLIR Team4718bc92018-07-17 16:56:54 -0700296 os << ") -> ";
297 auto results = func->getResults();
298 if (results.size() == 1)
299 os << *results[0];
300 else {
301 os << '(';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700302 interleaveComma(results, [&](Type *type) { os << *type; });
MLIR Team4718bc92018-07-17 16:56:54 -0700303 os << ')';
304 }
305 return;
306 }
307 case Type::Kind::Vector: {
308 auto *v = cast<VectorType>(type);
309 os << "vector<";
James Molloy87d81022018-07-23 11:44:40 -0700310 for (auto dim : v->getShape())
311 os << dim << 'x';
MLIR Team4718bc92018-07-17 16:56:54 -0700312 os << *v->getElementType() << '>';
313 return;
314 }
315 case Type::Kind::RankedTensor: {
316 auto *v = cast<RankedTensorType>(type);
317 os << "tensor<";
318 for (auto dim : v->getShape()) {
319 if (dim < 0)
320 os << '?';
321 else
322 os << dim;
323 os << 'x';
324 }
325 os << *v->getElementType() << '>';
326 return;
327 }
328 case Type::Kind::UnrankedTensor: {
329 auto *v = cast<UnrankedTensorType>(type);
330 os << "tensor<??" << *v->getElementType() << '>';
331 return;
332 }
333 case Type::Kind::MemRef: {
334 auto *v = cast<MemRefType>(type);
335 os << "memref<";
336 for (auto dim : v->getShape()) {
337 if (dim < 0)
338 os << '?';
339 else
340 os << dim;
341 os << 'x';
342 }
343 os << *v->getElementType();
344 for (auto map : v->getAffineMaps()) {
345 os << ", ";
MLIR Teamb61885d2018-07-18 16:29:21 -0700346 printAffineMapReference(map);
MLIR Team4718bc92018-07-17 16:56:54 -0700347 }
348 os << ", " << v->getMemorySpace();
349 os << '>';
350 return;
351 }
352 }
353}
354
355//===----------------------------------------------------------------------===//
Chris Lattner4fd59b02018-07-20 09:35:47 -0700356// Affine expressions and maps
357//===----------------------------------------------------------------------===//
358
359void ModulePrinter::print(const AffineExpr *expr) const {
360 switch (expr->getKind()) {
361 case AffineExpr::Kind::SymbolId:
362 os << 's' << cast<AffineSymbolExpr>(expr)->getPosition();
363 return;
364 case AffineExpr::Kind::DimId:
365 os << 'd' << cast<AffineDimExpr>(expr)->getPosition();
366 return;
367 case AffineExpr::Kind::Constant:
368 os << cast<AffineConstantExpr>(expr)->getValue();
369 return;
370 case AffineExpr::Kind::Add:
371 case AffineExpr::Kind::Mul:
372 case AffineExpr::Kind::FloorDiv:
373 case AffineExpr::Kind::CeilDiv:
374 case AffineExpr::Kind::Mod:
375 return print(cast<AffineBinaryOpExpr>(expr));
376 }
377}
378
379void ModulePrinter::print(const AffineBinaryOpExpr *expr) const {
380 if (expr->getKind() != AffineExpr::Kind::Add) {
381 os << '(';
382 print(expr->getLHS());
383 switch (expr->getKind()) {
384 case AffineExpr::Kind::Mul:
385 os << " * ";
386 break;
387 case AffineExpr::Kind::FloorDiv:
388 os << " floordiv ";
389 break;
390 case AffineExpr::Kind::CeilDiv:
391 os << " ceildiv ";
392 break;
393 case AffineExpr::Kind::Mod:
394 os << " mod ";
395 break;
396 default:
397 llvm_unreachable("unexpected affine binary op expression");
398 }
399
400 print(expr->getRHS());
401 os << ')';
402 return;
403 }
404
405 // Print out special "pretty" forms for add.
406 os << '(';
407 print(expr->getLHS());
408
409 // Pretty print addition to a product that has a negative operand as a
410 // subtraction.
411 if (auto *rhs = dyn_cast<AffineBinaryOpExpr>(expr->getRHS())) {
412 if (rhs->getKind() == AffineExpr::Kind::Mul) {
413 if (auto *rrhs = dyn_cast<AffineConstantExpr>(rhs->getRHS())) {
414 if (rrhs->getValue() < 0) {
415 os << " - (";
416 print(rhs->getLHS());
417 os << " * " << -rrhs->getValue() << "))";
418 return;
419 }
420 }
421 }
422 }
423
424 // Pretty print addition to a negative number as a subtraction.
425 if (auto *rhs = dyn_cast<AffineConstantExpr>(expr->getRHS())) {
426 if (rhs->getValue() < 0) {
427 os << " - " << -rhs->getValue() << ")";
428 return;
429 }
430 }
431
432 os << " + ";
433 print(expr->getRHS());
434 os << ')';
435}
436
437void ModulePrinter::print(const AffineMap *map) {
438 // Dimension identifiers.
439 os << '(';
440 for (int i = 0; i < (int)map->getNumDims() - 1; i++)
441 os << "d" << i << ", ";
442 if (map->getNumDims() >= 1)
443 os << "d" << map->getNumDims() - 1;
444 os << ")";
445
446 // Symbolic identifiers.
447 if (map->getNumSymbols() >= 1) {
448 os << " [";
449 for (int i = 0; i < (int)map->getNumSymbols() - 1; i++)
450 os << "s" << i << ", ";
451 if (map->getNumSymbols() >= 1)
452 os << "s" << map->getNumSymbols() - 1;
453 os << "]";
454 }
455
456 // AffineMap should have at least one result.
457 assert(!map->getResults().empty());
458 // Result affine expressions.
459 os << " -> (";
460 interleaveComma(map->getResults(), [&](AffineExpr *expr) { print(expr); });
461 os << ")";
462
463 if (!map->isBounded()) {
464 return;
465 }
466
467 // Print range sizes for bounded affine maps.
468 os << " size (";
469 interleaveComma(map->getRangeSizes(), [&](AffineExpr *expr) { print(expr); });
470 os << ")";
471}
472
473//===----------------------------------------------------------------------===//
Chris Lattner4c95a502018-06-23 16:03:42 -0700474// Function printing
475//===----------------------------------------------------------------------===//
476
Chris Lattner4fd59b02018-07-20 09:35:47 -0700477void ModulePrinter::printFunctionSignature(const Function *fn) {
Chris Lattner4c95a502018-06-23 16:03:42 -0700478 auto type = fn->getType();
479
480 os << "@" << fn->getName() << '(';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700481 interleaveComma(type->getInputs(), [&](Type *eltType) { print(eltType); });
Chris Lattner4c95a502018-06-23 16:03:42 -0700482 os << ')';
483
484 switch (type->getResults().size()) {
MLIR Team54b55a22018-07-18 10:16:05 -0700485 case 0:
486 break;
Chris Lattner4c95a502018-06-23 16:03:42 -0700487 case 1:
MLIR Team4718bc92018-07-17 16:56:54 -0700488 os << " -> ";
Chris Lattner4fd59b02018-07-20 09:35:47 -0700489 print(type->getResults()[0]);
Chris Lattner4c95a502018-06-23 16:03:42 -0700490 break;
491 default:
492 os << " -> (";
Chris Lattner4fd59b02018-07-20 09:35:47 -0700493 interleaveComma(type->getResults(), [&](Type *eltType) { print(eltType); });
Chris Lattner4c95a502018-06-23 16:03:42 -0700494 os << ')';
495 break;
496 }
497}
498
Chris Lattner4fd59b02018-07-20 09:35:47 -0700499void ModulePrinter::print(const ExtFunction *fn) {
Chris Lattner4c95a502018-06-23 16:03:42 -0700500 os << "extfunc ";
Chris Lattner4fd59b02018-07-20 09:35:47 -0700501 printFunctionSignature(fn);
MLIR Team54b55a22018-07-18 10:16:05 -0700502 os << '\n';
Chris Lattner4c95a502018-06-23 16:03:42 -0700503}
504
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700505namespace {
506
507// FunctionState contains common functionality for printing
508// CFG and ML functions.
Chris Lattner4fd59b02018-07-20 09:35:47 -0700509class FunctionState : public ModulePrinter {
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700510public:
Chris Lattner4fd59b02018-07-20 09:35:47 -0700511 FunctionState(const ModulePrinter &other) : ModulePrinter(other) {}
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700512
513 void printOperation(const Operation *op);
514
515protected:
Chris Lattnerf8cce872018-07-20 09:28:54 -0700516 void numberValueID(const SSAValue *value) {
517 assert(!valueIDs.count(value) && "Value numbered multiple times");
518 valueIDs[value] = nextValueID++;
519 }
520
Chris Lattner6119d382018-07-20 18:41:34 -0700521 void printValueID(const SSAValue *value,
522 bool dontPrintResultNo = false) const {
523 int resultNo = -1;
524 auto lookupValue = value;
525
526 // If this is a reference to the result of a multi-result instruction, print
527 // out the # identifier and make sure to map our lookup to the first result
528 // of the instruction.
529 if (auto *result = dyn_cast<InstResult>(value)) {
530 if (result->getOwner()->getNumResults() != 1) {
531 resultNo = result->getResultNumber();
532 lookupValue = result->getOwner()->getResult(0);
533 }
534 }
535
536 auto it = valueIDs.find(lookupValue);
537 if (it == valueIDs.end()) {
Chris Lattnerf8cce872018-07-20 09:28:54 -0700538 os << "<<INVALID SSA VALUE>>";
Chris Lattner6119d382018-07-20 18:41:34 -0700539 return;
540 }
541
542 os << '%' << it->getSecond();
543 if (resultNo != -1 && !dontPrintResultNo)
544 os << '#' << resultNo;
Chris Lattnerf8cce872018-07-20 09:28:54 -0700545 }
546
547private:
548 /// This is the value ID for each SSA value in the current function.
549 DenseMap<const SSAValue *, unsigned> valueIDs;
550 unsigned nextValueID = 0;
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700551};
James Molloy87d81022018-07-23 11:44:40 -0700552} // end anonymous namespace
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700553
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700554void FunctionState::printOperation(const Operation *op) {
Chris Lattnerf8cce872018-07-20 09:28:54 -0700555 os << " ";
556
Chris Lattnerac591f12018-07-22 21:02:26 -0700557 if (op->getNumResults()) {
558 printValueID(op->getResult(0), /*dontPrintResultNo*/ true);
559 os << " = ";
Chris Lattnerf8cce872018-07-20 09:28:54 -0700560 }
561
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700562 // Check to see if this is a known operation. If so, use the registered
563 // custom printer hook.
Chris Lattner4fd59b02018-07-20 09:35:47 -0700564 if (auto opInfo = state.operationSet->lookup(op->getName().str())) {
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700565 opInfo->printAssembly(op, os);
566 return;
567 }
568
Chris Lattnerf8cce872018-07-20 09:28:54 -0700569 // Otherwise use the standard verbose printing approach.
570
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700571 // TODO: escape name if necessary.
Chris Lattnerf8cce872018-07-20 09:28:54 -0700572 os << "\"" << op->getName().str() << "\"(";
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700573
Chris Lattnerac591f12018-07-22 21:02:26 -0700574 interleaveComma(op->getOperands(),
575 [&](const SSAValue *value) { printValueID(value); });
Chris Lattner7f9cc272018-07-19 08:35:28 -0700576
Chris Lattnerf8cce872018-07-20 09:28:54 -0700577 os << ')';
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700578 auto attrs = op->getAttrs();
579 if (!attrs.empty()) {
580 os << '{';
Chris Lattner4fd59b02018-07-20 09:35:47 -0700581 interleaveComma(attrs, [&](NamedAttribute attr) {
Chris Lattnerf8cce872018-07-20 09:28:54 -0700582 os << attr.first << ": ";
Chris Lattner4fd59b02018-07-20 09:35:47 -0700583 print(attr.second);
Chris Lattnerf8cce872018-07-20 09:28:54 -0700584 });
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700585 os << '}';
586 }
Chris Lattner3b2ef762018-07-18 15:31:25 -0700587
Chris Lattnerac591f12018-07-22 21:02:26 -0700588 // Print the type signature of the operation.
589 os << " : (";
590 interleaveComma(op->getOperands(),
591 [&](const SSAValue *value) { print(value->getType()); });
592 os << ") -> ";
Chris Lattnerf8cce872018-07-20 09:28:54 -0700593
Chris Lattnerac591f12018-07-22 21:02:26 -0700594 if (op->getNumResults() == 1) {
595 print(op->getResult(0)->getType());
596 } else {
597 os << '(';
598 interleaveComma(op->getResults(),
599 [&](const SSAValue *result) { print(result->getType()); });
600 os << ')';
Chris Lattnerf8cce872018-07-20 09:28:54 -0700601 }
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700602}
603
Chris Lattner4c95a502018-06-23 16:03:42 -0700604//===----------------------------------------------------------------------===//
605// CFG Function printing
606//===----------------------------------------------------------------------===//
607
608namespace {
Chris Lattner4fd59b02018-07-20 09:35:47 -0700609class CFGFunctionPrinter : public FunctionState {
Chris Lattner4c95a502018-06-23 16:03:42 -0700610public:
Chris Lattner4fd59b02018-07-20 09:35:47 -0700611 CFGFunctionPrinter(const CFGFunction *function, const ModulePrinter &other);
Chris Lattner4c95a502018-06-23 16:03:42 -0700612
613 const CFGFunction *getFunction() const { return function; }
614
615 void print();
616 void print(const BasicBlock *block);
Chris Lattnered65a732018-06-28 20:45:33 -0700617
618 void print(const Instruction *inst);
619 void print(const OperationInst *inst);
620 void print(const ReturnInst *inst);
621 void print(const BranchInst *inst);
James Molloy4f788372018-07-24 15:01:27 -0700622 void print(const CondBranchInst *inst);
Chris Lattner4c95a502018-06-23 16:03:42 -0700623
624 unsigned getBBID(const BasicBlock *block) {
625 auto it = basicBlockIDs.find(block);
626 assert(it != basicBlockIDs.end() && "Block not in this function?");
627 return it->second;
628 }
629
630private:
631 const CFGFunction *function;
MLIR Team54b55a22018-07-18 10:16:05 -0700632 DenseMap<const BasicBlock *, unsigned> basicBlockIDs;
Chris Lattnerf8cce872018-07-20 09:28:54 -0700633
Chris Lattner4fd59b02018-07-20 09:35:47 -0700634 void numberValuesInBlock(const BasicBlock *block);
Chris Lattner4c95a502018-06-23 16:03:42 -0700635};
James Molloy87d81022018-07-23 11:44:40 -0700636} // end anonymous namespace
Chris Lattner4c95a502018-06-23 16:03:42 -0700637
Chris Lattner4fd59b02018-07-20 09:35:47 -0700638CFGFunctionPrinter::CFGFunctionPrinter(const CFGFunction *function,
639 const ModulePrinter &other)
640 : FunctionState(other), function(function) {
Chris Lattner4c95a502018-06-23 16:03:42 -0700641 // Each basic block gets a unique ID per function.
642 unsigned blockID = 0;
Chris Lattnerf8cce872018-07-20 09:28:54 -0700643 for (auto &block : *function) {
644 basicBlockIDs[&block] = blockID++;
Chris Lattner4fd59b02018-07-20 09:35:47 -0700645 numberValuesInBlock(&block);
Chris Lattnerf8cce872018-07-20 09:28:54 -0700646 }
647}
648
649/// Number all of the SSA values in the specified basic block.
Chris Lattner4fd59b02018-07-20 09:35:47 -0700650void CFGFunctionPrinter::numberValuesInBlock(const BasicBlock *block) {
James Molloy61a656c2018-07-22 15:45:24 -0700651 for (auto *arg : block->getArguments()) {
652 numberValueID(arg);
653 }
Chris Lattnerf8cce872018-07-20 09:28:54 -0700654 for (auto &op : *block) {
655 // We number instruction that have results, and we only number the first
656 // result.
657 if (op.getNumResults() != 0)
658 numberValueID(op.getResult(0));
659 }
660
661 // Terminators do not define values.
Chris Lattner4c95a502018-06-23 16:03:42 -0700662}
663
Chris Lattner4fd59b02018-07-20 09:35:47 -0700664void CFGFunctionPrinter::print() {
Chris Lattner4c95a502018-06-23 16:03:42 -0700665 os << "cfgfunc ";
Chris Lattner4fd59b02018-07-20 09:35:47 -0700666 printFunctionSignature(getFunction());
Chris Lattner4c95a502018-06-23 16:03:42 -0700667 os << " {\n";
668
James Molloy87d81022018-07-23 11:44:40 -0700669 for (auto &block : *function)
670 print(&block);
Chris Lattner4c95a502018-06-23 16:03:42 -0700671 os << "}\n\n";
672}
673
Chris Lattner4fd59b02018-07-20 09:35:47 -0700674void CFGFunctionPrinter::print(const BasicBlock *block) {
James Molloy61a656c2018-07-22 15:45:24 -0700675 os << "bb" << getBBID(block);
Chris Lattner4c95a502018-06-23 16:03:42 -0700676
James Molloy61a656c2018-07-22 15:45:24 -0700677 if (!block->args_empty()) {
678 os << '(';
679 interleaveComma(block->getArguments(), [&](const BBArgument *arg) {
680 printValueID(arg);
681 os << ": ";
682 ModulePrinter::print(arg->getType());
683 });
684 os << ')';
685 }
686 os << ":\n";
687
Jacques Pienaarb020c542018-07-15 00:06:54 -0700688 for (auto &inst : block->getOperations()) {
Chris Lattner3a467cc2018-07-01 20:28:00 -0700689 print(&inst);
James Molloy61a656c2018-07-22 15:45:24 -0700690 os << '\n';
Jacques Pienaarb020c542018-07-15 00:06:54 -0700691 }
Chris Lattner4c95a502018-06-23 16:03:42 -0700692
693 print(block->getTerminator());
James Molloy61a656c2018-07-22 15:45:24 -0700694 os << '\n';
Chris Lattner4c95a502018-06-23 16:03:42 -0700695}
696
Chris Lattner4fd59b02018-07-20 09:35:47 -0700697void CFGFunctionPrinter::print(const Instruction *inst) {
Chris Lattner4c95a502018-06-23 16:03:42 -0700698 switch (inst->getKind()) {
Chris Lattnered65a732018-06-28 20:45:33 -0700699 case Instruction::Kind::Operation:
700 return print(cast<OperationInst>(inst));
Chris Lattnerf6d80a02018-06-24 11:18:29 -0700701 case TerminatorInst::Kind::Branch:
Chris Lattnered65a732018-06-28 20:45:33 -0700702 return print(cast<BranchInst>(inst));
James Molloy4f788372018-07-24 15:01:27 -0700703 case TerminatorInst::Kind::CondBranch:
704 return print(cast<CondBranchInst>(inst));
Chris Lattner4c95a502018-06-23 16:03:42 -0700705 case TerminatorInst::Kind::Return:
Chris Lattnered65a732018-06-28 20:45:33 -0700706 return print(cast<ReturnInst>(inst));
Chris Lattner4c95a502018-06-23 16:03:42 -0700707 }
708}
709
Chris Lattner4fd59b02018-07-20 09:35:47 -0700710void CFGFunctionPrinter::print(const OperationInst *inst) {
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700711 printOperation(inst);
Chris Lattner3b2ef762018-07-18 15:31:25 -0700712}
Chris Lattner1604e472018-07-23 08:42:19 -0700713
Chris Lattner4fd59b02018-07-20 09:35:47 -0700714void CFGFunctionPrinter::print(const BranchInst *inst) {
Jacques Pienaarb020c542018-07-15 00:06:54 -0700715 os << " br bb" << getBBID(inst->getDest());
Chris Lattner1604e472018-07-23 08:42:19 -0700716
717 if (inst->getNumOperands() != 0) {
718 os << '(';
719 // TODO: Use getOperands() when we have it.
720 interleaveComma(inst->getInstOperands(), [&](const InstOperand &operand) {
721 printValueID(operand.get());
722 });
723 os << ") : ";
724 interleaveComma(inst->getInstOperands(), [&](const InstOperand &operand) {
725 ModulePrinter::print(operand.get()->getType());
726 });
727 }
Chris Lattnered65a732018-06-28 20:45:33 -0700728}
Chris Lattner1604e472018-07-23 08:42:19 -0700729
James Molloy4f788372018-07-24 15:01:27 -0700730void CFGFunctionPrinter::print(const CondBranchInst *inst) {
731 os << " cond_br ";
732 printValueID(inst->getCondition());
733
734 os << ", bb" << getBBID(inst->getTrueDest());
735 if (inst->getNumTrueOperands() != 0) {
736 os << '(';
737 interleaveComma(inst->getTrueOperands(),
738 [&](const CFGValue *operand) { printValueID(operand); });
739 os << " : ";
740 interleaveComma(inst->getTrueOperands(), [&](const CFGValue *operand) {
741 ModulePrinter::print(operand->getType());
742 });
743 os << ")";
744 }
745
746 os << ", bb" << getBBID(inst->getFalseDest());
747 if (inst->getNumFalseOperands() != 0) {
748 os << '(';
749 interleaveComma(inst->getFalseOperands(),
750 [&](const CFGValue *operand) { printValueID(operand); });
751 os << " : ";
752 interleaveComma(inst->getFalseOperands(), [&](const CFGValue *operand) {
753 ModulePrinter::print(operand->getType());
754 });
755 os << ")";
756 }
757}
758
Chris Lattner40746442018-07-21 14:32:09 -0700759void CFGFunctionPrinter::print(const ReturnInst *inst) {
760 os << " return";
761
762 if (inst->getNumOperands() != 0)
763 os << ' ';
764
James Molloy4f788372018-07-24 15:01:27 -0700765 interleaveComma(inst->getOperands(),
766 [&](const CFGValue *operand) { printValueID(operand); });
767 os << " : ";
Chris Lattnerac591f12018-07-22 21:02:26 -0700768 interleaveComma(inst->getOperands(), [&](const CFGValue *operand) {
Chris Lattnerac591f12018-07-22 21:02:26 -0700769 ModulePrinter::print(operand->getType());
Chris Lattner40746442018-07-21 14:32:09 -0700770 });
771}
MLIR Team54b55a22018-07-18 10:16:05 -0700772
Chris Lattner4fd59b02018-07-20 09:35:47 -0700773void ModulePrinter::print(const CFGFunction *fn) {
774 CFGFunctionPrinter(fn, *this).print();
Chris Lattnered65a732018-06-28 20:45:33 -0700775}
776
Chris Lattner4c95a502018-06-23 16:03:42 -0700777//===----------------------------------------------------------------------===//
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700778// ML Function printing
Chris Lattner4c95a502018-06-23 16:03:42 -0700779//===----------------------------------------------------------------------===//
780
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700781namespace {
Chris Lattner4fd59b02018-07-20 09:35:47 -0700782class MLFunctionPrinter : public FunctionState {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700783public:
Chris Lattner4fd59b02018-07-20 09:35:47 -0700784 MLFunctionPrinter(const MLFunction *function, const ModulePrinter &other);
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700785
786 const MLFunction *getFunction() const { return function; }
787
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700788 // Prints ML function
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700789 void print();
790
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700791 // Methods to print ML function statements
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700792 void print(const Statement *stmt);
Tatiana Shpeismanfa412f72018-07-09 17:42:46 -0700793 void print(const OperationStmt *stmt);
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700794 void print(const ForStmt *stmt);
795 void print(const IfStmt *stmt);
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700796 void print(const StmtBlock *block);
797
798 // Number of spaces used for indenting nested statements
799 const static unsigned indentWidth = 2;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700800
801private:
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700802 const MLFunction *function;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700803 int numSpaces;
804};
James Molloy87d81022018-07-23 11:44:40 -0700805} // end anonymous namespace
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700806
Chris Lattner4fd59b02018-07-20 09:35:47 -0700807MLFunctionPrinter::MLFunctionPrinter(const MLFunction *function,
808 const ModulePrinter &other)
809 : FunctionState(other), function(function), numSpaces(0) {}
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700810
Chris Lattner4fd59b02018-07-20 09:35:47 -0700811void MLFunctionPrinter::print() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700812 os << "mlfunc ";
813 // FIXME: should print argument names rather than just signature
Chris Lattner4fd59b02018-07-20 09:35:47 -0700814 printFunctionSignature(function);
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700815 os << " {\n";
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700816 print(function);
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700817 os << " return\n";
818 os << "}\n\n";
819}
820
Chris Lattner4fd59b02018-07-20 09:35:47 -0700821void MLFunctionPrinter::print(const StmtBlock *block) {
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700822 numSpaces += indentWidth;
Jacques Pienaarb020c542018-07-15 00:06:54 -0700823 for (auto &stmt : block->getStatements()) {
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700824 print(&stmt);
Jacques Pienaarb020c542018-07-15 00:06:54 -0700825 os << "\n";
826 }
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700827 numSpaces -= indentWidth;
828}
829
Chris Lattner4fd59b02018-07-20 09:35:47 -0700830void MLFunctionPrinter::print(const Statement *stmt) {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700831 switch (stmt->getKind()) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -0700832 case Statement::Kind::Operation:
833 return print(cast<OperationStmt>(stmt));
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700834 case Statement::Kind::For:
835 return print(cast<ForStmt>(stmt));
836 case Statement::Kind::If:
837 return print(cast<IfStmt>(stmt));
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700838 }
839}
840
Chris Lattner4fd59b02018-07-20 09:35:47 -0700841void MLFunctionPrinter::print(const OperationStmt *stmt) {
842 printOperation(stmt);
843}
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700844
Chris Lattner4fd59b02018-07-20 09:35:47 -0700845void MLFunctionPrinter::print(const ForStmt *stmt) {
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -0700846 os.indent(numSpaces) << "for x = " << *stmt->getLowerBound();
847 os << " to " << *stmt->getUpperBound();
848 if (stmt->getStep()->getValue() != 1)
849 os << " step " << *stmt->getStep();
850
851 os << " {\n";
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700852 print(static_cast<const StmtBlock *>(stmt));
Tatiana Shpeisman565b9642018-07-16 11:47:09 -0700853 os.indent(numSpaces) << "}";
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700854}
855
Chris Lattner4fd59b02018-07-20 09:35:47 -0700856void MLFunctionPrinter::print(const IfStmt *stmt) {
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -0700857 os.indent(numSpaces) << "if () {\n";
858 print(stmt->getThenClause());
859 os.indent(numSpaces) << "}";
860 if (stmt->hasElseClause()) {
861 os << " else {\n";
862 print(stmt->getElseClause());
863 os.indent(numSpaces) << "}";
864 }
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700865}
866
Chris Lattner4fd59b02018-07-20 09:35:47 -0700867void ModulePrinter::print(const MLFunction *fn) {
868 MLFunctionPrinter(fn, *this).print();
MLIR Team4718bc92018-07-17 16:56:54 -0700869}
870
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700871//===----------------------------------------------------------------------===//
872// print and dump methods
873//===----------------------------------------------------------------------===//
Chris Lattnered65a732018-06-28 20:45:33 -0700874
MLIR Teamb61885d2018-07-18 16:29:21 -0700875void Attribute::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -0700876 ModuleState state(/*no context is known*/ nullptr);
877 ModulePrinter(os, state).print(this);
MLIR Teamb61885d2018-07-18 16:29:21 -0700878}
879
James Molloy87d81022018-07-23 11:44:40 -0700880void Attribute::dump() const { print(llvm::errs()); }
MLIR Teamb61885d2018-07-18 16:29:21 -0700881
MLIR Team4718bc92018-07-17 16:56:54 -0700882void Type::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -0700883 ModuleState state(getContext());
884 ModulePrinter(os, state).print(this);
MLIR Team4718bc92018-07-17 16:56:54 -0700885}
886
MLIR Team54b55a22018-07-18 10:16:05 -0700887void Type::dump() const { print(llvm::errs()); }
MLIR Team4718bc92018-07-17 16:56:54 -0700888
MLIR Team718c82f2018-07-16 09:45:22 -0700889void AffineMap::dump() const {
890 print(llvm::errs());
891 llvm::errs() << "\n";
892}
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700893
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700894void AffineExpr::dump() const {
895 print(llvm::errs());
896 llvm::errs() << "\n";
897}
898
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700899void AffineExpr::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -0700900 ModuleState state(/*no context is known*/ nullptr);
901 ModulePrinter(os, state).print(this);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700902}
903
904void AffineMap::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -0700905 ModuleState state(/*no context is known*/ nullptr);
906 ModulePrinter(os, state).print(this);
907}
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700908
Chris Lattner4fd59b02018-07-20 09:35:47 -0700909void Instruction::print(raw_ostream &os) const {
910 ModuleState state(getFunction()->getContext());
911 ModulePrinter modulePrinter(os, state);
912 CFGFunctionPrinter(getFunction(), modulePrinter).print(this);
913}
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700914
Chris Lattner4fd59b02018-07-20 09:35:47 -0700915void Instruction::dump() const {
916 print(llvm::errs());
917 llvm::errs() << "\n";
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700918}
919
Chris Lattner4c95a502018-06-23 16:03:42 -0700920void BasicBlock::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -0700921 ModuleState state(getFunction()->getContext());
922 ModulePrinter modulePrinter(os, state);
923 CFGFunctionPrinter(getFunction(), modulePrinter).print(this);
Chris Lattner4c95a502018-06-23 16:03:42 -0700924}
925
MLIR Team54b55a22018-07-18 10:16:05 -0700926void BasicBlock::dump() const { print(llvm::errs()); }
Chris Lattner4c95a502018-06-23 16:03:42 -0700927
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700928void Statement::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -0700929 ModuleState state(getFunction()->getContext());
930 ModulePrinter modulePrinter(os, state);
931 MLFunctionPrinter(getFunction(), modulePrinter).print(this);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -0700932}
933
MLIR Team54b55a22018-07-18 10:16:05 -0700934void Statement::dump() const { print(llvm::errs()); }
Jacques Pienaarb020c542018-07-15 00:06:54 -0700935
Chris Lattner4c95a502018-06-23 16:03:42 -0700936void Function::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -0700937 ModuleState state(getContext());
938 ModulePrinter(os, state).print(this);
Chris Lattner4c95a502018-06-23 16:03:42 -0700939}
940
MLIR Team54b55a22018-07-18 10:16:05 -0700941void Function::dump() const { print(llvm::errs()); }
942
Chris Lattner4c95a502018-06-23 16:03:42 -0700943void Module::print(raw_ostream &os) const {
Chris Lattner4fd59b02018-07-20 09:35:47 -0700944 ModuleState state(getContext());
945 state.initialize(this);
946 ModulePrinter(os, state).print(this);
Chris Lattner4c95a502018-06-23 16:03:42 -0700947}
948
MLIR Team54b55a22018-07-18 10:16:05 -0700949void Module::dump() const { print(llvm::errs()); }