1 /**************************************************************************** 2 * Copyright (C) 2008-2012 by Matteo Franchin * 3 * * 4 * This file is part of Box. * 5 * * 6 * Box is free software: you can redistribute it and/or modify it * 7 * under the terms of the GNU Lesser General Public License as published * 8 * by the Free Software Foundation, either version 3 of the License, or * 9 * (at your option) any later version. * 10 * * 11 * Box is distributed in the hope that it will be useful, * 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 14 * GNU Lesser General Public License for more details. * 15 * * 16 * You should have received a copy of the GNU Lesser General Public * 17 * License along with Box. If not, see <http://www.gnu.org/licenses/>. * 18 ****************************************************************************/ 19 20 /** 21 * @file vmsym.h 22 * @brief The implementation of the reference/definition list for the box VM. 23 * 24 * This file implements the mechanism to define and reference procedures, 25 * labels and other symbols needed by a Box bytecode compiled program. 26 * This mechanism is similar to the linking of the object files produced 27 * by the compilation of several C-source files. In this sense whe could 28 * say that this file implements the Box linker. 29 */ 30 31 #ifndef _BOX_VMSYM_H 32 # define _BOX_VMSYM_H 33 34 # include <box/types.h> 35 # include <box/array.h> 36 # include <box/hashtable.h> 37 # include <box/list.h> 38 # include <box/vm.h> 39 40 /** 41 * @brief An integer number used to identify a symbol. 42 */ 43 typedef BoxUInt BoxVMSymID; 44 45 /** Invalid symbol ID */ 46 #define BOXVMSYMID_NONE ((BoxVMSymID) 0) 47 48 /** 49 * @brief The table of references and definitions for the Box VM. 50 * 51 * This structure is embedded in the main VM structure VMProgram. 52 */ 53 typedef struct { 54 BoxHT syms; 55 BoxArr data, 56 defs, 57 refs, 58 dylibs; 59 } BoxVMSymTable; 60 61 /** This is the prototype for a function which generates a piece of code 62 * which makes a reference to a symbol. 63 * Functions of this type are called when a reference is made to a symbol 64 * ('resolving=0') or when the reference is being resolved ('resolving=1'). 65 * If the symbol has already been defined, then 'defined=1', otherwise 66 * 'defined=0'. 'def' and 'def_size'are respectively the pointer 67 * and the size of the definition data (which are allocated when the symbol 68 * is created with BoxVMSym_New). 69 */ 70 typedef BoxTask (*BoxVMSymResolver)(BoxVM *vm, BoxVMSymID sym_id, 71 BoxUInt sym_type, int defined, 72 void *def, size_t def_size, 73 void *ref, size_t ref_size); 74 75 /** 76 * @brief The details about a symbol. 77 */ 78 typedef struct { 79 BoxVMSymID sym_id; /**< The symbol ID number */ 80 BoxName name; /**< The name of the symbol */ 81 int defined; /**< Has a definition been given for the symbol? */ 82 size_t def_size, /**< Size of the symbol definition data. */ 83 def_addr; /**< Address of the data in the array 'data' */ 84 BoxUInt sym_type, /**< Type of the symbol */ 85 first_ref; /**< Number of the first reference to the symbol */ 86 } BoxVMSym; 87 88 /** 89 * @brief A reference... 90 */ 91 typedef struct { 92 BoxVMSymID 93 sym_id, /**< ID-number of the referenced symbol */ 94 next; /**< ID-number of the next reference to the same symbol */ 95 size_t ref_size, /**< Size of the data containing the symbol reference */ 96 ref_addr; /**< Address of the data in the array 'data' */ 97 int resolved; /**< Has the reference been resolved? */ 98 BoxVMSymResolver 99 resolver; /**< Function to be called for resolution */ 100 } BoxVMSymRef; 101 102 /* Data types used by the BoxVMSym_Code_* functions */ 103 typedef BoxTask (*BoxVMSymCodeGen)(BoxVM *vm, BoxVMSymID sym_id, 104 BoxUInt sym_type, int defined, 105 void *def, size_t def_size, 106 void *ref, size_t ref_size); 107 108 typedef struct { 109 BoxUInt proc_num, 110 pos, 111 size; 112 BoxVMSymCodeGen 113 code_gen; 114 } BoxVMSymCodeRef; 115 116 /** Initialize the symbol table of the program. 117 * @param vmp is the VM-program. 118 */ 119 BOXEXPORT void 120 BoxVMSymTable_Init(BoxVMSymTable *t); 121 122 /** Destroy the symbol table of the program. 123 * @param vmp is the VM-program. 124 */ 125 BOXEXPORT void 126 BoxVMSymTable_Finish(BoxVMSymTable *t); 127 128 /** Create a new symbol with name 'n' and type 'sym_type'. 129 * '*sym_id' is set with the allocated symbol number. 130 */ 131 BOXEXPORT BoxVMSymID 132 BoxVMSym_New(BoxVM *vmp, BoxUInt sym_type, BoxUInt def_size); 133 134 /** 135 * @brief Create a new symbol. 136 * 137 * @param vm The virtual machine associated to the symbol. 138 * @param sym_type The type of the symbol. 139 * @param def Pointer to the symbol data. 140 * @param def_size Size of the symbol data. 141 * @return A new symbol identifier (an integer). 142 */ 143 BOXEXPORT BoxVMSymID 144 BoxVMSym_Create(BoxVM *vm, BoxUInt sym_type, 145 const void *def, size_t def_size); 146 147 /** Associate a name to the symbol sym_id. 148 */ 149 BOXEXPORT void 150 BoxVMSym_Set_Name(BoxVM *vm, BoxVMSymID sym_id, const char *name); 151 152 /** Get the name of the given symbol sym_id (NULL if the symbol has not 153 * a name) 154 */ 155 const char *BoxVMSym_Get_Name(BoxVM *vm, BoxVMSymID sym_id); 156 157 /** 158 * @brief Find a symbol with the given name. 159 */ 160 BOXEXPORT BoxVMSymID 161 BoxVM_Find_Sym(BoxVM *vm, const char *name); 162 163 /** 164 * @brief Get the definition data for a symbol. 165 * 166 * @param vm The virtual machine the symbol refers to. 167 * @param sym_id The symbol identifier. 168 * @return The pointer to the definion data. The caller can write the 169 * definition data before defining the symbol. If this is what the caller 170 * decides to do, then it should also define the symbol by passing @c NULL 171 * as a last argument for BoxVMSym_Define() to avoid overwriting the symbol 172 * data. 173 * @note The pointer returned by this function must be used immediately, 174 * before adding new symbols (as data may be relocated when doing so). 175 */ 176 BOXEXPORT void * 177 BoxVMSym_Get_Definition(BoxVM *vm, BoxVMSymID sym_id); 178 179 /** 180 * @brief Define a symbol which was previously created with BoxVMSym_Create(). 181 * 182 * @param vm The virtual machine the symbol refers to. 183 * @param sym_id The symbol identifier. 184 * @param def The symbol data. Use @c NULL to leave the symbol data as it 185 * currently is (as set using BoxVMSym_Get_Definition()). 186 * @return @c BOXTASK_OK if the symbol was defined, else @c BOXTASK_FAILURE 187 * (which typically means that a symbol was defined twice). 188 */ 189 BOXEXPORT BoxTask 190 BoxVMSym_Define(BoxVM *vm, BoxVMSymID sym_id, void *def); 191 192 /** Return whether the symbol 'sym_id' has been defined or not */ 193 BOXEXPORT int 194 BoxVMSym_Is_Defined(BoxVM *vm, BoxVMSymID sym_id); 195 196 typedef enum { 197 BOXVMSYM_AUTO, 198 BOXVMSYM_RESOLVED, 199 BOXVMSYM_UNRESOLVED, 200 } BoxVMSymStatus; 201 202 /** Add a reference to the symbol 'sym_id'. The reference data is pointed 203 * by 'ref' and has size 'ref_size'. 'r' is the function to be called for 204 * resolving the symbol. If 'resolved' == BOXVMSYM_RESOLVED, the reference 205 * is marked as resolved, if 'resolved' == BOXVMSYM_UNRESOLVED, it is marked 206 * as unresolved. If 'resolved' == BOXVMSYM_AUTO, then it is marked as resolved 207 * only if the symbol is defined. 208 */ 209 BOXEXPORT void 210 BoxVMSym_Ref(BoxVM *vm, BoxVMSymID sym_id, BoxVMSymResolver r, 211 void *ref, size_t ref_size, BoxVMSymStatus resolved); 212 213 #if 0 214 /** Set the symbol resolver */ 215 BOXEXPORT BoxTask 216 BoxVMSym_Resolver_Set(BoxVM *vm, BoxVMSymID sym_id, VMSymResolver r); 217 #endif 218 219 /** Set *all_resolved = 1 only if there are no unresolved references */ 220 void BoxVMSym_Ref_Check(BoxVM *vm, int *all_resolved); 221 222 /** Print an error message for every unresolved reference */ 223 BOXEXPORT void 224 BoxVMSym_Ref_Report(BoxVM *vm); 225 226 /** 227 * @brief Resolve the symbol. 228 * 229 * A symbol can be resolved once it has been defined with BoxVMSym_Define(). 230 * The resolution consist in iterating over all the reference to the symbol 231 * and calling the resolutor (a callback). 232 * @param vm The virtual machine the symbol refers to. 233 * @param sym_id The symbol identifier. 234 * @return Whether the operation succeeded. 235 * @note If <pp>sym_id=0</pp>, then try to resolve all the defined symbols 236 * (undefined symbols are ignored). 237 */ 238 BOXEXPORT BoxTask 239 BoxVMSym_Resolve(BoxVM *vm, BoxVMSymID sym_id); 240 241 /** 242 * @brief Print the symbol table for the given symbol. 243 * 244 * The symbol table is a list of all the references made to the symbol. If @p 245 * sym_id is zero the references to all symbols will be printed. 246 * @param vm The virtual machine. 247 * @param out The output stream. 248 * @param sym_id The symbol identifier. 249 */ 250 BOXEXPORT void 251 BoxVMSym_Table_Print(BoxVM *vm, FILE *out, BoxVMSymID sym_id); 252 253 /** 254 * @brief Check that the type of the symbol @p sym_id is @p sym_type. 255 */ 256 BOXEXPORT BoxTask 257 BoxVMSym_Check_Type(BoxVM *vm, BoxVMSymID sym_id, BoxUInt sym_type); 258 259 /** 260 * @brief Open the given dynamic library to resolve symbols. 261 * 262 * If the file is not found then this function appends an appropriate extension 263 * (.so for linux, .dll for windows, etc.) and tries again. 264 */ 265 BOXEXPORT BoxTask 266 BoxVMSym_Resolve_CLib(BoxVM *vm, const char *lib_file); 267 268 /** 269 * @brief Resolution of functions defined in external dynamically loaded 270 * C libraries. 271 */ 272 BOXEXPORT BoxTask 273 BoxVMSym_Resolve_CLibs(BoxVM *vm, BoxList *lib_paths, BoxList *libs); 274 275 /** 276 * This function calls the function given as argument BoxVMSym_Code_Ref() 277 * to assemble a piece of VM-code which makes reference to the symbol 278 * @p sym_id. The reference will be resolved calling again @p code_gen 279 * once the symbol has been defined. 280 * The function @p code_gen assembles parametrically a piece of VM byte-code. 281 */ 282 BOXEXPORT BoxTask 283 BoxVMSym_Code_Ref(BoxVM *vm, BoxVMSymID sym_id, BoxVMSymCodeGen code_gen, 284 void *ref, size_t ref_size); 285 286 # define BoxVMSym_Code_New BoxVMSym_New 287 # define BoxVMSym_Code_Def BoxVMSym_Def 288 289 # define BoxVMSym_Resolve_All(vm) \ 290 BoxVMSym_Resolve((vm), 0) 291 292 #endif /* _BOX_VMSYM_H */ 293