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