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 vm_priv.h 22 * @brief Box virtual machine private definitions. 23 */ 24 25 #ifndef _BOX_VM_PRIVATE_H 26 # define _BOX_VM_PRIVATE_H 27 28 # include <stdio.h> 29 # include <stdarg.h> 30 # include <stdlib.h> 31 32 # include <box/types.h> 33 # include <box/defaults.h> 34 # include <box/array.h> 35 # include <box/occupation.h> 36 # include <box/hashtable.h> 37 # include <box/vm.h> 38 # include <box/vmsym.h> 39 # include <box/vmdasm.h> 40 # include <box/vmproc_priv.h> 41 42 # include <box/vmexec_priv.h> 43 44 45 /** 46 * Structure used in BoxOpInfo to list the input and output registers 47 * for each VM operation. 48 */ 49 typedef struct { 50 char kind, /**< 'a' for explicit argument, 'r' for implicit local register */ 51 type, /**< 'c':Char, 'i':Int, 'r':Real, 'p':Point, 'o':Obj */ 52 num, /**< Number of argument or register (can be 0, 1, 2) */ 53 io; /**< 'o' for output, 'i' for input, 'b' for input/output */ 54 } BoxOpReg; 55 56 /** 57 * @brief Enumeration of all the possible types of signatures for the Box VM 58 * instructions. 59 * 60 * Different signatures mean different number and/or type of arguments. 61 */ 62 typedef enum { 63 BOXOPSIGNATURE_NONE, 64 BOXOPSIGNATURE_ANY, 65 BOXOPSIGNATURE_IMM, 66 BOXOPSIGNATURE_ANY_ANY, 67 BOXOPSIGNATURE_ANY_IMM 68 } BoxOpSignature; 69 70 /** Possible methods for disassembling a Box VM operation. 71 * Each item in the enumeration corresponds to a different method to be used 72 * for disassembling the operation. 73 */ 74 typedef enum { 75 BOXOPDASM_ANY_ANY, 76 BOXOPDASM_ANY_IMM, 77 BOXOPDASM_JMP, 78 BOXOPDASM_CALL 79 } BoxOpDAsm; 80 81 /** Typedef of struc __BoxOpInfo */ 82 typedef struct BoxOpInfo_struct BoxOpInfo; 83 84 /** 85 * @brief Structure containing detailed information about one VM operation. 86 */ 87 struct BoxOpInfo_struct { 88 BoxOpId opcode; /**< Opcode for the operation */ 89 BoxGOp g_opcode; /**< Generic opcode */ 90 BoxOpInfo *next; /**< Next operation with the same generic opcode */ 91 const char *name; /**< Literal name of the opcode (a string) */ 92 BoxOpSignature 93 signature; /**< Operation kind (depends on the arguments) */ 94 BoxOpDAsm dasm; /**< How to disassemble the operation */ 95 char arg_type, /**< Type of the arguments */ 96 num_args, /**< Number of arguments */ 97 num_inputs, /**< Num. of input registers (explicit+implicit) */ 98 num_outputs, /**< Num. of output registers(explicit+implicit) */ 99 num_regs; /**< Num. of distinct registers involved by the 100 operation (this is not just in + out) */ 101 BoxOpReg *regs; /**< Pointer to the list of input/output regs */ 102 BoxVMOpExecutor 103 executor; /**< Pointer to the function which implements 104 the operation */ 105 }; 106 107 /** 108 * Content of a BoxOpDesc object. 109 */ 110 struct BoxOpDesc_struct { 111 const char *name; /**< Instruction name */ 112 BoxUInt numargs; /**< Number of arguments */ 113 114 int num_args; /**< Number of proper arguments. */ 115 int has_data; /**< Whether this instruction has attached 116 data. */ 117 BoxTypeId t_id; /**< Type of the arguments (all have the 118 same type) */ 119 BoxVMOpExecutor execute; /**< Per eseguire l'istruzione */ 120 }; 121 122 /** Table containing info about all the VM operations */ 123 typedef struct { 124 BoxOpInfo info[BOX_NUM_OPS]; /**< Table of BoxOpInfo strucs. One for each 125 VM operation */ 126 BoxOpReg *regs; /**< Buffer used by the BoxOpTable.info */ 127 } BoxOpTable; 128 129 /** 130 * @brief Identifies the form of a VM instruction argument. 131 * 132 * Possible forms are local register (e.g. ri1), global register (e.g. gri1), 133 * pointer (e.g. i[ro0 + 8]) and immediate (e.g. 1.234). 134 */ 135 typedef enum { 136 BOXOPARGFORM_GREG = 0, /**< Global register. */ 137 BOXOPARGFORM_LREG, /**< Local register. */ 138 BOXOPARGFORM_PTR, /**< Pointer. */ 139 BOXOPARGFORM_IMM /**< Immediate. */ 140 } BoxOpArgForm; 141 142 /** Item used in a backtrace to identify where the exception caused the 143 * particular function to exit. 144 */ 145 typedef struct { 146 BoxVMCallNum call_num; /**< Call number of the function */ 147 size_t vm_pos; /**< Position in the VM code */ 148 } BoxVMTrace; 149 150 151 typedef struct { 152 void *ptr; /**< Pointer to the region allocated for the registers */ 153 BoxInt min, /**< Min register number */ 154 max; /**< Max register number */ 155 } BoxVMRegs; 156 157 /** 158 * @brief Datastructure used to parse one single instruction argument. 159 */ 160 typedef struct { 161 union { 162 BoxChar val_char; /**< Value for Char registers. */ 163 BoxInt val_int; /**< Value for Int registers. */ 164 BoxReal val_real; /**< Value for Real registers. */ 165 BoxPtr val_ptr; /**< Value for Ptr registers. */ 166 } data; /**< Data associated to the argument. */ 167 } BoxOpArg; 168 169 /** 170 * This structure contains all the data which define the status for the VM. 171 * Status is allocated by VM_Module_Execute() inside its stack. 172 */ 173 struct BoxVMX_struct { 174 BoxVM *vm; /**< VM to execute. */ 175 176 BoxVMProcInstalled *p; /**< Procedure which is currently been executed */ 177 178 struct { 179 unsigned int 180 error :1, /**< Error detected */ 181 exit :1; /**< Exit current execution frame */ 182 } flags; /**< Execution flags */ 183 184 BoxInt op_size; 185 186 BoxVMRegs local[NUM_TYPES], /**< Local register allocation status */ 187 *global; /**< Global register allocation status */ 188 189 BoxInt alc[NUM_TYPES]; /**< Allocation status of local registers 190 (whether a 'new num_regs, num_vars' 191 instruction has been used) */ 192 }; 193 194 /** 195 * @brief The full status of the virtual machine of Box. 196 */ 197 struct BoxVM_struct { 198 BoxArr types; /**< Type bound to this VM. */ 199 BoxHT types_dict; /**< Dictionaries to find type IDs the corresponding 200 types.*/ 201 struct { 202 unsigned int 203 forcelong :1, /**< Force long form assembly. */ 204 hexcode :1, /**< Show Hex values in disassembled code */ 205 identdata :1; /**< Add also identity info for data inserted 206 into the data segment */ 207 } attr; /** Flags controlling the behaviour of the VM */ 208 209 struct { 210 unsigned int 211 globals :1, /**< Global regs have been allocated */ 212 op_table :1; /**< The operation table has been built */ 213 214 } has; /**< State of the VM */ 215 216 BoxArr stack, /**< The stack for the VM object */ 217 data_segment; /**< The segment of data (strings, etc.) which is 218 accessible through the register gro0 */ 219 220 BoxVMRegs global[NUM_TYPES]; /**< The values of the global registers */ 221 222 BoxPtr *box_vm_current, 223 *box_vm_arg1; 224 225 const BoxOpDesc 226 *exec_table; /**< Table collecting info about the instructions 227 which are useful for execution. */ 228 229 BoxVMProcTable 230 proc_table; /**< Table of installed and uninstalled procs */ 231 232 BoxVMSymTable 233 sym_table; /**< Table of referenced and defined symbols */ 234 235 BoxOpTable 236 op_table; /**< Table describing the instructions and their 237 properties */ 238 239 BoxArr backtrace; /**< Information about error location */ 240 char *fail_msg; /**< Failure message */ 241 242 BoxHT id_from_desc; /**< Hashtable containing object descriptors */ 243 BoxArr desc_from_id; /**< Table of descriptors from allocation IDs */ 244 }; 245 246 extern const size_t size_of_type[NUM_TYPES]; 247 248 /** Maximum num of arguments (implicit + explicit) that an operation 249 * can have 250 */ 251 #define BOXOP_MAX_NUM_ARGS 4 252 253 /** Build a table containing info on the Box VM operations for each of them. 254 * The table is addressable using a BoxGOp as index. 255 * This is quite an internal function. 256 */ 257 void BoxOpTable_Build(BoxOpTable *ot); 258 259 /** Destroy a BoxOpTable object created with BoxOpTable_Build */ 260 void BoxOpTable_Destroy(BoxOpTable *ot); 261 262 /** Print the given BoxOpTable to the given stream. */ 263 void BoxOpTable_Print(FILE *out, BoxOpTable *ot); 264 265 /** Get information about the specified generic VM operation. */ 266 BoxOpInfo *BoxVM_Get_Op_Info(BoxVM *vm, BoxGOp g_op); 267 268 /** Print all the signatures for a the given BoxOpInfo object. */ 269 void BoxOpInfo_Print(FILE *out, BoxOpInfo *oi); 270 271 /** (Internal) Get the execution table for the Box VM instructions. */ 272 const BoxOpDesc *BoxVM_Get_Exec_Table(void); 273 274 /** This is the type of the C functions which can be called by the VM. */ 275 typedef BoxTask (*BoxVMFunc)(BoxVMX *); 276 277 /** 278 * Initialise a BoxVM object for which space has been already allocated 279 * somehow. You'll need to use BoxVM_Finish to destroy the object. 280 * @see BoxVM_Finish, BoxVM_Create 281 */ 282 BOXEXPORT BoxTask 283 BoxVM_Init(BoxVM *vm); 284 285 /** 286 * @brief Destroy a BoxVM object initialised with BoxVM_Init(). 287 * @see BoxVM_Init 288 */ 289 BOXEXPORT void 290 BoxVM_Finish(BoxVM *vm); 291 292 BOXEXPORT BoxTask 293 BoxVM_Module_Execute(BoxVM *vm, BoxVMCallNum call_num); 294 295 /** 296 * Similar to BoxVM_Module_Execute(), but takes also pointers to child 297 * and parent. The register gro1 and gro2 are modified after this call: in 298 * particular, '*parent' is stored in gro1 and '*child' in gro2. 299 * This guarantee that the reference counting protocol is respected. 300 */ 301 BOXEXPORT BoxTask 302 BoxVM_Module_Execute_With_Args(BoxVM *vm, BoxVMCallNum cn, 303 BoxPtr *parent, BoxPtr *child); 304 305 /** 306 * Clear the backtrace of the program. 307 */ 308 void BoxVM_Backtrace_Clear(BoxVM *vm); 309 310 /** 311 * Print on 'stream' a human redable representation of the backtrace 312 * of the program. 313 */ 314 void BoxVM_Backtrace_Print(BoxVM *vm, FILE *stream); 315 316 /** Get the parent of the current combination (this is something with type 317 * ``BoxPtr *``. 318 */ 319 # define BoxVMX_Get_Parent(vmx) ((vmx)->vm->box_vm_current) 320 321 /** Get the child of the current combination (this is something with type 322 * ``BoxPtr *`` 323 */ 324 # define BoxVMX_Get_Child(vmx) ((vmx)->vm->box_vm_arg1) 325 326 /** Shorthand for BoxPtr_Get_Target(BoxVM_Get_Parent(vm)). */ 327 # define BoxVMX_Get_Parent_Target(vmx) \ 328 (BoxPtr_Get_Target(BoxVMX_Get_Parent(vmx))) 329 330 /** Shorthand for BoxPtr_Get_Target(BoxVM_Get_Child(vm)). */ 331 # define BoxVMX_Get_Child_Target(vmx) \ 332 (BoxPtr_Get_Target(BoxVMX_Get_Child(vmx))) 333 334 335 /* XXX TODO: the ones below are obsolete macros, which should be removed. */ 336 # define BOX_VM_THIS_PTR(vmx, Type) ((Type *) (vmx)->vm->box_vm_current->ptr) 337 # define BOX_VM_THIS(vmx, Type) (*BOX_VM_THIS_PTR(vmx, Type)) 338 # define BOX_VM_ARG1_PTR(vmx, Type) ((Type *) (vmx)->vm->box_vm_arg1->ptr) 339 # define BOX_VM_ARG1(vmx, Type) (*BOX_VM_ARG1_PTR(vmx, Type)) 340 # define BOX_VM_ARG_PTR BOX_VM_ARG1_PTR 341 # define BOX_VM_ARG BOX_VM_ARG1 342 # define BOX_VM_SUB_PARENT_PTR(vmp, parent_t) \ 343 SUBTYPE_PARENT_PTR(BOX_VM_THIS_PTR(vmp, BoxSubtype), parent_t) 344 # define BOX_VM_SUB_PARENT(vmp, parent_t) \ 345 (*BOX_VM_SUB_PARENT_PTR(vmp, parent_t)) 346 # define BOX_VM_SUB_CHILD_PTR(vmp, child_t) \ 347 SUBTYPE_CHILD_PTR(BOX_VM_THIS_PTR(vmp, BoxSubtype), child_t) 348 # define BOX_VM_SUB_CHILD(vmp, child_t) \ 349 (*BOX_VM_SUB_CHILD_PTR(vmp, child_t)) 350 # define BOX_VM_SUB2_PARENT(vmp, parent_t) \ 351 (*SUBTYPE_PARENT_PTR(BOX_VM_SUB_PARENT_PTR(vmp, BoxSubtype), parent_t)) 352 353 #endif /* _BOX_VM_PRIVATE_H */ 354