Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
epidemian
GitHub Repository: epidemian/gravity
Path: blob/master/src/utils/gravity_debug.c
1214 views
1
//
2
// gravity_debug.c
3
// gravity
4
//
5
// Created by Marco Bambini on 01/04/16.
6
// Copyright (c) 2016 CreoLabs. All rights reserved.
7
//
8
9
#include <assert.h>
10
#include "gravity_value.h"
11
#include "gravity_vmmacros.h"
12
#include "gravity_debug.h"
13
14
const char *opcode_constname (int n) {
15
switch (n) {
16
case CPOOL_VALUE_SUPER: return "SUPER";
17
case CPOOL_VALUE_NULL: return "NULL";
18
case CPOOL_VALUE_UNDEFINED: return "UNDEFINED";
19
case CPOOL_VALUE_ARGUMENTS: return "ARGUMENTS";
20
case CPOOL_VALUE_TRUE: return "TRUE";
21
case CPOOL_VALUE_FALSE: return "FALSE";
22
case CPOOL_VALUE_FUNC: return "FUNC";
23
}
24
25
assert(0);
26
return "N/A";
27
}
28
29
const char *opcode_name (opcode_t op) {
30
static const char *optable[] = {
31
"RET0", "HALT", "NOP", "RET", "CALL", "LOAD", "LOADS", "LOADAT",
32
"LOADK", "LOADG", "LOADI", "LOADU", "MOVE", "STORE", "STOREAT",
33
"STOREG", "STOREU", "JUMP", "JUMPF", "SWITCH", "ADD", "SUB", "DIV",
34
"MUL", "REM", "AND", "OR", "LT", "GT", "EQ", "LEQ", "GEQ", "NEQ",
35
"EQQ", "NEQQ", "ISA", "MATCH", "NEG", "NOT", "LSHIFT", "RSHIFT", "BAND",
36
"BOR", "BXOR", "BNOT", "MAPNEW", "LISTNEW", "RANGENEW", "SETLIST",
37
"CLOSURE", "CLOSE", "RESERVED1", "RESERVED2", "RESERVED3", "RESERVED4",
38
"RESERVED5", "RESERVED6"};
39
return optable[op];
40
}
41
42
#define DUMP_VM(buffer, bindex, ...) bindex += snprintf(&buffer[bindex], balloc-bindex, "%06u\t", pc); \
43
bindex += snprintf(&buffer[bindex], balloc-bindex, __VA_ARGS__); \
44
bindex += snprintf(&buffer[bindex], balloc-bindex, "\n");
45
46
#define DUMP_VM_NOCR(buffer, bindex, ...) bindex += snprintf(&buffer[bindex], balloc-bindex, "%06u\t", pc); \
47
bindex += snprintf(&buffer[bindex], balloc-bindex, __VA_ARGS__);
48
49
#define DUMP_VM_RAW(buffer, bindex, ...) bindex += snprintf(&buffer[bindex], balloc-bindex, __VA_ARGS__);
50
51
const char *gravity_disassemble (const char *bcode, uint32_t blen) {
52
uint32_t *ip = NULL;
53
uint32_t pc = 0, inst = 0, ninsts = 0;
54
opcode_t op;
55
56
const int rowlen = 256;
57
uint32_t bindex = 0;
58
uint32_t balloc = 0;
59
char *buffer = NULL;
60
61
// decode textual buffer to real bytecode
62
ip = gravity_bytecode_deserialize(bcode, blen, &ninsts);
63
if ((ip == NULL) || (ninsts == 0)) goto abort_disassemble;
64
65
// allocate a buffer big enought to fit all disassembled bytecode
66
// I assume that each instruction (each row) will be 256 chars long
67
balloc = ninsts * rowlen;
68
buffer = mem_alloc(balloc);
69
if (!buffer) goto abort_disassemble;
70
71
// conversion loop
72
while (pc < ninsts) {
73
inst = *ip++;
74
op = (opcode_t)OPCODE_GET_OPCODE(inst);
75
76
switch (op) {
77
case NOP: {
78
DUMP_VM(buffer, bindex, "NOP");
79
break;
80
}
81
82
case MOVE: {
83
OPCODE_GET_ONE8bit_ONE18bit(inst, const uint32_t r1, const uint32_t r2);
84
DUMP_VM(buffer, bindex, "MOVE %d %d", r1, r2);
85
break;
86
}
87
88
case LOADI: {
89
//OPCODE_GET_ONE8bit_ONE18bit(inst, uint32_t r1, int32_t value); if no support for signed int
90
OPCODE_GET_ONE8bit_SIGN_ONE17bit(inst, const uint32_t r1, const int32_t value);
91
DUMP_VM(buffer, bindex, "LOADI %d %d", r1, value);
92
break;
93
}
94
95
case LOADK: {
96
OPCODE_GET_ONE8bit_ONE18bit(inst, const uint32_t r1, const uint32_t index);
97
if (index < CPOOL_INDEX_MAX) {
98
DUMP_VM(buffer, bindex, "LOADK %d %d", r1, index);
99
} else {
100
const char *special;
101
switch (index) {
102
case CPOOL_VALUE_SUPER: special = "SUPER"; break;
103
case CPOOL_VALUE_NULL: special = "NULL"; break;
104
case CPOOL_VALUE_UNDEFINED: special = "UNDEFINED"; break;
105
case CPOOL_VALUE_ARGUMENTS: special = "ARGUMENTS"; break;
106
case CPOOL_VALUE_TRUE: special = "TRUE"; break;
107
case CPOOL_VALUE_FALSE: special = "FALSE"; break;
108
default: ASSERT(0, "Invalid index in LOADK opcode"); break;
109
}
110
DUMP_VM(buffer, bindex, "LOADK %d %s", r1, special);
111
}
112
break;
113
}
114
115
case LOADG: {
116
OPCODE_GET_ONE8bit_ONE18bit(inst, uint32_t r1, int32_t index);
117
DUMP_VM(buffer, bindex, "LOADG %d %d", r1, index);
118
break;
119
}
120
121
case LOAD:
122
case LOADS:
123
case LOADAT: {
124
OPCODE_GET_TWO8bit_ONE10bit(inst, const uint32_t r1, const uint32_t r2, const uint32_t r3);
125
DUMP_VM(buffer, bindex, "%s %d %d %d", (op == LOAD) ? "LOAD" : "LOADAT", r1, r2, r3);
126
break;
127
}
128
129
case LOADU: {
130
ASSERT(0, "To be implemented");
131
break;
132
}
133
134
case STOREG: {
135
OPCODE_GET_ONE8bit_ONE18bit(inst, uint32_t r1, int32_t index);
136
DUMP_VM(buffer, bindex, "STOREG %d %d", r1, index);
137
break;
138
}
139
140
case STOREU: {
141
ASSERT(0, "To be implemented");
142
break;
143
}
144
145
case STORE:
146
case STOREAT: {
147
OPCODE_GET_TWO8bit_ONE10bit(inst, const uint32_t r1, const uint32_t r2, const uint32_t r3);
148
DUMP_VM(buffer, bindex, "%s %d %d %d", (op == STORE) ? "STORE" : "STOREAT", r1, r2, r3);
149
break;
150
}
151
152
case EQQ:
153
case NEQQ:
154
case ISA:
155
case MATCH:
156
case LT:
157
case GT:
158
case EQ:
159
case LEQ:
160
case GEQ:
161
case NEQ: {
162
OPCODE_GET_TWO8bit_ONE10bit(inst, const uint32_t r1, const uint32_t r2, const uint32_t r3);
163
DUMP_VM(buffer, bindex, "%s %d %d %d", opcode_name(op), r1, r2, r3);
164
break;
165
}
166
167
// binary operators
168
case LSHIFT:
169
case RSHIFT:
170
case BAND:
171
case BOR:
172
case BXOR:
173
case ADD:
174
case SUB:
175
case DIV:
176
case MUL:
177
case REM:
178
case AND:
179
case OR: {
180
OPCODE_GET_TWO8bit_ONE10bit(inst, const uint32_t r1, const uint32_t r2, const uint32_t r3);
181
DUMP_VM(buffer, bindex, "%s %d %d %d", opcode_name(op), r1, r2, r3);
182
break;
183
}
184
185
// unary operators
186
case BNOT:
187
case NEG:
188
case NOT: {
189
OPCODE_GET_TWO8bit_ONE10bit(inst, const uint32_t r1, const uint32_t r2, const uint32_t r3);
190
#pragma unused(r3)
191
DUMP_VM(buffer, bindex, "%s %d %d %d", opcode_name(op), r1, r2, r3);
192
break;
193
}
194
195
case RANGENEW: {
196
OPCODE_GET_TWO8bit_ONE10bit(inst, const uint32_t r1, const uint32_t r2, const uint32_t r3);
197
DUMP_VM(buffer, bindex, "%s %d %d %d", opcode_name(op), r1, r2, r3);
198
break;
199
}
200
201
case JUMPF: {
202
OPCODE_GET_ONE8bit_ONE18bit(inst, const uint32_t r1, const int32_t value);
203
DUMP_VM(buffer, bindex, "JUMPF %d %d", r1, value);
204
break;
205
}
206
207
case JUMP: {
208
OPCODE_GET_ONE26bit(inst, const uint32_t value);
209
DUMP_VM(buffer, bindex, "JUMP %d", value);
210
break;
211
}
212
213
case CALL: {
214
// CALL A B C => R(A) = B(C0... CN)
215
OPCODE_GET_THREE8bit(inst, const uint32_t r1, const uint32_t r2, uint32_t r3);
216
DUMP_VM(buffer, bindex, "CALL %d %d %d", r1, r2, r3);
217
break;
218
}
219
220
case RET0:
221
case RET: {
222
223
if (op == RET0) {
224
DUMP_VM(buffer, bindex, "RET0");
225
} else {
226
OPCODE_GET_ONE8bit(inst, const uint32_t r1);
227
DUMP_VM(buffer, bindex, "RET %d", r1);
228
}
229
break;
230
}
231
232
case HALT: {
233
DUMP_VM(buffer, bindex, "HALT");
234
break;
235
}
236
237
case SWITCH: {
238
ASSERT(0, "To be implemented");
239
break;
240
}
241
242
case MAPNEW: {
243
OPCODE_GET_ONE8bit_ONE18bit(inst, const uint32_t r1, const uint32_t n);
244
DUMP_VM(buffer, bindex, "MAPNEW %d %d", r1, n);
245
break;
246
}
247
248
case LISTNEW: {
249
OPCODE_GET_ONE8bit_ONE18bit(inst, const uint32_t r1, const uint32_t n);
250
DUMP_VM(buffer, bindex, "LISTNEW %d %d", r1, n);
251
break;
252
}
253
254
case SETLIST: {
255
OPCODE_GET_TWO8bit_ONE10bit(inst, const uint32_t r1, uint32_t r2, const uint32_t r3);
256
#pragma unused(r3)
257
DUMP_VM(buffer, bindex, "SETLIST %d %d", r1, r2);
258
break;
259
}
260
261
case CLOSURE: {
262
OPCODE_GET_ONE8bit_ONE18bit(inst, const uint32_t r1, const uint32_t r2);
263
DUMP_VM(buffer, bindex, "CLOSURE %d %d", r1, r2);
264
break;
265
}
266
267
case CLOSE: {
268
OPCODE_GET_ONE8bit_ONE18bit(inst, const uint32_t r1, const uint32_t r2);
269
#pragma unused(r2)
270
DUMP_VM(buffer, bindex, "CLOSE %d", r1);
271
break;
272
}
273
274
case RESERVED1:
275
case RESERVED2:
276
case RESERVED3:
277
case RESERVED4:
278
case RESERVED5:
279
case RESERVED6: {
280
DUMP_VM(buffer, bindex, "RESERVED");
281
break;
282
}
283
}
284
285
++pc;
286
}
287
288
return buffer;
289
290
abort_disassemble:
291
if (ip) mem_free(ip);
292
if (buffer) mem_free(buffer);
293
return NULL;
294
}
295
296