2018-06-23 16:03:42 -07:00
|
|
|
//===- AsmPrinter.cpp - MLIR Assembly Printer Implementation --------------===//
|
|
|
|
//
|
|
|
|
// Copyright 2019 The MLIR Authors.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
// =============================================================================
|
|
|
|
//
|
|
|
|
// This file implements the MLIR AsmPrinter class, which is used to implement
|
|
|
|
// the various print() methods on the core IR objects.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2018-06-29 18:09:29 -07:00
|
|
|
#include "mlir/IR/AffineExpr.h"
|
|
|
|
#include "mlir/IR/AffineMap.h"
|
2018-06-23 16:03:42 -07:00
|
|
|
#include "mlir/IR/CFGFunction.h"
|
2018-06-28 17:02:32 -07:00
|
|
|
#include "mlir/IR/MLFunction.h"
|
2018-06-23 16:03:42 -07:00
|
|
|
#include "mlir/IR/Module.h"
|
|
|
|
#include "mlir/IR/Types.h"
|
|
|
|
#include "mlir/Support/STLExtras.h"
|
|
|
|
#include "llvm/ADT/DenseMap.h"
|
2018-06-29 18:09:29 -07:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2018-06-23 16:03:42 -07:00
|
|
|
using namespace mlir;
|
|
|
|
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Function printing
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
static void printFunctionSignature(const Function *fn, raw_ostream &os) {
|
|
|
|
auto type = fn->getType();
|
|
|
|
|
|
|
|
os << "@" << fn->getName() << '(';
|
|
|
|
interleave(type->getInputs(),
|
|
|
|
[&](Type *eltType) { os << *eltType; },
|
|
|
|
[&]() { os << ", "; });
|
|
|
|
os << ')';
|
|
|
|
|
|
|
|
switch (type->getResults().size()) {
|
|
|
|
case 0: break;
|
|
|
|
case 1:
|
|
|
|
os << " -> " << *type->getResults()[0];
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
os << " -> (";
|
|
|
|
interleave(type->getResults(),
|
|
|
|
[&](Type *eltType) { os << *eltType; },
|
|
|
|
[&]() { os << ", "; });
|
|
|
|
os << ')';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ExtFunction::print(raw_ostream &os) const {
|
|
|
|
os << "extfunc ";
|
|
|
|
printFunctionSignature(this, os);
|
|
|
|
os << "\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// CFG Function printing
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
class CFGFunctionState {
|
|
|
|
public:
|
|
|
|
CFGFunctionState(const CFGFunction *function, raw_ostream &os);
|
|
|
|
|
|
|
|
const CFGFunction *getFunction() const { return function; }
|
|
|
|
|
|
|
|
void print();
|
|
|
|
void print(const BasicBlock *block);
|
2018-06-28 20:45:33 -07:00
|
|
|
|
|
|
|
void print(const Instruction *inst);
|
|
|
|
void print(const OperationInst *inst);
|
|
|
|
void print(const ReturnInst *inst);
|
|
|
|
void print(const BranchInst *inst);
|
2018-06-23 16:03:42 -07:00
|
|
|
|
|
|
|
unsigned getBBID(const BasicBlock *block) {
|
|
|
|
auto it = basicBlockIDs.find(block);
|
|
|
|
assert(it != basicBlockIDs.end() && "Block not in this function?");
|
|
|
|
return it->second;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
const CFGFunction *function;
|
|
|
|
raw_ostream &os;
|
|
|
|
DenseMap<BasicBlock*, unsigned> basicBlockIDs;
|
|
|
|
};
|
|
|
|
} // end anonymous namespace
|
|
|
|
|
|
|
|
CFGFunctionState::CFGFunctionState(const CFGFunction *function, raw_ostream &os)
|
|
|
|
: function(function), os(os) {
|
|
|
|
|
|
|
|
// Each basic block gets a unique ID per function.
|
|
|
|
unsigned blockID = 0;
|
|
|
|
for (auto *block : function->blockList)
|
|
|
|
basicBlockIDs[block] = blockID++;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CFGFunctionState::print() {
|
|
|
|
os << "cfgfunc ";
|
|
|
|
printFunctionSignature(this->getFunction(), os);
|
|
|
|
os << " {\n";
|
|
|
|
|
|
|
|
for (auto *block : function->blockList)
|
|
|
|
print(block);
|
|
|
|
os << "}\n\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
void CFGFunctionState::print(const BasicBlock *block) {
|
|
|
|
os << "bb" << getBBID(block) << ":\n";
|
|
|
|
|
2018-06-28 20:45:33 -07:00
|
|
|
// TODO Print arguments.
|
|
|
|
for (auto inst : block->instList)
|
|
|
|
print(inst);
|
2018-06-23 16:03:42 -07:00
|
|
|
|
|
|
|
print(block->getTerminator());
|
|
|
|
}
|
|
|
|
|
2018-06-28 20:45:33 -07:00
|
|
|
void CFGFunctionState::print(const Instruction *inst) {
|
2018-06-23 16:03:42 -07:00
|
|
|
switch (inst->getKind()) {
|
2018-06-28 20:45:33 -07:00
|
|
|
case Instruction::Kind::Operation:
|
|
|
|
return print(cast<OperationInst>(inst));
|
2018-06-24 11:18:29 -07:00
|
|
|
case TerminatorInst::Kind::Branch:
|
2018-06-28 20:45:33 -07:00
|
|
|
return print(cast<BranchInst>(inst));
|
2018-06-23 16:03:42 -07:00
|
|
|
case TerminatorInst::Kind::Return:
|
2018-06-28 20:45:33 -07:00
|
|
|
return print(cast<ReturnInst>(inst));
|
2018-06-23 16:03:42 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-28 20:45:33 -07:00
|
|
|
void CFGFunctionState::print(const OperationInst *inst) {
|
|
|
|
// TODO: escape name if necessary.
|
|
|
|
os << " \"" << inst->getName().str() << "\"()\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
void CFGFunctionState::print(const BranchInst *inst) {
|
|
|
|
os << " br bb" << getBBID(inst->getDest()) << "\n";
|
|
|
|
}
|
|
|
|
void CFGFunctionState::print(const ReturnInst *inst) {
|
|
|
|
os << " return\n";
|
|
|
|
}
|
|
|
|
|
2018-06-23 16:03:42 -07:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// print and dump methods
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2018-06-28 20:45:33 -07:00
|
|
|
|
|
|
|
void Instruction::print(raw_ostream &os) const {
|
2018-06-23 16:03:42 -07:00
|
|
|
CFGFunctionState state(getFunction(), os);
|
|
|
|
state.print(this);
|
|
|
|
}
|
|
|
|
|
2018-06-28 20:45:33 -07:00
|
|
|
void Instruction::dump() const {
|
2018-06-23 16:03:42 -07:00
|
|
|
print(llvm::errs());
|
|
|
|
}
|
|
|
|
|
2018-06-29 18:09:29 -07:00
|
|
|
void AffineExpr::print(raw_ostream &os) const {
|
|
|
|
// TODO(bondhugula): print out affine expression
|
|
|
|
}
|
|
|
|
|
|
|
|
void AffineMap::print(raw_ostream &os) const {
|
|
|
|
// TODO(andydavis) Print out affine map based on dimensionCount and
|
|
|
|
// symbolCount: (d0, d1) [S0, S1] -> (d0 + S0, d1 + S1)
|
|
|
|
}
|
|
|
|
|
2018-06-23 16:03:42 -07:00
|
|
|
void BasicBlock::print(raw_ostream &os) const {
|
|
|
|
CFGFunctionState state(getFunction(), os);
|
|
|
|
state.print();
|
|
|
|
}
|
|
|
|
|
|
|
|
void BasicBlock::dump() const {
|
|
|
|
print(llvm::errs());
|
|
|
|
}
|
|
|
|
|
2018-06-28 17:02:32 -07:00
|
|
|
void MLStatement::print(raw_ostream &os) const {
|
|
|
|
//TODO
|
|
|
|
}
|
|
|
|
|
|
|
|
void MLStatement::dump() const {
|
|
|
|
print(llvm::errs());
|
|
|
|
}
|
2018-06-23 16:03:42 -07:00
|
|
|
void Function::print(raw_ostream &os) const {
|
|
|
|
switch (getKind()) {
|
|
|
|
case Kind::ExtFunc: return cast<ExtFunction>(this)->print(os);
|
|
|
|
case Kind::CFGFunc: return cast<CFGFunction>(this)->print(os);
|
2018-06-28 17:02:32 -07:00
|
|
|
case Kind::MLFunc: return cast<MLFunction>(this)->print(os);
|
2018-06-23 16:03:42 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Function::dump() const {
|
|
|
|
print(llvm::errs());
|
|
|
|
}
|
|
|
|
|
|
|
|
void CFGFunction::print(raw_ostream &os) const {
|
|
|
|
CFGFunctionState state(this, os);
|
|
|
|
state.print();
|
|
|
|
}
|
|
|
|
|
2018-06-28 17:02:32 -07:00
|
|
|
void MLFunction::print(raw_ostream &os) const {
|
|
|
|
os << "mlfunc ";
|
|
|
|
// FIXME: should print argument names rather than just signature
|
|
|
|
printFunctionSignature(this, os);
|
|
|
|
os << " {\n";
|
|
|
|
|
|
|
|
for (auto *stmt : stmtList)
|
|
|
|
stmt->print(os);
|
|
|
|
os << " return\n";
|
|
|
|
os << "}\n\n";
|
|
|
|
}
|
|
|
|
|
2018-06-23 16:03:42 -07:00
|
|
|
void Module::print(raw_ostream &os) const {
|
2018-06-29 18:09:29 -07:00
|
|
|
for (auto *map : affineMapList)
|
|
|
|
map->print(os);
|
2018-06-23 16:03:42 -07:00
|
|
|
for (auto *fn : functionList)
|
|
|
|
fn->print(os);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Module::dump() const {
|
|
|
|
print(llvm::errs());
|
|
|
|
}
|
|
|
|
|