1 /* Jitter: VM-independent mutable routine data structures.
2 
3    Copyright (C) 2016, 2017, 2018, 2019, 2020 Luca Saiu
4    Updated in 2021 by Luca Saiu
5    Written by Luca Saiu
6 
7    This file is part of Jitter.
8 
9    Jitter is free software: you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation, either version 3 of the License, or
12    (at your option) any later version.
13 
14    Jitter is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with Jitter.  If not, see <http://www.gnu.org/licenses/>. */
21 
22 
23 #include <stdio.h>
24 #include <stdbool.h>
25 #include <string.h>
26 
27 #include <jitter/jitter.h>
28 #include <jitter/jitter-mmap.h>
29 #include <jitter/jitter-mutable-routine.h>
30 #include <jitter/jitter-vm.h>
31 #include <jitter/jitter-rewrite.h>
32 #include <jitter/jitter-specialize.h>
33 
34 #include <jitter/jitter-hash.h>
35 #include <jitter/jitter-malloc.h>
36 #include <jitter/jitter-fatal.h>
37 
38 
39 /* Routine options.
40  * ************************************************************************** */
41 
42 /* Set the pointed mutable-routine-option struct to the default state. */
43 static void
jitter_initialize_options(struct jitter_mutable_routine_options * op)44 jitter_initialize_options (struct jitter_mutable_routine_options *op)
45 {
46   op->can_change = true;
47   op->slow_registers_only = false;
48   op->slow_literals_only = false;
49   op->add_final_exitvm = true;
50   op->optimization_rewriting = true;
51 }
52 
53 /* Change the options in the given routine to make options unchangeable from now
54    on.  This is harmless to call even if the options are already unchangeable.
55    In practice this is called when appending labels and meta-instructions; it is
56    not necessary to call when appending instruction parameters, as those always
57    follow meta-instructions.  Based on the same reasoning, rewriting rules
58    always follow instruction appending, so the low-level API only used for
59    rewriting does not need to use this. */
60 static void
jitter_routine_make_options_unchangeable(struct jitter_mutable_routine * p)61 jitter_routine_make_options_unchangeable (struct jitter_mutable_routine *p)
62 {
63   p->options.can_change = false;
64 }
65 
66 /* Fail fatally if the options in the pointed routine are no changeable. */
67 static void
jitter_fail_unless_options_changeable(struct jitter_mutable_routine * p)68 jitter_fail_unless_options_changeable (struct jitter_mutable_routine *p)
69 {
70   if (! p->options.can_change)
71     jitter_fatal ("cannot change options in non-empty routine");
72 }
73 
74 void
jitter_set_mutable_routine_option_slow_registers_only(struct jitter_mutable_routine * p,bool option)75 jitter_set_mutable_routine_option_slow_registers_only
76    (struct jitter_mutable_routine *p, bool option)
77 {
78   jitter_fail_unless_options_changeable (p);
79   p->options.slow_registers_only = option;
80 }
81 
82 void
jitter_set_mutable_routine_option_slow_literals_only(struct jitter_mutable_routine * p,bool option)83 jitter_set_mutable_routine_option_slow_literals_only
84    (struct jitter_mutable_routine *p, bool option)
85 {
86   jitter_fail_unless_options_changeable (p);
87   p->options.slow_literals_only = option;
88 }
89 
90 void
jitter_set_mutable_routine_option_slow_literals_and_registers_only(struct jitter_mutable_routine * p,bool option)91 jitter_set_mutable_routine_option_slow_literals_and_registers_only
92    (struct jitter_mutable_routine *p, bool option)
93 {
94   jitter_set_mutable_routine_option_slow_registers_only (p, option);
95   jitter_set_mutable_routine_option_slow_literals_only (p, option);
96 }
97 
98 void
jitter_set_mutable_routine_option_add_final_exitvm(struct jitter_mutable_routine * p,bool option)99 jitter_set_mutable_routine_option_add_final_exitvm
100    (struct jitter_mutable_routine *p, bool option)
101 {
102   jitter_fail_unless_options_changeable (p);
103   p->options.add_final_exitvm = option;
104 }
105 
106 void
jitter_set_mutable_routine_option_optimization_rewriting(struct jitter_mutable_routine * p,bool option)107 jitter_set_mutable_routine_option_optimization_rewriting
108    (struct jitter_mutable_routine *p, bool option)
109 {
110   jitter_fail_unless_options_changeable (p);
111   p->options.optimization_rewriting = option;
112 }
113 
114 
115 
116 /* Initialization and finalization
117  * ************************************************************************** */
118 
119 static void
jitter_initialize_routine(struct jitter_mutable_routine * p)120 jitter_initialize_routine (struct jitter_mutable_routine *p)
121 {
122   p->stage = jitter_routine_stage_unspecialized;
123 
124   jitter_initialize_options (& p->options);
125   p->expected_parameter_no = 0;
126   p->rewritable_instruction_no = 0;
127   p->current_instruction = NULL;
128   p->next_uninitialized_parameter = NULL; /* An intentionally invalid value. */
129   p->next_expected_parameter_type = NULL; /* An intentionally invalid value. */
130 
131   jitter_dynamic_buffer_initialize (& p->instructions);
132   p->next_unused_opaque_label = 0;
133   jitter_hash_initialize (& p->label_name_to_opaque_label);
134   jitter_dynamic_buffer_initialize (& p->opaque_label_to_instruction_index);
135   p->jump_targets = NULL;
136   p->instruction_index_to_specialized_instruction_offset = NULL;
137 
138   jitter_dynamic_buffer_initialize (& p->specialized_program);
139   jitter_dynamic_buffer_initialize (& p->replicated_blocks);
140   p->native_code = NULL;
141   jitter_dynamic_buffer_initialize (& p->specialized_label_indices);
142 
143   /* No slow registers have been seen yet. */
144   p->slow_register_per_class_no = 0;
145 
146   /* No executable routine exists yet for this routine. */
147   p->executable_routine = NULL;
148 }
149 
150 static void
jitter_finalize_routine(struct jitter_mutable_routine * p)151 jitter_finalize_routine (struct jitter_mutable_routine *p)
152 {
153   struct jitter_dynamic_buffer * const is = & p->instructions;
154   while (jitter_dynamic_buffer_size (is) != 0)
155     {
156       struct jitter_instruction *i
157         = * (struct jitter_instruction **)
158             jitter_dynamic_buffer_pop (is, sizeof (struct jitter_instruction*));
159       jitter_destroy_instruction (i);
160     }
161   jitter_dynamic_buffer_finalize (is);
162 
163   jitter_string_hash_finalize (& p->label_name_to_opaque_label, NULL);
164   jitter_dynamic_buffer_finalize (& p->opaque_label_to_instruction_index);
165 
166   if (p->jump_targets != NULL)
167     free (p->jump_targets);
168   if (p->instruction_index_to_specialized_instruction_offset != NULL)
169     free (p->instruction_index_to_specialized_instruction_offset);
170 
171   /* The specialized_program field may have been extracted, if this routine has
172      been made executable; in any case, this finalization will be valid. */
173   jitter_dynamic_buffer_finalize (& p->specialized_program);
174 
175   jitter_dynamic_buffer_finalize (& p->replicated_blocks);
176 
177 #ifdef JITTER_REPLICATE
178   /* The native_code field may be NULL because native code has never been
179      generated, but also if the routine was made executable.  In either case the
180      pointer field here will be NULL, so that we don't deallocate twice.  */
181   if (p->native_code != NULL)
182     jitter_executable_deallocate (p->native_code);
183 #endif // #ifdef JITTER_REPLICATE
184   jitter_dynamic_buffer_finalize (& p->specialized_label_indices);
185 }
186 
187 struct jitter_mutable_routine*
jitter_make_mutable_routine(const struct jitter_vm * vm)188 jitter_make_mutable_routine (const struct jitter_vm *vm)
189 {
190   struct jitter_mutable_routine *res = jitter_xmalloc (sizeof (struct jitter_mutable_routine));
191   jitter_initialize_routine (res);
192   res->vm = vm;
193   return res;
194 }
195 
196 void
jitter_destroy_mutable_routine(struct jitter_mutable_routine * p)197 jitter_destroy_mutable_routine (struct jitter_mutable_routine *p)
198 {
199   /* Unlink the executable routine, if any. */
200   if (p->executable_routine != NULL)
201     p->executable_routine->routine = NULL;
202 
203   if (p == NULL)
204     return;
205 
206   jitter_finalize_routine (p);
207   free (p);
208 }
209 
210 size_t
jitter_mutable_routine_instruction_no(const struct jitter_mutable_routine * p)211 jitter_mutable_routine_instruction_no (const struct jitter_mutable_routine *p)
212 {
213   return jitter_dynamic_buffer_size (& p->instructions)
214          / sizeof (struct jitter_instruction*);
215 }
216 
217 
218 
219 
220 /* Label handing.
221  * ************************************************************************** */
222 
223 jitter_label
jitter_fresh_label(struct jitter_mutable_routine * p)224 jitter_fresh_label (struct jitter_mutable_routine *p)
225 {
226   /* Allocate an identifier. */
227   jitter_label res = p->next_unused_opaque_label ++;
228 
229   /* Associate the label to an invalid instruction index. */
230   jitter_int invalid_instruction_index = -1;
231   jitter_dynamic_buffer_push (& p->opaque_label_to_instruction_index,
232                               & invalid_instruction_index,
233                               sizeof (invalid_instruction_index));
234 
235   /* Return the identifier. */
236   return res;
237 }
238 
239 jitter_label
jitter_symbolic_label(struct jitter_mutable_routine * p,const char * symbolic_name)240 jitter_symbolic_label (struct jitter_mutable_routine *p, const char *symbolic_name)
241 {
242   /* If the name is already known, return its label. */
243   if (jitter_string_hash_table_has (& p->label_name_to_opaque_label,
244                                     symbolic_name))
245     return jitter_string_hash_table_get (& p->label_name_to_opaque_label,
246                                          symbolic_name).fixnum;
247 
248   /* The name is new.  Allocate a new label, bind it to a copy of the name
249      (copies are handled by the hash table routines), and return the label. */
250   jitter_label res = jitter_fresh_label (p);
251   union jitter_word datum = {.fixnum = res};
252   jitter_string_hash_table_add (& p->label_name_to_opaque_label,
253                                 symbolic_name,
254                                 datum);
255   return res;
256 }
257 
258 /* Return the unspecialized instruction index for the given label in the pointed
259    routine, or -1 if the label is not associated to any instruction.
260    Unspecified behavior if the label is out of bounds. */
261 static jitter_int
jitter_get_label_instruction_index(struct jitter_mutable_routine * p,jitter_label label)262 jitter_get_label_instruction_index (struct jitter_mutable_routine *p,
263                                     jitter_label label)
264 {
265   jitter_int *array
266     = jitter_dynamic_buffer_to_pointer (& p->opaque_label_to_instruction_index);
267 
268   return array [label];
269 }
270 
271 /* Associate the given label in the pointed routine to the given unspecialized
272    instruction index.  Fail fatally if the label was already associated to an
273    index.  Unspecified behavior if the label is out of bounds. */
274 static void
jitter_set_label_instruction_index(struct jitter_mutable_routine * p,jitter_label label,jitter_int instruction_index)275 jitter_set_label_instruction_index (struct jitter_mutable_routine *p,
276                                     jitter_label label,
277                                     jitter_int instruction_index)
278 {
279   jitter_int *array
280     = jitter_dynamic_buffer_to_pointer (& p->opaque_label_to_instruction_index);
281   jitter_int previous_index = array [label];
282   if (previous_index != -1)
283     jitter_fatal ("label %li appended twice", (long) label);
284 
285   array [label] = instruction_index;
286 }
287 
288 
289 
290 
291 /* Routine construction API.
292  * ************************************************************************** */
293 
294 void
jitter_mutable_routine_append_label(struct jitter_mutable_routine * p,jitter_label label)295 jitter_mutable_routine_append_label (struct jitter_mutable_routine *p, jitter_label label)
296 {
297   if (p->stage != jitter_routine_stage_unspecialized)
298     jitter_fatal ("appending label in non non-unspecialized routine");
299   if (p->expected_parameter_no != 0)
300     jitter_fatal ("appending label %li with previous instruction "
301                   "incomplete", (long) label);
302   jitter_routine_make_options_unchangeable (p);
303 
304   jitter_int instruction_index = jitter_mutable_routine_instruction_no (p);
305   jitter_set_label_instruction_index (p, label, instruction_index);
306 
307   /* We added a label.  Everything before it can no longer be rewritten. */
308   p->rewritable_instruction_no = 0;
309 }
310 
311 jitter_label
jitter_mutable_routine_append_symbolic_label(struct jitter_mutable_routine * p,const char * label_name)312 jitter_mutable_routine_append_symbolic_label (struct jitter_mutable_routine *p, const char *label_name)
313 {
314   jitter_label res = jitter_symbolic_label (p, label_name);
315   jitter_mutable_routine_append_label (p, res);
316   return res;
317 }
318 
319 /* Close the current instruction which must have all of its parameters already
320    added (fail fatally otherwise), by calling the rewriter on it.  Set pointers
321    about the next parameter in the routine to reflect the fact that its address
322    is not known yet, and a new instruction is expected first.  Increment the
323    instruction counter. */
324 static void
jitter_close_current_instruction(struct jitter_mutable_routine * p)325 jitter_close_current_instruction (struct jitter_mutable_routine *p)
326 {
327   if (p->stage != jitter_routine_stage_unspecialized)
328     jitter_fatal ("closing instruction in non-unspecialized routine");
329   if (p->expected_parameter_no != 0)
330     jitter_fatal ("closing an instruction still expecting parameters");
331 
332   p->next_uninitialized_parameter = NULL;
333   p->next_expected_parameter_type = NULL;
334 
335   /* The instruction we just added is a candidate for rewriting, along with the
336      previous ones which were candidate already. */
337   p->rewritable_instruction_no ++;
338 
339   /* Unless optimization rewrites were disabled for this routine, rewrite the
340      last part of the routine, using the instruction we have just closed; that
341      instruction, along with some others preceding it, might very well change or
342      disappear after rewriting is done. */
343   if (p->options.optimization_rewriting)
344     p->vm->rewrite (p);
345 }
346 
347 /* Check that the pointed routine's last instruction is incomplete, and that the next
348    parameter it expects is compatible with the given actual type and, in case it's a
349    register, register class.  Fail fatally if that's not the case. */
350 static void
jitter_check_paremater_compatibility(struct jitter_mutable_routine * p,enum jitter_parameter_type actual_type,const struct jitter_register_class * register_class)351 jitter_check_paremater_compatibility
352    (struct jitter_mutable_routine *p,
353     enum jitter_parameter_type actual_type,
354     const struct jitter_register_class *register_class)
355 {
356   /* Check that the routine is in the right stage, and that we're
357      actually expecting a parameter. */
358   if (p->stage != jitter_routine_stage_unspecialized)
359     jitter_fatal ("appending parameter in non-unspecialized routine");
360   if (p->expected_parameter_no == 0)
361     jitter_fatal ("appending parameter with previous instruction complete");
362   if (p->next_expected_parameter_type == NULL)
363     jitter_fatal ("impossible if we passed the previous check");
364 
365   /* Check that the parameter type is compatible with what we expect. */
366   const struct jitter_meta_instruction_parameter_type * expected_type =
367     p->next_expected_parameter_type;
368   enum jitter_meta_instruction_parameter_kind expected_kind =
369     expected_type->kind;
370   switch (actual_type)
371     {
372     case jitter_parameter_type_register_id:
373       if (   expected_kind
374              != jitter_meta_instruction_parameter_kind_register
375           && expected_kind
376              != jitter_meta_instruction_parameter_kind_register_or_literal_fixnum
377           && expected_kind
378              != jitter_meta_instruction_parameter_kind_register_or_literal_label
379           && expected_kind
380              != jitter_meta_instruction_parameter_kind_register_or_literal_fixnum_or_literal_label)
381         jitter_fatal ("appending register argument not admitted by instruction");
382       if (expected_type->register_class != register_class)
383         jitter_fatal ("invalid register class for register argument");
384       break;
385     case jitter_parameter_type_literal:
386       if (   expected_kind
387              != jitter_meta_instruction_parameter_kind_literal_fixnum
388           && expected_kind
389              != jitter_meta_instruction_parameter_kind_literal_fixnum_or_literal_label
390           && expected_kind
391              != jitter_meta_instruction_parameter_kind_register_or_literal_fixnum
392           && expected_kind
393              != jitter_meta_instruction_parameter_kind_register_or_literal_fixnum_or_literal_label)
394         jitter_fatal ("appending immediate argument not admitted by instruction");
395       break;
396     case jitter_parameter_type_label:
397       if (   expected_kind
398              != jitter_meta_instruction_parameter_kind_literal_label
399           && expected_kind
400              != jitter_meta_instruction_parameter_kind_literal_fixnum_or_literal_label
401           && expected_kind
402              != jitter_meta_instruction_parameter_kind_register_or_literal_label
403           && expected_kind
404              != jitter_meta_instruction_parameter_kind_register_or_literal_fixnum_or_literal_label)
405         jitter_fatal ("appending label argument not admitted by instruction");
406       break;
407     default:
408       jitter_fatal ("jitter_mutable_routine_append_uninitialized_paremater: "
409                     "invalid actual argument type %lu",
410                     (unsigned long) actual_type);
411     }
412 }
413 
414 /* Make the current instruction, which must be incomplete, have the next
415    expected parameter as its own and start a new instruction if that parameter
416    was the last, but *don't* close the old instruction.  Don't make checks. */
417 static void
jitter_advance_past_next_parameter(struct jitter_mutable_routine * p)418 jitter_advance_past_next_parameter (struct jitter_mutable_routine *p)
419 {
420   if ((-- p->expected_parameter_no) != 0)
421     {
422       const struct jitter_instruction *in = p->current_instruction;
423       const struct jitter_meta_instruction *min = in->meta_instruction;
424 
425       /* There are other parameters expected in the current instruction after
426          the one we have just added.  Point to the next one. */
427       p->next_uninitialized_parameter
428         = in->parameters [min->parameter_no - p->expected_parameter_no];
429       p->next_expected_parameter_type ++;
430     }
431 }
432 
433 /* Add a parameter of the given parameter type (which is a
434    jitter_parameter_type, therefore an "actual" type and *not* a
435    jitter_meta_instruction_parameter type, expressing the set of "formal"
436    accepted types) to the last instruction of the given unspecialized routine,
437    which must be incomplete.  A register class is also given to check that it
438    matches with the expected parameter, in case of a register-type parameter; it
439    is ignored otherwise.
440    Fail fatally if the routine is not unspecialized
441    or its last instruction is complete, or if the kind or register class is
442    wrong.  Return a pointer to the parameter data structure, to be filled in by
443    the caller.  In any case, do *not* close the instruction, even if the appended
444    parameter was the last; doing that would interfere badly with rewriting, which
445    has to see every parameter correctly initialized.
446    This is used by jitter_mutable_routine_append_literal_parameter ,
447    jitter_mutable_routine_append_register_parameter and
448    jitter_mutable_routine_append_label_parameter . */
449 static struct jitter_parameter *
jitter_mutable_routine_append_uninitialized_paremater(struct jitter_mutable_routine * p,enum jitter_parameter_type actual_type,const struct jitter_register_class * register_class)450 jitter_mutable_routine_append_uninitialized_paremater
451    (struct jitter_mutable_routine *p,
452     enum jitter_parameter_type actual_type,
453     const struct jitter_register_class *register_class)
454 {
455   /* Check that the parameter is compatbile; fail fatally if it isn't. */
456   jitter_check_paremater_compatibility (p, actual_type, register_class);
457 
458   /* Keep a pointer to the next uninitialized parameter to be returned; it will
459      no longer be the next at the end of this function. */
460   struct jitter_parameter *res = p->next_uninitialized_parameter;
461 
462   /* Advance pointers in the routine past this parameter, starting a new
463      instruction if needed -- but don't close the current instruction: see the
464      comment before this function. */
465   jitter_advance_past_next_parameter (p);
466 
467   return res;
468 }
469 
470 /* Close the current instruction if the last appended parameter was the last
471    one.  See the comment before as to why this is not done there. */
472 static void
jitter_close_instruction_when_no_more_parameters(struct jitter_mutable_routine * p)473 jitter_close_instruction_when_no_more_parameters (struct jitter_mutable_routine *p)
474 {
475   if (p->expected_parameter_no == 0)
476     jitter_close_current_instruction (p);
477 }
478 
479 void
jitter_mutable_routine_append_literal_parameter(struct jitter_mutable_routine * p,union jitter_word immediate)480 jitter_mutable_routine_append_literal_parameter (struct jitter_mutable_routine *p,
481                                  union jitter_word immediate)
482 {
483   struct jitter_parameter * const pa
484     = jitter_mutable_routine_append_uninitialized_paremater (p, jitter_parameter_type_literal,
485                                              NULL);
486 
487   pa->type = jitter_parameter_type_literal;
488   pa->literal = immediate;
489   jitter_close_instruction_when_no_more_parameters (p);
490 }
491 
492 /* This is just a convenience wrapper around jitter_mutable_routine_append_literal_parameter
493    . */
494 void
jitter_mutable_routine_append_signed_literal_parameter(struct jitter_mutable_routine * p,jitter_int immediate)495 jitter_mutable_routine_append_signed_literal_parameter (struct jitter_mutable_routine *p,
496                                         jitter_int immediate)
497 {
498   union jitter_word immediate_union = {.fixnum = immediate};
499   jitter_mutable_routine_append_literal_parameter (p, immediate_union);
500 }
501 
502 /* This is just a convenience wrapper around jitter_mutable_routine_append_literal_parameter
503    . */
504 void
jitter_mutable_routine_append_unsigned_literal_parameter(struct jitter_mutable_routine * p,jitter_uint immediate)505 jitter_mutable_routine_append_unsigned_literal_parameter (struct jitter_mutable_routine *p,
506                                           jitter_uint immediate)
507 {
508   union jitter_word immediate_union = {.ufixnum = immediate};
509   jitter_mutable_routine_append_literal_parameter (p, immediate_union);
510 }
511 
512 /* This is just a convenience wrapper around jitter_mutable_routine_append_literal_parameter
513    . */
514 void
jitter_mutable_routine_append_pointer_literal_parameter(struct jitter_mutable_routine * p,void * immediate)515 jitter_mutable_routine_append_pointer_literal_parameter (struct jitter_mutable_routine *p,
516                                          void *immediate)
517 {
518   union jitter_word immediate_union = {.pointer = immediate};
519   jitter_mutable_routine_append_literal_parameter (p, immediate_union);
520 }
521 
522 void
jitter_mutable_routine_append_register_parameter(struct jitter_mutable_routine * p,const struct jitter_register_class * register_class,jitter_register_index register_index)523 jitter_mutable_routine_append_register_parameter
524    (struct jitter_mutable_routine *p,
525     const struct jitter_register_class *register_class,
526     jitter_register_index register_index)
527 {
528   /* If we have to always residualize registers, then increment this register
529      index by the number of fast registers in the class.  This way it is
530      guaranteed that the actual register used in execution will be slow.  (When
531      printing out the routine the register index will be shown *decremented* by
532      the number of fast registers in the class to compensate for this.) */
533   if (p->options.slow_registers_only)
534     register_index += register_class->fast_register_no;
535 
536   /* Append the register parameter. */
537   struct jitter_parameter * const pa
538     = jitter_mutable_routine_append_uninitialized_paremater
539          (p, jitter_parameter_type_register_id, register_class);
540   pa->type = jitter_parameter_type_register_id;
541   pa->register_index = register_index;
542   pa->register_class = register_class;
543   jitter_close_instruction_when_no_more_parameters (p);
544 
545   /* If this register is slow and its slow index is the highest up to this
546      point, record it: it will be needed to know how many slow registers to
547      allocate.  Notice that a negative slow_index (indicating a fast register)
548      will never satisfy the if condition, as p->slow_register_per_class_no is
549      initialized to zero and non-decreasing. */
550   jitter_int slow_index = register_index - register_class->fast_register_no;
551   jitter_int slow_register_no = slow_index + 1;
552   if (slow_register_no > p->slow_register_per_class_no)
553     p->slow_register_per_class_no = slow_register_no;
554 }
555 
556 jitter_label
jitter_mutable_routine_append_symbolic_label_parameter(struct jitter_mutable_routine * p,const char * label_name)557 jitter_mutable_routine_append_symbolic_label_parameter (struct jitter_mutable_routine *p,
558                                         const char *label_name)
559 {
560   jitter_label res = jitter_symbolic_label (p, label_name);
561   jitter_mutable_routine_append_label_parameter (p, res);
562   return res;
563 }
564 void
jitter_mutable_routine_append_label_parameter(struct jitter_mutable_routine * p,jitter_label label)565 jitter_mutable_routine_append_label_parameter (struct jitter_mutable_routine *p,
566                                jitter_label label)
567 {
568   struct jitter_parameter * const pa
569     = jitter_mutable_routine_append_uninitialized_paremater
570          (p, jitter_parameter_type_label, NULL);
571   pa->type = jitter_parameter_type_label;
572   pa->label = label;
573   jitter_close_instruction_when_no_more_parameters (p);
574 }
575 
576 void
jitter_mutable_routine_append_meta_instruction(struct jitter_mutable_routine * p,const struct jitter_meta_instruction * const mi)577 jitter_mutable_routine_append_meta_instruction (struct jitter_mutable_routine *p,
578                                 const struct jitter_meta_instruction * const mi)
579 {
580   if (p->stage != jitter_routine_stage_unspecialized)
581     jitter_fatal ("appending instruction %s in non-unspecialized routine",
582                   mi->name);
583   if (p->expected_parameter_no != 0)
584     jitter_fatal ("appending instruction %s with previous instruction"
585                   " incomplete", mi->name);
586   jitter_routine_make_options_unchangeable (p);
587 
588   /* Make the instruction. */
589   struct jitter_instruction *i
590     = p->current_instruction
591     = jitter_make_instruction (mi);
592 
593   /* Add a pointer to it to the dynamic buffer for instructions within the
594      routine. */
595   jitter_dynamic_buffer_push (& p->instructions,
596                               & i,
597                               sizeof (struct jitter_meta_instruction *));
598 
599   /* If this instruction has zero parameters then we're already done with it, and
600      we can close it immediately.  Otherwise set parameter pointers to the frist
601      parameter to be appended. */
602   if ((p->expected_parameter_no = mi->parameter_no) == 0)
603     jitter_close_current_instruction (p);
604   else
605     {
606       p->next_uninitialized_parameter = i->parameters [0];
607       p->next_expected_parameter_type = mi->parameter_types;
608     }
609 }
610 
611 void
jitter_mutable_routine_append_instruction_id(struct jitter_mutable_routine * p,const struct jitter_meta_instruction * const mis,size_t meta_instruction_no,unsigned unspecialized_opcode)612 jitter_mutable_routine_append_instruction_id (struct jitter_mutable_routine *p,
613                               const struct jitter_meta_instruction * const mis,
614                               size_t meta_instruction_no,
615                               unsigned unspecialized_opcode)
616 {
617   /* Sanity check. */
618   if (unspecialized_opcode >= meta_instruction_no)
619     jitter_fatal ("jitter_mutable_routine_append_instruction_id: invalid id %u",
620                   unspecialized_opcode);
621 
622   /* Find the address of the appropriate meta-instruction in the array. */
623   const struct jitter_meta_instruction * const mi
624     = mis + unspecialized_opcode;
625 
626   /* Append the meta-instruction. */
627   jitter_mutable_routine_append_meta_instruction (p, mi);
628 }
629 
630 void
jitter_mutable_routine_append_instruction_name(struct jitter_mutable_routine * p,const char * instruction_name)631 jitter_mutable_routine_append_instruction_name (struct jitter_mutable_routine *p,
632                                 const char *instruction_name)
633 {
634   const struct jitter_meta_instruction * const mi
635     = jitter_lookup_meta_instruction (p->vm->meta_instruction_string_hash,
636                                       instruction_name);
637   jitter_mutable_routine_append_meta_instruction (p, mi);
638 }
639 
640 
641 
642 
643 /* Lower-level routine-construction API.
644  * ************************************************************************** */
645 
646 void
jitter_mutable_routine_append_instruction(struct jitter_mutable_routine * p,const struct jitter_instruction * ip)647 jitter_mutable_routine_append_instruction (struct jitter_mutable_routine *p,
648                            const struct jitter_instruction *ip)
649 {
650   if (p->stage != jitter_routine_stage_unspecialized)
651     jitter_fatal ("jitter_mutable_routine_append_instruction: non non-unspecialized routine");
652   if (p->expected_parameter_no != 0)
653     jitter_fatal ("jitter_mutable_routine_append_instruction: previous instruction incomplete");
654   fprintf (stderr, "Pushing instruction at %p (%s)\n", ip,
655            ip->meta_instruction->name);
656 
657   /* Add the provided instruction.  There is no need to touch the fields about
658      expected parameters, since the previous instruction was already closed. */
659   jitter_dynamic_buffer_push (& p->instructions,
660                               & ip,
661                               sizeof (struct jitter_instruction*));
662 
663   /* Close the new instruction.  This increments the number of rewritable
664      instructions and triggers rewriting.  Notice that the instruction that was
665      just added, along with some others preceding it, might very well change or
666      disappear after rewriting is done. */
667   jitter_close_current_instruction (p);
668 }
669 
670 void
jitter_mutable_routine_append_parameter_copy(struct jitter_mutable_routine * p,const struct jitter_parameter * pp)671 jitter_mutable_routine_append_parameter_copy (struct jitter_mutable_routine *p,
672                               const struct jitter_parameter *pp)
673 {
674   /* Check that the parameter is compatbile with what we are expecting; fail
675      fatally if it isn't. */
676   jitter_check_paremater_compatibility (p, pp->type, pp->register_class);
677 
678   /* The next parameter is pre-allocated.  Copy the pointed one into it. */
679   jitter_copy_instruction_parameter (p->next_uninitialized_parameter, pp);
680 
681   /* Advance pointers in the routine past this parameter, starting a new
682      instruction if needed.  This however doesn't close the instruction... */
683   jitter_advance_past_next_parameter (p);
684 
685   /* ...So do it if needed. */
686   jitter_close_instruction_when_no_more_parameters (p);
687 }
688 
689 
690 
691 
692 /* Jump target computation on unspecialized routines.
693  * ************************************************************************** */
694 
695 bool*
jitter_mutable_routine_jump_targets(const struct jitter_mutable_routine * p)696 jitter_mutable_routine_jump_targets (const struct jitter_mutable_routine *p)
697 {
698   if (p->expected_parameter_no != 0)
699     jitter_fatal ("computing jump targets with an instruction incomplete");
700 
701   const int instruction_no = jitter_mutable_routine_instruction_no (p);
702   const struct jitter_instruction **ins
703     = (const struct jitter_instruction **)
704       jitter_dynamic_buffer_to_const_pointer (& p->instructions);
705   bool *res = jitter_xmalloc (sizeof (bool) * instruction_no);
706 
707   /* Initialize: no instruction is a jump target by default. */
708   int i;
709   for (i = 0; i < instruction_no; i ++)
710     res [i] = false;
711 
712   /* Scan every instruction... */
713   for (i = 0; i < instruction_no; i ++)
714     {
715       const struct jitter_parameter **ps
716         = (const struct jitter_parameter **) ins[i]->parameters;
717 
718       /* Any callee instruction is a branch target, reachable by a
719          branch-and-link. */
720       if (ins [i]->meta_instruction->callee)
721         res [i] = true;
722 
723       /* Any instruction directly *following* a caller instruction is a branch
724          target, implicitly reachable by a return. */
725       if (ins [i]->meta_instruction->caller && (i + 1) < instruction_no)
726         res [i + 1] = true;
727 
728       /* Look at every argument of the i-th instruction: for every one referring
729          another instruction as a jump target, set the target to true. */
730       const int arity = ins[i]->meta_instruction->parameter_no;
731       int j;
732       for (j = 0; j < arity; j ++)
733         {
734           const struct jitter_parameter *p = ps [j];
735           if (p->type == jitter_parameter_type_label)
736             {
737               const long target = p->label_as_index;
738               if (target < 0 || target >= instruction_no)
739                 {
740                   printf ("# Warning: invalid label literal in instruction "
741                           "at L%li\n", (long) i);
742                   res [i] = true; /* Make the invalid instruction visible. */
743                 }
744               else
745                 res [target] = true;
746             }
747         } /* inner for: parameter loop. */
748     } /* outer for: instruction loop. */
749 
750   return res;
751 }
752 
753 
754 
755 
756 /* Unspecialized routine printer.
757  * ************************************************************************** */
758 
759 /* Return the length of the longest instruction name actually used in this
760    routine. */
761 static size_t
jitter_maximum_instruction_name_length(const struct jitter_mutable_routine * p)762 jitter_maximum_instruction_name_length (const struct jitter_mutable_routine *p)
763 {
764   const int instruction_no = jitter_mutable_routine_instruction_no (p);
765   const struct jitter_instruction **ins
766     = (const struct jitter_instruction **)
767       jitter_dynamic_buffer_to_const_pointer (& p->instructions);
768 
769   /* Iterate on every instruction, and find the maximum length. */
770   size_t res = 0;
771   int i;
772   for (i = 0; i < instruction_no; i ++)
773     {
774       const struct jitter_instruction * in = ins [i];
775       const struct jitter_meta_instruction * mi = in->meta_instruction;
776       size_t instruction_name_length = strlen (mi->name);
777       if (instruction_name_length > res)
778         res = instruction_name_length;
779     }
780   return res;
781 }
782 
783 /* Begin using a class in the given print context, where the class name is
784    formed by the concatenation of the lower-case prefix for the VM of the
785    pointed mutable routine, concatenated to a dash, concatenated to the
786    given suffix.
787    For example, if the mutable routine r belonged to a VM named "foo",
788      jitter_mutable_routine_begin_class (ctx, r, "label")
789    would open a class in the context ctx named "foo-label". */
790 static void
jitter_mutable_routine_begin_class(jitter_print_context ctx,const struct jitter_mutable_routine * p,const char * suffix)791 jitter_mutable_routine_begin_class (jitter_print_context ctx,
792                                     const struct jitter_mutable_routine *p,
793                                     const char *suffix)
794 {
795   char *prefix = p->vm->configuration->lower_case_prefix;
796   size_t size = strlen (prefix) + 1 + strlen (suffix) + 1;
797   char *buffer = jitter_xmalloc (size);
798   sprintf (buffer, "%s-%s", prefix, suffix);
799   jitter_print_begin_class (ctx, buffer);
800   free (buffer);
801 }
802 
803 void
jitter_mutable_routine_print(jitter_print_context ctx,const struct jitter_mutable_routine * r)804 jitter_mutable_routine_print (jitter_print_context ctx,
805                               const struct jitter_mutable_routine *r)
806 {
807   const bool slow_registers_only = r->options.slow_registers_only;
808   const int instruction_no = jitter_mutable_routine_instruction_no (r);
809   const struct jitter_instruction **ins
810     = (const struct jitter_instruction **)
811       jitter_dynamic_buffer_to_const_pointer (& r->instructions);
812 
813   /* We need to keep track of which instructions are jump targets.  If we
814      already have the information, which is computed at specialization time,
815      then use it; otherwise compute it now. */
816   bool *is_target;
817   if (r->stage >= jitter_routine_stage_specialized)
818     is_target = r->jump_targets;
819   else
820     is_target = jitter_mutable_routine_jump_targets (r);
821 
822   /* Prepare a printf format string leaving the correct amount of space to align
823      the first argument of every instruction to the same column.  The format
824      string describes a single conversion specification, the instruction name as
825      a string. */
826   size_t max_instruction_name_length
827     = jitter_maximum_instruction_name_length (r);
828   size_t max_label_name_length
829     = (/* "$L" */ 2
830        + jitter_digit_no_radix_10 (instruction_no - 1)
831        + /* ":" */ 1);
832   int i;
833   for (i = 0; i < instruction_no; i ++)
834     {
835       const struct jitter_instruction * in = ins [i];
836       const struct jitter_meta_instruction * mi = in->meta_instruction;
837       const struct jitter_parameter **ps
838         = (const struct jitter_parameter **) in->parameters;
839 
840       bool newline_after_label = false; // FIXME: configuration parameter?
841       int indentation_width = max_label_name_length + 1;
842       int printed_char_no_for_this_line = 0;
843       if (is_target [i])
844         {
845           /* It is okay to use "$L" followed by an unspecialized index as a
846              label name; this way we have a guarantee that all label names are
847              unique. */
848           char label_name_buffer [100];
849           sprintf (label_name_buffer, "$L%i", i);
850           jitter_mutable_routine_begin_class (ctx, r, "label");
851           jitter_print_char_star (ctx, label_name_buffer);
852           jitter_print_end_class (ctx);
853           jitter_mutable_routine_begin_class (ctx, r, "punctuation");
854           jitter_print_char (ctx, ':');
855           jitter_print_end_class (ctx);
856           if (newline_after_label)
857             jitter_print_char (ctx, '\n');
858           else
859             printed_char_no_for_this_line = strlen (label_name_buffer) + 1;
860         }
861       int j;
862       for (j = printed_char_no_for_this_line; j < indentation_width; j ++)
863         jitter_print_char (ctx, ' ');
864       jitter_mutable_routine_begin_class (ctx, r, "instruction");
865       jitter_print_char_star (ctx, mi->name);
866       jitter_print_end_class (ctx);
867       if (mi->parameter_no > 0)
868         {
869           int j;
870           for (j = strlen (mi->name); j < max_instruction_name_length + 1; j ++)
871             jitter_print_char (ctx, ' ');
872         }
873       const int arity = mi->parameter_no;
874       for (j = 0; j < arity; j ++)
875         {
876           const struct jitter_parameter *p = ps [j];
877           switch (p->type)
878             {
879             case jitter_parameter_type_uninitialized:
880               jitter_mutable_routine_begin_class (ctx, r, "invalid");
881               jitter_print_char_star (ctx, "<uninitialized>");
882               jitter_print_end_class (ctx);
883               break;
884             case jitter_parameter_type_register_id:
885               {
886                 int register_index = p->register_index;
887                 /* If the routine has been modified to use slow registers only,
888                    unmodify it for printing: the modification simply consists in
889                    changing register indices so that the first one maps to the
890                    first slow register for each class. */
891                 const struct jitter_register_class *register_class
892                   = mi->parameter_types [j].register_class;
893                 if (slow_registers_only)
894                   register_index -= register_class->fast_register_no;
895                 /* Print the possibly unmodified register. */
896                 jitter_mutable_routine_begin_class (ctx, r, "register");
897                 jitter_print_char (ctx, '%');
898                 jitter_print_char (ctx, register_class->character);
899                 jitter_print_int (ctx, 10, register_index);
900                 jitter_print_end_class (ctx);
901                 break;
902               }
903             case jitter_parameter_type_literal:
904               {
905                 const jitter_literal_parameter_printer printer
906                   = mi->parameter_types [j].literal_printer;
907                 /* If the printer is the default printer than use the number
908                    class; otherwise let the printer itself deal with classes. */
909                 if (printer == jitter_default_literal_parameter_printer)
910                   jitter_mutable_routine_begin_class (ctx, r, "number");
911                 printer (ctx, p->literal.ufixnum);
912                 if (printer == jitter_default_literal_parameter_printer)
913                   jitter_print_end_class (ctx);
914                 break;
915               }
916             case jitter_parameter_type_label:
917               jitter_mutable_routine_begin_class (ctx, r, "label");
918               jitter_print_char_star (ctx, "$L");
919               jitter_print_long (ctx, 10, (long) p->label_as_index);
920               jitter_print_end_class (ctx);
921               break;
922             default:
923               /* Even if in the future I remove some parameter types this
924                  default case remains useful for debugging.  Don't touch it. */
925               jitter_mutable_routine_begin_class (ctx, r, "invalid");
926               jitter_print_char_star (ctx, "<INVALID-ARGUMENT-TYPE>");
927               jitter_print_end_class (ctx);
928               break;
929             } /* switch */
930           if (j + 1 != arity)
931             {
932               jitter_mutable_routine_begin_class (ctx, r, "punctuation");
933               jitter_print_char (ctx, ',');
934               jitter_print_end_class (ctx);
935               jitter_print_char (ctx, ' ');
936             }
937         } /* inner for: parameter loop. */
938       jitter_print_char (ctx, '\n');
939     } /* outer for: instruction loop. */
940 
941   /* If we have allocated the boolean array here then free it; if not then we
942      were reusing some part of the routine, and of course we should not break
943      it. */
944   if (r->stage < jitter_routine_stage_specialized)
945     free (is_target);
946 }
947 
948 
949 
950 
951 /* Label resolution.
952  * ************************************************************************** */
953 
954 void
jitter_mutable_routine_resolve_labels(struct jitter_mutable_routine * pr)955 jitter_mutable_routine_resolve_labels (struct jitter_mutable_routine *pr)
956 {
957   if (pr->stage != jitter_routine_stage_unspecialized)
958     jitter_fatal ("resolving unspecialized labels in non-unspecialized routine");
959 
960   const int instruction_no = jitter_mutable_routine_instruction_no (pr);
961   struct jitter_instruction **ins
962     = jitter_dynamic_buffer_to_pointer (& pr->instructions);
963 
964   /* Scan instructions sequentially, and for each of them scan parameters
965      sequentially, replacing opaque labels with instruction indices.  This
966      relies of parameters *not* being shared: each label parameter must be
967      touched exactly once. */
968 
969   /* For every instruction... */
970   int i;
971   for (i = 0; i < instruction_no; i ++)
972     {
973       const struct jitter_instruction * in = ins [i];
974       const struct jitter_meta_instruction * mi = in->meta_instruction;
975       struct jitter_parameter **ps = in->parameters;
976 
977       /* ...For every instruction parameter... */
978       const int arity = mi->parameter_no;
979       int j;
980       for (j = 0; j < arity; j ++)
981         {
982           struct jitter_parameter *p = ps [j];
983           /* ...If the parameter is a label... */
984           if (p->type == jitter_parameter_type_label)
985             {
986               /* Replace the label with its instruction index. */
987               jitter_label label = p->label;
988               jitter_int label_instruction_index
989                 = jitter_get_label_instruction_index (pr, label);
990               if (label_instruction_index == -1)
991                 jitter_fatal ("undefined label %li", (long) label);
992 
993               /* Notice that this assignment invalidates p->label . */
994               p->label_as_index = label_instruction_index;
995             }
996         }
997     }
998 }
999