-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdecomp.c
More file actions
125 lines (114 loc) · 3.16 KB
/
decomp.c
File metadata and controls
125 lines (114 loc) · 3.16 KB
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
#include "aux.h"
#include "types/arena.h"
#include "types/vec.h"
#include "types/sexp.h"
#include "types/ht.h"
#include "read.h"
#include "compi.h"
#include "comp.h"
#include "decomp.h"
static ptrdiff_t
op_basic(const char *name, ptrdiff_t offset)
{
printf("%-"CODE_COL"s\n", name);
return offset + 1;
}
static ptrdiff_t
op_imm(Chunk *chunk, const char *name, ptrdiff_t offset, size_t arglen)
{
printf("%-"CODE_COL"s ; ", name);
for (int i = 0; arglen - i > 0; i++) {
char buff[atoi(ARGS_COL)];
size_t idx = chunk->code[offset + i + 1];
snprintf(buff, atoi(ARGS_COL), "%s", valuestr(chunk->conspool[idx]));
printf("%s", buff);
if (i - 1 > 0) printf(", ");
}
putchar('\n');
return offset + arglen + 1;
}
static ptrdiff_t
op_jmp(Chunk *chunk, const char *name, ptrdiff_t offset, size_t arglen)
{
printf("%-"CODE_COL"s ; ", name);
for (int i = 0; arglen - i > 0; i++) {
char buff[atoi(ARGS_COL)];
snprintf(buff, atoi(ARGS_COL), "%d", chunk->code[offset + i + 1]);
printf("%s", buff);
if (i - 1 > 0) printf(", ");
}
putchar('\n');
return offset + arglen + 1;
}
static void
printcol(const char *width)
{
printf(";-");
for (int i = 0; i < atoi(width); i++) putchar('-');
printf("-");
}
static void
decompile_header(const char *name)
{
printf(DECOMP_HEADER"\n", name, "BYTE", "WHERE", "OPCODE", "ARGS");
printcol(BYTE_COL);
printcol(WHERE_COL);
printcol(CODE_COL);
printcol(ARGS_COL);
printf("\n");
}
static ptrdiff_t
decompile_op_(Chunk *chunk, ptrdiff_t offset)
{
static Range lastrange;
printf("; %0"BYTE_COL"ld ; ", offset);
Range where = whereis(chunk, offset);
if (offset > 0 && lastrange.at == where.at) {
printf("%-"WHERE_COL"s ", "-");
} else {
char buff[BUFSIZ];
snprintf(buff, BUFSIZ, "%-4ld %ld ", where.at, where.len);
printf("%-8s", buff);
}
printf("; ");
lastrange = where;
uint8_t instr = chunk->code[offset];
switch (instr) {
case OP_LOAD: return op_imm(chunk, "LOAD", offset, 1);
case OP_BIND: return op_imm(chunk, "BIND", offset, 1);
case OP_PUSH: return op_imm(chunk, "PUSH", offset, 1);
case OP_JF: return op_jmp(chunk, "JF", offset, 1);
case OP_JMP: return op_jmp(chunk, "JMP", offset, 1);
case OP_RET: return op_basic("RET", offset);
case OP_NEG: return op_basic("NEG", offset);
case OP_ADD: return op_basic("ADD", offset);
case OP_SUB: return op_basic("SUB", offset);
case OP_MUL: return op_basic("MUL", offset);
case OP_POP: return op_basic("POP", offset);
case OP_EQ: return op_basic("EQ", offset);
case OP_CALL: return op_basic("CALL", offset);
case OP_DIV: return op_basic("DIV", offset);
default:
printf("; Unknown opcode %d\n", instr);
return offset + 1;
}
}
ptrdiff_t
decompile_op(Chunk *chunk, ptrdiff_t offset)
{
decompile_header("OPCODE");
return decompile_op_(chunk, offset);
}
void
decompile(Chunk *chunk, const char *name)
{
decompile_header(name);
for (size_t offset = 0; offset < vec_len(chunk->code);)
offset = decompile_op_(chunk, offset);
printf(";\n");
for (size_t i = 0; i < vec_len(chunk->conspool); i++) {
if (!FUNP(chunk->conspool[i])) continue;
decompile(AS_FUN(chunk->conspool[i])->body, "<FUN>");
}
printf(";;; [END]\n");
}