annotate gcc/jit/docs/examples/tut04-toyvm/toyvm.cc @ 131:84e7813d76e9

gcc-8.2
author mir3636
date Thu, 25 Oct 2018 07:37:49 +0900
parents 04ced10e8804
children 1830386684a0
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /* A simple stack-based virtual machine to demonstrate
kono
parents:
diff changeset
2 JIT-compilation.
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3 Copyright (C) 2014-2018 Free Software Foundation, Inc.
111
kono
parents:
diff changeset
4
kono
parents:
diff changeset
5 This file is part of GCC.
kono
parents:
diff changeset
6
kono
parents:
diff changeset
7 GCC is free software; you can redistribute it and/or modify it
kono
parents:
diff changeset
8 under the terms of the GNU General Public License as published by
kono
parents:
diff changeset
9 the Free Software Foundation; either version 3, or (at your option)
kono
parents:
diff changeset
10 any later version.
kono
parents:
diff changeset
11
kono
parents:
diff changeset
12 GCC is distributed in the hope that it will be useful, but
kono
parents:
diff changeset
13 WITHOUT ANY WARRANTY; without even the implied warranty of
kono
parents:
diff changeset
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
kono
parents:
diff changeset
15 General Public License for more details.
kono
parents:
diff changeset
16
kono
parents:
diff changeset
17 You should have received a copy of the GNU General Public License
kono
parents:
diff changeset
18 along with GCC; see the file COPYING3. If not see
kono
parents:
diff changeset
19 <http://www.gnu.org/licenses/>. */
kono
parents:
diff changeset
20
kono
parents:
diff changeset
21 #include <assert.h>
kono
parents:
diff changeset
22 #include <errno.h>
kono
parents:
diff changeset
23 #include <stdio.h>
kono
parents:
diff changeset
24 #include <stdlib.h>
kono
parents:
diff changeset
25 #include <string.h>
kono
parents:
diff changeset
26
kono
parents:
diff changeset
27 #include <dejagnu.h>
kono
parents:
diff changeset
28
kono
parents:
diff changeset
29 #include <libgccjit++.h>
kono
parents:
diff changeset
30
kono
parents:
diff changeset
31 /* Wrapper around a gcc_jit_result *. */
kono
parents:
diff changeset
32
kono
parents:
diff changeset
33 class compilation_result
kono
parents:
diff changeset
34 {
kono
parents:
diff changeset
35 public:
kono
parents:
diff changeset
36 compilation_result (gcc_jit_result *result) :
kono
parents:
diff changeset
37 m_result (result)
kono
parents:
diff changeset
38 {
kono
parents:
diff changeset
39 }
kono
parents:
diff changeset
40 ~compilation_result ()
kono
parents:
diff changeset
41 {
kono
parents:
diff changeset
42 gcc_jit_result_release (m_result);
kono
parents:
diff changeset
43 }
kono
parents:
diff changeset
44
kono
parents:
diff changeset
45 void *get_code (const char *funcname)
kono
parents:
diff changeset
46 {
kono
parents:
diff changeset
47 return gcc_jit_result_get_code (m_result, funcname);
kono
parents:
diff changeset
48 }
kono
parents:
diff changeset
49
kono
parents:
diff changeset
50 private:
kono
parents:
diff changeset
51 gcc_jit_result *m_result;
kono
parents:
diff changeset
52 };
kono
parents:
diff changeset
53
kono
parents:
diff changeset
54 /* Functions are compiled to this function ptr type. */
kono
parents:
diff changeset
55 typedef int (*toyvm_compiled_func) (int);
kono
parents:
diff changeset
56
kono
parents:
diff changeset
57 enum opcode {
kono
parents:
diff changeset
58 /* Ops taking no operand. */
kono
parents:
diff changeset
59 DUP,
kono
parents:
diff changeset
60 ROT,
kono
parents:
diff changeset
61 BINARY_ADD,
kono
parents:
diff changeset
62 BINARY_SUBTRACT,
kono
parents:
diff changeset
63 BINARY_MULT,
kono
parents:
diff changeset
64 BINARY_COMPARE_LT,
kono
parents:
diff changeset
65 RECURSE,
kono
parents:
diff changeset
66 RETURN,
kono
parents:
diff changeset
67
kono
parents:
diff changeset
68 /* Ops taking an operand. */
kono
parents:
diff changeset
69 PUSH_CONST,
kono
parents:
diff changeset
70 JUMP_ABS_IF_TRUE
kono
parents:
diff changeset
71 };
kono
parents:
diff changeset
72
kono
parents:
diff changeset
73 #define FIRST_UNARY_OPCODE (PUSH_CONST)
kono
parents:
diff changeset
74
kono
parents:
diff changeset
75 const char * const opcode_names[] = {
kono
parents:
diff changeset
76 "DUP",
kono
parents:
diff changeset
77 "ROT",
kono
parents:
diff changeset
78 "BINARY_ADD",
kono
parents:
diff changeset
79 "BINARY_SUBTRACT",
kono
parents:
diff changeset
80 "BINARY_MULT",
kono
parents:
diff changeset
81 "BINARY_COMPARE_LT",
kono
parents:
diff changeset
82 "RECURSE",
kono
parents:
diff changeset
83 "RETURN",
kono
parents:
diff changeset
84
kono
parents:
diff changeset
85 "PUSH_CONST",
kono
parents:
diff changeset
86 "JUMP_ABS_IF_TRUE",
kono
parents:
diff changeset
87 };
kono
parents:
diff changeset
88
kono
parents:
diff changeset
89 struct toyvm_op
kono
parents:
diff changeset
90 {
kono
parents:
diff changeset
91 /* Which operation. */
kono
parents:
diff changeset
92 enum opcode op_opcode;
kono
parents:
diff changeset
93
kono
parents:
diff changeset
94 /* Some opcodes take an argument. */
kono
parents:
diff changeset
95 int op_operand;
kono
parents:
diff changeset
96
kono
parents:
diff changeset
97 /* The line number of the operation within the source file. */
kono
parents:
diff changeset
98 int op_linenum;
kono
parents:
diff changeset
99 };
kono
parents:
diff changeset
100
kono
parents:
diff changeset
101 #define MAX_OPS (64)
kono
parents:
diff changeset
102
kono
parents:
diff changeset
103 class toyvm_function
kono
parents:
diff changeset
104 {
kono
parents:
diff changeset
105 public:
kono
parents:
diff changeset
106 void
kono
parents:
diff changeset
107 add_op (enum opcode opcode,
kono
parents:
diff changeset
108 int operand, int linenum);
kono
parents:
diff changeset
109
kono
parents:
diff changeset
110 void
kono
parents:
diff changeset
111 add_unary_op (enum opcode opcode,
kono
parents:
diff changeset
112 const char *rest_of_line, int linenum);
kono
parents:
diff changeset
113
kono
parents:
diff changeset
114 static toyvm_function *
kono
parents:
diff changeset
115 parse (const char *filename, const char *name);
kono
parents:
diff changeset
116
kono
parents:
diff changeset
117 void
kono
parents:
diff changeset
118 disassemble_op (toyvm_op *op, int index, FILE *out);
kono
parents:
diff changeset
119
kono
parents:
diff changeset
120 void
kono
parents:
diff changeset
121 disassemble (FILE *out);
kono
parents:
diff changeset
122
kono
parents:
diff changeset
123 int
kono
parents:
diff changeset
124 interpret (int arg, FILE *trace);
kono
parents:
diff changeset
125
kono
parents:
diff changeset
126 compilation_result
kono
parents:
diff changeset
127 compile ();
kono
parents:
diff changeset
128
kono
parents:
diff changeset
129 const char *
kono
parents:
diff changeset
130 get_function_name () const { return m_funcname; }
kono
parents:
diff changeset
131
kono
parents:
diff changeset
132 private:
kono
parents:
diff changeset
133 void
kono
parents:
diff changeset
134 make_function_name (const char *filename);
kono
parents:
diff changeset
135
kono
parents:
diff changeset
136 private:
kono
parents:
diff changeset
137 const char *fn_filename;
kono
parents:
diff changeset
138 char *m_funcname;
kono
parents:
diff changeset
139 int fn_num_ops;
kono
parents:
diff changeset
140 toyvm_op fn_ops[MAX_OPS];
kono
parents:
diff changeset
141 friend struct compilation_state;
kono
parents:
diff changeset
142 };
kono
parents:
diff changeset
143
kono
parents:
diff changeset
144 #define MAX_STACK_DEPTH (8)
kono
parents:
diff changeset
145
kono
parents:
diff changeset
146 class toyvm_frame
kono
parents:
diff changeset
147 {
kono
parents:
diff changeset
148 public:
kono
parents:
diff changeset
149 void push (int arg);
kono
parents:
diff changeset
150 int pop ();
kono
parents:
diff changeset
151 void dump_stack (FILE *out);
kono
parents:
diff changeset
152
kono
parents:
diff changeset
153 private:
kono
parents:
diff changeset
154 toyvm_function *frm_function;
kono
parents:
diff changeset
155 int frm_pc;
kono
parents:
diff changeset
156 int frm_stack[MAX_STACK_DEPTH];
kono
parents:
diff changeset
157 int frm_cur_depth;
kono
parents:
diff changeset
158
kono
parents:
diff changeset
159 friend int toyvm_function::interpret (int arg, FILE *trace);
kono
parents:
diff changeset
160
kono
parents:
diff changeset
161 };
kono
parents:
diff changeset
162
kono
parents:
diff changeset
163 void
kono
parents:
diff changeset
164 toyvm_function::add_op (enum opcode opcode,
kono
parents:
diff changeset
165 int operand, int linenum)
kono
parents:
diff changeset
166 {
kono
parents:
diff changeset
167 toyvm_op *op;
kono
parents:
diff changeset
168 assert (fn_num_ops < MAX_OPS);
kono
parents:
diff changeset
169 op = &fn_ops[fn_num_ops++];
kono
parents:
diff changeset
170 op->op_opcode = opcode;
kono
parents:
diff changeset
171 op->op_operand = operand;
kono
parents:
diff changeset
172 op->op_linenum = linenum;
kono
parents:
diff changeset
173 }
kono
parents:
diff changeset
174
kono
parents:
diff changeset
175 void
kono
parents:
diff changeset
176 toyvm_function::add_unary_op (enum opcode opcode,
kono
parents:
diff changeset
177 const char *rest_of_line, int linenum)
kono
parents:
diff changeset
178 {
kono
parents:
diff changeset
179 int operand = atoi (rest_of_line);
kono
parents:
diff changeset
180 add_op (opcode, operand, linenum);
kono
parents:
diff changeset
181 }
kono
parents:
diff changeset
182
kono
parents:
diff changeset
183 void
kono
parents:
diff changeset
184 toyvm_function::make_function_name (const char *filename)
kono
parents:
diff changeset
185 {
kono
parents:
diff changeset
186 /* Skip any path separators. */
kono
parents:
diff changeset
187 const char *pathsep = strrchr (filename, '/');
kono
parents:
diff changeset
188 if (pathsep)
kono
parents:
diff changeset
189 filename = pathsep + 1;
kono
parents:
diff changeset
190
kono
parents:
diff changeset
191 /* Copy filename to funcname. */
kono
parents:
diff changeset
192 m_funcname = (char *)malloc (strlen (filename) + 1);
kono
parents:
diff changeset
193
kono
parents:
diff changeset
194 strcpy (m_funcname, filename);
kono
parents:
diff changeset
195
kono
parents:
diff changeset
196 /* Convert "." to NIL terminator. */
kono
parents:
diff changeset
197 *(strchr (m_funcname, '.')) = '\0';
kono
parents:
diff changeset
198 }
kono
parents:
diff changeset
199
kono
parents:
diff changeset
200 toyvm_function *
kono
parents:
diff changeset
201 toyvm_function::parse (const char *filename, const char *name)
kono
parents:
diff changeset
202 {
kono
parents:
diff changeset
203 FILE *f = NULL;
kono
parents:
diff changeset
204 toyvm_function *fn = NULL;
kono
parents:
diff changeset
205 char *line = NULL;
kono
parents:
diff changeset
206 ssize_t linelen;
kono
parents:
diff changeset
207 size_t bufsize;
kono
parents:
diff changeset
208 int linenum = 0;
kono
parents:
diff changeset
209
kono
parents:
diff changeset
210 assert (filename);
kono
parents:
diff changeset
211 assert (name);
kono
parents:
diff changeset
212
kono
parents:
diff changeset
213 f = fopen (filename, "r");
kono
parents:
diff changeset
214 if (!f)
kono
parents:
diff changeset
215 {
kono
parents:
diff changeset
216 fprintf (stderr,
kono
parents:
diff changeset
217 "cannot open file %s: %s\n",
kono
parents:
diff changeset
218 filename, strerror (errno));
kono
parents:
diff changeset
219 goto error;
kono
parents:
diff changeset
220 }
kono
parents:
diff changeset
221
kono
parents:
diff changeset
222 fn = (toyvm_function *)calloc (1, sizeof (toyvm_function));
kono
parents:
diff changeset
223 if (!fn)
kono
parents:
diff changeset
224 {
kono
parents:
diff changeset
225 fprintf (stderr, "out of memory allocating toyvm_function\n");
kono
parents:
diff changeset
226 goto error;
kono
parents:
diff changeset
227 }
kono
parents:
diff changeset
228 fn->fn_filename = filename;
kono
parents:
diff changeset
229 fn->make_function_name (filename);
kono
parents:
diff changeset
230
kono
parents:
diff changeset
231 /* Read the lines of the file. */
kono
parents:
diff changeset
232 while ((linelen = getline (&line, &bufsize, f)) != -1)
kono
parents:
diff changeset
233 {
kono
parents:
diff changeset
234 /* Note that this is a terrible parser, but it avoids the need to
kono
parents:
diff changeset
235 bring in lex/yacc as a dependency. */
kono
parents:
diff changeset
236 linenum++;
kono
parents:
diff changeset
237
kono
parents:
diff changeset
238 if (0)
kono
parents:
diff changeset
239 fprintf (stdout, "%3d: %s", linenum, line);
kono
parents:
diff changeset
240
kono
parents:
diff changeset
241 /* Lines beginning with # are comments. */
kono
parents:
diff changeset
242 if (line[0] == '#')
kono
parents:
diff changeset
243 continue;
kono
parents:
diff changeset
244
kono
parents:
diff changeset
245 /* Skip blank lines. */
kono
parents:
diff changeset
246 if (line[0] == '\n')
kono
parents:
diff changeset
247 continue;
kono
parents:
diff changeset
248
kono
parents:
diff changeset
249 #define LINE_MATCHES(OPCODE) (0 == strncmp ((OPCODE), line, strlen (OPCODE)))
kono
parents:
diff changeset
250 if (LINE_MATCHES ("DUP\n"))
kono
parents:
diff changeset
251 fn->add_op (DUP, 0, linenum);
kono
parents:
diff changeset
252 else if (LINE_MATCHES ("ROT\n"))
kono
parents:
diff changeset
253 fn->add_op (ROT, 0, linenum);
kono
parents:
diff changeset
254 else if (LINE_MATCHES ("BINARY_ADD\n"))
kono
parents:
diff changeset
255 fn->add_op (BINARY_ADD, 0, linenum);
kono
parents:
diff changeset
256 else if (LINE_MATCHES ("BINARY_SUBTRACT\n"))
kono
parents:
diff changeset
257 fn->add_op (BINARY_SUBTRACT, 0, linenum);
kono
parents:
diff changeset
258 else if (LINE_MATCHES ("BINARY_MULT\n"))
kono
parents:
diff changeset
259 fn->add_op (BINARY_MULT, 0, linenum);
kono
parents:
diff changeset
260 else if (LINE_MATCHES ("BINARY_COMPARE_LT\n"))
kono
parents:
diff changeset
261 fn->add_op (BINARY_COMPARE_LT, 0, linenum);
kono
parents:
diff changeset
262 else if (LINE_MATCHES ("RECURSE\n"))
kono
parents:
diff changeset
263 fn->add_op (RECURSE, 0, linenum);
kono
parents:
diff changeset
264 else if (LINE_MATCHES ("RETURN\n"))
kono
parents:
diff changeset
265 fn->add_op (RETURN, 0, linenum);
kono
parents:
diff changeset
266 else if (LINE_MATCHES ("PUSH_CONST "))
kono
parents:
diff changeset
267 fn->add_unary_op (PUSH_CONST,
kono
parents:
diff changeset
268 line + strlen ("PUSH_CONST "), linenum);
kono
parents:
diff changeset
269 else if (LINE_MATCHES ("JUMP_ABS_IF_TRUE "))
kono
parents:
diff changeset
270 fn->add_unary_op (JUMP_ABS_IF_TRUE,
kono
parents:
diff changeset
271 line + strlen("JUMP_ABS_IF_TRUE "), linenum);
kono
parents:
diff changeset
272 else
kono
parents:
diff changeset
273 {
kono
parents:
diff changeset
274 fprintf (stderr, "%s:%d: parse error\n", filename, linenum);
kono
parents:
diff changeset
275 free (fn);
kono
parents:
diff changeset
276 fn = NULL;
kono
parents:
diff changeset
277 goto error;
kono
parents:
diff changeset
278 }
kono
parents:
diff changeset
279 #undef LINE_MATCHES
kono
parents:
diff changeset
280 }
kono
parents:
diff changeset
281 free (line);
kono
parents:
diff changeset
282 fclose (f);
kono
parents:
diff changeset
283
kono
parents:
diff changeset
284 return fn;
kono
parents:
diff changeset
285
kono
parents:
diff changeset
286 error:
kono
parents:
diff changeset
287 free (line);
kono
parents:
diff changeset
288 if (f)
kono
parents:
diff changeset
289 fclose (f);
kono
parents:
diff changeset
290 free (fn);
kono
parents:
diff changeset
291 return NULL;
kono
parents:
diff changeset
292 }
kono
parents:
diff changeset
293
kono
parents:
diff changeset
294 void
kono
parents:
diff changeset
295 toyvm_function::disassemble_op (toyvm_op *op, int index, FILE *out)
kono
parents:
diff changeset
296 {
kono
parents:
diff changeset
297 fprintf (out, "%s:%d: index %d: %s",
kono
parents:
diff changeset
298 fn_filename, op->op_linenum, index,
kono
parents:
diff changeset
299 opcode_names[op->op_opcode]);
kono
parents:
diff changeset
300 if (op->op_opcode >= FIRST_UNARY_OPCODE)
kono
parents:
diff changeset
301 fprintf (out, " %d", op->op_operand);
kono
parents:
diff changeset
302 fprintf (out, "\n");
kono
parents:
diff changeset
303 }
kono
parents:
diff changeset
304
kono
parents:
diff changeset
305 void
kono
parents:
diff changeset
306 toyvm_function::disassemble (FILE *out)
kono
parents:
diff changeset
307 {
kono
parents:
diff changeset
308 int i;
kono
parents:
diff changeset
309 for (i = 0; i < fn_num_ops; i++)
kono
parents:
diff changeset
310 {
kono
parents:
diff changeset
311 toyvm_op *op = &fn_ops[i];
kono
parents:
diff changeset
312 disassemble_op (op, i, out);
kono
parents:
diff changeset
313 }
kono
parents:
diff changeset
314 }
kono
parents:
diff changeset
315
kono
parents:
diff changeset
316 void
kono
parents:
diff changeset
317 toyvm_frame::push (int arg)
kono
parents:
diff changeset
318 {
kono
parents:
diff changeset
319 assert (frm_cur_depth < MAX_STACK_DEPTH);
kono
parents:
diff changeset
320 frm_stack[frm_cur_depth++] = arg;
kono
parents:
diff changeset
321 }
kono
parents:
diff changeset
322
kono
parents:
diff changeset
323 int
kono
parents:
diff changeset
324 toyvm_frame::pop ()
kono
parents:
diff changeset
325 {
kono
parents:
diff changeset
326 assert (frm_cur_depth > 0);
kono
parents:
diff changeset
327 return frm_stack[--frm_cur_depth];
kono
parents:
diff changeset
328 }
kono
parents:
diff changeset
329
kono
parents:
diff changeset
330 void
kono
parents:
diff changeset
331 toyvm_frame::dump_stack (FILE *out)
kono
parents:
diff changeset
332 {
kono
parents:
diff changeset
333 int i;
kono
parents:
diff changeset
334 fprintf (out, "stack:");
kono
parents:
diff changeset
335 for (i = 0; i < frm_cur_depth; i++)
kono
parents:
diff changeset
336 {
kono
parents:
diff changeset
337 fprintf (out, " %d", frm_stack[i]);
kono
parents:
diff changeset
338 }
kono
parents:
diff changeset
339 fprintf (out, "\n");
kono
parents:
diff changeset
340 }
kono
parents:
diff changeset
341
kono
parents:
diff changeset
342 /* Execute the given function. */
kono
parents:
diff changeset
343
kono
parents:
diff changeset
344 int
kono
parents:
diff changeset
345 toyvm_function::interpret (int arg, FILE *trace)
kono
parents:
diff changeset
346 {
kono
parents:
diff changeset
347 toyvm_frame frame;
kono
parents:
diff changeset
348 #define PUSH(ARG) (frame.push (ARG))
kono
parents:
diff changeset
349 #define POP(ARG) (frame.pop ())
kono
parents:
diff changeset
350
kono
parents:
diff changeset
351 frame.frm_function = this;
kono
parents:
diff changeset
352 frame.frm_pc = 0;
kono
parents:
diff changeset
353 frame.frm_cur_depth = 0;
kono
parents:
diff changeset
354
kono
parents:
diff changeset
355 PUSH (arg);
kono
parents:
diff changeset
356
kono
parents:
diff changeset
357 while (1)
kono
parents:
diff changeset
358 {
kono
parents:
diff changeset
359 toyvm_op *op;
kono
parents:
diff changeset
360 int x, y;
kono
parents:
diff changeset
361 assert (frame.frm_pc < fn_num_ops);
kono
parents:
diff changeset
362 op = &fn_ops[frame.frm_pc++];
kono
parents:
diff changeset
363
kono
parents:
diff changeset
364 if (trace)
kono
parents:
diff changeset
365 {
kono
parents:
diff changeset
366 frame.dump_stack (trace);
kono
parents:
diff changeset
367 disassemble_op (op, frame.frm_pc, trace);
kono
parents:
diff changeset
368 }
kono
parents:
diff changeset
369
kono
parents:
diff changeset
370 switch (op->op_opcode)
kono
parents:
diff changeset
371 {
kono
parents:
diff changeset
372 /* Ops taking no operand. */
kono
parents:
diff changeset
373 case DUP:
kono
parents:
diff changeset
374 x = POP ();
kono
parents:
diff changeset
375 PUSH (x);
kono
parents:
diff changeset
376 PUSH (x);
kono
parents:
diff changeset
377 break;
kono
parents:
diff changeset
378
kono
parents:
diff changeset
379 case ROT:
kono
parents:
diff changeset
380 y = POP ();
kono
parents:
diff changeset
381 x = POP ();
kono
parents:
diff changeset
382 PUSH (y);
kono
parents:
diff changeset
383 PUSH (x);
kono
parents:
diff changeset
384 break;
kono
parents:
diff changeset
385
kono
parents:
diff changeset
386 case BINARY_ADD:
kono
parents:
diff changeset
387 y = POP ();
kono
parents:
diff changeset
388 x = POP ();
kono
parents:
diff changeset
389 PUSH (x + y);
kono
parents:
diff changeset
390 break;
kono
parents:
diff changeset
391
kono
parents:
diff changeset
392 case BINARY_SUBTRACT:
kono
parents:
diff changeset
393 y = POP ();
kono
parents:
diff changeset
394 x = POP ();
kono
parents:
diff changeset
395 PUSH (x - y);
kono
parents:
diff changeset
396 break;
kono
parents:
diff changeset
397
kono
parents:
diff changeset
398 case BINARY_MULT:
kono
parents:
diff changeset
399 y = POP ();
kono
parents:
diff changeset
400 x = POP ();
kono
parents:
diff changeset
401 PUSH (x * y);
kono
parents:
diff changeset
402 break;
kono
parents:
diff changeset
403
kono
parents:
diff changeset
404 case BINARY_COMPARE_LT:
kono
parents:
diff changeset
405 y = POP ();
kono
parents:
diff changeset
406 x = POP ();
kono
parents:
diff changeset
407 PUSH (x < y);
kono
parents:
diff changeset
408 break;
kono
parents:
diff changeset
409
kono
parents:
diff changeset
410 case RECURSE:
kono
parents:
diff changeset
411 x = POP ();
kono
parents:
diff changeset
412 x = interpret (x, trace);
kono
parents:
diff changeset
413 PUSH (x);
kono
parents:
diff changeset
414 break;
kono
parents:
diff changeset
415
kono
parents:
diff changeset
416 case RETURN:
kono
parents:
diff changeset
417 return POP ();
kono
parents:
diff changeset
418
kono
parents:
diff changeset
419 /* Ops taking an operand. */
kono
parents:
diff changeset
420 case PUSH_CONST:
kono
parents:
diff changeset
421 PUSH (op->op_operand);
kono
parents:
diff changeset
422 break;
kono
parents:
diff changeset
423
kono
parents:
diff changeset
424 case JUMP_ABS_IF_TRUE:
kono
parents:
diff changeset
425 x = POP ();
kono
parents:
diff changeset
426 if (x)
kono
parents:
diff changeset
427 frame.frm_pc = op->op_operand;
kono
parents:
diff changeset
428 break;
kono
parents:
diff changeset
429
kono
parents:
diff changeset
430 default:
kono
parents:
diff changeset
431 assert (0); /* unknown opcode */
kono
parents:
diff changeset
432
kono
parents:
diff changeset
433 } /* end of switch on opcode */
kono
parents:
diff changeset
434 } /* end of while loop */
kono
parents:
diff changeset
435
kono
parents:
diff changeset
436 #undef PUSH
kono
parents:
diff changeset
437 #undef POP
kono
parents:
diff changeset
438 }
kono
parents:
diff changeset
439
kono
parents:
diff changeset
440 /* JIT compilation. */
kono
parents:
diff changeset
441
kono
parents:
diff changeset
442 class compilation_state
kono
parents:
diff changeset
443 {
kono
parents:
diff changeset
444 public:
kono
parents:
diff changeset
445 compilation_state (toyvm_function &toyvmfn) :
kono
parents:
diff changeset
446 toyvmfn (toyvmfn)
kono
parents:
diff changeset
447 {}
kono
parents:
diff changeset
448
kono
parents:
diff changeset
449 void create_context ();
kono
parents:
diff changeset
450 void create_types ();
kono
parents:
diff changeset
451 void create_locations ();
kono
parents:
diff changeset
452 void create_function (const char *funcname);
kono
parents:
diff changeset
453 compilation_result compile ();
kono
parents:
diff changeset
454
kono
parents:
diff changeset
455 private:
kono
parents:
diff changeset
456 void
kono
parents:
diff changeset
457 add_push (gccjit::block block,
kono
parents:
diff changeset
458 gccjit::rvalue rvalue,
kono
parents:
diff changeset
459 gccjit::location loc);
kono
parents:
diff changeset
460
kono
parents:
diff changeset
461 void
kono
parents:
diff changeset
462 add_pop (gccjit::block block,
kono
parents:
diff changeset
463 gccjit::lvalue lvalue,
kono
parents:
diff changeset
464 gccjit::location loc);
kono
parents:
diff changeset
465
kono
parents:
diff changeset
466 private:
kono
parents:
diff changeset
467
kono
parents:
diff changeset
468 /* State. */
kono
parents:
diff changeset
469
kono
parents:
diff changeset
470 toyvm_function &toyvmfn;
kono
parents:
diff changeset
471
kono
parents:
diff changeset
472 gccjit::context ctxt;
kono
parents:
diff changeset
473
kono
parents:
diff changeset
474 gccjit::type int_type;
kono
parents:
diff changeset
475 gccjit::type bool_type;
kono
parents:
diff changeset
476 gccjit::type stack_type; /* int[MAX_STACK_DEPTH] */
kono
parents:
diff changeset
477
kono
parents:
diff changeset
478 gccjit::rvalue const_one;
kono
parents:
diff changeset
479
kono
parents:
diff changeset
480 gccjit::function fn;
kono
parents:
diff changeset
481 gccjit::param param_arg;
kono
parents:
diff changeset
482 gccjit::lvalue stack;
kono
parents:
diff changeset
483 gccjit::lvalue stack_depth;
kono
parents:
diff changeset
484 gccjit::lvalue x;
kono
parents:
diff changeset
485 gccjit::lvalue y;
kono
parents:
diff changeset
486
kono
parents:
diff changeset
487 gccjit::location op_locs[MAX_OPS];
kono
parents:
diff changeset
488 gccjit::block initial_block;
kono
parents:
diff changeset
489 gccjit::block op_blocks[MAX_OPS];
kono
parents:
diff changeset
490
kono
parents:
diff changeset
491 };
kono
parents:
diff changeset
492
kono
parents:
diff changeset
493 /* The main compilation hook. */
kono
parents:
diff changeset
494
kono
parents:
diff changeset
495 compilation_result
kono
parents:
diff changeset
496 toyvm_function::compile ()
kono
parents:
diff changeset
497 {
kono
parents:
diff changeset
498 compilation_state state (*this);
kono
parents:
diff changeset
499
kono
parents:
diff changeset
500 state.create_context ();
kono
parents:
diff changeset
501 state.create_types ();
kono
parents:
diff changeset
502 state.create_locations ();
kono
parents:
diff changeset
503 state.create_function (get_function_name ());
kono
parents:
diff changeset
504
kono
parents:
diff changeset
505 /* We've now finished populating the context. Compile it. */
kono
parents:
diff changeset
506 return state.compile ();
kono
parents:
diff changeset
507 }
kono
parents:
diff changeset
508
kono
parents:
diff changeset
509 /* Stack manipulation. */
kono
parents:
diff changeset
510
kono
parents:
diff changeset
511 void
kono
parents:
diff changeset
512 compilation_state::add_push (gccjit::block block,
kono
parents:
diff changeset
513 gccjit::rvalue rvalue,
kono
parents:
diff changeset
514 gccjit::location loc)
kono
parents:
diff changeset
515 {
kono
parents:
diff changeset
516 /* stack[stack_depth] = RVALUE */
kono
parents:
diff changeset
517 block.add_assignment (
kono
parents:
diff changeset
518 /* stack[stack_depth] */
kono
parents:
diff changeset
519 ctxt.new_array_access (
kono
parents:
diff changeset
520 stack,
kono
parents:
diff changeset
521 stack_depth,
kono
parents:
diff changeset
522 loc),
kono
parents:
diff changeset
523 rvalue,
kono
parents:
diff changeset
524 loc);
kono
parents:
diff changeset
525
kono
parents:
diff changeset
526 /* "stack_depth++;". */
kono
parents:
diff changeset
527 block.add_assignment_op (
kono
parents:
diff changeset
528 stack_depth,
kono
parents:
diff changeset
529 GCC_JIT_BINARY_OP_PLUS,
kono
parents:
diff changeset
530 const_one,
kono
parents:
diff changeset
531 loc);
kono
parents:
diff changeset
532 }
kono
parents:
diff changeset
533
kono
parents:
diff changeset
534 void
kono
parents:
diff changeset
535 compilation_state::add_pop (gccjit::block block,
kono
parents:
diff changeset
536 gccjit::lvalue lvalue,
kono
parents:
diff changeset
537 gccjit::location loc)
kono
parents:
diff changeset
538 {
kono
parents:
diff changeset
539 /* "--stack_depth;". */
kono
parents:
diff changeset
540 block.add_assignment_op (
kono
parents:
diff changeset
541 stack_depth,
kono
parents:
diff changeset
542 GCC_JIT_BINARY_OP_MINUS,
kono
parents:
diff changeset
543 const_one,
kono
parents:
diff changeset
544 loc);
kono
parents:
diff changeset
545
kono
parents:
diff changeset
546 /* "LVALUE = stack[stack_depth];". */
kono
parents:
diff changeset
547 block.add_assignment (
kono
parents:
diff changeset
548 lvalue,
kono
parents:
diff changeset
549 /* stack[stack_depth] */
kono
parents:
diff changeset
550 ctxt.new_array_access (stack,
kono
parents:
diff changeset
551 stack_depth,
kono
parents:
diff changeset
552 loc),
kono
parents:
diff changeset
553 loc);
kono
parents:
diff changeset
554 }
kono
parents:
diff changeset
555
kono
parents:
diff changeset
556 /* Create the context. */
kono
parents:
diff changeset
557
kono
parents:
diff changeset
558 void
kono
parents:
diff changeset
559 compilation_state::create_context ()
kono
parents:
diff changeset
560 {
kono
parents:
diff changeset
561 ctxt = gccjit::context::acquire ();
kono
parents:
diff changeset
562
kono
parents:
diff changeset
563 ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE,
kono
parents:
diff changeset
564 0);
kono
parents:
diff changeset
565 ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE,
kono
parents:
diff changeset
566 0);
kono
parents:
diff changeset
567 ctxt.set_int_option (GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL,
kono
parents:
diff changeset
568 3);
kono
parents:
diff changeset
569 ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES,
kono
parents:
diff changeset
570 0);
kono
parents:
diff changeset
571 ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING,
kono
parents:
diff changeset
572 0);
kono
parents:
diff changeset
573 ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_DEBUGINFO,
kono
parents:
diff changeset
574 1);
kono
parents:
diff changeset
575 }
kono
parents:
diff changeset
576
kono
parents:
diff changeset
577 /* Create types. */
kono
parents:
diff changeset
578
kono
parents:
diff changeset
579 void
kono
parents:
diff changeset
580 compilation_state::create_types ()
kono
parents:
diff changeset
581 {
kono
parents:
diff changeset
582 /* Create types. */
kono
parents:
diff changeset
583 int_type = ctxt.get_type (GCC_JIT_TYPE_INT);
kono
parents:
diff changeset
584 bool_type = ctxt.get_type (GCC_JIT_TYPE_BOOL);
kono
parents:
diff changeset
585 stack_type = ctxt.new_array_type (int_type, MAX_STACK_DEPTH);
kono
parents:
diff changeset
586
kono
parents:
diff changeset
587 /* The constant value 1. */
kono
parents:
diff changeset
588 const_one = ctxt.one (int_type);
kono
parents:
diff changeset
589
kono
parents:
diff changeset
590 }
kono
parents:
diff changeset
591
kono
parents:
diff changeset
592 /* Create locations. */
kono
parents:
diff changeset
593
kono
parents:
diff changeset
594 void
kono
parents:
diff changeset
595 compilation_state::create_locations ()
kono
parents:
diff changeset
596 {
kono
parents:
diff changeset
597 for (int pc = 0; pc < toyvmfn.fn_num_ops; pc++)
kono
parents:
diff changeset
598 {
kono
parents:
diff changeset
599 toyvm_op *op = &toyvmfn.fn_ops[pc];
kono
parents:
diff changeset
600
kono
parents:
diff changeset
601 op_locs[pc] = ctxt.new_location (toyvmfn.fn_filename,
kono
parents:
diff changeset
602 op->op_linenum,
kono
parents:
diff changeset
603 0); /* column */
kono
parents:
diff changeset
604 }
kono
parents:
diff changeset
605 }
kono
parents:
diff changeset
606
kono
parents:
diff changeset
607 /* Creating the function. */
kono
parents:
diff changeset
608
kono
parents:
diff changeset
609 void
kono
parents:
diff changeset
610 compilation_state::create_function (const char *funcname)
kono
parents:
diff changeset
611 {
kono
parents:
diff changeset
612 std::vector <gccjit::param> params;
kono
parents:
diff changeset
613 param_arg = ctxt.new_param (int_type, "arg", op_locs[0]);
kono
parents:
diff changeset
614 params.push_back (param_arg);
kono
parents:
diff changeset
615 fn = ctxt.new_function (GCC_JIT_FUNCTION_EXPORTED,
kono
parents:
diff changeset
616 int_type,
kono
parents:
diff changeset
617 funcname,
kono
parents:
diff changeset
618 params, 0,
kono
parents:
diff changeset
619 op_locs[0]);
kono
parents:
diff changeset
620
kono
parents:
diff changeset
621 /* Create stack lvalues. */
kono
parents:
diff changeset
622 stack = fn.new_local (stack_type, "stack");
kono
parents:
diff changeset
623 stack_depth = fn.new_local (int_type, "stack_depth");
kono
parents:
diff changeset
624 x = fn.new_local (int_type, "x");
kono
parents:
diff changeset
625 y = fn.new_local (int_type, "y");
kono
parents:
diff changeset
626
kono
parents:
diff changeset
627 /* 1st pass: create blocks, one per opcode. */
kono
parents:
diff changeset
628
kono
parents:
diff changeset
629 /* We need an entry block to do one-time initialization, so create that
kono
parents:
diff changeset
630 first. */
kono
parents:
diff changeset
631 initial_block = fn.new_block ("initial");
kono
parents:
diff changeset
632
kono
parents:
diff changeset
633 /* Create a block per operation. */
kono
parents:
diff changeset
634 for (int pc = 0; pc < toyvmfn.fn_num_ops; pc++)
kono
parents:
diff changeset
635 {
kono
parents:
diff changeset
636 char buf[16];
kono
parents:
diff changeset
637 sprintf (buf, "instr%i", pc);
kono
parents:
diff changeset
638 op_blocks[pc] = fn.new_block (buf);
kono
parents:
diff changeset
639 }
kono
parents:
diff changeset
640
kono
parents:
diff changeset
641 /* Populate the initial block. */
kono
parents:
diff changeset
642
kono
parents:
diff changeset
643 /* "stack_depth = 0;". */
kono
parents:
diff changeset
644 initial_block.add_assignment (stack_depth,
kono
parents:
diff changeset
645 ctxt.zero (int_type),
kono
parents:
diff changeset
646 op_locs[0]);
kono
parents:
diff changeset
647
kono
parents:
diff changeset
648 /* "PUSH (arg);". */
kono
parents:
diff changeset
649 add_push (initial_block,
kono
parents:
diff changeset
650 param_arg,
kono
parents:
diff changeset
651 op_locs[0]);
kono
parents:
diff changeset
652
kono
parents:
diff changeset
653 /* ...and jump to insn 0. */
kono
parents:
diff changeset
654 initial_block.end_with_jump (op_blocks[0],
kono
parents:
diff changeset
655 op_locs[0]);
kono
parents:
diff changeset
656
kono
parents:
diff changeset
657 /* 2nd pass: fill in instructions. */
kono
parents:
diff changeset
658 for (int pc = 0; pc < toyvmfn.fn_num_ops; pc++)
kono
parents:
diff changeset
659 {
kono
parents:
diff changeset
660 gccjit::location loc = op_locs[pc];
kono
parents:
diff changeset
661
kono
parents:
diff changeset
662 gccjit::block block = op_blocks[pc];
kono
parents:
diff changeset
663 gccjit::block next_block = (pc < toyvmfn.fn_num_ops
kono
parents:
diff changeset
664 ? op_blocks[pc + 1]
kono
parents:
diff changeset
665 : NULL);
kono
parents:
diff changeset
666
kono
parents:
diff changeset
667 toyvm_op *op;
kono
parents:
diff changeset
668 op = &toyvmfn.fn_ops[pc];
kono
parents:
diff changeset
669
kono
parents:
diff changeset
670 /* Helper macros. */
kono
parents:
diff changeset
671
kono
parents:
diff changeset
672 #define X_EQUALS_POP()\
kono
parents:
diff changeset
673 add_pop (block, x, loc)
kono
parents:
diff changeset
674 #define Y_EQUALS_POP()\
kono
parents:
diff changeset
675 add_pop (block, y, loc)
kono
parents:
diff changeset
676 #define PUSH_RVALUE(RVALUE)\
kono
parents:
diff changeset
677 add_push (block, (RVALUE), loc)
kono
parents:
diff changeset
678 #define PUSH_X()\
kono
parents:
diff changeset
679 PUSH_RVALUE (x)
kono
parents:
diff changeset
680 #define PUSH_Y() \
kono
parents:
diff changeset
681 PUSH_RVALUE (y)
kono
parents:
diff changeset
682
kono
parents:
diff changeset
683 block.add_comment (opcode_names[op->op_opcode], loc);
kono
parents:
diff changeset
684
kono
parents:
diff changeset
685 /* Handle the individual opcodes. */
kono
parents:
diff changeset
686
kono
parents:
diff changeset
687 switch (op->op_opcode)
kono
parents:
diff changeset
688 {
kono
parents:
diff changeset
689 case DUP:
kono
parents:
diff changeset
690 X_EQUALS_POP ();
kono
parents:
diff changeset
691 PUSH_X ();
kono
parents:
diff changeset
692 PUSH_X ();
kono
parents:
diff changeset
693 break;
kono
parents:
diff changeset
694
kono
parents:
diff changeset
695 case ROT:
kono
parents:
diff changeset
696 Y_EQUALS_POP ();
kono
parents:
diff changeset
697 X_EQUALS_POP ();
kono
parents:
diff changeset
698 PUSH_Y ();
kono
parents:
diff changeset
699 PUSH_X ();
kono
parents:
diff changeset
700 break;
kono
parents:
diff changeset
701
kono
parents:
diff changeset
702 case BINARY_ADD:
kono
parents:
diff changeset
703 Y_EQUALS_POP ();
kono
parents:
diff changeset
704 X_EQUALS_POP ();
kono
parents:
diff changeset
705 PUSH_RVALUE (
kono
parents:
diff changeset
706 ctxt.new_binary_op (
kono
parents:
diff changeset
707 GCC_JIT_BINARY_OP_PLUS,
kono
parents:
diff changeset
708 int_type,
kono
parents:
diff changeset
709 x, y,
kono
parents:
diff changeset
710 loc));
kono
parents:
diff changeset
711 break;
kono
parents:
diff changeset
712
kono
parents:
diff changeset
713 case BINARY_SUBTRACT:
kono
parents:
diff changeset
714 Y_EQUALS_POP ();
kono
parents:
diff changeset
715 X_EQUALS_POP ();
kono
parents:
diff changeset
716 PUSH_RVALUE (
kono
parents:
diff changeset
717 ctxt.new_binary_op (
kono
parents:
diff changeset
718 GCC_JIT_BINARY_OP_MINUS,
kono
parents:
diff changeset
719 int_type,
kono
parents:
diff changeset
720 x, y,
kono
parents:
diff changeset
721 loc));
kono
parents:
diff changeset
722 break;
kono
parents:
diff changeset
723
kono
parents:
diff changeset
724 case BINARY_MULT:
kono
parents:
diff changeset
725 Y_EQUALS_POP ();
kono
parents:
diff changeset
726 X_EQUALS_POP ();
kono
parents:
diff changeset
727 PUSH_RVALUE (
kono
parents:
diff changeset
728 ctxt.new_binary_op (
kono
parents:
diff changeset
729 GCC_JIT_BINARY_OP_MULT,
kono
parents:
diff changeset
730 int_type,
kono
parents:
diff changeset
731 x, y,
kono
parents:
diff changeset
732 loc));
kono
parents:
diff changeset
733 break;
kono
parents:
diff changeset
734
kono
parents:
diff changeset
735 case BINARY_COMPARE_LT:
kono
parents:
diff changeset
736 Y_EQUALS_POP ();
kono
parents:
diff changeset
737 X_EQUALS_POP ();
kono
parents:
diff changeset
738 PUSH_RVALUE (
kono
parents:
diff changeset
739 /* cast of bool to int */
kono
parents:
diff changeset
740 ctxt.new_cast (
kono
parents:
diff changeset
741 /* (x < y) as a bool */
kono
parents:
diff changeset
742 ctxt.new_comparison (
kono
parents:
diff changeset
743 GCC_JIT_COMPARISON_LT,
kono
parents:
diff changeset
744 x, y,
kono
parents:
diff changeset
745 loc),
kono
parents:
diff changeset
746 int_type,
kono
parents:
diff changeset
747 loc));
kono
parents:
diff changeset
748 break;
kono
parents:
diff changeset
749
kono
parents:
diff changeset
750 case RECURSE:
kono
parents:
diff changeset
751 {
kono
parents:
diff changeset
752 X_EQUALS_POP ();
kono
parents:
diff changeset
753 PUSH_RVALUE (
kono
parents:
diff changeset
754 ctxt.new_call (
kono
parents:
diff changeset
755 fn,
kono
parents:
diff changeset
756 x,
kono
parents:
diff changeset
757 loc));
kono
parents:
diff changeset
758 break;
kono
parents:
diff changeset
759 }
kono
parents:
diff changeset
760
kono
parents:
diff changeset
761 case RETURN:
kono
parents:
diff changeset
762 X_EQUALS_POP ();
kono
parents:
diff changeset
763 block.end_with_return (x, loc);
kono
parents:
diff changeset
764 break;
kono
parents:
diff changeset
765
kono
parents:
diff changeset
766 /* Ops taking an operand. */
kono
parents:
diff changeset
767 case PUSH_CONST:
kono
parents:
diff changeset
768 PUSH_RVALUE (
kono
parents:
diff changeset
769 ctxt.new_rvalue (int_type, op->op_operand));
kono
parents:
diff changeset
770 break;
kono
parents:
diff changeset
771
kono
parents:
diff changeset
772 case JUMP_ABS_IF_TRUE:
kono
parents:
diff changeset
773 X_EQUALS_POP ();
kono
parents:
diff changeset
774 block.end_with_conditional (
kono
parents:
diff changeset
775 /* "(bool)x". */
kono
parents:
diff changeset
776 ctxt.new_cast (x, bool_type, loc),
kono
parents:
diff changeset
777 op_blocks[op->op_operand], /* on_true */
kono
parents:
diff changeset
778 next_block, /* on_false */
kono
parents:
diff changeset
779 loc);
kono
parents:
diff changeset
780 break;
kono
parents:
diff changeset
781
kono
parents:
diff changeset
782 default:
kono
parents:
diff changeset
783 assert(0);
kono
parents:
diff changeset
784 } /* end of switch on opcode */
kono
parents:
diff changeset
785
kono
parents:
diff changeset
786 /* Go to the next block. */
kono
parents:
diff changeset
787 if (op->op_opcode != JUMP_ABS_IF_TRUE
kono
parents:
diff changeset
788 && op->op_opcode != RETURN)
kono
parents:
diff changeset
789 block.end_with_jump (next_block, loc);
kono
parents:
diff changeset
790
kono
parents:
diff changeset
791 } /* end of loop on PC locations. */
kono
parents:
diff changeset
792 }
kono
parents:
diff changeset
793
kono
parents:
diff changeset
794 compilation_result
kono
parents:
diff changeset
795 compilation_state::compile ()
kono
parents:
diff changeset
796 {
kono
parents:
diff changeset
797 return ctxt.compile ();
kono
parents:
diff changeset
798 }
kono
parents:
diff changeset
799
kono
parents:
diff changeset
800 char test[1024];
kono
parents:
diff changeset
801
kono
parents:
diff changeset
802 #define CHECK_NON_NULL(PTR) \
kono
parents:
diff changeset
803 do { \
kono
parents:
diff changeset
804 if ((PTR) != NULL) \
kono
parents:
diff changeset
805 { \
kono
parents:
diff changeset
806 pass ("%s: %s is non-null", test, #PTR); \
kono
parents:
diff changeset
807 } \
kono
parents:
diff changeset
808 else \
kono
parents:
diff changeset
809 { \
kono
parents:
diff changeset
810 fail ("%s: %s is NULL", test, #PTR); \
kono
parents:
diff changeset
811 abort (); \
kono
parents:
diff changeset
812 } \
kono
parents:
diff changeset
813 } while (0)
kono
parents:
diff changeset
814
kono
parents:
diff changeset
815 #define CHECK_VALUE(ACTUAL, EXPECTED) \
kono
parents:
diff changeset
816 do { \
kono
parents:
diff changeset
817 if ((ACTUAL) == (EXPECTED)) \
kono
parents:
diff changeset
818 { \
kono
parents:
diff changeset
819 pass ("%s: actual: %s == expected: %s", test, #ACTUAL, #EXPECTED); \
kono
parents:
diff changeset
820 } \
kono
parents:
diff changeset
821 else \
kono
parents:
diff changeset
822 { \
kono
parents:
diff changeset
823 fail ("%s: actual: %s != expected: %s", test, #ACTUAL, #EXPECTED); \
kono
parents:
diff changeset
824 fprintf (stderr, "incorrect value\n"); \
kono
parents:
diff changeset
825 abort (); \
kono
parents:
diff changeset
826 } \
kono
parents:
diff changeset
827 } while (0)
kono
parents:
diff changeset
828
kono
parents:
diff changeset
829 static void
kono
parents:
diff changeset
830 test_script (const char *scripts_dir, const char *script_name, int input,
kono
parents:
diff changeset
831 int expected_result)
kono
parents:
diff changeset
832 {
kono
parents:
diff changeset
833 char *script_path;
kono
parents:
diff changeset
834 toyvm_function *fn;
kono
parents:
diff changeset
835 int interpreted_result;
kono
parents:
diff changeset
836 toyvm_compiled_func code;
kono
parents:
diff changeset
837 int compiled_result;
kono
parents:
diff changeset
838
kono
parents:
diff changeset
839 snprintf (test, sizeof (test), "toyvm.cc: %s", script_name);
kono
parents:
diff changeset
840
kono
parents:
diff changeset
841 script_path = (char *)malloc (strlen (scripts_dir)
kono
parents:
diff changeset
842 + strlen (script_name) + 1);
kono
parents:
diff changeset
843 CHECK_NON_NULL (script_path);
kono
parents:
diff changeset
844 sprintf (script_path, "%s%s", scripts_dir, script_name);
kono
parents:
diff changeset
845
kono
parents:
diff changeset
846 fn = toyvm_function::parse (script_path, script_name);
kono
parents:
diff changeset
847 CHECK_NON_NULL (fn);
kono
parents:
diff changeset
848
kono
parents:
diff changeset
849 interpreted_result = fn->interpret (input, NULL);
kono
parents:
diff changeset
850 CHECK_VALUE (interpreted_result, expected_result);
kono
parents:
diff changeset
851
kono
parents:
diff changeset
852 compilation_result compiler_result = fn->compile ();
kono
parents:
diff changeset
853
kono
parents:
diff changeset
854 const char *funcname = fn->get_function_name ();
kono
parents:
diff changeset
855 code = (toyvm_compiled_func)compiler_result.get_code (funcname);
kono
parents:
diff changeset
856 CHECK_NON_NULL (code);
kono
parents:
diff changeset
857
kono
parents:
diff changeset
858 compiled_result = code (input);
kono
parents:
diff changeset
859 CHECK_VALUE (compiled_result, expected_result);
kono
parents:
diff changeset
860
kono
parents:
diff changeset
861 free (script_path);
kono
parents:
diff changeset
862 }
kono
parents:
diff changeset
863
kono
parents:
diff changeset
864 #define PATH_TO_SCRIPTS ("/jit/docs/examples/tut04-toyvm/")
kono
parents:
diff changeset
865
kono
parents:
diff changeset
866 static void
kono
parents:
diff changeset
867 test_suite (void)
kono
parents:
diff changeset
868 {
kono
parents:
diff changeset
869 const char *srcdir;
kono
parents:
diff changeset
870 char *scripts_dir;
kono
parents:
diff changeset
871
kono
parents:
diff changeset
872 snprintf (test, sizeof (test), "toyvm.cc");
kono
parents:
diff changeset
873
kono
parents:
diff changeset
874 /* We need to locate the test scripts.
kono
parents:
diff changeset
875 Rely on "srcdir" being set in the environment. */
kono
parents:
diff changeset
876
kono
parents:
diff changeset
877 srcdir = getenv ("srcdir");
kono
parents:
diff changeset
878 CHECK_NON_NULL (srcdir);
kono
parents:
diff changeset
879
kono
parents:
diff changeset
880 scripts_dir = (char *)malloc (strlen (srcdir) + strlen(PATH_TO_SCRIPTS)
kono
parents:
diff changeset
881 + 1);
kono
parents:
diff changeset
882 CHECK_NON_NULL (scripts_dir);
kono
parents:
diff changeset
883 sprintf (scripts_dir, "%s%s", srcdir, PATH_TO_SCRIPTS);
kono
parents:
diff changeset
884
kono
parents:
diff changeset
885 test_script (scripts_dir, "factorial.toy", 10, 3628800);
kono
parents:
diff changeset
886 test_script (scripts_dir, "fibonacci.toy", 10, 55);
kono
parents:
diff changeset
887
kono
parents:
diff changeset
888 free (scripts_dir);
kono
parents:
diff changeset
889 }
kono
parents:
diff changeset
890
kono
parents:
diff changeset
891 int
kono
parents:
diff changeset
892 main (int argc, char **argv)
kono
parents:
diff changeset
893 {
kono
parents:
diff changeset
894 const char *filename = NULL;
kono
parents:
diff changeset
895 toyvm_function *fn = NULL;
kono
parents:
diff changeset
896
kono
parents:
diff changeset
897 /* If called with no args, assume we're being run by the test suite. */
kono
parents:
diff changeset
898 if (argc < 3)
kono
parents:
diff changeset
899 {
kono
parents:
diff changeset
900 test_suite ();
kono
parents:
diff changeset
901 return 0;
kono
parents:
diff changeset
902 }
kono
parents:
diff changeset
903
kono
parents:
diff changeset
904 if (argc != 3)
kono
parents:
diff changeset
905 {
kono
parents:
diff changeset
906 fprintf (stdout,
kono
parents:
diff changeset
907 "%s FILENAME INPUT: Parse and run a .toy file\n",
kono
parents:
diff changeset
908 argv[0]);
kono
parents:
diff changeset
909 exit (1);
kono
parents:
diff changeset
910 }
kono
parents:
diff changeset
911
kono
parents:
diff changeset
912 filename = argv[1];
kono
parents:
diff changeset
913 fn = toyvm_function::parse (filename, filename);
kono
parents:
diff changeset
914 if (!fn)
kono
parents:
diff changeset
915 exit (1);
kono
parents:
diff changeset
916
kono
parents:
diff changeset
917 if (0)
kono
parents:
diff changeset
918 fn->disassemble (stdout);
kono
parents:
diff changeset
919
kono
parents:
diff changeset
920 printf ("interpreter result: %d\n",
kono
parents:
diff changeset
921 fn->interpret (atoi (argv[2]), NULL));
kono
parents:
diff changeset
922
kono
parents:
diff changeset
923 /* JIT-compilation. */
kono
parents:
diff changeset
924 compilation_result compiler_result = fn->compile ();
kono
parents:
diff changeset
925
kono
parents:
diff changeset
926 const char *funcname = fn->get_function_name ();
kono
parents:
diff changeset
927 toyvm_compiled_func code
kono
parents:
diff changeset
928 = (toyvm_compiled_func)compiler_result.get_code (funcname);
kono
parents:
diff changeset
929
kono
parents:
diff changeset
930 printf ("compiler result: %d\n",
kono
parents:
diff changeset
931 code (atoi (argv[2])));
kono
parents:
diff changeset
932
kono
parents:
diff changeset
933 return 0;
kono
parents:
diff changeset
934 }