Track allocated nodes using a G-machine struct in compiler series.
This commit is contained in:
parent
ecc1091c0a
commit
30579afc6d
|
@ -15,7 +15,7 @@ void instruction_pushint::print(int indent, std::ostream& to) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void instruction_pushint::gen_llvm(llvm_context& ctx, Function* f) const {
|
void instruction_pushint::gen_llvm(llvm_context& ctx, Function* f) const {
|
||||||
ctx.create_push(f, ctx.create_num(ctx.create_i32(value)));
|
ctx.create_push(f, ctx.create_num(f, ctx.create_i32(value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void instruction_pushglobal::print(int indent, std::ostream& to) const {
|
void instruction_pushglobal::print(int indent, std::ostream& to) const {
|
||||||
|
@ -26,7 +26,7 @@ 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.custom_functions.at("f_" + name);
|
||||||
auto arity = ctx.create_i32(global_f->arity);
|
auto arity = ctx.create_i32(global_f->arity);
|
||||||
ctx.create_push(f, ctx.create_global(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 {
|
||||||
|
@ -55,7 +55,7 @@ void instruction_mkapp::print(int indent, std::ostream& to) const {
|
||||||
void instruction_mkapp::gen_llvm(llvm_context& ctx, Function* f) const {
|
void instruction_mkapp::gen_llvm(llvm_context& ctx, Function* f) const {
|
||||||
auto left = ctx.create_pop(f);
|
auto left = ctx.create_pop(f);
|
||||||
auto right = ctx.create_pop(f);
|
auto right = ctx.create_pop(f);
|
||||||
ctx.create_push(f, ctx.create_app(left, right));
|
ctx.create_push(f, ctx.create_app(f, left, right));
|
||||||
}
|
}
|
||||||
|
|
||||||
void instruction_update::print(int indent, std::ostream& to) const {
|
void instruction_update::print(int indent, std::ostream& to) const {
|
||||||
|
@ -146,7 +146,7 @@ void instruction_binop::gen_llvm(llvm_context& ctx, Function* f) const {
|
||||||
case TIMES: result = ctx.builder.CreateMul(left_int, right_int); break;
|
case TIMES: result = ctx.builder.CreateMul(left_int, right_int); break;
|
||||||
case DIVIDE: result = ctx.builder.CreateSDiv(left_int, right_int); break;
|
case DIVIDE: result = ctx.builder.CreateSDiv(left_int, right_int); break;
|
||||||
}
|
}
|
||||||
ctx.create_push(f, ctx.create_num(result));
|
ctx.create_push(f, ctx.create_num(f, result));
|
||||||
}
|
}
|
||||||
|
|
||||||
void instruction_eval::print(int indent, std::ostream& to) const {
|
void instruction_eval::print(int indent, std::ostream& to) const {
|
||||||
|
|
|
@ -5,7 +5,9 @@ using namespace llvm;
|
||||||
|
|
||||||
void llvm_context::create_types() {
|
void llvm_context::create_types() {
|
||||||
stack_type = StructType::create(ctx, "stack");
|
stack_type = StructType::create(ctx, "stack");
|
||||||
|
gmachine_type = StructType::create(ctx, "gmachine");
|
||||||
stack_ptr_type = PointerType::getUnqual(stack_type);
|
stack_ptr_type = PointerType::getUnqual(stack_type);
|
||||||
|
gmachine_ptr_type = PointerType::getUnqual(gmachine_type);
|
||||||
tag_type = IntegerType::getInt8Ty(ctx);
|
tag_type = IntegerType::getInt8Ty(ctx);
|
||||||
struct_types["node_base"] = StructType::create(ctx, "node_base");
|
struct_types["node_base"] = StructType::create(ctx, "node_base");
|
||||||
struct_types["node_app"] = StructType::create(ctx, "node_app");
|
struct_types["node_app"] = StructType::create(ctx, "node_app");
|
||||||
|
@ -14,10 +16,16 @@ void llvm_context::create_types() {
|
||||||
struct_types["node_ind"] = StructType::create(ctx, "node_ind");
|
struct_types["node_ind"] = StructType::create(ctx, "node_ind");
|
||||||
struct_types["node_data"] = StructType::create(ctx, "node_data");
|
struct_types["node_data"] = StructType::create(ctx, "node_data");
|
||||||
node_ptr_type = PointerType::getUnqual(struct_types.at("node_base"));
|
node_ptr_type = PointerType::getUnqual(struct_types.at("node_base"));
|
||||||
function_type = FunctionType::get(Type::getVoidTy(ctx), { stack_ptr_type }, false);
|
function_type = FunctionType::get(Type::getVoidTy(ctx), { gmachine_ptr_type }, false);
|
||||||
|
|
||||||
|
gmachine_type->setBody(
|
||||||
|
stack_ptr_type,
|
||||||
|
node_ptr_type
|
||||||
|
);
|
||||||
struct_types.at("node_base")->setBody(
|
struct_types.at("node_base")->setBody(
|
||||||
IntegerType::getInt32Ty(ctx)
|
IntegerType::getInt32Ty(ctx),
|
||||||
|
IntegerType::getInt8Ty(ctx),
|
||||||
|
node_ptr_type
|
||||||
);
|
);
|
||||||
struct_types.at("node_app")->setBody(
|
struct_types.at("node_app")->setBody(
|
||||||
struct_types.at("node_base"),
|
struct_types.at("node_base"),
|
||||||
|
@ -82,34 +90,40 @@ void llvm_context::create_functions() {
|
||||||
"stack_popn",
|
"stack_popn",
|
||||||
&module
|
&module
|
||||||
);
|
);
|
||||||
functions["stack_slide"] = Function::Create(
|
functions["gmachine_slide"] = Function::Create(
|
||||||
FunctionType::get(void_type, { stack_ptr_type, sizet_type }, false),
|
FunctionType::get(void_type, { gmachine_ptr_type, sizet_type }, false),
|
||||||
Function::LinkageTypes::ExternalLinkage,
|
Function::LinkageTypes::ExternalLinkage,
|
||||||
"stack_slide",
|
"gmachine_slide",
|
||||||
&module
|
&module
|
||||||
);
|
);
|
||||||
functions["stack_update"] = Function::Create(
|
functions["gmachine_update"] = Function::Create(
|
||||||
FunctionType::get(void_type, { stack_ptr_type, sizet_type }, false),
|
FunctionType::get(void_type, { gmachine_ptr_type, sizet_type }, false),
|
||||||
Function::LinkageTypes::ExternalLinkage,
|
Function::LinkageTypes::ExternalLinkage,
|
||||||
"stack_update",
|
"gmachine_update",
|
||||||
&module
|
&module
|
||||||
);
|
);
|
||||||
functions["stack_alloc"] = Function::Create(
|
functions["gmachine_alloc"] = Function::Create(
|
||||||
FunctionType::get(void_type, { stack_ptr_type, sizet_type }, false),
|
FunctionType::get(void_type, { gmachine_ptr_type, sizet_type }, false),
|
||||||
Function::LinkageTypes::ExternalLinkage,
|
Function::LinkageTypes::ExternalLinkage,
|
||||||
"stack_alloc",
|
"gmachine_alloc",
|
||||||
&module
|
&module
|
||||||
);
|
);
|
||||||
functions["stack_pack"] = Function::Create(
|
functions["gmachine_pack"] = Function::Create(
|
||||||
FunctionType::get(void_type, { stack_ptr_type, sizet_type, tag_type }, false),
|
FunctionType::get(void_type, { gmachine_ptr_type, sizet_type, tag_type }, false),
|
||||||
Function::LinkageTypes::ExternalLinkage,
|
Function::LinkageTypes::ExternalLinkage,
|
||||||
"stack_pack",
|
"gmachine_pack",
|
||||||
&module
|
&module
|
||||||
);
|
);
|
||||||
functions["stack_split"] = Function::Create(
|
functions["gmachine_split"] = Function::Create(
|
||||||
FunctionType::get(node_ptr_type, { stack_ptr_type, sizet_type }, false),
|
FunctionType::get(void_type, { gmachine_ptr_type, sizet_type }, false),
|
||||||
Function::LinkageTypes::ExternalLinkage,
|
Function::LinkageTypes::ExternalLinkage,
|
||||||
"stack_split",
|
"gmachine_split",
|
||||||
|
&module
|
||||||
|
);
|
||||||
|
functions["gmachine_track"] = Function::Create(
|
||||||
|
FunctionType::get(node_ptr_type, { gmachine_ptr_type, node_ptr_type }, false),
|
||||||
|
Function::LinkageTypes::ExternalLinkage,
|
||||||
|
"gmachine_track",
|
||||||
&module
|
&module
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -139,14 +153,8 @@ void llvm_context::create_functions() {
|
||||||
&module
|
&module
|
||||||
);
|
);
|
||||||
|
|
||||||
functions["eval"] = Function::Create(
|
|
||||||
FunctionType::get(node_ptr_type, { node_ptr_type }, false),
|
|
||||||
Function::LinkageTypes::ExternalLinkage,
|
|
||||||
"eval",
|
|
||||||
&module
|
|
||||||
);
|
|
||||||
functions["unwind"] = Function::Create(
|
functions["unwind"] = Function::Create(
|
||||||
FunctionType::get(void_type, { stack_ptr_type }, false),
|
FunctionType::get(void_type, { gmachine_ptr_type }, false),
|
||||||
Function::LinkageTypes::ExternalLinkage,
|
Function::LinkageTypes::ExternalLinkage,
|
||||||
"unwind",
|
"unwind",
|
||||||
&module
|
&module
|
||||||
|
@ -165,40 +173,44 @@ ConstantInt* llvm_context::create_size(size_t i) {
|
||||||
|
|
||||||
Value* llvm_context::create_pop(Function* f) {
|
Value* llvm_context::create_pop(Function* f) {
|
||||||
auto pop_f = functions.at("stack_pop");
|
auto pop_f = functions.at("stack_pop");
|
||||||
return builder.CreateCall(pop_f, { f->arg_begin() });
|
return builder.CreateCall(pop_f, { unwrap_gmachine_stack_ptr(f->arg_begin()) });
|
||||||
}
|
}
|
||||||
Value* llvm_context::create_peek(Function* f, Value* off) {
|
Value* llvm_context::create_peek(Function* f, Value* off) {
|
||||||
auto peek_f = functions.at("stack_peek");
|
auto peek_f = functions.at("stack_peek");
|
||||||
return builder.CreateCall(peek_f, { f->arg_begin(), off });
|
return builder.CreateCall(peek_f, { unwrap_gmachine_stack_ptr(f->arg_begin()), off });
|
||||||
}
|
}
|
||||||
void llvm_context::create_push(Function* f, Value* v) {
|
void llvm_context::create_push(Function* f, Value* v) {
|
||||||
auto push_f = functions.at("stack_push");
|
auto push_f = functions.at("stack_push");
|
||||||
builder.CreateCall(push_f, { f->arg_begin(), v });
|
builder.CreateCall(push_f, { unwrap_gmachine_stack_ptr(f->arg_begin()), v });
|
||||||
}
|
}
|
||||||
void llvm_context::create_popn(Function* f, Value* off) {
|
void llvm_context::create_popn(Function* f, Value* off) {
|
||||||
auto popn_f = functions.at("stack_popn");
|
auto popn_f = functions.at("stack_popn");
|
||||||
builder.CreateCall(popn_f, { f->arg_begin(), off });
|
builder.CreateCall(popn_f, { unwrap_gmachine_stack_ptr(f->arg_begin()), off });
|
||||||
}
|
}
|
||||||
void llvm_context::create_update(Function* f, Value* off) {
|
void llvm_context::create_update(Function* f, Value* off) {
|
||||||
auto update_f = functions.at("stack_update");
|
auto update_f = functions.at("gmachine_update");
|
||||||
builder.CreateCall(update_f, { f->arg_begin(), off });
|
builder.CreateCall(update_f, { f->arg_begin(), off });
|
||||||
}
|
}
|
||||||
void llvm_context::create_pack(Function* f, Value* c, Value* t) {
|
void llvm_context::create_pack(Function* f, Value* c, Value* t) {
|
||||||
auto pack_f = functions.at("stack_pack");
|
auto pack_f = functions.at("gmachine_pack");
|
||||||
builder.CreateCall(pack_f, { f->arg_begin(), c, t });
|
builder.CreateCall(pack_f, { f->arg_begin(), c, t });
|
||||||
}
|
}
|
||||||
void llvm_context::create_split(Function* f, Value* c) {
|
void llvm_context::create_split(Function* f, Value* c) {
|
||||||
auto split_f = functions.at("stack_split");
|
auto split_f = functions.at("gmachine_split");
|
||||||
builder.CreateCall(split_f, { f->arg_begin(), c });
|
builder.CreateCall(split_f, { f->arg_begin(), c });
|
||||||
}
|
}
|
||||||
void llvm_context::create_slide(Function* f, Value* off) {
|
void llvm_context::create_slide(Function* f, Value* off) {
|
||||||
auto slide_f = functions.at("stack_slide");
|
auto slide_f = functions.at("gmachine_slide");
|
||||||
builder.CreateCall(slide_f, { f->arg_begin(), off });
|
builder.CreateCall(slide_f, { f->arg_begin(), off });
|
||||||
}
|
}
|
||||||
void llvm_context::create_alloc(Function* f, Value* n) {
|
void llvm_context::create_alloc(Function* f, Value* n) {
|
||||||
auto alloc_f = functions.at("stack_alloc");
|
auto alloc_f = functions.at("gmachine_alloc");
|
||||||
builder.CreateCall(alloc_f, { f->arg_begin(), n });
|
builder.CreateCall(alloc_f, { f->arg_begin(), n });
|
||||||
}
|
}
|
||||||
|
Value* llvm_context::create_track(Function* f, Value* v) {
|
||||||
|
auto track_f = functions.at("gmachine_track");
|
||||||
|
return builder.CreateCall(track_f, { f->arg_begin(), v });
|
||||||
|
}
|
||||||
|
|
||||||
Value* llvm_context::create_eval(Value* e) {
|
Value* llvm_context::create_eval(Value* e) {
|
||||||
auto eval_f = functions.at("eval");
|
auto eval_f = functions.at("eval");
|
||||||
|
@ -210,6 +222,11 @@ void llvm_context::create_unwind(Function* f) {
|
||||||
builder.CreateCall(unwind_f, { f->args().begin() });
|
builder.CreateCall(unwind_f, { f->args().begin() });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Value* llvm_context::unwrap_gmachine_stack_ptr(Value* g) {
|
||||||
|
auto offset_0 = create_i32(0);
|
||||||
|
return builder.CreateGEP(g, { offset_0, offset_0 });
|
||||||
|
}
|
||||||
|
|
||||||
Value* llvm_context::unwrap_num(Value* v) {
|
Value* llvm_context::unwrap_num(Value* v) {
|
||||||
auto num_ptr_type = PointerType::getUnqual(struct_types.at("node_num"));
|
auto num_ptr_type = PointerType::getUnqual(struct_types.at("node_num"));
|
||||||
auto cast = builder.CreatePointerCast(v, num_ptr_type);
|
auto cast = builder.CreatePointerCast(v, num_ptr_type);
|
||||||
|
@ -218,9 +235,10 @@ Value* llvm_context::unwrap_num(Value* v) {
|
||||||
auto int_ptr = builder.CreateGEP(cast, { offset_0, offset_1 });
|
auto int_ptr = builder.CreateGEP(cast, { offset_0, offset_1 });
|
||||||
return builder.CreateLoad(int_ptr);
|
return builder.CreateLoad(int_ptr);
|
||||||
}
|
}
|
||||||
Value* llvm_context::create_num(Value* v) {
|
Value* llvm_context::create_num(Function* f, Value* v) {
|
||||||
auto alloc_num_f = functions.at("alloc_num");
|
auto alloc_num_f = functions.at("alloc_num");
|
||||||
return builder.CreateCall(alloc_num_f, { v });
|
auto alloc_num_call = builder.CreateCall(alloc_num_f, { v });
|
||||||
|
return create_track(f, alloc_num_call);
|
||||||
}
|
}
|
||||||
|
|
||||||
Value* llvm_context::unwrap_data_tag(Value* v) {
|
Value* llvm_context::unwrap_data_tag(Value* v) {
|
||||||
|
@ -232,20 +250,20 @@ Value* llvm_context::unwrap_data_tag(Value* v) {
|
||||||
return builder.CreateLoad(tag_ptr);
|
return builder.CreateLoad(tag_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
Value* llvm_context::create_global(Value* f, Value* a) {
|
Value* llvm_context::create_global(Function* f, Value* gf, Value* a) {
|
||||||
auto alloc_global_f = functions.at("alloc_global");
|
auto alloc_global_f = functions.at("alloc_global");
|
||||||
return builder.CreateCall(alloc_global_f, { f, a });
|
auto alloc_global_call = builder.CreateCall(alloc_global_f, { gf, a });
|
||||||
|
return create_track(f, alloc_global_call);
|
||||||
}
|
}
|
||||||
|
|
||||||
Value* llvm_context::create_app(Value* l, Value* r) {
|
Value* llvm_context::create_app(Function* f, Value* l, Value* r) {
|
||||||
auto alloc_app_f = functions.at("alloc_app");
|
auto alloc_app_f = functions.at("alloc_app");
|
||||||
return builder.CreateCall(alloc_app_f, { l, r });
|
auto alloc_app_call = builder.CreateCall(alloc_app_f, { l, r });
|
||||||
|
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(std::string name, int32_t arity) {
|
||||||
auto void_type = llvm::Type::getVoidTy(ctx);
|
auto void_type = llvm::Type::getVoidTy(ctx);
|
||||||
auto function_type =
|
|
||||||
llvm::FunctionType::get(void_type, { stack_ptr_type }, false);
|
|
||||||
auto new_function = llvm::Function::Create(
|
auto new_function = llvm::Function::Create(
|
||||||
function_type,
|
function_type,
|
||||||
llvm::Function::LinkageTypes::ExternalLinkage,
|
llvm::Function::LinkageTypes::ExternalLinkage,
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <llvm/IR/LLVMContext.h>
|
#include <llvm/IR/LLVMContext.h>
|
||||||
#include <llvm/IR/IRBuilder.h>
|
#include <llvm/IR/IRBuilder.h>
|
||||||
#include <llvm/IR/Module.h>
|
#include <llvm/IR/Module.h>
|
||||||
|
#include <llvm/IR/Value.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
struct llvm_context {
|
struct llvm_context {
|
||||||
|
@ -23,7 +24,9 @@ struct llvm_context {
|
||||||
std::map<std::string, llvm::StructType*> struct_types;
|
std::map<std::string, llvm::StructType*> struct_types;
|
||||||
|
|
||||||
llvm::StructType* stack_type;
|
llvm::StructType* stack_type;
|
||||||
|
llvm::StructType* gmachine_type;
|
||||||
llvm::PointerType* stack_ptr_type;
|
llvm::PointerType* stack_ptr_type;
|
||||||
|
llvm::PointerType* gmachine_ptr_type;
|
||||||
llvm::PointerType* node_ptr_type;
|
llvm::PointerType* node_ptr_type;
|
||||||
llvm::IntegerType* tag_type;
|
llvm::IntegerType* tag_type;
|
||||||
llvm::FunctionType* function_type;
|
llvm::FunctionType* function_type;
|
||||||
|
@ -50,18 +53,21 @@ struct llvm_context {
|
||||||
void create_split(llvm::Function*, llvm::Value*);
|
void create_split(llvm::Function*, llvm::Value*);
|
||||||
void create_slide(llvm::Function*, llvm::Value*);
|
void create_slide(llvm::Function*, llvm::Value*);
|
||||||
void create_alloc(llvm::Function*, llvm::Value*);
|
void create_alloc(llvm::Function*, llvm::Value*);
|
||||||
|
llvm::Value* create_track(llvm::Function*, llvm::Value*);
|
||||||
|
|
||||||
llvm::Value* create_eval(llvm::Value*);
|
llvm::Value* create_eval(llvm::Value*);
|
||||||
void create_unwind(llvm::Function*);
|
void create_unwind(llvm::Function*);
|
||||||
|
|
||||||
|
llvm::Value* unwrap_gmachine_stack_ptr(llvm::Value*);
|
||||||
|
|
||||||
llvm::Value* unwrap_num(llvm::Value*);
|
llvm::Value* unwrap_num(llvm::Value*);
|
||||||
llvm::Value* create_num(llvm::Value*);
|
llvm::Value* create_num(llvm::Function*, llvm::Value*);
|
||||||
|
|
||||||
llvm::Value* unwrap_data_tag(llvm::Value*);
|
llvm::Value* unwrap_data_tag(llvm::Value*);
|
||||||
|
|
||||||
llvm::Value* create_global(llvm::Value*, llvm::Value*);
|
llvm::Value* create_global(llvm::Function*, llvm::Value*, llvm::Value*);
|
||||||
|
|
||||||
llvm::Value* create_app(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(std::string name, int32_t arity);
|
||||||
};
|
};
|
||||||
|
|
101
09/runtime.c
101
09/runtime.c
|
@ -25,7 +25,7 @@ struct node_num* alloc_num(int32_t n) {
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct node_global* alloc_global(void (*f)(struct stack*), int32_t a) {
|
struct node_global* alloc_global(void (*f)(struct gmachine*), int32_t a) {
|
||||||
struct node_global* node = (struct node_global*) alloc_node();
|
struct node_global* node = (struct node_global*) alloc_node();
|
||||||
node->base.tag = NODE_GLOBAL;
|
node->base.tag = NODE_GLOBAL;
|
||||||
node->arity = a;
|
node->arity = a;
|
||||||
|
@ -40,6 +40,12 @@ struct node_ind* alloc_ind(struct node_base* n) {
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void free_node_direct(struct node_base* n) {
|
||||||
|
if(n->tag == NODE_DATA) {
|
||||||
|
free(((struct node_data*) n)->array);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void stack_init(struct stack* s) {
|
void stack_init(struct stack* s) {
|
||||||
s->size = 4;
|
s->size = 4;
|
||||||
s->count = 0;
|
s->count = 0;
|
||||||
|
@ -74,49 +80,81 @@ void stack_popn(struct stack* s, size_t n) {
|
||||||
s->count -= n;
|
s->count -= n;
|
||||||
}
|
}
|
||||||
|
|
||||||
void stack_slide(struct stack* s, size_t n) {
|
void gmachine_init(struct gmachine* g) {
|
||||||
assert(s->count > n);
|
stack_init(&g->stack);
|
||||||
s->data[s->count - n - 1] = s->data[s->count - 1];
|
g->nodes = NULL;
|
||||||
s->count -= n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void stack_update(struct stack* s, size_t o) {
|
void gmachine_free(struct gmachine* g) {
|
||||||
assert(s->count > o + 1);
|
stack_free(&g->stack);
|
||||||
struct node_ind* ind = (struct node_ind*) s->data[s->count - o - 2];
|
struct node_base* to_free = g->nodes;
|
||||||
|
struct node_base* next;
|
||||||
|
|
||||||
|
while(to_free) {
|
||||||
|
next = to_free->gc_next;
|
||||||
|
free_node_direct(to_free);
|
||||||
|
free(to_free);
|
||||||
|
to_free = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void gmachine_slide(struct gmachine* g, size_t n) {
|
||||||
|
assert(g->stack.count > n);
|
||||||
|
g->stack.data[g->stack.count - n - 1] = g->stack.data[g->stack.count - 1];
|
||||||
|
g->stack.count -= n;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gmachine_update(struct gmachine* g, size_t o) {
|
||||||
|
assert(g->stack.count > o + 1);
|
||||||
|
struct node_ind* ind =
|
||||||
|
(struct node_ind*) g->stack.data[g->stack.count - o - 2];
|
||||||
ind->base.tag = NODE_IND;
|
ind->base.tag = NODE_IND;
|
||||||
ind->next = s->data[s->count -= 1];
|
ind->next = g->stack.data[g->stack.count -= 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
void stack_alloc(struct stack* s, size_t o) {
|
void gmachine_alloc(struct gmachine* g, size_t o) {
|
||||||
while(o--) {
|
while(o--) {
|
||||||
stack_push(s, (struct node_base*) alloc_ind(NULL));
|
stack_push(&g->stack,
|
||||||
|
gmachine_track(g, (struct node_base*) alloc_ind(NULL)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void stack_pack(struct stack* s, size_t n, int8_t t) {
|
void gmachine_pack(struct gmachine* g, size_t n, int8_t t) {
|
||||||
assert(s->count >= n);
|
assert(g->stack.count >= n);
|
||||||
|
|
||||||
struct node_base** data = malloc(sizeof(*data) * n);
|
struct node_base** data = malloc(sizeof(*data) * n);
|
||||||
assert(data != NULL);
|
assert(data != NULL);
|
||||||
memcpy(data, &s->data[s->count - n], n * sizeof(*data));
|
memcpy(data, &g->stack.data[g->stack.count - n], n * sizeof(*data));
|
||||||
|
|
||||||
struct node_data* new_node = (struct node_data*) alloc_node();
|
struct node_data* new_node = (struct node_data*) alloc_node();
|
||||||
new_node->array = data;
|
new_node->array = data;
|
||||||
new_node->base.tag = NODE_DATA;
|
new_node->base.tag = NODE_DATA;
|
||||||
new_node->tag = t;
|
new_node->tag = t;
|
||||||
|
|
||||||
stack_popn(s, n);
|
stack_popn(&g->stack, n);
|
||||||
stack_push(s, (struct node_base*) new_node);
|
stack_push(&g->stack, gmachine_track(g, (struct node_base*) new_node));
|
||||||
}
|
}
|
||||||
|
|
||||||
void stack_split(struct stack* s, size_t n) {
|
void gmachine_split(struct gmachine* g, size_t n) {
|
||||||
struct node_data* node = (struct node_data*) stack_pop(s);
|
struct node_data* node = (struct node_data*) stack_pop(&g->stack);
|
||||||
for(size_t i = 0; i < n; i++) {
|
for(size_t i = 0; i < n; i++) {
|
||||||
stack_push(s, node->array[i]);
|
stack_push(&g->stack, node->array[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void unwind(struct stack* s) {
|
struct node_base* gmachine_track(struct gmachine* g, struct node_base* b) {
|
||||||
|
b->gc_next = g->nodes;
|
||||||
|
g->nodes = b;
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gmachine_gc(struct gmachine* g) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void unwind(struct gmachine* g) {
|
||||||
|
struct stack* s = &g->stack;
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
struct node_base* peek = stack_peek(s, 0);
|
struct node_base* peek = stack_peek(s, 0);
|
||||||
if(peek->tag == NODE_APP) {
|
if(peek->tag == NODE_APP) {
|
||||||
|
@ -131,7 +169,7 @@ void unwind(struct stack* s) {
|
||||||
= ((struct node_app*) s->data[s->count - i - 1])->right;
|
= ((struct node_app*) s->data[s->count - i - 1])->right;
|
||||||
}
|
}
|
||||||
|
|
||||||
n->function(s);
|
n->function(g);
|
||||||
} else if(peek->tag == NODE_IND) {
|
} else if(peek->tag == NODE_IND) {
|
||||||
struct node_ind* n = (struct node_ind*) peek;
|
struct node_ind* n = (struct node_ind*) peek;
|
||||||
stack_pop(s);
|
stack_pop(s);
|
||||||
|
@ -142,17 +180,7 @@ void unwind(struct stack* s) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct node_base* eval(struct node_base* n) {
|
extern void f_main(struct gmachine* s);
|
||||||
struct stack program_stack;
|
|
||||||
stack_init(&program_stack);
|
|
||||||
stack_push(&program_stack, n);
|
|
||||||
unwind(&program_stack);
|
|
||||||
struct node_base* result = stack_pop(&program_stack);
|
|
||||||
stack_free(&program_stack);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern void f_main(struct stack* s);
|
|
||||||
|
|
||||||
void print_node(struct node_base* n) {
|
void print_node(struct node_base* n) {
|
||||||
if(n->tag == NODE_APP) {
|
if(n->tag == NODE_APP) {
|
||||||
|
@ -174,10 +202,17 @@ void print_node(struct node_base* n) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
|
struct gmachine gmachine;
|
||||||
struct node_global* first_node = alloc_global(f_main, 0);
|
struct node_global* first_node = alloc_global(f_main, 0);
|
||||||
struct node_base* result = eval((struct node_base*) first_node);
|
struct node_base* result;
|
||||||
|
|
||||||
|
gmachine_init(&gmachine);
|
||||||
|
gmachine_track(&gmachine, (struct node_base*) first_node);
|
||||||
|
stack_push(&gmachine.stack, (struct node_base*) first_node);
|
||||||
|
unwind(&gmachine);
|
||||||
|
result = stack_pop(&gmachine.stack);
|
||||||
printf("Result: ");
|
printf("Result: ");
|
||||||
print_node(result);
|
print_node(result);
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
|
gmachine_free(&gmachine);
|
||||||
}
|
}
|
||||||
|
|
29
09/runtime.h
29
09/runtime.h
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
struct stack;
|
struct gmachine;
|
||||||
|
|
||||||
enum node_tag {
|
enum node_tag {
|
||||||
NODE_APP,
|
NODE_APP,
|
||||||
|
@ -13,6 +13,8 @@ enum node_tag {
|
||||||
|
|
||||||
struct node_base {
|
struct node_base {
|
||||||
enum node_tag tag;
|
enum node_tag tag;
|
||||||
|
int8_t gc_color;
|
||||||
|
struct node_base* gc_next;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct node_app {
|
struct node_app {
|
||||||
|
@ -29,7 +31,7 @@ struct node_num {
|
||||||
struct node_global {
|
struct node_global {
|
||||||
struct node_base base;
|
struct node_base base;
|
||||||
int32_t arity;
|
int32_t arity;
|
||||||
void (*function)(struct stack*);
|
void (*function)(struct gmachine*);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct node_ind {
|
struct node_ind {
|
||||||
|
@ -46,8 +48,9 @@ struct node_data {
|
||||||
struct node_base* alloc_node();
|
struct node_base* alloc_node();
|
||||||
struct node_app* alloc_app(struct node_base* l, struct node_base* r);
|
struct node_app* alloc_app(struct node_base* l, struct node_base* r);
|
||||||
struct node_num* alloc_num(int32_t n);
|
struct node_num* alloc_num(int32_t n);
|
||||||
struct node_global* alloc_global(void (*f)(struct stack*), int32_t a);
|
struct node_global* alloc_global(void (*f)(struct gmachine*), int32_t a);
|
||||||
struct node_ind* alloc_ind(struct node_base* n);
|
struct node_ind* alloc_ind(struct node_base* n);
|
||||||
|
void free_node_direct(struct node_base*);
|
||||||
|
|
||||||
struct stack {
|
struct stack {
|
||||||
size_t size;
|
size_t size;
|
||||||
|
@ -61,10 +64,18 @@ void stack_push(struct stack* s, struct node_base* n);
|
||||||
struct node_base* stack_pop(struct stack* s);
|
struct node_base* stack_pop(struct stack* s);
|
||||||
struct node_base* stack_peek(struct stack* s, size_t o);
|
struct node_base* stack_peek(struct stack* s, size_t o);
|
||||||
void stack_popn(struct stack* s, size_t n);
|
void stack_popn(struct stack* s, size_t n);
|
||||||
void stack_slide(struct stack* s, size_t n);
|
|
||||||
void stack_update(struct stack* s, size_t o);
|
|
||||||
void stack_alloc(struct stack* s, size_t o);
|
|
||||||
void stack_pack(struct stack* s, size_t n, int8_t t);
|
|
||||||
void stack_split(struct stack* s, size_t n);
|
|
||||||
|
|
||||||
struct node_base* eval(struct node_base* n);
|
struct gmachine {
|
||||||
|
struct stack stack;
|
||||||
|
struct node_base* nodes;
|
||||||
|
};
|
||||||
|
|
||||||
|
void gmachine_init(struct gmachine* g);
|
||||||
|
void gmachine_free(struct gmachine* g);
|
||||||
|
void gmachine_slide(struct gmachine* g, size_t n);
|
||||||
|
void gmachine_update(struct gmachine* g, size_t o);
|
||||||
|
void gmachine_alloc(struct gmachine* g, size_t o);
|
||||||
|
void gmachine_pack(struct gmachine* g, size_t n, int8_t t);
|
||||||
|
void gmachine_split(struct gmachine* g, size_t n);
|
||||||
|
struct node_base* gmachine_track(struct gmachine* g, struct node_base* b);
|
||||||
|
void gmachine_gc(struct gmachine* g);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user