1 /* Jitter: generator implementation.
2 
3    Copyright (C) 2017, 2018, 2019, 2020, 2021 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 /* Include the Gnulib header. */
23 #include <config.h>
24 
25 #include <assert.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <ctype.h>
29 #include <unistd.h> /* for unlink and rmdir */
30 #include <string.h>
31 #include <sys/stat.h> /* For mkdir and permission bit macros. */
32 #include <errno.h>
33 
34 #include <xalloc.h>
35 #include <gl_array_list.h>
36 #include <gl_xlist.h>
37 
38 #include "jitterc-generate.h"
39 #include "jitterc-utility.h"
40 #include "jitterc-vm.h"
41 #include "jitterc-rewrite.h"
42 #include "jitterc-mangle.h"
43 
44 #include <jitter/jitter-fatal.h>
45 #include <jitter/jitter-string.h>
46 
47 /* This contains fixed opcodes for special specialized instructions. */
48 #include <jitter/jitter-specialize.h>
49 
50 
51 /* Preliminary definitions.
52  * ************************************************************************** */
53 
54 /* VM prefixes as occurring in templates and generated files before
55    replacement. */
56 #define INPUT_LOWER_CASE_PREFIX  "vmprefix"
57 #define INPUT_UPPER_CASE_PREFIX  "VMPREFIX"
58 
59 /* The temporary subdirectory basename.  This directory contains a temporary
60    copy of the generated files, to be copied to the actual output directory
61    at the end if everything succeeds. */
62 #define TMP "tmp-vm-generator"
63 
64 
65 
66 
67 /* Code generation machinery.
68  * ************************************************************************** */
69 
70 /* Perform a fprintf call exiting fatally in case of error. */
71 #define EMIT_TO(...)                                      \
72   do                                                      \
73     {                                                     \
74       if (fprintf (__VA_ARGS__) < 0)                      \
75         jitter_fatal ("could not write to output file");  \
76     }                                                     \
77   while (false)
78 
79 /* Perform a fprintf call exiting fatally in case of error and using as output
80    the variable f, jitter it is in the current scope. */
81 #define EMIT(...)         \
82   EMIT_TO(f, __VA_ARGS__)
83 
84 static FILE *
jitterc_fopen_pathname(const char * pathname,const char * opentype)85 jitterc_fopen_pathname (const char *pathname, const char *opentype)
86 {
87   FILE *res = fopen (pathname, opentype);
88   if (res == NULL)
89     jitter_fatal ("could not open file %s in mode %s", pathname, opentype);
90   return res;
91 }
92 
93 /* Return a new file stream open for reading, or fail fatally in case of error;
94    the file full pathname is given as an argument. */
95 static FILE *
jitterc_fopen_r_pathname(const char * pathname)96 jitterc_fopen_r_pathname (const char *pathname)
97 {
98   return jitterc_fopen_pathname (pathname, "r");
99 }
100 
101 /* Return a new file stream open for writing, or fail fatally in case of error;
102    the file full pathname is given as an argument. */
103 static FILE *
jitterc_fopen_w_pathname(const char * pathname)104 jitterc_fopen_w_pathname (const char *pathname)
105 {
106   return jitterc_fopen_pathname (pathname, "w");
107 }
108 
109 /* Return a new file stream open for appending, or fail fatally in case of
110    error; the file full pathname is given as an argument. */
111 static FILE *
jitterc_fopen_a_pathname(const char * pathname)112 jitterc_fopen_a_pathname (const char *pathname)
113 {
114   return jitterc_fopen_pathname (pathname, "a");
115 }
116 
117 /* Return a malloc-allocated string containing the full pathname of the given
118    basename, within the temporary directory of the pointed VM. */
119 __attribute__ ((returns_nonnull, nonnull (1, 2)))
120 static char *
jitterc_pathname(const struct jitterc_vm * vm,const char * basename)121 jitterc_pathname (const struct jitterc_vm *vm,
122                   const char *basename)
123 {
124   size_t pathname_size
125     = strlen (vm->tmp_directory) + 1 + strlen (basename) + 1;
126   char *pathname = xmalloc (pathname_size);
127   sprintf (pathname, "%s/%s", vm->tmp_directory, basename);
128   return pathname;
129 }
130 
131 /* Return a new file stream open for appending in the temporary directory of the
132    pointed VM, or fail fatally in case of error; the file basename is given as
133    an argument. */
134 static FILE *
jitterc_fopen_a_basename(const struct jitterc_vm * vm,const char * basename)135 jitterc_fopen_a_basename (const struct jitterc_vm *vm,
136                           const char *basename)
137 {
138   char *pathname = jitterc_pathname (vm, basename);
139   FILE *res = jitterc_fopen_a_pathname (pathname);
140   free (pathname);
141   return res;
142 }
143 
144 static FILE *
jitterc_fopen_w_or_a_and_remember_basename(const struct jitterc_vm * vm,const char * basename,const char letter)145 jitterc_fopen_w_or_a_and_remember_basename (const struct jitterc_vm *vm,
146                                             const char *basename,
147                                             const char letter)
148 {
149   gl_list_add_last (vm->written_file_names,
150                     jitter_clone_string (basename));
151   char *pathname = jitterc_pathname (vm, basename);
152   FILE *res;
153   if (letter == 'w')
154     res = jitterc_fopen_w_pathname (pathname);
155   else if (letter == 'a')
156     res = jitterc_fopen_a_pathname (pathname);
157   else
158     jitter_fatal ("jitterc_fopen_w_or_a_and_remember_basename: wrong letter");
159   free (pathname);
160   return res;
161 }
162 
163 /* Return a new file stream open for writing; the given file basename is
164    appended to the temporary output directory of the VM whose pointer is given,
165    and the file basename is copied to the written_file_names list in the VM, so
166    that the written file can be moved later to the actual output directory if
167    everything succeeds. */
168 __attribute__ ((unused))
169 static FILE *
jitterc_fopen_w_and_remember_basename(const struct jitterc_vm * vm,const char * basename)170 jitterc_fopen_w_and_remember_basename (const struct jitterc_vm *vm,
171                                        const char *basename)
172 {
173   return jitterc_fopen_w_or_a_and_remember_basename (vm, basename, 'w');
174 }
175 
176 /* Like jitterc_fopen_w_and_remember_basename, but append instead of
177    overwriting in case the file already exists. */
178 static FILE *
jitterc_fopen_a_and_remember_basename(const struct jitterc_vm * vm,const char * basename)179 jitterc_fopen_a_and_remember_basename (const struct jitterc_vm *vm,
180                                        const char *basename)
181 {
182   return jitterc_fopen_w_or_a_and_remember_basename (vm, basename, 'a');
183 }
184 
185 /* Close the given stream, failing fatally in case of errors.  This works for
186    both input and output streams.*/
187 void
jitterc_fclose(FILE * f)188 jitterc_fclose (FILE *f)
189 {
190   if (fclose (f) != 0)
191     jitter_fatal ("could not close file");
192 }
193 
194 /* Make the given directory, exiting fatally in case of error. */
195 static void
jitterc_mkdir(const char * pathname)196 jitterc_mkdir (const char *pathname)
197 {
198   if (mkdir (pathname, S_IRWXU) != 0 && errno != EEXIST)
199     jitter_fatal ("could not make directory %s", (pathname));
200 }
201 
202 /* From this point on any use of fopen, fclose or fprintf or mkdir is almost
203    certainly a mistake.  Poison the identifiers in question. */
204 #pragma GCC poison \
205   mkdir fclose fprintf fopen
206 
207 #define FOR_LIST(VARIABLE, COMMA, LIST)                                  \
208   for (VARIABLE = 0                                                      \
209          , COMMA = ((VARIABLE == gl_list_size (LIST) - 1) ? "" : ",");   \
210        VARIABLE < gl_list_size (LIST);                                   \
211        VARIABLE ++                                                       \
212          , COMMA = ((VARIABLE == gl_list_size (LIST) - 1) ? "" : ","))
213 
214 #define FOR_LIST_DOWN(VARIABLE, COMMA, LIST)      \
215   for (VARIABLE = gl_list_size (LIST) - 1         \
216          , COMMA = ((VARIABLE == 0) ? "" : ",");  \
217        VARIABLE >= 0;                             \
218        VARIABLE --                                \
219          , COMMA = ((VARIABLE == 0) ? "" : ","))
220 
221 
222 
223 /* Simple source generation. */
224 
225 /* Emit verbatim text to the output, without any added whitespace.  This
226    is useful to emit comments or C code. */
227 static void
jitterc_emit_text_to_stream(const struct jitterc_vm * vm,const char * file_basename,const char * text)228 jitterc_emit_text_to_stream (const struct jitterc_vm *vm,
229                              const char *file_basename,
230                              const char *text)
231 {
232   FILE *f = jitterc_fopen_a_basename (vm, file_basename);
233   EMIT ("%s", text);
234   jitterc_fclose (f);
235 }
236 
237 /* Emit user-specified code.  FIXME: use this everywhere and find some way of
238    handling #line directives out of user code. */
239 static void
jitterc_emit_user_c_code_to_stream(const struct jitterc_vm * vm,FILE * f,const char * code,char * description)240 jitterc_emit_user_c_code_to_stream (const struct jitterc_vm *vm,
241                                     FILE *f,
242                                     const char *code,
243                                     char *description)
244 {
245   EMIT("/* User-specified code, %s part: beginning. */\n", description);
246   EMIT("%s", code);
247   EMIT("\n/* User-specified code, %s part: end */\n", description);
248   EMIT("\n");
249 }
250 
251 /* Emit user-specified code.  FIXME: use this everywhere and find some way of
252    handling #line directives out of user code. */
253 static void
jitterc_emit_user_c_code(const struct jitterc_vm * vm,const char * file_basename,const char * code,char * description)254 jitterc_emit_user_c_code (const struct jitterc_vm *vm,
255                           const char *file_basename,
256                           const char *code,
257                           char *description)
258 {
259   FILE *f = jitterc_fopen_a_basename (vm, file_basename);
260   jitterc_emit_user_c_code_to_stream (vm, f, code, description);
261   jitterc_fclose (f);
262 }
263 
264 /* Emit the initial part of the user-specified code for the header.  This user code
265    comes before everything, even before standard #include directives. */
266 static void
jitterc_emit_initial_header_c(const struct jitterc_vm * vm)267 jitterc_emit_initial_header_c (const struct jitterc_vm *vm)
268 {
269   jitterc_emit_user_c_code (vm, "vm.h", vm->initial_header_c_code,
270                             "initial header");
271 }
272 
273 /* Like jitterc_emit_initial_header_c for the other generated files. */
274 static void
jitterc_emit_initial_vm1_c(const struct jitterc_vm * vm)275 jitterc_emit_initial_vm1_c (const struct jitterc_vm *vm)
276 {
277   jitterc_emit_user_c_code (vm, "vm1.c", vm->initial_vm1_c_code,
278                             "initial vm1");
279 }
280 static void
jitterc_emit_initial_vm2_c(const struct jitterc_vm * vm)281 jitterc_emit_initial_vm2_c (const struct jitterc_vm *vm)
282 {
283   jitterc_emit_user_c_code (vm, "vm2.c", vm->initial_vm2_c_code,
284                             "initial vm2");
285 }
286 static void
jitterc_emit_initial_vm_main_c(const struct jitterc_vm * vm)287 jitterc_emit_initial_vm_main_c (const struct jitterc_vm *vm)
288 {
289   jitterc_emit_user_c_code (vm, "vm-main.c", vm->initial_vm_main_c_code,
290                             "initial vm-main");
291 }
292 
293 
294 /* Emit the early part of the user-specified code for the header. */
295 static void
jitterc_emit_early_header_c(const struct jitterc_vm * vm)296 jitterc_emit_early_header_c (const struct jitterc_vm *vm)
297 {
298   jitterc_emit_user_c_code (vm, "vm.h", vm->early_header_c_code,
299                             "early header");
300 }
301 
302 /* Emit the late part of the user-specified code for the header. */
303 static void
jitterc_emit_late_header_c(const struct jitterc_vm * vm)304 jitterc_emit_late_header_c (const struct jitterc_vm *vm)
305 {
306   jitterc_emit_user_c_code (vm, "vm.h", vm->late_header_c_code,
307                             "late header");
308 }
309 
310 /* Emit the late part of the user-specified code for the header. */
311 static void
jitterc_emit_header_closing(const struct jitterc_vm * vm)312 jitterc_emit_header_closing (const struct jitterc_vm *vm)
313 {
314   FILE *f = jitterc_fopen_a_basename (vm, "vm.h");
315   EMIT("\n");
316   EMIT("/* Close the multiple-inclusion guard opened in the template. */\n");
317   EMIT("#endif // #ifndef VMPREFIX_VM_H_\n");
318   jitterc_fclose (f);
319 }
320 
321 static void
jitterc_emit_meta_instructions_h(const struct jitterc_vm * vm)322 jitterc_emit_meta_instructions_h (const struct jitterc_vm *vm)
323 {
324   FILE *f = jitterc_fopen_a_basename (vm, "vm.h");
325   EMIT("#ifndef VMPREFIX_META_INSTRUCTIONS_H_\n#define VMPREFIX_META_INSTRUCTIONS_H_\n\n");
326   EMIT("enum vmprefix_meta_instruction_id\n");
327   EMIT("  {\n");
328   int i; char *comma;
329   FOR_LIST(i, comma, vm->instructions)
330     EMIT("    vmprefix_meta_instruction_id_%s = %i%s\n",
331          (((const struct jitterc_instruction*)
332            gl_list_get_at (vm->instructions, i))->mangled_name),
333          i,
334          comma);
335   EMIT("  };\n");
336   EMIT("\n#define VMPREFIX_META_INSTRUCTION_NO %i\n\n", i);
337 
338   EMIT("/* The longest meta-instruction name length, not mangled, without\n");
339   EMIT("   counting the final '\\0' character. */\n");
340   EMIT("#define VMPREFIX_MAX_META_INSTRUCTION_NAME_LENGTH %u\n\n",
341        (unsigned) vm->max_instruction_name_length);
342   EMIT("#endif // #ifndef VMPREFIX_META_INSTRUCTIONS_H_\n");
343   jitterc_fclose (f);
344 }
345 
346 /* Emit user C code for literal argument printing.  This is called at the
347    appropriate time to be visible in the relevant part of the generated code
348    without forward-declarations. */
349 static void
jitterc_emit_printer_c(const struct jitterc_vm * vm)350 jitterc_emit_printer_c  (const struct jitterc_vm *vm)
351 {
352   jitterc_emit_user_c_code (vm, "vm1.c", vm->printer_c_code,
353                             "printer");
354 }
355 
356 /* The generated file also includes what was in the old generated
357    vm/meta-instruction-parameter-types.c . */
358 static void
jitterc_emit_meta_instructions(const struct jitterc_vm * vm)359 jitterc_emit_meta_instructions (const struct jitterc_vm *vm)
360 {
361   FILE *f = jitterc_fopen_a_basename (vm, "vm1.c");
362   int i; char *comma __attribute__ ((unused));
363   EMIT("//#include <stdbool.h>\n\n");
364   EMIT("//#include <jitter/jitter.h>\n");
365   EMIT("//#include <jitter/jitter-instruction.h>\n\n");
366   EMIT("//#include \"vmprefix-meta-instructions.h\"\n");
367   EMIT("\n");
368   EMIT("// FIXME: comment.\n");
369   EMIT("struct jitter_hash_table\n");
370   EMIT("vmprefix_meta_instruction_hash;\n");
371   EMIT("\n\n");
372   FOR_LIST(i, comma, vm->instructions)
373     {
374       const struct jitterc_instruction *in
375         = (const struct jitterc_instruction*)
376           (gl_list_get_at (vm->instructions, i));
377 
378       int in_arity = gl_list_size (in->arguments);
379       if (in_arity == 0)
380         continue;
381 
382       EMIT("static const /*FIXME: use enum jitterc_instruction_argument_kind instead*/struct jitter_meta_instruction_parameter_type vmprefix_%s_meta_instruction_parameter_types [%i] =\n  {",
383            in->mangled_name,
384            in_arity);
385       int j; char *inner_comma;
386       FOR_LIST(j, inner_comma, in->arguments)
387       //for (j = 0; j < in_arity; j ++)
388         {
389           //if (j == (in_arity - 1))
390           //  inner_comma = "";
391           /* FIXME: this is a temporary compatibility hack.  I should do away
392              with enum jitter_meta_instruction_parameter_type and use enum
393              jitterc_instruction_argument_kind instead .*/
394           const struct jitterc_instruction_argument *arg
395             = (const struct jitterc_instruction_argument *)
396               (gl_list_get_at (in->arguments, j));
397           char *kind;
398           bool includes_register = false;
399           switch ((int) arg->kind)
400             {
401             case   jitterc_instruction_argument_kind_register:
402               kind = "jitter_meta_instruction_parameter_kind_register";
403               includes_register = true;
404               break;
405             case   jitterc_instruction_argument_kind_literal:
406               kind = "jitter_meta_instruction_parameter_kind_literal_fixnum";
407               break;
408             case   jitterc_instruction_argument_kind_label:
409             case   jitterc_instruction_argument_kind_fast_label:
410               kind = "jitter_meta_instruction_parameter_kind_literal_label";
411               break;
412             case   jitterc_instruction_argument_kind_register
413                  | jitterc_instruction_argument_kind_literal:
414               kind = "jitter_meta_instruction_parameter_kind_register_or_literal_fixnum";
415               includes_register = true;
416               break;
417             case   jitterc_instruction_argument_kind_register
418                  | jitterc_instruction_argument_kind_label:
419               kind = "jitter_meta_instruction_parameter_kind_register_or_literal_label";
420               includes_register = true;
421               break;
422             case   jitterc_instruction_argument_kind_literal
423                  | jitterc_instruction_argument_kind_label:
424               kind = "jitter_meta_instruction_parameter_kind_literal_fixnum_or_literal_label";
425               includes_register = false;
426               break;
427             case   jitterc_instruction_argument_kind_register
428                  | jitterc_instruction_argument_kind_literal
429                  | jitterc_instruction_argument_kind_label:
430               kind = "jitter_meta_instruction_parameter_kind_register_or_literal_fixnum_or_literal_label";
431               includes_register = true;
432               break;
433             default:
434               jitter_fatal ("Unsupported enum jitterc_instruction_argument_kind case: %i\n",
435                              (int) arg->kind);
436             }
437 
438           /* Get the name of the literal printer, of a default if none was
439              given. */
440           char *literal_printer_name;
441           if (arg->c_literal_printer_name != NULL)
442             literal_printer_name = arg->c_literal_printer_name;
443           else
444             literal_printer_name = "jitter_default_literal_parameter_printer";
445 
446           if (includes_register)
447             EMIT(" { %s, & vmprefix_register_class_%c, %s }%s", kind,
448                  arg->register_class_character, literal_printer_name,
449                  inner_comma);
450           else
451             EMIT(" { %s, NULL, %s }%s", kind, literal_printer_name,
452                  inner_comma);
453         }
454       EMIT(" };\n\n");
455     }
456   //EMIT("  };\n");
457   EMIT("\n");
458   EMIT("const struct jitter_meta_instruction\n");
459   EMIT("vmprefix_meta_instructions [VMPREFIX_META_INSTRUCTION_NO]\n");
460   EMIT("  = {\n");
461   FOR_LIST(i, comma, vm->instructions)
462     {
463       const struct jitterc_instruction *in
464         = (const struct jitterc_instruction*)
465           (gl_list_get_at (vm->instructions, i));
466       int in_arity = gl_list_size (in->arguments);
467       EMIT("      { %i, \"%s\", %i, %s, %s, %s, ",
468            i, in->name, in_arity,
469            ((in->callerness == jitterc_callerness_caller)
470             ? "true" : "false"),
471            ((in->calleeness == jitterc_calleeness_callee)
472             ? "true" : "false"),
473            ((in->relocatability == jitterc_relocatability_relocatable)
474             ? "true /* FIXME: this may be wrong with replacements. */"
475             : "false  /* FIXME: this may be wrong with replacements. */"));
476       if (in_arity == 0)
477         EMIT("NULL }%s\n", comma);
478       else
479         EMIT("vmprefix_%s_meta_instruction_parameter_types }%s\n",
480              in->mangled_name, comma);
481     }
482   EMIT("    };\n");
483   jitterc_fclose (f);
484 }
485 
486 static void
jitterc_emit_specialized_instructions_h(const struct jitterc_vm * vm)487 jitterc_emit_specialized_instructions_h (const struct jitterc_vm *vm)
488 {
489   FILE *f = jitterc_fopen_a_basename (vm, "vm.h");
490   EMIT("#ifndef VMPREFIX_SPECIALIZED_INSTRUCTIONS_H_\n#define VMPREFIX_SPECIALIZED_INSTRUCTIONS_H_\n\n");
491   EMIT("enum vmprefix_specialized_instruction_opcode\n");
492   EMIT("  {\n");
493   int i; char *comma;
494   FOR_LIST(i, comma, vm->specialized_instructions)
495     EMIT("    vmprefix_specialized_instruction_opcode_%s = %i%s\n",
496          (((const struct jitterc_specialized_instruction*)
497            gl_list_get_at (vm->specialized_instructions, i))->mangled_name),
498          i,
499          comma);
500   EMIT("  };\n");
501   EMIT("\n#define VMPREFIX_SPECIALIZED_INSTRUCTION_NO %i\n\n", i);
502   EMIT("#endif // #ifndef VMPREFIX_SPECIALIZED_INSTRUCTIONS_H_\n");
503   jitterc_fclose (f);
504 }
505 
506 static void
jitterc_emit_specialized_instruction_names(const struct jitterc_vm * vm)507 jitterc_emit_specialized_instruction_names (const struct jitterc_vm *vm)
508 {
509   FILE *f = jitterc_fopen_a_basename (vm, "vm1.c");
510   EMIT("//#include \"vmprefix-specialized-instructions.h\"\n");
511   EMIT("\n");
512   EMIT("const char * const\n");
513   EMIT("vmprefix_specialized_instruction_names [VMPREFIX_SPECIALIZED_INSTRUCTION_NO]\n");
514   EMIT("  = {\n");
515   int i; char *comma;
516   FOR_LIST(i, comma, vm->specialized_instructions)
517     EMIT("      \"%s\"%s\n",
518          (((const struct jitterc_specialized_instruction*)
519            gl_list_get_at (vm->specialized_instructions, i))->name),
520          comma);
521   EMIT("    };\n");
522   jitterc_fclose (f);
523 }
524 
525 static void
jitterc_emit_specialized_instruction_residual_arities(const struct jitterc_vm * vm)526 jitterc_emit_specialized_instruction_residual_arities
527    (const struct jitterc_vm *vm)
528 {
529   FILE *f = jitterc_fopen_a_basename (vm, "vm1.c");
530   EMIT("// #include <stdlib.h>\n\n");
531   EMIT("// #include \"vmprefix-specialized-instructions.h\"\n");
532   EMIT("const size_t\n");
533   EMIT("vmprefix_specialized_instruction_residual_arities [VMPREFIX_SPECIALIZED_INSTRUCTION_NO]\n");
534   EMIT("  = {\n");
535   int i; char *comma;
536   FOR_LIST(i, comma, vm->specialized_instructions)
537     {
538       const struct jitterc_specialized_instruction* sins
539         = ((const struct jitterc_specialized_instruction*)
540            gl_list_get_at (vm->specialized_instructions, i));
541       size_t residual_arity = 0;
542       int j;
543       for (j = 0; j < gl_list_size (sins->specialized_arguments); j ++)
544         if (((const struct jitterc_specialized_argument*)
545              gl_list_get_at (sins->specialized_arguments, j))->residual)
546           residual_arity ++;
547       EMIT("      %i%s /* %s */\n", (int)residual_arity, comma, sins->name);
548     }
549   EMIT("    };\n");
550   jitterc_fclose (f);
551 }
552 
553 /* This factors the implementation of
554    jitterc_emit_specialized_instruction_label_bitmasks and
555    jitterc_emit_specialized_instruction_fast_label_bitmasks . */
556 static void
jitterc_emit_specialized_instruction_label_bitmasks_possibly_fast(const struct jitterc_vm * vm,bool fast)557 jitterc_emit_specialized_instruction_label_bitmasks_possibly_fast
558    (const struct jitterc_vm *vm,
559     bool fast)
560 {
561   FILE *f = jitterc_fopen_a_basename (vm, "vm1.c");
562   if (fast)
563     EMIT("#ifdef JITTER_HAVE_PATCH_IN\n");
564   EMIT("const unsigned long // FIXME: shall I use a shorter type when possible?\n");
565   EMIT("vmprefix_specialized_instruction_%slabel_bitmasks [VMPREFIX_SPECIALIZED_INSTRUCTION_NO]\n",
566        fast ? "fast_" : "");
567   EMIT("  = {\n");
568   EMIT("      /* It's important that !BEGINBASICBLOCK has a zero here: it does not need residual patching. */\n");
569   int i; char *comma;
570   FOR_LIST(i, comma, vm->specialized_instructions)
571     {
572       const struct jitterc_specialized_instruction* sins
573         = ((const struct jitterc_specialized_instruction*)
574            gl_list_get_at (vm->specialized_instructions, i));
575       EMIT("      0");
576       int j;
577       int residual_counter = 0;
578       for (j = 0; j < gl_list_size (sins->specialized_arguments); j ++)
579         {
580           const struct jitterc_specialized_argument *sarg
581             = ((const struct jitterc_specialized_argument*)
582                gl_list_get_at (sins->specialized_arguments, j));
583           if (! sarg->residual)
584             continue;
585           bool has_a_one;
586           if (fast)
587             has_a_one
588               = sarg->kind == jitterc_instruction_argument_kind_fast_label;
589           else
590             has_a_one
591               =     sarg->kind == jitterc_instruction_argument_kind_label
592                  || sarg->kind == jitterc_instruction_argument_kind_fast_label;
593           if (has_a_one)
594             EMIT(" | (1UL << %i)", residual_counter);
595 
596           residual_counter ++;
597         }
598       EMIT("%s /* %s */\n", comma, sins->name);
599     }
600   EMIT("    };\n");
601   if (fast)
602     EMIT("#endif // #ifdef JITTER_HAVE_PATCH_IN\n\n");
603   jitterc_fclose (f);
604 }
605 static void
jitterc_emit_specialized_instruction_label_bitmasks(const struct jitterc_vm * vm)606 jitterc_emit_specialized_instruction_label_bitmasks (const struct jitterc_vm *vm)
607 {
608   jitterc_emit_specialized_instruction_label_bitmasks_possibly_fast (vm, false);
609 }
610 static void
jitterc_emit_specialized_instruction_fast_label_bitmasks(const struct jitterc_vm * vm)611 jitterc_emit_specialized_instruction_fast_label_bitmasks (const struct jitterc_vm *vm)
612 {
613   jitterc_emit_specialized_instruction_label_bitmasks_possibly_fast (vm, true);
614 }
615 
616 
617 
618 
619 /* Code generation utility.
620  * ************************************************************************** */
621 
622 /* Emit a #line directive referring the Jitter VM specification source file,
623    unless #line-generation was disabled and unless enable_hash_line is false.
624    Rationale: according to the C Standard # preprocessor directives must not
625    appear within macro arguments, and the enable_hash_line argument provides an
626    easy way of disabling #line directives in such contexts, without having
627    explicit conditionals in callers. */
628 static void
jitterc_emit_hash_line(FILE * f,const struct jitterc_vm * vm,int line_no,bool enable_hash_line)629 jitterc_emit_hash_line (FILE *f, const struct jitterc_vm *vm, int line_no,
630                         bool enable_hash_line)
631 {
632   if (vm->generate_line && enable_hash_line)
633     EMIT("#line %i \"%s\"\n", line_no, vm->source_file_name);
634 }
635 
636 
637 
638 
639 /* More complex code generation.
640  * ************************************************************************** */
641 
642 static void
jitterc_emit_specialized_instruction_relocatables(const struct jitterc_vm * vm)643 jitterc_emit_specialized_instruction_relocatables
644    (const struct jitterc_vm *vm)
645 {
646   FILE *f = jitterc_fopen_a_basename (vm, "vm1.c");
647 
648   EMIT("// FIXME: I may want to conditionalize this.\n");
649   EMIT("const bool\n");
650   EMIT("vmprefix_specialized_instruction_relocatables [VMPREFIX_SPECIALIZED_INSTRUCTION_NO]\n");
651   EMIT("  = {\n");
652   int i; char *comma;
653   FOR_LIST(i, comma, vm->specialized_instructions)
654     {
655       const struct jitterc_specialized_instruction* sins
656         = ((const struct jitterc_specialized_instruction*)
657            gl_list_get_at (vm->specialized_instructions, i));
658       bool relocatable = (sins->relocatability
659                           == jitterc_relocatability_relocatable);
660       EMIT("      %s%s // %s\n",
661            relocatable ? "true" : "false",
662            comma,
663            sins->name);
664     }
665   EMIT("    };\n\n");
666   jitterc_fclose (f);
667 }
668 
669 /* Emit the definition of a bool vector, one element per specialized instruction,
670    each element being true iff the corresponding instruction is a caller/callee. */
671 static void
jitterc_emit_specialized_instruction_callers_or_callees(const struct jitterc_vm * vm,bool callers)672 jitterc_emit_specialized_instruction_callers_or_callees
673   (const struct jitterc_vm *vm,
674    bool callers)
675 {
676   FILE *f = jitterc_fopen_a_basename (vm, "vm1.c");
677   char *name = callers ? "callers" : "callees";
678 
679   EMIT("// FIXME: this is not currently accessed, and in fact may be useless.\n");
680   EMIT("const bool\n");
681   EMIT("vmprefix_specialized_instruction_%s [VMPREFIX_SPECIALIZED_INSTRUCTION_NO]\n",
682        name);
683   EMIT("  = {\n");
684   int i; char *comma;
685   FOR_LIST(i, comma, vm->specialized_instructions)
686     {
687       const struct jitterc_specialized_instruction* sins
688         = ((const struct jitterc_specialized_instruction*)
689            gl_list_get_at (vm->specialized_instructions, i));
690       bool value;
691       if (sins->instruction == NULL)
692         value = false;
693       else if (callers)
694         value = (sins->instruction->callerness == jitterc_callerness_caller);
695       else
696         value = (sins->instruction->calleeness == jitterc_calleeness_callee);
697       EMIT("      %s%s // %s\n", value ? "true" : "false", comma, sins->name);
698     }
699   EMIT("    };\n\n");
700   jitterc_fclose (f);
701 }
702 
703 /* Emit the definition of a bool vector, one element per specialized instruction,
704    each element being true iff the corresponding instruction is a caller. */
705 static void
jitterc_emit_specialized_instruction_callers(const struct jitterc_vm * vm)706 jitterc_emit_specialized_instruction_callers
707    (const struct jitterc_vm *vm)
708 {
709   jitterc_emit_specialized_instruction_callers_or_callees (vm, true);
710 }
711 
712 /* Emit the definition of a bool vector, one element per specialized instruction,
713    each element being true iff the corresponding instruction is a callee. */
714 static void
jitterc_emit_specialized_instruction_callees(const struct jitterc_vm * vm)715 jitterc_emit_specialized_instruction_callees
716    (const struct jitterc_vm *vm)
717 {
718   jitterc_emit_specialized_instruction_callers_or_callees (vm, false);
719 }
720 
721 /* Emit the definition of an array whose indices are specialised instruction
722    opcode, and whose elements are the corresponding unspecialised instructions
723    opcodes -- or -1 when there is no mapping. */
724 static void
jitterc_emit_specialized_instruction_to_unspecialized_instruction(const struct jitterc_vm * vm)725 jitterc_emit_specialized_instruction_to_unspecialized_instruction
726    (const struct jitterc_vm *vm)
727 {
728   FILE *f = jitterc_fopen_a_basename (vm, "vm1.c");
729 
730   EMIT("/* An array whose indices are specialised instruction opcodes, and\n");
731   EMIT("   whose elements are the corresponding unspecialised instructions\n");
732   EMIT("   opcodes -- or -1 when there is no mapping mapping having */\n");
733   EMIT("const int\n");
734   EMIT("vmprefix_specialized_instruction_to_unspecialized_instruction\n");
735   EMIT("   [VMPREFIX_SPECIALIZED_INSTRUCTION_NO]\n");
736   EMIT("  = {\n");
737   int i; char *comma;
738   FOR_LIST(i, comma, vm->specialized_instructions)
739     {
740       const struct jitterc_specialized_instruction* sins
741         = ((const struct jitterc_specialized_instruction*)
742            gl_list_get_at (vm->specialized_instructions, i));
743       if (sins->instruction == NULL)
744         EMIT("    -1%s /* %s */\n", comma, sins->name);
745       else
746         EMIT("    vmprefix_meta_instruction_id_%s%s /* %s */\n",
747              sins->instruction->mangled_name, comma, sins->name);
748     }
749   EMIT("    };\n\n");
750   jitterc_fclose (f);
751 }
752 
753 /* Emit the worst-case defect table for the pointed VM. */
754 static void
jitterc_emit_worst_case_defect_table(const struct jitterc_vm * vm)755 jitterc_emit_worst_case_defect_table (const struct jitterc_vm *vm)
756 {
757   FILE *f = jitterc_fopen_a_basename (vm, "vm1.c");
758   EMIT("#ifdef JITTER_HAVE_PATCH_IN\n");
759   EMIT("/* Worst-case defect table. */\n");
760   EMIT("const jitter_uint\n");
761   EMIT("vmprefix_worst_case_defect_table [] =\n");
762   EMIT("  {\n");
763   int i; char *comma;
764   FOR_LIST(i, comma, vm->specialized_instructions)
765     {
766       const struct jitterc_specialized_instruction* sins
767         = ((const struct jitterc_specialized_instruction*)
768            gl_list_get_at (vm->specialized_instructions, i));
769       if (sins->has_as_replacement == NULL)
770         EMIT("    vmprefix_specialized_instruction_opcode_%s%s /* NOT potentially defective. */\n",
771              sins->mangled_name, comma);
772       else
773         EMIT("    /*vmprefix_specialized_instruction_opcode__eINVALID*/vmprefix_specialized_instruction_opcode_%s%s /* POTENTIALLY DEFECTIVE. */\n",
774              sins->has_as_replacement->mangled_name, comma);
775     }
776   EMIT("  };\n");
777   EMIT("#endif // #ifdef JITTER_HAVE_PATCH_IN\n");
778   EMIT("\n\n");
779   jitterc_fclose (f);
780 }
781 
782 
783 
784 
785 /* Rewriter generation.
786  * ************************************************************************** */
787 
788 /* Emit code for the pointed template expression to the pointed stream for the
789    pointed VM; the generated C code evaluates to a literal if
790    evaluate_to_literal is true, otherwise it evaluates to an instruction
791    argument.  This is to be used both in rules bodies for instantiating template
792    expression and within a condition for evaluating a rule guard -- but the
793    output is not a condition.
794    About enable_hash_line, see the comment before jitterc_emit_hash_line .  */
795 static void
jitterc_emit_rewrite_rule_template_expression(FILE * f,const struct jitterc_vm * vm,const struct jitterc_template_expression * te,bool evaluate_to_literal,bool enable_hash_line)796 jitterc_emit_rewrite_rule_template_expression
797    (FILE *f,
798     const struct jitterc_vm *vm,
799     const struct jitterc_template_expression *te,
800     bool evaluate_to_literal,
801     bool enable_hash_line)
802 {
803   /* Generate a #line directive for the template expression, indepdendently from
804      its shape. */
805   jitterc_emit_hash_line(f, vm, te->line_no, enable_hash_line);
806 
807   /* Generate different code according to the AST case. */
808   switch (te->case_)
809     {
810     case jitterc_instruction_argument_expression_case_boolean_constant:
811       if (! evaluate_to_literal)
812         jitter_fatal ("template expression: unexpected boolean constant");
813       EMIT("      %s\n", te->constant.fixnum ? "true" : "false");
814       break;
815 
816     case jitterc_instruction_argument_expression_case_fixnum_constant:
817       if (! evaluate_to_literal)
818         jitter_fatal ("template expression: unexpected fixnum constant");
819       EMIT("      %"JITTER_PRIi"\n", te->constant.fixnum);
820       break;
821 
822     case jitterc_instruction_argument_expression_case_placeholder:
823       if (evaluate_to_literal)
824         EMIT("      JITTER_RULE_LITERAL_FIELD(JITTER_PLACEHOLDER_NAME(%s))\n",
825              te->placeholder);
826       else
827         EMIT("      JITTER_PLACEHOLDER_NAME(%s)\n", te->placeholder);
828       break;
829 
830     case jitterc_instruction_argument_expression_case_operation:
831       {
832         int i; char *comma;
833         EMIT("#warning: operators (here \"%s\") not really implemented yet\n",
834              te->operator->name);
835         /* Convert the operator name to upper case, to emit it as part of a C
836            macro name. */
837         char operator_name_uppercase [1000];
838         for (i = 0; te->operator->name [i] != '\0'; i ++)
839           operator_name_uppercase [i] = toupper (te->operator->name [i]);
840         operator_name_uppercase [i] = '\0';
841 
842         EMIT("      JITTER_RULE_EXPRESSION_%s(\n", operator_name_uppercase);
843         FOR_LIST(i, comma, te->operand_expressions)
844           {
845             const struct jitterc_template_expression *oe
846               = gl_list_get_at (te->operand_expressions, i);
847             bool literal_expected = true; // FIXME: compute it for real.
848             jitterc_emit_rewrite_rule_template_expression (f, vm, oe,
849                                                            literal_expected,
850                                                            false);
851             EMIT("                                %s\n", comma);
852           }
853         EMIT("                               )\n");
854         break;
855       }
856 
857     default:
858       jitter_fatal ("impossible template expression case");
859     }
860 }
861 
862 /* Emit a condition matching the argument_idx-th argument of the
863    instruction_idx-th instruction (both 0-based) of the candidate instructions,
864    to the pointed stream for the pointed VM.
865    The generated code assumes that the opcode have already been matched, so the
866    arity is correct. */
867 static void
jitterc_emit_rewrite_rule_argument_condition(FILE * f,const struct jitterc_vm * vm,int instruction_idx,int argument_idx,const struct jitterc_argument_pattern * ap)868 jitterc_emit_rewrite_rule_argument_condition
869    (FILE *f,
870     const struct jitterc_vm *vm,
871     int instruction_idx,
872     int argument_idx,
873     const struct jitterc_argument_pattern *ap)
874 {
875   /* Generate a #line directive for the argument pattern, indepdendently from
876      its shape. */
877   jitterc_emit_hash_line(f, vm, ap->line_no, true);
878 
879   /* If the argument pattern specifies a literal, check that it matches.  This
880      is a good check to make first, as it will fail frequently.  This check also
881      currently includes a check on the kind (required literal), subsumed by the
882      kind checks below; anyway GCC should have no problem merging them into one
883      conditional, since there are no side effects in between.  */
884   if (ap->has_literal)
885     EMIT("    JITTER_RULE_CONDITION_MATCH_LITERAL_ARGUMENT(%i, %i, %"
886          JITTER_PRIi ")\n",
887          instruction_idx, argument_idx, ap->literal.fixnum);
888 
889   /* If a kind bitmask is specified, check it. */
890   if (ap->kind != jitterc_instruction_argument_kind_unspecified)
891     {
892       /* A kind is a bitmask, and we accept any one match with a bit.  This
893          means that the alternatives are in logical or.  Using C's infix || is
894          more convenient here than our non-variadic prefix macros. */
895       EMIT("    JITTER_RULE_CONDITION(false\n");
896       if (ap->kind & jitterc_instruction_argument_kind_register)
897         EMIT("                          || JITTER_RULE_ARGUMENT_IS_A_REGISTER(%i, %i)\n",
898              instruction_idx, argument_idx);
899       if (ap->kind & jitterc_instruction_argument_kind_literal)
900         EMIT("                          || JITTER_RULE_ARGUMENT_IS_A_LITERAL(%i, %i)\n",
901              instruction_idx, argument_idx);
902       if (ap->kind & jitterc_instruction_argument_kind_label)
903         EMIT("                          || JITTER_RULE_ARGUMENT_IS_A_LABEL(%i, %i)\n",
904              instruction_idx, argument_idx);
905       /* Close the logical or. */
906       EMIT("                         )\n");
907     }
908 
909   /* Match against a placeholder (destructively), if a placeholder name is
910      given. */
911   if (ap->placeholder_or_NULL != NULL)
912     EMIT("    JITTER_RULE_CONDITION_MATCH_PLACEHOLDER(%i, %i, %s)\n",
913          instruction_idx, argument_idx, ap->placeholder_or_NULL);
914 }
915 
916 /* Generate content for the condition section of the pointed rewrite rule for
917    the pointed VM to the pointed stream. */
918 static void
jitterc_emit_rewrite_rule_condition(FILE * f,const struct jitterc_vm * vm,const struct jitterc_rule * rule)919 jitterc_emit_rewrite_rule_condition (FILE *f, const struct jitterc_vm *vm,
920                                      const struct jitterc_rule *rule)
921 {
922   int i, j; char *comma __attribute__ ((unused));
923 
924   /* Check that the opcode of every candidate instruction matches its
925      pattern. */
926   EMIT("    /* Check opcodes first: they are likely not to match, and in */\n");
927   EMIT("    /* that case we want to fail as early as possible. */\n");
928   FOR_LIST(i, comma, rule->in_instruction_patterns)
929     {
930       const struct jitterc_instruction_pattern *ip
931         = gl_list_get_at (rule->in_instruction_patterns, i);
932       char *opcode = ip->instruction_name;
933       char *mangled_opcode = jitterc_mangle (opcode);
934       jitterc_emit_hash_line(f, vm, ip->line_no, true);
935       EMIT("    JITTER_RULE_CONDITION_MATCH_OPCODE(%i, %s)\n",
936            i, mangled_opcode);
937       free (mangled_opcode);
938     }
939 
940   /* Then check instruction arguments against the template, binding placeholders
941      in the process. */
942   EMIT("    /* Check arguments, binding placeholders.  We don't have to worry */\n");
943   EMIT("    /* about arity, since the opcodes match if we're here. */\n");
944   FOR_LIST(i, comma, rule->in_instruction_patterns)
945     {
946       const struct jitterc_instruction_pattern *ip
947         = gl_list_get_at (rule->in_instruction_patterns, i);
948       FOR_LIST(j, comma, ip->argument_patterns)
949         {
950           const struct jitterc_argument_pattern *ap
951             = gl_list_get_at (ip->argument_patterns, j);
952           jitterc_emit_rewrite_rule_argument_condition (f, vm, i, j, ap);
953         }
954     }
955 
956   /* Emit the guard at the end, as it may use any placeholder.  If that succeeds
957      as well the condition is satisfied. */
958   EMIT("    /* Rule guard. */\n");
959   EMIT("    JITTER_RULE_CONDITION(\n");
960   jitterc_emit_rewrite_rule_template_expression (f, vm, rule->guard, true,
961                                                  false);
962   EMIT("                         )\n");
963 }
964 
965 /* Generate code for the pointed instruction template for the pointed VM to the
966    pointed stream.  This is to be used within the body section of rules. */
967 void
jitterc_emit_rewrite_rule_instruction_template(FILE * f,const struct jitterc_vm * vm,const struct jitterc_instruction_template * it)968 jitterc_emit_rewrite_rule_instruction_template
969    (FILE *f,
970     const struct jitterc_vm *vm,
971     const struct jitterc_instruction_template *it)
972 {
973   /* Emit a #line directive for the instruction template. */
974   jitterc_emit_hash_line(f, vm, it->line_no, true);
975 
976   /* Emit code to add the opcode. */
977   EMIT("    //fprintf (stderr, \"    rewrite: adding instruction %s\\n\");\n",
978        it->instruction_name);
979   char *mangled_opcode = jitterc_mangle (it->instruction_name);
980   EMIT("    JITTER_RULE_APPEND_INSTRUCTION_(%s);\n", mangled_opcode);
981   free (mangled_opcode);
982 
983   /* Emit code to add the instantiation of every argument template. */
984   int i; char *comma __attribute__ ((unused));
985   FOR_LIST(i, comma, it->argument_expressions)
986     {
987       const struct jitterc_template_expression *ae
988         = gl_list_get_at (it->argument_expressions, i);
989       EMIT("    //fprintf (stderr, \"    instantiating the %i-th argument of %s\\n\");\n",
990            i, it->instruction_name);
991 
992       // FIXME: make a rewriting-specific macro instead of using
993       // jitter_mutable_routine_append_parameter_copy ?
994       EMIT("    jitter_mutable_routine_append_parameter_copy (jitter_mutable_routine_p,\n");
995       jitterc_emit_rewrite_rule_template_expression (f, vm, ae, false, true);
996       EMIT("                                 );\n");
997     }
998 }
999 
1000 /* Generate code for the pointed rewrite rule for the pointed VM to the pointed
1001    stream. */
1002 static void
jitterc_emit_rewrite_rule(FILE * f,const struct jitterc_vm * vm,const struct jitterc_rule * rule)1003 jitterc_emit_rewrite_rule (FILE *f, const struct jitterc_vm *vm,
1004                            const struct jitterc_rule *rule)
1005 {
1006   int i; char *comma __attribute__ ((unused));
1007 
1008   EMIT("/* Rewrite rule \"%s\" */\n", rule->name);
1009   int head_size = gl_list_size (rule->in_instruction_patterns);
1010 
1011   /* Open the rule section. */
1012   jitterc_emit_hash_line(f, vm, rule->line_no, true);
1013   EMIT("JITTER_RULE_BEGIN(%i)\n", head_size);
1014 
1015   /* Emit the placeholder declaration section. */
1016   EMIT("  JITTER_RULE_BEGIN_PLACEHOLDER_DECLARATIONS\n");
1017   FOR_LIST(i, comma, rule->placeholders)
1018     {
1019       const char *placeholder = gl_list_get_at (rule->placeholders, i);
1020       EMIT("    JITTER_RULE_DECLARE_PLACEHOLDER_(%s);\n",
1021            placeholder);
1022     }
1023   EMIT("  JITTER_RULE_END_PLACEHOLDER_DECLARATIONS\n");
1024 
1025   /* Emit the placeholder declaration section. */
1026   EMIT("  JITTER_RULE_BEGIN_CONDITIONS\n");
1027   jitterc_emit_rewrite_rule_condition (f, vm, rule);
1028   EMIT("  JITTER_RULE_END_CONDITIONS\n");
1029 
1030   /* Emit the placeholder cloning section. */
1031   EMIT("  JITTER_RULE_BEGIN_PLACEHOLDER_CLONING\n");
1032   FOR_LIST(i, comma, rule->placeholders)
1033     {
1034       const char *placeholder = gl_list_get_at (rule->placeholders, i);
1035       EMIT("    JITTER_RULE_CLONE_PLACEHOLDER_(%s);\n",
1036            placeholder);
1037     }
1038   EMIT("  JITTER_RULE_END_PLACEHOLDER_CLONING\n");
1039 
1040   /* Emit the rule body, by compiling instruction templates one after the
1041      other. */
1042   EMIT("  JITTER_RULE_BEGIN_BODY\n");
1043   EMIT("  //fprintf (stderr, \"* The rule %s (line %i) fires...\\n\");\n",
1044        rule->name, rule->line_no);
1045   FOR_LIST(i, comma, rule->out_instruction_templates)
1046     {
1047       const struct jitterc_instruction_template *it
1048         = gl_list_get_at (rule->out_instruction_templates, i);
1049       jitterc_emit_rewrite_rule_instruction_template (f, vm, it);
1050     }
1051   EMIT("    //fprintf (stderr, \"  ...End of the rule %s\\n\");\n",
1052        rule->name);
1053   EMIT("  JITTER_RULE_END_BODY\n");
1054 
1055   /* Emit the placeholder destruction section. */
1056   EMIT("  JITTER_RULE_BEGIN_PLACEHOLDER_DESTRUCTION\n");
1057   FOR_LIST(i, comma, rule->placeholders)
1058     {
1059       const char *placeholder = gl_list_get_at (rule->placeholders, i);
1060       EMIT("    JITTER_RULE_DESTROY_PLACEHOLDER_(%s);\n",
1061            placeholder);
1062     }
1063   EMIT("  JITTER_RULE_END_PLACEHOLDER_DESTRUCTION\n");
1064 
1065   /* Close the rule section, and we're done. */
1066   EMIT("JITTER_RULE_END\n");
1067   EMIT("\n");
1068 }
1069 
1070 static void
jitterc_emit_rewriter(const struct jitterc_vm * vm)1071 jitterc_emit_rewriter (const struct jitterc_vm *vm)
1072 {
1073   FILE *f = jitterc_fopen_a_basename (vm, "vm1.c");
1074 
1075   EMIT("void\n");
1076   EMIT("vmprefix_rewrite (struct jitter_mutable_routine *jitter_mutable_routine_p)\n");
1077   EMIT("{\n");
1078 
1079   /* Add the common prolog, defining variables to be visible to the entire
1080      function body. */
1081   EMIT("  JITTTER_REWRITE_FUNCTION_PROLOG_;\n");
1082   EMIT("\n");
1083 
1084   /* Add user-specified code for the rewriter. */
1085   jitterc_emit_user_c_code_to_stream (vm, f, vm->rewriter_c_code, "rewriter");
1086   EMIT("\n");
1087 
1088   /* Generate code for the rules. */
1089   int i; char *comma __attribute__ ((unused));
1090   FOR_LIST(i, comma, vm->rewrite_rules)
1091     {
1092       const struct jitterc_rule *rule
1093         = ((const struct jitterc_rule*)
1094            gl_list_get_at (vm->rewrite_rules, i));
1095       EMIT("//asm volatile (\"\\n# checking %s\");\n", rule->name);
1096       EMIT("//fprintf (stderr, \"Trying rule %i of %i, \\\"%s\\\" (line %i)\\n\");\n",
1097            i + 1, (int) gl_list_size (vm->rewrite_rules),
1098            rule->name,
1099            rule->line_no);
1100       jitterc_emit_rewrite_rule (f, vm, rule);
1101     }
1102   EMIT("//fprintf (stderr, \"No more rules to try\\n\");\n");
1103 
1104   EMIT("}\n");
1105   EMIT("\n\n");
1106   jitterc_fclose (f);
1107 }
1108 
1109 
1110 
1111 
1112 /* Specializer generation.
1113  * ************************************************************************** */
1114 
1115 static void
jitterc_emit_specializer_recognizer_prototypes(FILE * f,const struct jitterc_specialized_instruction_tree * tree)1116 jitterc_emit_specializer_recognizer_prototypes
1117    (FILE *f,
1118     const struct jitterc_specialized_instruction_tree* tree)
1119 {
1120   EMIT("inline static enum vmprefix_specialized_instruction_opcode\n");
1121   EMIT("vmprefix_recognize_specialized_instruction_%s (struct jitter_parameter ** const ps,\n",
1122        tree->prefix_mangled_name);
1123   EMIT("                                               bool enable_fast_literals)\n");
1124   EMIT("  __attribute__ ((pure));\n");
1125   int i;
1126   for (i = 0; i < gl_list_size (tree->children); i ++)
1127     {
1128       const struct jitterc_specialized_instruction_tree_child *sarg_and_child
1129         = ((const struct jitterc_specialized_instruction_tree_child *)
1130            gl_list_get_at (tree->children, i));
1131       jitterc_emit_specializer_recognizer_prototypes (f, sarg_and_child->child);
1132     }
1133 }
1134 
1135 static void
jitterc_emit_specializer_recognizers(FILE * f,const struct jitterc_vm * vm,const struct jitterc_specialized_instruction_tree * tree)1136 jitterc_emit_specializer_recognizers
1137    (FILE *f,
1138     const struct jitterc_vm *vm,
1139     const struct jitterc_specialized_instruction_tree* tree)
1140 {
1141   EMIT("inline static enum vmprefix_specialized_instruction_opcode\n");
1142   EMIT("vmprefix_recognize_specialized_instruction_%s (struct jitter_parameter ** const ps,\n",
1143        tree->prefix_mangled_name);
1144   EMIT("                                               bool enable_fast_literals)\n");
1145   EMIT("{\n");
1146   if (gl_list_size (tree->children) == 0)
1147     {
1148       EMIT("  /* The prefix is a full specialized instruction.  We're done recognizing it. */\n");
1149       if (tree->specialized_instruction == NULL)
1150         EMIT("  jitter_fatal (\"No specialised instruction exists to \"\n"
1151              "                \"complete %s/... (zero fast registers and no \"\n"
1152              "                \"slow registers?)\");\n",
1153              tree->prefix_name);
1154       else
1155         EMIT("  return vmprefix_specialized_instruction_opcode_%s;\n",
1156              tree->specialized_instruction->mangled_name);
1157       EMIT("}\n\n");
1158       /* There's nothing more in this subtree. */
1159       return;
1160     }
1161 
1162   EMIT("  enum vmprefix_specialized_instruction_opcode res = vmprefix_specialized_instruction_opcode_%s;\n",
1163        jitterc_mangle ("!INVALID"));
1164   int i;
1165   for (i = 0; i < gl_list_size (tree->children); i ++)
1166     {
1167       const struct jitterc_specialized_instruction_tree_child *sarg_and_child
1168         = ((const struct jitterc_specialized_instruction_tree_child *)
1169            gl_list_get_at (tree->children, i));
1170       const struct jitterc_specialized_argument *sarg
1171         = sarg_and_child->specialized_argument;
1172       const struct jitterc_specialized_instruction_tree *child
1173         = sarg_and_child->child;
1174       EMIT("  if ((");
1175       switch (sarg->kind)
1176         {
1177         case jitterc_instruction_argument_kind_literal:
1178           EMIT("(* ps)->type == jitter_parameter_type_literal");
1179           if (! sarg->residual)
1180             // FIXME: this will need generatilzation with more literal types.
1181             EMIT(" && (* ps)->literal.fixnum == %li && enable_fast_literals",
1182                  (long) sarg->nonresidual_literal->value.fixnum);
1183           break;
1184         case jitterc_instruction_argument_kind_register:
1185           EMIT("(* ps)->type == jitter_parameter_type_register_id");
1186           // FIXME: this will need generatilzation with more register classes; or, more likely, not.
1187           if (! sarg->residual)
1188             EMIT(" && (* ps)->register_index == %u",
1189                  (unsigned) sarg->nonresidual_register->index);
1190           break;
1191         case jitterc_instruction_argument_kind_label:
1192         case jitterc_instruction_argument_kind_fast_label:
1193           EMIT("(* ps)->type == jitter_parameter_type_label");
1194           if (! sarg->residual)
1195             jitter_fatal ("non-residual label: this should not happen");
1196           break;
1197         default:
1198           jitter_fatal ("jitterc_emit_specializer_recognizers: unhandled kind");
1199         }
1200       EMIT(")\n");
1201       EMIT("      && (res = vmprefix_recognize_specialized_instruction_%s (ps + 1, enable_fast_literals)))\n",
1202            child->prefix_mangled_name);
1203       EMIT("    goto done;\n");
1204     }
1205   EMIT("done:\n");
1206   EMIT("  return res;\n");
1207   EMIT("}\n\n");
1208 
1209   /* Generate definitions for every subtree. */
1210   for (i = 0; i < gl_list_size (tree->children); i ++)
1211     {
1212       const struct jitterc_specialized_instruction_tree_child *sarg_and_child
1213         = ((const struct jitterc_specialized_instruction_tree_child *)
1214            gl_list_get_at (tree->children, i));
1215       jitterc_emit_specializer_recognizers (f, vm, sarg_and_child->child);
1216     }
1217 }
1218 
1219 static void
jitterc_emit_specializer(const struct jitterc_vm * vm)1220 jitterc_emit_specializer (const struct jitterc_vm *vm)
1221 {
1222   FILE *f = jitterc_fopen_a_basename (vm, "vm1.c");
1223   EMIT("//#include <jitter/jitter-fatal.h>\n");
1224   EMIT("\n");
1225   EMIT("//#include <jitter/jitter.h>\n");
1226   EMIT("//#include <jitter/jitter-instruction.h>\n");
1227   EMIT("//#include <jitter/jitter-specialize.h>\n");
1228   EMIT("\n");
1229   EMIT("//#include \"vmprefix-vm.h\"\n");
1230   EMIT("//#include \"vmprefix-meta-instructions.h\"\n");
1231   EMIT("//#include \"vmprefix-specialized-instructions.h\"\n");
1232   EMIT("\n\n");
1233   EMIT("/* Recognizer function prototypes. */\n");
1234   int i; char *comma __attribute__ ((unused));
1235 #define LET_TREE                                               \
1236     const struct jitterc_specialized_instruction_tree *tree    \
1237       = ((const struct jitterc_specialized_instruction_tree*)  \
1238          gl_list_get_at (vm->specialized_instruction_forest, i))
1239   /* First generate a function prototype per specialized instruction prefix
1240      recognizer.  I want to declare them all before the first definition, to
1241      be able to call the functions in any order. */
1242   FOR_LIST(i, comma, vm->specialized_instruction_forest)
1243     {
1244       LET_TREE;
1245       jitterc_emit_specializer_recognizer_prototypes (f, tree);
1246     }
1247   EMIT("\n\n");
1248 
1249   /* Generate the actual definitions. */
1250   EMIT("/* Recognizer function definitions. */\n");
1251   FOR_LIST(i, comma, vm->specialized_instruction_forest)
1252     {
1253       LET_TREE;
1254       jitterc_emit_specializer_recognizers (f, vm, tree);
1255     }
1256 #undef LET_TREE
1257   EMIT("\n\n");
1258 
1259   /* Generate the main recognizer function. */
1260   EMIT("/* Recognizer entry point. */\n");
1261   EMIT("static enum vmprefix_specialized_instruction_opcode\n");
1262   EMIT("vmprefix_recognize_specialized_instruction (struct jitter_mutable_routine *p,\n");
1263   EMIT("                                            const struct jitter_instruction *ins)\n");
1264   EMIT("{\n");
1265   EMIT("  bool fl = ! p->options.slow_literals_only;\n");
1266   EMIT("  const struct jitter_meta_instruction *mi = ins->meta_instruction;\n");
1267   EMIT("  switch (mi->id)\n");
1268   EMIT("    {\n");
1269   FOR_LIST(i, comma, vm->instructions)
1270     {
1271       const struct jitterc_instruction* ins
1272         = ((const struct jitterc_instruction*)
1273            gl_list_get_at (vm->instructions, i));
1274       EMIT("    case vmprefix_meta_instruction_id_%s:\n", ins->mangled_name);
1275       EMIT("      return vmprefix_recognize_specialized_instruction_%s (ins->parameters, fl);\n",
1276            ins->mangled_name);
1277     }
1278   EMIT("    default:\n");
1279   EMIT("      jitter_fatal (\"invalid meta-instruction id %%i\", (int)mi->id);\n");
1280   EMIT("    }\n");
1281   EMIT("  __builtin_unreachable ();\n");
1282   EMIT("}\n\n");
1283 
1284   /* Generate the specializer function. */
1285   EMIT("/* Specializer entry point: the only non-static function here. */\n");
1286   EMIT("int\n");
1287   EMIT("vmprefix_specialize_instruction (struct jitter_mutable_routine *p,\n");
1288   EMIT("                                 const struct jitter_instruction *ins)\n");
1289   EMIT("{\n");
1290   EMIT("  enum vmprefix_specialized_instruction_opcode opcode\n");
1291   EMIT("    = vmprefix_recognize_specialized_instruction (p, ins);\n");
1292   EMIT("  if (opcode == vmprefix_specialized_instruction_opcode_%s)\n",
1293        jitterc_mangle ("!INVALID"));
1294   EMIT("    jitter_fatal (\"specialization failed: %%s\", ins->meta_instruction->name);\n");
1295   EMIT("\n");
1296   EMIT("#ifdef JITTER_HAVE_PATCH_IN\n");
1297   EMIT("  /* Replace the opcode with its non-defective counterpart. */\n");
1298   EMIT("  opcode = vmprefix_defect_table [opcode];\n");
1299   EMIT("#endif // #ifdef JITTER_HAVE_PATCH_IN\n");
1300   EMIT("\n");
1301   EMIT("  jitter_add_specialized_instruction_opcode (p, opcode);\n");
1302   EMIT("\n");
1303   EMIT("\n");
1304   EMIT("  /* FIXME: in the old shell-based generator I grouped specialized instructions by\n");
1305   EMIT("     their \"residual parameter map\", yielding a switch with a lot of different\n");
1306   EMIT("     specialized instructions mapping to the same case.  I should redo that here. */\n");
1307   EMIT("  switch (opcode)\n");
1308   EMIT("    {\n");
1309   FOR_LIST(i, comma, vm->specialized_instructions)
1310     {
1311       const struct jitterc_specialized_instruction* sins
1312         = ((const struct jitterc_specialized_instruction*)
1313            gl_list_get_at (vm->specialized_instructions, i));
1314       EMIT("    case vmprefix_specialized_instruction_opcode_%s:\n", sins->mangled_name);
1315       const struct jitterc_instruction* uins = sins->instruction;
1316 
1317       /* Emit code to add residual residual arguments to the threads, except for
1318          the last arguments of non-relocatable and caller instructions, which
1319          are special. */
1320       size_t residual_no = gl_list_size (sins->specialized_arguments);
1321       bool is_non_relocatable
1322         = (   uins != NULL
1323            && sins->relocatability == jitterc_relocatability_non_relocatable);
1324       bool is_caller
1325         = (   uins != NULL
1326            && uins->callerness == jitterc_callerness_caller);
1327       if (is_non_relocatable || is_caller)
1328         residual_no --;
1329       int j;
1330       for (j = 0; j < residual_no; j ++)
1331         {
1332           const struct jitterc_specialized_argument* sarg
1333             = ((const struct jitterc_specialized_argument*)
1334                gl_list_get_at (sins->specialized_arguments, j));
1335           if (! sarg->residual)
1336             continue;
1337           switch (sarg->kind)
1338             {
1339             case jitterc_instruction_argument_kind_register:
1340               EMIT("      /* A slow register is passed as a residual literal offset. */");
1341               EMIT("      jitter_add_specialized_instruction_literal (p, VMPREFIX_SLOW_REGISTER_OFFSET(%c, ins->parameters[%i]->register_index));\n",
1342                    sarg->unspecialized->register_class_character, j);
1343               break;
1344             case jitterc_instruction_argument_kind_literal:
1345               EMIT("      jitter_add_specialized_instruction_literal (p, ins->parameters[%i]->literal.ufixnum);\n", j);
1346               break;
1347             case jitterc_instruction_argument_kind_label:
1348             case jitterc_instruction_argument_kind_fast_label:
1349               EMIT("      jitter_add_specialized_instruction_label_index (p, ins->parameters[%i]->label_as_index);\n", j);
1350               break;
1351             default:
1352               jitter_fatal ("jitterc_emit_specializer: unhandled kind");
1353             }
1354         }
1355 
1356       /* Add one more residual argument in case of a non-relocatable
1357          instruction, as a placeholder for the return label. */
1358       if (is_non_relocatable)
1359         {
1360           EMIT("      /* Non-relocatable instruction: make place for the return label,\n");
1361           EMIT("         whose correct value will be patched in at specialization time. */\n");
1362           EMIT("      jitter_add_specialized_instruction_literal (p, -1);\n");
1363         }
1364 
1365       /* Add one more residual argument in case of a caller instruction, as a
1366          placeholder for the return label. */
1367       if (is_caller)
1368         {
1369           EMIT("      /* Caller instruction: make place for the return address,\n");
1370           EMIT("         whose correct value will be patched in at specialization time. */\n");
1371           EMIT("      jitter_add_specialized_instruction_literal (p, -1);\n");
1372         }
1373 
1374       /* Done handling sins . */
1375       EMIT("      break;\n\n");
1376     }
1377   EMIT("    default:\n");
1378   EMIT("      jitter_fatal (\"invalid specialized instruction opcode %%i\", (int)opcode);\n");
1379   EMIT("    }\n");
1380   EMIT("  return 1; // FIXME: I should rethink this return value.\n");
1381   EMIT("}\n\n");
1382 
1383   jitterc_fclose (f);
1384 }
1385 
1386 
1387 
1388 
1389 /* VM stack support.
1390  * ************************************************************************** */
1391 
1392 /* Emit an upper-case conversion of the given lower-case string. */
1393 static void
jitterc_emit_upper_case(FILE * f,const char * lower_case_string)1394 jitterc_emit_upper_case (FILE *f, const char *lower_case_string)
1395 {
1396   const char *p;
1397   for (p = lower_case_string; *p != '\0'; p ++)
1398     EMIT("%c", toupper (* p));
1399 }
1400 
1401 /* Emit the CPP definition of a stack operation, to be called by user code
1402    within instructions.  The generated macro is a wrapper around a stack
1403    operation defined in jitter/jitter-stack.h . */
1404 static void
jitterc_emit_stack_operation_definition(FILE * f,const struct jitterc_stack * stack,const char * lower_case_operation_name,size_t arity)1405 jitterc_emit_stack_operation_definition (FILE *f,
1406                                          const struct jitterc_stack *stack,
1407                                          const char *lower_case_operation_name,
1408                                          size_t arity)
1409 {
1410   assert (stack->implementation == jitterc_stack_implementation_tos
1411           || stack->implementation == jitterc_stack_implementation_no_tos);
1412   EMIT("/* Wrapper definition of the %s operation for the %s stack \"%s\". */\n",
1413        lower_case_operation_name,
1414        ((stack->implementation == jitterc_stack_implementation_tos)
1415         ? "TOS-optimized" : "non-TOS-optimized"),
1416        stack->lower_case_long_name);
1417   EMIT("#define JITTER_");
1418   jitterc_emit_upper_case (f, lower_case_operation_name);
1419   EMIT("_%s(", stack->upper_case_long_name);
1420   int i;
1421   for (i = 0; i < arity; i ++)
1422     EMIT("x%i%s", i, i != (arity - 1) ? ", ": "");
1423   const char *optimization_suffix
1424     = (stack->implementation == jitterc_stack_implementation_tos) ? "TOS" : "NTOS";
1425   EMIT(")  \\\n");
1426   EMIT("  JITTER_STACK_%s_", optimization_suffix);
1427   jitterc_emit_upper_case (f, lower_case_operation_name);
1428   EMIT("(%s, jitter_state_runtime. , %s", stack->c_type,
1429        stack->lower_case_long_name);
1430   for (i = 0; i < arity; i ++)
1431     EMIT(", x%i", i);
1432   EMIT(")\n\n");
1433 }
1434 
1435 /* Emit CPP definitions for stack operations, for every stack of the pointed
1436    VM. */
1437 static void
jitterc_emit_stack_operation_definitions(FILE * f,const struct jitterc_vm * vm)1438 jitterc_emit_stack_operation_definitions (FILE *f, const struct jitterc_vm *vm)
1439 {
1440   int i; char *comma __attribute__ ((unused));
1441   FOR_LIST(i, comma, vm->stacks)
1442     {
1443       const struct jitterc_stack *stack = gl_list_get_at (vm->stacks, i);
1444       jitterc_emit_stack_operation_definition (f, stack, "top", 0);
1445       jitterc_emit_stack_operation_definition (f, stack, "under_top", 0);
1446       jitterc_emit_stack_operation_definition (f, stack, "at_depth", 1);
1447       jitterc_emit_stack_operation_definition (f, stack, "at_nonzero_depth", 1);
1448       jitterc_emit_stack_operation_definition (f, stack, "set_at_depth", 2);
1449       jitterc_emit_stack_operation_definition (f, stack, "set_at_nonzero_depth", 2);
1450       jitterc_emit_stack_operation_definition (f, stack, "push_unspecified", 0);
1451       jitterc_emit_stack_operation_definition (f, stack, "push", 1);
1452 
1453       jitterc_emit_stack_operation_definition (f, stack, "drop", 0);
1454       jitterc_emit_stack_operation_definition (f, stack, "dup", 0);
1455       jitterc_emit_stack_operation_definition (f, stack, "swap", 0);
1456       jitterc_emit_stack_operation_definition (f, stack, "quake", 0);
1457       jitterc_emit_stack_operation_definition (f, stack, "over", 0);
1458       jitterc_emit_stack_operation_definition (f, stack, "tuck", 0);
1459       jitterc_emit_stack_operation_definition (f, stack, "nip", 0);
1460       jitterc_emit_stack_operation_definition (f, stack, "rot", 0);
1461       jitterc_emit_stack_operation_definition (f, stack, "mrot", 0);
1462       jitterc_emit_stack_operation_definition (f, stack, "roll", 1);
1463       jitterc_emit_stack_operation_definition (f, stack, "mroll", 1);
1464       jitterc_emit_stack_operation_definition (f, stack, "slide", 2);
1465       jitterc_emit_stack_operation_definition (f, stack, "whirl", 1);
1466       jitterc_emit_stack_operation_definition (f, stack, "bulge", 1);
1467 
1468       jitterc_emit_stack_operation_definition (f, stack, "height", 0);
1469       jitterc_emit_stack_operation_definition (f, stack, "set_height", 1);
1470 
1471       jitterc_emit_stack_operation_definition (f, stack, "reverse", 1);
1472 
1473       jitterc_emit_stack_operation_definition (f, stack, "unary", 1);
1474       jitterc_emit_stack_operation_definition (f, stack, "binary", 1); // Not a mistake.
1475     }
1476 }
1477 
1478 /* Emit data structure declarations for VM stack backings.  This generates code
1479    within the state backing struct containined within the VM state struct. */
1480 static void
jitterc_emit_stack_backing_declarations(FILE * f,const struct jitterc_vm * vm)1481 jitterc_emit_stack_backing_declarations (FILE *f, const struct jitterc_vm *vm)
1482 {
1483   EMIT("  /* Stack backing data structures. */\n");
1484   int i; char *comma __attribute__ ((unused));
1485   FOR_LIST(i, comma, vm->stacks)
1486     {
1487       const struct jitterc_stack *stack = gl_list_get_at (vm->stacks, i);
1488 
1489       EMIT("  struct jitter_stack_backing jitter_stack_%s_backing;\n", stack->lower_case_long_name);
1490     }
1491   EMIT("\n");
1492 }
1493 
1494 /* Emit data structure declarations for VM stacks.  This generates code within
1495    the state runtime struct containined within the VM state struct. */
1496 static void
jitterc_emit_stack_runtime_declarations(FILE * f,const struct jitterc_vm * vm)1497 jitterc_emit_stack_runtime_declarations (FILE *f, const struct jitterc_vm *vm)
1498 {
1499   EMIT("  /* Stack runtime data structures. */\n");
1500   int i; char *comma __attribute__ ((unused));
1501   FOR_LIST(i, comma, vm->stacks)
1502     {
1503       const struct jitterc_stack *stack = gl_list_get_at (vm->stacks, i);
1504 
1505       assert (stack->implementation == jitterc_stack_implementation_tos
1506               || stack->implementation == jitterc_stack_implementation_no_tos);
1507       const char *optimization_suffix
1508         = ((stack->implementation == jitterc_stack_implementation_tos)
1509            ? "TOS" : "NTOS");
1510       EMIT("  JITTER_STACK_%s_DECLARATION(%s, %s);\n",
1511            optimization_suffix,
1512            stack->c_type,
1513            stack->lower_case_long_name);
1514     }
1515   EMIT("\n");
1516 }
1517 
1518 /* Emit initialization code for VM stacks.  This generates code within the VM
1519    state initialization function. */
1520 static void
jitterc_emit_stack_initializations(FILE * f,const struct jitterc_vm * vm)1521 jitterc_emit_stack_initializations (FILE *f, const struct jitterc_vm *vm)
1522 {
1523   EMIT("  /* Initialize stack backings and stack runtime data structures, pointing\n");
1524   EMIT("     to memory from the backings. */\n");
1525   int i; char *comma __attribute__ ((unused));
1526   FOR_LIST(i, comma, vm->stacks)
1527     {
1528       const struct jitterc_stack *stack = gl_list_get_at (vm->stacks, i);
1529 
1530       assert (stack->implementation == jitterc_stack_implementation_tos
1531               || stack->implementation == jitterc_stack_implementation_no_tos);
1532       const char *optimization_lower_case_suffix
1533         = ((stack->implementation == jitterc_stack_implementation_tos)
1534            ? "tos" : "ntos");
1535       const char *optimization_upper_case_suffix
1536         = ((stack->implementation == jitterc_stack_implementation_tos)
1537            ? "TOS" : "NTOS");
1538       char *c_type = stack->c_type;
1539       char *c_initial_value = stack->c_initial_value;
1540       const unsigned long element_no = stack->element_no;
1541       int guard_underflow = stack->guard_underflow;
1542       int guard_overflow = stack->guard_overflow;
1543       char element_pointer_name [121];
1544       if (c_initial_value != NULL)
1545         {
1546           char element_name [100];
1547           sprintf (element_name,
1548                    "jitter_stack_%c_initial_element", stack->letter);
1549           EMIT("  %s %s = (%s) (%s);\n",
1550                c_type, element_name, c_type, c_initial_value);
1551           sprintf (element_pointer_name, "(char *) & %s", element_name);
1552         }
1553       else
1554         sprintf (element_pointer_name, "NULL");
1555 
1556       EMIT("  jitter_stack_initialize_%s_backing(& jitter_state_backing->jitter_stack_%s_backing,\n",
1557            optimization_lower_case_suffix, stack->lower_case_long_name);
1558       EMIT("                                      sizeof (%s),\n",
1559            stack->c_type);
1560       EMIT("                                      %lu,\n", element_no);
1561       EMIT("                                      %s,\n", element_pointer_name);
1562       EMIT("                                      %i,\n", guard_underflow);
1563       EMIT("                                      %i);\n", guard_overflow);
1564       EMIT("  JITTER_STACK_%s_INITIALIZE(%s, jitter_state_runtime-> ,\n",
1565            optimization_upper_case_suffix, stack->c_type);
1566       EMIT("                              %s, jitter_state_backing->jitter_stack_%s_backing);\n",
1567            stack->lower_case_long_name, stack->lower_case_long_name);
1568     }
1569   EMIT("\n");
1570 }
1571 
1572 /* Emit finalization code for VM stacks.  This generates code within the VM
1573    state finalization function. */
1574 static void
jitterc_emit_stack_finalizations(FILE * f,const struct jitterc_vm * vm)1575 jitterc_emit_stack_finalizations (FILE *f, const struct jitterc_vm *vm)
1576 {
1577   EMIT("  /* Finalize stack backings -- There is no need to finalize the stack\n");
1578   EMIT("     runtime data structures, as they hold no heap data of their own. */\n");
1579   int i; char *comma __attribute__ ((unused));
1580   FOR_LIST(i, comma, vm->stacks)
1581     {
1582       const struct jitterc_stack *stack = gl_list_get_at (vm->stacks, i);
1583 
1584       EMIT("  jitter_stack_finalize_backing (& jitter_state_backing->jitter_stack_%s_backing);\n",
1585            stack->lower_case_long_name);
1586     }
1587   EMIT("\n");
1588 }
1589 
1590 /* Emit initialisation code for VM registers.  This generates code within the VM
1591    state initialisation function. */
1592 static void
jitterc_emit_register_initializations(FILE * f,const struct jitterc_vm * vm)1593 jitterc_emit_register_initializations (FILE *f, const struct jitterc_vm *vm)
1594 {
1595   EMIT("  /* Initialise the link register, if present. */\n");
1596   EMIT("#if    defined(JITTER_DISPATCH_SWITCH)                   \\\n");
1597   EMIT("    || defined(JITTER_DISPATCH_DIRECT_THREADING)         \\\n");
1598   EMIT("    || defined(JITTER_DISPATCH_MINIMAL_THREADING)        \\\n");
1599   EMIT("    || (   defined(JITTER_DISPATCH_NO_THREADING)         \\\n");
1600   EMIT("        && ! defined(JITTER_MACHINE_SUPPORTS_PROCEDURE))\n");
1601   EMIT("  jitter_state_runtime->_jitter_link = NULL;\n");
1602   EMIT("#endif\n");
1603   EMIT("\n");
1604 
1605   int i; char *comma __attribute__ ((unused));
1606   FOR_LIST(i, comma, vm->register_classes)
1607     {
1608       const struct jitterc_register_class *rc
1609         = gl_list_get_at (vm->register_classes, i);
1610 
1611       if (rc->c_initial_value != NULL)
1612         {
1613           EMIT("  /* Initialise %c-class fast registers. */\n", rc->letter);
1614           int j;
1615           for (j = 0; j < rc->fast_register_no; j ++)
1616             {
1617               EMIT("  jitter_state_runtime->jitter_fast_register_%c_%i\n",
1618                    rc->letter, j);
1619               EMIT("    = (%s) (%s);\n", rc->c_type, rc->c_initial_value);
1620             }
1621         }
1622       else
1623         EMIT("  /* No need to initialise %c-class fast registers. */\n", rc->letter);
1624       EMIT("\n");
1625     }
1626   EMIT("\n");
1627 }
1628 
1629 /* There is no register finalisation code. */
1630 
1631 
1632 
1633 
1634 
1635 /* VM state.
1636  * ************************************************************************** */
1637 
1638 static void
jitterc_emit_state_h(const struct jitterc_vm * vm)1639 jitterc_emit_state_h (const struct jitterc_vm *vm)
1640 {
1641   FILE *f = jitterc_fopen_a_basename (vm, "vm.h");
1642   EMIT("#ifndef VMPREFIX_STATE_H_\n");
1643   EMIT("#define VMPREFIX_STATE_H_\n\n");
1644   EMIT("//#include <jitter/jitter.h>\n\n");
1645 
1646   /* Insert C code from the user.  This is supposed to come in before the struct
1647      definition. */
1648   EMIT("/* Early C code from the user for the state definition. */\n");
1649   EMIT("%s", vm->state_early_c_code);
1650   EMIT("/* End of the early C code from the user for the state definition. */\n\n");
1651 
1652   EMIT("/* The VM state backing. */\n");
1653   EMIT("struct vmprefix_state_backing\n");
1654   EMIT("{\n");
1655   EMIT("  /* The Array.  This initial pointer is kept in the backing, since it is\n");
1656   EMIT("     not normally needed at run time.  By subtracting JITTER_ARRAY_BIAS from\n");
1657   EMIT("     it (as a pointer to char) we get the base pointer. */\n");
1658   EMIT("  char *jitter_array;\n");
1659   EMIT("\n");
1660   EMIT("  /* How many slow registers per class the Array can hold, without being\n");
1661   EMIT("     reallocated.  This number is always the same for evey class. */\n");
1662   EMIT("  jitter_int jitter_slow_register_no_per_class;\n");
1663   EMIT("\n");
1664 
1665   /* Emit declarations for stack backing data structures. */
1666   jitterc_emit_stack_backing_declarations (f, vm);
1667 
1668   EMIT("  /* State backing fields added in C by the user. */\n");
1669   EMIT("%s", vm->state_backing_struct_c_code);
1670   EMIT("\n  /* End of the state backing fields added in C by the user. */\n");
1671   EMIT("};\n");
1672   EMIT("\n");
1673 
1674   EMIT("/* The VM state runtime data structure, using memory from the VM state backing. */\n");
1675   EMIT("struct vmprefix_state_runtime\n");
1676   EMIT("{\n");
1677   EMIT("#if    defined(JITTER_DISPATCH_SWITCH)                   \\\n");
1678   EMIT("    || defined(JITTER_DISPATCH_DIRECT_THREADING)         \\\n");
1679   EMIT("    || defined(JITTER_DISPATCH_MINIMAL_THREADING)        \\\n");
1680   EMIT("    || (   defined(JITTER_DISPATCH_NO_THREADING)         \\\n");
1681   EMIT("        && ! defined(JITTER_MACHINE_SUPPORTS_PROCEDURE))\n");
1682   EMIT("  /* A link register for branch-and-link operations.  This field must *not*\n");
1683   EMIT("     be accessed from user code, as it may not exist on all dispatching\n");
1684   EMIT("     models.  It is only used internally for JITTER_PROCEDURE_PROLOG. */\n");
1685   EMIT("  const union jitter_word *_jitter_link;\n");
1686   EMIT("#endif\n");
1687   EMIT("\n");
1688   EMIT("  /* With recent GCC versions (as of Summer 2017) the *last* declared fields\n");
1689   EMIT("     are the most likely to be allocated in registers; this is why VM registers\n");
1690   EMIT("     are in reverse order here.  The first few fast registers will be the \"fastest\"\n");
1691   EMIT("     ones, allocated in hardware registers; they may be followed by other fast\n");
1692   EMIT("     fast allocated on the stack at known offsets, with intermediate performance; then\n");
1693   EMIT("     come the slow registers.  In critical code the users should prefer a register with as\n");
1694   EMIT("     small an index as possible for best performance. */\n");
1695   int i; char *comma __attribute__ ((unused));
1696   FOR_LIST(i, comma, vm->register_classes)
1697     {
1698       const struct jitterc_register_class *c
1699         = (gl_list_get_at (vm->register_classes, i));
1700       int j;
1701       for (j = c->fast_register_no - 1; j >= 0; j --)
1702         EMIT("  vmprefix_register_%c jitter_fast_register_%c_%i;\n",
1703              c->letter, c->letter, j);
1704     }
1705   EMIT("\n");
1706 
1707   /* Emit declarations for stack runtime data structures. */
1708   jitterc_emit_stack_runtime_declarations (f, vm);
1709 
1710   /* Insert C code from the user.  This is supposed to contain struct fields. */
1711   EMIT("  /* State runtime fields added in C by the user. */\n");
1712   EMIT("%s", vm->state_runtime_struct_c_code);
1713   EMIT("\n  /* End of the state runtime fields added in C by the user. */\n");
1714 
1715   EMIT("};\n");
1716   EMIT("\n");
1717 
1718   EMIT("/* A struct holding both the backing and the runtime part of the VM state. */\n");
1719   EMIT("struct vmprefix_state\n");
1720   EMIT("{\n");
1721   EMIT("  /* Pointers to the previous and next VM state for this VM. */\n");
1722   EMIT("  struct jitter_list_links links;\n");
1723   EMIT("\n");
1724   EMIT("  /* Each state data structure contains its backing. */\n");
1725   EMIT("  struct vmprefix_state_backing vmprefix_state_backing;\n");
1726   EMIT("\n");
1727   EMIT("  /* Each state data structure contains its runtime data structures,\n");
1728   EMIT("     to be allocated to registers as long as possible, and using\n");
1729   EMIT("     memory from the backing. */\n");
1730   EMIT("  struct vmprefix_state_runtime vmprefix_state_runtime;\n");
1731   EMIT("};\n");
1732 
1733   EMIT("#endif // #ifndef VMPREFIX_STATE_H_\n");
1734   jitterc_fclose (f);
1735 }
1736 
1737 static void
jitterc_emit_state(const struct jitterc_vm * vm)1738 jitterc_emit_state (const struct jitterc_vm *vm)
1739 {
1740   FILE *f = jitterc_fopen_a_basename (vm, "vm1.c");
1741 
1742   EMIT("void\n");
1743   EMIT("vmprefix_state_initialize (struct vmprefix_state *jitter_state)\n");
1744   EMIT("{\n");
1745   EMIT("  struct vmprefix_state_backing * const jitter_state_backing\n");
1746   EMIT("    __attribute__ ((unused))\n");
1747   EMIT("    = & jitter_state->vmprefix_state_backing;\n");
1748   EMIT("  struct vmprefix_state_runtime * const jitter_state_runtime\n");
1749   EMIT("    __attribute__ ((unused))\n");
1750   EMIT("    = & jitter_state->vmprefix_state_runtime;\n");
1751   EMIT("\n");
1752 
1753   EMIT("  /* Initialize the Array. */\n");
1754   EMIT("  jitter_state_backing->jitter_slow_register_no_per_class = 0; // FIXME: raise?\n");
1755   EMIT("  jitter_state_backing->jitter_array\n");
1756   EMIT("    = jitter_xmalloc (VMPREFIX_ARRAY_SIZE(jitter_state_backing\n");
1757   EMIT("                         ->jitter_slow_register_no_per_class));\n");
1758   EMIT("\n");
1759   EMIT("  /* Initialize special-purpose data. */\n");
1760   EMIT("  vmprefix_initialize_special_purpose_data (VMPREFIX_ARRAY_TO_SPECIAL_PURPOSE_STATE_DATA (jitter_state_backing->jitter_array));\n");
1761   EMIT("\n");
1762 
1763   /* Emit initialisation code for stacks and registers. */
1764   jitterc_emit_stack_initializations (f, vm);
1765   jitterc_emit_register_initializations (f, vm);
1766 
1767   EMIT("  /* User code for state initialization. */\n");
1768   EMIT("%s\n", vm->state_initialization_c_code);
1769   EMIT("  /* End of the user code for state initialization. */\n");
1770   EMIT("\n");
1771   EMIT("  /* Link this new state to the list of states. */\n");
1772   EMIT("  JITTER_LIST_LINK_LAST (vmprefix_state, links, & vmprefix_vm->states, jitter_state);\n");
1773   EMIT("\n");
1774   EMIT("}\n");
1775   EMIT("\n");
1776 
1777   EMIT("void\n");
1778   EMIT("vmprefix_state_finalize (struct vmprefix_state *jitter_state)\n");
1779   EMIT("{\n");
1780   EMIT("  /* Unlink this new state from the list of states. */\n");
1781   EMIT("  JITTER_LIST_UNLINK (vmprefix_state, links, & vmprefix_vm->states, jitter_state);\n");
1782   EMIT("\n");
1783   EMIT("  struct vmprefix_state_backing * const jitter_state_backing\n");
1784   EMIT("    __attribute__ ((unused))\n");
1785   EMIT("    = & jitter_state->vmprefix_state_backing;\n");
1786   EMIT("  struct vmprefix_state_runtime * const jitter_state_runtime\n");
1787   EMIT("    __attribute__ ((unused))\n");
1788   EMIT("    = & jitter_state->vmprefix_state_runtime;\n");
1789   EMIT("\n");
1790   EMIT("  /* Finalize special-purpose data. */\n");
1791   EMIT("  vmprefix_finalize_special_purpose_data (VMPREFIX_ARRAY_TO_SPECIAL_PURPOSE_STATE_DATA (jitter_state_backing->jitter_array));\n");
1792   EMIT("\n");
1793 
1794   /* Emit finalization for stacks. */
1795   jitterc_emit_stack_finalizations (f, vm);
1796   EMIT("\n");
1797 
1798   EMIT("  /* User code for state finalization. */\n");
1799   EMIT("%s\n", vm->state_finalization_c_code);
1800   EMIT("  /* End of the user code for state finalization. */\n");
1801   EMIT("\n");
1802   EMIT("  /* Finalize the Array. */\n");
1803   EMIT("  free ((void *) jitter_state_backing->jitter_array);\n");
1804   EMIT("\n");
1805   EMIT("}\n\n");
1806 
1807   jitterc_fclose (f);
1808 }
1809 
1810 
1811 
1812 
1813 /* VM configuration.
1814  * ************************************************************************** */
1815 
1816 /* Emit configuration macros.  These are mostly useful to statically initialise
1817    the one instance of struct jitter_vm_configuration , to be used in --version
1818    and similar, and for for vm-main.c . */
1819 static void
jitterc_emit_configuration_macros(const struct jitterc_vm * vm)1820 jitterc_emit_configuration_macros (const struct jitterc_vm *vm)
1821 {
1822   FILE *f = jitterc_fopen_a_basename (vm, "vm.h");
1823 
1824   EMIT("/* Configuration data for struct jitter_vm_configuration. */\n");
1825   char *name = vm->name;
1826   if (name == NULL)
1827     {
1828       name = jitter_clone_string (vm->lower_case_prefix);
1829       if (strlen (name) > 0)
1830         name [0] = toupper (name [0]);
1831     }
1832   EMIT("#define VMPREFIX_VM_NAME JITTER_STRINGIFY(%s)\n", name);
1833   EMIT("#define VMPREFIX_LOWER_CASE_PREFIX \"%s\"\n", vm->lower_case_prefix);
1834   EMIT("#define VMPREFIX_UPPER_CASE_PREFIX \"%s\"\n", vm->upper_case_prefix);
1835   EMIT("#define VMPREFIX_DISPATCH_HUMAN_READABLE \\\n");
1836   EMIT("  JITTER_DISPATCH_NAME_STRING\n");
1837   EMIT("#define VMPREFIX_MAX_FAST_REGISTER_NO_PER_CLASS %i\n",
1838        (int) vm->max_fast_register_no_per_class);
1839   EMIT("#define VMPREFIX_MAX_NONRESIDUAL_LITERAL_NO %i\n",
1840        (int) vm->max_nonresidual_literal_no);
1841 
1842   EMIT("\n");
1843   jitterc_fclose (f);
1844 }
1845 
1846 
1847 
1848 
1849 /* VM register classes.
1850  * ************************************************************************** */
1851 
1852 /* Emit header code for register classes. */
1853 static void
jitterc_emit_register_classes_h(const struct jitterc_vm * vm)1854 jitterc_emit_register_classes_h (const struct jitterc_vm *vm)
1855 {
1856   FILE *f = jitterc_fopen_a_basename (vm, "vm.h");
1857 
1858   EMIT("\n");
1859   EMIT("/* For each register class define the register type, a unique index, and the\n");
1860   EMIT("   number of fast registers.  Indices are useful for computing slow register\n");
1861   EMIT("   offsets.  For each register class declare a global register class\n");
1862   EMIT("   descriptor, convenient to use when generating unspecialized instructions\n");
1863   EMIT("   from the C API.*/\n");
1864   int i; char *comma __attribute__ ((unused));
1865   FOR_LIST(i, comma, vm->register_classes)
1866     {
1867       const struct jitterc_register_class *c
1868         = (gl_list_get_at (vm->register_classes, i));
1869       EMIT("typedef\n%s vmprefix_register_%c;\n", c->c_type, c->letter);
1870       EMIT("#define VMPREFIX_REGISTER_%c_CLASS_ID %i\n", c->letter, i);
1871       EMIT("#define VMPREFIX_REGISTER_%c_FAST_REGISTER_NO %i\n", c->letter,
1872            (int) c->fast_register_no);
1873       EMIT("extern const struct jitter_register_class\n");
1874       EMIT("vmprefix_register_class_%c;\n", c->letter);
1875     }
1876   EMIT("\n");
1877 
1878   EMIT("/* How many register classes we have. */\n");
1879   EMIT("#define VMPREFIX_REGISTER_CLASS_NO  %i\n",
1880        (int) gl_list_size (vm->register_classes));
1881   EMIT("\n");
1882 
1883   EMIT("/* A union large enough to hold a register of any class, or a machine word. */\n");
1884   EMIT("union vmprefix_any_register\n");
1885   EMIT("{\n");
1886   EMIT("  /* In any case the union must be at least as large as a machine word. */\n");
1887   EMIT("  jitter_int jitter_unused_field;\n\n");
1888   FOR_LIST(i, comma, vm->register_classes)
1889     {
1890       const struct jitterc_register_class *c
1891         = (gl_list_get_at (vm->register_classes, i));
1892       EMIT("  vmprefix_register_%c %c /* A %c-class register */;\n",
1893            c->letter, c->letter, c->letter);
1894     }
1895   EMIT("};\n");
1896   EMIT("\n");
1897 
1898   EMIT("/* An enumeration of all vmprefix register classes. */\n");
1899   EMIT("enum vmprefix_register_class_id\n");
1900   EMIT("  {\n");
1901   FOR_LIST(i, comma, vm->register_classes)
1902     {
1903       const struct jitterc_register_class *c
1904         = (gl_list_get_at (vm->register_classes, i));
1905       EMIT("    vmprefix_register_class_id_%c = VMPREFIX_REGISTER_%c_CLASS_ID,\n",
1906            c->letter, c->letter);
1907     }
1908   EMIT("\n");
1909   EMIT("    /* The number of register class ids, not valid as a class id itself. */\n");
1910   EMIT("    vmprefix_register_class_id_no = VMPREFIX_REGISTER_CLASS_NO\n");
1911   EMIT("  };\n");
1912   EMIT("\n");
1913 
1914   EMIT("/* A macro expanding to a statement initialising a rank of slow\n");
1915   EMIT("   registers.  The argument has type union vmprefix_any_register *\n");
1916   EMIT("   and points to the first register in a rank. */\n");
1917   EMIT("#define VMPREFIX_INITIALIZE_SLOW_REGISTER_RANK(rank) \\\n");
1918   EMIT("  do \\\n");
1919   EMIT("    { \\\n");
1920   EMIT("      union vmprefix_any_register *_jitter_rank __attribute__ ((unused)) \\\n");
1921   EMIT("        = (rank); \\\n");
1922   FOR_LIST(i, comma, vm->register_classes)
1923     {
1924       const struct jitterc_register_class *c
1925         = (gl_list_get_at (vm->register_classes, i));
1926       if (c->c_initial_value != NULL)
1927         EMIT("      _jitter_rank [%i].%c = (%s) (%s); \\\n",
1928              (int) i, c->letter, c->c_type, c->c_initial_value);
1929       else
1930         EMIT("      /* %c-class registers need no initialisation. */ \\\n",
1931              c->letter);
1932     }
1933   EMIT("    } \\\n");
1934   EMIT("  while (false)\n");
1935   EMIT("\n");
1936   EMIT("\n");
1937 
1938   jitterc_fclose (f);
1939 }
1940 
1941 /* Emit implementation code for register classes. */
1942 static void
jitterc_emit_register_classes(const struct jitterc_vm * vm)1943 jitterc_emit_register_classes (const struct jitterc_vm *vm)
1944 {
1945   FILE *f = jitterc_fopen_a_basename (vm, "vm1.c");
1946   EMIT("\n");
1947 
1948   /* Emit definitions for global register class descriptors. */
1949   int i; char *comma;
1950   FOR_LIST(i, comma, vm->register_classes)
1951     {
1952       const struct jitterc_register_class *c
1953         = (gl_list_get_at (vm->register_classes, i));
1954       EMIT("/* The register class descriptor for %c registers. */\n", c->letter);
1955       EMIT("const struct jitter_register_class\n");
1956       EMIT("vmprefix_register_class_%c\n", c->letter);
1957       EMIT("  = {\n");
1958       EMIT("      vmprefix_register_class_id_%c,\n", c->letter);
1959       EMIT("      '%c',\n", c->letter);
1960       EMIT("      \"%s\",\n", c->lower_case_long_name);
1961       EMIT("      \"%s\",\n", c->upper_case_long_name);
1962       EMIT("      VMPREFIX_REGISTER_%c_FAST_REGISTER_NO,\n", c->letter);
1963       EMIT("      %i /* Use slow registers */\n", (int) c->use_slow_registers);
1964       EMIT("    };\n\n");
1965     }
1966   EMIT("\n");
1967 
1968   /* Group register class descriptors into a constant pointer constant array. */
1969   EMIT("/* A pointer to every existing register class descriptor. */\n");
1970   EMIT("const struct jitter_register_class * const\n");
1971   EMIT("vmprefix_regiter_classes []\n");
1972   EMIT("  = {\n");
1973   FOR_LIST(i, comma, vm->register_classes)
1974     {
1975       const struct jitterc_register_class *c
1976         = (gl_list_get_at (vm->register_classes, i));
1977       EMIT("      & vmprefix_register_class_%c%s\n", c->letter, comma);
1978     }
1979   EMIT("    };\n");
1980   EMIT("\n");
1981 
1982   /* Emit the definition of vmprefix_register_class_character_to_register_class
1983      , returning a pointer to one of the structures above. */
1984   EMIT("const struct jitter_register_class *\n");
1985   EMIT("vmprefix_register_class_character_to_register_class (char c)\n");
1986   EMIT("{\n");
1987   EMIT("  switch (c)\n");
1988   EMIT("    {\n");
1989   FOR_LIST(i, comma, vm->register_classes)
1990     {
1991       const struct jitterc_register_class *c
1992         = (gl_list_get_at (vm->register_classes, i));
1993       EMIT("    case '%c': return & vmprefix_register_class_%c;\n",
1994            c->letter, c->letter);
1995     }
1996   EMIT("    default:  return NULL;\n");
1997   EMIT("    }\n");
1998   EMIT("}\n");
1999   EMIT("\n");
2000 
2001   jitterc_fclose (f);
2002 }
2003 
2004 
2005 
2006 
2007 /* VM register access.
2008  * ************************************************************************** */
2009 
2010 /* Emit macro definitions for accessing slow registers.  These go into the
2011    VM header, since they are useful both in specialization, for computing
2012    offsets from the base, and in the executor. */
2013 static void
jitterc_emit_register_access_macros_h(const struct jitterc_vm * vm)2014 jitterc_emit_register_access_macros_h (const struct jitterc_vm *vm)
2015 {
2016   FILE *f = jitterc_fopen_a_basename (vm, "vm.h");
2017 
2018   EMIT("/* How many residuals we can have at most.  This, with some dispatching models,\n");
2019   EMIT("   is needed to compute a slow register offset from the base. */\n");
2020   EMIT("#define VMPREFIX_MAX_RESIDUAL_ARITY  %i\n\n", (int)vm->max_residual_arity);
2021 
2022   jitterc_fclose (f);
2023 }
2024 
2025 
2026 
2027 
2028 /* Executor generation.
2029  * ************************************************************************** */
2030 
2031 /* Emit macro definitions for accessing registers as lvalues, available to user
2032    meta-instruction code (mostly for implied operands) and for the generated
2033    code as well (for defining instruction register operands).  There is one
2034    zero-argument macro per fast register, plus another for slow register, having
2035    the register index as the argument.
2036 
2037    The slow-register access macro yields an array access with an index known at
2038    compile time. */
2039 static void
jitterc_emit_executor_register_access_macros(FILE * f,const struct jitterc_vm * vm)2040 jitterc_emit_executor_register_access_macros (FILE *f,
2041                                               const struct jitterc_vm *vm)
2042 {
2043   EMIT("/* Expand to the i-th fast register as an lvalue.  This is used internally,\n");
2044   EMIT("   always with a literal index . */\n");
2045   EMIT("#define JITTER_FAST_REGISTER(class, index)                             \\\n");
2046   EMIT("  (JITTER_CONCATENATE_FOUR(jitter_state_runtime.jitter_fast_register_, \\\n");
2047   EMIT("                           class, _, index))\n");
2048   EMIT("\n");
2049   int i, j; char *comma __attribute__ ((unused));
2050   FOR_LIST(i, comma, vm->register_classes)
2051     {
2052       const struct jitterc_register_class *c
2053         = (gl_list_get_at (vm->register_classes, i));
2054       for (j = 0; j < c->fast_register_no; j ++)
2055         {
2056           EMIT("/* Expand to the %i-th fast %c-register as an lvalue. */\n",
2057                j, c->letter);
2058           EMIT("#define JITTER_FAST_REGISTER_%c_%i JITTER_FAST_REGISTER(%c, %i)\n\n",
2059                c->letter, j, c->letter, j);
2060         }
2061     }
2062   EMIT("/* Expand to a slow register lvalue, given an offset in bytes from the base. */\n");
2063   EMIT("#define JITTER_SLOW_REGISTER_FROM_OFFSET(c, offset)               \\\n");
2064   EMIT("  (* ((JITTER_CONCATENATE_TWO(vmprefix_register_, c) * restrict)  \\\n");
2065   EMIT("      (((char *) jitter_array_base) + offset)))\n");
2066   EMIT("\n");
2067   const int vmprefix_slow_register_with_access_macro_no = 32;
2068   EMIT("/* Expand to the i-th register, which must be a slow register, as an lvalue.\n");
2069   EMIT("   The given index must be a register index counting from 0 and including fast\n");
2070   EMIT("   regusters as well, if there are any.  For example if an r class had 3 fast\n");
2071   EMIT("   registers then the first slow register would be %%r3, to be accessed as\n");
2072   EMIT("   JITTER_SLOW_REGISTER(r, 3).  It would be invalid to access %%r0, %%r1 and\n");
2073   EMIT("   %%r2 which this macro, as %%r0, %%r1 and %%r2 would be fast. */\n");
2074   EMIT("#define JITTER_SLOW_REGISTER(c, i)                                          \\\n");
2075   EMIT("  JITTER_SLOW_REGISTER_FROM_OFFSET(c, VMPREFIX_SLOW_REGISTER_OFFSET(c, i))\n");
2076   EMIT("\n");
2077   EMIT("/* It's not possible to have a single macro JITTER_REGISTER taking an index and\n");
2078   EMIT("   expanding to either a fast or a slow register lvalue, due to CPP conditional\n");
2079   EMIT("   limitations.  This restriction is unfortunate, but we have to live with it\n");
2080   EMIT("   as long as we don't switch to a different preprocessor.\n");
2081   EMIT("   What we can have is a set of zero-argument macros each expanding to a register\n");
2082   EMIT("   lvalue, for *a limited number* of registers.  Here we define access macros for\n");
2083   EMIT("   every fast register plus a reasonable number (currently %i) of slow registers,\n",
2084        vmprefix_slow_register_with_access_macro_no);
2085   EMIT("   per class. */\n");
2086   FOR_LIST(i, comma, vm->register_classes)
2087     {
2088       const struct jitterc_register_class *c
2089         = (gl_list_get_at (vm->register_classes, i));
2090       for (j = 0; j < c->fast_register_no; j ++)
2091         EMIT("#define JITTER_REGISTER_%c_%-3i  JITTER_FAST_REGISTER(%c, %i)\n",
2092              c->letter, j, c->letter, j);
2093       for (;
2094            j < (c->fast_register_no
2095                 + vmprefix_slow_register_with_access_macro_no);
2096            j ++)
2097         EMIT("#define JITTER_REGISTER_%c_%-3i  JITTER_SLOW_REGISTER(%c, %i)\n",
2098              c->letter, j, c->letter, j);
2099     }
2100   EMIT("\n");
2101   EMIT("\n");
2102 }
2103 
2104   static void
jitterc_emit_executor_reserve_registers(FILE * f,const struct jitterc_vm * vm)2105 jitterc_emit_executor_reserve_registers (FILE *f,
2106                                             const struct jitterc_vm *vm)
2107 {
2108   /* We don't need to reserve global registers even with no-threading dispatch
2109      if this machine needs no residaul arguments at all. */
2110   if (vm->max_residual_arity == 0)
2111     return;
2112 
2113   EMIT("#ifdef JITTER_DISPATCH_NO_THREADING\n\n");
2114 
2115   EMIT("/* Reserve the scratch register, if any. */\n");
2116   EMIT("#ifdef JITTER_SCRATCH_REGISTER\n");
2117   EMIT("  register union jitter_word\n");
2118   EMIT("  jitter_residual_argument_scratch_register_variable asm (JITTER_STRINGIFY(JITTER_SCRATCH_REGISTER));\n");
2119   EMIT("#endif // #ifdef JITTER_SCRATCH_REGISTER\n\n");
2120 
2121   EMIT("/* Reserve The Array base register. */\n");
2122   EMIT("#ifndef JITTER_BASE_REGISTER\n");
2123   EMIT("# error \"the machine does not define JITTER_BASE_REGISTER\"\n");
2124   EMIT("#else\n");
2125   EMIT("register char * restrict\n");
2126   EMIT("vmprefix_array_base_register_variable asm (JITTER_STRINGIFY(JITTER_BASE_REGISTER));\n");
2127   EMIT("#endif // #ifndef JITTER_BASE_REGISTER\n\n");
2128 
2129   EMIT("/* Reserve registers for our %i residual arguments.  If this particular VM doesn't\n",
2130        (int) vm->max_residual_arity);
2131   EMIT("   need all of those supported by the assembly machine then reserve only the first\n");
2132   EMIT("   ones.  If, on the other hand, we need more residual arguments than we have\n");
2133   EMIT("   available registers, use CPP macros to map the remaining residual arguments\n");
2134   EMIT("   to memory locations relative to the base, with constant offsets. */\n\n");
2135 
2136   int i;
2137   for (i = 0; i < vm->max_residual_arity; i ++)
2138     {
2139       EMIT("/* Define a macro for the %i-th residual as a register, or as a residual\n", i);
2140       EMIT("   memory slot.  Also define a macro expanding to inline asm code with\n");
2141       EMIT("   output constraints on the appropriate register or memory, to let GCC\n");
2142       EMIT("   know that its value has been changed by unknown code. */\n");
2143       EMIT("#if (%i < JITTER_RESIDUAL_REGISTER_NO)\n", i);
2144       EMIT("  register union jitter_word\n");
2145       EMIT("  jitter_residual_argument_%i_register_variable asm (JITTER_STRINGIFY(JITTER_RESIDUAL_REGISTER_%i));\n", i, i);
2146       EMIT("# define JITTER_RESIDUAL_ARGUMENT_%i               \\\n", i);
2147       EMIT("    jitter_residual_argument_%i_register_variable\n", i);
2148       EMIT("# define JITTER_MARK_RESIDUAL_%i_AS_SET_BY_ASSEMBLY                 \\\n", i);
2149       EMIT("    JITTER_MARK_REGISTER_AS_SET_BY_ASSEMBLY(jitter_residual_argument_%i_register_variable)\n", i);
2150       EMIT("#else\n");
2151       EMIT("# define JITTER_RESIDUAL_ARGUMENT_%i  \\\n", i);
2152       EMIT("    (* (union jitter_word *)                 \\\n");
2153       EMIT("       (jitter_array_base + VMPREFIX_RESIDUAL_OFFSET(%i)))\n", i);
2154       EMIT("# define JITTER_MARK_RESIDUAL_%i_AS_SET_BY_ASSEMBLY                    \\\n", i);
2155       EMIT("    JITTER_MARK_MEMORY_AS_SET_BY_ASSEMBLY(JITTER_RESIDUAL_ARGUMENT_%i)\n", i);
2156       EMIT("#endif // #if (%i < JITTER_RESIDUAL_REGISTER_NO)\n\n", i);
2157     }
2158 
2159   EMIT("/* The global register values we reserve in this compilation unit are\n");
2160   EMIT("   callee-save: the called function is supposed to save them before\n");
2161   EMIT("   setting them, and restore them to their previous value before\n");
2162   EMIT("   returning to the caller.  Of course this is not done automatically\n");
2163   EMIT("   in this compilation unit, so we have to do it by hand.  Notice that\n");
2164   EMIT("   every variable allocated to a register by GCC will not use the\n");
2165   EMIT("   registers we reserved, so we can be sure that, if we save our\n");
2166   EMIT("   global register variables before setting them for the first time,\n");
2167   EMIT("   their values will be the ones we want to retain. */\n");
2168   EMIT("\n");
2169   EMIT("/* The buffer where I keep the original register values needs to hold\n");
2170   EMIT("   every residual register, plus possibly the scratch register and the\n");
2171   EMIT("   residual base; those two registers are not always used, but allocating\n");
2172   EMIT("   just two words more costs essentially nothing and lets me simplify\n");
2173   EMIT("   the code a little.  The two words are not written or read unless\n");
2174   EMIT("   needed. */\n");
2175   EMIT("#define VMPREFIX_REGISTER_BUFFER_ELEMENT_NO (JITTER_RESIDUAL_REGISTER_NO + 2)\n");
2176   EMIT("__attribute__ ((noinline, cold))\n");
2177   EMIT("\n");
2178 
2179   EMIT("static void\n");
2180   EMIT("vmprefix_save_registers (union jitter_word *buffer)\n");
2181   EMIT("{\n");
2182   EMIT("  buffer [0].pointer = (union jitter_word*) vmprefix_array_base_register_variable;\n");
2183   EMIT("#ifdef JITTER_SCRATCH_REGISTER\n");
2184   EMIT("  buffer [1] = jitter_residual_argument_scratch_register_variable;\n");
2185   EMIT("#endif // #ifdef JITTER_SCRATCH_REGISTER\n");
2186   for (i = 0; i < vm->max_residual_arity; i ++)
2187     {
2188       EMIT("#if (%i < JITTER_RESIDUAL_REGISTER_NO)\n", i);
2189       EMIT("  buffer [%i + 2] = JITTER_RESIDUAL_ARGUMENT_%i;\n", i, i);
2190       EMIT("#endif // #if (%i < JITTER_RESIDUAL_REGISTER_NO)\n", i);
2191     }
2192   EMIT("}\n");
2193   EMIT("\n");
2194 
2195   EMIT("__attribute__ ((noinline, cold))\n");
2196   EMIT("static void\n");
2197   EMIT("vmprefix_restore_registers (const union jitter_word *buffer)\n");
2198   EMIT("{\n");
2199   EMIT("  vmprefix_array_base_register_variable = (char *) buffer [0].pointer;\n");
2200   EMIT("#ifdef JITTER_SCRATCH_REGISTER\n");
2201   EMIT("  jitter_residual_argument_scratch_register_variable = buffer [1];\n");
2202   EMIT("#endif // #ifdef JITTER_SCRATCH_REGISTER\n");
2203   for (i = 0; i < vm->max_residual_arity; i ++)
2204     {
2205       EMIT("#if (%i < JITTER_RESIDUAL_REGISTER_NO)\n", i);
2206       EMIT("  JITTER_RESIDUAL_ARGUMENT_%i = buffer [%i + 2];\n", i, i);
2207       EMIT("#endif // #if (%i < JITTER_RESIDUAL_REGISTER_NO)\n", i);
2208     }
2209   EMIT("}\n");
2210   EMIT("\n");
2211 
2212   EMIT("#endif // #ifdef JITTER_DISPATCH_NO_THREADING\n\n\n");
2213 }
2214 
2215 static void
jitterc_emit_executor_global_wrappers(FILE * f,const struct jitterc_vm * vm)2216 jitterc_emit_executor_global_wrappers
2217    (FILE *f, const struct jitterc_vm *vm)
2218 {
2219   EMIT("/* Selectively suppress suprious -Wmaybe-uninitialized .\n");
2220   EMIT("   The indirect jump hack I use in profiling mode in order to\n");
2221   EMIT("   have a large gap inside a function introduced by assembler without\n");
2222   EMIT("   being restricted by jump offset limits (intentionally) tricks GCC\n");
2223   EMIT("   into believing that the indirect jump may reach any instruction label;\n");
2224   EMIT("   GCC would then warn that some locals might be used uninitialized,\n");
2225   EMIT("   by skipping over their initialization.  This however is not possible,\n");
2226   EMIT("   and I want to selectively silence the warning for the variables in\n");
2227   EMIT("   question. */\n");
2228   EMIT("#pragma GCC diagnostic push\n");
2229   EMIT("#pragma GCC diagnostic ignored \"-Wmaybe-uninitialized\"\n");
2230   EMIT("\n");
2231   EMIT("  /* Wrap functions and globals used within VM instructions, if needed.\n");
2232   EMIT("     This is a trick to keep instructions readable while avoiding PC-relative\n");
2233   EMIT("     addressing, which would mess up replicated code. */\n");
2234   EMIT("#ifdef JITTER_REPLICATE\n\n");
2235 
2236   /* When using replication we have to wrap C functions called from VM
2237      instructions. */
2238   EMIT("  /* Protect the C globals used in VM instructions so that they are always\n");
2239   EMIT("     referred thru a pointer (from a register or the stack) set in the\n");
2240   EMIT("     non-replicated part.  This is necessary on architectures where I can't\n");
2241   EMIT("     force global references to pass thru a GOT.\n");
2242   EMIT("     [FIXME: possibly don't do this on architectures that don't need it.] */\n\n");
2243   int i; char *comma __attribute__ ((unused));
2244   FOR_LIST(i, comma, vm->wrapped_globals)
2245     {
2246       const char *name
2247         = ((const char*) gl_list_get_at (vm->wrapped_globals, i));
2248       EMIT("  typeof (%s) * volatile _my_volatile_pointer_to_%s = & %s;\n",
2249            name, name, name);
2250       EMIT("  typeof (%s) * const restrict _my_pointer_to_%s __attribute__ ((unused))\n",
2251            name, name);
2252       EMIT("     = _my_volatile_pointer_to_%s;\n", name);
2253       EMIT("# undef %s\n", name);
2254       EMIT("# define %s (* _my_pointer_to_%s)\n\n", name, name);
2255     }
2256 
2257   EMIT("  /* Similarly, wrap the C functions used in VM instructions, so that they are\n");
2258   EMIT("     always called thru a function pointer.  This is necessary on architectures\n");
2259   EMIT("     where call instructions represent the callee as a PC-relative address.\n");
2260   EMIT("     Unfortunately C has a special quirky syntax for function pointers, so I\n");
2261   EMIT("     can't just use the code above.  [FIXME: don't do this on architectures\n");
2262   EMIT("     that don't need it.] */\n");
2263   FOR_LIST(i, comma, vm->wrapped_functions)
2264     {
2265       const char *name
2266         = ((const char*) gl_list_get_at (vm->wrapped_functions, i));
2267       EMIT("  typeof (%s) * volatile _my_volatile_pointer_to_%s = & %s;\n",
2268            name, name, name);
2269       EMIT("  typeof (%s) * const _my_%s __attribute__ ((unused))\n",
2270            name, name);
2271       EMIT("     = * _my_volatile_pointer_to_%s;\n", name);
2272       EMIT("# undef %s\n", name);
2273       EMIT("# define %s _my_%s\n\n", name, name);
2274     }
2275   EMIT("/* See the comment above about spurious -Wmaybe-uninitialized warnings. */\n");
2276   EMIT("#pragma GCC diagnostic pop\n");
2277   EMIT("#endif // #ifdef JITTER_REPLICATE\n\n");
2278   EMIT("\n");
2279 }
2280 
2281 /* Emit macro definitions (and possibly inline asm statements) for the given
2282    specialized argument, occurring in the given 0-based position among all the
2283    arguments and in the given (still 0-based) position among the residual
2284    arguments of a specialized instruction.  Non-fast-label residuals and
2285    fast-label "residuals" have independent counters: for example the five sargs
2286    of a specialized instruction foo_r0_nR_fR_nR_fR would have residual indices:
2287    - 0 (non-residual)
2288    - 0 (first residual non-fast-label)
2289    - 0 (first "residual" fast label)
2290    - 1 (second residual non-fast-label)
2291    - 1 (second "residual" fast label). */
2292 static void
jitterc_emit_executor_sarg_definition(FILE * f,int index,int residual_index,const struct jitterc_specialized_argument * sarg,bool have_fast_labels)2293 jitterc_emit_executor_sarg_definition
2294    (FILE *f, int index, int residual_index,
2295     const struct jitterc_specialized_argument* sarg,
2296     bool have_fast_labels)
2297 {
2298   switch (sarg->kind)
2299     {
2300     case jitterc_instruction_argument_kind_register:
2301       EMIT("    /* The %ith argument is a %s\n        register. */\n",
2302            index,
2303            sarg->residual ? "slow (therefore residual, passed as an offset)"
2304            : "fast");
2305       if (sarg->residual)
2306         {
2307           EMIT("  /* Define a macro expanding to the slow register offset. */\n");
2308           EMIT("#if defined(JITTER_DISPATCH_NO_THREADING)\n");
2309           EMIT("# define JITTER_SLOW_REGISTER_OFFSET%i (JITTER_RESIDUAL_ARGUMENT_%i.fixnum)\n", index, residual_index);
2310           EMIT("#elif defined (JITTER_DISPATCH_MINIMAL_THREADING)\n");
2311           EMIT("# define JITTER_SLOW_REGISTER_OFFSET%i ((((union jitter_word*)jitter_ip)[%i]).fixnum)\n", index, residual_index);
2312           EMIT("#else\n");
2313           EMIT("# define JITTER_SLOW_REGISTER_OFFSET%i ((((union jitter_word*)jitter_ip)[%i]).fixnum)\n", index, residual_index + 1);
2314           EMIT("#endif // #if defined(JITTER_DISPATCH_NO_THREADING)\n");
2315 
2316           EMIT("  /* Define a macro expanding to an l-value for the VM register content. */\n");
2317           EMIT("#   define JITTER_ARG%i  JITTER_SLOW_REGISTER_FROM_OFFSET(%c, JITTER_SLOW_REGISTER_OFFSET%i)\n",
2318                index, sarg->unspecialized->register_class_character, index);
2319         }
2320       else
2321         EMIT("#   define JITTER_ARG%i  JITTER_FAST_REGISTER(%c, %i)\n",
2322              index, sarg->unspecialized->register_class_character,
2323              (int) sarg->nonresidual_register->index);
2324       break;
2325 
2326     case jitterc_instruction_argument_kind_literal:
2327       EMIT("    /* The %ith argument is a %sresidual literal. */\n",
2328            index, sarg->residual ? "" : "non");
2329       if (sarg->residual)
2330         goto residual_label_or_literal;
2331       else
2332         /* FIXME: this will need generalization with more literal kinds. */
2333         EMIT("#   define JITTER_ARG%i  ((const union jitter_word){.fixnum = %liL})\n",
2334              index, (long)sarg->nonresidual_literal->value.fixnum);
2335       break;
2336 
2337     case jitterc_instruction_argument_kind_label:
2338       EMIT("    /* The %ith argument is a %sresidual label. */\n",
2339            index, sarg->residual ? "" : "non");
2340       if (! sarg->residual)
2341         jitter_fatal ("nonresidual label");
2342     residual_label_or_literal:
2343       EMIT("#if defined(JITTER_DISPATCH_NO_THREADING)\n");
2344       EMIT("#   define JITTER_ARG%i  JITTER_RESIDUAL_ARGUMENT_%i\n", index, residual_index);
2345       EMIT("    JITTER_MARK_RESIDUAL_%i_AS_SET_BY_ASSEMBLY;\n", residual_index);
2346       EMIT("#elif defined (JITTER_REPLICATE)\n");
2347       EMIT("#   define JITTER_ARG%i  (((union jitter_word*)jitter_ip)[%i])\n", index, residual_index);
2348       EMIT("#else\n");
2349       EMIT("#   define JITTER_ARG%i  (((union jitter_word*)jitter_ip)[%i])\n", index, residual_index + 1);
2350       EMIT("#endif // #if defined(JITTER_DISPATCH_NO_THREADING)\n");
2351       break;
2352 
2353     case jitterc_instruction_argument_kind_fast_label:
2354       if (! sarg->residual)
2355         jitter_fatal ("nonresidual fast label");
2356 
2357       if (have_fast_labels)
2358         {
2359           EMIT("    /* The %ith argument is a \"residual\" fast label.  Define its\n", index);
2360           EMIT("       _ARGF macro as the residual *index* (counting only fast labels, 0-based),\n");
2361           EMIT("       so that at replication time we know what instruction address to patch in. */\n");
2362           EMIT("#   define JITTER_ARGF%i %i\n", index, residual_index);
2363           EMIT("    /* JITTER_ARG%i is intentionally not defined for a fast label. */\n\n", index);
2364         }
2365       else
2366         goto residual_label_or_literal;
2367 
2368       break;
2369 
2370     default:
2371       jitter_fatal ("jitterc_emit_executor_sarg_definition: invalid argument kind %i", (int) sarg->kind);
2372     }
2373   EMIT("#   define JITTER_ARGN%i (JITTER_ARG%i.fixnum)\n", index, index);
2374   EMIT("#   define JITTER_ARGU%i (JITTER_ARG%i.ufixnum)\n", index, index);
2375   EMIT("#   define JITTER_ARGP%i (JITTER_ARG%i.pointer)\n", index, index);
2376   if ((have_fast_labels && sarg->replacement) || ! have_fast_labels)
2377     {
2378       EMIT("#   define JITTER_ARGF%i JITTER_ARGP%i\n", index, index);
2379     }
2380   /*
2381   else if (! have_fast_labels)
2382     EMIT("#   define JITTER_ARGF%i JITTER_ARGP%i\n", index, index);
2383   */
2384   EMIT("\n");
2385 }
2386 
2387 /* An internal function factoring code run twice in
2388    jitterc_emit_sarg_definitions .  This emits definitions for user-visible
2389    argument-access macros, assuming fast labels are enabled or not, as per the
2390    given argument. */
2391 static void
jitterc_emit_sarg_definitions_internal(FILE * f,const struct jitterc_specialized_instruction * sins,bool have_fast_labels)2392 jitterc_emit_sarg_definitions_internal
2393    (FILE *f, const struct jitterc_specialized_instruction *sins,
2394     bool have_fast_labels)
2395 {
2396   size_t residual_arity = 0;
2397   size_t residual_label_index = 0;
2398   int j; char *comma __attribute__ ((unused));
2399   FOR_LIST(j, comma, sins->specialized_arguments)
2400     {
2401       const struct jitterc_specialized_argument* sarg
2402         = ((const struct jitterc_specialized_argument*)
2403            gl_list_get_at (sins->specialized_arguments, j));
2404       if (   have_fast_labels
2405           && sarg->kind == jitterc_instruction_argument_kind_fast_label)
2406         {
2407           jitterc_emit_executor_sarg_definition
2408             (f, j, residual_label_index, sarg, have_fast_labels);
2409           residual_label_index ++;
2410         }
2411       else
2412         jitterc_emit_executor_sarg_definition
2413           (f, j, residual_arity, sarg, have_fast_labels);
2414 
2415       if (   sarg->residual
2416           && (   sarg->kind != jitterc_instruction_argument_kind_fast_label
2417               || ! have_fast_labels))
2418         residual_arity ++;
2419     }
2420 }
2421 
2422 /* Emit definitions for the user-visible argument-access macros of the given
2423    instruction.  The generated code is conditionalized on fast label support, if
2424    needed. */
2425 static void
jitterc_emit_sarg_definitions(FILE * f,const struct jitterc_specialized_instruction * sins)2426 jitterc_emit_sarg_definitions
2427    (FILE *f, const struct jitterc_specialized_instruction *sins)
2428 {
2429   /* Emit a conditionalized argument definition for when fast labels are used, ending
2430      in an #else case for the non-fast-label case. */
2431   if (sins->instruction->has_fast_labels)
2432     {
2433       EMIT("  /* Define argument-access macros for %s . */\n", sins->name);
2434       EMIT("#ifdef JITTER_HAVE_PATCH_IN\n");
2435       EMIT("  /* Define argument-access macros assuming that fast branches are enabled. */\n");
2436       jitterc_emit_sarg_definitions_internal (f, sins, true);
2437       EMIT("#else\n");
2438       EMIT("  /* Define argument-access macros assuming that fast branches are disabled. */\n");
2439     }
2440 
2441   /* Emit the non-fast-label case, which is always there. */
2442   jitterc_emit_sarg_definitions_internal (f, sins, false);
2443 
2444   /* Close the conditional we opened if there were fast labels. */
2445   if (sins->instruction->has_fast_labels)
2446     EMIT("# endif // #ifdef JITTER_HAVE_PATCH_IN\n");
2447 }
2448 
2449 static void
jitterc_emit_specialized_instruction_residual_arity_definition(FILE * f,const struct jitterc_specialized_instruction * sins)2450 jitterc_emit_specialized_instruction_residual_arity_definition
2451    (FILE *f, const struct jitterc_specialized_instruction *sins)
2452 {
2453   /* How many residual arguments we have in total, including fast labels if
2454      any. */
2455   size_t residual_argument_no = 0;
2456 
2457   /* The number of non-fast-label residual arguments, including both non-fast
2458      labels and non-label residuals. */
2459   size_t non_fast_label_residual_argument_no = 0;
2460 
2461   /* Count non-fast-labels and all residuals. */
2462   int j; char *comma __attribute__ ((unused));
2463   FOR_LIST(j, comma, sins->specialized_arguments)
2464     {
2465       const struct jitterc_specialized_argument* sarg
2466         = ((const struct jitterc_specialized_argument*)
2467            gl_list_get_at (sins->specialized_arguments, j));
2468       if (sarg->residual)
2469         {
2470           residual_argument_no ++;
2471           if (sarg->kind != jitterc_instruction_argument_kind_fast_label)
2472             non_fast_label_residual_argument_no ++;
2473         }
2474     }
2475 
2476   /* Emit the residual arity definition, making it conditional only if needed. */
2477   if (non_fast_label_residual_argument_no == residual_argument_no)
2478     {
2479       EMIT("  /* The residual arity for this instruction does not depend on fast labels. */\n");
2480       EMIT("  #define JITTER_SPECIALIZED_INSTRUCTION_RESIDUAL_ARITY %i\n",
2481            (int) non_fast_label_residual_argument_no);
2482     }
2483   else
2484     {
2485       EMIT("  /* The residual arity varies depending on whether we have fast labels. */\n");
2486       EMIT("#ifdef JITTER_HAVE_PATCH_IN\n");
2487       EMIT("  #define JITTER_SPECIALIZED_INSTRUCTION_RESIDUAL_ARITY %i\n",
2488            (int) non_fast_label_residual_argument_no);
2489       EMIT("#else\n");
2490       EMIT("  #define JITTER_SPECIALIZED_INSTRUCTION_RESIDUAL_ARITY %i\n",
2491            (int) residual_argument_no);
2492       EMIT("#endif // #ifdef JITTER_HAVE_PATCH_IN\n");
2493     }
2494 }
2495 
2496 /* Names for fast-branching macros, without the prefix "JITTER_BRANCH". */
2497 static const char *
2498 jitter_fast_branch_macros []
2499   = {
2500       "",
2501       "_IF_ZERO",
2502       "_IF_NONZERO",
2503       "_IF_POSITIVE",
2504       "_IF_NONPOSITIVE",
2505       "_IF_NEGATIVE",
2506       "_IF_NONNEGATIVE",
2507       "_IF_EQUAL",
2508       "_IF_NOTEQUAL",
2509       "_IF_LESS_SIGNED",
2510       "_IF_LESS_UNSIGNED",
2511       "_IF_NOTLESS_SIGNED",
2512       "_IF_NOTLESS_UNSIGNED",
2513       "_IF_GREATER_SIGNED",
2514       "_IF_GREATER_UNSIGNED",
2515       "_IF_NOTGREATER_SIGNED",
2516       "_IF_NOTGREATER_UNSIGNED",
2517       "_IF_AND",
2518       "_IF_NOTAND",
2519       "_IF_PLUS_OVERFLOWS",
2520       "_IF_MINUS_OVERFLOWS",
2521       "_IF_TIMES_OVERFLOWS",
2522       "_IF_DIVIDED_OVERFLOWS",
2523       "_IF_REMAINDER_OVERFLOWS",
2524       "_IF_NEGATE_OVERFLOWS",
2525       /*
2526 // FIXME: I *think* I only use these internally.
2527       "_IF_NEVER_UNARY",
2528       "_IF_ALWAYS_UNARY",
2529       */
2530       /* Here the underscore is intentional: even the name with (one) initial
2531          underscore is defined conditionally, only in caller instructions. */
2532       "_AND_LINK_INTERNAL"
2533     };
2534 
2535 /* How many strings jitter_fast_branch_macros has. */
2536 static const size_t
2537 jitter_fast_branch_macro_no
2538 = sizeof (jitter_fast_branch_macros) / sizeof (jitter_fast_branch_macros [0]);
2539 
2540 /* Same role as jitter_fast_branch_macros above for operations fast-branching on
2541    overflow.  Only the operation name is given here. */
2542 static const char *
2543 jitter_fast_branching_operation_macros []
2544   = {
2545       "PLUS",
2546       "MINUS",
2547       "TIMES",
2548       "DIVIDED",
2549       "REMAINDER",
2550       "NEGATE"
2551     };
2552 /* How many strings jitter_fast_branching_operation_macros has. */
2553 static const size_t
2554 jitter_fast_branching_operation_macro_no
2555 = sizeof (jitter_fast_branching_operation_macros)
2556   / sizeof (jitter_fast_branching_operation_macros [0]);
2557 
2558 /* Emit macro definitions for fast branching.  These are defined in a different
2559    way for replacement and non-replacement specialized instructions. */
2560 static void
jitterc_emit_executor_fast_branch_definitions(FILE * f,const struct jitterc_vm * vm,const struct jitterc_specialized_instruction * sins)2561 jitterc_emit_executor_fast_branch_definitions
2562   (FILE *f, const struct jitterc_vm *vm,
2563    const struct jitterc_specialized_instruction* sins)
2564 {
2565   bool is_replacement = (sins->is_replacement_of != NULL);
2566 
2567   if (is_replacement)
2568     EMIT("    /* This specialized instruction is a replacement. */\n");
2569   else
2570     EMIT("    /* This specialized instruction is not a replacement. */\n");
2571   int i;
2572   for (i = 0; i < jitter_fast_branch_macro_no; i ++)
2573     {
2574       const char *macro_name = jitter_fast_branch_macros [i];
2575       EMIT("#   undef JITTER_BRANCH_FAST%s\n", macro_name);
2576       if (is_replacement)
2577         EMIT("#   define JITTER_BRANCH_FAST%s JITTER_BRANCH%s\n", macro_name, macro_name);
2578       else
2579         EMIT("#   define JITTER_BRANCH_FAST%s _JITTER_BRANCH_FAST%s\n", macro_name, macro_name);
2580     }
2581   for (i = 0; i < jitter_fast_branching_operation_macro_no; i ++)
2582     {
2583       const char *macro_name = jitter_fast_branching_operation_macros [i];
2584       EMIT("#   undef JITTER_%s_BRANCH_FAST_IF_OVERFLOW\n", macro_name);
2585       if (is_replacement)
2586         EMIT("#   define JITTER_%s_BRANCH_FAST_IF_OVERFLOW JITTER_%s_BRANCH_IF_OVERFLOW\n", macro_name, macro_name);
2587       else
2588         EMIT("#   define JITTER_%s_BRANCH_FAST_IF_OVERFLOW _JITTER_%s_BRANCH_FAST_IF_OVERFLOW\n", macro_name, macro_name);
2589     }
2590 }
2591 
2592 static void
jitterc_emit_executor_ordinary_specialized_instructions(FILE * f,const struct jitterc_vm * vm)2593 jitterc_emit_executor_ordinary_specialized_instructions
2594    (FILE *f, const struct jitterc_vm *vm)
2595 {
2596   int i; char *comma __attribute__ ((unused));
2597 
2598   /* Generate code for each ordinary specialized instruction. */
2599   EMIT("  /* Ordinary specialized instructions. */\n");
2600   FOR_LIST(i, comma, vm->specialized_instructions)
2601     {
2602       const struct jitterc_specialized_instruction* sins
2603         = ((const struct jitterc_specialized_instruction*)
2604            gl_list_get_at (vm->specialized_instructions, i));
2605       /* Ignore special specialized instructions: we have already dealt with
2606          them. */
2607       if (sins->instruction == NULL)
2608         continue;
2609 
2610       const struct jitterc_instruction* uins = sins->instruction;
2611       bool is_relocatable
2612         = (sins->relocatability == jitterc_relocatability_relocatable);
2613       bool is_caller = (uins->callerness == jitterc_callerness_caller);
2614       bool is_callee = (uins->calleeness == jitterc_calleeness_callee);
2615 
2616       EMIT("  JITTER_INSTRUCTION_PROLOG_(%s, %s, %s)\n",
2617            sins->name, sins->mangled_name,
2618            (sins->hotness == jitterc_hotness_hot)
2619            ? "hot"
2620            : "cold");
2621       EMIT("  {\n");
2622 
2623       /* Emit definitions for fast-branch macros.  The definitions will be
2624          different for replacement and non-replacement instructions. */
2625       jitterc_emit_executor_fast_branch_definitions (f, vm, sins);
2626 
2627       if (! is_relocatable)
2628         {
2629           EMIT("    /* This specialized instruction is non-relocatable.\n");
2630           EMIT("       Its %i-th argument, a literal, is the return address where to jump\n",
2631                (int) (gl_list_size (sins->specialized_arguments) - 1));
2632           EMIT("       at the end, back to relocated code. */\n\n");
2633         }
2634 
2635       if (is_caller)
2636         {
2637           EMIT("    /* This specialized instruction is a caller.\n");
2638           EMIT("       Its %i-th argument, a literal, is the return address where to jump\n",
2639                (int) (gl_list_size (sins->specialized_arguments) - 1));
2640           EMIT("       back after the procedure returns.  Branch-and-link\n");
2641           EMIT("       functionality is enabled for this instruction. */\n");
2642           EMIT("#   define JITTER_BRANCH_AND_LINK      JITTER_BRANCH_AND_LINK_INTERNAL\n");
2643           EMIT("#   define JITTER_BRANCH_FAST_AND_LINK JITTER_BRANCH_FAST_AND_LINK_INTERNAL\n\n");
2644         }
2645 
2646       /* Define the specialized instruction opcode and name as macros, to be
2647          used in the body and, in case of fast labels, in the arguments. */
2648       EMIT("#   define JITTER_SPECIALIZED_INSTRUCTION_OPCODE       %i\n", i);
2649       EMIT("#   define JITTER_SPECIALIZED_INSTRUCTION_NAME         %s\n\n",
2650            sins->name);
2651       EMIT("#   define JITTER_SPECIALIZED_INSTRUCTION_MANGLED_NAME %s\n\n",
2652            sins->mangled_name);
2653 
2654       /* Emit a macro definition for the specialized instruction residual arity. */
2655       jitterc_emit_specialized_instruction_residual_arity_definition (f, sins);
2656       EMIT("\n");
2657 
2658       /* Emit macro definitions for specialized arguments, to be used in the body. */
2659       jitterc_emit_sarg_definitions (f, sins);
2660       EMIT("\n");
2661 
2662       if (is_callee)
2663         {
2664           EMIT("  /* This specialized instruction is a callee.  Set the link\n");
2665           EMIT("     pointer if needed... */\n");
2666           EMIT("  union jitter_word _jitter_the_link;\n");
2667           EMIT("  _JITTER_PROCEDURE_PROLOG (_jitter_the_link);\n");
2668           EMIT("  /* ...And make it accessible to this instruction, read-only,\n");
2669           EMIT("     through a macro. */\n");
2670           EMIT("  #define JITTER_LINK \\\n");
2671           EMIT("    ((const void *) \\\n");
2672           EMIT("     (_jitter_the_link.pointer))\n");
2673           EMIT("\n");
2674         }
2675 
2676       /* If this is a non-relocatable instruction and replication is enabled,
2677          the actual code to replicate is trivial: just a jump; then comes the
2678          epilog.  After the epilog we can put the label where relocated code
2679          jumps to, which is where control flows to in the other cases.  The
2680          actual user-specified code for the VM instruction comes after the
2681          label. */
2682       if (! is_relocatable)
2683         {
2684           EMIT("#ifdef JITTER_REPLICATE\n");
2685           EMIT("    /* Pretend to modify the non-relocatable code pointer, to force GCC to keep\n");
2686           EMIT("       it on the stack rather than in read-only memory.  I had to do this to prevent\n");
2687           EMIT("       a GCC 8 snapshot on SH from being too clever. */\n");
2688           EMIT("    //JITTER_MARK_MEMORY_AS_SET_BY_ASSEMBLY(JITTER_SPECIALIZED_INSTRUCTION_NON_RELOCATABLE_CODE_VARIABLE);\n");
2689           EMIT("    /* FIXME: no, it's not enough.  GCC 8 on SH keeps the stack pointer *offset*\n");
2690           EMIT("       in memory, as a 16-bit constant; and since it reads it with a PC-relative\n");
2691           EMIT("       load the relocated part crashes.\n");
2692           EMIT("                 mov.w     .L1667,r0\n");
2693           EMIT("                 mov.l     @(r0,r15),r1\n");
2694           EMIT("                 jmp       @r1\n");
2695           EMIT("       r15 is the stack pointer.  The constant at .L1667 is\n");
2696           EMIT("          .L1667:\n");
2697           EMIT("                 .short    232\n");
2698           EMIT("       and this explains everything: 232 doesn't fit in a byte sign-extended, so it\n");
2699           EMIT("       can't work as an immediate.  Shall I keep these code pointers as a single array?\n");
2700           EMIT("       I don't know.  I'll switch to GNU C nested functions for non-relocatable code,\n");
2701           EMIT("       but the problem will be the same. */\n");
2702           EMIT("    /* Jump to non-relocatable code. */\n");
2703           EMIT("    JITTER_COMPUTED_GOTO(JITTER_SPECIALIZED_INSTRUCTION_NON_RELOCATABLE_CODE_VARIABLE);\n");
2704           EMIT("\n");
2705           EMIT("    /* Here the residual arity is given as zero: it's too late to\n");
2706           EMIT("       skip residuals, since we've already jumped and this code is\n");
2707           EMIT("       unreachable.  The instruction pointer, if any, is advanced\n");
2708           EMIT("       in the non-relocatable code. */\n");
2709           EMIT("    JITTER_INSTRUCTION_EPILOG_(%s, %s, 0)\n", sins->name, sins->mangled_name);
2710           EMIT("\n");
2711           EMIT("    /* Relocated code will jump to this label in non-relocated code. */\n");
2712           EMIT("  JITTER_SPECIALIZED_INSTRUCTION_NON_RELOCATABLE_CODE_LABEL:\n");
2713           EMIT("    JITTER_COMMENT_IN_ASM_(\"%s non-relocatable code\");\n", sins->name);
2714           EMIT("#endif // #ifdef JITTER_REPLICATE\n");
2715         }
2716 
2717       if (is_caller)
2718         {
2719           EMIT("#if    defined(JITTER_DISPATCH_NO_THREADING)         \\\n");
2720           EMIT("    && ! defined(JITTER_MACHINE_SUPPORTS_PROCEDURE)\n");
2721           EMIT("  /* We use the implicit atgument at the end of the calling.\n");
2722           EMIT("     instruction to discover the procedure return address. */\n");
2723           EMIT("  const void * _jitter_return_pointer = JITTER_ARGP%i;\n",
2724                (int) (gl_list_size (sins->specialized_arguments) - 1));
2725           EMIT("  /* And make it accessible to the user (who will usually call \n");
2726           EMIT("     JITTER_BRANCH_AND_LINK) thru a nice macro. */\n");
2727           EMIT("# define JITTER_RETURN_ADDRESS _jitter_return_pointer\n");
2728           EMIT("#endif\n\n");
2729         }
2730 
2731       /* Emit profiling instrumentation code for the instruction. */
2732       EMIT("#if defined (JITTER_PROFILE_SAMPLE)\n");
2733       EMIT("  JITTER_PROFILE_SAMPLE_UPDATE\n");
2734       EMIT("     (VMPREFIX_OWN_SPECIAL_PURPOSE_STATE_DATA,\n");
2735       EMIT("      JITTER_SPECIALIZED_INSTRUCTION_OPCODE);\n");
2736       EMIT("  /* Force the compiler not move sample-profiling instrumentation\n");
2737       EMIT("     beyond this point; this way the actual user code is timed.\n");
2738       EMIT("     This is still not perfect, as residuals are materialised before\n");
2739       EMIT("     we arrive here, but should be adequate at least for slow VM\n");
2740       EMIT("     instructions. */\n");
2741       EMIT("  JITTER_PRETEND_TO_POSSIBLY_JUMP_ANYWHERE ();\n");
2742       EMIT("#endif\n");
2743       EMIT("#if defined (JITTER_PROFILE_COUNT)\n");
2744       EMIT("  /* Notice that, differently from the code above, this\n");
2745       EMIT("     instrumentation code *can* be reordered freely: as long as a\n");
2746       EMIT("     VM instruction is counted, the count increment can be placed\n");
2747       EMIT("     anyehere.  Let GCC move this code and possibly achieve better\n");
2748       EMIT("     throughput by exploiting instruction-level parallelism and\n");
2749       EMIT("     therefore approximate more closely a non-profiled build. */\n");
2750       EMIT("  JITTER_PROFILE_COUNT_UPDATE\n");
2751       EMIT("     (VMPREFIX_OWN_SPECIAL_PURPOSE_STATE_DATA,\n");
2752       EMIT("      JITTER_SPECIALIZED_INSTRUCTION_OPCODE);\n");
2753       EMIT("#endif\n");
2754       EMIT("\n");
2755 
2756       /* Emit the user C code for the beginning of every instruction, if any. */
2757       jitterc_emit_user_c_code_to_stream
2758          (vm, f, vm->instruction_beginning_c_code, "instruction-beginning-c");
2759 
2760       /* Emit user-specified code for the instruction.  We have already opened a brace, so
2761          another pair is not needed. */
2762       EMIT("\n    /* User code for %s . */\n", sins->name);
2763       EMIT("%s\n", uins->code);
2764       EMIT("    /* End of the user code for %s . */\n\n", sins->name);
2765 
2766       /* Emit the user C code for the end of every instruction, if any.  Notice
2767          that the code is not always reachable. */
2768       jitterc_emit_user_c_code_to_stream (vm, f, vm->instruction_end_c_code,
2769                                           "instruction-end-c");
2770 
2771       if (! is_relocatable)
2772         {
2773           EMIT("#ifdef JITTER_REPLICATE\n");
2774           EMIT("    /* Advance the instruction pointer, if any, to skip residuals;\n");
2775           EMIT("       then jump back to replicated code. */\n");
2776           EMIT("    const void *_jitter_back_to_replicated_code_pointer = JITTER_ARGP%i;\n",
2777                (int) (gl_list_size (sins->specialized_arguments) - 1));
2778           EMIT("    JITTER_SKIP_RESIDUALS_;\n");
2779           EMIT("    goto * _jitter_back_to_replicated_code_pointer;\n");
2780           EMIT("#endif // #ifdef JITTER_REPLICATE\n\n");
2781         }
2782 
2783       /* Undefine macros only visible in caller instructions. */
2784       if (is_caller)
2785         {
2786           EMIT("    /* Undefine macros only visible in caller instructions. */\n");
2787           EMIT("#   undef JITTER_BRANCH_AND_LINK\n");
2788           EMIT("#   undef JITTER_BRANCH_FAST_AND_LINK\n\n");
2789         }
2790 
2791       /* Undefine argument macros.  Those will be redefined before the next
2792          instruction as needed; it would be dangerous to leave previous
2793          definitions active, because some instruction body coming after this
2794          might reuse some old definition by mistake in case the new instruction
2795          doesn't override it. */
2796       EMIT("    /* Undefine the %s argument macros so they can't be used\n",
2797            sins->name);
2798       EMIT("       by mistake in the instruction body coming next. */\n");
2799       int j; char *comma __attribute__ ((unused));
2800       FOR_LIST(j, comma, sins->specialized_arguments)
2801         {
2802           EMIT("#   undef JITTER_SLOW_REGISTER_OFFSET%i\n", j);
2803           EMIT("#   undef JITTER_ARG%i\n", j);
2804           EMIT("#   undef JITTER_ARGN%i\n", j);
2805           EMIT("#   undef JITTER_ARGU%i\n", j);
2806           EMIT("#   undef JITTER_ARGP%i\n", j);
2807           EMIT("#   undef JITTER_ARGF%i\n", j);
2808         }
2809 
2810       /* Undefine the specialized instruction opcode and name. */
2811       EMIT("\n");
2812       EMIT("#   undef JITTER_SPECIALIZED_INSTRUCTION_OPCODE\n");
2813       EMIT("#   undef JITTER_SPECIALIZED_INSTRUCTION_NAME\n");
2814       EMIT("#   undef JITTER_SPECIALIZED_INSTRUCTION_MANGLED_NAME\n\n");
2815 
2816       EMIT("  }\n");
2817 
2818       /* If we have defined a link, undefine it: it is only visible in its
2819          instruction. */
2820       if (is_callee)
2821         {
2822           EMIT("  /* Undefine the link macro. */\n");
2823           EMIT("#   undef JITTER_LINK\n\n");
2824         }
2825       if (is_caller)
2826         {
2827           EMIT("#if    defined(JITTER_DISPATCH_NO_THREADING)         \\\n");
2828           EMIT("    && ! defined(JITTER_MACHINE_SUPPORTS_PROCEDURE)\n");
2829           EMIT("# undef JITTER_RETURN_ADDRESS\n");
2830           EMIT("#endif\n\n");
2831         }
2832 
2833       /* This is the instruction epilog only for relocatable instructions, and
2834          when replication is disabled. */
2835       if (! is_relocatable)
2836         EMIT("#ifndef JITTER_REPLICATE\n");
2837       EMIT(" JITTER_INSTRUCTION_EPILOG_(%s, %s, JITTER_SPECIALIZED_INSTRUCTION_RESIDUAL_ARITY)\n",
2838            sins->name, sins->mangled_name);
2839       if (! is_relocatable)
2840         EMIT("#endif // #ifndef JITTER_REPLICATE\n");
2841       EMIT("#   undef JITTER_SPECIALIZED_INSTRUCTION_RESIDUAL_ARITY\n");
2842       EMIT("\n");
2843    }
2844   EMIT("  /* End of the ordinary specialized instructions. */\n\n");
2845 }
2846 
2847 /* Emit the patch-in header, before the main executor. */
2848 static void
jitterc_emit_patch_in_header(FILE * f,const struct jitterc_vm * vm)2849 jitterc_emit_patch_in_header (FILE *f, const struct jitterc_vm *vm)
2850 {
2851   /* Generate the patch-in header.  The generated code expands to an inline asm
2852      statement.  It is convenient to keep header and footer within the main
2853      executor function, so as to guarantee that the order is respected. */
2854   EMIT("#ifdef JITTER_HAVE_PATCH_IN\n");
2855   EMIT("  /* Generate the single patch-in header for this executor as a\n");
2856   EMIT("     global asm statement.  This expands into a global definition in\n");
2857   EMIT("     assembly in a separate subsection, and relies on toplevel C\n");
2858   EMIT("     definitions not being reordered: vmprefix_execute_or_initialize\n");
2859   EMIT("     will add to the same global.  Do the same for defects. */\n");
2860   EMIT("  JITTER_DEFECT_HEADER(vmprefix);\n");
2861   EMIT("  JITTER_PATCH_IN_HEADER(vmprefix);\n");
2862   EMIT("#endif // #ifdef JITTER_HAVE_PATCH_IN\n\n");
2863   EMIT("#ifndef JITTER_DISPATCH_SWITCH\n");
2864   EMIT("  JITTER_DATA_LOCATION_HEADER(vmprefix);\n");
2865   EMIT("#endif // #ifndef JITTER_DISPATCH_SWITCH\n");
2866   EMIT("\n");
2867 }
2868 
2869 /* Emit the patch-in footer, after the main executor. */
2870 static void
jitterc_emit_patch_in_footer(FILE * f,const struct jitterc_vm * vm)2871 jitterc_emit_patch_in_footer (FILE *f, const struct jitterc_vm *vm)
2872 {
2873   /* Generate the patch-in footer.  See the comment in
2874      jitterc_emit_patch_in_header . */
2875   EMIT("#ifndef JITTER_DISPATCH_SWITCH\n");
2876   EMIT("  JITTER_DATA_LOCATION_FOOTER(vmprefix);\n");
2877   EMIT("#endif // #ifndef JITTER_DISPATCH_SWITCH\n");
2878   EMIT("#ifdef JITTER_HAVE_PATCH_IN\n");
2879   EMIT("  /* Close the patch-in global definition for this executor.  This defines a\n");
2880   EMIT("     new global in the patch-in subsection, holding the descriptor number.\n");
2881   EMIT("     This is a global asm statement.  Same for defects.  See the comment before\n");
2882   EMIT("      the JITTER_PATCH_IN_HEADER use above. */\n");
2883   EMIT("  JITTER_PATCH_IN_FOOTER(vmprefix);\n");
2884   EMIT("  JITTER_DEFECT_FOOTER(vmprefix);\n");
2885   EMIT("#endif // #ifdef JITTER_HAVE_PATCH_IN\n\n");
2886 }
2887 
2888 /* Emit the beginning of the case for a special specialized instruction in the
2889    executor.  The C code for the instruction body must be emitted right after
2890    this. */
2891 static void
jitterc_emit_executor_special_specialized_instruction_beginning(FILE * f,const struct jitterc_vm * vm,const char * name,enum jitter_specialized_instruction_opcode opcode,const char * hotness,int residual_arity)2892 jitterc_emit_executor_special_specialized_instruction_beginning
2893    (FILE *f, const struct jitterc_vm *vm,
2894     const char *name,
2895     enum jitter_specialized_instruction_opcode opcode,
2896     const char *hotness, int residual_arity)
2897 {
2898   EMIT("JITTER_INSTRUCTION_PROLOG_(%s, %s, %s)\n",
2899        name, jitterc_mangle (name), hotness);
2900   EMIT("#define JITTER_SPECIALIZED_INSTRUCTION_RESIDUAL_ARITY %i\n",
2901        residual_arity);
2902   EMIT("#define JITTER_SPECIALIZED_INSTRUCTION_OPCODE  %i\n", opcode);
2903   EMIT("#define JITTER_SPECIALIZED_INSTRUCTION_NAME  %s\n", name);
2904   EMIT("#define JITTER_SPECIALIZED_INSTRUCTION_MANGLED_NAME  %s\n",
2905        jitterc_mangle (name));
2906   EMIT("{\n");
2907 }
2908 
2909 /* Emit the end of the case for a special specialized instruction in the
2910    executor.  This must follow the emission of the C instruction body. */
2911 static void
jitterc_emit_executor_special_specialized_instruction_end(FILE * f,const struct jitterc_vm * vm,const char * name,enum jitter_specialized_instruction_opcode opcode,const char * hotness,int residual_arity)2912 jitterc_emit_executor_special_specialized_instruction_end
2913    (FILE *f, const struct jitterc_vm *vm,
2914     const char *name,
2915     enum jitter_specialized_instruction_opcode opcode,
2916     const char *hotness, int residual_arity)
2917 {
2918   EMIT("}\n");
2919   EMIT("JITTER_INSTRUCTION_EPILOG_(%s, %s, %i)\n",
2920        name, jitterc_mangle (name), residual_arity);
2921   EMIT("#undef JITTER_SPECIALIZED_INSTRUCTION_OPCODE\n");
2922   EMIT("#undef JITTER_SPECIALIZED_INSTRUCTION_NAME\n");
2923   EMIT("#undef JITTER_SPECIALIZED_INSTRUCTION_MANGLED_NAME\n");
2924   EMIT("#undef JITTER_SPECIALIZED_INSTRUCTION_RESIDUAL_ARITY\n");
2925   EMIT("\n");
2926 }
2927 
2928 /* Emit the case for a special specialized instruction in the executor. */
2929 static void
jitterc_emit_executor_special_specialized_instruction(FILE * f,const struct jitterc_vm * vm,const char * name,enum jitter_specialized_instruction_opcode opcode,const char * hotness,int residual_arity,const char * c_code)2930 jitterc_emit_executor_special_specialized_instruction
2931    (FILE *f, const struct jitterc_vm *vm,
2932     const char *name,
2933     enum jitter_specialized_instruction_opcode opcode,
2934     const char *hotness, int residual_arity,
2935     const char *c_code)
2936 {
2937   jitterc_emit_executor_special_specialized_instruction_beginning
2938      (f, vm, name, opcode, hotness, residual_arity);
2939   EMIT("\n%s\n", c_code);
2940   jitterc_emit_executor_special_specialized_instruction_end
2941      (f, vm, name, opcode, hotness, residual_arity);
2942 }
2943 
2944 /* Emit macro calls to generate data locations in a separate subsection.  This
2945    needs to be called as the body of the special specialized instruction
2946    !DATALOCATIONS . */
2947 static void
jitterc_emit_executor_data_locations(FILE * f,const struct jitterc_vm * vm)2948 jitterc_emit_executor_data_locations (FILE *f, const struct jitterc_vm *vm)
2949 {
2950   int i, j; char *comma __attribute__ ((unused));
2951   EMIT("#ifndef JITTER_DISPATCH_SWITCH\n");
2952 
2953   /* First emit reserved registers: these are in fact guaranteed to be
2954      registers. */
2955 
2956   /* Instruction pointer, if any. */
2957   EMIT("#ifndef JITTER_DISPATCH_NO_THREADING\n");
2958   EMIT("  JITTER_DATA_LOCATION_DATUM (\"instruction pointer\", jitter_ip);\n");
2959   EMIT("#endif // #ifndef JITTER_DISPATCH_NO_THREADING\n");
2960 
2961   /* Base. */
2962   EMIT("  JITTER_DATA_LOCATION_DATUM (\"base\", jitter_array_base);\n");
2963 
2964   /* Scratch, if any. */
2965   EMIT("#ifdef JITTER_DISPATCH_NO_THREADING\n");
2966   EMIT("#ifdef JITTER_SCRATCH_REGISTER\n");
2967   EMIT("  JITTER_DATA_LOCATION_DATUM (\"scratch\", jitter_residual_argument_scratch_register_variable);\n");
2968   EMIT("#endif // #ifdef JITTER_SCRATCH_REGISTER\n\n");
2969   EMIT("#endif // #ifdef JITTER_DISPATCH_NO_THREADING\n");
2970 
2971   /* Residual registers, if any. */
2972   EMIT("#ifdef JITTER_DISPATCH_NO_THREADING\n");
2973   for (i = 0; i < vm->max_residual_arity; i ++)
2974     {
2975       EMIT("#if (%i < JITTER_RESIDUAL_REGISTER_NO)\n", i);
2976       EMIT("  JITTER_DATA_LOCATION_DATUM (\"residual %i\", jitter_residual_argument_%i_register_variable);\n", i, i);
2977       EMIT("#endif // #if (%i < JITTER_RESIDUAL_REGISTER_NO)\n", i);
2978     }
2979   EMIT("#endif // #ifdef JITTER_DISPATCH_NO_THREADING\n");
2980 
2981   /* Link register, if any. */
2982   EMIT("#if    defined(JITTER_DISPATCH_SWITCH)                    \\\n");
2983   EMIT("    || defined(JITTER_DISPATCH_DIRECT_THREADING)          \\\n");
2984   EMIT("    || defined(JITTER_DISPATCH_MINIMAL_THREADING)         \\\n");
2985   EMIT("    || (   defined(JITTER_DISPATCH_NO_THREADING)          \\\n");
2986   EMIT("        && ! defined(JITTER_MACHINE_SUPPORTS_PROCEDURE))\n");
2987   EMIT("\n");
2988   EMIT("  JITTER_DATA_LOCATION_DATUM (\"link register\", jitter_state_runtime._jitter_link);\n");
2989   EMIT("#endif // link register\n");
2990 
2991   /* For each stack... */
2992   FOR_LIST(i, comma, vm->stacks)
2993     {
2994       const struct jitterc_stack *stack = gl_list_get_at (vm->stacks, i);
2995       const char * stack_name = stack->lower_case_long_name;
2996       if (stack->implementation == jitterc_stack_implementation_tos)
2997         {
2998           EMIT("  JITTER_DATA_LOCATION_DATUM (\"%s top\", \n", stack_name);
2999           EMIT("     JITTER_STACK_TOS_TOP_NAME (whatever, jitter_state_runtime., %s));\n",
3000                stack_name);
3001           EMIT("  JITTER_DATA_LOCATION_DATUM (\"%s undertop ptr\", \n", stack_name);
3002           EMIT("     JITTER_STACK_TOS_UNDER_TOP_POINTER_NAME (whatever, jitter_state_runtime., %s));\n",
3003                stack_name);
3004         }
3005       else if (stack->implementation == jitterc_stack_implementation_no_tos)
3006 
3007         {
3008           EMIT("  JITTER_DATA_LOCATION_DATUM (\"%s top ptr\", \n", stack_name);
3009           EMIT("     JITTER_STACK_NTOS_TOP_POINTER_NAME (whatever, jitter_state_runtime., %s));\n",
3010                stack_name);
3011         }
3012       else
3013         jitter_fatal ("stack implementation unknown: this should not happen");
3014 
3015     }
3016 
3017   /* For each register class... */
3018   FOR_LIST(i, comma, vm->register_classes)
3019     {
3020       const struct jitterc_register_class *c
3021         = (gl_list_get_at (vm->register_classes, i));
3022       /* Emit each fast register as a datum. */
3023       for (j = 0; j < c->fast_register_no; j ++)
3024         EMIT("JITTER_DATA_LOCATION_DATUM(\"%%%%%c%i\", JITTER_REGISTER_%c_%i);\n",
3025              c->letter, j, c->letter, j);
3026     }
3027   EMIT("#endif // #ifndef JITTER_DISPATCH_SWITCH\n");
3028 }
3029 
3030 static void
jitterc_emit_executor_main_function(FILE * f,const struct jitterc_vm * vm)3031 jitterc_emit_executor_main_function
3032    (FILE *f, const struct jitterc_vm *vm)
3033 {
3034   /* Generate the actual executor main function. */
3035   EMIT("static void\n");
3036   EMIT("vmprefix_execute_or_initialize (bool jitter_initialize,\n");
3037   EMIT("                                vmprefix_program_point jitter_initial_program_point,\n");
3038   EMIT("                                struct vmprefix_state * const jitter_original_state)\n");
3039   EMIT("{\n");
3040 
3041   /* Emit debugging prints.  FIXME: implement something like this, cleanly, in a
3042      different function. */
3043 /*
3044   EMIT("#ifdef JITTER_DISPATCH_NO_THREADING\n");
3045   EMIT("  printf (\"JITTER_RESIDUAL_REGISTER_NO is %%i\\n\", (int)JITTER_RESIDUAL_REGISTER_NO);\n");
3046   EMIT("#endif // #ifdef JITTER_DISPATCH_NO_THREADING\n");
3047   EMIT("  printf (\"VMPREFIX_MAX_RESIDUAL_ARITY is %%i\\n\", (int)VMPREFIX_MAX_RESIDUAL_ARITY);\n");
3048   EMIT("  printf (\"VMPREFIX_MAX_MEMORY_RESIDUAL_ARITY is %%i\\n\", (int)VMPREFIX_MAX_MEMORY_RESIDUAL_ARITY);\n");
3049   EMIT("  {int q;\n");
3050   EMIT("#ifdef JITTER_REPLICATE\n");
3051   EMIT("  for (q = JITTER_RESIDUAL_REGISTER_NO; q < VMPREFIX_MAX_MEMORY_RESIDUAL_ARITY; q ++)\n");
3052   EMIT("    printf (\"VMPREFIX_RESIDUAL_OFFSET(%%i) is %%i or 0x%%x\\n\", q, (int)VMPREFIX_RESIDUAL_OFFSET(q), (int)VMPREFIX_RESIDUAL_OFFSET(q));\n");
3053   EMIT("#endif // #ifdef JITTER_REPLICATE\n");
3054   EMIT("  printf (\"VMPREFIX_REGISTER_r_FAST_REGISTER_NO is %%i\\n\", (int)VMPREFIX_REGISTER_r_FAST_REGISTER_NO);\n");
3055   EMIT("  for (q = VMPREFIX_REGISTER_r_FAST_REGISTER_NO; q < (VMPREFIX_REGISTER_r_FAST_REGISTER_NO + 10); q ++)\n");
3056   EMIT("    printf (\"VMPREFIX_SLOW_REGISTER_OFFSET(r, %%i) is %%i or 0x%%x\\n\", q, (int)VMPREFIX_SLOW_REGISTER_OFFSET(r, q), (int)VMPREFIX_SLOW_REGISTER_OFFSET(r, q));\n");
3057   EMIT("  }\n");
3058   EMIT("  asm volatile (\"\\n.pushsection .rodata\\n\"\n");
3059   EMIT("                \"\\nFOO:\\n\"\n");
3060   EMIT("                \"\\n.asciz \\\"" JITTER_STRINGIFY(jitter_initial_program_point) " is at %%[thing]\\\"\\n\"\n");
3061   EMIT("                \"\\n.popsection\\n\"\n");
3062   EMIT("                :\n");
3063   EMIT("                : [thing] \"X\" (jitter_initial_program_point)\n");
3064   EMIT("               );\n");
3065   EMIT("\n\n");
3066 */
3067   EMIT("#ifdef JITTER_DISPATCH_NO_THREADING\n");
3068   EMIT("  /* Save the values in the registers we reserved as global variables,\n");
3069   EMIT("     since from the point of view of the other C compilation units such\n");
3070   EMIT("     registers are callee-save.  FIXME: this is not really needed when\n");
3071   EMIT("     initializing, if I've been careful; but for the time being I want\n");
3072   EMIT("     to play it safe. */\n");
3073   EMIT("  union jitter_word jitter_register_buffer [VMPREFIX_REGISTER_BUFFER_ELEMENT_NO];\n");
3074   EMIT("  vmprefix_save_registers (jitter_register_buffer);\n");
3075   EMIT("#endif // #ifdef JITTER_DISPATCH_NO_THREADING\n\n");
3076 
3077   /* Emit the patch-in header.  This must come before the frist patch-in or
3078      defect use. */
3079   jitterc_emit_patch_in_header (f, vm);
3080 
3081   /* The main executor function begins with three big static arrays containing
3082      the labels where every specialized instruction begins and ends, and their sizes
3083      (only when replication is enabled), to be used only at initialization. */
3084   EMIT("  /* Initialization.  This is only called once at startup. */\n");
3085   EMIT("  if (__builtin_expect (jitter_initialize, false))\n");
3086   EMIT("    {\n");
3087   EMIT("      /* Make sure that vm1 and vm2 were macroexpanded consistently\n");
3088   EMIT("         with respect to instrumentation macros.  This relies on the\n");
3089   EMIT("         enum values for each feature working as individual bits in a\n");
3090   EMIT("         bitmask: see the comment in jitter/jitter-vm.h . */\n");
3091   EMIT("      enum jitter_vm_instrumentation correct_instrumentation\n");
3092   EMIT("        = jitter_vm_instrumentation_none;\n");
3093   EMIT("#if defined (JITTER_PROFILE_COUNT)\n");
3094   EMIT("      correct_instrumentation |= jitter_vm_instrumentation_count;\n");
3095   EMIT("#endif\n");
3096   EMIT("#if defined (JITTER_PROFILE_SAMPLE)\n");
3097   EMIT("      correct_instrumentation |= jitter_vm_instrumentation_sample;\n");
3098   EMIT("#endif\n");
3099   EMIT("      if (vmprefix_vm_configuration->instrumentation != correct_instrumentation)\n");
3100   EMIT("        jitter_fatal (\"vm1 and vm2 were compiled with different profiling \"\n");
3101   EMIT("                      \"instrumentation macros.  Please recompile with coherent \"\n");
3102   EMIT("                      \"CPPFLAGS\");\n");
3103   EMIT("\n");
3104 
3105   EMIT("#if defined (JITTER_PROFILE_SAMPLE)\n");
3106   EMIT("    /* Initialise the sample-profile subsystem, once and for all. */\n");
3107   EMIT("    vmprefix_profile_sample_initialize ();\n");
3108   EMIT("#endif // #if defined (JITTER_PROFILE_SAMPLE)\n");
3109   EMIT("\n");
3110 
3111   EMIT("#ifndef JITTER_DISPATCH_SWITCH\n");
3112   EMIT("      /* FIXME: I can do this with only one relocation, by keeping\n");
3113   EMIT("         a pointer to the first VM instruction beginning in a static\n");
3114   EMIT("         variable, and then having a static vector of offsets with\n");
3115   EMIT("         respect to the first pointer.  This will slightly complicate\n");
3116   EMIT("         my initialization code, but should make startup faster.\n");
3117   EMIT("         FIXME: that won't work on AVR, according to the GCC\n");
3118   EMIT("         documentation.  Do I care?  Probably not, since AVRs can't\n");
3119   EMIT("         address more than 2^16 bytes, which is too little to run my\n");
3120   EMIT("         VMs. */\n");
3121   EMIT("      static const jitter_thread vmprefix_the_threads []\n");
3122   EMIT("        = {\n");
3123   int i; char *comma;
3124   FOR_LIST(i, comma, vm->specialized_instructions)
3125     {
3126       const struct jitterc_specialized_instruction* sins
3127         = ((const struct jitterc_specialized_instruction*)
3128            gl_list_get_at (vm->specialized_instructions, i));
3129       EMIT("            && JITTER_SPECIALIZED_INSTRUCTION_BEGIN_LABEL_OF(%s)%s\n",
3130            sins->mangled_name, comma);
3131     }
3132   EMIT("          };\n");
3133 
3134   /* Also generate thread ends. */
3135   EMIT("      static const jitter_thread vmprefix_the_thread_ends []\n");
3136   EMIT("        = {\n");
3137   FOR_LIST(i, comma, vm->specialized_instructions)
3138     {
3139       const struct jitterc_specialized_instruction* sins
3140         = ((const struct jitterc_specialized_instruction*)
3141            gl_list_get_at (vm->specialized_instructions, i));
3142       EMIT("            && JITTER_SPECIALIZED_INSTRUCTION_END_LABEL_OF(%s)%s\n",
3143            sins->mangled_name, comma);
3144     }
3145   EMIT("          };\n");
3146   EMIT("      static const long\n");
3147   EMIT("      vmprefix_the_thread_sizes [VMPREFIX_SPECIALIZED_INSTRUCTION_NO]\n");
3148   EMIT("        = {\n");
3149   FOR_LIST(i, comma, vm->specialized_instructions)
3150     {
3151       const struct jitterc_specialized_instruction* sins
3152         = ((const struct jitterc_specialized_instruction*)
3153            gl_list_get_at (vm->specialized_instructions, i));
3154       EMIT("            (long) ((jitter_int) (&& JITTER_SPECIALIZED_INSTRUCTION_END_LABEL_OF(%s))\n",
3155            sins->mangled_name);
3156       EMIT("                    - (jitter_int) (&& JITTER_SPECIALIZED_INSTRUCTION_BEGIN_LABEL_OF(%s)))%s\n",
3157            sins->mangled_name, comma);
3158     }
3159   EMIT("          };\n");
3160   EMIT("      vmprefix_thread_sizes = vmprefix_the_thread_sizes;\n");
3161   EMIT("      vmprefix_threads = vmprefix_the_threads;\n");
3162   EMIT("      vmprefix_thread_ends = vmprefix_the_thread_ends;\n");
3163 
3164   /// FIXME: this is for debugging: begin
3165   EMIT("#ifdef JITTER_PROFILE\n");
3166   EMIT("      fprintf (stderr, \"VM instruction range: \");\n");
3167   const struct jitterc_specialized_instruction* first_sins
3168     = ((const struct jitterc_specialized_instruction*)
3169        gl_list_get_at (vm->specialized_instructions, 0));
3170   const struct jitterc_specialized_instruction* last_sins
3171     = ((const struct jitterc_specialized_instruction*)
3172        gl_list_get_at (vm->specialized_instructions,
3173                        gl_list_size (vm->specialized_instructions) - 1));
3174   EMIT("      fprintf (stderr, \"[%%p, \", && JITTER_SPECIALIZED_INSTRUCTION_BEGIN_LABEL_OF(%s));\n",
3175        first_sins->mangled_name);
3176   EMIT("      fprintf (stderr, \"%%p)\", && JITTER_SPECIALIZED_INSTRUCTION_END_LABEL_OF(%s));\n",
3177        last_sins->mangled_name);
3178   EMIT("      fprintf (stderr, \"\\n\");\n");
3179   EMIT("#endif // #ifdef JITTER_PROFILE\n");
3180   /// FIXME: this is for debugging: end
3181 
3182   EMIT("#endif // #ifndef JITTER_DISPATCH_SWITCH\n");
3183   EMIT("\n");
3184   EMIT("      /* Back to regular C, without our reserved registers if any; I can share\n");
3185   EMIT("         the end code with the non-initialization case. */\n");
3186   EMIT("#ifdef JITTER_HAVE_PATCH_IN\n");
3187   EMIT("      //JITTER_DUMP_PATCH_IN_DESCRIPTORS(vmprefix);\n");
3188   EMIT("#endif // #ifdef JITTER_HAVE_PATCH_IN\n");
3189   EMIT("      goto jitter_possibly_restore_registers_and_return_label;\n");
3190   EMIT("    }\n");
3191   EMIT("\n\n");
3192 
3193   EMIT("  /* Here is the actual *executor* initialization, to be run before\n");
3194   EMIT("     actually running the code. */\n\n");
3195 
3196   jitterc_emit_executor_global_wrappers (f, vm);
3197 
3198   /* If control flow reaches this point then we are actually executing code. */
3199   EMIT("  /* Make an automatic struct holding a copy of the state whose pointer was given.\n");
3200   EMIT("     The idea is that the copy should be in registers, as far as possible. */\n");
3201   EMIT("  struct vmprefix_state_runtime jitter_state_runtime\n");
3202   EMIT("    = jitter_original_state->vmprefix_state_runtime;\n\n");
3203 
3204   EMIT("  /* Initialize a pointer to The Array base.  This pointer will be in a\n");
3205   EMIT("     global register variable with no-threading dispatch, and with\n");
3206   EMIT("     other dispatches in an automatic variable, still hopefully kept\n");
3207   EMIT("     in a register. */\n");
3208   EMIT("/* About the pragma, look for \"-Wmaybe-uninitialized\" in the comments above. FIXME: this is to avoid a GCC warning with profiling.  Check with profiling on. */\n");
3209   EMIT("#pragma GCC diagnostic push\n");
3210   EMIT("#pragma GCC diagnostic ignored \"-Wmaybe-uninitialized\"\n");
3211   EMIT("#ifdef JITTER_DISPATCH_NO_THREADING\n");
3212   EMIT("# define jitter_array_base vmprefix_array_base_register_variable\n");
3213   EMIT("#else\n");
3214   EMIT("  char * restrict jitter_array_base __attribute__ ((unused));\n");
3215   EMIT("#endif // #ifdef JITTER_DISPATCH_NO_THREADING\n");
3216   EMIT("#pragma GCC diagnostic pop\n");
3217   EMIT("  jitter_array_base\n");
3218   EMIT("    = (((char *) jitter_original_state->vmprefix_state_backing.jitter_array)\n");
3219   EMIT("       + JITTER_ARRAY_BIAS);\n");
3220   EMIT("\n");
3221 
3222   EMIT("  /* Declare the instruction pointer from the thread array, unless the dispatching\n");
3223   EMIT("     model is no-threading, in which case no thread array even exists. */\n");
3224   EMIT("  vmprefix_program_point jitter_ip = NULL; /* Invalidate to catch errors. */\n");
3225 
3226   /* EMIT("  /\* Declare a variable to be supposedly used as a computed goto target for jumping;\n"); */
3227   /* EMIT("     to any VM instruction; in actuality the variable is not ever accessed by reachable\n"); */
3228   /* EMIT("     code, but only mentioned in inline assembly constraints to force GCC to keep its\n"); */
3229   /* EMIT("     register allocation compatible between the end of a VM instruction and the beginning\n"); */
3230   /* EMIT("     of any other.  Assembly constraints will always require jitter_anywhere_label to be\n"); */
3231   /* EMIT("     in memory rather than in a register, so as not to waste one register on this. *\/\n"); */
3232   /* EMIT("  volatile union jitter_word jitter_anywhere_variable __attribute__ ((unused));\n\n"); */
3233 
3234   EMIT("#ifdef JITTER_REPLICATE\n");
3235   EMIT("  /* Save an instruction address within this function, to jump to at VM exit\n");
3236   EMIT("     time; that way we can be sure that at exit time we are back to\n");
3237   EMIT("     non-replicated code, and stuff like PC-relative addressing work again\n");
3238   EMIT("     without special tricks.  This variable may safely (and actually should,\n");
3239   EMIT("     for performance) be kept on the stack.  We need it to be volatile to\n");
3240   EMIT("     prevent the compiler from being too clever and jump to it using a\n");
3241   EMIT("     PC-relative displacement from replicated code.   It must not be static,\n");
3242   EMIT("     since non-automatic variables are problematic to access from replicated\n");
3243   EMIT("     code, which might use PC-relative addressing. */\n");
3244   EMIT("  volatile typeof (&& jitter_exit_vm_label) restrict\n");
3245   EMIT("  jitter_saved_exit_non_replicated_code_pointer = &&jitter_exit_vm_label;\n");
3246   EMIT("  JITTER_MARK_MEMORY_AS_SET_BY_ASSEMBLY(jitter_saved_exit_non_replicated_code_pointer);\n");
3247   EMIT("#endif // #ifdef JITTER_REPLICATE\n");
3248   EMIT("\n\n");
3249 
3250   // FIXME: move to a new function: BEGIN
3251   /* Generate a variable per non-relocatable specialized instruction holding the
3252      address where to jump out of the relocated code.  This will be useful as a
3253      jump target, in the first implementation of non-relocatability. */
3254   EMIT("#ifdef JITTER_REPLICATE\n");
3255   EMIT("  /* FIXME: comment. */\n");
3256   FOR_LIST(i, comma, vm->specialized_instructions)
3257     {
3258       const struct jitterc_specialized_instruction* sins
3259         = ((const struct jitterc_specialized_instruction*)
3260            gl_list_get_at (vm->specialized_instructions, i));
3261 
3262       /* Ignore special and relocatable specialized instructions. */
3263       if (sins->instruction == NULL
3264           || sins->relocatability == jitterc_relocatability_relocatable)
3265         continue;
3266 
3267       EMIT("  volatile void *JITTER_SPECIALIZED_INSTRUCTION_NON_RELOCATABLE_CODE_VARIABLE_OF(%s)\n",
3268            sins->mangled_name);
3269       EMIT("    = && JITTER_SPECIALIZED_INSTRUCTION_NON_RELOCATABLE_CODE_LABEL_OF(%s);\n",
3270            sins->mangled_name);
3271       EMIT("  asm volatile (\"#pretend to affect \" JITTER_STRINGIFY(JITTER_SPECIALIZED_INSTRUCTION_NON_RELOCATABLE_CODE_VARIABLE_OF(%s)) \"\\n\"\n", sins->mangled_name);
3272       EMIT("                : \"+m\" (JITTER_SPECIALIZED_INSTRUCTION_NON_RELOCATABLE_CODE_VARIABLE_OF(%s)));\n", sins->mangled_name);
3273     }
3274   EMIT("#endif // #ifdef JITTER_REPLICATE\n");
3275   // FIXME: move to a new function: END
3276 
3277   /* Insert C code from the user.  This is supposed to come in right before
3278      execution starts. */
3279   EMIT("  /* Initialization C code from the user */\n");
3280   EMIT("%s", vm->initialization_c_code);
3281   EMIT("  /* End of the initialization C code from the user */\n\n");
3282   EMIT("\n");
3283 
3284   /* Insert architecture-specific execution-beginning code. */
3285   EMIT("  /* Execute architecture-specific execution-beginning code, if any.\n");
3286   EMIT("     Make sure it is safe to expand the macro without do..while\n");
3287   EMIT("     (false). */\n");
3288   EMIT("  {}; JITTER_EXECUTION_BEGINNING_; {};\n");
3289   EMIT("\n");
3290 
3291   EMIT("#if defined (JITTER_PROFILE_SAMPLE)\n");
3292   EMIT("    /* Start sample-profiling: this starts the periodic timer signal,\n");
3293   EMIT("       whose handler will look at the current instruction field within\n");
3294   EMIT("       the special-purpose struct in the Array. */\n");
3295   EMIT("    vmprefix_profile_sample_start (VMPREFIX_OWN_STATE);\n");
3296   EMIT("#endif // #if defined (JITTER_PROFILE_SAMPLE)\n");
3297   EMIT("\n");
3298 
3299   EMIT("  /* Jump to the first instruction.  If replication is enabled this point\n");
3300   EMIT("     marks the boundary between the ordinary world of C compiled code and\n");
3301   EMIT("     the more fragile replicated code, where PC-relative address does\n");
3302   EMIT("     not work as intended (which prevents the use of global and static\n");
3303   EMIT("     variables, string literals and possibly large literal constants), and\n");
3304   EMIT("     GDB gets easily confused. */\n");
3305   EMIT("  jitter_ip = jitter_initial_program_point;\n\n");
3306   EMIT("  /* This is the actual jump to the first instruction: it's not an\n");
3307   EMIT("     inline asm constraint lie like below. */\n\n");
3308   EMIT("# if   defined(JITTER_DISPATCH_SWITCH)\n");
3309   EMIT("    goto jitter_dispatching_switch_label;\n");
3310   EMIT("# elif (defined(JITTER_DISPATCH_DIRECT_THREADING)  \\\n");
3311   EMIT("        || defined(JITTER_DISPATCH_MINIMAL_THREADING))\n");
3312   EMIT("    goto * (jitter_ip->label);\n");
3313   EMIT("# elif defined(JITTER_DISPATCH_NO_THREADING)\n");
3314   EMIT("    /* On no-threading we only use jitter_ip for the first instruction.\n");
3315   EMIT("       Make it an alias for the base, which will be enough to satisfy\n");
3316   EMIT("       inline assembly code which pretends to alter the instruction\n");
3317   EMIT("       pointer in ways invisible to the compiler.\n");
3318   EMIT("       At least in my tests this trick frees up one hardware register,\n");
3319   EMIT("       which is not surprising. */\n");
3320   EMIT("    goto * jitter_ip;\n");
3321   EMIT("#   define jitter_ip vmprefix_array_base_register_variable\n");
3322   EMIT("# else\n");
3323   EMIT("#   error \"unknown dispatch\"\n");
3324   EMIT("# endif // if ... dispatch\n");
3325 
3326   EMIT("  /* FIXME: comment: this is the fake dispatch routine. */\n");
3327   // FIXME: Is clobbering memory really needed?  It would be better if I didn't do this.
3328   //        I should explicitly mark as set the base and possibly the instruction pointer,
3329   //        but nothing more.
3330   //EMIT("  asm volatile (\"\" : : : \"memory\");\n");
3331   EMIT(" /* The label is unused (from the compiler's point of view) for simple\n");
3332   EMIT("    dispatches when not profiling.  (In reality it is always unused.)\n");
3333   EMIT("    FIXME: comment. */\n");
3334   EMIT(" jitter_dispatch_label: __attribute__ ((hot, unused))\n");
3335   // FIXME: same.
3336   //EMIT("  asm volatile (\"\\njitter_dispatch_label_asm:\\n\" : : : \"memory\");\n");
3337   EMIT("#if   defined(JITTER_DISPATCH_SWITCH)\n");
3338   EMIT("  /* This code is unreachable, but the compiler does not know it.  FIXME: comment. */\n");
3339   EMIT("  goto jitter_dispatching_switch_label;\n");
3340   EMIT("#elif defined(JITTER_DISPATCH_DIRECT_THREADING)\n");
3341   EMIT("  /* Again this code is unreachable, but the compiler does not know it.  FIXME: comment. */\n");
3342   EMIT("  goto * jitter_ip;\n");
3343   EMIT("#endif\n");
3344   EMIT("#ifdef JITTER_REPLICATE\n");
3345   EMIT("  asm volatile (\"\\njitter_dispatch_label_asm:\\n\" :);\n");
3346   EMIT("  JITTER_PRETEND_TO_UPDATE_IP_;\n");
3347   FOR_LIST(i, comma, vm->specialized_instructions)
3348     {
3349       EMIT("  JITTER_PRETEND_TO_UPDATE_IP_;\n");
3350       const struct jitterc_specialized_instruction* sins
3351         = ((const struct jitterc_specialized_instruction*)
3352            gl_list_get_at (vm->specialized_instructions, i));
3353       EMIT("  JITTER_PRETEND_TO_POSSIBLY_JUMP_TO_(JITTER_SPECIALIZED_INSTRUCTION_BEGIN_LABEL_OF(%s));\n",
3354            sins->mangled_name);
3355       /*
3356       EMIT("  JITTER_PRETEND_TO_UPDATE_IP_;\n");
3357       EMIT("  JITTER_PRETEND_TO_POSSIBLY_JUMP_TO_(JITTER_SPECIALIZED_INSTRUCTION_END_LABEL_OF(%s));\n",
3358            sins->mangled_name);
3359       */
3360     }
3361   //EMIT("  JITTER_PRETEND_TO_POSSIBLY_JUMP_TO_(a_label);\n");
3362   EMIT("  JITTER_PRETEND_TO_UPDATE_IP_;\n");
3363   EMIT("  JITTER_PRETEND_TO_POSSIBLY_JUMP_TO_(jitter_exit_vm_label);\n");
3364   EMIT("  JITTER_PRETEND_TO_UPDATE_IP_;\n");
3365   EMIT("  JITTER_PRETEND_TO_POSSIBLY_JUMP_TO_(jitter_possibly_restore_registers_and_return_label);\n");
3366   EMIT("  goto jitter_dispatch_label;\n");
3367   EMIT("#endif // #ifdef JITTER_REPLICATE\n\n");
3368 
3369   /* EMIT("#ifdef JITTER_REPLICATE\n"); */
3370   /* EMIT("  /\* This is actually unreachable, but I use GCC inline assembly with\n"); */
3371   /* EMIT("     constraints declaring to jump here just to force the compiler to\n"); */
3372   /* EMIT("     allocate registers at the end of each VM instruction in a compatible\n"); */
3373   /* EMIT("     way with the beginning of any other.  This code could, in theory,\n"); */
3374   /* EMIT("     jump to any label within this function -- in practice it would\n"); */
3375   /* EMIT("     crash horribly if ever reached, but that is not a problem. *\/\n"); */
3376   /* EMIT(" jitter_jump_anywhere_label: __attribute__ ((cold, unused));\n"); */
3377   /* EMIT("  jitter_next_program_point = && jitter_dispatch_label;\n"); */
3378   /* EMIT("  asm (JITTER_ASM_COMMENT_UNIQUE(\"Pretend to alter next_program_point\"\n"); */
3379   /* EMIT("                                 \" at %%[next_program_point] based on\"\n"); */
3380   /* EMIT("                                 \" jitter_state_runtime at %%[runtime]\"\n"); */
3381   /* EMIT("                                 \" and * jitter_original_state %%[jitter_original_state].\")\n"); */
3382   /* EMIT("       : [next_program_point] \"+m\" (jitter_next_program_point) // m\n"); */
3383   /* /\* About the constraints on [runtime], GCC 8 20170430 snapshot, */
3384   /*    tested on the JitterLisp VM: */
3385   /*    - "X": */
3386   /*       aarch64: invalid 'asm': invalid expression as operand */
3387   /*       alpha:   ok */
3388   /*       sh:      ok */
3389   /*    - "ro", "rom", "romg", "roX": */
3390   /*       aarch64: ok */
3391   /*       alpha:   cannot reload integer constant operand in 'asm' */
3392   /*       sh:      cannot reload integer constant operand in 'asm' */
3393   /*    Any constraint works on the other architectures I'm testing. */
3394 
3395   /*    This is ugly.  I consider SH to be important, and Aarch64 is popular. */
3396   /*    Alpha is lower-priority, but I like to support it as well.  This will */
3397   /*    need a conditional.  The "X" constraint is more reasonable, so I will */
3398   /*    single out aarch64. *\/ */
3399   /* EMIT("       : [runtime] \"X\" (jitter_state_runtime) // \"X\"\n"); */
3400   /* EMIT("         , [jitter_original_state] \"m\" (* jitter_original_state) // m\n"); */
3401   /* EMIT("      );\n"); */
3402   /* EMIT("  goto * jitter_next_program_point;\n"); */
3403   /* EMIT("#endif // #ifdef JITTER_REPLICATE\n"); */
3404   /* EMIT("\n"); */
3405 
3406   /* Generate the switch dispatcher, which expands to nothing unless
3407      switch-dispatching is enabled. */
3408   EMIT("#ifdef JITTER_DISPATCH_SWITCH\n");
3409   EMIT("  /* This is the dispatching switch.  At the beginning of the first VM\n");
3410   EMIT("     VM instruction and at the end of each other, control jumps here. */\n");
3411   EMIT(" jitter_dispatching_switch_label:\n");
3412   EMIT("  switch (jitter_ip->fixnum)\n");
3413   EMIT("    {\n");
3414   EMIT("#endif // #ifdef JITTER_DISPATCH_SWITCH\n");
3415   EMIT("\n");
3416 
3417   /* Generate code for special specialized instructions.  This has to be kept
3418      manually synchronized with jitterc-vm.c in case I add, remove or change
3419      any special specialized instruction. */
3420 
3421   jitterc_emit_executor_special_specialized_instruction
3422      (f, vm, "!INVALID",
3423       jitter_specialized_instruction_opcode_INVALID,
3424       "cold", 0,
3425       "jitter_fatal (\"reached the !INVALID instruction\");");
3426   jitterc_emit_executor_special_specialized_instruction
3427      (f, vm, "!BEGINBASICBLOCK",
3428       jitter_specialized_instruction_opcode_BEGINBASICBLOCK,
3429       "hot", /* This zero is a special case.  FIXME: explain. */0,
3430       "#ifdef JITTER_DISPATCH_MINIMAL_THREADING\n"
3431       "  JITTER_SET_IP (jitter_ip + 1);\n"
3432       "#endif // #ifdef JITTER_DISPATCH_MINIMAL_THREADING\n");
3433   jitterc_emit_executor_special_specialized_instruction
3434      (f, vm, "!EXITVM",
3435       jitter_specialized_instruction_opcode_EXITVM,
3436       "cold", 0, "JITTER_EXIT();");
3437   jitterc_emit_executor_special_specialized_instruction_beginning
3438      (f, vm, "!DATALOCATIONS",
3439       jitter_specialized_instruction_opcode_DATALOCATIONS,
3440       "cold", 0);
3441   jitterc_emit_executor_data_locations (f, vm);
3442   jitterc_emit_executor_special_specialized_instruction_end
3443      (f, vm, "!DATALOCATIONS",
3444       jitter_specialized_instruction_opcode_DATALOCATIONS,
3445       "cold", 0);
3446   jitterc_emit_executor_special_specialized_instruction
3447      (f, vm, "!NOP",
3448       jitter_specialized_instruction_opcode_NOP,
3449       "cold", 0, "  /* Do nothing. */;");
3450   jitterc_emit_executor_special_specialized_instruction
3451      (f, vm, "!UNREACHABLE0",
3452       jitter_specialized_instruction_opcode_UNREACHABLE0,
3453       "cold", 0,
3454       "jitter_fatal (\"reached the !UNREACHABLE0 instruction\");");
3455   jitterc_emit_executor_special_specialized_instruction
3456      (f, vm, "!UNREACHABLE1",
3457       jitter_specialized_instruction_opcode_UNREACHABLE1,
3458       "cold", 0,
3459       "jitter_fatal (\"reached the !UNREACHABLE1 instruction\");");
3460   jitterc_emit_executor_special_specialized_instruction
3461      (f, vm, "!UNREACHABLE2",
3462       jitter_specialized_instruction_opcode_UNREACHABLE2,
3463       "cold", 0,
3464       "jitter_fatal (\"reached the !UNREACHABLE2 instruction\");");
3465 
3466   /* Generate code for the ordinary specialized instructions as specified in
3467      user code. */
3468   jitterc_emit_executor_ordinary_specialized_instructions (f, vm);
3469 
3470   /* Close the dispatcher switch; of course this will expand to nothing unless
3471      switch-dispatching is enabled. */
3472   EMIT("#ifdef JITTER_DISPATCH_SWITCH\n");
3473   EMIT("  default:\n");
3474   EMIT("    jitter_fatal (\"invalid opcode %%li for VM specialized instruction\",\n");
3475   EMIT("                  (long) jitter_ip->fixnum);\n");
3476   EMIT("  } /* switch */\n");
3477   EMIT("#endif // #ifdef JITTER_DISPATCH_SWITCH\n");
3478   EMIT("\n");
3479 
3480   /* Emit the final part of the function, consisting in the label to jump to
3481      before exiting from the executor. */
3482   EMIT("  /* The code jumps here when executing the special specialized instruction\n");
3483   EMIT("     EXITVM, or on a call to the macro JITTER_EXIT from an ordinary specialized\n");
3484   EMIT("     instruction.  This code is *not* replicated: when replication is enabled\n");
3485   EMIT("     jumping here means crossing the boundary from the fragaile replicated\n");
3486   EMIT("     code back into ordinary compiled C, where PC-relative addressing works. */\n");
3487   EMIT("  jitter_exit_vm_label: __attribute__ ((cold));\n");
3488   EMIT("    JITTER_COMMENT_IN_ASM_(\"About to exit the function\");\n");
3489   EMIT("    // fprintf (stderr, \"Restoring the VM state to the struct...\\n\");\n");
3490   EMIT("    /* Copy the VM state from the local copy we have modified back to\n");
3491   EMIT("       the structure to which we received a pointer. */\n");
3492   EMIT("    jitter_original_state->vmprefix_state_runtime = jitter_state_runtime;\n");
3493   EMIT("\n");
3494   EMIT("    // fprintf (stderr, \"Exiting the VM...\\n\");\n\n");
3495   EMIT("\n");
3496   EMIT("#if defined (JITTER_PROFILE_SAMPLE)\n");
3497   EMIT("    /* Stop sample-profiling: this stops the periodic timer signal, while\n");
3498   EMIT("       we are no longer updating the current instruction field within the\n");
3499   EMIT("       special-purpose struct in the Array. */\n");
3500   EMIT("    vmprefix_profile_sample_stop ();\n");
3501   EMIT("#endif // #if defined (JITTER_PROFILE_SAMPLE)\n");
3502   EMIT("\n");
3503 
3504   /* Emit the patch-in footer.  This must come after every patch-in or defect
3505      use. */
3506   jitterc_emit_patch_in_footer (f, vm);
3507 
3508   /* Insert C code from the user.  This is supposed to come in right after
3509      execution ends. */
3510   EMIT("  /* Finalization C code from the user */\n");
3511   EMIT("%s", vm->finalization_c_code);
3512   EMIT("  /* End of the finalization C code from the user */\n\n");
3513   EMIT("\n");
3514 
3515   /* Insert architecture-specific execution-end code. */
3516   EMIT("  /* Execute architecture-specific execution-end code, if any.  Make \n");
3517   EMIT("     sure it is safe to expand the macro without do..while (false). */\n");
3518   EMIT("  {}; JITTER_EXECUTION_END_; {};\n");
3519   EMIT("\n");
3520 
3521   EMIT("  /* This program point is reachable for both thread initialization and\n");
3522   EMIT("     execution.  In either case it is not performance-critical. */\n");
3523   EMIT("  jitter_possibly_restore_registers_and_return_label: __attribute__ ((cold));\n");
3524   EMIT("    //if (jitter_initialize) puts (\"-- RETURNING FROM INITIALIZATION\\n\");\n");
3525   EMIT("#ifdef JITTER_DISPATCH_NO_THREADING\n");
3526   EMIT("    /* Back to regular C without our reserved registers: restore the\n");
3527   EMIT("       values held in such registers at entry. */\n");
3528   EMIT("    vmprefix_restore_registers (jitter_register_buffer);\n");
3529   EMIT("#endif // #ifdef JITTER_DISPATCH_NO_THREADING\n");
3530 
3531   // FIXME: this is a test, for profiling: begin
3532   EMIT("#ifdef JITTER_PROFILE\n");
3533   EMIT("#define PROFILING_SPACE (1024 * 1024 * 100)\n");
3534   EMIT("    if (jitter_initialize)\n");
3535   EMIT("      fprintf (stderr, \"Profiling space: [%%p, %%p)\\n\", && vmprefix_profiling_space, ((char *) (&& vmprefix_profiling_space)) + PROFILING_SPACE);\n");
3536   EMIT("    /* Do an indirect jump to the return statement rather than a simple\n");
3537   EMIT("       conditional.  With this trick I can afford even a very large gap\n");
3538   EMIT("       within the code for a single C function, without being constrained\n");
3539   EMIT("       by branch offset limits on any architecture. */\n");
3540   EMIT("    void *return_address_variable = && return_label;\n");
3541   EMIT("    JITTER_MARK_LVALUE_AS_SET_BY_ASSEMBLY (return_address_variable);\n");
3542   EMIT("    goto *return_address_variable;\n");
3543   EMIT("  vmprefix_profiling_space: __attribute__ ((unused)) // FIXME: do this from assembly\n");
3544   EMIT("    asm volatile (\".fill (\" JITTER_STRINGIFY(PROFILING_SPACE) \")\");\n");
3545   EMIT("  return_label:\n");
3546   EMIT("#endif // #ifdef JITTER_PROFILE\n");
3547   EMIT("    return;\n");
3548   // FIXME: this is a test, for profiling: end
3549   EMIT("}\n");
3550   EMIT("\n");
3551 }
3552 
3553 /* FIXME: move to a template.  This might need a forward declarartion for the
3554    main execute-or-initialize function, currently relying on complicated
3555    function attributes; but that will be simplified. */
3556 void
jitterc_emit_executor_wrappers(FILE * f,const struct jitterc_vm * vm)3557 jitterc_emit_executor_wrappers
3558    (FILE *f, const struct jitterc_vm *vm)
3559 {
3560   /* This function is the most critical to compile with the right GCC options;
3561      for any threading model more sophisticated than direct threading this is a
3562      matter of correctness, not just efficiency. */
3563   EMIT("/* The definition of this is machine-generated in vmprefix-vm2.c , and the\n");
3564   EMIT("   function is not intended for the user.  If initializing then set\n");
3565   EMIT("   structuredvm_threads and structuredvm_thread_sizes and just return, ignoring\n");
3566   EMIT("   the other fieldsp and s.  If not initializing then actually enter VM code\n");
3567   EMIT("   starting from the given program point in the pointed state. */\n");
3568   EMIT("static void\n");
3569   EMIT("vmprefix_execute_or_initialize (bool jitter_initialize,\n");
3570   EMIT("                                vmprefix_program_point jitter_initial_program_point,\n");
3571   EMIT("                                struct vmprefix_state * const jitter_original_state)\n");
3572   EMIT("  __attribute__ ((noclone, noinline));\n");
3573   EMIT("\n");
3574   EMIT("void\n");
3575   EMIT("vmprefix_execute_executable_routine (const struct jitter_executable_routine *er,\n");
3576   EMIT("                                     struct vmprefix_state *s)\n");
3577   EMIT("{\n");
3578   EMIT("  vmprefix_make_place_for_slow_registers (s, er->slow_register_per_class_no);\n");
3579   EMIT("  jitter_program_point initial_program_point\n");
3580   EMIT("    = VMPREFIX_EXECUTABLE_ROUTINE_BEGINNING (er);\n");
3581   EMIT("  vmprefix_execute_or_initialize (false, initial_program_point, s);\n");
3582   EMIT("}\n");
3583   EMIT("\n");
3584   EMIT("\n");
3585   EMIT("/* Threads or pointers to native code blocks of course don't exist with\n");
3586   EMIT("   switch-dispatching. */\n");
3587   EMIT("#ifndef JITTER_DISPATCH_SWITCH\n");
3588   EMIT("const jitter_thread *\n");
3589   EMIT("vmprefix_threads;\n");
3590   EMIT("\n");
3591   EMIT("const jitter_thread *\n");
3592   EMIT("vmprefix_thread_ends;\n");
3593   EMIT("\n");
3594   EMIT("const long *\n");
3595   EMIT("vmprefix_thread_sizes;\n");
3596   EMIT("#endif // #ifndef JITTER_DISPATCH_SWITCH\n");
3597   EMIT("\n");
3598 
3599   EMIT("void\n");
3600   EMIT("vmprefix_initialize_threads (void)\n");
3601   EMIT("{\n");
3602   EMIT("  vmprefix_execute_or_initialize (true, NULL, NULL);\n");
3603   EMIT("}\n");
3604   EMIT("\n");
3605 
3606   EMIT("void\n");
3607   EMIT("vmprefix_branch_to_program_point (vmprefix_program_point p, struct vmprefix_state *s)\n");
3608   EMIT("{\n");
3609   EMIT("  vmprefix_execute_or_initialize (false, p, s);\n");
3610   EMIT("}\n");
3611   EMIT("\n");
3612 }
3613 
3614 /* Emit definitions for JITTER_VM_PREFIX_LOWER_CASE and
3615    JITTER_VM_PREFIX_UPPER_CASE .  These should not go to public headers, but
3616    they are convenient to have in more than one generated C file. */
3617 static void
jitterc_emit_vm_name_macros(const struct jitterc_vm * vm,const char * basename)3618 jitterc_emit_vm_name_macros (const struct jitterc_vm *vm, const char *basename)
3619 {
3620   FILE *f = jitterc_fopen_a_basename (vm, basename);
3621   /* Generate private macro definitions in the JITTER_ namespace, not exported
3622      to the user via headers.  These are useful to compose VM-specific
3623      identifiers via CPP token concatenation, in a way which is unobstrusive to
3624      the user.  */
3625   EMIT("/* These two macros are convenient for making VM-specific identifiers\n");
3626   EMIT("   using VM-independent macros from a public header, without polluting\n");
3627   EMIT("   the global namespace. */\n");
3628   EMIT("#define JITTER_VM_PREFIX_LOWER_CASE %s\n", vm->lower_case_prefix);
3629   EMIT("#define JITTER_VM_PREFIX_UPPER_CASE %s\n", vm->upper_case_prefix);
3630   EMIT("\n");
3631   jitterc_fclose (f);
3632 }
3633 
3634 /* Do the job of jitterc_emit_vm_name_macros for the two generated .c files */
3635 static void
jitterc_emit_vm_name_macros_vm1(const struct jitterc_vm * vm)3636 jitterc_emit_vm_name_macros_vm1 (const struct jitterc_vm *vm)
3637 {
3638   jitterc_emit_vm_name_macros (vm, "vm1.c");
3639 }
3640 static void
jitterc_emit_vm_name_macros_vm2(const struct jitterc_vm * vm)3641 jitterc_emit_vm_name_macros_vm2 (const struct jitterc_vm *vm)
3642 {
3643   jitterc_emit_vm_name_macros (vm, "vm2.c");
3644 }
3645 
3646 static void
jitterc_emit_executor_general_purpose_state_data_access_macros(FILE * f,const struct jitterc_vm * vm)3647 jitterc_emit_executor_general_purpose_state_data_access_macros
3648    (FILE *f, const struct jitterc_vm *vm)
3649 {
3650   EMIT("/* Most of the needed macros are in jitter-executor.h .  This however\n");
3651   EMIT("   needs to be here, as it relies on a prefix to be substituted. */\n");
3652   EMIT("#define JITTER_STATE_BACKING  \\\n");
3653   EMIT("  (jitter_original_state->vmprefix_state_backing)\n");
3654 }
3655 
3656 /* Emit access macros for special-purpose data, to be used from VM code. */
3657 static void
jitterc_emit_executor_special_purpose_state_data_access_macros(FILE * f,const struct jitterc_vm * vm)3658 jitterc_emit_executor_special_purpose_state_data_access_macros
3659    (FILE *f, const struct jitterc_vm *vm)
3660 {
3661   EMIT("/* Expand to an l-value evaluating to the pending_notification field for\n");
3662   EMIT("   the current state. */\n");
3663   EMIT("#define JITTER_PENDING_NOTIFICATIONS  \\\n");
3664   EMIT("  (VMPREFIX_OWN_SPECIAL_PURPOSE_STATE_DATA->pending_notifications)\n");
3665   EMIT("/* Expand to an l-value evaluating to the pending field of the struct\n");
3666   EMIT("   jitter_signal_notification element for the given signal, for the\n");
3667   EMIT("   current state. */\n");
3668   EMIT("#define JITTER_PENDING_SIGNAL_NOTIFICATION(signal_id)  \\\n");
3669   EMIT("  ((VMPREFIX_OWN_SPECIAL_PURPOSE_STATE_DATA->pending_signal_notifications + (signal_id))->pending)\n");
3670   EMIT("\n");
3671 }
3672 
3673 static void
jitterc_emit_executor(const struct jitterc_vm * vm)3674 jitterc_emit_executor (const struct jitterc_vm *vm)
3675 {
3676   FILE *f = jitterc_fopen_a_and_remember_basename (vm, "vm2.c");
3677   EMIT("//#include <config.h>\n\n");
3678 
3679   EMIT("#include <stdbool.h>\n");
3680   EMIT("#include <stdio.h>\n");
3681   EMIT("#include <stdlib.h>\n\n");
3682 
3683   /* Insert C code from the user.  This is supposed to come in very early,
3684      before most includes. */
3685   EMIT("/* Early C code from the user. */\n");
3686   EMIT("%s", vm->early_c_code);
3687   EMIT("/* End of the early C code from the user. */\n\n");
3688 
3689   EMIT("#include <jitter/jitter.h>\n");
3690   EMIT("#include <jitter/jitter-instruction.h>\n\n");
3691   EMIT("#define JITTER_THIS_CAN_INCLUDE_JITTER_EXECUTOR_H\n");
3692   EMIT("#include <jitter/jitter-executor.h>\n\n");
3693 
3694   EMIT("#ifdef JITTER_ENABLE_ASSEMBLY\n");
3695   EMIT("#include <jitter/jitter-machine-common.h>\n");
3696   EMIT("#include <jitter/machine/jitter-machine.h>\n");
3697   EMIT("#endif // #ifdef JITTER_ENABLE_ASSEMBLY\n");
3698 
3699   EMIT("#include <jitter/jitter-fatal.h>\n");
3700   EMIT("#include <jitter/jitter-malloc.h>\n\n");
3701 
3702   EMIT("#include \"vmprefix-vm.h\"\n");
3703   EMIT("//#include \"vmprefix-meta-instructions.h\"\n");
3704   EMIT("//#include \"vmprefix-specialized-instructions.h\"\n");
3705   EMIT("//#include \"vmprefix-state.h\"\n\n");
3706 
3707   EMIT("/* Include stack data structure support. */\n");
3708   EMIT("#include <jitter/jitter-stack.h>\n\n");
3709 
3710   EMIT("/* Include patch-in definitions, only if patch-in is enabled.  We knoe whether it is\n");
3711   EMIT("   by checking JITTER_HAVE_PATCH_IN , defined in jitter/jitter-patch-in.h . */\n");
3712   EMIT("#include <jitter/jitter-patch-in.h>\n");
3713   EMIT("#ifdef JITTER_HAVE_PATCH_IN\n");
3714   EMIT("# include <jitter/jitter-fast-branch.h>\n");
3715   EMIT("\n");
3716   EMIT("  JITTER_DEFECT_DESCRIPTOR_DECLARATIONS_(vmprefix);\n");
3717   EMIT("  JITTER_PATCH_IN_DESCRIPTOR_DECLARATIONS_(vmprefix);\n");
3718   EMIT("#endif // #ifdef JITTER_HAVE_PATCH_IN\n\n");
3719 
3720   EMIT("/* Always include fast-branch definitions, which use patch-ins where possible\n");
3721   EMIT("   or consist in fallback definitions otherwise. */\n");
3722   EMIT("#include <jitter/jitter-fast-branch.h>\n\n");
3723   EMIT("#define JITTER_FAST_BRANCH_PREFIX vmprefix_\n\n");
3724 
3725   /* Emit macros to access general-purpose state data. */
3726   jitterc_emit_executor_general_purpose_state_data_access_macros (f, vm);
3727 
3728   /* Emit macros to access special-purpose state data. */
3729   jitterc_emit_executor_special_purpose_state_data_access_macros (f, vm);
3730 
3731   /* Emit register-access macros. */
3732   jitterc_emit_executor_register_access_macros (f, vm);
3733 
3734   /* Emit global register code. */
3735   jitterc_emit_executor_reserve_registers (f, vm);
3736 
3737   /* Emit CPP definitions for stack operations. */
3738   jitterc_emit_stack_operation_definitions (f, vm);
3739 
3740   /* Insert C code from the user.  This is supposed to come in late, after CPP
3741      includes and definitions, right before the executor functions. */
3742   EMIT("/* Late C code from the user. */\n");
3743   EMIT("%s", vm->before_main_c_code);
3744   EMIT("/* End of the late C code from the user. */\n\n");
3745 
3746   /* Generate a few easy wrapper functions calling vmprefix_execute_or_initialize ,
3747      which are the actual entry points into this compilation unit. */
3748   jitterc_emit_executor_wrappers (f, vm);
3749 
3750   /* Emit the main executor/initialization function. */
3751   jitterc_emit_executor_main_function (f, vm);
3752 
3753   jitterc_fclose (f);
3754 }
3755 
3756 
3757 
3758 
3759 /* File copying utility.
3760  * ************************************************************************** */
3761 
3762 static void
jitterc_copy_file_to_tmp(struct jitterc_vm * vm,const char * to_basename,const char * from_pathname)3763 jitterc_copy_file_to_tmp (struct jitterc_vm *vm,
3764                           const char *to_basename,
3765                           const char *from_pathname)
3766 {
3767   FILE *to_stream = jitterc_fopen_a_and_remember_basename (vm, to_basename);
3768   FILE *from_stream = jitterc_fopen_r_pathname (from_pathname);
3769   while (! feof (from_stream))
3770     {
3771       int c = fgetc (from_stream);
3772       if (c == EOF)
3773         break;
3774       EMIT_TO(to_stream, "%c", c);
3775     }
3776   jitterc_fclose (to_stream);
3777   jitterc_fclose (from_stream);
3778 }
3779 
3780 static void
jitterc_copy_template_to_tmp(struct jitterc_vm * vm,const char * basename)3781 jitterc_copy_template_to_tmp (struct jitterc_vm *vm,
3782                                 const char *basename)
3783 {
3784   size_t basename_size
3785     = strlen (vm->template_directory) + 1 + strlen (basename) + 1;
3786   char *from_pathname = xmalloc (basename_size);
3787   sprintf (from_pathname, "%s/%s", vm->template_directory, basename);
3788 
3789   jitterc_copy_file_to_tmp (vm, basename, from_pathname);
3790   free (from_pathname);
3791 }
3792 
3793 static void
jitterc_copy_templates_to_tmp(struct jitterc_vm * vm,bool generate_frontend)3794 jitterc_copy_templates_to_tmp (struct jitterc_vm *vm,
3795                                bool generate_frontend)
3796 {
3797   jitterc_copy_template_to_tmp (vm, "vm1.c");
3798   jitterc_copy_template_to_tmp (vm, "vm.h");
3799   if (generate_frontend)
3800     jitterc_copy_template_to_tmp (vm, "vm-main.c");
3801 }
3802 
3803 
3804 
3805 
3806 /* Template and temporary file handling.
3807  * ************************************************************************** */
3808 
3809 /* Copy files from the temporary directory to the actual output directory,
3810    replacing prefixes. */
3811 
3812 /* Return a malloc-allocated string holding the full content of the named
3813    text file, failing fatally on any error. */
3814 static char *
jitterc_file_content(const char * pathname)3815 jitterc_file_content (const char *pathname)
3816 {
3817   /* Read the whole input into core. */
3818   FILE *from_stream = jitterc_fopen_r_pathname (pathname);
3819   size_t allocated_length = 15;
3820   char *buffer = xmalloc (allocated_length + 1);
3821   size_t used_size = 0;
3822   while (! feof (from_stream))
3823     {
3824       int c = fgetc (from_stream);
3825       if (c == EOF)
3826         break;
3827 
3828       buffer [used_size ++] = c;
3829       if ((used_size + 1) >= allocated_length)
3830         buffer = xrealloc (buffer, allocated_length *= 2);
3831     }
3832   assert (used_size < allocated_length);
3833   buffer [used_size] = '\0';
3834   jitterc_fclose (from_stream);
3835 
3836   /* Return the buffer, trimmed so as not to waste memory. */
3837   return xrealloc (buffer, strlen (buffer) + 1);
3838 }
3839 
3840 /* Replace every occurrence of from_string with to_string within in_string,
3841    which must be malloc-allocated.  Free in_string and return a new copy of it,
3842    allocated with malloc, with the substitution performed.
3843    Doing this in core sounds inefficient in terms of memory use, but I don't
3844    feel like implementing Knuth-Morris-Pratt from scratch when in practice we
3845    will always work with files of modest size. */
3846 __attribute__ ((warn_unused_result, nonnull (1, 2, 3)))
3847 static char*
jitterc_filter_and_realloc_string(char * in_string,const char * to_string,const char * from_string)3848 jitterc_filter_and_realloc_string (char *in_string,
3849                                    const char *to_string,
3850                                    const char *from_string)
3851 {
3852   /* It's not clear what the right thing to do would be if from_string were an
3853      empty string; it's probably a useless case to support anyway.  Instead
3854      to_string and in_string are allowed to be empty. */
3855   size_t from_string_length = strlen (from_string);
3856   assert (from_string_length > 0);
3857   size_t to_string_length = strlen (to_string);
3858   size_t in_string_length = strlen (in_string);
3859 
3860   /* Compute a safe upper bound on the result size, and allocate a sufficiently
3861      large buffer. */
3862   size_t greater_length = (from_string_length > to_string_length)
3863                           ? from_string_length
3864                           : to_string_length;
3865   size_t out_string_size
3866     = (size_t)
3867       (in_string_length * ((double) greater_length) / from_string_length)
3868       /* Add one unit in case we round up, plus another for the final '\0'. */
3869       + 1 + 1;
3870   char *out_string = xmalloc (out_string_size);
3871 
3872   /* Copy the input buffer text to the output stream, with replacements. */
3873   char *in_pointer = in_string, *out_pointer = out_string;
3874   char *next_occurrence;
3875   /* As long as we can find an occurrence of from_string ... */
3876   while ((next_occurrence = strstr (in_pointer, from_string)) != NULL)
3877     {
3878       /* We found an occurrence.  Copy the part of the text we haven't copied
3879          yet. */
3880       size_t literally_copied_length = next_occurrence - in_pointer;
3881       memcpy (out_pointer, in_pointer, literally_copied_length);
3882 
3883       /* We stopped right before the occurrence of from_string in the input
3884          text.  But of course instead of writing from_string now we need to
3885          write its replacement. */
3886       memcpy (out_pointer + literally_copied_length, to_string,
3887               to_string_length);
3888 
3889       /* The next point to search in the input starts right after the end of
3890          from_string in the input buffer.  Advance to_pointer as well by
3891          skipping the length of to_string . */
3892       in_pointer = next_occurrence + from_string_length;
3893       out_pointer += literally_copied_length + to_string_length;
3894     }
3895   /* Copy the input text after the last occurrence until the end, including the
3896      final '\0'. */
3897   strcpy (out_pointer, in_pointer);
3898 
3899   /* Free the input string and return the output string we filled, trimmed so as
3900      not to waste memory. */
3901   free (in_string);
3902   return xrealloc (out_string, strlen (out_string) + 1);
3903 }
3904 
3905 
3906 
3907 
3908 /* Template and temporary file moving.
3909  * ************************************************************************** */
3910 
3911 /* Move a single file from the given path to the given path, replacing the VM
3912    prefix in the content. */
3913 static void
jitterc_fix_and_move(const struct jitterc_vm * vm,const char * to_pathname,const char * from_pathname)3914 jitterc_fix_and_move (const struct jitterc_vm *vm,
3915                       const char *to_pathname,
3916                       const char *from_pathname)
3917 {
3918   /* Read the input file to core. */
3919   char *content = jitterc_file_content (from_pathname);
3920 
3921   /* Perform the replacements. */
3922   content
3923     = jitterc_filter_and_realloc_string (content,
3924                                            vm->lower_case_prefix,
3925                                            INPUT_LOWER_CASE_PREFIX);
3926   content
3927     = jitterc_filter_and_realloc_string (content,
3928                                            vm->upper_case_prefix,
3929                                            INPUT_UPPER_CASE_PREFIX);
3930 
3931   /* Write the modified text to the output file, and free it. */
3932   FILE *to_stream = jitterc_fopen_w_pathname (to_pathname);
3933   EMIT_TO(to_stream, "%s", content);
3934   jitterc_fclose (to_stream);
3935   free (content);
3936 
3937   /* Remove the original file, which is supposed to be in the temporary
3938      directory if this function is called as intended.  Errors are not fatal
3939      here.  FIXME: warn? */
3940   unlink (from_pathname);
3941 }
3942 
3943 /* Move generated files from the temporary directory to the final directory,
3944    replacing the prefix in the content and prepending the prefix to
3945    basenames. */
3946 static void
jitterc_fix_and_move_files_from_tmp(const struct jitterc_vm * vm)3947 jitterc_fix_and_move_files_from_tmp (const struct jitterc_vm *vm)
3948 {
3949   int i; char *comma __attribute__ ((unused));
3950   size_t to_directory_length = strlen (vm->directory);
3951   size_t tmp_directory_length = strlen (vm->tmp_directory);
3952   size_t prefix_length = strlen (vm->lower_case_prefix);
3953   FOR_LIST(i, comma, vm->written_file_names)
3954     {
3955       const char *basename = gl_list_get_at (vm->written_file_names, i);
3956       size_t tmp_pathname_length
3957         = tmp_directory_length + 1 + strlen (basename) + 1;
3958       char *tmp_pathname = xmalloc (tmp_pathname_length);
3959       sprintf (tmp_pathname, "%s/%s", vm->tmp_directory, basename);
3960       size_t to_pathname_length
3961         = to_directory_length + 1 + prefix_length + 1 + strlen (basename) + 1;
3962       char *to_pathname = xmalloc (to_pathname_length);
3963       sprintf (to_pathname, "%s/%s-%s",
3964                vm->directory, vm->lower_case_prefix, basename);
3965       jitterc_fix_and_move (vm, to_pathname, tmp_pathname);
3966       free (tmp_pathname);
3967       free (to_pathname);
3968     }
3969 
3970   /* Remove the temporary directory.  It makes no sense to fail fatally in this
3971      case, since the result is usable.  FIXME: warn? */
3972   rmdir (vm->tmp_directory);
3973 }
3974 
3975 
3976 
3977 /* Entry point.
3978  * ************************************************************************** */
3979 
3980 void
jitterc_generate(struct jitterc_vm * vm,bool generate_frontend,const char * template_directory,const char * output_directory)3981 jitterc_generate (struct jitterc_vm *vm,
3982                   bool generate_frontend,
3983                   const char *template_directory,
3984                   const char *output_directory)
3985 {
3986   assert (vm->template_directory == NULL);
3987   assert (vm->directory == NULL);
3988   assert (vm->tmp_directory == NULL);
3989 
3990   /* Set directories in the VM data structure.  Make output directories if needed. */
3991   vm->template_directory = jitter_clone_string (template_directory);
3992   vm->directory = jitter_clone_string (output_directory);
3993   jitterc_mkdir (vm->directory);
3994   char *tmp = getenv ("TMPDIR");
3995   if (tmp == NULL)
3996     tmp = "/tmp";
3997   char *tmp_directory_basename = "jitterc-XXXXXX";
3998   vm->tmp_directory
3999     = xmalloc (strlen (tmp) + 1 + strlen (tmp_directory_basename) + 1);
4000   sprintf (vm->tmp_directory, "%s/%s", tmp, tmp_directory_basename);
4001   if (mkdtemp (vm->tmp_directory) == NULL)
4002     jitter_fatal ("could not make the temporary directory %s",
4003                    vm->tmp_directory);
4004 
4005   /* Emit the code part coming *before* templates. */
4006   const char *initial_comment
4007     = "/* This code is machine-generated.  See its source for license\n"
4008       "   information. This software is derived from software\n"
4009       "   distributed under the GNU GPL version 3 or later. */\n\n";
4010   jitterc_emit_text_to_stream (vm, "vm.h",  initial_comment);
4011   jitterc_emit_initial_header_c (vm);
4012   jitterc_emit_text_to_stream (vm, "vm1.c",  initial_comment);
4013   jitterc_emit_initial_vm1_c (vm);
4014   jitterc_emit_text_to_stream (vm, "vm2.c",  initial_comment);
4015   jitterc_emit_initial_vm2_c (vm);
4016   if (generate_frontend)
4017     {
4018       /* Nothing is really customizable in vm-main.c ; but I can emit user code,
4019          and only that, if vm-main.c is actually used. */
4020       jitterc_emit_text_to_stream (vm, "vm-main.c",  initial_comment);
4021       jitterc_emit_initial_vm_main_c (vm);
4022     }
4023 
4024   /* Copy all the templates to the temporary directory. */
4025   jitterc_copy_templates_to_tmp (vm, generate_frontend);
4026 
4027   /* Append machine-generated code to the copied templates in the temporary
4028      directory, and generate a separate file for the heavyweight part.  Perform
4029      no prefix-replacement yet. */
4030   jitterc_emit_early_header_c (vm);
4031   jitterc_emit_configuration_macros (vm);
4032   jitterc_emit_register_classes_h (vm);
4033   jitterc_emit_state_h (vm);
4034   jitterc_emit_meta_instructions_h (vm);
4035   jitterc_emit_specialized_instructions_h (vm);
4036   jitterc_emit_register_access_macros_h (vm);
4037   jitterc_emit_late_header_c (vm);
4038   jitterc_emit_header_closing (vm);
4039 
4040   /* From this point on the generated code goes to vm1.c . */
4041   jitterc_emit_vm_name_macros_vm1 (vm);
4042   jitterc_emit_printer_c (vm);
4043   jitterc_emit_meta_instructions (vm);
4044   jitterc_emit_register_classes (vm);
4045   jitterc_emit_specialized_instruction_names (vm);
4046   jitterc_emit_specialized_instruction_residual_arities (vm);
4047   jitterc_emit_specialized_instruction_label_bitmasks (vm);
4048   jitterc_emit_specialized_instruction_fast_label_bitmasks (vm);
4049   jitterc_emit_specialized_instruction_relocatables (vm);
4050   jitterc_emit_specialized_instruction_callers (vm);
4051   jitterc_emit_specialized_instruction_callees (vm);
4052   jitterc_emit_specialized_instruction_to_unspecialized_instruction (vm);
4053   jitterc_emit_worst_case_defect_table (vm);
4054   jitterc_emit_rewriter (vm);
4055   jitterc_emit_specializer (vm);
4056   jitterc_emit_state (vm);
4057 
4058   /* From this point on the generated code goes to vm2.c . */
4059   jitterc_emit_vm_name_macros_vm2 (vm);
4060   jitterc_emit_executor (vm);
4061 
4062   /* Move files from the temporary directory to their actual destination,
4063      replacing prefixes in the content and also prepending the prefix to
4064      the final basenames. */
4065   jitterc_fix_and_move_files_from_tmp (vm);
4066 }
4067 
4068 
4069 /* This Emacs Lisp function is convenient for turning hand-written C code into
4070    code for generating it.  It's not necessarily intended for the user, but
4071    comes in handy for editing this file.
4072 
4073 (defun replace-region-with-emits (beginning end)
4074   (interactive "r")
4075   (save-mark-and-excursion
4076     (save-restriction
4077       (narrow-to-region beginning end)
4078       (let ((pairs '(("\\\\" . "\\\\\\\\")
4079                      ("%" . "%%")
4080                      ("\"" . "\\\\\"")
4081                      ("^" . "EMIT(\"")
4082                      ("$" . "\\\\n\");")))
4083             (case-replace t)
4084             (case-fold-search t)
4085             (fill-prefix nil)
4086             (indent-region-function nil))
4087         (dolist (pair pairs)
4088           (goto-char (point-min))
4089           (replace-regexp (car pair) (cdr pair)))))))
4090 */
4091 
4092 /* FIXME: what about this hack?
4093    #define STRING(...) #__VA_ARGS__
4094 
4095    It works fine, but the C++ (and, I guess C as well) standard only requires
4096    compilers to accept a limited-length logical line.  This limit is 65536
4097    characters, which should be enough if long literal code is split across
4098    different macro calls once in a while.  Anyway, this is dumb.  I'm sure
4099    GCC, and any other well-designed compiler, has no such artificial limit. */
4100