147 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 "toy/AST.h"14#include "toy/Dialect.h"15#include "toy/Lexer.h"16#include "toy/MLIRGen.h"17#include "toy/Parser.h"18#include <memory>19#include <string>20#include <system_error>21#include <utility>22 23#include "mlir/IR/AsmState.h"24#include "mlir/IR/BuiltinOps.h"25#include "mlir/IR/MLIRContext.h"26#include "mlir/Parser/Parser.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 35using namespace toy;36namespace cl = llvm::cl;37 38static cl::opt<std::string> inputFilename(cl::Positional,39 cl::desc("<input toy file>"),40 cl::init("-"),41 cl::value_desc("filename"));42 43namespace {44enum InputType { Toy, MLIR };45} // namespace46static cl::opt<enum InputType> inputType(47 "x", cl::init(Toy), cl::desc("Decided the kind of output desired"),48 cl::values(clEnumValN(Toy, "toy", "load the input file as a Toy source.")),49 cl::values(clEnumValN(MLIR, "mlir",50 "load the input file as an MLIR file")));51 52namespace {53enum Action { None, DumpAST, DumpMLIR };54} // namespace55static cl::opt<enum Action> emitAction(56 "emit", cl::desc("Select the kind of output desired"),57 cl::values(clEnumValN(DumpAST, "ast", "output the AST dump")),58 cl::values(clEnumValN(DumpMLIR, "mlir", "output the MLIR dump")));59 60/// Returns a Toy AST resulting from parsing the file or a nullptr on error.61static std::unique_ptr<toy::ModuleAST>62parseInputFile(llvm::StringRef filename) {63 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> fileOrErr =64 llvm::MemoryBuffer::getFileOrSTDIN(filename);65 if (std::error_code ec = fileOrErr.getError()) {66 llvm::errs() << "Could not open input file: " << ec.message() << "\n";67 return nullptr;68 }69 auto buffer = fileOrErr.get()->getBuffer();70 LexerBuffer lexer(buffer.begin(), buffer.end(), std::string(filename));71 Parser parser(lexer);72 return parser.parseModule();73}74 75static int dumpMLIR() {76 mlir::MLIRContext context;77 // Load our Dialect in this MLIR Context.78 context.getOrLoadDialect<mlir::toy::ToyDialect>();79 80 // Handle '.toy' input to the compiler.81 if (inputType != InputType::MLIR &&82 !llvm::StringRef(inputFilename).ends_with(".mlir")) {83 auto moduleAST = parseInputFile(inputFilename);84 if (!moduleAST)85 return 6;86 mlir::OwningOpRef<mlir::ModuleOp> module = mlirGen(context, *moduleAST);87 if (!module)88 return 1;89 90 module->dump();91 return 0;92 }93 94 // Otherwise, the input is '.mlir'.95 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> fileOrErr =96 llvm::MemoryBuffer::getFileOrSTDIN(inputFilename);97 if (std::error_code ec = fileOrErr.getError()) {98 llvm::errs() << "Could not open input file: " << ec.message() << "\n";99 return -1;100 }101 102 // Parse the input mlir.103 llvm::SourceMgr sourceMgr;104 sourceMgr.AddNewSourceBuffer(std::move(*fileOrErr), llvm::SMLoc());105 mlir::OwningOpRef<mlir::ModuleOp> module =106 mlir::parseSourceFile<mlir::ModuleOp>(sourceMgr, &context);107 if (!module) {108 llvm::errs() << "Error can't load file " << inputFilename << "\n";109 return 3;110 }111 112 module->dump();113 return 0;114}115 116static int dumpAST() {117 if (inputType == InputType::MLIR) {118 llvm::errs() << "Can't dump a Toy AST when the input is MLIR\n";119 return 5;120 }121 122 auto moduleAST = parseInputFile(inputFilename);123 if (!moduleAST)124 return 1;125 126 dump(*moduleAST);127 return 0;128}129 130int main(int argc, char **argv) {131 // Register any command line options.132 mlir::registerAsmPrinterCLOptions();133 mlir::registerMLIRContextCLOptions();134 cl::ParseCommandLineOptions(argc, argv, "toy compiler\n");135 136 switch (emitAction) {137 case Action::DumpAST:138 return dumpAST();139 case Action::DumpMLIR:140 return dumpMLIR();141 default:142 llvm::errs() << "No action specified (parsing only?), use -emit=<action>\n";143 }144 145 return 0;146}147