Skip to content

Commit

Permalink
feat: Added driver class to be used by other projects (server wink wink)
Browse files Browse the repository at this point in the history
  • Loading branch information
alinalihassan committed Jun 2, 2022
1 parent 6c47745 commit 6d1be42
Show file tree
Hide file tree
Showing 5 changed files with 157 additions and 91 deletions.
6 changes: 4 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ set(CLANG_LIBS clangTooling)

# Executable configuration
set(CLI_NAME lesma)
set(TESTS_NAME tests)

set(COMMON_SOURCES
src/liblesma/Common/Utils.cpp
Expand All @@ -61,6 +62,7 @@ set(COMMON_SOURCES
src/liblesma/Backend/Codegen.cpp
src/liblesma/Symbol/SymbolTable.cpp
src/liblesma/Symbol/SymbolType.cpp
src/liblesma/Driver/Driver.cpp
)
set(CLI_SOURCES src/cli/main.cpp)
set(TEST_SOURCES tests/test.cpp)
Expand All @@ -71,8 +73,8 @@ set(COMMON_LIBS ${LLVM_LIBS} ${CLANG_LIBS} fmt nameof)
add_executable(${CLI_NAME} ${COMMON_SOURCES} ${CLI_SOURCES})
add_executable(tests ${COMMON_SOURCES} ${TEST_SOURCES})

target_link_libraries(${CLI_NAME} PRIVATE ${COMMON_LIBS} CLI11)
target_link_libraries(tests PRIVATE ${COMMON_LIBS} Catch2::Catch2)
target_link_libraries(${CLI_NAME} PRIVATE ${COMMON_LIBS} CLI11)
target_link_libraries(${TESTS_NAME} PRIVATE ${COMMON_LIBS} Catch2::Catch2)


# Tests
Expand Down
93 changes: 6 additions & 87 deletions src/cli/main.cpp
Original file line number Diff line number Diff line change
@@ -1,23 +1,12 @@
#include <vector>

#include "CLI/CLI.hpp"
#include "plf_nanotimer.h"

#include "liblesma/Backend/Codegen.h"
#include "liblesma/Frontend/Lexer.h"
#include "liblesma/Frontend/Parser.h"
#include "liblesma/Common/Utils.h"
#include "liblesma/Driver/Driver.h"

#include "llvm/Support/SourceMgr.h"
using namespace lesma;

#define TIMEIT(debug_operation, statements) \
timer.start(); \
statements \
results = timer.get_elapsed_ms(); \
total += results; \
if (options->timer) \
print(DEBUG, "{} -> {:.2f} ms\n", debug_operation, results);

std::unique_ptr<CLIOptions> parseCLI(int argc, char **argv) {
bool debug = false;
bool timer = false;
Expand Down Expand Up @@ -47,79 +36,9 @@ std::unique_ptr<CLIOptions> parseCLI(int argc, char **argv) {
}

int main(int argc, char **argv) {
// Configure Timer
plf::nanotimer timer;
double results, total = 0;

// Configure Source Manager
std::shared_ptr<SourceMgr> srcMgr = std::make_shared<SourceMgr>(SourceMgr());

// CLI Parsing
TIMEIT("CLI", auto options = parseCLI(argc, argv);)

try {
// Read Source
TIMEIT("File read",
auto buffer = MemoryBuffer::getFile(options->file);
if (buffer.getError() != std::error_code()) throw LesmaError(llvm::SMRange(), "Could not read file: {}", options->file);

srcMgr->AddNewSourceBuffer(std::move(*buffer), llvm::SMLoc());
auto source_str = srcMgr->getMemoryBuffer(1)->getBuffer().str();)

// Lexer
TIMEIT("Lexer scan",
auto lexer = std::make_unique<Lexer>(srcMgr);
lexer->ScanAll();)

if (options->debug) {
print(DEBUG, "TOKENS: \n");
for (const auto &tok: lexer->getTokens())
print("Token: {}\n", tok->Dump(srcMgr));
}

// Parser
TIMEIT("Parsing",
auto parser = std::make_unique<Parser>(lexer->getTokens());
parser->Parse();)

if (options->debug)
print(DEBUG, "AST:\n{}", parser->getAST()->toString(srcMgr.get(), "", true));

// Codegen
TIMEIT("Compiling",
std::vector<std::string> modules;
auto codegen = std::make_unique<Codegen>(std::move(parser), srcMgr, options->file, modules, options->jit, true);
codegen->Run();)

if (options->debug) {
print(DEBUG, "LLVM IR: \n");
codegen->Dump();
}

// Optimization
TIMEIT("Optimizing", codegen->Optimize(llvm::PassBuilder::OptimizationLevel::O3);)

int exit_code = 0;
if (!options->jit) {
// Compile to Object File
TIMEIT("Writing Object File", codegen->WriteToObjectFile(options->output);)

// Link Object File
TIMEIT("Linking Object File", codegen->LinkObjectFile(fmt::format("{}.o", options->output));)
} else {
// Executing
TIMEIT("Execution", exit_code = codegen->JIT();)
}

if (options->timer)
print(DEBUG, "Total -> {:.2f} ms\n", total);

return exit_code;
} catch (const LesmaError &err) {
if (!err.getSpan().isValid())
print(ERROR, err.what());
else
showInline(srcMgr.get(), err.getSpan(), err.what(), options->file, true);
return err.exit_code;
}
auto options = parseCLI(argc, argv);
auto *driver_options = new Options{SourceType::FILE, options->file,
static_cast<Debug>(options->debug ? (LEXER | AST | IR) : NONE), options->output, options->timer};
return options->jit ? Driver::Run(driver_options) : Driver::Compile(driver_options);
}
4 changes: 2 additions & 2 deletions src/liblesma/Common/Utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace lesma {
WARNING,
DEBUG,
SUCCESS,
NONE
CLEAR
};

struct CLIOptions {
Expand All @@ -45,7 +45,7 @@ namespace lesma {

template<typename S, typename... Args>
void print(const S &format_str, const Args &...args) {
print(NONE, format_str, args...);
print(CLEAR, format_str, args...);
}

void showInline(llvm::SourceMgr *srcMgr, llvm::SMRange span, const std::string &reason, const std::string &file, bool is_error);
Expand Down
104 changes: 104 additions & 0 deletions src/liblesma/Driver/Driver.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
#include "Driver.h"

#include "plf_nanotimer.h"

using namespace lesma;

#define TIMEIT(debug_operation, statements) \
timer.start(); \
statements \
results = timer.get_elapsed_ms(); \
total += results; \
if (options->timer) \
print(DEBUG, "{} -> {:.2f} ms\n", debug_operation, results);


int Driver::BaseCompile(Options *options, bool jit) {
// Configure Timer
plf::nanotimer timer;
double results, total = 0;

// Configure Source Manager
std::shared_ptr<llvm::SourceMgr> srcMgr = std::make_shared<llvm::SourceMgr>(llvm::SourceMgr());

try {
// Read Source
TIMEIT("File read",
if (options->sourceType == SourceType::FILE) {
auto buffer = llvm::MemoryBuffer::getFile(options->source);
if (buffer.getError() != std::error_code()) throw LesmaError(llvm::SMRange(), "Could not read file: {}", options->source);

srcMgr->AddNewSourceBuffer(std::move(*buffer), llvm::SMLoc());
}
else {
auto buffer = llvm::MemoryBuffer::getMemBuffer(options->source);
srcMgr->AddNewSourceBuffer(std::move(buffer), llvm::SMLoc());
})

// Lexer
TIMEIT("Lexer scan",
auto lexer = std::make_unique<Lexer>(srcMgr);
lexer->ScanAll();)

if (options->debug & LEXER) {
print(DEBUG, "TOKENS: \n");
for (const auto &tok: lexer->getTokens())
print("Token: {}\n", tok->Dump(srcMgr));
}

// Parser
TIMEIT("Parsing",
auto parser = std::make_unique<Parser>(lexer->getTokens());
parser->Parse();)

if (options->debug & AST)
print(DEBUG, "AST:\n{}", parser->getAST()->toString(srcMgr.get(), "", true));

// Codegen
TIMEIT("Compiling",
std::vector<std::string> modules;
auto codegen = std::make_unique<Codegen>(std::move(parser), srcMgr,
options->sourceType == FILE ? options->source : ".",
modules, jit, true);
codegen->Run();)

if (options->debug & IR) {
print(DEBUG, "LLVM IR: \n");
codegen->Dump();
}

// Optimization
TIMEIT("Optimizing", codegen->Optimize(llvm::PassBuilder::OptimizationLevel::O3);)

int exit_code = 0;
if (!jit) {
// Compile to Object File
TIMEIT("Writing Object File", codegen->WriteToObjectFile(options->output_filename);)

// Link Object File
TIMEIT("Linking Object File", codegen->LinkObjectFile(fmt::format("{}.o", options->output_filename));)
} else {
// Executing
TIMEIT("Execution", exit_code = codegen->JIT();)
}

if (options->timer)
print(DEBUG, "Total -> {:.2f} ms\n", total);

return exit_code;
} catch (const LesmaError &err) {
if (!err.getSpan().isValid())
print(ERROR, err.what());
else
showInline(srcMgr.get(), err.getSpan(), err.what(), options->source, true);
return err.exit_code;
}
}

int Driver::Run(lesma::Options *options) {
return BaseCompile(options, true);
}

int Driver::Compile(Options *options) {
return BaseCompile(options, false);
}
41 changes: 41 additions & 0 deletions src/liblesma/Driver/Driver.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#pragma once

#include <string>
#include <vector>

#include "liblesma/Backend/Codegen.h"
#include "liblesma/Frontend/Lexer.h"
#include "liblesma/Frontend/Parser.h"
#include "liblesma/Common/Utils.h"

#include "llvm/Support/SourceMgr.h"

namespace lesma {
enum SourceType {
FILE,
STRING,
};

enum Debug {
NONE = 0x00, // 00000000
LEXER = 0x01, // 00000001
AST = 0x02, // 00000010
IR = 0x04, // 00000100
};

struct Options {
SourceType sourceType;
std::string source;
Debug debug = NONE;
std::string output_filename = "output";
bool timer = false;
};

class Driver {
private:
static int BaseCompile(Options *options, bool jit);
public:
static int Run(Options *options);
static int Compile(Options *options);
};
}

0 comments on commit 6d1be42

Please sign in to comment.