diff --git a/include/backend/backend.h b/include/backend/backend.h index ba768cb..f3b97b0 100644 --- a/include/backend/backend.h +++ b/include/backend/backend.h @@ -17,13 +17,12 @@ class Backend { mlir::Value visit(shared_ptr); public: - shared_ptr ast; - explicit Backend(shared_ptr); + explicit Backend(); void codegen(std::ostream& outstream); void to_object(std::string filename); - shared_ptr traverse(); + shared_ptr traverse(shared_ptr ast); mlir::Value visit_block(shared_ptr); mlir::Value visit_integer_literal(shared_ptr); mlir::Value visit_character_literal(shared_ptr); diff --git a/include/compiler.h b/include/compiler.h new file mode 100644 index 0000000..044f5cc --- /dev/null +++ b/include/compiler.h @@ -0,0 +1,40 @@ +#pragma once + +#include + +#include "ANTLRFileStream.h" +#include "FusionLexer.h" +#include "ParseTree.h" +#include "ast/builder.h" +#include "ast/symbol/symbol_table.h" +#include "backend/backend.h" + +using std::shared_ptr, std::unique_ptr; + +class Compiler { + private: + shared_ptr symbol_table; + unique_ptr backend; + unique_ptr builder; + + antlr4::ANTLRFileStream* file; + fusion::FusionLexer* lexer; + antlr4::tree::ParseTree* tree; + antlr4::CommonTokenStream* tokens; + fusion::FusionParser* parser; + + public: + Compiler(std::string filename, + shared_ptr symbol_table, + unique_ptr backend, + unique_ptr builder); + ~Compiler(); + + void build_ast(); + void run_passes(); + void xml(); + + void build_backend(); + void to_object(std::string filename); + void codegen(std::ofstream& outfile); +}; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d908b3e..07cb699 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,6 +1,7 @@ set( fusion_src_files "${CMAKE_CURRENT_SOURCE_DIR}/main.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/compiler.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/backend/backend.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/backend/visitor.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/backend/io.cpp" diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index ceb2415..76d4c38 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -260,11 +260,11 @@ void ast::Function::xml(int level) { << type->get_name() << "\" name=\"" << name << "\" ref_name=\"" << ref_name << "\">\n"; - std::cout << std::string(level * 4, ' ') << "\n"; + std::cout << std::string((level + 1) * 4, ' ') << "\n"; for (const auto& param : params) { - param->xml(level + 1); + param->xml(level + 2); } - std::cout << std::string(level * 4, ' ') << "\n"; + std::cout << std::string((level + 1) * 4, ' ') << "\n"; body->xml(level + 1); std::cout << std::string(level * 4, ' ') << "\n"; diff --git a/src/backend/backend.cpp b/src/backend/backend.cpp index 3ef6ee5..0aff875 100644 --- a/src/backend/backend.cpp +++ b/src/backend/backend.cpp @@ -19,13 +19,12 @@ #include "mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h" #include "mlir/Target/LLVMIR/Export.h" -Backend::Backend(shared_ptr ast) { - this->ast = ast; +Backend::Backend() { ctx::builder->setInsertionPointToStart(ctx::module->getBody()); builtin::define_all(); } -shared_ptr Backend::traverse() { +shared_ptr Backend::traverse(shared_ptr ast) { visit(ast); if (mlir::failed(mlir::verify(*ctx::module))) { diff --git a/src/compiler.cpp b/src/compiler.cpp new file mode 100644 index 0000000..834eccd --- /dev/null +++ b/src/compiler.cpp @@ -0,0 +1,76 @@ +#include + +#include "ANTLRFileStream.h" +#include "CommonTokenStream.h" +#include "FusionLexer.h" +#include "FusionParser.h" +#include "ast/passes/pass.h" +#include "compiler.h" +#include "errors.h" + +Compiler::Compiler(std::string filename, + shared_ptr symbol_table, + unique_ptr backend, + unique_ptr builder) { + this->symbol_table = symbol_table; + this->backend = std::move(backend); + this->builder = std::move(builder); + + file = new antlr4::ANTLRFileStream(); + file->loadFromFile(filename); + + lexer = new fusion::FusionLexer(file); + tokens = new antlr4::CommonTokenStream(lexer); + parser = new fusion::FusionParser(tokens); + + tree = parser->file(); +} + +Compiler::~Compiler() { + delete file; + delete lexer; + delete tokens; + delete parser; +} + +void Compiler::build_ast() { + try { + builder->visit(tree); + assert(builder->has_ast()); + } catch (CompileTimeException const& e) { + std::cerr << e.what() << std::endl; + exit(1); + } +} + +void Compiler::run_passes() { + try { + Pass::run_passes(builder->get_ast(), symbol_table); + assert(builder->has_ast()); + } catch (CompileTimeException const& e) { + std::cerr << e.what() << std::endl; + exit(1); + } +} + +void Compiler::xml() { + builder->get_ast()->xml(0); +} + +void Compiler::build_backend() { + backend->traverse(this->builder->get_ast()); +} + +void Compiler::to_object(std::string filename) { + backend->to_object(filename + ".o"); + + std::string command = "clang " + filename + ".o -o " + filename; + system(command.c_str()); + + command = "rm " + filename + ".o"; + system(command.c_str()); +} + +void Compiler::codegen(std::ofstream& outfile) { + backend->codegen(outfile); +} diff --git a/src/main.cpp b/src/main.cpp index 83d959f..12e75f6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,87 +1,61 @@ -#include "FusionLexer.h" -#include "FusionParser.h" - -#include "ANTLRFileStream.h" -#include "CommonTokenStream.h" -#include "tree/ParseTree.h" - #include "ast/builder.h" #include "ast/passes/pass.h" #include "ast/symbol/symbol_table.h" #include "backend/backend.h" -#include "errors.h" +#include "compiler.h" #include "shared/context.h" #include +#include -int main(int argc, char** argv) { - antlr4::ANTLRFileStream afs; - afs.loadFromFile(argv[1]); - fusion::FusionLexer lexer(&afs); - antlr4::CommonTokenStream tokens(&lexer); - fusion::FusionParser parser(&tokens); - - antlr4::tree::ParseTree* tree = parser.file(); +using std::shared_ptr, std::unique_ptr, std::make_shared, std::make_unique; +int main(int argc, char** argv) { ctx::initialize_context(); - std::shared_ptr symtab = std::make_shared(); - Builder builder = Builder(symtab); + shared_ptr symbol_table = make_shared(); + unique_ptr builder = make_unique(symbol_table); + unique_ptr backend = make_unique(); + Compiler compiler = + Compiler(argv[1], symbol_table, std::move(backend), std::move(builder)); - try { - builder.visit(tree); - assert(builder.has_ast()); - for (size_t i = 0; i < argc; i++) { - std::string arg = std::string(argv[i]); - if (arg == "--xml") { - builder.get_ast()->xml(0); - } + compiler.build_ast(); + for (size_t i = 0; i < argc; i++) { + std::string arg = std::string(argv[i]); + if (arg == "--xml") { + compiler.xml(); } + } - Pass::run_passes(builder.get_ast(), symtab); - assert(builder.has_ast()); - for (size_t i = 0; i < argc; i++) { - std::string arg = std::string(argv[i]); - if (arg == "--pass-xml") { - builder.get_ast()->xml(0); - } + compiler.run_passes(); + for (size_t i = 0; i < argc; i++) { + std::string arg = std::string(argv[i]); + if (arg == "--pass-xml") { + compiler.xml(); } - } catch (CompileTimeException const& e) { - std::cerr << e.what() << std::endl; - return 1; } - Backend backend = Backend(builder.get_ast()); - backend.traverse(); - - // backend args + compiler.build_backend(); for (size_t i = 0; i < argc; i++) { std::string arg = std::string(argv[i]); if (arg == "--emit-llvm" && i == argc - 1) { - std::cerr << "You must provide a file to target llvm ir" - << std::endl; + std::cerr << "You must provide a file emit llvm ir to" << std::endl; return 1; } - if (arg == "-o" && i == argc - 1 && argv[i + 1][0] != '-') { - std::cerr << "You must provide a file to target" << std::endl; + if (arg == "-o" && i == argc - 1) { + std::cerr << "You must provide a file to compile" << std::endl; return 1; } if (arg == "-o") { std::string filename = std::string(argv[i + 1]); - backend.to_object(filename + ".o"); - - std::string command = "clang " + filename + ".o -o " + filename; - system(command.c_str()); - - command = "rm " + filename + ".o"; - system(command.c_str()); + compiler.to_object(filename); } if (arg == "--emit-llvm") { std::ofstream outfile(argv[i + 1]); - backend.codegen(outfile); + compiler.codegen(outfile); } }