Reduct  v1.0.4-3-gdaf0d70
A functional and immutable language.
Loading...
Searching...
No Matches
disasm_impl.h
Go to the documentation of this file.
1#ifndef REDUCT_DISASM_IMPL_H
2#define REDUCT_DISASM_IMPL_H 1
3
4#include "compile.h"
5#include "disasm.h"
6
8{
9 REDUCT_ASSERT(reduct != REDUCT_NULL);
10 REDUCT_ASSERT(function != REDUCT_NULL);
12
13 if (reduct == REDUCT_NULL || function == REDUCT_NULL || out == REDUCT_NULL)
14 {
15 return;
16 }
17
18 REDUCT_FPRINTF(out, "================================================================================\n");
19 REDUCT_FPRINTF(out, "Function: %p\n", (void*)function);
20 REDUCT_FPRINTF(out, "Arity: %u\n", (unsigned int)function->arity);
21 REDUCT_FPRINTF(out, "Instruction count: %u\n", (unsigned int)function->instCount);
22 REDUCT_FPRINTF(out, "Constant count: %u\n", (unsigned int)function->constantCount);
23 REDUCT_FPRINTF(out, "--------------------------------------------------------------------------------\n");
24
25 for (reduct_size_t i = 0; i < function->instCount; ++i)
26 {
27 reduct_inst_t inst = function->insts[i];
29 reduct_bool_t isConst = (REDUCT_INST_GET_OP(inst) & REDUCT_MODE_CONST) != 0;
34
35 const char* opName = "UNKNOWN";
36 switch (op)
37 {
39 opName = "LIST";
40 break;
42 opName = "JMP";
43 break;
45 opName = "JMPF";
46 break;
48 opName = "JMPT";
49 break;
51 opName = "CALL";
52 break;
54 opName = "RET";
55 break;
57 opName = "APPEND";
58 break;
60 opName = "MOV";
61 break;
63 opName = "EQ";
64 break;
66 opName = "NEQ";
67 break;
69 opName = "SEQ";
70 break;
72 opName = "SNEQ";
73 break;
75 opName = "LT";
76 break;
78 opName = "LE";
79 break;
81 opName = "GT";
82 break;
84 opName = "GE";
85 break;
87 opName = "ADD";
88 break;
90 opName = "SUB";
91 break;
93 opName = "MUL";
94 break;
96 opName = "DIV";
97 break;
99 opName = "MOD";
100 break;
102 opName = "BAND";
103 break;
105 opName = "BOR";
106 break;
108 opName = "BXOR";
109 break;
111 opName = "BNOT";
112 break;
114 opName = "SHL";
115 break;
117 opName = "SHR";
118 break;
120 opName = "CLOSURE";
121 break;
123 opName = "CAPTURE";
124 break;
126 opName = "TAILCALL";
127 break;
128 default:
129 break;
130 }
131
132 REDUCT_FPRINTF(out, "[%04u] %-12s ", (unsigned int)i, opName);
133
134 switch (REDUCT_INST_GET_OP_BASE(inst))
135 {
137 REDUCT_FPRINTF(out, "R%-5u %-6s %-6s", a, "", "");
138 break;
140 REDUCT_FPRINTF(out, "%-6d %-6s %-6s", sbx, "", "");
141 break;
144 REDUCT_FPRINTF(out, "R%-5u %-6d %-6s", a, sbx, "");
145 break;
149 REDUCT_FPRINTF(out, "R%-5u %-6u %c%-5u", a, b, isConst ? 'K' : 'R', c);
150 break;
152 REDUCT_FPRINTF(out, "%c%-5u %-6s %-6s", isConst ? 'K' : 'R', c, "", "");
153 break;
157 REDUCT_FPRINTF(out, "R%-5u %-6s %c%-5u", a, "", isConst ? 'K' : 'R', c);
158 break;
160 REDUCT_FPRINTF(out, "R%-5u %-6s K%-5u", a, "", c);
161 break;
162 default:
163 REDUCT_FPRINTF(out, "R%-5u R%-5u %c%-5u", a, b, isConst ? 'K' : 'R', c);
164 break;
165 }
166
167 reduct_bool_t hasInlineConst = REDUCT_FALSE;
168 if (op == REDUCT_OPCODE_CLOSURE || isConst)
169 {
170 hasInlineConst = REDUCT_TRUE;
171 }
172
173 if (op == REDUCT_OPCODE_JMP || op == REDUCT_OPCODE_JMPF || op == REDUCT_OPCODE_JMPT)
174 {
175 int target = (int)i + 1 + sbx;
176 REDUCT_FPRINTF(out, " ; -> [%04u]\n", target);
177 }
178 else if (hasInlineConst && c < function->constantCount)
179 {
180 reduct_const_slot_t* slot = &function->constants[c];
181 REDUCT_FPRINTF(out, " ; ");
182 if (slot->type == REDUCT_CONST_SLOT_ITEM)
183 {
184 reduct_item_t* item = slot->item;
185 if (item->type == REDUCT_ITEM_TYPE_ATOM)
186 {
187 REDUCT_FPRINTF(out, "\"%.*s\"\n", (int)item->atom.length, item->atom.string);
188 }
189 else if (item->type == REDUCT_ITEM_TYPE_LIST)
190 {
191 REDUCT_FPRINTF(out, "(list of %u handles)\n", (unsigned int)item->list.length);
192 }
193 else if (item->type == REDUCT_ITEM_TYPE_FUNCTION)
194 {
195 REDUCT_FPRINTF(out, "(function %p)\n", (void*)&item->function);
196 }
197 else
198 {
199 REDUCT_FPRINTF(out, "(unknown item)\n");
200 }
201 }
202 else if (slot->type == REDUCT_CONST_SLOT_CAPTURE)
203 {
204 REDUCT_FPRINTF(out, "(capture %.*s)\n", (int)slot->capture->length, slot->capture->string);
205 }
206 else
207 {
208 REDUCT_FPRINTF(out, "(none)\n");
209 }
210 }
211 else
212 {
213 REDUCT_FPRINTF(out, "\n");
214 }
215 }
216
217 if (function->constantCount > 0)
218 {
219 REDUCT_FPRINTF(out, "--------------------------------------------------------------------------------\n");
220 for (reduct_uint16_t i = 0; i < function->constantCount; ++i)
221 {
222 reduct_const_slot_t* slot = &function->constants[i];
223 if (slot->type == REDUCT_CONST_SLOT_ITEM)
224 {
225 reduct_item_t* item = slot->item;
226 if (item->type == REDUCT_ITEM_TYPE_ATOM)
227 {
228 REDUCT_FPRINTF(out, "[K%03u] \"%.*s\"\n", (unsigned int)i, (int)item->atom.length,
229 item->atom.string);
230 }
231 else if (item->type == REDUCT_ITEM_TYPE_LIST)
232 {
233 REDUCT_FPRINTF(out, "[K%03u] (list of %u handles)\n", (unsigned int)i,
234 (unsigned int)item->list.length);
235 }
236 else if (item->type == REDUCT_ITEM_TYPE_FUNCTION)
237 {
238 REDUCT_FPRINTF(out, "[K%03u] (function %p)\n", (unsigned int)i, (void*)&item->function);
239 }
240 else
241 {
242 REDUCT_FPRINTF(out, "[K%03u] (unknown type)\n", (unsigned int)i);
243 }
244 }
245 else if (slot->type == REDUCT_CONST_SLOT_CAPTURE)
246 {
247 REDUCT_FPRINTF(out, "[K%03u] (capture %.*s)\n", (unsigned int)i, (int)slot->capture->length,
248 slot->capture->string);
249 }
250 else
251 {
252 REDUCT_FPRINTF(out, "[K%03u] (none)\n", (unsigned int)i);
253 }
254 }
255 }
256
257 REDUCT_FPRINTF(out, "================================================================================\n");
258
259 for (reduct_uint16_t i = 0; i < function->constantCount; ++i)
260 {
261 reduct_const_slot_t* slot = &function->constants[i];
262 if (slot->type == REDUCT_CONST_SLOT_ITEM)
263 {
264 reduct_item_t* item = slot->item;
265 if (item->type == REDUCT_ITEM_TYPE_FUNCTION)
266 {
267 reduct_disasm_internal(reduct, &item->function, out);
268 }
269 }
270 }
271}
272
274{
275 REDUCT_ASSERT(reduct != REDUCT_NULL);
276 REDUCT_ASSERT(function != REDUCT_NULL);
278
279 reduct_disasm_internal(reduct, function, out);
280}
281
282#endif
Bytecode compilation.
size_t reduct_size_t
Definition defs.h:100
#define REDUCT_FPRINTF
Definition defs.h:50
reduct_bool_t
Boolean type.
Definition defs.h:135
@ REDUCT_FALSE
Definition defs.h:137
@ REDUCT_TRUE
Definition defs.h:136
uint32_t reduct_uint32_t
Definition defs.h:95
FILE * reduct_file_t
Definition defs.h:44
#define REDUCT_ASSERT(_cond)
Definition defs.h:25
#define REDUCT_API
Definition defs.h:7
uint16_t reduct_uint16_t
Definition defs.h:97
#define REDUCT_NULL
Definition defs.h:23
Bytecode disassembly.
static void reduct_disasm_internal(reduct_t *reduct, reduct_function_t *function, reduct_file_t out)
Definition disasm_impl.h:7
REDUCT_API void reduct_disasm(reduct_t *reduct, reduct_function_t *function, reduct_file_t out)
Disassembles a compiled function.
#define REDUCT_CONST_SLOT_CAPTURE(_capture)
Create a constant slot containing a variable name to be captured.
Definition function.h:64
#define REDUCT_CONST_SLOT_ITEM(_item)
Create a constant slot containing an item.
Definition function.h:57
#define REDUCT_INST_GET_C(_inst)
Get the C operand from an instruction.
Definition inst.h:185
#define REDUCT_INST_GET_A(_inst)
Get the A operand from an instruction.
Definition inst.h:171
#define REDUCT_INST_GET_SBX(_inst)
Get the SBX operand from an instruction.
Definition inst.h:192
#define REDUCT_INST_GET_OP(_inst)
Get the opcode from an instruction.
Definition inst.h:156
reduct_opcode_t
Opcode enumeration.
Definition inst.h:49
reduct_uint32_t reduct_inst_t
Instruction type.
Definition inst.h:97
#define REDUCT_INST_GET_B(_inst)
Get the B operand from an instruction.
Definition inst.h:178
#define REDUCT_INST_GET_OP_BASE(_inst)
Get the opcode base (without reduct_mode_t) from an instruction. Mask clears the REDUCT_MODE_CONST bi...
Definition inst.h:163
@ REDUCT_MODE_CONST
Constant operand mode.
Definition inst.h:41
@ REDUCT_OPCODE_DIV
(A, B, C) R(A) = R(B) / R/K(C)
Definition inst.h:71
@ REDUCT_OPCODE_JMPF
(A, sBx) Jump by sBx if R(A) is falsy.
Definition inst.h:53
@ REDUCT_OPCODE_JMPT
(A, sBx) Jump by sBx if R(A) is truthy.
Definition inst.h:54
@ REDUCT_OPCODE_APPEND
(A, C) Append value in R/K(C) to the back of the list in R(A).
Definition inst.h:59
@ REDUCT_OPCODE_SHR
(A, B, C) R(A) = R(B) >> R/K(C)
Definition inst.h:78
@ REDUCT_OPCODE_SEQ
(A, B, C) If R(B) === R/K(C) store true in R(A), else false.
Definition inst.h:62
@ REDUCT_OPCODE_SHL
(A, B, C) R(A) = R(B) << R/K(C)
Definition inst.h:77
@ REDUCT_OPCODE_SUB
(A, B, C) R(A) = R(B) - R/K(C)
Definition inst.h:69
@ REDUCT_OPCODE_NEQ
(A, B, C) If R(B) != R/K(C) store true in R(A), else false.
Definition inst.h:61
@ REDUCT_OPCODE_MOV
(A, C) Move value in R/K(C) to R(A).
Definition inst.h:57
@ REDUCT_OPCODE_MUL
(A, B, C) R(A) = R(B) * R/K(C)
Definition inst.h:70
@ REDUCT_OPCODE_ADD
(A, B, C) R(A) = R(B) + R/K(C)
Definition inst.h:68
@ REDUCT_OPCODE_BAND
(A, B, C) R(A) = R(B) & R/K(C)
Definition inst.h:73
@ REDUCT_OPCODE_RET
(C) Return value in R/K(C).
Definition inst.h:58
@ REDUCT_OPCODE_BNOT
(A, C) R(A) = ~R/K(C)
Definition inst.h:76
@ REDUCT_OPCODE_EQ
(A, B, C) If R(B) == R/K(C) store true in R(A), else false.
Definition inst.h:60
@ REDUCT_OPCODE_CALL
(A, B, C) Call callable in R/K(C) with B args starting from R(A). Result in R(A).
Definition inst.h:56
@ REDUCT_OPCODE_GT
(A, B, C) If R(B) > R/K(C) store true in R(A), else false.
Definition inst.h:66
@ REDUCT_OPCODE_JMP
(sBx) Unconditional jump by relative offset sBx.
Definition inst.h:52
@ REDUCT_OPCODE_SNEQ
(A, B, C) If R(B) !== R/K(C) store true in R(A), else false.
Definition inst.h:63
@ REDUCT_OPCODE_GE
(A, B, C) If R(B) >= R/K(C) store true in R(A), else false.
Definition inst.h:67
@ REDUCT_OPCODE_BOR
(A, B, C) R(A) = R(B) | R/K(C)
Definition inst.h:74
@ REDUCT_OPCODE_CLOSURE
(A, C) Wrap the function prototype in K(C) in a closure and store in R(A).
Definition inst.h:79
@ REDUCT_OPCODE_LE
(A, B, C) If R(B) <= R/K(C) store true in R(A), else false.
Definition inst.h:65
@ REDUCT_OPCODE_LIST
(A) Create a new list and store it in R(A).
Definition inst.h:51
@ REDUCT_OPCODE_TAILCALL
(A, B, C) Tail call callable in R/K(C) with B args starting from R(A).
Definition inst.h:81
@ REDUCT_OPCODE_BXOR
(A, B, C) R(A) = R(B) ^ R/K(C)
Definition inst.h:75
@ REDUCT_OPCODE_CAPTURE
(A, B, C) Capture R/K(C) into constant slot B in closure R(A).
Definition inst.h:80
@ REDUCT_OPCODE_MOD
(A, B, C) R(A) = R(B) % R/K(C)
Definition inst.h:72
@ REDUCT_OPCODE_LT
(A, B, C) If R(B) < R/K(C) store true in R(A), else false.
Definition inst.h:64
#define REDUCT_ITEM_TYPE_LIST
A list.
Definition item.h:28
#define REDUCT_ITEM_TYPE_ATOM
An atom.
Definition item.h:27
#define REDUCT_ITEM_TYPE_FUNCTION
A function.
Definition item.h:29
reduct_uint32_t length
The length of the string (must be first, check the reduct_item_t structure).
Definition atom.h:49
char * string
Pointer to the string.
Definition atom.h:53
Constant slot.
Definition function.h:43
reduct_const_slot_type_t type
The type of the constant slot.
Definition function.h:44
struct reduct_item * item
The item contained in the constant slot.
Definition function.h:47
struct reduct_atom * capture
The name of the variable to be captured.
Definition function.h:48
Compiled function structure.
Definition function.h:78
reduct_inst_t * insts
An array of instructions.
Definition function.h:81
reduct_const_slot_t * constants
The array of constant slots forming the constant template.
Definition function.h:83
reduct_uint32_t instCount
Number of instructions.
Definition function.h:79
reduct_uint16_t constantCount
Number of constants.
Definition function.h:84
reduct_uint8_t arity
The number of arguments the function expects.
Definition function.h:87
Item structure.
Definition item.h:57
reduct_list_t list
A list.
Definition item.h:67
reduct_function_t function
A function.
Definition item.h:69
reduct_atom_t atom
An atom.
Definition item.h:66
reduct_item_type_t type
The type of the item.
Definition item.h:61
reduct_uint32_t length
Total number of elements.
Definition list.h:49
State structure.
Definition core.h:61