1 /****************************************************************************
2 * Copyright (C) 2008 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 #include <assert.h>
21 #include <string.h>
22 #include <stdlib.h>
23
24 #include "config.h"
25
26 #include <ltdl.h>
27 #define DYLIB
28
29 #include "defaults.h"
30 #include "types.h"
31 #include "strutils.h"
32 #include "messages.h"
33 #include "mem.h"
34 #include "vm_priv.h"
35 #include "vmsym.h"
36 #include "vmsymstuff.h"
37 #include "vmproc.h"
38 #include "list.h"
39
40 #ifdef DYLIB
My_Close_DyLib(void * item)41 static void My_Close_DyLib(void *item) {
42 void *dylib = *((void **) item);
43 if (lt_dlclose(dylib)) {
44 MSG_WARNING("BoxVMSym_Destroy: My_Close_DyLib: lt_dlclose failure");
45 }
46 }
47 #endif
48
BoxVMSymTable_Init(BoxVMSymTable * st)49 void BoxVMSymTable_Init(BoxVMSymTable *st) {
50 BoxHT_Init_Default(& st->syms, VMSYM_SYM_HT_SIZE);
51 BoxArr_Init(& st->data, sizeof(BoxChar), VMSYM_DATA_ARR_SIZE);
52 BoxArr_Init(& st->defs, sizeof(BoxVMSym), VMSYM_DEF_ARR_SIZE);
53 BoxArr_Init(& st->refs, sizeof(BoxVMSymRef), VMSYM_REF_ARR_SIZE);
54 #ifdef DYLIB
55 BoxArr_Init(& st->dylibs, sizeof(void *), VMSYM_DYLIB_ARR_SIZE);
56 BoxArr_Set_Finalizer(& st->dylibs, My_Close_DyLib);
57 #endif
58
59 if (lt_dlinit() != 0) {
60 MSG_WARNING("BoxVMSym_Init: lt_dlinit failed!");
61 }
62 }
63
BoxVMSymTable_Finish(BoxVMSymTable * st)64 void BoxVMSymTable_Finish(BoxVMSymTable *st) {
65 BoxHT_Finish(& st->syms);
66 BoxArr_Finish(& st->data);
67 BoxArr_Finish(& st->defs);
68 BoxArr_Finish(& st->refs);
69 #ifdef DYLIB
70 BoxArr_Finish(& st->dylibs);
71 #endif
72 if (lt_dlexit() != 0) {
73 MSG_WARNING("BoxVMSym_Destroy: lt_dlexit failed!");
74 }
75 }
76
BoxVMSym_New(BoxVM * vm,BoxUInt sym_type,BoxUInt def_size)77 BoxVMSymID BoxVMSym_New(BoxVM *vm, BoxUInt sym_type, BoxUInt def_size) {
78 return BoxVMSym_Create(vm, sym_type, NULL, def_size);
79 }
80
81 /* Create a new symbol. */
82 BoxVMSymID
BoxVMSym_Create(BoxVM * vm,BoxUInt sym_type,const void * def,size_t def_size)83 BoxVMSym_Create(BoxVM *vm, BoxUInt sym_type,
84 const void *def, size_t def_size) {
85 BoxVMSymTable *st = & vm->sym_table;
86 BoxVMSymID sym_id;
87 BoxVMSym *ss = BoxArr_Push(& st->defs, & ss);
88
89 assert(ss);
90 ss->name.length = 0;
91 ss->name.text = NULL;
92 ss->sym_type = sym_type;
93 ss->defined = 0;
94 ss->def_size = def_size;
95 ss->def_addr = 1 + BoxArr_Num_Items(& st->data);
96 ss->first_ref = 0;
97
98 sym_id = BoxArr_Num_Items(& st->defs);
99 BoxArr_MPush(& st->data, def, def_size);
100 return sym_id;
101 }
102
103 /** Associate a name to the symbol sym_id. */
BoxVMSym_Set_Name(BoxVM * vm,BoxVMSymID sym_id,const char * name)104 void BoxVMSym_Set_Name(BoxVM *vm, BoxVMSymID sym_id, const char *name) {
105 BoxVMSymTable *st = & vm->sym_table;
106 BoxHTItem *hi;
107 BoxVMSym *s;
108 /*char *n_str;*/
109 size_t name_len;
110
111 s = (BoxVMSym *) BoxArr_Item_Ptr(& st->defs, sym_id);
112 if (s->name.length != 0) {
113 MSG_FATAL("This symbol has already been given a name!");
114 assert(0);
115 }
116
117 name_len = strlen(name) + 1; /* include also the terminating '\0' char */
118 if (BoxHT_Find(& st->syms, name, name_len, & hi)) {
119 MSG_FATAL("Another symbol exists having the name '%s'!", name);
120 assert(0);
121 }
122
123 (void) BoxHT_Insert_Obj(& st->syms, name, name_len,
124 & sym_id, sizeof(BoxUInt));
125 if (!BoxHT_Find(& st->syms, name, name_len, & hi) ) {
126 MSG_FATAL("Hashtable seems not to work (from BoxVMSym_Add)");
127 assert(0);
128 }
129
130 s->name.text = (char *) hi->key;
131 s->name.length = hi->key_size - 1; /* Without the final '\0' */
132 }
133
BoxVMSym_Get_Name(BoxVM * vm,BoxVMSymID sym_id)134 const char *BoxVMSym_Get_Name(BoxVM *vm, BoxVMSymID sym_id) {
135 BoxVMSymTable *st = & vm->sym_table;
136 BoxVMSym *s = (BoxVMSym *) BoxArr_Item_Ptr(& st->defs, sym_id);
137 return s->name.text;
138 }
139
140 /* Get the definition data for a symbol. */
BoxVMSym_Get_Definition(BoxVM * vm,BoxVMSymID sym_id)141 void *BoxVMSym_Get_Definition(BoxVM *vm, BoxVMSymID sym_id) {
142 BoxVMSymTable *st = & vm->sym_table;
143 BoxVMSym *s = (BoxVMSym *) BoxArr_Item_Ptr(& st->defs, sym_id);
144 void *def_data_ptr = BoxArr_Item_Ptr(& st->data, s->def_addr);
145 return def_data_ptr;
146 }
147
148 /* Define a symbol which was previously created with BoxVMSym_Create(). */
149 BoxTask
BoxVMSym_Define(BoxVM * vm,BoxVMSymID sym_id,void * def)150 BoxVMSym_Define(BoxVM *vm, BoxVMSymID sym_id, void *def) {
151 BoxVMSymTable *st = & vm->sym_table;
152 BoxVMSym *s = BoxArr_Get_Item_Ptr(& st->defs, sym_id);
153
154 if (s->defined) {
155 const char *sym_name = BoxVMSym_Get_Name(vm, sym_id);
156 MSG_ERROR("Double definition of the symbol '%s'.", sym_name);
157 return BOXTASK_FAILURE;
158 }
159
160 if (def) {
161 void *def_data_ptr = BoxArr_Item_Ptr(& st->data, s->def_addr);
162 (void) memcpy(def_data_ptr, def, s->def_size);
163 }
164
165 s->defined = 1;
166 return BOXTASK_OK;
167 }
168
BoxVMSym_Is_Defined(BoxVM * vm,BoxVMSymID sym_id)169 int BoxVMSym_Is_Defined(BoxVM *vm, BoxVMSymID sym_id) {
170 BoxVMSymTable *st = & vm->sym_table;
171 BoxVMSym *s = (BoxVMSym *) BoxArr_Item_Ptr(& st->defs, sym_id);
172 return s->defined;
173 }
174
BoxVMSym_Ref(BoxVM * vm,BoxVMSymID sym_id,BoxVMSymResolver r,void * ref,size_t ref_size,BoxVMSymStatus resolved)175 void BoxVMSym_Ref(BoxVM *vm, BoxVMSymID sym_id, BoxVMSymResolver r,
176 void *ref, size_t ref_size, BoxVMSymStatus resolved) {
177 BoxVMSymTable *st = & vm->sym_table;
178 BoxVMSym *s;
179 BoxVMSymRef sr;
180 void *ref_data_ptr;
181
182 assert(ref_size > 0 || ref == NULL);
183 s = (BoxVMSym *) BoxArr_Item_Ptr(& st->defs, sym_id);
184 sr.sym_id = sym_id;
185 sr.next = s->first_ref;
186 sr.ref_size = ref_size;
187 sr.ref_addr = 1 + BoxArr_Num_Items(& st->data);
188 switch(resolved) {
189 case BOXVMSYM_RESOLVED: sr.resolved = 1; break;
190 case BOXVMSYM_UNRESOLVED: sr.resolved = 0; break;
191 default: sr.resolved = s->defined; break;
192 }
193 sr.resolver = r;
194
195 /* Copy the data for the reference */
196 if (ref_size > 0) {
197 BoxArr_MPush(& st->data, NULL, ref_size);
198 ref_data_ptr = BoxArr_Item_Ptr(& st->data, sr.ref_addr);
199 (void) memcpy(ref_data_ptr, ref, ref_size);
200 }
201
202 /* Add the reference */
203 BoxArr_Push(& st->refs, & sr);
204 /* Link the reference to the list of references for the symbol */
205 s->first_ref = BoxArr_Num_Items(& st->refs);
206 }
207
208 static int
My_Check_Ref(BoxUInt item_num,void * item,void * all_resolved)209 My_Check_Ref(BoxUInt item_num, void *item, void *all_resolved) {
210 BoxVMSymRef *sr = (BoxVMSymRef *) item;
211 *((int *) all_resolved) &= sr->resolved;
212 return 1;
213 }
214
BoxVMSym_Ref_Check(BoxVM * vm,int * all_resolved)215 void BoxVMSym_Ref_Check(BoxVM *vm, int *all_resolved) {
216 BoxVMSymTable *st = & vm->sym_table;
217 *all_resolved = 1;
218 (void) BoxArr_Iter(& st->refs, My_Check_Ref, all_resolved);
219 }
220
221 static int
My_Report_Ref(BoxUInt item_num,void * item,void * pass_data)222 My_Report_Ref(BoxUInt item_num, void *item, void *pass_data) {
223 BoxVM *vm = (BoxVM *) pass_data;
224 BoxVMSymRef *sr = (BoxVMSymRef *) item;
225 if (!sr->resolved) {
226 MSG_ERROR("Unresolved reference to the symbol (ID=%d, name='%s')",
227 sr->sym_id, BoxVMSym_Get_Name(vm, sr->sym_id));
228 }
229 return 1;
230 }
231
BoxVMSym_Ref_Report(BoxVM * vm)232 void BoxVMSym_Ref_Report(BoxVM *vm) {
233 BoxVMSymTable *st = & vm->sym_table;
234 (void) BoxArr_Iter(& st->refs, My_Report_Ref, vm);
235 }
236
237 #if 0
238 BoxTask BoxVMSym_Resolver_Set(BoxVM *vm, BoxVMSymID sym_id, BoxVMSymResolver r) {
239 BoxVMSymTable *st = & vm->sym_table;
240 BoxVMSym *s;
241
242 s = (BoxVMSym *) BoxArr_ItemPtr(& st->defs, sym_id);
243 s->resolver = r;
244 return BOXTASK_OK;
245 }
246 #endif
247
BoxVMSym_Resolve(BoxVM * vm,BoxVMSymID sym_id)248 BoxTask BoxVMSym_Resolve(BoxVM *vm, BoxVMSymID sym_id) {
249 BoxVMSymTable *st = & vm->sym_table;
250 BoxVMSym *s;
251 BoxUInt next;
252 BoxUInt sym_type, def_size, ref_size;
253 void *def, *ref;
254
255 if (sym_id < 1) {
256 BoxUInt i, num_defs = BoxArr_Num_Items(& st->defs);
257 for(i=1; i<=num_defs; i++) {
258 BOXTASK( BoxVMSym_Resolve(vm, i) );
259 }
260 return BOXTASK_OK;
261 }
262
263 s = (BoxVMSym *) BoxArr_Item_Ptr(& st->defs, sym_id);
264 if (! s->defined) return BOXTASK_OK;
265 next = s->first_ref;
266 def = BoxArr_Item_Ptr(& st->data, s->def_addr);
267 def_size = s->def_size;
268 sym_type = s->sym_type;
269 while (next > 0) {
270 BoxVMSymRef *sr = (BoxVMSymRef *) BoxArr_Item_Ptr(& st->refs, next);
271 if (sr->sym_id != sym_id) {
272 MSG_FATAL("BoxVMSym_Resolve: bad reference in the chain!");
273 return BOXTASK_FAILURE;
274 }
275
276 if (!sr->resolved) {
277 if (sr->resolver == NULL) {
278 MSG_ERROR("BoxVMSym_Resolve: cannot resolve the symbol: "
279 "the resolver is not present!");
280 return BOXTASK_FAILURE;
281 }
282
283 ref_size = sr->ref_size;
284 ref = (ref_size > 0) ? BoxArr_Item_Ptr(& st->data, sr->ref_addr) : 0;
285
286 BOXTASK( sr->resolver(vm, sym_id, sym_type, 1, def, def_size,
287 ref, ref_size) );
288 sr->resolved = 1;
289 }
290
291 next = sr->next;
292 }
293 return BOXTASK_OK;
294 }
295
BoxVMSym_Table_Print(BoxVM * vm,FILE * out,BoxVMSymID sym_id)296 void BoxVMSym_Table_Print(BoxVM *vm, FILE *out, BoxVMSymID sym_id) {
297 BoxVMSymTable *st = & vm->sym_table;
298 BoxVMSym *s;
299 BoxUInt next, ref_num;
300 char *sym_name;
301
302 if (sym_id < 1) {
303 BoxUInt i, num_defs = BoxArr_Num_Items(& st->defs);
304 fprintf(out, "The table contains "SUInt" symbols\n", num_defs);
305 for(i=1; i<=num_defs; i++) {
306 BoxVMSym_Table_Print(vm, out, i);
307 }
308 return;
309 }
310
311 s = (BoxVMSym *) BoxArr_Item_Ptr(& st->defs, sym_id);
312 next = s->first_ref;
313 sym_name = (s->name.length > 0) ? s->name.text : "";
314 ref_num = 1;
315
316 fprintf(out,
317 "Symbol ID = "SUInt"; name = '%s'; type = "SUInt"; "
318 "defined = %d, def_addr = "SUInt", def_size = "SUInt"\n",
319 sym_id, sym_name, s->sym_type,
320 s->defined, s->def_addr, s->def_size);
321
322 while(next > 0) {
323 BoxVMSymRef *sr = (BoxVMSymRef *) BoxArr_Item_Ptr(& st->refs, next);
324 if (sr->sym_id != sym_id) {
325 fprintf(out, "Bad reference in the chain!");
326 return;
327 }
328
329 fprintf(out,
330 " Reference number = "SUInt"; ref_addr = "SUInt"; "
331 "ref_size = "SUInt"; resolved = %d, resolver = %p\n",
332 ref_num, sr->ref_addr,
333 sr->ref_size, sr->resolved, sr->resolver);
334
335 next = sr->next;
336 ++ref_num;
337 }
338 }
339
BoxVMSym_Check_Type(BoxVM * vm,BoxVMSymID sym_id,BoxUInt sym_type)340 BoxTask BoxVMSym_Check_Type(BoxVM *vm, BoxVMSymID sym_id, BoxUInt sym_type) {
341 BoxVMSymTable *st = & vm->sym_table;
342 BoxVMSym *s;
343 s = (BoxVMSym *) BoxArr_Item_Ptr(& st->defs, sym_id);
344 return (s->sym_type == sym_type) ? BOXTASK_OK : BOXTASK_FAILURE;
345 }
346
347 typedef struct {
348 BoxVM *vm;
349 void *dylib;
350 const char *lib_file;
351 } MyCLibRefData;
352
353 #ifdef DYLIB
354 static int
My_Resolve_Ref_With_CLib(BoxVMSymID sym_id,void * item,void * pass_data)355 My_Resolve_Ref_With_CLib(BoxVMSymID sym_id, void *item, void *pass_data) {
356 BoxVMSym *s = (BoxVMSym *) item;
357 if (!s->defined) {
358 MyCLibRefData *clrd = pass_data;
359 BoxVM *vm = clrd->vm;
360 if (s->sym_type == BOXVMSYMTYPE_PROC) {
361 const char *proc_name;
362 if (BoxVMSym_Proc_Is_Implemented(vm, sym_id, & proc_name)) {
363 (void) BoxVMSym_Define_Proc(vm, sym_id, NULL);
364
365 } else {
366 const char *err_msg;
367 void *sym;
368
369 err_msg = lt_dlerror();
370 sym = lt_dlsym(clrd->dylib, proc_name);
371 err_msg = lt_dlerror();
372
373 if (err_msg)
374 return 1;
375
376 if (!sym) {
377 MSG_ERROR("Symbol '%s' from library '%s' is NULL",
378 proc_name, clrd->lib_file);
379 return 1;
380 }
381
382 (void) BoxVMSym_Define_Proc(vm, sym_id, (BoxCCallOld) sym);
383 }
384 }
385 }
386 return 1;
387 }
388 #endif
389
BoxVMSym_Resolve_CLib(BoxVM * vm,const char * lib_file)390 BoxTask BoxVMSym_Resolve_CLib(BoxVM *vm, const char *lib_file) {
391 #ifdef DYLIB
392 BoxVMSymTable *st = & vm->sym_table;
393 MyCLibRefData clrd;
394 clrd.vm = vm;
395 clrd.lib_file = lib_file;
396 clrd.dylib = lt_dlopenext(lib_file);
397 if (clrd.dylib == NULL)
398 return BOXTASK_FAILURE;
399 BoxArr_Push(& st->dylibs, & clrd.dylib);
400 (void) BoxArr_Iter(& st->defs, My_Resolve_Ref_With_CLib, & clrd);
401 return BOXTASK_OK;
402 #else
403 MSG_WARNING("Cannot load '%s': the virtual machine was compiled "
404 "without support for dynamic loading of libraries.", lib_file);
405 return BOXTASK_FAILURE;
406 #endif
407 }
408
409 struct clibs_data {
410 BoxVM *vm;
411 BoxList *lib_paths;
412 char *path;
413 char *lib;
414 };
415
416 static BoxTask
My_Iter_Over_Paths(void * string,void * pass_data)417 My_Iter_Over_Paths(void *string, void *pass_data) {
418 struct clibs_data *cld = (struct clibs_data *) pass_data;
419 char *lib_file;
420 BoxTask status;
421 cld->path = (char *) string;
422 lib_file = Box_Mem_Strdup(Box_Print("%s/lib%s", cld->path, cld->lib));
423 status = BoxVMSym_Resolve_CLib(cld->vm, lib_file);
424 Box_Mem_Free(lib_file);
425 if (status == BOXTASK_OK) return BOXTASK_FAILURE; /* Stop here, if we have found it! */
426 return BOXTASK_OK;
427 }
428
429 static BoxTask
My_Iter_Over_Libs(void * string,void * pass_data)430 My_Iter_Over_Libs(void *string, void *pass_data) {
431 struct clibs_data *cld = (struct clibs_data *) pass_data;
432 cld->lib = (char *) string;
433 /* IS_SUCCESS is misleading: here we use BOXTASK_OK, just to continue
434 * the iteration. Therefore if we get BOXTASK_OK, it means that the library
435 * has not been found
436 */
437 if (BoxList_Iter(cld->lib_paths, My_Iter_Over_Paths, cld) == BOXTASK_OK) {
438 MSG_WARNING("'%s' <-- library has not been found or cannot be loaded!",
439 cld->lib);
440 }
441 return BOXTASK_OK;
442 }
443
444
445
446
447
448
449
450
451
452
453
454
455 static int
My_Resolve_Own_Symbol(BoxVMSymID sym_id,void * item,void * pass)456 My_Resolve_Own_Symbol(BoxVMSymID sym_id, void *item, void *pass) {
457 BoxVM *vm = pass;
458 BoxVMSym *s = (BoxVMSym *) item;
459 if (!s->defined) {
460 if (s->sym_type == BOXVMSYMTYPE_PROC) {
461 const char *proc_name;
462 if (BoxVMSym_Proc_Is_Implemented(vm, sym_id, & proc_name))
463 (void) BoxVMSym_Define_Proc(vm, sym_id, NULL);
464
465 else {
466 }
467 }
468 }
469 return 1;
470 }
471
My_Resolve_Own_Symbols(BoxVM * vm)472 BoxTask My_Resolve_Own_Symbols(BoxVM *vm) {
473 BoxVMSymTable *st = & vm->sym_table;
474 (void) BoxArr_Iter(& st->defs, My_Resolve_Own_Symbol, vm);
475 return BOXTASK_OK;
476 }
477
478
479
480
481
482
483
484
BoxVMSym_Resolve_CLibs(BoxVM * vm,BoxList * lib_paths,BoxList * libs)485 BoxTask BoxVMSym_Resolve_CLibs(BoxVM *vm, BoxList *lib_paths, BoxList *libs) {
486 struct clibs_data cld;
487 (void) My_Resolve_Own_Symbols(vm);
488 cld.vm = vm;
489 cld.lib_paths = lib_paths;
490 return BoxList_Iter(libs, My_Iter_Over_Libs, & cld);
491 }
492
493 /****************************************************************************/
494
495 static BoxTask
My_Code_Generator(BoxVM * vm,BoxVMSymID sym_id,BoxUInt sym_type,int defined,void * def,BoxUInt def_size,void * ref,BoxUInt ref_size)496 My_Code_Generator(BoxVM *vm, BoxVMSymID sym_id, BoxUInt sym_type,
497 int defined, void *def, BoxUInt def_size,
498 void *ref, BoxUInt ref_size) {
499 BoxVMSymCodeRef *ref_head = (BoxVMSymCodeRef *) ref;
500 void *ref_tail = ref + sizeof(BoxVMSymCodeRef);
501 BoxUInt ref_tail_size = ref_size - sizeof(BoxVMSymCodeRef);
502 BoxVMProcTable *pt = & vm->proc_table;
503 BoxVMProc *tmp_proc;
504 BoxUInt saved_proc_num;
505
506 saved_proc_num = BoxVM_Proc_Target_Get(vm);
507 BoxVM_Proc_Empty(vm, pt->tmp_proc);
508 BoxVM_Proc_Target_Set(vm, pt->tmp_proc);
509 tmp_proc = pt->target_proc;
510 /* Call the procedure here! */
511 BOXTASK( ref_head->code_gen(vm, sym_id, sym_type, defined,
512 def, def_size, ref_tail, ref_tail_size) );
513 BoxVM_Proc_Target_Set(vm, ref_head->proc_num);
514 /* Replace the referencing code with the generated code */
515 {
516 void *src = BoxArr_First_Item_Ptr(& tmp_proc->code);
517 int src_size = BoxArr_Num_Items(& tmp_proc->code);
518 BoxArr *dest = & pt->target_proc->code; /* Destination sheet */
519 int dest_pos = ref_head->pos + 1; /* NEED TO ADD 1 */
520 if (src_size != ref_head->size) {
521 MSG_ERROR("My_Code_Generator: The code for the resolved reference does "
522 "not match the space which was reserved for it!");
523 return BOXTASK_FAILURE;
524 }
525 BoxArr_Overwrite(dest, dest_pos, src, src_size);
526 }
527 BoxVM_Proc_Target_Set(vm, saved_proc_num);
528 return BOXTASK_OK;
529 }
530
531 BoxTask
BoxVMSym_Code_Ref(BoxVM * vm,BoxVMSymID sym_id,BoxVMSymCodeGen code_gen,void * ref,size_t ref_size)532 BoxVMSym_Code_Ref(BoxVM *vm, BoxVMSymID sym_id, BoxVMSymCodeGen code_gen,
533 void *ref, size_t ref_size) {
534 BoxVMSymTable *st = & vm->sym_table;
535 BoxVMSym *s;
536 void *def;
537 BoxVMProcTable *pt = & vm->proc_table;
538
539 BoxUInt ref_all_size;
540 BoxVMSymCodeRef *ref_head;
541 void *ref_all, *ref_tail;
542
543 s = (BoxVMSym *) BoxArr_Item_Ptr(& st->defs, sym_id);
544 def = BoxArr_Item_Ptr(& st->data, s->def_addr);
545
546 ref_all_size = sizeof(BoxVMSymCodeRef) + ref_size;
547 ref_all = Box_Mem_Safe_Alloc(ref_all_size);
548 ref_head = (BoxVMSymCodeRef *) ref_all;
549 ref_tail = ref_all + sizeof(BoxVMSymCodeRef);
550
551 /* fill the section describing the code */
552 ref_head->code_gen = code_gen;
553 ref_head->proc_num = pt->target_proc_num;
554 ref_head->pos = BoxArr_Num_Items(& pt->target_proc->code);
555
556 /* Copy the user provided reference data */
557 if (ref != NULL && ref_size > 0)
558 (void) memcpy(ref_tail, ref, ref_size);
559
560 BOXTASK( code_gen(vm, sym_id, s->sym_type, s->defined, def, s->def_size,
561 ref, ref_size) );
562 if (pt->target_proc_num != ref_head->proc_num) {
563 MSG_ERROR("BoxVMSym_Code_Ref: the function 'code_gen' must not change "
564 "the current target for compilation!");
565 }
566 ref_head->size = BoxArr_Num_Items(& pt->target_proc->code) - ref_head->pos;
567 BoxVMSym_Ref(vm, sym_id, My_Code_Generator, ref_all, ref_all_size, -1);
568 Box_Mem_Free(ref_all);
569 return BOXTASK_OK;
570 }
571
572 #if 0
573 /* Usage for the function 'BoxVMSym_Code_Ref' */
574
575 # define CALL_TYPE 1
576
577 /* This is the function which assembles the code for the function call */
578 BoxTask Assemble_Call(BoxVM *vm, BoxVMSymID sym_id, BoxUInt sym_type,
579 int defined, void *def, BoxUInt def_size,
580 void *ref, BoxUInt ref_size) {
581 BoxUInt call_num = 0;
582 assert(sym_type == CALL_TYPE);
583 if (defined && def != NULL) {
584 assert(def_size=sizeof(BoxUInt));
585 call_num = *((BoxUInt *) def);
586 }
587 BoxVM_Assemble(vm, ASM_CALL_I, CAT_IMM, call_num);
588 return BOXTASK_OK;
589 }
590
591 int main(void) {
592 BoxVMSymID sym_id;
593 BoxVM *vm;
594 /* Initialization of the VM goes here
595 ...
596 ...
597 */
598
599 /* Here we define that a new symbol with type CALL_TYPE=1 exists */
600 (void) BoxVMSym_New(vm, & sym_id, CALL_TYPE, sizeof(BoxUInt));
601 /* Here we make a reference to it: at this point the assembled code for
602 * "call 0" will be added to the current target procedure.
603 * 0 is wrong, but we don't know what is the right number, because
604 * the symbol is still not defined.
605 */
606 (void) BoxVMSym_Code_Ref(vm, sym_id, Assemble_Call);
607 /* Here we define the symbol "my_proc" to be (BoxUInt) 123.
608 * Now we know that all the "call" instructions referencing
609 * the symbol "my_proc" should be assembled with "call 123"
610 */
611 (void) BoxVMSym_Def(vm, sym_id, & ((BoxUInt) 123));
612 /* We can now resolve all the past references which were made when
613 * we were not aware of the real value of "my_proc".
614 * The code "call 0" will be replaced with "call 123"
615 */
616 (void) BoxVMSym_Resolve_All(vm);
617 return 0;
618 }
619 #endif
620