main.cpp 4.35 KB
Newer Older
刘睿博's avatar
刘睿博 committed
1

lxq's avatar
lxq committed
2
#include "Module.hpp"
刘睿博's avatar
刘睿博 committed
3
#include "PassManager.hpp"
lyz's avatar
lyz committed
4
#include "ast.hpp"
lxq's avatar
lxq committed
5
#include "cminusf_builder.hpp"
jhe's avatar
lab3  
jhe committed
6
#include "CodeGen.hpp"
刘睿博's avatar
刘睿博 committed
7 8 9 10 11
#include "PassManager.hpp"
#include "DeadCode.hpp"
#include "Mem2Reg.hpp"
#include "LoopDetection.hpp"
#include "LICM.hpp"
lyz's avatar
lyz committed
12 13

#include <filesystem>
lxq's avatar
lxq committed
14
#include <fstream>
lyz's avatar
lyz committed
15 16 17 18 19 20
#include <iostream>
#include <string>

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

lxq's avatar
lxq committed
21
struct Config {
lyz's avatar
lyz committed
22 23 24 25 26
    string exe_name; // compiler exe name
    std::filesystem::path input_file;
    std::filesystem::path output_file;

    bool emitast{false};
jhe's avatar
lab3  
jhe committed
27
    bool emitasm{false};
lxq's avatar
lxq committed
28
    bool emitllvm{false};
刘睿博's avatar
刘睿博 committed
29 30 31
    // optization conifg
    bool mem2reg{false};
    bool licm{false};
lyz's avatar
lyz committed
32

lxq's avatar
lxq committed
33
    Config(int argc, char **argv) : argc(argc), argv(argv) {
lyz's avatar
lyz committed
34 35 36 37
        parse_cmd_line();
        check();
    }

lxq's avatar
lxq committed
38
  private:
lyz's avatar
lyz committed
39 40 41 42 43 44 45 46 47 48
    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
49
int main(int argc, char **argv) {
lyz's avatar
lyz committed
50
    Config config(argc, argv);
lxq's avatar
lxq committed
51

lyz's avatar
lyz committed
52 53
    auto syntax_tree = parse(config.input_file.c_str());
    auto ast = AST(syntax_tree);
lxq's avatar
lxq committed
54 55 56 57 58 59 60 61 62 63

    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();

刘睿博's avatar
刘睿博 committed
64 65 66 67 68 69 70 71 72 73 74 75
        PassManager PM(m.get());
        // optimization 
        if(config.mem2reg) {
            PM.add_pass<Mem2Reg>();
            PM.add_pass<DeadCode>();
        }
        if(config.licm) {
            PM.add_pass<LoopInvariantCodeMotion>();
            PM.add_pass<DeadCode>();
        }
        PM.run();

lxq's avatar
lxq committed
76 77 78 79 80 81
        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();
jhe's avatar
lab3  
jhe committed
82 83 84 85
        } else if (config.emitasm) {
            CodeGen codegen(m.get());
            codegen.run();
            output_stream << codegen.print();
lxq's avatar
lxq committed
86 87
        }
    }
lyz's avatar
lyz committed
88 89 90 91

    return 0;
}

lxq's avatar
lxq committed
92
void Config::parse_cmd_line() {
lyz's avatar
lyz committed
93
    exe_name = argv[0];
lxq's avatar
lxq committed
94 95
    for (int i = 1; i < argc; ++i) {
        if (argv[i] == "-h"s || argv[i] == "--help"s) {
lyz's avatar
lyz committed
96
            print_help();
lxq's avatar
lxq committed
97 98
        } else if (argv[i] == "-o"s) {
            if (output_file.empty() && i + 1 < argc) {
lyz's avatar
lyz committed
99 100
                output_file = argv[i + 1];
                i += 1;
lxq's avatar
lxq committed
101
            } else {
lyz's avatar
lyz committed
102 103
                print_err("bad output file");
            }
lxq's avatar
lxq committed
104
        } else if (argv[i] == "-emit-ast"s) {
lyz's avatar
lyz committed
105
            emitast = true;
jhe's avatar
lab3  
jhe committed
106 107
        } else if (argv[i] == "-S"s) {
            emitasm = true;
lxq's avatar
lxq committed
108 109
        } else if (argv[i] == "-emit-llvm"s) {
            emitllvm = true;
刘睿博's avatar
刘睿博 committed
110 111 112 113 114
        } else if (argv[i] == "-mem2reg"s) {
            mem2reg = true;
        } else if (argv[i] == "-licm"s) {
            licm = true;
        }else {
lxq's avatar
lxq committed
115
            if (input_file.empty()) {
lyz's avatar
lyz committed
116
                input_file = argv[i];
lxq's avatar
lxq committed
117
            } else {
lyz's avatar
lyz committed
118 119 120 121 122 123 124 125
                string err =
                    "unrecognized command-line option \'"s + argv[i] + "\'"s;
                print_err(err);
            }
        }
    }
}

lxq's avatar
lxq committed
126 127
void Config::check() {
    if (input_file.empty()) {
lyz's avatar
lyz committed
128 129
        print_err("no input file");
    }
lxq's avatar
lxq committed
130
    if (input_file.extension() != ".cminus") {
lyz's avatar
lyz committed
131 132
        print_err("file format not recognized");
    }
刘睿博's avatar
刘睿博 committed
133 134 135 136 137 138 139 140 141
    if (emitllvm and emitasm) {
        print_err("emit llvm and emit asm both set");
    }
    if (not emitllvm and not emitasm and not emitast) {
        print_err("not supported: generate executable file directly");
    }
    if (licm and not mem2reg) {
        print_err("licm must be used with mem2reg");
    }
lxq's avatar
lxq committed
142
    if (output_file.empty()) {
lyz's avatar
lyz committed
143
        output_file = input_file.stem();
刘睿博's avatar
刘睿博 committed
144 145 146 147 148
        if (emitllvm) {
            output_file.replace_extension(".ll");
        } else if (emitasm) {
            output_file.replace_extension(".s");
        }
lyz's avatar
lyz committed
149 150 151
    }
}

lxq's avatar
lxq committed
152
void Config::print_help() const {
lyz's avatar
lyz committed
153
    std::cout << "Usage: " << exe_name
刘睿博's avatar
刘睿博 committed
154 155
              << " [-h|--help] [-o <target-file>] [-emit-llvm] [-S] [-dump-json]"
                 "[-mem2reg] [-licm]"
lyz's avatar
lyz committed
156 157 158 159 160
                 "<input-file>"
              << std::endl;
    exit(0);
}

lxq's avatar
lxq committed
161
void Config::print_err(const string &msg) const {
lyz's avatar
lyz committed
162 163 164
    std::cout << exe_name << ": " << msg << std::endl;
    exit(-1);
}