lily/src/gmachine.cpp

191 lines
7.0 KiB
C++

#include "gmachine.hpp"
#include <iostream>
namespace lily {
std::ostream& operator<<(std::ostream& os, instruction& inst) {
inst.to_stream(os);
return os;
}
std::ostream& instruction_slide::to_stream(std::ostream& os) {
os << "slide(" << amount << ")";
return os;
}
std::ostream& instruction_alloc::to_stream(std::ostream& os) {
os << "alloc(" << amount << ")";
return os;
}
std::ostream& instruction_pop::to_stream(std::ostream& os) {
os << "pop(" << amount << ")";
return os;
}
std::ostream& instruction_unwind::to_stream(std::ostream& os) {
os << "unwind";
return os;
}
std::ostream& instruction_push_global::to_stream(std::ostream& os) {
os << "pushglobal(" << name << ")";
return os;
}
std::ostream& instruction_push_int::to_stream(std::ostream& os) {
os << "pushint(" << value << ")";
return os;
}
std::ostream& instruction_push_str::to_stream(std::ostream& os) {
os << "pushstr(" << str << ")";
return os;
}
std::ostream& instruction_push::to_stream(std::ostream& os) {
os << "push(" << offset << ")";
return os;
}
std::ostream& instruction_mkapp::to_stream(std::ostream& os) {
os << "mkapp";
return os;
}
std::ostream& instruction_eval::to_stream(std::ostream& os) {
os << "eval";
return os;
}
std::ostream& instruction_op::to_stream(std::ostream& os) {
os << "op(" << op_supercombinator(op) << ")";
return os;
}
std::ostream& instruction_cond::to_stream(std::ostream& os) {
os << "cond";
return os;
}
std::ostream& instruction_update::to_stream(std::ostream& os) {
os << "update(" << offset << ")";
return os;
}
std::ostream& instruction_pack::to_stream(std::ostream& os) {
os << "pack(" << constructor << ", " << arity << ")";
return os;
}
std::ostream& instruction_split::to_stream(std::ostream& os) {
os << "split(" << arity << ")";
return os;
}
std::ostream& instruction_jump::to_stream(std::ostream& os) {
os << "jump";
return os;
}
void instruction_slide::gen_llvm(llvm_context& ctx) {
llvm::Value* stack = ctx.get_current_function()->arg_begin();
builder.CreateCall(stack_slide_func, { stack, get_int32_constant(amount) });
}
void instruction_alloc::gen_llvm(llvm_context& ctx) {
llvm::Value* stack = ctx.get_current_function()->arg_begin();
builder.CreateCall(stack_alloc_func, { stack, get_int32_constant(amount) });
}
void instruction_pop::gen_llvm(llvm_context& ctx) {
llvm::Value* stack = ctx.get_current_function()->arg_begin();
builder.CreateCall(stack_popn_func, { stack, get_int32_constant(amount) });
}
void instruction_unwind::gen_llvm(llvm_context& ctx) {
}
void instruction_push_global::gen_llvm(llvm_context& ctx) {
llvm::Value* stack = ctx.get_current_function()->arg_begin();
llvm::Value* new_node = builder.CreateCall(malloc_node_global_func,
{ get_int8_constant(2), ctx.get_supercombinator(name) }, "temp");
// TODO get arity
builder.CreateCall(stack_push_func, { stack, new_node });
}
void instruction_push_int::gen_llvm(llvm_context& ctx) {
llvm::Value* stack = ctx.get_current_function()->arg_begin();
llvm::Value* new_node = builder.CreateCall(malloc_node_num_func,
{ get_int32_constant(value) });
builder.CreateCall(stack_push_func, { stack, new_node });
}
void instruction_push_str::gen_llvm(llvm_context& ctx) {
}
void instruction_push::gen_llvm(llvm_context& ctx) {
llvm::Value* stack = ctx.get_current_function()->arg_begin();
llvm::Value* peeked = builder.CreateCall(stack_peek_func, { stack, get_int32_constant(offset) }, "temp");
builder.CreateCall(stack_push_func, { stack, peeked });
}
void instruction_mkapp::gen_llvm(llvm_context& ctx) {
llvm::Value* stack = ctx.get_current_function()->arg_begin();
llvm::Value* func = builder.CreateCall(stack_pop_func, { stack }, "temp");
llvm::Value* param = builder.CreateCall(stack_pop_func, { stack }, "temp");
llvm::Value* app_node = builder.CreateCall(malloc_node_app_func, { func, param }, "temp");
builder.CreateCall(stack_push_func, { stack, app_node });
}
void instruction_eval::gen_llvm(llvm_context& ctx) {
llvm::Value* stack = ctx.get_current_function()->arg_begin();
llvm::Value* top = builder.CreateCall(stack_pop_func, { stack }, "temp");
llvm::Value* evaluated = builder.CreateCall(eval_func, { top }, "temp");
builder.CreateCall(stack_push_func, { stack, evaluated });
}
void instruction_op::gen_llvm(llvm_context& ctx) {
llvm::Value* stack = ctx.get_current_function()->arg_begin();
llvm::Value* param1 = builder.CreateCall(stack_pop_func, { stack }, "temp");
llvm::Value* param2 = builder.CreateCall(stack_pop_func, { stack }, "temp");
llvm::Value* param1_node_num = builder.CreatePointerCast(param1, llvm::PointerType::getUnqual(node_num_type), "temp");
llvm::Value* param2_node_num = builder.CreatePointerCast(param2, llvm::PointerType::getUnqual(node_num_type), "temp");
llvm::Value* param1_intptr = builder.CreateGEP(param1_node_num, { get_int32_constant(0), get_int32_constant(1) }, "temp");
llvm::Value* param2_intptr = builder.CreateGEP(param2_node_num, { get_int32_constant(0), get_int32_constant(1) }, "temp");
llvm::Value* param1_int = builder.CreateLoad(llvm::IntegerType::get(context, 32), param1_intptr, "temp");
llvm::Value* param2_int = builder.CreateLoad(llvm::IntegerType::get(context, 32), param2_intptr, "temp");
llvm::Value* op_result;
switch(op) {
case binop::add: op_result = builder.CreateAdd(param2_int, param1_int, "temp"); break;
case binop::subtract: op_result = builder.CreateSub(param2_int, param1_int, "temp"); break;
case binop::times: op_result = builder.CreateMul(param2_int, param1_int, "temp"); break;
case binop::divide: op_result = builder.CreateSDiv(param2_int, param1_int, "temp"); break;
}
llvm::Value* new_node = builder.CreateCall(malloc_node_num_func, { op_result }, "temp");
builder.CreateCall(stack_push_func, { stack, new_node });
}
void instruction_cond::gen_llvm(llvm_context& ctx) {
}
void instruction_update::gen_llvm(llvm_context& ctx) {
llvm::Value* stack = ctx.get_current_function()->arg_begin();
builder.CreateCall(stack_update_func, { stack, get_int32_constant(offset) });
}
void instruction_pack::gen_llvm(llvm_context& ctx) {
}
void instruction_split::gen_llvm(llvm_context& ctx) {
}
void instruction_jump::gen_llvm(llvm_context& ctx) {
}
}