feat: local function variables on stack

This commit is contained in:
Orangerot 2025-05-15 21:58:29 +02:00
parent e13c2aac40
commit d8bb323b09

40
wai.c
View file

@ -78,7 +78,7 @@ struct func_type_t {
struct func_t { struct func_t {
size_t func_type_index; size_t func_type_index;
size_t num_local_vars; size_t num_local_vars;
u_char *func_start_addr; u_char *addr;
}; };
enum export_desc { enum export_desc {
@ -96,9 +96,8 @@ struct export_t {
}; };
struct module { struct module {
struct func_type_t func_types[MAX_FUNCTIONS]; // TYPE SECTION struct func_type_t func_types[MAX_FUNCTIONS];
u_char *code[MAX_FUNCTIONS]; // CODE SECTION struct func_t func[MAX_FUNCTIONS];
size_t func_to_func_type[MAX_FUNCTIONS]; // FUNCTION SECTION
struct table_t *tables; struct table_t *tables;
struct mem_t *mems; struct mem_t *mems;
struct global_t *globals; struct global_t *globals;
@ -110,7 +109,6 @@ struct module {
u_char *binary; u_char *binary;
struct stack stack; struct stack stack;
size_t num_exports; size_t num_exports;
int scope;
}; };
enum INSTRUCTION { enum INSTRUCTION {
@ -314,10 +312,10 @@ int parse_instruction(struct module *module, u_char *binary, size_t func_i, size
} }
case INSTR_LOCAL_GET: { case INSTR_LOCAL_GET: {
int local_index = binary[i]; int local_index = binary[i];
size_t func_type_i = module->func_to_func_type[func_i]; size_t func_type_i = module->func[func_i].func_type_index;
struct func_type_t *func_type = &module->func_types[func_type_i]; struct func_type_t *func_type = &module->func_types[func_type_i];
// TODO: take local variables into account in addition to parameters int num_locals = func_type->num_params + module->func[func_i].num_local_vars;
int num_locals = func_type->num_params;
printf("num locals %d, %d\n", num_locals, num_locals - 1 - local_index); printf("num locals %d, %d\n", num_locals, num_locals - 1 - local_index);
stack_peak(&module->stack, &result, num_locals - 1 - local_index, func_stack_begin); stack_peak(&module->stack, &result, num_locals - 1 - local_index, func_stack_begin);
incr(i, len); incr(i, len);
@ -333,8 +331,9 @@ int parse_instruction(struct module *module, u_char *binary, size_t func_i, size
int parse_function(struct module *module, size_t func_i, int len) { int parse_function(struct module *module, size_t func_i, int len) {
int i = 0; int i = 0;
u_char *binary = module->code[func_i]; struct func_t *func = &module->func[func_i];
size_t func_type_i = module->func_to_func_type[func_i]; u_char *binary = func->addr;
size_t func_type_i = func->func_type_index;
struct func_type_t *func_type = &module->func_types[func_type_i]; struct func_type_t *func_type = &module->func_types[func_type_i];
int body_size = binary[i]; int body_size = binary[i];
size_t func_stack_begin = module->stack.bytes; size_t func_stack_begin = module->stack.bytes;
@ -342,9 +341,12 @@ int parse_function(struct module *module, size_t func_i, int len) {
struct value_t result = {0}; struct value_t result = {0};
incr(i, len); incr(i, len);
// int local_decl_cound = binary[i]; func->num_local_vars = binary[i];
incr(i, len); incr(i, len);
module->scope = 1; for (int local_var_i = 0; local_var_i < func->num_local_vars; local_var_i++) {
stack_push(&module->stack, &(struct value_t) {.type = binary[i], .value = 0});
incr(i, len);
}
while (binary[i] != INSTR_END) { while (binary[i] != INSTR_END) {
i += parse_instruction(module, &binary[i], func_i, func_stack_begin, len); i += parse_instruction(module, &binary[i], func_i, func_stack_begin, len);
} }
@ -352,7 +354,7 @@ int parse_function(struct module *module, size_t func_i, int len) {
func_stack_end = module->stack.bytes; func_stack_end = module->stack.bytes;
module->stack.bytes = func_stack_begin; module->stack.bytes = func_stack_begin;
for (size_t param_i = 0; param_i < func_type->num_params; param_i++) { for (size_t local_i = 0; local_i < func_type->num_params + func->num_local_vars; local_i++) {
stack_pop(&module->stack, &result); stack_pop(&module->stack, &result);
} }
for (size_t result_i = 0; result_i < func_type->num_results; result_i++) { for (size_t result_i = 0; result_i < func_type->num_results; result_i++) {
@ -406,7 +408,7 @@ int parse_section(struct module *module, u_char *binary, int len) {
size_t num_functions = binary[i]; size_t num_functions = binary[i];
incr(i, len); incr(i, len);
for (size_t function_i = 0; function_i < num_functions; function_i++) { for (size_t function_i = 0; function_i < num_functions; function_i++) {
module->func_to_func_type[function_i] = binary[i]; module->func[function_i].func_type_index = binary[i];
incr(i, len); incr(i, len);
} }
break; break;
@ -442,7 +444,7 @@ int parse_section(struct module *module, u_char *binary, int len) {
printf("export name: %s of type %d\n", export->name, export->description); printf("export name: %s of type %d\n", export->name, export->description);
if (export->description == Export_Func) { if (export->description == Export_Func) {
printf("exported function %s(", export->name); printf("exported function %s(", export->name);
size_t func_type_index = module->func_to_func_type[export->func_index]; size_t func_type_index = module->func[export->func_index].func_type_index;
struct func_type_t *func_type = &module->func_types[func_type_index]; struct func_type_t *func_type = &module->func_types[func_type_index];
for (size_t param_i = 0; param_i < func_type->num_params; param_i++) { for (size_t param_i = 0; param_i < func_type->num_params; param_i++) {
printf("%s", TYPE_NAME[func_type->param[param_i]]); printf("%s", TYPE_NAME[func_type->param[param_i]]);
@ -472,7 +474,7 @@ int parse_section(struct module *module, u_char *binary, int len) {
int num_functions2 = binary[i]; int num_functions2 = binary[i];
incr(i, len); incr(i, len);
for (int function_i = 0; function_i < num_functions2; function_i++) { for (int function_i = 0; function_i < num_functions2; function_i++) {
module->code[function_i] = &binary[i]; module->func[function_i].addr = &binary[i];
stack_push(&module->stack, &(struct value_t) {.type = TYPE_F64, .value.f64 = 1}); stack_push(&module->stack, &(struct value_t) {.type = TYPE_F64, .value.f64 = 1});
i += parse_function(module, function_i, len); i += parse_function(module, function_i, len);
stack_pop(&module->stack, &(struct value_t) {0}); stack_pop(&module->stack, &(struct value_t) {0});
@ -521,8 +523,9 @@ int main(int argc, char **argv) {
struct stat st; struct stat st;
struct module module = {0}; struct module module = {0};
if (argc != 2) { if (argc < 3) {
printf("Usage: %s [file] [function name] [function arguments ...]\n", argv[0]); printf("Usage: %s [file] [function name] [function arguments ...]\n", argv[0]);
exit(1);
}; };
file = fopen(argv[1], "r"); file = fopen(argv[1], "r");
if (file == NULL) { if (file == NULL) {
@ -552,7 +555,8 @@ int main(int argc, char **argv) {
exit(1); exit(1);
} }
size_t function_search_i = module.exports[export_search_i].func_index; size_t function_search_i = module.exports[export_search_i].func_index;
struct func_type_t *func_type_search = &module.func_types[module.func_to_func_type[function_search_i]]; size_t function_search_type_index = module.func[function_search_i].func_type_index;
struct func_type_t *func_type_search = &module.func_types[function_search_type_index];
if (func_type_search->num_params != argc - 3) { if (func_type_search->num_params != argc - 3) {
printf("Not enough function arguments provided. Got %d expected %zu. \n", argc - 3, func_type_search->num_params); printf("Not enough function arguments provided. Got %d expected %zu. \n", argc - 3, func_type_search->num_params);
exit(1); exit(1);