This repository has been archived on 2024-03-07. You can view files and clone it, but cannot push or open issues/pull-requests.
wongola/lib/Compiler.cpp

133 lines
3.5 KiB
C++
Raw Normal View History

#include "Compiler.hpp"
2023-09-27 21:05:04 +00:00
#include <llvm/IR/BasicBlock.h>
#include <llvm/TargetParser/Host.h>
#include <llvm/Target/TargetOptions.h>
#include <llvm/Target/TargetMachine.h>
#include <llvm/Support/TargetSelect.h>
#include <llvm/Support/FileSystem.h>
#include <llvm/MC/TargetRegistry.h>
#include <llvm/IR/LegacyPassManager.h>
namespace wg
{
/*explicit*/ Compiler::Compiler()
{
}
/*virtual*/ Compiler::~Compiler()
{
}
2023-09-27 21:05:04 +00:00
void Compiler::gen()
{
2023-09-27 21:05:04 +00:00
auto target_triple = llvm::sys::getDefaultTargetTriple();
llvm::InitializeAllTargetInfos();
llvm::InitializeAllTargets();
llvm::InitializeAllTargetMCs();
llvm::InitializeAllAsmParsers();
llvm::InitializeAllAsmPrinters();
std::string err;
auto target = llvm::TargetRegistry::lookupTarget(target_triple, err);
if (!target)
{
llvm::errs() << err;
abort();
}
auto cpu = "generic";
auto features = "";
llvm::TargetOptions opt;
auto rm = std::optional<llvm::Reloc::Model>();
auto target_machine = target->createTargetMachine(target_triple,
cpu,
features,
opt,
rm);
m_module->setDataLayout(target_machine->createDataLayout());
m_module->setTargetTriple(target_triple);
auto filename = "output.o";
std::error_code ec;
llvm::raw_fd_ostream dest(filename, ec, llvm::sys::fs::OF_None);
WG_ASSERT(!ec, "cannot write output file.");
llvm::legacy::PassManager pass;
auto file_type = llvm::CodeGenFileType::CGFT_ObjectFile;
if (target_machine->addPassesToEmitFile(pass, dest, nullptr, file_type))
{
llvm::errs() << "Target machine cannot emit a file of this type";
}
pass.run(*m_module);
dest.flush();
m_module->print(llvm::outs(), nullptr);
}
llvm::Value* Compiler::compile(std::shared_ptr<Node> node)
{
switch (node->type())
{
case NODE_PROG: {
auto* block = llvm::BasicBlock::Create(*m_context,
"entry");
m_builder->SetInsertPoint(block);
for (size_t i=0; i<node->size(); i++)
{
compile(node->child(i));
}
return block;
} break;
case NODE_ADD: {
auto* lhs = compile(node->child(0));
auto* rhs = compile(node->child(1));
return m_builder->CreateAdd(lhs, rhs);
} break;
case NODE_SUB: {
auto* lhs = compile(node->child(0));
auto* rhs = compile(node->child(1));
return m_builder->CreateSub(lhs, rhs);
} break;
case NODE_MUL: {
auto* lhs = compile(node->child(0));
auto* rhs = compile(node->child(1));
return m_builder->CreateMul(lhs, rhs);
} break;
case NODE_DIV: {
auto* lhs = compile(node->child(0));
auto* rhs = compile(node->child(1));
return m_builder->CreateSDiv(lhs, rhs);
} break;
case NODE_MOD: {
auto* lhs = compile(node->child(0));
auto* rhs = compile(node->child(1));
return m_builder->CreateSRem(lhs, rhs);
} break;
case NODE_INT: {
return llvm::ConstantInt::get(*m_context, llvm::APInt(32, 0, true));
} break;
default:
WG_ASSERT(false,
std::string()
+ "cannot compile unknown node '"
+ NodeTypeStr[node->type()]
+ "'");
}
}
}