1 /* Jitter: defective VM instruction header.
2 
3    Copyright (C) 2018, 2021 Luca Saiu
4    Updated in 2020 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 #ifndef JITTER_DEFECT_H_
24 #define JITTER_DEFECT_H_
25 
26 /* Include core headers.
27  * ************************************************************************** */
28 
29 /* Include macro definitions about whether we have a machine file, and about the
30    dispatching model. */
31 #include <jitter/jitter.h>
32 
33 /* Include sectioning macros, if they are supported. */
34 #if defined (JITTER_HAVE_KNOWN_BINARY_FORMAT)
35 # include <jitter/jitter-sections.h>
36 #endif // #if defined (JITTER_HAVE_KNOWN_BINARY_FORMAT)
37 
38 /* The debugging facility relies on standard I/O. */
39 #include <stdio.h>
40 
41 
42 
43 
44 /* Introduction.
45  * ************************************************************************** */
46 
47 // FIXME: write.
48 
49 
50 
51 
52 /* Defect descriptor data structures: C API.
53  * ************************************************************************** */
54 
55 /* A descriptor associated to each program point possibly causing a specialized
56    VM instruction to be defective.  A specialized VM instruction is defective if
57    it has even one such descritpor with non-zero displacement. */
58 struct jitter_defect_descriptor
59 {
60   /* The opcode of the specialized instruction in question. */
61   jitter_uint specialized_opcode;
62 
63   /* The distance between a used label as seen from C and the same label as seen
64      from assembly.  A displacement of zero means that the C and the assembly
65      views agree; a non-zero displacement means that the instruction is
66      defective. */
67   jitter_int displacement;
68 };
69 
70 
71 
72 
73 /* Prefix-dependent names for globals.
74  * ************************************************************************** */
75 
76 /* The name of the global descriptor vector. */
77 #define JITTER_DEFECT_DESCRIPTORS_NAME(_jitter_vm_the_prefix)         \
78   JITTER_CONCATENATE_TWO(_jitter_vm_the_prefix, _defect_descriptors)
79 
80 /* The name of the global descriptor vector. */
81 #define JITTER_DEFECT_DESCRIPTORS_SIZE_IN_BYTES_NAME(_jitter_vm_the_prefix)     \
82   JITTER_CONCATENATE_TWO(JITTER_DEFECT_DESCRIPTORS_NAME(_jitter_vm_the_prefix), \
83                          _size_in_bytes)
84 
85 /* Expand to extern declaration of the variables defined in assembly, to be used
86    from C. */
87 #define JITTER_DEFECT_DESCRIPTOR_DECLARATIONS_(_jitter_vm_the_prefix)   \
88   extern const struct jitter_defect_descriptor                          \
89   JITTER_DEFECT_DESCRIPTORS_NAME(_jitter_vm_the_prefix) [];             \
90   extern const jitter_uint                                              \
91   JITTER_DEFECT_DESCRIPTORS_SIZE_IN_BYTES_NAME(_jitter_vm_the_prefix);
92 
93 
94 
95 
96 /* Defect descriptor opening and closing macros.
97  * ************************************************************************** */
98 
99 /* Each defect descriptor contains information about one program point possibly
100    causing a defect. */
101 
102 /* Expand to a string literal containing the .rodata subsection number
103    containing the defect descriptors. */
104 #define JITTER_ASM_DEFECT_SUBSECTION  \
105   "11"
106 
107 /* Expand to a C top-level inline asm statement containing the defect
108    header. */
109 #define JITTER_DEFECT_HEADER(_jitter_vm_the_prefix)                  \
110   asm (JITTER_ASM_OPEN_DEFINITION                                    \
111           (JITTER_ASM_DEFECT_SUBSECTION,                             \
112            JITTER_DEFECT_DESCRIPTORS_NAME (_jitter_vm_the_prefix)))
113 
114 /* Expand to a C top-level inline asm statement containing the defect
115    footer. */
116 #define JITTER_DEFECT_FOOTER(_jitter_vm_the_prefix)                  \
117   asm (JITTER_ASM_CLOSE_DEFINITION                                   \
118           (JITTER_ASM_DEFECT_SUBSECTION,                             \
119            JITTER_DEFECT_DESCRIPTORS_NAME (_jitter_vm_the_prefix)))
120 
121 
122 
123 
124 /* Defect descriptor macros.
125  * ************************************************************************** */
126 
127 /* Expand to a literal template string adding a defect descriptor for the
128    current specialized instruction.  This should be used within an inline asm
129    goto statement having jitter_dispatch_label as gotolabel. */
130 #define JITTER_ASM_DEFECT_DESCRIPTOR                                \
131   JITTER_ASM_COMMENT_UNIQUE(                                        \
132      "Defect descriptor for "                                       \
133      JITTER_STRINGIFY(JITTER_SPECIALIZED_INSTRUCTION_MANGLED_NAME)) \
134   JITTER_ASM_ENTER_SUBSECTION(JITTER_ASM_DEFECT_SUBSECTION) "\n\t"  \
135   JITTER_ASM_WORD " "                                               \
136      JITTER_STRINGIFY(JITTER_SPECIALIZED_INSTRUCTION_OPCODE) "\n\t" \
137   JITTER_ASM_WORD " "                                               \
138      "(%l[jitter_dispatch_label] - jitter_dispatch_label_asm)\n"    \
139   JITTER_ASM_EXIT_SUBSECTION "\n\t"
140 
141 
142 
143 
144 /* Defect efficient data structures.
145  * ************************************************************************** */
146 
147 /* Compiling code with defect descriptors yields an object file containing all
148    the required information, but the subsection hack leaves the data ordered in
149    a very inconvenient and inefficient way.  This functionality generates a
150    "defect table", which is a C array which can be indexed by a specialized
151    instruction opcode, whose elements are each the opcode of the replacement
152    specialized instruction; this opcode will be the same as the index if the
153    instruction is not defective.
154 
155    The "worst-case defect table" is a defect table mapping each specialized
156    opcode for an instruction which can possibly be defective to its replacement.
157    The worst-case defect table is a global constant for each VM.
158 
159    The idea is, of course, to make searching for a replacement instruction a
160    fast O(1) operation which can be executed unconditionally on any specialized
161    instruction, be it defective or not. */
162 
163 /* I can just use a forward-declaration here instead of a header inclusion.
164    Anyway this is the struct defined in jitter/jitter-vm.h . */
165 struct jitter_vm;
166 
167 /* Given a pointer to the VM struct, an initial pointer to the defect descriptor
168    array, the number of defects descriptors and a pointer to the worst-case
169    defect table, initialize the pointed defect table.  The defect table is a
170    global, already existing for any given VM, which only needs to be initialized
171    once even if a VM subsystem is finalized and re-initialized multiple
172    times. */
173 void
174 jitter_fill_defect_table (jitter_uint *defect_table,
175                           const struct jitter_vm *vm,
176                           const jitter_uint *worst_case_defect_table,
177                           const struct jitter_defect_descriptor *descs,
178                           size_t desc_no)
179   __attribute__ ((nonnull (1, 2, 3, 4)));
180 
181 
182 
183 
184 /* Defect debugging.
185  * ************************************************************************** */
186 
187 /* Dump the pointed defect table to the given stream. */
188 void
189 jitter_dump_defect_table (FILE *f,
190                           const jitter_uint *defect_table,
191                           const struct jitter_vm *vm)
192   __attribute__ ((nonnull (1, 2, 3)));
193 
194 
195 #endif // JITTER_DEFECT_H_
196