1 /* Jitter: runtime VM-independent header for generated executors.
2 
3    Copyright (C) 2016, 2017, 2019, 2020 Luca Saiu
4    Written by Luca Saiu
5 
6    This file is part of Jitter.
7 
8    Jitter is free software: you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation, either version 3 of the License, or
11    (at your option) any later version.
12 
13    Jitter is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17 
18    You should have received a copy of the GNU General Public License
19    along with Jitter.  If not, see <http://www.gnu.org/licenses/>. */
20 
21 
22 /* This header is used internally by machine-generated executors.  It
23    is not for the user to see.
24 
25    For example, some functionality defined here may depend on
26    JITTER_VM_PREFIX_LOWER_CASE and JITTER_VM_PREFIX_UPPER_CASE, which are
27    defined by machine-generated code in a .c file, without polluting the user
28    name space. */
29 
30 #ifndef JITTER_EXECUTOR_H_
31 #define JITTER_EXECUTOR_H_
32 
33 /* Fail if this is not included from generated code.
34  * ************************************************************************** */
35 
36 /* This header relies on internal machinery and defines macros that the user
37    should never see out of VM instruction code; using such macros from some
38    other context, even by mistake, is unsupported and might lead to subtle
39    bugs. */
40 #ifndef JITTER_THIS_CAN_INCLUDE_JITTER_EXECUTOR_H
41 # error "The header <jitter/jitter-executor.h> must only be included from C"
42 # error "files machine-generated by Jitter, and is not for the user to see."
43 # error "You are probably including the header directly."
44 # error "Don't."
45 #endif // #ifndef JITTER_THIS_CAN_INCLUDE_JITTER_EXECUTOR_H
46 
47 
48 
49 
50 /* Include headers.
51  * ************************************************************************** */
52 
53 #include <jitter/jitter.h>
54 #include <jitter/jitter-fast-branch.h>
55 #if defined (JITTER_HAVE_KNOWN_BINARY_FORMAT)
56 # include <jitter/jitter-sections.h>
57 #endif // #if defined (JITTER_HAVE_KNOWN_BINARY_FORMAT)
58 #if defined (JITTER_ENABLE_ASSEMBLY)
59 # include <jitter/machine/jitter-machine.h>
60 #endif //#if defined (JITTER_ENABLE_ASSEMBLY)
61 
62 
63 /* Consistency check.
64  * ************************************************************************** */
65 
66 // FIXME: this check is probably wrong.  Instead I should make sure that fast
67 // branch-and-links are rewritten into a default version using unconditional
68 // fast branches.
69 
70 /* /\* Defining patch-in support without procedures leads to subtle annoying */
71 /*    crashes: in practice it's not possible to check if a fast label argument of */
72 /*    some instruction is used only as a simple branch target, or for */
73 /*    branch-and-link as well; when the fast version of a branching macro is */
74 /*    rewritten into the slow version by the fallback definitions below, the */
75 /*    rewritten definition must work: either both branch and branch-and-link are */
76 /*    supported for fast label, or neither. */
77 
78 /*    Notice that it is not necessary to explicitly support every conditional */
79 /*    branch variant: if some conditional is not expliticitly defined it is */
80 /*    rewritten into an ordinary C conditional containing an unconditional fast */
81 /*    branch.  Having the unconditional version suffices. *\/ */
82 /* #if    defined(JITTER_DISPATCH_NO_THREADING)      \ */
83 /*     && defined(JITTER_MACHINE_SUPPORTS_PATCH_IN)  \ */
84 /*     && ! defined(JITTER_MACHINE_SUPPORTS_PROCEDURE) */
85 /* # error "you can't define machine-specific procedure support without having patch-ins." */
86 /* #endif */
87 
88 
89 
90 
91 /* Unique string generation in (GNU) CPP.
92  * ************************************************************************** */
93 
94 /* Expand to a string literal, different at every expansion.  This is convenient for
95    inline assembly comments, to prevent GCC from factoring code which is meant
96    to be duplicated -- typically to avoid tail-merging in replicated VM
97    instruction code.
98    Notice that the unique identifier generated in inline asm code by "%=" is not
99    enough to prevent tail-merging: GCC sees two identical string literals containing
100    "%=" as, indeed, equal.
101    This relies on __COUNTER__ , a GNU C preprocessor extension, but the advanced
102    dispatching models requiring this rely on GCC anyway. */
103 #define JITTER_STRING_LITERAL_UNIQUE  \
104   " [" JITTER_STRINGIFY(__COUNTER__) "] "
105 
106 /* Expand to an integer literal, different at any expansion.  This has similar
107    applications to JITTER_STRING_LITERAL_UNIQUE , but is meant for C
108    identifiers.  Again, this relies on the GNU C preprocessor. */
109 #define JITTER_INTEGER_LITERAL_UNIQUE  \
110   __COUNTER__
111 
112 
113 
114 
115 /* Architecture-specific initialisation and finalisation.
116  * ************************************************************************** */
117 
118 /* Some ports may add their own custom code to be executed at initialisation and
119    finalisation of the executor.
120 
121    This feature is meant for tasks such as reading and then restoring the state
122    of some register not visible from C.  Since in such a context it is useful to
123    introduce automatic variables visible from VM instruction bodies these macros
124    have a trailing underscore in their names, and are expanded in a context
125    where it is safe not to protect the definition with a do { ... } while
126    (false) loop. */
127 
128 /* This feature is only meant for minimal-threading and no-threading.  Disable
129    any architecture-specific execution begin and end code when using simple
130    dispatches. */
131 #if (! defined(JITTER_DISPATCH_MINIMAL_THREADING)) \
132     && (! defined(JITTER_DISPATCH_NO_THREADING))
133 # undef JITTER_EXECUTION_BEGINNING_
134 # undef JITTER_EXECUTION_END_
135 #endif
136 
137 /* Define a fallback JITTER_EXECUTION_BEGINNING_ if none is defined. */
138 #if ! defined (JITTER_EXECUTION_BEGINNING_)
139 # define JITTER_EXECUTION_BEGINNING_ {}
140 #endif // #if ! defined (JITTER_EXECUTION_BEGINNING_)
141 
142 /* Define a fallback JITTER_EXECUTION_END_ if none is defined. */
143 #if ! defined (JITTER_EXECUTION_END_)
144 # define JITTER_EXECUTION_END_ {}
145 #endif // #if ! defined (JITTER_EXECUTION_END_)
146 
147 
148 
149 
150 /* Miscellaneous machinery for the executor, possibly to move.
151  * ************************************************************************** */
152 
153 /* Expand to a line-comment prefix for assembly as a string.  "\n# " is a sensible
154    default working on most architectures, but this can be overridden in the
155    architecture-specific header
156    machine/ARCHICTECTURE/jitter/machine/jitter-machine.h .
157    Rationale for the newline: on SH, at least with the GNU assembler, comments
158    are introduced by "#" at the beginning of a line or by "!" anywhere else; but
159    "!" is not supported on other architectures. */
160 #ifndef JITTER_ASM_COMMENT_PREFIX
161 # define JITTER_ASM_COMMENT_PREFIX  \
162     "\n# "
163 #endif // #ifndef JITTER_ASM_COMMENT_PREFIX
164 
165 /* Expand to a string literal suitable to be part inline asm, containing a
166    comment-opening text and a terminating "\n\t" sequence. */
167 #define JITTER_ASM_COMMENT(_jitter_string_literal)         \
168   JITTER_ASM_COMMENT_PREFIX _jitter_string_literal "\n\t"
169 
170 /* Expand to a string literal suitable to be part inline asm, containing a
171    comment-opening text, a unique identifier making the generated literal
172    different from all others, and a terminating "\n\t" sequence. */
173 #define JITTER_ASM_COMMENT_UNIQUE(_jitter_string_literal)   \
174   JITTER_ASM_COMMENT_PREFIX _jitter_string_literal " "      \
175   JITTER_STRING_LITERAL_UNIQUE "\n\t"
176 
177 /* Expand to an inline asm C statement containing the given comment, and a
178    terminating "\n\t" sequence. */
179 #define JITTER_COMMENT_IN_ASM_(_jitter_string_literal)       \
180   asm volatile (JITTER_ASM_COMMENT(_jitter_string_literal))
181 
182 /* Expand to a string literal containing an asm comment, including containing
183    the given text and a unique identifier which will prevent GCC from merging
184    different expansions with the same argument. */
185 #define JITTER_COMMENT_IN_ASM_UNIQUE_(_jitter_string_literal)       \
186   asm volatile (JITTER_ASM_COMMENT_UNIQUE(_jitter_string_literal))
187 
188 
189 
190 
191 /* Debugging features to be used with disassembly.
192  * ************************************************************************** */
193 
194 // FIXME: I should move this section to a different header.
195 
196 /* "Debugging nops" serve to generate nop instructions containing recognizable
197    integer arguments, to be read back by humans disassembling compiled code.
198    If there is no architecture-specific code for generating debugging nops, just
199    generate nothing in their place. */
200 #ifndef _JITTER_ASM_DEBUGGING_NOP
201 # define _JITTER_ASM_DEBUGGING_NOP(integer_literal_as_string)  \
202   ""
203 #endif // #ifndef _JITTER_ASM_DEBUGGING_NOP
204 
205 /* Debugging nops: user macro, generating a readable asm comment followed (where
206    possible) by the nop.
207    The argument must be an integer literal in Gas syntax, with no surrounding
208    quotes.  The machine-specific macro will emit the appropriate prefix to
209    interpret the digit sequence as a hexadecimal constant.
210    The expansion of this macro should be used in an *extended* asm statement,
211    since '%' characters appearing, for example, as register prefixes, will
212    appear escaped as "%%".
213    For portability with respect to architectures only supporting small operands,
214    the arguments should be non-negative and representable in 7 bits (Rationale:
215    one way to implement a "nop" is by adding a short immediate to a register,
216    followed by adding it back with the opposite sign; another alternative is
217    xoring and a literal constant into the register itself, twice). */
218 #define JITTER_ASM_DEBUGGING_NOP(integer_literal)                 \
219   JITTER_ASM_COMMENT_UNIQUE ("Debugging nop: "                    \
220                              JITTER_STRINGIFY (integer_literal))  \
221   _JITTER_ASM_DEBUGGING_NOP(JITTER_STRINGIFY (integer_literal))   \
222   "\n\t"
223 
224 /* A machine code snipped causing a trap, written in text form in a syntax
225    suitable for extended inline asm.  If no machine-specific definition exists,
226    define a stub here. */
227 #ifndef _JITTER_ASM_CRASH
228 # define _JITTER_ASM_CRASH                                      \
229     JITTER_ASM_COMMENT_PREFIX "unimplemented for this machine"
230 #endif // #ifndef _JITTER_ASM_DEBUGGING_NOP
231 
232 /* Expand to a C statement causing a trap.
233    This is meant to catch bugs, by delimiting code past the end of VM
234    specialized instruction which is not supposed to be replicated.  If such
235    code is ever executed it is useful to make the failure well visible.
236    It is important that this does not use __builtin_unreachable .  The
237    code this is used in is in fact unreachable, but GCC must not be
238    informed about the fact, as the code serves to keep the register
239    assignment compatible across different program points: the compiler
240    must see some impossible control transfers as possible. */
241 #define JITTER_CRASH_                                        \
242   asm volatile (JITTER_ASM_COMMENT_UNIQUE ("Cause a crash")  \
243                 _JITTER_ASM_CRASH "\n\t"                     \
244                 : /* outputs */)
245 
246 
247 
248 
249 /* Macros to let GCC see variables as changed.
250  * ************************************************************************** */
251 
252 // FIXME: use in the definitions below.
253 #define JITTER_MARK_AS_ASM_OUTPUT_(_jitter_constraint, _jitter_lvalue)  \
254   asm (JITTER_ASM_COMMENT_UNIQUE("Pretend to set "                      \
255                                  JITTER_STRINGIFY(_jitter_lvalue)       \
256                                  " with a "                             \
257                                  _jitter_constraint                     \
258                                  " constraint in "                      \
259                                  "%[the_jitter_lvalue]")                \
260        : [the_jitter_lvalue] _jitter_constraint (_jitter_lvalue))
261 
262 // FIXME: comment
263 #define JITTER_MARK_RVALUE_AS_READ_BY_ASSEMBLY(variable)               \
264   asm volatile (JITTER_ASM_COMMENT_UNIQUE(                             \
265                    "Pretend to read the register or memory variable "  \
266                    JITTER_STRINGIFY(variable) " in "                   \
267                    "%[_variable]")                                     \
268                 :                                                      \
269                 : [_variable] "X" (variable))
270 #define JITTER_MARK_LVALUE_AS_DEFINED_BY_ASSEMBLY(variable)             \
271   asm volatile (JITTER_ASM_COMMENT_UNIQUE(                              \
272                    "Pretend to write the register or memory variable "  \
273                    JITTER_STRINGIFY(variable) " in "                    \
274                    "%[_variable]")                                      \
275                 : [_variable] "=X" (variable))
276 #define JITTER_MARK_LVALUE_AS_SET_BY_ASSEMBLY(variable)                \
277   asm volatile (JITTER_ASM_COMMENT_UNIQUE(                             \
278                   "Pretend to read and write the register or memory "  \
279                   "variable " JITTER_STRINGIFY(variable) " in "        \
280                   "%[_variable]")                                      \
281                 : [_variable] "+g" (variable))
282 
283 #define JITTER_MARK_REGISTER_AS_DEFINED_BY_ASSEMBLY(variable)  \
284   asm volatile (JITTER_ASM_COMMENT_UNIQUE(                     \
285                    "Pretend to write the register variable "   \
286                    JITTER_STRINGIFY(variable) " in "           \
287                    "%[register_variable]")                     \
288                 : [register_variable] "=r" (variable))
289 #define JITTER_MARK_REGISTER_AS_SET_BY_ASSEMBLY(variable)              \
290   asm volatile (JITTER_ASM_COMMENT_UNIQUE(                             \
291                    "Pretend to read and write the register variable "  \
292                                    JITTER_STRINGIFY(variable) " in "   \
293                                    "%[register_variable]")             \
294                 : [register_variable] "+r" (variable))
295 
296 #define JITTER_MARK_MEMORY_AS_DEFINED_BY_ASSEMBLY(variable)  \
297   asm volatile (JITTER_ASM_COMMENT_UNIQUE(                   \
298                    "Pretend to write the memory variable "   \
299                      JITTER_STRINGIFY(variable))             \
300                 : "=m" (variable))
301 #define JITTER_MARK_MEMORY_AS_SET_BY_ASSEMBLY(variable)              \
302   asm volatile (JITTER_ASM_COMMENT_UNIQUE(                           \
303                    "Pretend to read and write the memory variable "  \
304                    JITTER_STRINGIFY(variable))                       \
305                 : "+m" (variable))
306 #define JITTER_MARK_ARRAY_ELEMENT_AS_SET_BY_ASSEMBLY(variable, offset)     \
307   asm volatile (JITTER_ASM_COMMENT_UNIQUE(                                 \
308                    "Pretend to read and write a memory word from "         \
309                    JITTER_STRINGIFY(variable)                              \
310                    " at offset " JITTER_STRINGIFY(offset))                 \
311                 : "+m" (* (jitter_int*) ((char*) (variable) + (offset))))
312 
313 
314 
315 
316 /* Fallback defect descriptors.
317  * ************************************************************************** */
318 
319 /* If defect descriptors are not supported, provide a dummy compatibility macro
320    expanding to an empty string.
321    FIXME: use defect descriptors, when possible, with minimal threading. */
322 #ifndef JITTER_ASM_DEFECT_DESCRIPTOR
323 # define JITTER_ASM_DEFECT_DESCRIPTOR ""
324 #endif // #ifndef JITTER_ASM_DEFECT_DESCRIPTOR
325 
326 
327 
328 /* Macros to let GCC see jumps to indeterminate locations.
329  * ************************************************************************** */
330 
331 // FIXME: comment.
332 #define JITTER_IP_INPUT_CONSTRAINT "r"
333 
334 // FIXME: comment.
335 // FIXME: remove.  Fake-jumping to an arbitrary label different from
336 // jitter_dispatch_label doesn't work well with defect descriptors.
337 #define JITTER_PRETEND_TO_POSSIBLY_JUMP_TO_(_jitter_label)             \
338   asm goto (JITTER_ASM_COMMENT_UNIQUE("Pretend to possibly jump to "   \
339                                       JITTER_STRINGIFY(_jitter_label)  \
340                                       " at %l["                        \
341                                       JITTER_STRINGIFY(_jitter_label)  \
342                                       "] based on "                    \
343                                       " jitter_ip"                     \
344                                       " at %[the_jitter_ip]")          \
345             : /* outputs */                                            \
346             : [the_jitter_ip] JITTER_IP_INPUT_CONSTRAINT (jitter_ip)   \
347               /* inputs */                                             \
348             : /* clobbers */                                           \
349             : /* jump destinations */ _jitter_label)
350 
351 #define JITTER_PRETEND_TO_UPDATE_IP_                          \
352   JITTER_MARK_AS_ASM_OUTPUT_("+" JITTER_IP_INPUT_CONSTRAINT,  \
353                              jitter_ip)
354 
355 #define JITTER_PRETEND_TO_JUMP_TO_(_jitter_label)      \
356   JITTER_PRETEND_TO_POSSIBLY_JUMP_TO_(_jitter_label);  \
357   __builtin_unreachable ()
358 
359 /* Expand to zero assembly instructions, but with inline asm constraints
360    affecting GCC's program representation as if the generated code could either
361    jump to the content of jitter_anywhere_variable or fall thru.
362 
363    Rationale: see the comment about JITTER_PRETEND_TO_JUMP_ANYWHERE below. */
364 #define JITTER_PRETEND_TO_POSSIBLY_JUMP_ANYWHERE()          \
365   do                                                        \
366     {                                                       \
367       asm goto (JITTER_ASM_DEFECT_DESCRIPTOR                \
368                 JITTER_ASM_COMMENT_UNIQUE( \
369                    "# Pretending to possibly jump to " \
370                    "%l[jitter_dispatch_label] thru %[_jitter_ip]") \
371                 : \
372                 : [_jitter_ip] JITTER_IP_INPUT_CONSTRAINT (jitter_ip) \
373                 : \
374                 : jitter_dispatch_label); \
375     }                                                                  \
376   while (false)
377 
378 /* Expand to zero assembly instructions, but with inline asm constraints and
379    intrinsics affecting GCC's program representation as if the generated code
380    unconditionally jumped to the content of jitter_anywhere_variable .
381 
382    Rationale: this code is actually unreachable, but for this program point I
383    want GCC to use a register assignment which is coherent with the beginning of
384    any other VM instruction, which may actually follow this point during
385    replicated code execution.  I would like to simply insert a "goto
386    jump_anywhere;" here, but GCC might move the jump before the instruction end
387    label [FIXME: can it really happen?  I'm pretty sure I saw that more than
388    once, but I should ask some GCC expert for confirmation], which must not
389    happen.  So, in order to generate something GCC optimizations can't meddle
390    with, I will insert a pretend-jump in inline assembly, with the constraint
391    that the control may only flow to the jump_anywhere label; from there control
392    could actually jump to any label in this function.  This way I ensure
393    compatibility among VM instructions without generating too much junk code, if
394    any.  The input operand is required to be in memory and *not* in a register,
395    so that GCC doesn't waste a register on this useless thing. */
396 #define JITTER_PRETEND_TO_JUMP_ANYWHERE          \
397   do                                             \
398     {                                            \
399       JITTER_PRETEND_TO_POSSIBLY_JUMP_ANYWHERE();  \
400       __builtin_unreachable ();                  \
401     }                                            \
402   while (false)
403 
404 
405 
406 
407 /* Macros expanding to per-instruction labels and variable names.
408  * ************************************************************************** */
409 
410 /* Expand to the label at the beginning of the user code for the specialized
411    instruction with the given name, in case of relocatable instructions;
412    otherwise expand to the label at the beginning of the relocatable stub
413    for non-relocatable instructions. */
414 #define JITTER_SPECIALIZED_INSTRUCTION_BEGIN_LABEL_OF(name)  \
415   JITTER_CONCATENATE_THREE(jitter_specialized_instruction_, name, _beginning_label)
416 
417 /* Expand to the label at the end of the user code for the specialized
418    instruction with the given name. */
419 #define JITTER_SPECIALIZED_INSTRUCTION_END_LABEL_OF(name)  \
420   JITTER_CONCATENATE_THREE(jitter_specialized_instruction_, name, _end_label)
421 
422 /* Expand to the label at the beginning of the user code for the specialized
423    instruction with the given name, in case of non-relocatable instructions. */
424 #define JITTER_SPECIALIZED_INSTRUCTION_NON_RELOCATABLE_CODE_LABEL_OF(name)  \
425   JITTER_CONCATENATE_THREE(jitter_specialized_instruction_, name, _non_relocatable_code_label)
426 
427 /* Expand to the name of the variable defined as
428    JITTER_SPECIALIZED_INSTRUCTION_NON_RELOCATABLE_CODE_LABEL_OF(name) .  The
429    variable is always stack-allocated and can be safely read from relocated
430    code. */
431 #define JITTER_SPECIALIZED_INSTRUCTION_NON_RELOCATABLE_CODE_VARIABLE_OF(name)  \
432   JITTER_CONCATENATE_THREE(jitter_specialized_instruction_, name, _non_relocatable_code_variable)
433 
434 
435 
436 
437 /* User macros to access VM state data structures.
438  * ************************************************************************** */
439 
440 /* Expand to the current VM state runtime, as a struct. */
441 #define JITTER_STATE_RUNTIME  \
442   jitter_state_runtime
443 
444 /* The macro JITTER_STATE_BACKING expands to the current VM state backing, as a
445    struct.  It is defined in machine-generated code. */
446 
447 /* Expand to an l-value referrign the named field in the current VM state
448    runtime. */
449 #define JITTER_STATE_RUNTIME_FIELD(field_name)  \
450   (JITTER_STATE_RUNTIME.field_name)
451 
452 /* Expand to an l-value referrign the named field in the current VM state
453    backing. */
454 #define JITTER_STATE_BACKING_FIELD(field_name)  \
455   (JITTER_STATE_BACKING.field_name)
456 
457 
458 
459 
460 /* Nullary macros expanding to per-instruction labels and variable names.
461  * ************************************************************************** */
462 
463 /* These rely on JITTER_SPECIALIZED_INSTRUCTION_MANGLED_NAME , whose definitions
464    is machine-generated to be visible from user instruction code.  Using these
465    zero-argument macros is more convenient.
466 
467    CPP expansion semantics allows these macros to be used even in the expansion
468    of other macros. */
469 
470 /* Expand to the specialized instruction begin label for the current instruction. */
471 #define JITTER_SPECIALIZED_INSTRUCTION_BEGIN_LABEL  \
472   JITTER_SPECIALIZED_INSTRUCTION_BEGIN_LABEL_OF(    \
473     JITTER_SPECIALIZED_INSTRUCTION_MANGLED_NAME)
474 
475 /* Expand to the stringification of
476    JITTER_SPECIALIZED_INSTRUCTION_BEGIN_LABEL . */
477 #define JITTER_SPECIALIZED_INSTRUCTION_BEGIN_LABEL_AS_STRING   \
478   JITTER_STRINGIFY(JITTER_SPECIALIZED_INSTRUCTION_BEGIN_LABEL)
479 
480 /* Expand to the specialized instruction end label for the current instruction. */
481 #define JITTER_SPECIALIZED_INSTRUCTION_END_LABEL  \
482   JITTER_SPECIALIZED_INSTRUCTION_END_LABEL_OF(    \
483     JITTER_SPECIALIZED_INSTRUCTION_MANGLED_NAME)
484 
485 /* Expand to the label at the beginning of the user code for the current
486    instruction, in case of non-relocatable instructions; expand to some
487    probably unbound identifier otherwise. */
488 #define JITTER_SPECIALIZED_INSTRUCTION_NON_RELOCATABLE_CODE_LABEL  \
489   JITTER_SPECIALIZED_INSTRUCTION_NON_RELOCATABLE_CODE_LABEL_OF(    \
490      JITTER_SPECIALIZED_INSTRUCTION_MANGLED_NAME)
491 
492 /* Expand to the name of the variable defined as
493    JITTER_SPECIALIZED_INSTRUCTION_NON_RELOCATABLE_CODE_LABEL .  The variable is
494    always stack-allocated and can be safely read from relocated code.  Expand to
495    some probably unbound identifier for relocatable instructions. */
496 #define JITTER_SPECIALIZED_INSTRUCTION_NON_RELOCATABLE_CODE_VARIABLE  \
497   JITTER_SPECIALIZED_INSTRUCTION_NON_RELOCATABLE_CODE_VARIABLE_OF(    \
498      JITTER_SPECIALIZED_INSTRUCTION_MANGLED_NAME)
499 
500 
501 
502 
503 /* VM routine termination.
504  * ************************************************************************** */
505 
506 /* Exit the executor function and return to C. */
507 #ifdef JITTER_REPLICATE
508   /* With replication enabled it's important to avoid tail-merging, which is why
509      this is a wrapped computed goto rather than a simple goto... */
510 # define JITTER_EXIT()                                                         \
511     do                                                                         \
512       {                                                                        \
513         JITTER_COMPUTED_GOTO (jitter_saved_exit_non_replicated_code_pointer);  \
514       }                                                                        \
515     while (false)
516 #else
517   /* ...But in the case of switch dispatching computed gotos may not be usable
518      at all, and with direct-threading there is no correctness problem. */
519 # define JITTER_EXIT()              \
520     do                              \
521       {                             \
522         goto jitter_exit_vm_label;  \
523       }                             \
524     while (false)
525 #endif // #ifdef JITTER_REPLICATE
526 
527 
528 
529 
530 /* VM instruction prolog and epilog.
531  * ************************************************************************** */
532 
533 /* VM instruction prolog. */
534 #if   defined(JITTER_DISPATCH_SWITCH)
535   /* VM instruction prolog: switch dispatching. */
536 # define JITTER_INSTRUCTION_PROLOG_(name, mangled_name, residual_arity)  \
537   case JITTER_CONCATENATE_THREE(JITTER_VM_PREFIX_LOWER_CASE,             \
538                                 _specialized_instruction_opcode_,        \
539                                 mangled_name):
540 #else
541   /* VM instruction prolog: every non-switch dispatches. */
542 # define JITTER_INSTRUCTION_PROLOG_(name, mangled_name, hotness_attribute)  \
543 {                                                                           \
544   JITTER_SPECIALIZED_INSTRUCTION_BEGIN_LABEL_OF(mangled_name):              \
545     __attribute__ ((hotness_attribute)); \
546 /*JITTER_COMMENT_IN_ASM_UNIQUE_("here comes " JITTER_STRINGIFY (name));*/
547 #endif // defined(JITTER_DISPATCH_SWITCH)
548 
549 /* How many words are used to encode the current specialized instruction, given
550    its residual arity.  According to the dispatching model there may be a word
551    for the opcode or the thread, or not.
552    This relies on JITTER_SPECIALIZED_INSTRUCTION_RESIDUAL_ARITY being defined,
553    which is the case when this macro is used as intended, from specialized
554    instruction code within the executor. */
555 #if   defined(JITTER_DISPATCH_SWITCH)            \
556    || defined(JITTER_DISPATCH_DIRECT_THREADING)
557 # define JITTER_SPECIALIZED_INSTRUCTION_WORD_NO          \
558     (1 + JITTER_SPECIALIZED_INSTRUCTION_RESIDUAL_ARITY)
559 #elif defined(JITTER_DISPATCH_MINIMAL_THREADING)
560 # define JITTER_SPECIALIZED_INSTRUCTION_WORD_NO    \
561     JITTER_SPECIALIZED_INSTRUCTION_RESIDUAL_ARITY
562 #elif defined(JITTER_DISPATCH_NO_THREADING)
563 # define JITTER_SPECIALIZED_INSTRUCTION_WORD_NO    \
564     JITTER_SPECIALIZED_INSTRUCTION_RESIDUAL_ARITY
565 #else
566 # error "unknown dispatching model"
567 #endif
568 
569 /* Modify the instruction pointer, if any, to skip the appropriate number of
570    residuals for the current instruction plus the opcode or thread, if any.
571    This relies on JITTER_SPECIALIZED_INSTRUCTION_RESIDUAL_ARITY being defined,
572    which is the case when this macro is used as intended, from specialized
573    instruction code within the executor.
574    FIXME: shall I use the do..while (false) trick here?  This macro is expanded
575    a lot of times, and never from user code. */
576 // FIXME: add a _ suffix to the name.
577 // FIXME: do not define for no-threading.
578 #if   defined(JITTER_DISPATCH_SWITCH)            \
579    || defined(JITTER_DISPATCH_DIRECT_THREADING)
580 # define JITTER_SKIP_RESIDUALS_                                       \
581   JITTER_SET_IP(jitter_ip + JITTER_SPECIALIZED_INSTRUCTION_WORD_NO);
582 #elif defined(JITTER_DISPATCH_MINIMAL_THREADING)
583 # define JITTER_SKIP_RESIDUALS_                                       \
584   JITTER_SET_IP(jitter_ip + JITTER_SPECIALIZED_INSTRUCTION_WORD_NO);
585 #elif defined(JITTER_DISPATCH_NO_THREADING)
586 # define JITTER_SKIP_RESIDUALS_  \
587   /* do nothing. */
588 #else
589 # error "unknown dispatching model"
590 #endif // #if   defined([dispatching model]...
591 
592 /* A VM instruction epilog. */
593 #if   defined(JITTER_DISPATCH_SWITCH)
594 # define JITTER_INSTRUCTION_EPILOG_(name, mangled_name, residual_arity)  \
595     JITTER_SKIP_RESIDUALS_;                                              \
596     JITTER_BRANCH_TO_IP();
597 #elif defined(JITTER_DISPATCH_DIRECT_THREADING)
598 # define JITTER_INSTRUCTION_EPILOG_(name, mangled_name, residual_arity)  \
599       JITTER_SKIP_RESIDUALS_;                                            \
600       JITTER_BRANCH_TO_IP();                                             \
601     }                                                                    \
602    JITTER_SPECIALIZED_INSTRUCTION_END_LABEL_OF(mangled_name):            \
603      __builtin_unreachable ();
604 #elif defined(JITTER_DISPATCH_MINIMAL_THREADING) || defined(JITTER_DISPATCH_NO_THREADING)
605 # define JITTER_INSTRUCTION_EPILOG_(name, mangled_name, residual_arity)  \
606        JITTER_SKIP_RESIDUALS_;                                           \
607      }                                                                   \
608 /*JITTER_PRETEND_TO_UPDATE_IP_; */ \
609 /*JITTER_PRETEND_TO_POSSIBLY_JUMP_ANYWHERE();*/ \
610 /*asm goto ("\n\taddiu $0, $0, 2\n\n" : : "r" (jitter_ip) : : JITTER_SPECIALIZED_INSTRUCTION_END_LABEL_OF(mangled_name)); */\
611 /*  JITTER_PRETEND_TO_UPDATE_IP_;*/ \
612 /*asm volatile ("\n\taddiu $0, $0, 4\n\t" JITTER_ASM_COMMENT_UNIQUE("foo1"):);*/ \
613 /*JITTER_PRETEND_TO_UPDATE_IP_;*/ \
614 JITTER_PRETEND_TO_UPDATE_IP_;\
615      /* Mark the end of the specialized instruction with a label. */     \
616     JITTER_SPECIALIZED_INSTRUCTION_END_LABEL_OF(mangled_name):           \
617 if (jitter_ip != NULL) goto * jitter_ip; \
618 /*JITTER_PRETEND_TO_POSSIBLY_JUMP_ANYWHERE();*/ \
619 /*__builtin_unreachable ();*/ \
620 /*JITTER_PRETEND_TO_UPDATE_IP_;*/ \
621 /*asm volatile ("\n\taddiu $0, $0, 5\n\t" JITTER_ASM_COMMENT_UNIQUE("foo2"));*/ \
622      /* What follows is unreachable, but serves to prevent GCC from      \
623         reordering code across labels.  The final indirect branch,       \
624         which of course would not branch anywhere correct if it were     \
625         actually executed, serves to force the compiler to keep the      \
626         register assignment compatible between this program point,       \
627         at the end of VM instructions, with the register assignment      \
628         at the beginning of every VM instruction, or even at their end.  \
629         From GCC's point of view, this goto * statement may reach any    \
630         label in the function whose address I have taken. */             \
631      JITTER_CRASH_;                                                      \
632      JITTER_PRETEND_TO_UPDATE_IP_;                                       \
633      goto * jitter_ip;
634 #else
635 # error "unknown dispatching model"
636 #endif // #if defined(JITTER_DISPATCH_SWITCH)
637 
638 
639 
640 
641 /* VM branching utility.
642  * ************************************************************************** */
643 
644 // FIXME: shall I move this page and everything below to some other header?
645 
646 /* After a VM branch-and-link operation is performed the rest of the specialized
647    instruction code is unreachable; in other words the return program point is
648    the beginning of the VM instruction following the calling VM instruction, and
649    not the machine instruction following the *machine* calling instruction.
650    This restriction is artificial on machines where VM calls are implemented by
651    native branch-and-link or call instructions, but is needed for compatibility
652    with simpler dispatching models where the intuitive semantics is not
653    implementable.
654    It's important that GCC does not assume that the code past the
655    branch-and-link is *automatically* unreachable, as would be the case if we
656    simply used __builtin_unreachable.
657    This is needed, for example, in the case of a branch-and-link at the end of
658    the first branch of a two-way conditional within a VM specialized instruction.
659    Without this jump the control after returning would fall back into the second
660    branch, which would be incorrect.
661    The solution is this macro: instead of marking the code as unreachable let's
662    simply jump to the end of the specialized instruction after the call.  In the
663    common case where there is no code to skip over GCC will optimize the jump
664    away.
665    This macro relies on JITTER_SPECIALIZED_INSTRUCTION_MANGLED_NAME having the
666    correct definition at the time of the macro call, which is true if the macro
667    is used as intended within user code for VM instructions. */
668 #define JITTER_JUMP_TO_SPECIALIZED_INSTRUCTION_END    \
669   do                                                  \
670     {                                                 \
671       goto JITTER_SPECIALIZED_INSTRUCTION_END_LABEL;  \
672     }                                                 \
673   while (false)
674 
675 
676 
677 
678 /* Avoiding GCC tail-merging optimizations with replicated code.
679  * ************************************************************************** */
680 
681 /* The problem is performing the equivalent of goto * while avoiding
682    tail-merging, which would be disastrous in replicated code when the shared
683    jumping instruction happened to be out of the current VM instruction
684    block. */
685 
686 /* Define a trivial wrapper around GNU C's computed goto.  This will be used for
687    direct threading, where tail-merging is not a problem. */
688 #define JITTER_COMPUTED_GOTO_TRIVIAL(target)  \
689   do                                          \
690     {                                         \
691       goto * (target);                        \
692     }                                         \
693   while (false)
694 
695 /* Perform the equivalent of a goto * in assembly, using unique inline asm code,
696    different from any other.  This is useful to avoid tail-merging, which would
697    be disastrous in replicated code when the shared jumping instruction happened
698    to be out of the current VM instruction block.
699 
700    The gotolabel declared in the inline asm statement is the "jump anywhere"
701    label, actually unreachable at run time, but branching to an undetermined
702    label; this is enough for GCC to assume the following to be any VM
703    instruction.
704    The actual jump target, which is always the beginning of the VM instruction,
705    is given as the first inline asm input.  The second input, not really used in
706    practice but needed to satisfy GCC, is again the "jump anywhere" label as an
707    expression -- without it, I've seen GCC 8 snapshots ICE at the following
708    __builtin_unreachable () with "error: flow control insn inside a basic
709    block".  Omitting __builtin_unreachable () is a no-no, as it enormously
710    simplifies the control-flow graph, and provides more opportunities for
711    optimization.
712 
713    This relies, of course, on the architecture-specific assembly syntax for
714    jumping thru a register or memory, along with the appropriate input operand
715    constaraint, to be defined in jitter-machine.h .
716 
717    JITTER_ASM_COMPUTED_GOTO_TEMPLATE holds the asm template as a string literal,
718    using an input argument named _jitter_the_target .
719    JITTER_ASM_COMPUTED_GOTO_INPUT_CONSTRAINT is the input constraint for the
720    target expression as a string literal, typically "r" but occasionally "rm"
721    on CISC architectrues. */
722 #if    (! defined(JITTER_ASM_COMPUTED_GOTO_TEMPLATE))          \
723     || (! defined(JITTER_ASM_COMPUTED_GOTO_INPUT_CONSTRAINT))
724   /* Fail if only one of the two architecture-specific macros for computed
725      gotos in assembly is defined.  That should never happen. */
726 # if    defined(JITTER_ASM_COMPUTED_GOTO_TEMPLATE)          \
727      || defined(JITTER_ASM_COMPUTED_GOTO_INPUT_CONSTRAINT)
728 #   error "only one of JITTER_ASM_COMPUTED_GOTO_TEMPLATE"
729 #   error "and JITTER_ASM_COMPUTED_GOTO_INPUT_CONSTRAINT is defined"
730 # endif
731 #else
732   /* A few architectures (notably PowerPC) may also need clobbers to jump via
733      register, but that is optional.  If no clobbers were defined, define them
734      as empty. */
735 # if ! defined(JITTER_ASM_COMPUTED_GOTO_CLOBBERS)
736 #   define JITTER_ASM_COMPUTED_GOTO_CLOBBERS /* nothing */
737 # endif // ! defined(JITTER_ASM_COMPUTED_GOTO_CLOBBERS)
738   /* If we arrived here we have all the information to define
739      JITTER_COMPUTED_GOTO_IN_ASM . */
740 # define JITTER_COMPUTED_GOTO_IN_ASM(target)                                   \
741     do                                                                         \
742       {                                                                        \
743         const void *_jitter_the_target = (const void*) (target);               \
744         asm goto (JITTER_ASM_DEFECT_DESCRIPTOR                                 \
745                   JITTER_ASM_COMMENT_UNIQUE("goto* in assembly to "            \
746                                             JITTER_STRINGIFY(target) " "       \
747                                             "at %[_jitter_the_target], "       \
748                                             "not actually going to "           \
749                                             "jitter_dispatch_label at "        \
750                                             "%l[jitter_dispatch_label]")       \
751                   JITTER_ASM_COMPUTED_GOTO_TEMPLATE                            \
752                   : /* outputs */                                              \
753                   : [_jitter_the_target]                                       \
754                     JITTER_ASM_COMPUTED_GOTO_INPUT_CONSTRAINT                  \
755                        (_jitter_the_target)                                    \
756                     /* inputs */                                               \
757                   : JITTER_ASM_COMPUTED_GOTO_CLOBBERS /* clobbers */           \
758                   : jitter_dispatch_label /* gotolabels */);                   \
759         /* This is an unconditional branch: the following statement in the     \
760            same block is unreachable. */                                       \
761         __builtin_unreachable();                                               \
762       }                                                                        \
763     while (false)
764 #endif // #if (! defined(JITTER_ASM_COMPUTED_GOTO_TEMPLATE)) || (! defined ...
765 
766 /* Define JITTER_COMPUTED_GOTO using one of the macros above. */
767 #ifdef JITTER_REPLICATE
768   /* Replication is enabled: use the assembly version of goto * , or the trivial
769      version if there is no assembly version available. */
770 # ifdef JITTER_COMPUTED_GOTO_IN_ASM
771 #   define JITTER_COMPUTED_GOTO(target)    \
772       JITTER_COMPUTED_GOTO_IN_ASM(target)
773 #   else
774 #   define JITTER_COMPUTED_GOTO(target)     \
775       JITTER_COMPUTED_GOTO_TRIVIAL(target)
776 # endif // ifdef JITTER_COMPUTED_GOTO_IN_ASM
777 #else /* replication is disabled */
778   /* Replication is disabled: we don't need the hacks above, so in this case we
779      can always use the fallback definition, using a native GCC computed goto;
780      this might be more efficient with conditionals. */
781 # define JITTER_COMPUTED_GOTO(target)      \
782     JITTER_COMPUTED_GOTO_TRIVIAL(target)
783 #endif // #ifdef JITTER_REPLICATE
784 
785 
786 
787 
788 /* VM branching.
789  * ************************************************************************** */
790 
791 /* Set the VM instruction pointer.  This is only defined for dispatching
792    models where an instruction pointer exists. */
793 #if      defined(JITTER_DISPATCH_SWITCH)             \
794       || defined(JITTER_DISPATCH_DIRECT_THREADING)   \
795       || defined(JITTER_DISPATCH_MINIMAL_THREADING)
796 # define JITTER_SET_IP(target_pointer)                           \
797     do                                                           \
798       {                                                          \
799         jitter_ip = (const union jitter_word*)(target_pointer);  \
800       }                                                          \
801     while (false)
802 #endif // #if      defined(JITTER_DISPATCH_SWITCH) || ...
803 
804 /* Jump to the current VM instruction pointer.  This is only defined for
805    dispatching models where an instruction pointer is actually used.*/
806 #if      defined(JITTER_DISPATCH_SWITCH)
807 # define JITTER_BRANCH_TO_IP()                 \
808     do                                         \
809       {                                        \
810         goto jitter_dispatching_switch_label;  \
811       }                                        \
812     while (false)
813 #elif    defined(JITTER_DISPATCH_DIRECT_THREADING)   \
814       || defined(JITTER_DISPATCH_MINIMAL_THREADING)
815 # define JITTER_BRANCH_TO_IP()                    \
816     do                                            \
817       {                                           \
818         JITTER_COMPUTED_GOTO(jitter_ip->thread);  \
819       }                                           \
820     while (false)
821 #endif // #if   defined(...
822 
823 /* Branch to a given VM label, represented as appropriate for the dispatching
824    model. */
825 #ifdef JITTER_DISPATCH_NO_THREADING
826 #define JITTER_BRANCH(target)        \
827   do                                 \
828     {                                \
829       JITTER_COMPUTED_GOTO(target);  \
830     }                                \
831   while (false)
832 #else
833 #define JITTER_BRANCH(target_pointer)  \
834   do                                   \
835     {                                  \
836       JITTER_SET_IP(target_pointer);   \
837       JITTER_BRANCH_TO_IP();           \
838       __builtin_unreachable (); /* FIXME: this seems beneficial here, differently from the no-threading case; anyway, the problem could be catched with a defect handler, and this is not a guarantee of correctness. */ \
839     }                                  \
840   while (false)
841 #endif // #ifdef JITTER_DISPATCH_NO_THREADING
842 
843 /* _JITTER_PROCEDURE_PROLOG is only used by generated code in callee
844    instructions, and is not intended for the user.  The user is only supposed to
845    read JITTER_LINK , which holds the value set by _JITTER_PROCEDURE_PROLOG --
846    either as defined here or in a machine-specific definition. */
847 # define __JITTER_PROCEDURE_PROLOG_COMMON(link_union)      \
848     do                                                     \
849       {                                                    \
850         (link_union).pointer                               \
851           = (void *) (jitter_state_runtime._jitter_link);  \
852       }                                                    \
853     while (false)
854 #if    defined(JITTER_DISPATCH_SWITCH)             \
855     || defined(JITTER_DISPATCH_DIRECT_THREADING)   \
856     || defined(JITTER_DISPATCH_MINIMAL_THREADING)
857 # define _JITTER_PROCEDURE_PROLOG(link_union)  \
858     __JITTER_PROCEDURE_PROLOG_COMMON(link_union)
859 #elif    defined(JITTER_DISPATCH_NO_THREADING)
860 # ifndef JITTER_MACHINE_SUPPORTS_PROCEDURE
861 #   define _JITTER_PROCEDURE_PROLOG(link_union)  \
862       __JITTER_PROCEDURE_PROLOG_COMMON(link_union)
863 # endif // ifndef JITTER_MACHINE_SUPPORTS_PROCEDURE
864 #else
865 # error "unknown dispatching model"
866 #endif
867 
868 /* Branch-and-link to a given VM label, represented in a way appropriate for the
869    dispatching model.
870    A branch-and-link operation unconditionally branches to a VM target, and also
871    saves the return address (the beginning of the following VM instruction,
872    ignoring any code in the caller instruction past the branch-and-link) in some
873    implementation-specific resource, only up to the end of the callee
874    instruction.
875    The saved return access is accessible in reading from the target VM
876    instruction, which *must* be a callee instruction, and only reachable thru
877    branch-and-link , as JITTER_LINK .
878 
879    This is a generic definition which works everywhere but does not exploit the
880    hardware branch target predictor like a machine-specific implementation
881    could.  Return operations will easily mispredict.
882 
883    This macro is reserved for internal use.  The macro intended for the user
884    is named JITTER_BRANCH_AND_LINK , and is only visible from caller
885    instructions; this forces the user to correctly declare callers so that
886    return labels can be handled in every case. */
887 #if    defined(JITTER_DISPATCH_SWITCH)             \
888     || defined(JITTER_DISPATCH_DIRECT_THREADING)   \
889     || defined(JITTER_DISPATCH_MINIMAL_THREADING)
890 # define JITTER_BRANCH_AND_LINK_INTERNAL(target_rvalue)                      \
891     do                                                               \
892       {                                                              \
893         jitter_state_runtime._jitter_link                            \
894           = ((const union jitter_word *)                             \
895              (jitter_ip + JITTER_SPECIALIZED_INSTRUCTION_WORD_NO));  \
896         JITTER_BRANCH(target_rvalue);                                \
897       }                                                              \
898     while (false)
899 #elif    defined(JITTER_DISPATCH_NO_THREADING)
900 # ifndef JITTER_MACHINE_SUPPORTS_PROCEDURE
901 #   define JITTER_BRANCH_AND_LINK_INTERNAL(target_rvalue)                              \
902       do                                                                       \
903         {                                                                      \
904           /* Use the return address from the implicit specialized argument */  \
905           jitter_state_runtime._jitter_link = JITTER_RETURN_ADDRESS;           \
906           JITTER_BRANCH(target_rvalue);                                        \
907         }                                                                      \
908       while (false)
909 # endif // ifndef JITTER_MACHINE_SUPPORTS_PROCEDURE
910 #else
911 # error "unknown dispatching model"
912 #endif
913 
914 /* Define the branch-and-link-with operation, in a way similar to
915    JITTER_BRANCH_AND_LINK_INTERNAL just above.  In this case, however, the
916    macro is not conditionally defined: a branch-and-link-with doesn't count as a
917    call (since it can't return), and therefore the operation is available in any
918    VM instruction, even non-callers.  This is why the macro name doesn't begin
919    with an underscore. */
920 #if    defined(JITTER_DISPATCH_SWITCH)                    \
921     || defined(JITTER_DISPATCH_DIRECT_THREADING)          \
922     || defined(JITTER_DISPATCH_MINIMAL_THREADING)         \
923     || (defined(JITTER_DISPATCH_NO_THREADING)             \
924         && ! defined(JITTER_MACHINE_SUPPORTS_PROCEDURE))
925 # define JITTER_BRANCH_AND_LINK_WITH(_jitter_target_rvalue,      \
926                                      _jitter_new_link)           \
927     do                                                           \
928       {                                                          \
929         jitter_state_runtime._jitter_link = (_jitter_new_link);  \
930         JITTER_BRANCH(_jitter_target_rvalue);                    \
931       }                                                          \
932     while (false)
933 #endif
934 
935 /* Sanity check, useful for writing new ports. */
936 #if (defined(JITTER_DISPATCH_NO_THREADING)          \
937      && defined(JITTER_MACHINE_SUPPORTS_PROCEDURE)  \
938      && ! defined(JITTER_BRANCH_AND_LINK_WITH))
939 # error "The machine claims to support procedures but lacks a definition"
940 # error "for JITTER_BRANCH_AND_LINK_WITH .  Can't use no-threading."
941 #endif // #if ... sanity check.
942 
943 /* An internal definition used for JITTER_RETURN . */
944 # define _JITTER_RETURN_COMMON(link_rvalue)  \
945     do                                       \
946       {                                      \
947         JITTER_BRANCH(link_rvalue);          \
948       }                                      \
949     while (false)
950 
951 /* Return to the caller, using the label provided as the rvalue parameter as the
952    destination.  In its generic implementation this is a simple unconditional
953    branch, but of course machine-specific implementation will use native return
954    or branch-to-link-register instruction, with better branch target prediction
955    performance. */
956 #if    defined(JITTER_DISPATCH_SWITCH)            \
957     || defined(JITTER_DISPATCH_DIRECT_THREADING)  \
958     || defined(JITTER_DISPATCH_MINIMAL_THREADING)
959 # define JITTER_RETURN(link_rvalue)  \
960     _JITTER_RETURN_COMMON(link_rvalue)
961 #elif    defined(JITTER_DISPATCH_NO_THREADING)
962 # ifndef JITTER_MACHINE_SUPPORTS_PROCEDURE
963 #   define JITTER_RETURN(link_rvalue)  \
964       _JITTER_RETURN_COMMON(link_rvalue)
965 # endif // ifndef JITTER_MACHINE_SUPPORTS_PROCEDURE
966 #else
967 # error "unknown dispatching model"
968 #endif
969 
970 
971 /* VM conditional non-fast branching.
972  * ************************************************************************** */
973 
974 /* These macros are used internally in replacement instructions, as alternatives
975    to fast conditional branches.  They are not very useful for human users, as
976    they expand to the same code generated by unconditional branches within
977    conditionals; however their direct use is not forbidden. */
978 
979 /* This macro is only used internally in the following macro definitions in this
980    section. */
981 #define _JITTER_BRANCH_IF(outer_operator, type, operand0,    \
982                           infix_operator, operand1, target)  \
983   do                                                         \
984     {                                                        \
985       if (outer_operator ((type) (operand0)                  \
986                           infix_operator                     \
987                           (type) (operand1)))                \
988         JITTER_BRANCH (target);                              \
989     }                                                        \
990   while (false)
991 
992 /* These are the non-fast counterparts of the similarly named macros in
993    jitter-fast-branch.h and the machine-specific headers. */
994 #define JITTER_BRANCH_IF_ZERO(operand, target)            \
995   _JITTER_BRANCH_IF(, jitter_uint, operand, ==, 0, target)
996 #define JITTER_BRANCH_IF_NONZERO(operand, target)         \
997   _JITTER_BRANCH_IF(, jitter_uint, operand, !=, 0, target)
998 #define JITTER_BRANCH_IF_POSITIVE(operand, target)      \
999   _JITTER_BRANCH_IF(, jitter_int, operand, >, 0, target)
1000 #define JITTER_BRANCH_IF_NONPOSITIVE(operand, target)    \
1001   _JITTER_BRANCH_IF(, jitter_int, operand, <=, 0, target)
1002 #define JITTER_BRANCH_IF_NEGATIVE(operand, target)      \
1003   _JITTER_BRANCH_IF(, jitter_int, operand, <, 0, target)
1004 #define JITTER_BRANCH_IF_NONNEGATIVE(operand, target)    \
1005   _JITTER_BRANCH_IF(, jitter_int, operand, >=, 0, target)
1006 #define JITTER_BRANCH_IF_EQUAL(operand0, operand1, target)     \
1007   _JITTER_BRANCH_IF(, jitter_int, operand0, ==, operand1, target)
1008 #define JITTER_BRANCH_IF_NOTEQUAL(operand0, operand1, target)  \
1009   _JITTER_BRANCH_IF(, jitter_int, operand0, !=, operand1, target)
1010 #define JITTER_BRANCH_IF_LESS_SIGNED(operand0, operand1, target)  \
1011   _JITTER_BRANCH_IF(, jitter_int, operand0, <, operand1, target)
1012 #define JITTER_BRANCH_IF_LESS_UNSIGNED(operand0, operand1, target)  \
1013   _JITTER_BRANCH_IF(, jitter_uint, operand0, <, operand1, target)
1014 #define JITTER_BRANCH_IF_NOTLESS_SIGNED(operand0, operand1, target)  \
1015   _JITTER_BRANCH_IF(, jitter_int, operand0, >=, operand1, target)
1016 #define JITTER_BRANCH_IF_NOTLESS_UNSIGNED(operand0, operand1, target)  \
1017   _JITTER_BRANCH_IF(, jitter_uint, operand0, >=, operand1, target)
1018 #define JITTER_BRANCH_IF_GREATER_SIGNED(operand0, operand1, target)  \
1019   _JITTER_BRANCH_IF(, jitter_int, operand0, >, operand1, target)
1020 #define JITTER_BRANCH_IF_GREATER_UNSIGNED(operand0, operand1, target)  \
1021   _JITTER_BRANCH_IF(, jitter_uint, operand0, >, operand1, target)
1022 #define JITTER_BRANCH_IF_NOTGREATER_SIGNED(operand0, operand1, target)  \
1023   _JITTER_BRANCH_IF(, jitter_int, operand0, <=, operand1, target)
1024 #define JITTER_BRANCH_IF_NOTGREATER_UNSIGNED(operand0, operand1, target)  \
1025   _JITTER_BRANCH_IF(, jitter_uint, operand0, <=, operand1, target)
1026 #define JITTER_BRANCH_IF_AND(operand0, operand1, target)  \
1027   _JITTER_BRANCH_IF(, jitter_uint, operand0, &, operand1, target)
1028 #define JITTER_BRANCH_IF_NOTAND(operand0, operand1, target)  \
1029   _JITTER_BRANCH_IF(!, jitter_uint, operand0, &, operand1, target)
1030 
1031 /* This factors the common code for branch-on-overflow primitives. */
1032 #define JITTER_BRANCH_IF_OPERATION_OVERFLOWS(operation_name,     \
1033                                              operand0, operand1, \
1034                                              target)             \
1035   do                                                             \
1036     {                                                            \
1037       if (JITTER_CONCATENATE_THREE (JITTER_WOULD_,               \
1038                                     operation_name,              \
1039                                     _OVERFLOW)                   \
1040              (jitter_uint, jitter_int,                           \
1041               (operand0), (operand1),                            \
1042               JITTER_BITS_PER_WORD))                             \
1043         JITTER_BRANCH (target);                                  \
1044     }                                                            \
1045   while (false)
1046 
1047 #define JITTER_BRANCH_IF_PLUS_OVERFLOWS(opd0, opd1, tgt)              \
1048   JITTER_BRANCH_IF_OPERATION_OVERFLOWS (PLUS, (opd0), (opd1), (tgt))
1049 #define JITTER_BRANCH_IF_MINUS_OVERFLOWS(opd0, opd1, tgt)              \
1050   JITTER_BRANCH_IF_OPERATION_OVERFLOWS (MINUS, (opd0), (opd1), (tgt))
1051 #define JITTER_BRANCH_IF_TIMES_OVERFLOWS(opd0, opd1, tgt)              \
1052   JITTER_BRANCH_IF_OPERATION_OVERFLOWS (TIMES, (opd0), (opd1), (tgt))
1053 #define JITTER_BRANCH_IF_DIVIDED_OVERFLOWS(opd0, opd1, tgt)              \
1054   JITTER_BRANCH_IF_OPERATION_OVERFLOWS (DIVIDED, (opd0), (opd1), (tgt))
1055 #define JITTER_BRANCH_IF_REMAINDER_OVERFLOWS(opd0, opd1, tgt)              \
1056   JITTER_BRANCH_IF_OPERATION_OVERFLOWS (REMAINDER, (opd0), (opd1), (tgt))
1057 #define JITTER_BRANCH_IF_NEGATE_OVERFLOWS(opd0, tgt)              \
1058   JITTER_BRANCH_IF_OPERATION_OVERFLOWS (MINUS, 0, (opd0), (tgt))
1059 
1060 /* This factors the common code for operate-and-branch-on-overflow primitives. */
1061 #define JITTER_OPERATION_BRANCH_IF_OVERFLOW(res, operation_name,       \
1062                                             operand0, infix, operand1, \
1063                                             target)                    \
1064   do                                                                   \
1065     {                                                                  \
1066       const jitter_int _jitter_opd0_value = (jitter_int) (operand0);   \
1067       const jitter_int _jitter_opd1_value = (jitter_int) (operand1);   \
1068       if (JITTER_CONCATENATE_THREE (JITTER_WOULD_, operation_name,     \
1069                                     _OVERFLOW)                         \
1070              (jitter_uint, jitter_int,                                 \
1071               _jitter_opd0_value, _jitter_opd1_value,                  \
1072               JITTER_BITS_PER_WORD))                                   \
1073         JITTER_BRANCH (target);                                        \
1074       else                                                             \
1075         (res) = _jitter_opd0_value infix _jitter_opd1_value;           \
1076     }                                                                  \
1077   while (false)
1078 
1079 #define JITTER_PLUS_BRANCH_IF_OVERFLOW(res, opd0, opd1, tgt)  \
1080   JITTER_OPERATION_BRANCH_IF_OVERFLOW ((res), PLUS, (opd0), +, (opd1), (tgt))
1081 #define JITTER_MINUS_BRANCH_IF_OVERFLOW(res, opd0, opd1, tgt)  \
1082   JITTER_OPERATION_BRANCH_IF_OVERFLOW ((res), MINUS, (opd0), -, (opd1), (tgt))
1083 #define JITTER_TIMES_BRANCH_IF_OVERFLOW(res, opd0, opd1, tgt)  \
1084   JITTER_OPERATION_BRANCH_IF_OVERFLOW ((res), TIMES, (opd0), *, (opd1), (tgt))
1085 #define JITTER_DIVIDED_BRANCH_IF_OVERFLOW(res, opd0, opd1, tgt)  \
1086   JITTER_OPERATION_BRANCH_IF_OVERFLOW ((res), DIVIDED, (opd0), /, (opd1), (tgt))
1087 #define JITTER_REMAINDER_BRANCH_IF_OVERFLOW(res, opd0, opd1, tgt)  \
1088   JITTER_OPERATION_BRANCH_IF_OVERFLOW ((res), REMAINDER, (opd0), %, (opd1), (tgt))
1089 #define JITTER_NEGATE_BRANCH_IF_OVERFLOW(res, opd0, tgt)  \
1090   JITTER_OPERATION_BRANCH_IF_OVERFLOW ((res), MINUS, 0, -, (opd0), (tgt))
1091 
1092 #endif // #ifndef JITTER_EXECUTOR_H_
1093