Make llvm_context a class.

This commit is contained in:
Danila Fedorin 2020-09-15 19:08:00 -07:00
parent 55486d511f
commit 0e3f16139d
5 changed files with 109 additions and 84 deletions

View File

@ -87,11 +87,11 @@ void compiler::create_llvm_binop(binop op) {
instructions.push_back(instruction_ptr(new instruction_binop(op))); instructions.push_back(instruction_ptr(new instruction_binop(op)));
instructions.push_back(instruction_ptr(new instruction_update(2))); instructions.push_back(instruction_ptr(new instruction_update(2)));
instructions.push_back(instruction_ptr(new instruction_pop(2))); instructions.push_back(instruction_ptr(new instruction_pop(2)));
ctx.builder.SetInsertPoint(&new_function->getEntryBlock()); ctx.get_builder().SetInsertPoint(&new_function->getEntryBlock());
for(auto& instruction : instructions) { for(auto& instruction : instructions) {
instruction->gen_llvm(ctx, new_function); instruction->gen_llvm(ctx, new_function);
} }
ctx.builder.CreateRetVoid(); ctx.get_builder().CreateRetVoid();
} }
void compiler::create_llvm_bool(bool b) { void compiler::create_llvm_bool(bool b) {
@ -99,11 +99,11 @@ void compiler::create_llvm_bool(bool b) {
std::vector<instruction_ptr> instructions; std::vector<instruction_ptr> instructions;
instructions.push_back(instruction_ptr(new instruction_pushint(b))); instructions.push_back(instruction_ptr(new instruction_pushint(b)));
instructions.push_back(instruction_ptr(new instruction_update(0))); instructions.push_back(instruction_ptr(new instruction_update(0)));
ctx.builder.SetInsertPoint(&new_function->getEntryBlock()); ctx.get_builder().SetInsertPoint(&new_function->getEntryBlock());
for(auto& instruction : instructions) { for(auto& instruction : instructions) {
instruction->gen_llvm(ctx, new_function); instruction->gen_llvm(ctx, new_function);
} }
ctx.builder.CreateRetVoid(); ctx.get_builder().CreateRetVoid();
} }
void compiler::generate_llvm() { void compiler::generate_llvm() {
@ -136,8 +136,8 @@ void compiler::output_llvm(const std::string& into) {
target->createTargetMachine(targetTriple, cpu, features, target->createTargetMachine(targetTriple, cpu, features,
options, llvm::Optional<llvm::Reloc::Model>())); options, llvm::Optional<llvm::Reloc::Model>()));
ctx.module.setDataLayout(targetMachine->createDataLayout()); ctx.get_module().setDataLayout(targetMachine->createDataLayout());
ctx.module.setTargetTriple(targetTriple); ctx.get_module().setTargetTriple(targetTriple);
std::error_code ec; std::error_code ec;
llvm::raw_fd_ostream file(into, ec, llvm::sys::fs::F_None); llvm::raw_fd_ostream file(into, ec, llvm::sys::fs::F_None);
@ -149,7 +149,7 @@ void compiler::output_llvm(const std::string& into) {
if (targetMachine->addPassesToEmitFile(pm, file, NULL, type)) { if (targetMachine->addPassesToEmitFile(pm, file, NULL, type)) {
throw compiler_error("failed to add passes to pass manager"); throw compiler_error("failed to add passes to pass manager");
} else { } else {
pm.run(ctx.module); pm.run(ctx.get_module());
file.close(); file.close();
} }
} }

View File

@ -16,11 +16,11 @@ void global_function::declare_llvm(llvm_context& ctx) {
} }
void global_function::generate_llvm(llvm_context& ctx) { void global_function::generate_llvm(llvm_context& ctx) {
ctx.builder.SetInsertPoint(&generated_function->getEntryBlock()); ctx.get_builder().SetInsertPoint(&generated_function->getEntryBlock());
for(auto& instruction : instructions) { for(auto& instruction : instructions) {
instruction->gen_llvm(ctx, generated_function); instruction->gen_llvm(ctx, generated_function);
} }
ctx.builder.CreateRetVoid(); ctx.get_builder().CreateRetVoid();
} }
void global_constructor::generate_llvm(llvm_context& ctx) { void global_constructor::generate_llvm(llvm_context& ctx) {
@ -29,11 +29,11 @@ void global_constructor::generate_llvm(llvm_context& ctx) {
std::vector<instruction_ptr> instructions; std::vector<instruction_ptr> instructions;
instructions.push_back(instruction_ptr(new instruction_pack(tag, arity))); instructions.push_back(instruction_ptr(new instruction_pack(tag, arity)));
instructions.push_back(instruction_ptr(new instruction_update(0))); instructions.push_back(instruction_ptr(new instruction_update(0)));
ctx.builder.SetInsertPoint(&new_function->getEntryBlock()); ctx.get_builder().SetInsertPoint(&new_function->getEntryBlock());
for (auto& instruction : instructions) { for (auto& instruction : instructions) {
instruction->gen_llvm(ctx, new_function); instruction->gen_llvm(ctx, new_function);
} }
ctx.builder.CreateRetVoid(); ctx.get_builder().CreateRetVoid();
} }
global_function& global_scope::add_function( global_function& global_scope::add_function(

View File

@ -24,9 +24,9 @@ void instruction_pushglobal::print(int indent, std::ostream& to) const {
} }
void instruction_pushglobal::gen_llvm(llvm_context& ctx, Function* f) const { void instruction_pushglobal::gen_llvm(llvm_context& ctx, Function* f) const {
auto& global_f = ctx.custom_functions.at("f_" + name); auto& global_f = ctx.get_custom_function(name);
auto arity = ctx.create_i32(global_f->arity); auto arity = ctx.create_i32(global_f.arity);
ctx.create_push(f, ctx.create_global(f, global_f->function, arity)); ctx.create_push(f, ctx.create_global(f, global_f.function, arity));
} }
void instruction_push::print(int indent, std::ostream& to) const { void instruction_push::print(int indent, std::ostream& to) const {
@ -101,17 +101,17 @@ void instruction_jump::print(int indent, std::ostream& to) const {
void instruction_jump::gen_llvm(llvm_context& ctx, Function* f) const { void instruction_jump::gen_llvm(llvm_context& ctx, Function* f) const {
auto top_node = ctx.create_peek(f, ctx.create_size(0)); auto top_node = ctx.create_peek(f, ctx.create_size(0));
auto tag = ctx.unwrap_data_tag(top_node); auto tag = ctx.unwrap_data_tag(top_node);
auto safety_block = BasicBlock::Create(ctx.ctx, "safety", f); auto safety_block = ctx.create_basic_block("safety", f);
auto switch_op = ctx.builder.CreateSwitch(tag, safety_block, tag_mappings.size()); auto switch_op = ctx.get_builder().CreateSwitch(tag, safety_block, tag_mappings.size());
std::vector<BasicBlock*> blocks; std::vector<BasicBlock*> blocks;
for(auto& branch : branches) { for(auto& branch : branches) {
auto branch_block = BasicBlock::Create(ctx.ctx, "branch", f); auto branch_block = ctx.create_basic_block("branch", f);
ctx.builder.SetInsertPoint(branch_block); ctx.get_builder().SetInsertPoint(branch_block);
for(auto& instruction : branch) { for(auto& instruction : branch) {
instruction->gen_llvm(ctx, f); instruction->gen_llvm(ctx, f);
} }
ctx.builder.CreateBr(safety_block); ctx.get_builder().CreateBr(safety_block);
blocks.push_back(branch_block); blocks.push_back(branch_block);
} }
@ -119,7 +119,7 @@ void instruction_jump::gen_llvm(llvm_context& ctx, Function* f) const {
switch_op->addCase(ctx.create_i8(mapping.first), blocks[mapping.second]); switch_op->addCase(ctx.create_i8(mapping.first), blocks[mapping.second]);
} }
ctx.builder.SetInsertPoint(safety_block); ctx.get_builder().SetInsertPoint(safety_block);
} }
void instruction_if::print(int indent, std::ostream& to) const { void instruction_if::print(int indent, std::ostream& to) const {
@ -140,25 +140,25 @@ void instruction_if::gen_llvm(llvm_context& ctx, llvm::Function* f) const {
auto top_node = ctx.create_peek(f, ctx.create_size(0)); auto top_node = ctx.create_peek(f, ctx.create_size(0));
auto num = ctx.unwrap_num(top_node); auto num = ctx.unwrap_num(top_node);
auto nonzero_block = BasicBlock::Create(ctx.ctx, "nonzero", f); auto nonzero_block = ctx.create_basic_block("nonzero", f);
auto zero_block = BasicBlock::Create(ctx.ctx, "zero", f); auto zero_block = ctx.create_basic_block("zero", f);
auto resume_block = BasicBlock::Create(ctx.ctx, "resume", f); auto resume_block = ctx.create_basic_block("resume", f);
auto switch_op = ctx.builder.CreateSwitch(num, nonzero_block, 2); auto switch_op = ctx.get_builder().CreateSwitch(num, nonzero_block, 2);
switch_op->addCase(ctx.create_i32(0), zero_block); switch_op->addCase(ctx.create_i32(0), zero_block);
ctx.builder.SetInsertPoint(nonzero_block); ctx.get_builder().SetInsertPoint(nonzero_block);
for(auto& instruction : on_true) { for(auto& instruction : on_true) {
instruction->gen_llvm(ctx, f); instruction->gen_llvm(ctx, f);
} }
ctx.builder.CreateBr(resume_block); ctx.get_builder().CreateBr(resume_block);
ctx.builder.SetInsertPoint(zero_block); ctx.get_builder().SetInsertPoint(zero_block);
for(auto& instruction : on_false) { for(auto& instruction : on_false) {
instruction->gen_llvm(ctx, f); instruction->gen_llvm(ctx, f);
} }
ctx.builder.CreateBr(resume_block); ctx.get_builder().CreateBr(resume_block);
ctx.builder.SetInsertPoint(resume_block); ctx.get_builder().SetInsertPoint(resume_block);
} }
void instruction_slide::print(int indent, std::ostream& to) const { void instruction_slide::print(int indent, std::ostream& to) const {
@ -180,13 +180,13 @@ void instruction_binop::gen_llvm(llvm_context& ctx, Function* f) const {
auto right_int = ctx.unwrap_num(ctx.create_pop(f)); auto right_int = ctx.unwrap_num(ctx.create_pop(f));
llvm::Value* result; llvm::Value* result;
switch(op) { switch(op) {
case PLUS: result = ctx.builder.CreateAdd(left_int, right_int); break; case PLUS: result = ctx.get_builder().CreateAdd(left_int, right_int); break;
case MINUS: result = ctx.builder.CreateSub(left_int, right_int); break; case MINUS: result = ctx.get_builder().CreateSub(left_int, right_int); break;
case TIMES: result = ctx.builder.CreateMul(left_int, right_int); break; case TIMES: result = ctx.get_builder().CreateMul(left_int, right_int); break;
case DIVIDE: result = ctx.builder.CreateSDiv(left_int, right_int); break; case DIVIDE: result = ctx.get_builder().CreateSDiv(left_int, right_int); break;
case MODULO: result = ctx.builder.CreateSRem(left_int, right_int); break; case MODULO: result = ctx.get_builder().CreateSRem(left_int, right_int); break;
case EQUALS: result = ctx.builder.CreateICmpEQ(left_int, right_int); break; case EQUALS: result = ctx.get_builder().CreateICmpEQ(left_int, right_int); break;
case LESS_EQUALS: result = ctx.builder.CreateICmpSLE(left_int, right_int); break; case LESS_EQUALS: result = ctx.get_builder().CreateICmpSLE(left_int, right_int); break;
} }
ctx.create_push(f, ctx.create_num(f, result)); ctx.create_push(f, ctx.create_num(f, result));
} }

View File

@ -163,6 +163,18 @@ void llvm_context::create_functions() {
); );
} }
IRBuilder<>& llvm_context::get_builder() {
return builder;
}
Module& llvm_context::get_module() {
return module;
}
BasicBlock* llvm_context::create_basic_block(const std::string& name, llvm::Function* f) {
return BasicBlock::Create(ctx, name, f);
}
ConstantInt* llvm_context::create_i8(int8_t i) { ConstantInt* llvm_context::create_i8(int8_t i) {
return ConstantInt::get(ctx, APInt(8, i)); return ConstantInt::get(ctx, APInt(8, i));
} }
@ -254,7 +266,7 @@ Value* llvm_context::create_app(Function* f, Value* l, Value* r) {
return create_track(f, alloc_app_call); return create_track(f, alloc_app_call);
} }
llvm::Function* llvm_context::create_custom_function(std::string name, int32_t arity) { llvm::Function* llvm_context::create_custom_function(const std::string& name, int32_t arity) {
auto void_type = llvm::Type::getVoidTy(ctx); auto void_type = llvm::Type::getVoidTy(ctx);
auto new_function = llvm::Function::Create( auto new_function = llvm::Function::Create(
function_type, function_type,
@ -271,3 +283,7 @@ llvm::Function* llvm_context::create_custom_function(std::string name, int32_t a
return new_function; return new_function;
} }
llvm_context::custom_function& llvm_context::get_custom_function(const std::string& name) {
return *custom_functions.at("f_" + name);
}

View File

@ -7,7 +7,8 @@
#include <llvm/IR/Value.h> #include <llvm/IR/Value.h>
#include <map> #include <map>
struct llvm_context { class llvm_context {
public:
struct custom_function { struct custom_function {
llvm::Function* function; llvm::Function* function;
int32_t arity; int32_t arity;
@ -15,6 +16,7 @@ struct llvm_context {
using custom_function_ptr = std::unique_ptr<custom_function>; using custom_function_ptr = std::unique_ptr<custom_function>;
private:
llvm::LLVMContext ctx; llvm::LLVMContext ctx;
llvm::IRBuilder<> builder; llvm::IRBuilder<> builder;
llvm::Module module; llvm::Module module;
@ -31,14 +33,20 @@ struct llvm_context {
llvm::IntegerType* tag_type; llvm::IntegerType* tag_type;
llvm::FunctionType* function_type; llvm::FunctionType* function_type;
void create_types();
void create_functions();
public:
llvm_context() llvm_context()
: builder(ctx), module("bloglang", ctx) { : builder(ctx), module("bloglang", ctx) {
create_types(); create_types();
create_functions(); create_functions();
} }
void create_types(); llvm::IRBuilder<>& get_builder();
void create_functions(); llvm::Module& get_module();
llvm::BasicBlock* create_basic_block(const std::string& name, llvm::Function* f);
llvm::ConstantInt* create_i8(int8_t); llvm::ConstantInt* create_i8(int8_t);
llvm::ConstantInt* create_i32(int32_t); llvm::ConstantInt* create_i32(int32_t);
@ -68,5 +76,6 @@ struct llvm_context {
llvm::Value* create_app(llvm::Function*, llvm::Value*, llvm::Value*); llvm::Value* create_app(llvm::Function*, llvm::Value*, llvm::Value*);
llvm::Function* create_custom_function(std::string name, int32_t arity); llvm::Function* create_custom_function(const std::string& name, int32_t arity);
custom_function& get_custom_function(const std::string& name);
}; };