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 {
size_t func_type_index;
size_t num_local_vars;
u_char *func_start_addr;
u_char *addr;
};
enum export_desc {
@ -96,9 +96,8 @@ struct export_t {
};
struct module {
struct func_type_t func_types[MAX_FUNCTIONS]; // TYPE SECTION
u_char *code[MAX_FUNCTIONS]; // CODE SECTION
size_t func_to_func_type[MAX_FUNCTIONS]; // FUNCTION SECTION
struct func_type_t func_types[MAX_FUNCTIONS];
struct func_t func[MAX_FUNCTIONS];
struct table_t *tables;
struct mem_t *mems;
struct global_t *globals;
@ -110,7 +109,6 @@ struct module {
u_char *binary;
struct stack stack;
size_t num_exports;
int scope;
};
enum INSTRUCTION {
@ -314,10 +312,10 @@ int parse_instruction(struct module *module, u_char *binary, size_t func_i, size
}
case INSTR_LOCAL_GET: {
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];
// TODO: take local variables into account in addition to parameters
int num_locals = func_type->num_params;
int num_locals = func_type->num_params + module->func[func_i].num_local_vars;
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);
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 i = 0;
u_char *binary = module->code[func_i];
size_t func_type_i = module->func_to_func_type[func_i];
struct func_t *func = &module->func[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];
int body_size = binary[i];
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};
incr(i, len);
// int local_decl_cound = binary[i];
func->num_local_vars = binary[i];
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) {
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;
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);
}
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];
incr(i, len);
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);
}
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);
if (export->description == Export_Func) {
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];
for (size_t param_i = 0; param_i < func_type->num_params; 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];
incr(i, len);
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});
i += parse_function(module, function_i, len);
stack_pop(&module->stack, &(struct value_t) {0});
@ -521,8 +523,9 @@ int main(int argc, char **argv) {
struct stat st;
struct module module = {0};
if (argc != 2) {
if (argc < 3) {
printf("Usage: %s [file] [function name] [function arguments ...]\n", argv[0]);
exit(1);
};
file = fopen(argv[1], "r");
if (file == NULL) {
@ -552,7 +555,8 @@ int main(int argc, char **argv) {
exit(1);
}
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) {
printf("Not enough function arguments provided. Got %d expected %zu. \n", argc - 3, func_type_search->num_params);
exit(1);