Make llvm_context a class.
This commit is contained in:
parent
55486d511f
commit
0e3f16139d
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue
Block a user