Track allocated nodes using a G-machine struct in compiler series.
This commit is contained in:
		
							parent
							
								
									153349f3d5
								
							
						
					
					
						commit
						281dbbd174
					
				| @ -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); | ||||||
| }; | }; | ||||||
|  | |||||||
| @ -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); | ||||||
| } | } | ||||||
|  | |||||||
| @ -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