main.cpp 2.99 KB
Newer Older
lxq's avatar
lxq committed
1
#include "Module.hpp"
lyz's avatar
lyz committed
2
#include "ast.hpp"
lxq's avatar
lxq committed
3
#include "cminusf_builder.hpp"
lyz's avatar
lyz committed
4 5

#include <filesystem>
lxq's avatar
lxq committed
6
#include <fstream>
lyz's avatar
lyz committed
7 8 9 10 11 12
#include <iostream>
#include <string>

using std::string;
using std::operator""s;

lxq's avatar
lxq committed
13
struct Config {
lyz's avatar
lyz committed
14 15 16 17 18
    string exe_name; // compiler exe name
    std::filesystem::path input_file;
    std::filesystem::path output_file;

    bool emitast{false};
lxq's avatar
lxq committed
19
    bool emitllvm{false};
lyz's avatar
lyz committed
20

lxq's avatar
lxq committed
21
    Config(int argc, char **argv) : argc(argc), argv(argv) {
lyz's avatar
lyz committed
22 23 24 25
        parse_cmd_line();
        check();
    }

lxq's avatar
lxq committed
26
  private:
lyz's avatar
lyz committed
27 28 29 30 31 32 33 34 35 36
    int argc{-1};
    char **argv{nullptr};

    void parse_cmd_line();
    void check();
    // print helper infomation and exit
    void print_help() const;
    void print_err(const string &msg) const;
};

lxq's avatar
lxq committed
37
int main(int argc, char **argv) {
lyz's avatar
lyz committed
38
    Config config(argc, argv);
lxq's avatar
lxq committed
39

lyz's avatar
lyz committed
40 41
    auto syntax_tree = parse(config.input_file.c_str());
    auto ast = AST(syntax_tree);
lxq's avatar
lxq committed
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61

    if (config.emitast) { // if emit ast (lab1), print ast and return
        ASTPrinter printer;
        ast.run_visitor(printer);
    } else {
        std::unique_ptr<Module> m;
        CminusfBuilder builder;
        ast.run_visitor(builder);
        m = builder.getModule();

        std::ofstream output_stream(config.output_file);
        if (config.emitllvm) {
            auto abs_path = std::filesystem::canonical(config.input_file);
            output_stream << "; ModuleID = 'cminus'\n";
            output_stream << "source_filename = " << abs_path << "\n\n";
            output_stream << m->print();
        }

        // TODO: lab3 lab4 (IR optimization or codegen)
    }
lyz's avatar
lyz committed
62 63 64 65

    return 0;
}

lxq's avatar
lxq committed
66
void Config::parse_cmd_line() {
lyz's avatar
lyz committed
67
    exe_name = argv[0];
lxq's avatar
lxq committed
68 69
    for (int i = 1; i < argc; ++i) {
        if (argv[i] == "-h"s || argv[i] == "--help"s) {
lyz's avatar
lyz committed
70
            print_help();
lxq's avatar
lxq committed
71 72
        } else if (argv[i] == "-o"s) {
            if (output_file.empty() && i + 1 < argc) {
lyz's avatar
lyz committed
73 74
                output_file = argv[i + 1];
                i += 1;
lxq's avatar
lxq committed
75
            } else {
lyz's avatar
lyz committed
76 77
                print_err("bad output file");
            }
lxq's avatar
lxq committed
78
        } else if (argv[i] == "-emit-ast"s) {
lyz's avatar
lyz committed
79
            emitast = true;
lxq's avatar
lxq committed
80 81 82 83
        } else if (argv[i] == "-emit-llvm"s) {
            emitllvm = true;
        } else {
            if (input_file.empty()) {
lyz's avatar
lyz committed
84
                input_file = argv[i];
lxq's avatar
lxq committed
85
            } else {
lyz's avatar
lyz committed
86 87 88 89 90 91 92 93
                string err =
                    "unrecognized command-line option \'"s + argv[i] + "\'"s;
                print_err(err);
            }
        }
    }
}

lxq's avatar
lxq committed
94 95
void Config::check() {
    if (input_file.empty()) {
lyz's avatar
lyz committed
96 97
        print_err("no input file");
    }
lxq's avatar
lxq committed
98
    if (input_file.extension() != ".cminus") {
lyz's avatar
lyz committed
99 100
        print_err("file format not recognized");
    }
lxq's avatar
lxq committed
101
    if (output_file.empty()) {
lyz's avatar
lyz committed
102 103 104 105
        output_file = input_file.stem();
    }
}

lxq's avatar
lxq committed
106
void Config::print_help() const {
lyz's avatar
lyz committed
107 108 109 110 111 112 113
    std::cout << "Usage: " << exe_name
              << " [-h|--help] [-o <target-file>] [-mem2reg] [-emit-llvm] [-S] "
                 "<input-file>"
              << std::endl;
    exit(0);
}

lxq's avatar
lxq committed
114
void Config::print_err(const string &msg) const {
lyz's avatar
lyz committed
115 116 117
    std::cout << exe_name << ": " << msg << std::endl;
    exit(-1);
}