Skip to content

Instantly share code, notes, and snippets.

@luizperes
Created December 8, 2016 01:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save luizperes/576df8b21c11e5dc039dc5ea944cf1cb to your computer and use it in GitHub Desktop.
Save luizperes/576df8b21c11e5dc039dc5ea944cf1cb to your computer and use it in GitHub Desktop.
/* This is the source code of Brain Programming Language.
* It is licensed under GNU GPL v. 3 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Brain, 2016.
*/
#include "Bootstrap.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Linker/Linker.h"
using namespace llvm;
// forward declaration of static member.
Bootstrap* Bootstrap::_instance = nullptr;
Bootstrap::Bootstrap()
{
}
Bootstrap* Bootstrap::instance()
{
if (_instance == nullptr) {
_instance = new Bootstrap;
}
return _instance;
}
int Bootstrap::init(int argc, char** argv)
{
ArgsHandler args_handler(argc, argv);
Parser parser(args_handler.get_string_file());
io_lib = std::string(getenv("HOME")) + "/.brain/lib/";
io_lib += ArgsOptions::instance()->get_io_option() == IO_REPL ? "io_repl.ll" : "io.ll";
if (ArgsOptions::instance()->has_option(BO_IS_EMITTING_CODE)) {
parser.ast_code_gen();
std::cout << "\n";
return 0;
}
module_name = args_handler.get_file_name();
// Create the context and the module
llvm::LLVMContext llvm_context;
llvm::SMDiagnostic err;
std::unique_ptr<llvm::Module> io_module;
if (ASTInfo::instance()->is_using_io_lib) {
io_module = llvm::parseIRFile(llvm::StringRef(io_lib), err,
llvm_context);
if (!io_module) {
err.print(argv[0], llvm::errs());
return -1;
}
}
llvm::ErrorOr<llvm::Module *> module_or_err = new llvm::Module(module_name,
llvm_context);
auto Owner = std::unique_ptr<llvm::Module>(module_or_err.get());
auto *module = Owner.get();
// Create the main function: "i32 @main()"
auto *MainF = llvm::cast<llvm::Function>(module->getOrInsertFunction("main", llvm::Type::getInt32Ty(llvm_context), (llvm::Type *)0));
// Create the entry block
auto *basic_block = llvm::BasicBlock::Create(llvm_context,
// Conventionnaly called:
"EntryBlock",
// Add it to "main" function
MainF);
// Create a builder to add instructions.
llvm::IRBuilder<> builder(basic_block);
// Insert the block to function.
builder.SetInsertPoint(basic_block);
// Generate IR code from parser.
parser.code_gen(module, builder);
// Return 0 to the "main" function.
builder.CreateRet(builder.getInt32(0));
if (ArgsOptions::instance()->has_option(BO_IS_EMITTING_AST)) {
std::cout << "=== Debug Information ===" << "\n";
parser.debug_description(0);
}
if(ArgsOptions::instance()->has_option(BO_IS_EMITTING_LLVM)) {
std::cout << "=== LLVM IR ===" << "\n";
std::string dumpStr;
llvm::raw_string_ostream dumpStrOstream(dumpStr);
module->print(dumpStrOstream, nullptr);
if (io_module) {
io_module->print(dumpStrOstream, nullptr);
}
std::cout << dumpStr;
}
// Default initialization.
llvm::InitializeNativeTarget();
llvm::InitializeNativeTargetAsmPrinter();
llvm::InitializeNativeTargetAsmParser();
auto module1 = new llvm::Module(module_name,
llvm_context);
Linker::linkModules(*module1, std::move(Owner));
Linker::linkModules(*module1, std::move(io_module));
auto mod = module1;
auto TargetTriple = sys::getDefaultTargetTriple();
mod->setTargetTriple(TargetTriple);
std::string Error;
auto Target = TargetRegistry::lookupTarget(TargetTriple, Error);
if (!Target) {
errs() << Error;
return 1;
}
auto CPU = "generic";
auto Features = "";
TargetOptions opt;
auto RM = Optional<Reloc::Model>();
auto TheTargetMachine =
Target->createTargetMachine(TargetTriple, CPU, Features, opt, RM);
mod->setDataLayout(TheTargetMachine->createDataLayout());
auto Filename = "output.o";
std::error_code EC;
raw_fd_ostream dest(Filename, EC, sys::fs::F_None);
if (EC) {
errs() << "Could not open file: " << EC.message();
return 1;
}
legacy::PassManager pass;
auto FileType = TargetMachine::CGFT_ObjectFile;
if (TheTargetMachine->addPassesToEmitFile(pass, dest, FileType)) {
errs() << "TheTargetMachine can't emit a file of this type";
return 1;
}
pass.run(*mod);
dest.flush();
outs() << "Wrote " << Filename << "\n";
// ========= NOT HERE
// Create the execution engine.
std::string error_str;
engine_builder = new llvm::EngineBuilder(std::move(Owner));
execution_engine = engine_builder->setErrorStr(&error_str)
.setMCJITMemoryManager(std::unique_ptr<llvm::SectionMemoryManager>
(new llvm::SectionMemoryManager())).create();
if (io_module) {
execution_engine->addModule(std::move(io_module));
}
if (!error_str.empty()) {
std::cout << error_str << "\n";
return -1;
}
// Finalize the execution engine before use it
execution_engine->finalizeObject();
if (ArgsOptions::instance()->has_option(BO_IS_EMITTING_AST) ||
ArgsOptions::instance()->has_option(BO_IS_EMITTING_LLVM)) {
// Run the program
std::cout << "=== Program Output ===" << "\n";
}
// No args.
std::vector<llvm::GenericValue> Args(0);
llvm::GenericValue gv = execution_engine->runFunction(MainF, Args);
llvm::llvm_shutdown();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment