Skip to content

Commit

Permalink
feat: Functional modules system for both AOT and JIT
Browse files Browse the repository at this point in the history
  • Loading branch information
alinalihassan committed Mar 8, 2022
1 parent c451467 commit a8e9fee
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 41 deletions.
85 changes: 56 additions & 29 deletions src/Backend/Codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

using namespace lesma;

Codegen::Codegen(std::unique_ptr<Parser> parser, const std::string &filename) {
Codegen::Codegen(std::unique_ptr<Parser> parser, const std::string &filename, bool jit, bool main) {
InitializeNativeTarget();
InitializeNativeTargetAsmPrinter();
InitializeNativeTargetAsmParser();
Expand All @@ -17,14 +17,17 @@ Codegen::Codegen(std::unique_ptr<Parser> parser, const std::string &filename) {
Scope = new SymbolTable(nullptr);
TargetMachine = InitializeTargetMachine();

isJIT = jit;
isMain = main;

TopLevelFunc = InitializeTopLevel();
}

llvm::Function *Codegen::InitializeTopLevel() {
std::vector<llvm::Type *> paramTypes = {};

FunctionType *FT = FunctionType::get(Builder->getInt64Ty(), paramTypes, false);
Function *F = Function::Create(FT, Function::ExternalLinkage, "main", *TheModule);
Function *F = Function::Create(FT, isMain ? Function::ExternalLinkage : Function::InternalLinkage, "main", *TheModule);

auto entry = BasicBlock::Create(*TheContext, "entry", F);
Builder->SetInsertPoint(entry);
Expand Down Expand Up @@ -60,34 +63,49 @@ void Codegen::CompileModule(const std::string &filepath) {
auto parser = std::make_unique<Parser>(lexer->getTokens());
parser->Parse();

// TODO: Delete it, memory leak, smart pointer made us lose the references to other modules
// Codegen
auto codegen = std::make_unique<Codegen>(std::move(parser), filepath);
auto codegen = new Codegen(std::move(parser), filepath, isJIT, false);
codegen->Run();

// Optimize
codegen->Optimize(llvm::PassBuilder::OptimizationLevel::O3);
codegen->Dump();

codegen->TheModule->setModuleIdentifier(filepath);

// Add function to main module
// Module::iterator it;
// Module::iterator end = codegen->TheModule->end();
// for (it = codegen->TheModule->begin(); it != end; ++it) {
// auto name = std::string{(*it).getName()};
// auto new_func = Function::Create((*it).getFunctionType(),
// Function::ExternalLinkage,
// name,
// TheModule.get());
//
// Scope->insertSymbol(name, new_func, new_func->getFunctionType());
// }

// Link modules together
// if (Linker::linkModules(*codegen->TheModule, std::move(codegen->TheModule)))
// print(ERROR, "Error linking modules together\n");
if (isJIT) {
// Link modules together
if (Linker::linkModules(*TheModule, std::move(codegen->TheModule)))
print(ERROR, "Error linking modules together\n");

// Add function to main module
Module::iterator it;
Module::iterator end = TheModule->end();
for (it = TheModule->begin(); it != end; ++it) {
auto name = std::string{(*it).getName()};
if (!Scope->lookup(name))
Scope->insertSymbol(name, (Value *) &(*it).getFunction(), (*it).getFunctionType());
}

Modules.push_back(codegen->getModule());
Modules.push_back(codegen->getModule());
} else {
std::string obj_file = fmt::format("tmp{}", ObjectFiles.size());
codegen->WriteToObjectFile(obj_file);
ObjectFiles.push_back(fmt::format("{}.o", obj_file));

// Add function definitions
Module::iterator it;
Module::iterator end = codegen->TheModule->end();
for (it = codegen->TheModule->begin(); it != end; ++it) {
auto name = std::string{(*it).getName()};
auto new_func = Function::Create((*it).getFunctionType(),
Function::ExternalLinkage,
name,
*TheModule);

Scope->insertSymbol(name, new_func, new_func->getFunctionType());
}
}
}

void Codegen::Optimize(llvm::PassBuilder::OptimizationLevel opt) {
Expand Down Expand Up @@ -125,11 +143,15 @@ void Codegen::LinkObjectFile(const std::string &obj_filename) {
if (clangPath.getError())
throw CodegenError("Unable to find clang path\n");

std::string output = getBasename(obj_filename);

std::vector<const char *> args;
args.push_back(clangPath.get().c_str());
args.push_back(obj_filename.c_str());
for (const auto& obj: ObjectFiles)
args.push_back(obj.c_str());
args.push_back("-o");
args.push_back(getBasename(obj_filename).c_str());
args.push_back(output.c_str());

auto DiagOpts = new clang::DiagnosticOptions();
auto DiagID = new clang::DiagnosticIDs();
Expand All @@ -147,14 +169,20 @@ void Codegen::LinkObjectFile(const std::string &obj_filename) {

if (Res)
throw CodegenError("Linking Failed\n");

// Remove object files
remove(obj_filename.c_str());
for (const auto& obj: ObjectFiles)
remove(obj.c_str());
}

int Codegen::JIT(std::vector<ThreadSafeModule> modules) {
for (auto &module: modules) {
auto jit_error = TheJIT->addModule(std::move(module));
if (jit_error)
throw CodegenError("JIT Error:\n{}");
}
int Codegen::JIT() {
// Commented out for now, the linker seems to just copy the functions over to the main module
// for (auto &module: Modules) {
// auto jit_error = TheJIT->addModule(std::move(module));
// if (jit_error)
// throw CodegenError("JIT Error:\n{}");
// }
auto jit_error = TheJIT->addModule(ThreadSafeModule(std::move(TheModule), std::move(TheContext)));
if (jit_error)
throw CodegenError("JIT Error:\n{}");
Expand Down Expand Up @@ -748,7 +776,6 @@ std::string Codegen::getTypeMangledName(llvm::Type *type) {
return "(struct_" + param_str + ")";
}

type->print(outs());
throw CodegenError("Unknown type found during mangling");
}

Expand Down
11 changes: 8 additions & 3 deletions src/Backend/Codegen.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <llvm/IR/Module.h>
#include <llvm/IR/PassManager.h>
#include <llvm/IR/Verifier.h>
#include <llvm/Linker/Linker.h>
#include <llvm/Passes/PassBuilder.h>
#include <llvm/Support/Host.h>
#include <llvm/Support/Program.h>
Expand Down Expand Up @@ -45,20 +46,24 @@ namespace lesma {
std::stack<llvm::BasicBlock *> breakBlocks;
std::stack<llvm::BasicBlock *> continueBlocks;
std::stack<std::vector<llvm::Value *>> deferStack;

std::vector<ThreadSafeModule> Modules;
std::vector<std::string> ObjectFiles;
llvm::Function *TopLevelFunc;
bool isBreak = false;
bool isReturn = false;
bool isJIT = false;
bool isMain = true;

public:
std::vector<ThreadSafeModule> Modules;
Codegen(std::unique_ptr<Parser> parser, const std::string &filename);
Codegen(std::unique_ptr<Parser> parser, const std::string &filename, bool jit, bool main);

void Dump();
void Run();
int JIT();
void WriteToObjectFile(const std::string &output);
void LinkObjectFile(const std::string &obj_filename);
void Optimize(llvm::PassBuilder::OptimizationLevel opt);
int JIT(std::vector<ThreadSafeModule> modules);
ThreadSafeModule getModule() { return {std::move(TheModule), std::move(TheContext)}; };

protected:
Expand Down
7 changes: 2 additions & 5 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ int main(int argc, char **argv) {

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

// Optimization
Expand All @@ -63,12 +63,9 @@ int main(int argc, char **argv) {

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

// Remove Object File
TIMEIT("Remove Object File", remove(fmt::format("{}.o", options->output).c_str());)
} else {
// Executing
TIMEIT("Execution", exit_code = codegen->JIT(std::move(codegen->Modules));)
TIMEIT("Execution", exit_code = codegen->JIT();)
}

if (options->debug)
Expand Down
8 changes: 4 additions & 4 deletions tests/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Parser *initializeParser(Lexer *lexer) {
Codegen *initializeCodegen(Parser *parser) {
std::unique_ptr<Parser> parser_pointer;
parser_pointer.reset(parser);
auto codegen = new Codegen(std::move(parser_pointer), "");
auto codegen = new Codegen(std::move(parser_pointer), "", true, false);
codegen->Run();

return codegen;
Expand Down Expand Up @@ -101,7 +101,7 @@ TEST_CASE("Codegen", "Run & Optimize") {
auto parser = initializeParser(lexer);
auto codegen = initializeCodegen(parser);
codegen->Optimize(llvm::PassBuilder::OptimizationLevel::O3);
int exit_code = codegen->JIT(std::move(codegen->Modules));
int exit_code = codegen->JIT();

REQUIRE(exit_code == 0);

Expand All @@ -116,12 +116,12 @@ TEST_CASE("Codegen", "Run & Optimize") {

BENCHMARK("Codegen & JIT") {
auto cg = initializeCodegen(parser);
cg->JIT(std::move(codegen->Modules));
cg->JIT();
};

BENCHMARK("Codegen, Optimize & JIT") {
auto cg = initializeCodegen(parser);
cg->Optimize(llvm::PassBuilder::OptimizationLevel::O3);
cg->JIT(std::move(codegen->Modules));
cg->JIT();
};
}

0 comments on commit a8e9fee

Please sign in to comment.