brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.3 KiB · 3094935 Raw
171 lines · cpp
1//===- toyc.cpp - The Toy Compiler ----------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements the entry point for the Toy compiler.10//11//===----------------------------------------------------------------------===//12 13#include "mlir/IR/Diagnostics.h"14#include "toy/AST.h"15#include "toy/Dialect.h"16#include "toy/Lexer.h"17#include "toy/MLIRGen.h"18#include "toy/Parser.h"19 20#include "mlir/IR/AsmState.h"21#include "mlir/IR/BuiltinOps.h"22#include "mlir/IR/MLIRContext.h"23#include "mlir/IR/Verifier.h"24#include "mlir/Parser/Parser.h"25#include "mlir/Pass/PassManager.h"26#include "mlir/Transforms/Passes.h"27 28#include "llvm/ADT/StringRef.h"29#include "llvm/Support/CommandLine.h"30#include "llvm/Support/ErrorOr.h"31#include "llvm/Support/MemoryBuffer.h"32#include "llvm/Support/SourceMgr.h"33#include "llvm/Support/raw_ostream.h"34#include <memory>35#include <string>36#include <system_error>37#include <utility>38 39using namespace toy;40namespace cl = llvm::cl;41 42static cl::opt<std::string> inputFilename(cl::Positional,43                                          cl::desc("<input toy file>"),44                                          cl::init("-"),45                                          cl::value_desc("filename"));46 47namespace {48enum InputType { Toy, MLIR };49} // namespace50static cl::opt<enum InputType> inputType(51    "x", cl::init(Toy), cl::desc("Decided the kind of output desired"),52    cl::values(clEnumValN(Toy, "toy", "load the input file as a Toy source.")),53    cl::values(clEnumValN(MLIR, "mlir",54                          "load the input file as an MLIR file")));55 56namespace {57enum Action { None, DumpAST, DumpMLIR };58} // namespace59static cl::opt<enum Action> emitAction(60    "emit", cl::desc("Select the kind of output desired"),61    cl::values(clEnumValN(DumpAST, "ast", "output the AST dump")),62    cl::values(clEnumValN(DumpMLIR, "mlir", "output the MLIR dump")));63 64static cl::opt<bool> enableOpt("opt", cl::desc("Enable optimizations"));65 66/// Returns a Toy AST resulting from parsing the file or a nullptr on error.67static std::unique_ptr<toy::ModuleAST>68parseInputFile(llvm::StringRef filename) {69  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> fileOrErr =70      llvm::MemoryBuffer::getFileOrSTDIN(filename);71  if (std::error_code ec = fileOrErr.getError()) {72    llvm::errs() << "Could not open input file: " << ec.message() << "\n";73    return nullptr;74  }75  auto buffer = fileOrErr.get()->getBuffer();76  LexerBuffer lexer(buffer.begin(), buffer.end(), std::string(filename));77  Parser parser(lexer);78  return parser.parseModule();79}80 81static int loadMLIR(llvm::SourceMgr &sourceMgr, mlir::MLIRContext &context,82                    mlir::OwningOpRef<mlir::ModuleOp> &module) {83  // Handle '.toy' input to the compiler.84  if (inputType != InputType::MLIR &&85      !llvm::StringRef(inputFilename).ends_with(".mlir")) {86    auto moduleAST = parseInputFile(inputFilename);87    if (!moduleAST)88      return 6;89    module = mlirGen(context, *moduleAST);90    return !module ? 1 : 0;91  }92 93  // Otherwise, the input is '.mlir'.94  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> fileOrErr =95      llvm::MemoryBuffer::getFileOrSTDIN(inputFilename);96  if (std::error_code ec = fileOrErr.getError()) {97    llvm::errs() << "Could not open input file: " << ec.message() << "\n";98    return -1;99  }100 101  // Parse the input mlir.102  sourceMgr.AddNewSourceBuffer(std::move(*fileOrErr), llvm::SMLoc());103  module = mlir::parseSourceFile<mlir::ModuleOp>(sourceMgr, &context);104  if (!module) {105    llvm::errs() << "Error can't load file " << inputFilename << "\n";106    return 3;107  }108  return 0;109}110 111static int dumpMLIR() {112  mlir::MLIRContext context;113  // Load our Dialect in this MLIR Context.114  context.getOrLoadDialect<mlir::toy::ToyDialect>();115 116  mlir::OwningOpRef<mlir::ModuleOp> module;117  llvm::SourceMgr sourceMgr;118  mlir::SourceMgrDiagnosticHandler sourceMgrHandler(sourceMgr, &context);119  if (int error = loadMLIR(sourceMgr, context, module))120    return error;121 122  if (enableOpt) {123    mlir::PassManager pm(module.get()->getName());124    // Apply any generic pass manager command line options and run the pipeline.125    if (mlir::failed(mlir::applyPassManagerCLOptions(pm)))126      return 4;127 128    // Add a run of the canonicalizer to optimize the mlir module.129    pm.addNestedPass<mlir::toy::FuncOp>(mlir::createCanonicalizerPass());130    if (mlir::failed(pm.run(*module)))131      return 4;132  }133 134  module->dump();135  return 0;136}137 138static int dumpAST() {139  if (inputType == InputType::MLIR) {140    llvm::errs() << "Can't dump a Toy AST when the input is MLIR\n";141    return 5;142  }143 144  auto moduleAST = parseInputFile(inputFilename);145  if (!moduleAST)146    return 1;147 148  dump(*moduleAST);149  return 0;150}151 152int main(int argc, char **argv) {153  // Register any command line options.154  mlir::registerAsmPrinterCLOptions();155  mlir::registerMLIRContextCLOptions();156  mlir::registerPassManagerCLOptions();157 158  cl::ParseCommandLineOptions(argc, argv, "toy compiler\n");159 160  switch (emitAction) {161  case Action::DumpAST:162    return dumpAST();163  case Action::DumpMLIR:164    return dumpMLIR();165  default:166    llvm::errs() << "No action specified (parsing only?), use -emit=<action>\n";167  }168 169  return 0;170}171