-
Notifications
You must be signed in to change notification settings - Fork 5
/
compile.h
251 lines (205 loc) · 4.39 KB
/
compile.h
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
#ifndef COMPILE_H
#define COMPILE_H
#include "types.h"
#include "rhd/heap_string.h"
#include "data_type.h"
#include "rhd/hash_string.h"
#include "rhd/hash_map.h"
#include "arena.h"
#include "instruction.h"
#include "register.h"
#include "virtual_opcodes.h"
#include <setjmp.h>
enum
{
VREG_SP,
VREG_BP,
VREG_IP,
VREG_RETURN_VALUE,
VREG_MAX
};
typedef int vreg_t;
typedef int reg_t;
typedef struct
{
int nbits;
int indexed;
union
{
int64_t dq;
int32_t dd[2];
int16_t dw[4];
int8_t db[8];
};
} vregval_t;
static void setvregval(vregval_t *rv, int i)
{
rv->indexed = 0;
rv->nbits = 32;
rv->dd[0] = i;
}
static int getvregval(vregval_t *rv)
{
switch(rv->nbits)
{
case 32:
return rv->dd[0];
case 64:
return rv->dq;
case 8:
return rv->db[0];
case 16:
return rv->dw[0];
}
}
static void setvregvalindex(vregval_t *rv, int index)
{
rv->indexed = 1;
rv->nbits = 32;
rv->dd[0] = index;
}
typedef struct variable_s
{
int offset;
int is_param;
struct ast_node_s *data_type_node;
} variable_t;
#define FUNCTION_NAME_MAX_CHARACTERS (64)
#define VOPCACHE_MAX (64)
typedef struct
{
voperand_t key, value;
} vopcache_t;
typedef struct function_s
{
char name[FUNCTION_NAME_MAX_CHARACTERS];
struct hash_map *arguments;
struct hash_map *variables;
int localvariablesize;
heap_string bytecode;
vinstr_t *instructions;
size_t instruction_index;
size_t index;
/* vinstr_t *returns[32]; */
/* size_t numreturns; */
vopcache_t vopcache[VOPCACHE_MAX];
size_t vopcacheindex;
voperand_t eoflabel;
int argcost;
int returnsize;
} function_t;
#define FUNCTION_MAX_INSTRUCTIONS (256)
struct reljmp_s
{
i32 data_index;
i32 ip;
int type;
};
typedef struct reljmp_s reljmp_t;
#define RJ_JNZ (1)
#define RJ_JZ (2)
#define RJ_JNE (1)
#define RJ_JE (2)
#define RJ_JL (4)
#define RJ_JLE (8)
#define RJ_JG (16)
#define RJ_JGE (32)
#define RJ_JMP (64)
#define RJ_REVERSE (1<<30)
typedef struct
{
/* vinstr_t *breaks[32]; */
/* size_t maxbreaks; */
/* size_t numbreaks; */
voperand_t breaklabel;
} scope_t;
enum RELOC_TYPE
{
RELOC_CODE,
RELOC_DATA,
RELOC_IMPORT
};
struct relocation
{
enum RELOC_TYPE type;
size_t size;
intptr_t from;
intptr_t to;
};
enum BUILD_TARGET
{
BT_UNKNOWN,
BT_LINUX_X86,
BT_LINUX_X64,
BT_WIN32,
BT_WIN64,
BT_MEMORY,
BT_OPCODES
};
static const char* build_target_strings[] = { "Unknown", "Linux ELF x86", "Linux ELF x64", "Win32", "Win64", "Memory", "Opcodes", NULL};
struct dynlib_sym
{
const char* lib_name;
const char* sym_name;
intptr_t offset; //TODO: FIXME if and when we ever compile for cross platform or x86/x64 this should probably be changed to match the target binary format.
hash_t hash;
};
typedef struct dynlib_sym* (*find_import_fn_t)(void *userptr, const char *key);
typedef struct
{
int index;
size_t length;
char *buffer;
} indexed_data_t;
#define MAX_INDEXED_DATA 256 //TODO: dynamically increase
typedef struct
{
//size in bits of each type
int longsize;
int intsize;
int shortsize;
int charsize;
int floatsize;
int doublesize;
int pointersize;
} fundamental_type_size_t;
#define COMPILER_MAX_FUNCTIONS (64)
#define COMPILER_MAX_SCOPES (16)
typedef enum
{
COMPILER_FLAGS_NONE,
COMPILER_FLAGS_ALU_THREE_OPERANDS,
COMPILER_FLAGS_INDIRECT_ADDRESSING
} compiler_flags_t;
struct compiler_s
{
arena_t *allocator;
int numbits;
int flags;
jmp_buf jmp;
int build_target;
u32 entry;
heap_string data;
struct linked_list *relocations;
fundamental_type_size_t fts;
heap_string instr;
function_t *function;
indexed_data_t indexed_data[MAX_INDEXED_DATA];
int numindexeddata;
scope_t *scope[COMPILER_MAX_SCOPES]; //TODO: N number of scopes, dynamic array / stack
int scope_index;
void* find_import_fn_userptr;
find_import_fn_t find_import_fn;
int (*rvalue)(struct compiler_s *ctx, vreg_t reg, struct ast_node *n);
int (*lvalue)(struct compiler_s *ctx, vreg_t reg, struct ast_node *n);
void (*print)(struct compiler_s *ctx, const char *fmt, ...);
size_t numfunctions;
struct hash_map *functions;
size_t vregindex;
size_t labelindex;
};
typedef struct compiler_s compiler_t;
int add_indexed_data(compiler_t *ctx, const void *buffer, size_t len);
function_t *compiler_alloc_function(compiler_t *ctx, const char *name);
void compiler_init(compiler_t *c, arena_t *allocator, int numbits, compiler_flags_t flags);
#endif