-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathmain.c
139 lines (125 loc) · 3.44 KB
/
main.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#include <sinter/config.h>
#include <sinter.h>
#include <sinter/heap.h>
#include <sinter/stack.h>
#include <sinter/program.h>
#include <sinter/vm.h>
/**
* Validates the program header. Faults if it is invalid.
*/
static inline void validate_header(const svm_header_t *const header) {
if (header->magic != SVM_MAGIC) {
SIDEBUG("Invalid magic: %x\n", header->magic);
sifault(sinter_fault_invalid_program);
return;
}
}
/**
* Expands our sinanbox_t result into a friendlier structure for external
* consumers to use.
*/
static void set_result(sinanbox_t exec_result, sinter_value_t *result) {
if (NANBOX_ISEMPTY(exec_result)) {
SIDEBUG("Program did not return value from toplevel\n");
return;
}
SIDEBUG("Return value: ");
SIDEBUG_NANBOX(exec_result);
SIDEBUG("\n");
switch (NANBOX_GETTYPE(exec_result)) {
NANBOX_CASES_TINT
result->type = sinter_type_integer;
result->integer_value = NANBOX_INT(exec_result);
break;
case NANBOX_TBOOL:
result->type = sinter_type_boolean;
result->boolean_value = NANBOX_BOOL(exec_result);
break;
case NANBOX_TUNDEF:
result->type = sinter_type_undefined;
break;
case NANBOX_TNULL:
result->type = sinter_type_null;
break;
case NANBOX_TIFN:
result->type = sinter_type_function;
result->object_value = exec_result.as_u32;
break;
NANBOX_CASES_TPTR {
siheap_header_t *obj = SIHEAP_NANBOXTOPTR(exec_result);
switch (obj->type) {
case sitype_strconst:
case sitype_string:
case sitype_strpair:
result->type = sinter_type_string;
result->string_value = sistrobj_tocharptr(obj);
break;
case sitype_intcont:
case sitype_function:
result->type = sinter_type_function;
result->object_value = exec_result.as_u32;
break;
case sitype_array:
result->type = sinter_type_array;
result->object_value = exec_result.as_u32;
break;
case sitype_array_data:
case sitype_empty:
case sitype_frame:
case sitype_free:
case sitype_env:
default:
SIBUGV("Unexpected return object type %d\n", obj->type);
break;
}
break;
}
default:
if (NANBOX_ISFLOAT(exec_result)) {
result->type = sinter_type_float;
result->float_value = NANBOX_FLOAT(exec_result);
} else {
SIBUGV("Unexpected NaNbox: %08x\n", exec_result.as_u32);
}
break;
}
}
sinter_fault_t sinter_run(const unsigned char *const code, const size_t code_size, sinter_value_t *result) {
#ifndef SINTER_STATIC_HEAP
if (!siheap) {
SIDEBUG("Heap not yet initialised!\n");
return sinter_fault_uninitialised_heap;
}
#endif
sistate.fault_reason = sinter_fault_none;
sistate.program = code;
sistate.program_end = code + code_size;
sistate.running = true;
sistate.pc = NULL;
sistate.env = NULL;
if (SINTER_FAULTED()) {
*result = (sinter_value_t) { 0 };
return sistate.fault_reason;
}
// Reset the heap and stack
siheap_init();
sistack_init();
const svm_header_t *header = (const svm_header_t *) code;
validate_header(header);
const svm_function_t *entry_fn = (const svm_function_t *) SISTATE_ADDRTOPC(header->entry);
sinanbox_t exec_result = siexec(entry_fn, NULL, 0, NULL);
set_result(exec_result, result);
return sinter_fault_none;
}
void sinter_setup_heap(void *heap, size_t size) {
#ifdef SINTER_STATIC_HEAP
(void) heap; (void) size;
return;
#else
siheap = heap;
siheap_size = size;
#endif
}
void sinter_stop(void) {
sistop();
}