1 /* VM default frontend for vmprefix VM.
2
3 Copyright (C) 2016, 2017, 2018, 2019, 2020 Luca Saiu
4 Written by Luca Saiu
5
6 This file is part of Jitter.
7
8 Jitter is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 Jitter is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with Jitter. If not, see <http://www.gnu.org/licenses/>. */
20
21
22 /* Generated file warning.
23 * ************************************************************************** */
24
25 /* Unless this file is named exactly "vm-main.c" , without any prefix, you are
26 looking at a machine-generated derived file. The original source is the
27 vm-main.c template from Jitter. */
28
29
30
31
32 /* Include headers.
33 * ************************************************************************** */
34
35 #ifdef HAVE_CONFIG_H
36 /* Use Gnulib, if available; on GNU everything should work even without it.
37
38 FIXME: I might want to find a solution for other systems, but they are not
39 prioritary. */
40 # include <config.h>
41 #endif // #ifdef HAVE_CONFIG_H
42
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <unistd.h>
46 #include <string.h>
47 #include <stdbool.h>
48
49 #include <argp.h>
50
51 #include <jitter/jitter.h>
52
53 /* Include optional headers. */
54 #ifdef JITTER_HAVE_SETRLIMIT
55 # include <sys/resource.h> /* For getrlimit and setrlimit . */
56 #endif // #ifdef JITTER_HAVE_SETRLIMIT
57
58 #include <jitter/jitter-parse-int.h>
59 #include <jitter/jitter-fatal.h>
60
61 #include "vmprefix-vm.h"
62
63
64
65
66 /* Command line handling.
67 * ************************************************************************** */
68
69 /* All the information encoded by the user in the command line. */
70 struct vmprefix_main_command_line
71 {
72 bool debug;
73 bool profile_specialized;
74 bool profile_unspecialized;
75 bool progress_on_stderr;
76 bool print_locations, print_routine, disassemble_routine, run_routine;
77 bool slow_literals_only, slow_registers_only;
78 bool optimization_rewriting;
79 char *input_file;
80 char *objdump_name;
81 char *objdump_options; /* Use default options when NULL. */
82 bool objdump_name_overridden;
83
84 #ifdef JITTER_HAVE_ALARM
85 /* The wall-clock run time limit in seconds, or 0 if there is no limit. */
86 unsigned int wall_clock_run_time_limit;
87 #endif // #ifdef JITTER_HAVE_ALARM
88
89 #ifdef JITTER_HAVE_SETRLIMIT
90 /* The CPU time limit in seconds, or RLIM_INFINITY if there is no limit. */
91 rlim_t cpu_time_limit;
92 #endif // #ifdef JITTER_HAVE_SETRLIMIT
93 };
94
95 /* Numeric identifiers for --no-* , or more in general "default" options having
96 no short equivalent and specifying the default behavior; these are
97 particularly convenient for interactive use where a complex command line is
98 modified frequently. Each case must have a value which is not an ASCII
99 character. */
100 enum vmprefix_vm_negative_option
101 {
102 vmprefix_vm_negative_option_no_cross_disassemble = -1,
103 vmprefix_vm_negative_option_no_disassemble = -2,
104 vmprefix_vm_negative_option_no_debug = -3,
105 vmprefix_vm_negative_option_no_dry_run = -4,
106 vmprefix_vm_negative_option_no_print_locations = -5,
107 vmprefix_vm_negative_option_no_print_routine = -6,
108 vmprefix_vm_negative_option_no_profile_specialized = -7,
109 vmprefix_vm_negative_option_no_profile_unspecialized = -8,
110 vmprefix_vm_negative_option_no_progress_on_stderr = -9,
111 vmprefix_vm_negative_option_no_slow_literals_only = -10,
112 vmprefix_vm_negative_option_no_slow_registers_only = -11,
113 vmprefix_vm_negative_option_no_slow_only = -12,
114 vmprefix_vm_negative_option_optimization_rewriting = -13
115 };
116
117 /* Numeric keys for options having only a long format. These must not conflict
118 with any value in enum vmprefix_vm_negative_option . */
119 enum vmprefix_vm_long_only_option
120 {
121 vmprefix_vm_long_only_option_print_locations = -109,
122 vmprefix_vm_long_only_option_profile_specialized = -110,
123 vmprefix_vm_long_only_option_profile_unspecialized = -111,
124 vmprefix_vm_long_only_option_dump_jitter_version = -112,
125 vmprefix_vm_long_only_option_slow_only = -113
126 };
127
128 /* Update our option state with the information from a single command-line
129 option. */
130 static error_t
parse_opt(int key,char * arg,struct argp_state * state)131 parse_opt (int key, char *arg, struct argp_state *state)
132 {
133 struct vmprefix_main_command_line *cl = state->input;
134 switch (key)
135 {
136 /* FIXME: within the case I could use state->arg_num to get the current
137 non-option argument index, if needed. */
138 case ARGP_KEY_INIT:
139 /* Set reasonable default values. */
140 cl->debug = false;
141 cl->progress_on_stderr = false;
142 cl->print_locations = false;
143 cl->profile_specialized = false;
144 cl->profile_unspecialized = false;
145 cl->print_routine = false;
146 cl->disassemble_routine = false;
147 cl->run_routine = true;
148 cl->slow_literals_only = false;
149 cl->slow_registers_only = false;
150 cl->optimization_rewriting = true;
151 cl->input_file = NULL;
152 cl->objdump_name = JITTER_OBJDUMP;
153 cl->objdump_name_overridden = false;
154 cl->objdump_options = NULL;
155 #ifdef JITTER_HAVE_ALARM
156 cl->wall_clock_run_time_limit = 0;
157 #endif // #ifdef JITTER_HAVE_ALARM
158 #ifdef JITTER_HAVE_SETRLIMIT
159 cl->cpu_time_limit = RLIM_INFINITY;
160 #endif // #ifdef JITTER_HAVE_SETRLIMIT
161 break;
162 case 't':
163 {
164 jitter_long_long limit;
165 if (jitter_string_to_long_long_inconvenient (arg, & limit) != 0)
166 argp_error (state, "--time-limit: invalid integer %s", arg);
167 #ifdef JITTER_HAVE_ALARM
168 if (limit < 0)
169 argp_error (state, "--time-limit: negative time %s", arg);
170 else if (limit > UINT_MAX)
171 argp_error (state, "--time-limit: integer %s out of range", arg);
172 else if (limit > 0)
173 cl->wall_clock_run_time_limit = limit;
174 #else
175 fprintf (stderr, "warning: alarm is disabled\n");
176 #endif // #ifdef JITTER_HAVE_ALARM
177 }
178 break;
179 case 'c':
180 {
181 jitter_long_long limit;
182 if (jitter_string_to_long_long_inconvenient (arg, & limit) != 0)
183 argp_error (state, "--cpu-time-limit: invalid integer %s", arg);
184 #ifdef JITTER_HAVE_SETRLIMIT
185 if (limit < 0)
186 argp_error (state, "--cpu-time-limit: negative time %" JITTER_PRIill,
187 limit);
188 else if (limit > 0)
189 cl->cpu_time_limit = limit;
190 #else
191 fprintf (stderr, "warning: setrlimit is disabled\n");
192 #endif // #ifdef JITTER_HAVE_SETRLIMIT
193 }
194 break;
195 case 'd':
196 cl->debug = true;
197 break;
198 case vmprefix_vm_long_only_option_dump_jitter_version:
199 printf ("%s\n", JITTER_PACKAGE_VERSION);
200 exit (EXIT_SUCCESS);
201 case vmprefix_vm_negative_option_no_debug:
202 cl->debug = false;
203 break;
204 case 'e':
205 cl->progress_on_stderr = true;
206 break;
207 case vmprefix_vm_negative_option_no_progress_on_stderr:
208 cl->progress_on_stderr = false;
209 break;
210 case vmprefix_vm_long_only_option_print_locations:
211 cl->print_locations = true;
212 break;
213 case vmprefix_vm_long_only_option_profile_specialized:
214 cl->profile_specialized = true;
215 break;
216 case vmprefix_vm_long_only_option_profile_unspecialized:
217 cl->profile_unspecialized = true;
218 break;
219 case 'p':
220 cl->print_routine = true;
221 break;
222 case vmprefix_vm_negative_option_no_print_locations:
223 cl->print_locations = false;
224 break;
225 case vmprefix_vm_negative_option_no_print_routine:
226 cl->print_routine = false;
227 break;
228 case vmprefix_vm_negative_option_no_profile_specialized:
229 cl->profile_specialized = false;
230 break;
231 case vmprefix_vm_negative_option_no_profile_unspecialized:
232 cl->profile_unspecialized = false;
233 break;
234 case 'b':
235 cl->objdump_name = arg;
236 cl->objdump_name_overridden = true;
237 break;
238 case 'B':
239 cl->objdump_options = arg;
240 break;
241 case 'D':
242 cl->disassemble_routine = true;
243 if (! cl->objdump_name_overridden)
244 cl->objdump_name = (arg != NULL) ? arg : JITTER_OBJDUMP;
245 break;
246 case vmprefix_vm_negative_option_no_disassemble:
247 case vmprefix_vm_negative_option_no_cross_disassemble:
248 cl->disassemble_routine = false;
249 break;
250 case 'C':
251 cl->disassemble_routine = true;
252 #if defined(JITTER_CROSS_COMPILING) && defined (JITTER_CROSS_OBJDUMP)
253 if (! cl->objdump_name_overridden)
254 cl->objdump_name = JITTER_CROSS_OBJDUMP;
255 #else
256 if (! cl->objdump_name_overridden)
257 cl->objdump_name = JITTER_OBJDUMP;
258 #endif // #if defined(JITTER_CROSS_COMPILING) && defined (JITTER_CROSS_OBJDUMP)
259 break;
260 case 'n':
261 cl->run_routine = false;
262 break;
263 case vmprefix_vm_negative_option_no_dry_run:
264 cl->run_routine = true;
265 break;
266 case 'L':
267 cl->slow_literals_only = true;
268 break;
269 case 'R':
270 cl->slow_registers_only = true;
271 break;
272 case vmprefix_vm_long_only_option_slow_only:
273 cl->slow_literals_only = true;
274 cl->slow_registers_only = true;
275 break;
276 case vmprefix_vm_negative_option_no_slow_literals_only:
277 cl->slow_literals_only = false;
278 break;
279 case vmprefix_vm_negative_option_no_slow_registers_only:
280 cl->slow_registers_only = false;
281 break;
282 case vmprefix_vm_negative_option_no_slow_only:
283 cl->slow_literals_only = false;
284 cl->slow_registers_only = false;
285 break;
286 case 'r':
287 cl->optimization_rewriting = false; /* The default is true. */
288 break;
289 case vmprefix_vm_negative_option_optimization_rewriting:
290 cl->optimization_rewriting = true;
291 break;
292
293 case ARGP_KEY_ARG:
294 cl->input_file = arg;
295 break;
296
297 /* case ARGP_KEY_NO_ARGS: /\* If this case is omitted, the default is sensible. *\/ */
298 /* argp_error (state, "you have to supply the input file\n"); */
299 /* break; */
300
301 /* case ARGP_KEY_SUCCESS: /\* If this case is omitted, the default is sensible. *\/ */
302 /* break; */
303
304 case ARGP_KEY_END:
305 if (state->arg_num != 1)
306 argp_error (state, "you gave %i input files instead of one.",
307 (int)state->arg_num);
308 break;
309
310 /* case ARGP_KEY_FINI: /\* If this case is omitted, the default is sensible. *\/ */
311 /* break; */
312
313 default:
314 return ARGP_ERR_UNKNOWN;
315 }
316 return 0;
317 }
318
319 /* Command-line option specification. */
320 static struct argp_option vmprefix_main_option_specification[] =
321 {/* Most frequently used options. */
322 {NULL, '\0', NULL, OPTION_DOC, "Frequently used options:", 10},
323 {"print-routine", 'p', NULL, 0,
324 "Print back the parsed routine"},
325 {"dry-run", 'n', NULL, 0,
326 "Do not actually run the routine"},
327 {"no-run", '\0', NULL, OPTION_ALIAS },
328 /* Most frequently used negative options. */
329 {NULL, '\0', NULL, OPTION_DOC, "", 11},
330 {"no-dry-run", vmprefix_vm_negative_option_no_dry_run, NULL, 0,
331 "Actually run the parsed routine (default)"},
332 {"no-print-routine", vmprefix_vm_negative_option_no_print_routine, NULL, 0,
333 "Don't print back the parsed routine (default)"},
334
335 /* Disassembly options. */
336 {NULL, '\0', NULL, OPTION_DOC, "Disassembly options:", 20},
337 {"objdump", 'b', "OBJDUMP", 0,
338 "If disassemblying use the given objdump program, overriding the default"},
339 {"objdump-options", 'B', "OPTS", 0,
340 "If disassemblying use the given objdump options, overriding the default"
341 " (" JITTER_OBJDUMP_OPTIONS
342 "). Options for raw dumping and for setting the correct endianness are "
343 " provided in any case, but user options take precedence"},
344 {"disassemble", 'D', "OBJDUMP", OPTION_ARG_OPTIONAL,
345 "Disassemble native " JITTER_HOST_TRIPLET " code using the given objdump"
346 " program (default: " JITTER_OBJDUMP
347 ") with, unless overridden, the default options"},
348 {"cross-disassemble", 'C', NULL, 0,
349 #if defined(JITTER_CROSS_COMPILING) && defined (JITTER_CROSS_OBJDUMP)
350 "Cross-disassemble " JITTER_HOST_TRIPLET " code (presumably through"
351 " an emulator running on " JITTER_BUILD_TRIPLET
352 " , on which this program was compiled) using "
353 JITTER_CROSS_OBJDUMP " by default"
354 #else
355 "Disassemble native " JITTER_HOST_TRIPLET " code, using " JITTER_OBJDUMP
356 " by default with, unless overridden, the default options"
357 " (this option exists for compatibility with cross-compiled builds)"
358 #endif // #if defined(JITTER_CROSS_COMPILING) && defined (JITTER_CROSS_OBJDUMP)
359 },
360 {"print-locations", vmprefix_vm_long_only_option_print_locations, NULL, 0,
361 "Print data-location information, mapping VM structures to hardware "
362 "resources"},
363 /* Disassembly negative options. */
364 {NULL, '\0', NULL, OPTION_DOC, "", 21},
365 {"no-disassemble", vmprefix_vm_negative_option_no_disassemble, NULL, 0,
366 "Don't disassemble the parsed routine (default)"},
367 {"no-cross-disassemble", vmprefix_vm_negative_option_no_cross_disassemble,
368 NULL, 0,
369 "Don't cross-disassemble the parsed routine (default)"},
370 {"no-print-locations", vmprefix_vm_negative_option_no_print_locations, NULL, 0,
371 "Don't print data location information (default)"},
372
373 /* Debugging, testing and benchmarking options. */
374 {NULL, '\0', NULL, OPTION_DOC,
375 "Debugging, testing and benchmarking options:", 30},
376 {"progress-on-stderr", 'e', NULL, 0,
377 "Show progress information on stderr instead of stdout"},
378 {"debug", 'd', NULL, 0, "Enable debugging" },
379 {"profile-specialized", vmprefix_vm_long_only_option_profile_specialized,
380 NULL, 0,
381 "Print VM specialised instruction profiling information, if configured in"},
382 {"profile-unspecialized", vmprefix_vm_long_only_option_profile_unspecialized,
383 NULL, 0,
384 "Print VM unspecialised instruction profiling information, if configured "
385 "in"},
386 {"slow-literals-only", 'L', NULL, 0,
387 "Use slow literals even where fast literals would be available"
388 " (this is mostly useful to measure the speedup introduced by fast"
389 " literals, or possibly to benchmark a worst-case scenario)"},
390 {"slow-registers-only", 'R', NULL, 0,
391 "Use slow registers even when fast registers would be available"
392 " (this is mostly useful to measure the speedup introduced by fast"
393 " registers, or to benchmark a worst-case scenario)"},
394 {"slow-only", vmprefix_vm_long_only_option_slow_only, NULL, 0,
395 "Equivalent to passing both --slow-literals-only and"
396 " --slow-registers-only"},
397 {"dump-jitter-version", vmprefix_vm_long_only_option_dump_jitter_version,
398 NULL, 0,
399 "Print the Jitter version only, without any surrounding text; this "
400 "is convenient for scripts" },
401 {"dump-version", '\0', NULL, OPTION_ALIAS },
402 {"no-optimization-rewriting", 'r', NULL, 0,
403 "Disable optimization rewriting (this is mostly useful for debugging "
404 "rewrite rules and for measuring the speedup they introduce)" },
405 /* Debugging, testing and benchmarking negative options. */
406 {NULL, '\0', NULL, OPTION_DOC, "", 31},
407 {"no-progress-on-stderr", vmprefix_vm_negative_option_no_progress_on_stderr,
408 NULL, 0, "Show progress information on stdout (default)"},
409 {"no-debug", vmprefix_vm_negative_option_no_debug,
410 NULL, 0, "Disable debugging (default)"},
411 {"no-profile-specialized", vmprefix_vm_negative_option_no_profile_specialized,
412 NULL, 0, "Disable specialized instruction profiling (default)"},
413 {"no-profile-unspecialized", vmprefix_vm_negative_option_no_profile_unspecialized,
414 NULL, 0, "Disable unspecialized instruction profiling (default)"},
415 {"no-slow-literals-only", vmprefix_vm_negative_option_no_slow_literals_only,
416 NULL, 0, "Use fast literals when possible (default)"},
417 {"no-slow-registers-only", vmprefix_vm_negative_option_no_slow_registers_only,
418 NULL, 0, "Use fast registers when possible (default)"},
419 {"no-slow-only", vmprefix_vm_negative_option_no_slow_only, NULL, 0,
420 "Equivalent to passing both --no-slow-literals-only and"
421 " --no-slow-registers-only (default)"},
422 {"optimization-rewriting", vmprefix_vm_negative_option_optimization_rewriting,
423 NULL, 0, "Enable optimization rewriting (default)"},
424
425 /* Test suite options. */
426 {NULL, '\0', NULL, OPTION_DOC, "Options mostly useful for test suites:", 40},
427 {"time-limit", 't', "S", 0,
428 "Fail if wall-clock run time exceeds S seconds (0 for no limit)"
429 #ifndef JITTER_HOST_OS_IS_GNU
430 "; this uses the alarm function, which may interfere with sleep on"
431 " non-GNU systems where sleep is implemented with SIGALRM"
432 #endif // #ifndef JITTER_HOST_OS_IS_GNU
433 #ifndef JITTER_HAVE_ALARM
434 " (Ignored on this configuration.)"
435 #endif // #ifndef JITTER_HAVE_SETRLIMIT
436 },
437 {"cpu-time-limit", 'c', "S", 0,
438 "Fail if CPU time exceeds S seconds (0 for no limit)"
439 #ifndef JITTER_HAVE_SETRLIMIT
440 " (Ignored on this configuration.)"
441 #endif // #ifndef JITTER_HAVE_SETRLIMIT
442 },
443
444 /* Common GNU-style options. */
445 {NULL, '\0', NULL, OPTION_DOC, "Common GNU-style options:", -1},
446 /* These are automatically generated. */
447
448 /* Option terminator. */
449 { 0 }};
450
451 /* Customised text text to print on --help and --version . */
452 static void
the_argp_program_version_hook(FILE * restrict stream,struct argp_state * s)453 the_argp_program_version_hook (FILE * restrict stream, struct argp_state *s)
454 {
455 const struct jitter_vm_configuration *c = vmprefix_vm_configuration;
456
457 const char *instrumentation
458 = jitter_vm_instrumentation_to_string (c->instrumentation);
459 fprintf (stream,
460 "VM driver for %s, %s%s%s dispatch "
461 "(" JITTER_PACKAGE_NAME ") " JITTER_PACKAGE_VERSION "\n",
462 c->lower_case_prefix,
463 instrumentation,
464 (strlen (instrumentation) > 0 ? ", " : ""),
465 c->dispatch_human_readable);
466 fprintf
467 (stream,
468 "Copyright (C) 2021 Luca Saiu.\n"
469 "Jitter comes with ABSOLUTELY NO WARRANTY.\n"
470 "You may redistribute copies of Jitter under the terms of the GNU\n"
471 "General Public License, version 3 or any later version published\n"
472 "by the Free Software Foundation. For more information see the\n"
473 "file named COPYING.\n"
474 "\n"
475 "Written by Luca Saiu <http://ageinghacker.net> (Jitter, its runtime,\n"
476 "this driver program).\n");
477 }
478 void (*argp_program_version_hook) (FILE * restrict stream, struct argp_state *s)
479 = the_argp_program_version_hook;
480 const char *argp_program_bug_address = JITTER_PACKAGE_BUGREPORT;
481
482 /* The parser main data structure. */
483 static struct argp argp =
484 {
485 vmprefix_main_option_specification,
486 parse_opt,
487 "FILE.vm",
488 "Run a routine encoded as a text file on the " VMPREFIX_VM_NAME
489 " VM, using " JITTER_DISPATCH_NAME_STRING " dispatch."
490 };
491
492
493
494
495 /* Main function.
496 * ************************************************************************** */
497
498 int
main(int argc,char ** argv)499 main (int argc, char **argv)
500 {
501 /* Parse our arguments; every option seen by 'parse_opt' will
502 be reflected in 'arguments'. */
503 struct vmprefix_main_command_line cl;
504 argp_parse (&argp, argc, argv,
505 0,//ARGP_IN_ORDER,
506 0, &cl);
507
508 /* Initialise the GNU Libtextstyle wrapper, if used. */
509 #ifdef JITTER_WITH_LIBTEXTSTYLE
510 jitter_print_libtextstyle_initialize ();
511
512 /* FIXME: this should be less crude, but is enough for checking that the
513 libtextstyle wrapper works. */
514 char *style_file_name = "vmprefix-style.css";
515 styled_ostream_t ostream
516 = styled_ostream_create (STDOUT_FILENO, "(stdout)", TTYCTL_AUTO,
517 style_file_name);
518 #endif // #ifdef JITTER_WITH_LIBTEXTSTYLE
519
520 /* Make a print context, using the Libtextstyle wrapper if possible. */
521 jitter_print_context ctx
522 #ifdef JITTER_WITH_LIBTEXTSTYLE
523 = jitter_print_context_make_libtextstyle (ostream);
524 #else
525 = jitter_print_context_make_file_star (stdout);
526 #endif // #ifdef JITTER_WITH_LIBTEXTSTYLE
527
528 FILE *progress;
529 if (cl.progress_on_stderr)
530 progress = stderr;
531 else
532 progress = stdout;
533
534 #ifdef JITTER_HAVE_ALARM
535 /* Set a limit to the wall-clock run time, if so requested on the command
536 line. */
537 if (cl.wall_clock_run_time_limit != 0)
538 alarm (cl.wall_clock_run_time_limit);
539 #endif // #ifdef JITTER_HAVE_ALARM
540
541 #ifdef JITTER_HAVE_SETRLIMIT
542 /* Set a limit to the CPU time, if so requested on the command line. */
543 if (cl.cpu_time_limit != RLIM_INFINITY)
544 {
545 if (cl.debug)
546 fprintf (progress, "Setting resource limits...\n");
547 struct rlimit limit;
548 if (getrlimit (RLIMIT_CPU, & limit) != 0)
549 jitter_fatal ("getrlimit failed");
550 limit.rlim_cur = cl.cpu_time_limit;
551 if (setrlimit (RLIMIT_CPU, & limit) != 0)
552 jitter_fatal ("setrlimit failed");
553 }
554 #endif // #ifdef JITTER_HAVE_SETRLIMIT
555
556 if (cl.debug)
557 fprintf (progress, "Initializing...\n");
558 vmprefix_initialize ();
559
560 /* Make an empty VM routine, and set options as requested by the user. */
561 struct vmprefix_mutable_routine *r = vmprefix_make_mutable_routine ();
562 if (cl.debug)
563 fprintf (progress,
564 "Options:\n"
565 "* slow literals only: %s\n"
566 "* slow registers only: %s\n"
567 "* optimization rewriting: %s\n",
568 cl.slow_literals_only ? "yes" : "no",
569 cl.slow_registers_only ? "yes" : "no",
570 cl.optimization_rewriting ? "yes" : "no");
571 vmprefix_set_mutable_routine_option_slow_literals_only
572 (r, cl.slow_literals_only);
573 vmprefix_set_mutable_routine_option_slow_registers_only
574 (r, cl.slow_registers_only);
575 vmprefix_set_mutable_routine_option_optimization_rewriting
576 (r, cl.optimization_rewriting);
577
578 /* Print the VM configuration if in debugging mode. */
579 if (cl.debug)
580 vmprefix_print_vm_configuration (progress, vmprefix_vm_configuration);
581
582 if (cl.debug)
583 fprintf (progress, "Parsing...\n");
584 if (! strcmp (cl.input_file, "-"))
585 vmprefix_parse_mutable_routine_from_file_star (stdin, r);
586 else
587 vmprefix_parse_mutable_routine_from_file (cl.input_file, r);
588 if (cl.debug)
589 fprintf (progress, "The requried slow register number is %li per class.\n",
590 (long) r->slow_register_per_class_no);
591
592 /* Make an executable jittery routine. */
593 if (cl.debug)
594 fprintf (progress, "Making executable...\n");
595 struct vmprefix_executable_routine *er
596 = vmprefix_make_executable_routine (r);
597
598 if (cl.print_routine)
599 {
600 if (cl.debug)
601 fprintf (progress, "Printing back the routine...\n");
602 vmprefix_mutable_routine_print (ctx, r);
603 }
604
605 if (cl.print_locations)
606 {
607 if (cl.debug)
608 fprintf (progress, "Printing data location information...\n");
609 vmprefix_dump_data_locations (ctx);
610 }
611
612 if (cl.disassemble_routine)
613 {
614 if (cl.debug)
615 fprintf (progress, "Disassembling...\n");
616 vmprefix_executable_routine_disassemble (ctx, er, true, cl.objdump_name,
617 cl.objdump_options);
618 }
619
620 /* If we dumped data locations or printed back or disassembled the routine,
621 this run is not performance critical and we afford a couple more syscalls.
622 Flush the output buffer, so that the routine is visible before running, and
623 possibly crashing. */
624 if (cl.print_locations || cl.print_routine || cl.disassemble_routine)
625 {
626 jitter_print_flush (ctx);
627 fflush (stdout);
628 fflush (stderr);
629 }
630
631 if (cl.run_routine)
632 {
633 if (cl.debug)
634 fprintf (progress, "Initializing VM state...\n");
635 struct vmprefix_state s;
636 vmprefix_state_initialize (& s);
637
638 if (cl.debug)
639 fprintf (progress, "Interpreting...\n");
640 vmprefix_execute_executable_routine (er, & s);
641
642 if (cl.profile_specialized)
643 {
644 if (cl.debug)
645 fprintf (progress, "Printing specialised profile...\n");
646 struct vmprefix_profile_runtime *pr
647 = vmprefix_state_profile_runtime (& s);
648 vmprefix_profile_runtime_print_specialized (ctx, pr);
649 }
650
651 if (cl.profile_unspecialized)
652 {
653 if (cl.debug)
654 fprintf (progress, "Printing unspecialised profile...\n");
655 struct vmprefix_profile_runtime *pr
656 = vmprefix_state_profile_runtime (& s);
657 vmprefix_profile_runtime_print_unspecialized (ctx, pr);
658 }
659
660 if (cl.debug)
661 fprintf (progress, "Finalizing VM state...\n");
662 vmprefix_state_finalize (& s);
663 }
664
665 if (cl.debug)
666 fprintf (progress, "Destroying the routine data structure...\n");
667 /* Destroy the Jittery routine in both its versions, executable and
668 non-executable. */
669 vmprefix_destroy_executable_routine (er);
670 vmprefix_destroy_mutable_routine (r);
671
672 if (cl.debug)
673 fprintf (progress, "Finalizing...\n");
674 vmprefix_finalize ();
675
676 /* Destroy the print context. */
677 jitter_print_context_destroy (ctx);
678
679 /* End the ostream and finalise the GNU Libtextstyle wrapper, if used. */
680 #ifdef JITTER_WITH_LIBTEXTSTYLE
681 styled_ostream_free (ostream);
682 jitter_print_libtextstyle_finalize ();
683 #endif // #ifdef JITTER_WITH_LIBTEXTSTYLE
684
685 if (cl.debug)
686 fprintf (progress, "Still alive at exit.\n");
687 return 0;
688 }
689