2 * Copyright (C) 2001-2008, The Perl Foundation.
7 examples/c/nanoparrot.c
11 demonstrates how the interpreter interprets bytecode
12 its vastly simplified but the very basics are the same
15 -DTRACE ... turn on opcode tracing (FUNC_CORE, SWITCH_CORE only)
16 -DFUNC_CORE run function base opcodes
18 -DSWITCH_CORE run switched opcode core
22 The CGOTO run core works only for compilers like gcc that allow
27 cc -o nanoparrot -Wall nanoparrot.c -O3 && time ./nanoparrot mops
43 typedef double FLOATVAL
;
47 #define NUM_REGISTERS 32
56 #define REG_INT(interp, x) (interp)->bp[(x)].int_reg
58 #if defined(PREDEREF_CORE)
59 # define IREG(x) (_reg_base + pc[(x)])
60 # define ICONST(x) *(INTVAL*)pc[(x)]
61 # define SCONST(x) *(STRING**)pc[(x)]
63 # define IREG(x) REG_INT(interp, pc[(x)])
64 # define ICONST(x) pc[(x)]
65 # define SCONST(x) interp->code->const_table[pc[(x)]]
73 typedef struct Interp
{
76 opcode_t
*(**op_func
)(opcode_t
*, struct Interp
*);
85 #define OPCODES OP(end), OP(print_sc), OP(print_i), \
86 OP(set_i_ic), OP(if_i_ic), OP(sub_i_i_i), \
90 * some macros to get 3 different kinds of run loops
91 * you might skip this ugliness and continue
92 * at dispatch loop ~90 lines below
94 * or for the curious: look at the preprocessor output
97 #define OP(x) OP_ ## (x)
98 typedef enum { OPCODES
} opcodes
;
108 #if defined(FUNC_CORE)
112 run(Interp *interp, opcode_t *pc) \
115 printf("PC %2d %s\n", pc - interp->code->byte_code, \
116 interp->op_info[*pc]); \
117 pc = interp->op_func[*pc](pc, interp); \
123 run(Interp *interp, opcode_t *pc) \
126 pc = interp->op_func[*pc](pc, interp); \
133 # define CASE(function) \
135 function(opcode_t *pc, Interp *interp) \
138 # define NEXT return pc; }
139 # define DONE return 0; }
141 #else /* !FUNC_CORE */
145 # if defined(SWITCH_CORE)
150 run(Interp *interp, opcode_t *pc)>
152 RT#48260: Not yet documented!!!
159 run(Interp
*interp
, opcode_t
*pc
)
164 printf("PC %2d %s\n", pc - interp->code->byte_code, \
165 interp->op_info[*pc]); \
173 # define CASE(x) case OP_ ## (x):
174 # define NEXT continue;
175 # define DONE return;
176 # define ENDDISPATCH default : printf("illegal instruction"); \
177 exit(EXIT_FAILURE); \
182 run(Interp
*interp
, opcode_t
*pc
)
184 # define OP(x) &&lOP_##x
185 static void *labels
[] = { OPCODES
};
187 # define CASE(x) lOP_##x:
188 # define NEXT goto *labels[*pc];
189 # define DISPATCH NEXT
191 # define DONE return;
193 # endif /* SWITCH or CGOTO */
194 #endif /* !FUNC_CORE */
197 * dispatch loop / opcode (function) bodies i.e. the .ops files
204 printf("%s", SCONST(1));
208 printf("%d", IREG(1));
222 IREG(1) = IREG(2) - IREG(3);
226 printf("illegal opcode\n");
233 # define DEF_OP(op) \
234 interp->op_func[OP_ ## op] = op; \
235 interp->op_info[OP_ ## op] = #op
237 # define DEF_OP(op) \
238 interp->op_info[OP_ ## op] = #op
244 init(Interp *interp, opcode_t *prog)>
246 RT#48260: Not yet documented!!!
253 init(Interp
*interp
, opcode_t
*prog
)
256 * create 1 register frame
258 interp
->bp
= calloc(NUM_REGISTERS
, sizeof (struct Reg
));
260 * and some space for opcodes
262 interp
->op_func
= malloc(OP_MAX
* sizeof (void*));
263 interp
->op_info
= malloc(OP_MAX
* sizeof (char*));
265 * define opcode function and opcode info
278 interp
->code
= malloc(sizeof (struct pf
));
279 interp
->code
->byte_code
= prog
;
282 * create a simplified constant table
285 interp
->code
->const_table
= malloc(N_CONSTS
* sizeof (char*));
286 interp
->code
->const_table
[0] = "\n";
287 interp
->code
->const_table
[1] = "done\n";
288 interp
->code
->const_table
[2] = "error\n";
289 interp
->code
->const_table
[3] = "usage: ./nanoparrot mops\n";
295 main(int argc, char *argv[])>
297 RT#48260: Not yet documented!!!
304 main(int argc
, char *argv
[])
312 { OP_set_i_ic
, 4, 100000000, /* set I4, n */
313 OP_print_i
, 4, /* print I4 */
314 OP_print_sc
, 0, /* print "\n" */
315 OP_set_i_ic
, 5, 1, /* set I5, 1 */
316 OP_sub_i_i_i
, 4, 4, 5, /* L1: sub I4, I4, I5 */
317 OP_if_i_ic
, 4, -4, /* if I4, L1 */
318 OP_print_sc
, 1, /* print "done\n" */
323 OP_set_i_ic
, 0, 2, /* set I0, 2 */
324 OP_if_i_ic
, 0, 6, /* if I0, L1 */
325 OP_print_sc
, 2, /* print "error\n" */
327 OP_print_sc
, 3, /* L1: print "usage...\n" */
330 Interp
*interp
= malloc(sizeof (Interp
));
334 if (strcmp(argv
[1], "mops") == 0)
344 * c-file-style: "parrot"
346 * vim: expandtab shiftwidth=4: