Compare commits
No commits in common. "9d0692a391cd492db3d393560d029e3d72840a77" and "e13c2aac40279d420faac6527964303bb62ab7b4" have entirely different histories.
9d0692a391
...
e13c2aac40
388
wai.c
388
wai.c
|
@ -54,7 +54,6 @@ enum section {
|
||||||
};
|
};
|
||||||
|
|
||||||
enum TYPE {
|
enum TYPE {
|
||||||
TYPE_ANY = 0,
|
|
||||||
TYPE_I32 = 0x7F,
|
TYPE_I32 = 0x7F,
|
||||||
TYPE_I64 = 0x7E,
|
TYPE_I64 = 0x7E,
|
||||||
TYPE_F32 = 0x7D,
|
TYPE_F32 = 0x7D,
|
||||||
|
@ -64,6 +63,68 @@ enum TYPE {
|
||||||
TYPE_EXTERNREF = 0x6F
|
TYPE_EXTERNREF = 0x6F
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct stack {
|
||||||
|
u_char items[STACK_CAPACITY];
|
||||||
|
size_t bytes;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct func_type_t {
|
||||||
|
enum TYPE param[MAX_FUNCTION_PARAMETERS];
|
||||||
|
enum TYPE result[MAX_FUNCTION_RESULTS];
|
||||||
|
size_t num_params;
|
||||||
|
size_t num_results;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct func_t {
|
||||||
|
size_t func_type_index;
|
||||||
|
size_t num_local_vars;
|
||||||
|
u_char *func_start_addr;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum export_desc {
|
||||||
|
Export_Func,
|
||||||
|
Export_Table,
|
||||||
|
Export_Mem,
|
||||||
|
Export_Global,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct export_t {
|
||||||
|
char name[MAX_EXPORT_NAME_LENGTH];
|
||||||
|
size_t name_length;
|
||||||
|
size_t func_index;
|
||||||
|
enum export_desc description;
|
||||||
|
};
|
||||||
|
|
||||||
|
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 table_t *tables;
|
||||||
|
struct mem_t *mems;
|
||||||
|
struct global_t *globals;
|
||||||
|
struct elem_t *elems;
|
||||||
|
struct data_t *datas;
|
||||||
|
struct start_t *start;
|
||||||
|
struct import_t *imports;
|
||||||
|
struct export_t exports[MAX_FUNCTIONS];
|
||||||
|
u_char *binary;
|
||||||
|
struct stack stack;
|
||||||
|
size_t num_exports;
|
||||||
|
int scope;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum INSTRUCTION {
|
||||||
|
INSTR_CALL = 0x10,
|
||||||
|
INSTR_ELSE = 0x05,
|
||||||
|
INSTR_END = 0x0b,
|
||||||
|
INSTR_F64_CONST = 0x44,
|
||||||
|
INSTR_F64_LT = 0x63,
|
||||||
|
INSTR_F64_MUL = 0xa2,
|
||||||
|
INSTR_F64_SUB = 0xa1,
|
||||||
|
INSTR_IF = 0x04,
|
||||||
|
INSTR_LOCAL_GET = 0x20,
|
||||||
|
};
|
||||||
|
|
||||||
static const int TYPE_SIZE[] = {
|
static const int TYPE_SIZE[] = {
|
||||||
[TYPE_I32] = 4,
|
[TYPE_I32] = 4,
|
||||||
[TYPE_I64] = 8,
|
[TYPE_I64] = 8,
|
||||||
|
@ -81,56 +142,7 @@ static const char *TYPE_NAME[] = {
|
||||||
[TYPE_F64] = "F64",
|
[TYPE_F64] = "F64",
|
||||||
[TYPE_V128] = "V128",
|
[TYPE_V128] = "V128",
|
||||||
[TYPE_FUNCREF] = "FREF",
|
[TYPE_FUNCREF] = "FREF",
|
||||||
[TYPE_EXTERNREF] = "EXTR",
|
[TYPE_EXTERNREF] = "EXTR"
|
||||||
[TYPE_ANY] = "ANY",
|
|
||||||
};
|
|
||||||
|
|
||||||
struct stack {
|
|
||||||
u_char items[STACK_CAPACITY];
|
|
||||||
size_t bytes;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct func_type_t {
|
|
||||||
enum TYPE param[MAX_FUNCTION_PARAMETERS];
|
|
||||||
enum TYPE result[MAX_FUNCTION_RESULTS];
|
|
||||||
size_t num_params;
|
|
||||||
size_t num_results;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct func_t {
|
|
||||||
size_t func_type_index;
|
|
||||||
size_t num_local_vars;
|
|
||||||
u_char *addr;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum export_desc {
|
|
||||||
Export_Func,
|
|
||||||
Export_Table,
|
|
||||||
Export_Mem,
|
|
||||||
Export_Global,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct export_t {
|
|
||||||
char name[MAX_EXPORT_NAME_LENGTH];
|
|
||||||
size_t name_length;
|
|
||||||
size_t func_index;
|
|
||||||
enum export_desc description;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct module {
|
|
||||||
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;
|
|
||||||
struct elem_t *elems;
|
|
||||||
struct data_t *datas;
|
|
||||||
struct start_t *start;
|
|
||||||
struct import_t *imports;
|
|
||||||
struct export_t exports[MAX_FUNCTIONS];
|
|
||||||
u_char *binary;
|
|
||||||
struct stack stack;
|
|
||||||
size_t num_exports;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct value_t {
|
struct value_t {
|
||||||
|
@ -146,13 +158,7 @@ struct value_t {
|
||||||
} value;
|
} value;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct context {
|
#define incr(i, len) i++; if (i >= len) {return -1;}
|
||||||
struct module *module;
|
|
||||||
size_t func_i;
|
|
||||||
size_t func_stack_begin;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define incr(i, len) i++; if (i >= len) {return 0;}
|
|
||||||
|
|
||||||
void print_value(struct value_t *value) {
|
void print_value(struct value_t *value) {
|
||||||
void *number = &value->value;
|
void *number = &value->value;
|
||||||
|
@ -161,7 +167,6 @@ void print_value(struct value_t *value) {
|
||||||
printf("%d", *(int32_t*)number);
|
printf("%d", *(int32_t*)number);
|
||||||
break;
|
break;
|
||||||
case TYPE_I64:
|
case TYPE_I64:
|
||||||
case TYPE_ANY:
|
|
||||||
printf("%ld", *(int64_t*)number);
|
printf("%ld", *(int64_t*)number);
|
||||||
break;
|
break;
|
||||||
case TYPE_F32:
|
case TYPE_F32:
|
||||||
|
@ -171,7 +176,7 @@ void print_value(struct value_t *value) {
|
||||||
printf("%f", *(double*)number);
|
printf("%f", *(double*)number);
|
||||||
break;
|
break;
|
||||||
case TYPE_V128:
|
case TYPE_V128:
|
||||||
printf("%f", (double) *(__int128*)number);
|
printf("%ld", *(__int128*)number);
|
||||||
break;
|
break;
|
||||||
case TYPE_FUNCREF:
|
case TYPE_FUNCREF:
|
||||||
printf("%ld", *(int64_t*)number);
|
printf("%ld", *(int64_t*)number);
|
||||||
|
@ -185,7 +190,7 @@ void print_value(struct value_t *value) {
|
||||||
|
|
||||||
void stack_peak(struct stack *s, struct value_t *value, size_t nth, size_t from) {
|
void stack_peak(struct stack *s, struct value_t *value, size_t nth, size_t from) {
|
||||||
int byte_i = from - 1;
|
int byte_i = from - 1;
|
||||||
for (size_t element_i = 0; element_i < nth && byte_i > 0; element_i++) {
|
for (int element_i = 0; element_i < nth && byte_i > 0; element_i++) {
|
||||||
byte_i -= TYPE_SIZE[s->items[byte_i]];
|
byte_i -= TYPE_SIZE[s->items[byte_i]];
|
||||||
}
|
}
|
||||||
value->type = s->items[byte_i];
|
value->type = s->items[byte_i];
|
||||||
|
@ -200,6 +205,9 @@ void stack_push(struct stack *s, const struct value_t *value) {
|
||||||
|
|
||||||
printf("stack: ");
|
printf("stack: ");
|
||||||
for (int i = s->bytes - 1; i > 0; i -= TYPE_SIZE[s->items[i]] + 1) {
|
for (int i = s->bytes - 1; i > 0; i -= TYPE_SIZE[s->items[i]] + 1) {
|
||||||
|
enum TYPE t = s->items[i];
|
||||||
|
size_t type_size = TYPE_SIZE[t];
|
||||||
|
void *number = &s->items[i - type_size];
|
||||||
struct value_t stack_value = {0};
|
struct value_t stack_value = {0};
|
||||||
stack_peak(s, &stack_value, 0, i + 1);
|
stack_peak(s, &stack_value, 0, i + 1);
|
||||||
print_value(&stack_value);
|
print_value(&stack_value);
|
||||||
|
@ -218,157 +226,133 @@ void stack_pop(struct stack *s, struct value_t *value) {
|
||||||
s->bytes -= TYPE_SIZE[value->type] + 1;
|
s->bytes -= TYPE_SIZE[value->type] + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int parse_function(struct module *module, size_t func_i, size_t len);
|
int parse_function(struct module *module, size_t func_i, int len);
|
||||||
int parse_instruction(struct context context, u_char *binary, size_t len);
|
int parse_instruction(struct module *module, u_char *binary, size_t func_i, size_t func_stack_begin, int len) {
|
||||||
|
int i = 0;
|
||||||
#define PARAMS(...) __VA_ARGS__
|
enum INSTRUCTION instr = binary[i];
|
||||||
|
|
||||||
// https://webassembly.github.io/spec/core/appendix/index-instructions.html
|
|
||||||
// OP(NAME, CODE, PARAM, NUM_RESULTS, LEN_IMMIDIATE, BODY)
|
|
||||||
#define DEFINE_OPERATIONS(OP) \
|
|
||||||
OP(INSTR_F64_MUL, 0xa2, PARAMS(TYPE_F64, TYPE_F64), 1, 0, result->type = TYPE_F64; result->value.f64 = a->value.f64 * b->value.f64) \
|
|
||||||
OP(INSTR_F64_SUB, 0xa1, PARAMS(TYPE_F64, TYPE_F64), 1, 0, result->type = TYPE_F64; result->value.f64 = b->value.f64 - a->value.f64) \
|
|
||||||
OP(INSTR_F64_LT, 0x63, PARAMS(TYPE_F64, TYPE_F64), 1, 0, result->type = TYPE_F64; result->value.f64 = b->value.f64 < a->value.f64) \
|
|
||||||
OP(INSTR_F64_CONST, 0x44, PARAMS(), 1, 8, result->type = TYPE_F64; result->value.f64 = *(double*)immidiate) \
|
|
||||||
OP(INSTR_LOCAL_GET, 0x20, PARAMS(), 1, 1, \
|
|
||||||
size_t func_type_i = context.module->func[context.func_i].func_type_index; \
|
|
||||||
struct func_type_t *func_type = &context.module->func_types[func_type_i]; \
|
|
||||||
int num_locals = func_type->num_params + context.module->func[context.func_i].num_local_vars; \
|
|
||||||
\
|
|
||||||
printf("num locals %d, %d\n", num_locals, num_locals - 1 - *(u_char*)immidiate); \
|
|
||||||
stack_peak(&context.module->stack, result, num_locals - 1 - *(u_char*)immidiate, context.func_stack_begin); \
|
|
||||||
) \
|
|
||||||
OP(INSTR_CALL, 0x10, PARAMS(), 0, 1, parse_function(context.module, *(u_char*)immidiate, len)) \
|
|
||||||
OP(INSTR_IF, 0x04, PARAMS(TYPE_ANY), 0, 1, \
|
|
||||||
size_t i = 0; \
|
|
||||||
enum TYPE condition_type = *(u_char*) immidiate; \
|
|
||||||
if (a->type != condition_type) \
|
|
||||||
printf("Wrong types!\n"); \
|
|
||||||
\
|
|
||||||
while (binary[i] != INSTR_ELSE) { \
|
|
||||||
if (a->value.i64) { \
|
|
||||||
i += parse_instruction(context, &binary[i], len); \
|
|
||||||
} else { \
|
|
||||||
incr(i, len); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
incr(i, len); \
|
|
||||||
while (binary[i] != INSTR_END) { \
|
|
||||||
if (a->value.i64) { \
|
|
||||||
incr(i, len); \
|
|
||||||
} else { \
|
|
||||||
i += parse_instruction(context, &binary[i], len); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
incr(i, len); \
|
|
||||||
return i; \
|
|
||||||
)
|
|
||||||
|
|
||||||
enum OP_CODES {
|
|
||||||
#define AS_ENUM(NAME, CODE, PARAM, NUM_RESULTS, LEN_IMMIDIATE, BODY) NAME = CODE,
|
|
||||||
DEFINE_OPERATIONS(AS_ENUM)
|
|
||||||
INSTR_END = 0x0B,
|
|
||||||
INSTR_ELSE = 0x05
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#define AS_FUNCTION(NAME, CODE, PARAM, NUM_RESULTS, LEN_IMMIDIATE, BODY) \
|
|
||||||
int exec_##NAME(struct context context, struct value_t *a, \
|
|
||||||
struct value_t *b, void *immidiate, struct value_t *result, \
|
|
||||||
u_char *binary, size_t len) { \
|
|
||||||
(void) context; \
|
|
||||||
(void) a; \
|
|
||||||
(void) b; \
|
|
||||||
(void) immidiate; \
|
|
||||||
(void) result; \
|
|
||||||
(void) binary; \
|
|
||||||
(void) len; \
|
|
||||||
BODY; \
|
|
||||||
return 0; \
|
|
||||||
}
|
|
||||||
DEFINE_OPERATIONS(AS_FUNCTION)
|
|
||||||
|
|
||||||
struct instruction {
|
|
||||||
size_t num_param;
|
|
||||||
enum TYPE params[2];
|
|
||||||
size_t len_immidiate;
|
|
||||||
size_t num_results;
|
|
||||||
int (*exec) (struct context context, struct value_t *a, struct value_t *b, void *immidiate, struct value_t *result, u_char *binary, size_t len);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct instruction INSTRUCTIONS[] = {
|
|
||||||
#define AS_INSTRUCTION(NAME, CODE, PARAM, NUM_RESULTS, LEN_IMMIDIATE, BODY) \
|
|
||||||
[NAME] = { \
|
|
||||||
.num_param = sizeof((enum TYPE[]) {PARAM}) / sizeof(enum TYPE), \
|
|
||||||
.params = {PARAM}, \
|
|
||||||
.num_results = NUM_RESULTS, \
|
|
||||||
.len_immidiate = LEN_IMMIDIATE, \
|
|
||||||
.exec = &exec_##NAME \
|
|
||||||
},
|
|
||||||
DEFINE_OPERATIONS(AS_INSTRUCTION)
|
|
||||||
};
|
|
||||||
|
|
||||||
int parse_instruction(struct context context, u_char *binary, size_t len) {
|
|
||||||
size_t i = 0;
|
|
||||||
enum OP_CODES op_code = binary[i];
|
|
||||||
u_char *instr_addr = &binary[i];
|
u_char *instr_addr = &binary[i];
|
||||||
|
struct value_t a = {0};
|
||||||
|
struct value_t b = {0};
|
||||||
struct value_t result = {0};
|
struct value_t result = {0};
|
||||||
struct value_t arguments[2];
|
|
||||||
|
|
||||||
incr(i, len);
|
incr(i, len);
|
||||||
|
|
||||||
struct instruction *instr = &INSTRUCTIONS[op_code];
|
switch (instr) {
|
||||||
if (instr->exec == NULL) {
|
case INSTR_CALL: {
|
||||||
printf("not implemented/illegal instruction %x at %lx\n", op_code, instr_addr - context.module->binary);
|
int func_index = binary[i];
|
||||||
exit(1);
|
incr(i, len);
|
||||||
};
|
// stack_pop(&module->stack, &a);
|
||||||
|
parse_function(module, func_index, len);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case INSTR_ELSE:
|
||||||
|
printf("reached else instruction: impossible!\n");
|
||||||
|
case INSTR_END:
|
||||||
|
break;
|
||||||
|
case INSTR_F64_CONST:
|
||||||
|
result.type = TYPE_F64;
|
||||||
|
result.value.f64 = *(double*)&binary[i];
|
||||||
|
i += 8;
|
||||||
|
stack_push(&module->stack, &result);
|
||||||
|
break;
|
||||||
|
case INSTR_F64_LT: {
|
||||||
|
stack_pop(&module->stack, &a);
|
||||||
|
stack_pop(&module->stack, &b);
|
||||||
|
if (a.type != TYPE_F64 || b.type != TYPE_F64)
|
||||||
|
printf("Wrong types!\n");
|
||||||
|
result.type = TYPE_F64;
|
||||||
|
result.value.f64 = b.value.f64 < a.value.f64;
|
||||||
|
stack_push(&module->stack, &result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case INSTR_F64_MUL: {
|
||||||
|
stack_pop(&module->stack, &a);
|
||||||
|
stack_pop(&module->stack, &b);
|
||||||
|
if (a.type != TYPE_F64 || b.type != TYPE_F64)
|
||||||
|
printf("Wrong types!\n");
|
||||||
|
result.type = TYPE_F64;
|
||||||
|
result.value.f64 = a.value.f64 * b.value.f64;
|
||||||
|
stack_push(&module->stack, &result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case INSTR_F64_SUB: {
|
||||||
|
stack_pop(&module->stack, &a);
|
||||||
|
stack_pop(&module->stack, &b);
|
||||||
|
if (a.type != TYPE_F64 || b.type != TYPE_F64)
|
||||||
|
printf("Wrong types!\n");
|
||||||
|
result.type = TYPE_F64;
|
||||||
|
result.value.f64 = b.value.f64 - a.value.f64;
|
||||||
|
stack_push(&module->stack, &result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case INSTR_IF: {
|
||||||
|
stack_pop(&module->stack, &a);
|
||||||
|
enum TYPE condition_type = binary[i];
|
||||||
|
incr(i, len);
|
||||||
|
if (a.type != condition_type)
|
||||||
|
printf("Wrong types!\n");
|
||||||
|
|
||||||
for (size_t param_i = 0; param_i < instr->num_param; param_i++) {
|
while (binary[i] != INSTR_ELSE) {
|
||||||
stack_pop(&context.module->stack, &arguments[param_i]);
|
// TODO test condition with correct type.
|
||||||
if (instr->params[param_i] != TYPE_ANY && arguments[param_i].type != instr->params[param_i]) {
|
// This might not matter since all types are false with 0x0
|
||||||
printf("wrong type! %x\n", op_code);
|
if (a.value.i64) {
|
||||||
}
|
i += parse_instruction(module, &binary[i], func_i, func_stack_begin, len);
|
||||||
|
} else {
|
||||||
|
incr(i, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
incr(i, len);
|
||||||
|
while (binary[i] != INSTR_END) {
|
||||||
|
if (a.value.i64) {
|
||||||
|
incr(i, len);
|
||||||
|
} else {
|
||||||
|
i += parse_instruction(module, &binary[i], func_i, func_stack_begin, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
incr(i, len);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case INSTR_LOCAL_GET: {
|
||||||
|
int local_index = binary[i];
|
||||||
|
size_t func_type_i = module->func_to_func_type[func_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;
|
||||||
|
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);
|
||||||
|
stack_push(&module->stack, &result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
printf("unknown instruction! %x at %lx\n", instr, instr_addr - module->binary);
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
i += instr->exec(context, &arguments[0], &arguments[1], &binary[i], &result, &binary[i + instr->len_immidiate], len);
|
|
||||||
i += instr->len_immidiate;
|
|
||||||
if (instr->num_results) {
|
|
||||||
stack_push(&context.module->stack, &result);
|
|
||||||
}
|
|
||||||
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
int parse_function(struct module *module, size_t func_i, size_t len) {
|
int parse_function(struct module *module, size_t func_i, int len) {
|
||||||
size_t i = 0;
|
int i = 0;
|
||||||
struct func_t *func = &module->func[func_i];
|
u_char *binary = module->code[func_i];
|
||||||
u_char *binary = func->addr;
|
size_t func_type_i = module->func_to_func_type[func_i];
|
||||||
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;
|
||||||
size_t func_stack_end;
|
size_t func_stack_end;
|
||||||
struct value_t result = {0};
|
struct value_t result = {0};
|
||||||
struct context context = {
|
|
||||||
.module = module,
|
|
||||||
.func_i = func_i,
|
|
||||||
.func_stack_begin = func_stack_begin
|
|
||||||
};
|
|
||||||
|
|
||||||
incr(i, len);
|
incr(i, len);
|
||||||
func->num_local_vars = binary[i];
|
// int local_decl_cound = binary[i];
|
||||||
incr(i, len);
|
incr(i, len);
|
||||||
for (size_t local_var_i = 0; local_var_i < func->num_local_vars; local_var_i++) {
|
module->scope = 1;
|
||||||
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(context, &binary[i], len);
|
i += parse_instruction(module, &binary[i], func_i, func_stack_begin, len);
|
||||||
}
|
}
|
||||||
incr(i, len);
|
incr(i, 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 local_i = 0; local_i < func_type->num_params + func->num_local_vars; local_i++) {
|
for (size_t param_i = 0; param_i < func_type->num_params; param_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++) {
|
||||||
|
@ -378,8 +362,8 @@ int parse_function(struct module *module, size_t func_i, size_t len) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
int parse_section(struct module *module, u_char *binary, size_t len) {
|
int parse_section(struct module *module, u_char *binary, int len) {
|
||||||
size_t i = 0;
|
int i = 0;
|
||||||
enum section type = binary[i];
|
enum section type = binary[i];
|
||||||
incr(i, len);
|
incr(i, len);
|
||||||
int size = binary[i];
|
int size = binary[i];
|
||||||
|
@ -397,7 +381,7 @@ int parse_section(struct module *module, u_char *binary, size_t len) {
|
||||||
for (size_t type_i = 0; type_i < num_types; type_i++) {
|
for (size_t type_i = 0; type_i < num_types; type_i++) {
|
||||||
if (binary[i] != 0x60) {
|
if (binary[i] != 0x60) {
|
||||||
printf("expected function type, found %x\n", binary[i]);
|
printf("expected function type, found %x\n", binary[i]);
|
||||||
return 0;
|
return -1;
|
||||||
}
|
}
|
||||||
incr(i, len);
|
incr(i, len);
|
||||||
func_type = &module->func_types[type_i];
|
func_type = &module->func_types[type_i];
|
||||||
|
@ -422,7 +406,7 @@ int parse_section(struct module *module, u_char *binary, size_t 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[function_i].func_type_index = binary[i];
|
module->func_to_func_type[function_i] = binary[i];
|
||||||
incr(i, len);
|
incr(i, len);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -438,7 +422,7 @@ int parse_section(struct module *module, u_char *binary, size_t len) {
|
||||||
|
|
||||||
if(module->num_exports > MAX_FUNCTIONS) {
|
if(module->num_exports > MAX_FUNCTIONS) {
|
||||||
printf("Number of exports exceeds maximum number of functions in a module (%d)", MAX_FUNCTIONS);
|
printf("Number of exports exceeds maximum number of functions in a module (%d)", MAX_FUNCTIONS);
|
||||||
return 0;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
incr(i, len);
|
incr(i, len);
|
||||||
|
@ -458,7 +442,7 @@ int parse_section(struct module *module, u_char *binary, size_t 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[export->func_index].func_type_index;
|
size_t func_type_index = module->func_to_func_type[export->func_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]]);
|
||||||
|
@ -488,7 +472,7 @@ int parse_section(struct module *module, u_char *binary, size_t 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->func[function_i].addr = &binary[i];
|
module->code[function_i] = &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});
|
||||||
|
@ -509,7 +493,7 @@ int parse_section(struct module *module, u_char *binary, size_t len) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int parse_module(struct module *module, u_char *binary, size_t len) {
|
int parse_module(struct module *module, u_char *binary, size_t len) {
|
||||||
size_t i = 0;
|
int i = 0;
|
||||||
char *magic = "\0asm";
|
char *magic = "\0asm";
|
||||||
while (i < 4) {
|
while (i < 4) {
|
||||||
if ((char) binary[i] != magic[i]) {
|
if ((char) binary[i] != magic[i]) {
|
||||||
|
@ -521,7 +505,7 @@ int parse_module(struct module *module, u_char *binary, size_t len) {
|
||||||
printf("magic found\n");
|
printf("magic found\n");
|
||||||
printf("wasm version: %d\n", le32toh(*(int*)&binary[i]));
|
printf("wasm version: %d\n", le32toh(*(int*)&binary[i]));
|
||||||
i += 4;
|
i += 4;
|
||||||
printf("addr %zu\n", i);
|
printf("addr %d\n", i);
|
||||||
|
|
||||||
module->binary = binary;
|
module->binary = binary;
|
||||||
|
|
||||||
|
@ -537,9 +521,8 @@ int main(int argc, char **argv) {
|
||||||
struct stat st;
|
struct stat st;
|
||||||
struct module module = {0};
|
struct module module = {0};
|
||||||
|
|
||||||
if (argc < 3) {
|
if (argc != 2) {
|
||||||
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) {
|
||||||
|
@ -569,9 +552,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;
|
||||||
size_t function_search_type_index = module.func[function_search_i].func_type_index;
|
struct func_type_t *func_type_search = &module.func_types[module.func_to_func_type[function_search_i]];
|
||||||
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 != (size_t) (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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue