llvm-project/flang/tools/tco/tco.cpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

114 lines
3.7 KiB
C++
Raw Normal View History

[flang] Add Fortran IR (FIR) MLIR dialect implementation (flang-compiler/f18#1035) Adds FIR library that implements an MLIR dialect to which Fortran parse-tree will be lowered to. FIR is defined and documented inside FIROps.td added in this commit. It is possible to generate a more readable description FIRLangRef.md from FIROps.td following the related instructions added to the README.md by this commit. This patch adds FIR definition and implementation that allow parsing, printing, and verifying FIR. FIR transformations and lowering to Standard and LLVM dialects are not part of this patch. The FIR verifiers are verifying the basic properties of FIR operations in order to provide a sufficient frame for lowering. Verifiers for more advanced FIR properties can be added as needed. Coarrays are not covered by FIR defined in this patch. This patch also adds tco tool that is meant to process FIR input files and drives transformations on it. The tco tool is used for testing. In this patch, it is only used to demonstrate parsing/verifying/ and dumping FIR with round-trip tests. Note: This commit does not reflect an actual work log, it is a feature-based split of the changes done in the FIR experimental branch. The related work log can be found in the commits between: https://github.com/schweitzpgi/f18/commit/742edde572bd74d77cf7d447132ccf0949187fce and https://github.com/schweitzpgi/f18/commit/2ff55242126d86061f4fed9ef7b59d3636b5fd0b Changes on top of these original commits were made during this patch review. Original-commit: flang-compiler/f18@30b428a51e140e5fb12bd53a0619f10ff510f408 Reviewed-on: https://github.com/flang-compiler/f18/pull/1035
2020-03-12 12:47:22 +08:00
//===- tco.cpp - Tilikum Crossing Opt ---------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This is to be like LLVM's opt program, only for FIR. Such a program is
// required for roundtrip testing, etc.
//
//===----------------------------------------------------------------------===//
#include "flang/Optimizer/Dialect/FIRDialect.h"
#include "flang/Optimizer/Support/KindMapping.h"
#include "mlir/IR/MLIRContext.h"
#include "mlir/IR/Module.h"
#include "mlir/Parser.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Pass/PassManager.h"
#include "mlir/Transforms/Passes.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
static cl::opt<std::string>
inputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-"));
static cl::opt<std::string> outputFilename("o",
cl::desc("Specify output filename"),
cl::value_desc("filename"),
cl::init("-"));
static cl::opt<bool> emitFir("emit-fir",
cl::desc("Parse and pretty-print the input"),
cl::init(false));
static void printModuleBody(mlir::ModuleOp mod, raw_ostream &output) {
for (auto &op : mod.getBody()->without_terminator())
output << op << '\n';
}
// compile a .fir file
static int compileFIR() {
// check that there is a file to load
ErrorOr<std::unique_ptr<MemoryBuffer>> fileOrErr =
MemoryBuffer::getFileOrSTDIN(inputFilename);
if (std::error_code EC = fileOrErr.getError()) {
errs() << "Could not open file: " << EC.message() << '\n';
return 1;
}
// load the file into a module
SourceMgr sourceMgr;
sourceMgr.AddNewSourceBuffer(std::move(*fileOrErr), SMLoc());
auto context = std::make_unique<mlir::MLIRContext>();
auto owningRef = mlir::parseSourceFile(sourceMgr, context.get());
if (!owningRef) {
errs() << "Error can't load file " << inputFilename << '\n';
return 2;
}
if (mlir::failed(owningRef->verify())) {
errs() << "Error verifying FIR module\n";
return 4;
}
std::error_code ec;
ToolOutputFile out(outputFilename, ec, sys::fs::OF_None);
// run passes
mlir::PassManager pm{context.get()};
mlir::applyPassManagerCLOptions(pm);
if (emitFir) {
// parse the input and pretty-print it back out
// -emit-fir intentionally disables all the passes
} else {
// TODO: Actually add passes when added to FIR code base
// add all the passes
// the user can disable them individually
}
// run the pass manager
if (mlir::succeeded(pm.run(*owningRef))) {
// passes ran successfully, so keep the output
if (emitFir)
printModuleBody(*owningRef, out.os());
out.keep();
return 0;
}
// pass manager failed
printModuleBody(*owningRef, errs());
errs() << "\n\nFAILED: " << inputFilename << '\n';
return 8;
}
int main(int argc, char **argv) {
fir::registerFIR();
fir::registerFIRPasses();
[[maybe_unused]] InitLLVM y(argc, argv);
mlir::registerPassManagerCLOptions();
mlir::PassPipelineCLParser passPipe("", "Compiler passes to run");
cl::ParseCommandLineOptions(argc, argv, "Tilikum Crossing Optimizer\n");
return compileFIR();
}