Implement parser/IR support for CFG functions, basic blocks and return instruction.
This is pretty much minimal scaffolding for this step. Basic block arguments,
instructions, other terminators, a proper IR representation for
blocks/instructions, etc are all coming.
PiperOrigin-RevId: 201826439
diff --git a/lib/IR/AsmPrinter.cpp b/lib/IR/AsmPrinter.cpp
new file mode 100644
index 0000000..f857963
--- /dev/null
+++ b/lib/IR/AsmPrinter.cpp
@@ -0,0 +1,175 @@
+//===- 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.
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/IR/CFGFunction.h"
+#include "mlir/IR/Module.h"
+#include "mlir/IR/Types.h"
+#include "mlir/Support/STLExtras.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/ADT/DenseMap.h"
+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);
+ void print(const TerminatorInst *inst);
+
+ 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";
+
+ // TODO Print arguments and instructions.
+
+ print(block->getTerminator());
+}
+
+void CFGFunctionState::print(const TerminatorInst *inst) {
+ switch (inst->getKind()) {
+ case TerminatorInst::Kind::Return:
+ os << " return\n";
+ break;
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// print and dump methods
+//===----------------------------------------------------------------------===//
+
+void TerminatorInst::print(raw_ostream &os) const {
+ CFGFunctionState state(getFunction(), os);
+ state.print(this);
+}
+
+void TerminatorInst::dump() const {
+ print(llvm::errs());
+}
+
+void BasicBlock::print(raw_ostream &os) const {
+ CFGFunctionState state(getFunction(), os);
+ state.print();
+}
+
+void BasicBlock::dump() const {
+ print(llvm::errs());
+}
+
+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);
+ }
+}
+
+void Function::dump() const {
+ print(llvm::errs());
+}
+
+void CFGFunction::print(raw_ostream &os) const {
+ CFGFunctionState state(this, os);
+ state.print();
+}
+
+void Module::print(raw_ostream &os) const {
+ for (auto *fn : functionList)
+ fn->print(os);
+}
+
+void Module::dump() const {
+ print(llvm::errs());
+}
+