1 /*
2 value.c
3
4 value handling
5
6 Copyright (C) 2002 Bill Currie <bill@taniwha.org>
7
8 Author: Bill Currie <bill@taniwha.org>
9 Date: 2002/06/04
10
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License
13 as published by the Free Software Foundation; either version 2
14 of the License, or (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
20 See the GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to:
24
25 Free Software Foundation, Inc.
26 59 Temple Place - Suite 330
27 Boston, MA 02111-1307, USA
28
29 */
30 #ifdef HAVE_CONFIG_H
31 # include "config.h"
32 #endif
33
34 #ifdef HAVE_STRING_H
35 # include <string.h>
36 #endif
37 #ifdef HAVE_STRINGS_H
38 # include <strings.h>
39 #endif
40 #include <stdlib.h>
41
42 #include "QF/alloc.h"
43 #include "QF/dstring.h"
44 #include "QF/hash.h"
45 #include "QF/mathlib.h"
46 #include "QF/va.h"
47
48 #include "qfcc.h"
49 #include "def.h"
50 #include "defspace.h"
51 #include "diagnostic.h"
52 #include "emit.h"
53 #include "expr.h"
54 #include "reloc.h"
55 #include "strpool.h"
56 #include "symtab.h"
57 #include "type.h"
58 #include "value.h"
59
60 typedef struct {
61 def_t *def;
62 union {
63 string_t string_val;
64 float float_val;
65 float vector_val[3];
66 int entity_val;
67 int field_val;
68 int func_val;
69 ex_pointer_t pointer;
70 float quaternion_val[4];
71 int integer_val;
72 } i;
73 } immediate_t;
74
75 static hashtab_t *value_table;
76 static ex_value_t *free_values;
77
78 static uintptr_t
value_get_hash(const void * _val,void * unused)79 value_get_hash (const void *_val, void *unused)
80 {
81 const ex_value_t *val = (const ex_value_t *) _val;
82 return Hash_Buffer (&val->v, sizeof (val->v)) + val->type;
83 }
84
85 static int
value_compare(const void * _val1,const void * _val2,void * unused)86 value_compare (const void *_val1, const void *_val2, void *unused)
87 {
88 const ex_value_t *val1 = (const ex_value_t *) _val1;
89 const ex_value_t *val2 = (const ex_value_t *) _val2;
90 if (val1->type != val2->type)
91 return 0;
92 return memcmp (&val1->v, &val2->v, sizeof (val1->v)) == 0;
93 }
94
95 static ex_value_t *
new_value(void)96 new_value (void)
97 {
98 ex_value_t *value;
99 ALLOC (256, ex_value_t, values, value);
100 return value;
101 }
102
103 static ex_value_t *
find_value(const ex_value_t * val)104 find_value (const ex_value_t *val)
105 {
106 ex_value_t *value;
107
108 value = Hash_FindElement (value_table, val);
109 if (value)
110 return value;
111 value = new_value ();
112 *value = *val;
113 Hash_AddElement (value_table, value);
114 return value;
115 }
116
117 ex_value_t *
new_string_val(const char * string_val)118 new_string_val (const char *string_val)
119 {
120 ex_value_t val;
121 memset (&val, 0, sizeof (val));
122 val.type = ev_string;
123 if (string_val)
124 val.v.string_val = save_string (string_val);
125 return find_value (&val);
126 }
127
128 ex_value_t *
new_float_val(float float_val)129 new_float_val (float float_val)
130 {
131 ex_value_t val;
132 memset (&val, 0, sizeof (val));
133 val.type = ev_float;
134 val.v.float_val = float_val;
135 return find_value (&val);
136 }
137
138 ex_value_t *
new_vector_val(const float * vector_val)139 new_vector_val (const float *vector_val)
140 {
141 ex_value_t val;
142 memset (&val, 0, sizeof (val));
143 val.type = ev_vector;
144 VectorCopy (vector_val, val.v.vector_val);
145 return find_value (&val);
146 }
147
148 ex_value_t *
new_entity_val(int entity_val)149 new_entity_val (int entity_val)
150 {
151 ex_value_t val;
152 memset (&val, 0, sizeof (val));
153 val.type = ev_entity;
154 val.v.entity_val = entity_val;
155 return find_value (&val);
156 }
157
158 ex_value_t *
new_field_val(int field_val,type_t * type,def_t * def)159 new_field_val (int field_val, type_t *type, def_t *def)
160 {
161 ex_value_t val;
162 memset (&val, 0, sizeof (val));
163 val.type = ev_field;
164 val.v.pointer.val = field_val;
165 val.v.pointer.type = type;
166 val.v.pointer.def = def;
167 return find_value (&val);
168 }
169
170 ex_value_t *
new_func_val(int func_val,type_t * type)171 new_func_val (int func_val, type_t *type)
172 {
173 ex_value_t val;
174 memset (&val, 0, sizeof (val));
175 val.type = ev_func;
176 val.v.func_val.val = func_val;
177 val.v.func_val.type = type;
178 return find_value (&val);
179 }
180
181 ex_value_t *
new_pointer_val(int pointer_val,type_t * type,def_t * def)182 new_pointer_val (int pointer_val, type_t *type, def_t *def)
183 {
184 ex_value_t val;
185 memset (&val, 0, sizeof (val));
186 val.type = ev_pointer;
187 val.v.pointer.val = pointer_val;
188 val.v.pointer.type = type;
189 val.v.pointer.def = def;
190 return find_value (&val);
191 }
192
193 ex_value_t *
new_quaternion_val(const float * quaternion_val)194 new_quaternion_val (const float *quaternion_val)
195 {
196 ex_value_t val;
197 memset (&val, 0, sizeof (val));
198 val.type = ev_quat;
199 QuatCopy (quaternion_val, val.v.quaternion_val);
200 return find_value (&val);
201 }
202
203 ex_value_t *
new_integer_val(int integer_val)204 new_integer_val (int integer_val)
205 {
206 ex_value_t val;
207 memset (&val, 0, sizeof (val));
208 val.type = ev_integer;
209 val.v.integer_val = integer_val;
210 return find_value (&val);
211 }
212
213 ex_value_t *
new_uinteger_val(int uinteger_val)214 new_uinteger_val (int uinteger_val)
215 {
216 ex_value_t val;
217 memset (&val, 0, sizeof (val));
218 val.type = ev_uinteger;
219 val.v.uinteger_val = uinteger_val;
220 return find_value (&val);
221 }
222
223 ex_value_t *
new_short_val(short short_val)224 new_short_val (short short_val)
225 {
226 ex_value_t val;
227 memset (&val, 0, sizeof (val));
228 val.type = ev_short;
229 val.v.short_val = short_val;
230 return find_value (&val);
231 }
232
233 ex_value_t *
new_nil_val(type_t * type)234 new_nil_val (type_t *type)
235 {
236 ex_value_t val;
237 memset (&val, 0, sizeof (val));
238 val.type = low_level_type (type);
239 if (val.type == ev_pointer|| val.type == ev_field )
240 val.v.pointer.type = type->t.fldptr.type;
241 if (val.type == ev_func)
242 val.v.func_val.type = type;
243 return find_value (&val);
244 }
245
246 static hashtab_t *string_imm_defs;
247 static hashtab_t *float_imm_defs;
248 static hashtab_t *vector_imm_defs;
249 static hashtab_t *entity_imm_defs;
250 static hashtab_t *field_imm_defs;
251 static hashtab_t *func_imm_defs;
252 static hashtab_t *pointer_imm_defs;
253 static hashtab_t *quaternion_imm_defs;
254 static hashtab_t *integer_imm_defs;
255
256 static void
imm_free(void * _imm,void * unused)257 imm_free (void *_imm, void *unused)
258 {
259 free (_imm);
260 }
261
262 static uintptr_t
imm_get_hash(const void * _imm,void * _tab)263 imm_get_hash (const void *_imm, void *_tab)
264 {
265 immediate_t *imm = (immediate_t *) _imm;
266 hashtab_t **tab = (hashtab_t **) _tab;
267
268 if (tab == &string_imm_defs) {
269 const char *str = pr.strings->strings + imm->i.string_val;
270 return str ? Hash_String (str) : 0;
271 } else if (tab == &float_imm_defs) {
272 return imm->i.integer_val;
273 } else if (tab == &vector_imm_defs) {
274 return Hash_Buffer (&imm->i.vector_val, sizeof (&imm->i.vector_val));
275 } else if (tab == &entity_imm_defs) {
276 return imm->i.integer_val;
277 } else if (tab == &field_imm_defs) {
278 return Hash_Buffer (&imm->i.pointer, sizeof (&imm->i.pointer));
279 } else if (tab == &func_imm_defs) {
280 return imm->i.integer_val;
281 } else if (tab == &pointer_imm_defs) {
282 return Hash_Buffer (&imm->i.pointer, sizeof (&imm->i.pointer));
283 } else if (tab == &quaternion_imm_defs) {
284 return Hash_Buffer (&imm->i.quaternion_val,
285 sizeof (&imm->i.quaternion_val));
286 } else if (tab == &integer_imm_defs) {
287 return imm->i.integer_val;
288 } else {
289 internal_error (0, 0);
290 }
291 }
292
293 static int
imm_compare(const void * _imm1,const void * _imm2,void * _tab)294 imm_compare (const void *_imm1, const void *_imm2, void *_tab)
295 {
296 immediate_t *imm1 = (immediate_t *) _imm1;
297 immediate_t *imm2 = (immediate_t *) _imm2;
298 hashtab_t **tab = (hashtab_t **) _tab;
299
300 if (tab == &string_imm_defs) {
301 const char *str1 = pr.strings->strings + imm1->i.string_val;
302 const char *str2 = pr.strings->strings + imm2->i.string_val;
303 return (str1 == str2 || (str1 && str2 && !strcmp (str1, str2)));
304 } else if (tab == &float_imm_defs) {
305 return imm1->i.float_val == imm2->i.float_val;
306 } else if (tab == &vector_imm_defs) {
307 return VectorCompare (imm1->i.vector_val, imm2->i.vector_val);
308 } else if (tab == &entity_imm_defs) {
309 return imm1->i.entity_val == imm2->i.entity_val;
310 } else if (tab == &field_imm_defs) {
311 return !memcmp (&imm1->i.pointer, &imm2->i.pointer,
312 sizeof (imm1->i.pointer));
313 } else if (tab == &func_imm_defs) {
314 return imm1->i.func_val == imm2->i.func_val;
315 } else if (tab == &pointer_imm_defs) {
316 return !memcmp (&imm1->i.pointer, &imm2->i.pointer,
317 sizeof (imm1->i.pointer));
318 } else if (tab == &quaternion_imm_defs) {
319 return (VectorCompare (imm1->i.quaternion_val,
320 imm2->i.quaternion_val)
321 && imm1->i.quaternion_val[3] == imm2->i.quaternion_val[3]);
322 } else if (tab == &integer_imm_defs) {
323 return imm1->i.integer_val == imm2->i.integer_val;
324 } else {
325 internal_error (0, 0);
326 }
327 }
328
329 int
ReuseString(const char * str)330 ReuseString (const char *str)
331 {
332 return strpool_addstr (pr.strings, str);
333 }
334
335 static float
value_as_float(ex_value_t * value)336 value_as_float (ex_value_t *value)
337 {
338 if (value->type == ev_uinteger)
339 return value->v.uinteger_val;
340 if (value->type == ev_integer)
341 return value->v.integer_val;
342 if (value->type == ev_short)
343 return value->v.short_val;
344 if (value->type == ev_float)
345 return value->v.float_val;
346 return 0;
347 }
348
349 static int
value_as_int(ex_value_t * value)350 value_as_int (ex_value_t *value)
351 {
352 if (value->type == ev_uinteger)
353 return value->v.uinteger_val;
354 if (value->type == ev_integer)
355 return value->v.integer_val;
356 if (value->type == ev_short)
357 return value->v.short_val;
358 if (value->type == ev_float)
359 return value->v.float_val;
360 return 0;
361 }
362
363 static unsigned
value_as_uint(ex_value_t * value)364 value_as_uint (ex_value_t *value)
365 {
366 if (value->type == ev_uinteger)
367 return value->v.uinteger_val;
368 if (value->type == ev_integer)
369 return value->v.integer_val;
370 if (value->type == ev_short)
371 return value->v.short_val;
372 if (value->type == ev_float)
373 return value->v.float_val;
374 return 0;
375 }
376
377 ex_value_t *
convert_value(ex_value_t * value,type_t * type)378 convert_value (ex_value_t *value, type_t *type)
379 {
380 if (!is_scalar (type) || !is_scalar (ev_types[value->type])) {
381 error (0, "unable to convert non-scalar value");
382 return value;
383 }
384 if (is_float (type)) {
385 float val = value_as_float (value);
386 return new_float_val (val);
387 } else if (type->type == ev_short) {
388 int val = value_as_int (value);
389 return new_short_val (val);
390 } else if (type->type == ev_uinteger) {
391 unsigned val = value_as_uint (value);
392 return new_uinteger_val (val);
393 } else {
394 //FIXME handle enums separately?
395 int val = value_as_int (value);
396 return new_integer_val (val);
397 }
398 }
399
400 ex_value_t *
alias_value(ex_value_t * value,type_t * type)401 alias_value (ex_value_t *value, type_t *type)
402 {
403 ex_value_t new;
404
405 if (type_size (type) != type_size (ev_types[value->type])) {
406 error (0, "unable to alias different sized values");
407 return value;
408 }
409 new = *value;
410 new.type = type->type;
411 return find_value (&new);
412 }
413
414 static immediate_t *
make_def_imm(def_t * def,hashtab_t * tab,ex_value_t * val)415 make_def_imm (def_t *def, hashtab_t *tab, ex_value_t *val)
416 {
417 immediate_t *imm;
418
419 imm = calloc (1, sizeof (immediate_t));
420 imm->def = def;
421 memcpy (&imm->i, &val->v, sizeof (imm->i));
422
423 Hash_AddElement (tab, imm);
424
425 return imm;
426 }
427
428 def_t *
emit_value(ex_value_t * value,def_t * def)429 emit_value (ex_value_t *value, def_t *def)
430 {
431 def_t *cn;
432 hashtab_t *tab = 0;
433 type_t *type;
434 ex_value_t val = *value;
435 immediate_t *imm, search;
436
437 if (!string_imm_defs) {
438 clear_immediates ();
439 }
440 cn = 0;
441 if (val.type == ev_void)
442 val.type = type_nil->type;
443 switch (val.type) {
444 case ev_entity:
445 tab = entity_imm_defs;
446 type = &type_entity;
447 break;
448 case ev_field:
449 tab = field_imm_defs;
450 type = &type_field;
451 break;
452 case ev_func:
453 tab = func_imm_defs;
454 type = &type_function;
455 break;
456 case ev_pointer:
457 tab = pointer_imm_defs;
458 type = &type_pointer;
459 break;
460 case ev_integer:
461 case ev_uinteger:
462 if (!def || def->type != &type_float) {
463 tab = integer_imm_defs;
464 type = &type_integer;
465 break;
466 }
467 val.v.float_val = val.v.integer_val;
468 val.type = ev_float;
469 case ev_float:
470 tab = float_imm_defs;
471 type = &type_float;
472 break;
473 case ev_string:
474 val.v.integer_val = ReuseString (val.v.string_val);
475 tab = string_imm_defs;
476 type = &type_string;
477 break;
478 case ev_vector:
479 tab = vector_imm_defs;
480 type = &type_vector;
481 break;
482 case ev_quat:
483 tab = quaternion_imm_defs;
484 type = &type_quaternion;
485 break;
486 default:
487 internal_error (0, 0);
488 }
489 memcpy (&search.i, &val.v, sizeof (search.i));
490 imm = (immediate_t *) Hash_FindElement (tab, &search);
491 if (imm && strcmp (imm->def->name, ".zero") == 0) {
492 if (def) {
493 imm = 0; //FIXME do full def aliasing
494 } else {
495 symbol_t *sym;
496 sym = make_symbol (".zero", &type_zero, 0, sc_extern);
497 return sym->s.def;
498 }
499 }
500 if (imm) {
501 cn = imm->def;
502 if (def) {
503 defspace_free_loc (def->space, def->offset, type_size (def->type));
504 def->offset = cn->offset;
505 def->initialized = def->constant = 1;
506 def->nosave = 1;
507 def->local = 0;
508 cn = def;
509 } else {
510 if (cn->type != type) {
511 def = new_def (".imm", type, pr.near_data, sc_static);
512 def->offset = cn->offset;
513 cn = def;
514 }
515 }
516 return cn;
517 }
518 // allocate a new one
519 // always share immediates
520 if (def) {
521 if (def->type != type) {
522 cn = new_def (".imm", type, pr.near_data, sc_static);
523 cn->offset = def->offset;
524 } else {
525 cn = def;
526 }
527 } else {
528 cn = new_def (".imm", type, pr.near_data, sc_static);
529 }
530 cn->initialized = cn->constant = 1;
531 cn->nosave = 1;
532 // copy the immediate to the global area
533 switch (val.type) {
534 case ev_string:
535 reloc_def_string (cn);
536 break;
537 case ev_func:
538 if (val.v.func_val.val) {
539 reloc_t *reloc;
540 reloc = new_reloc (cn->space, cn->offset, rel_def_func);
541 reloc->next = pr.relocs;
542 pr.relocs = reloc;
543 }
544 break;
545 case ev_field:
546 if (val.v.pointer.def)
547 reloc_def_field_ofs (val.v.pointer.def, cn);
548 break;
549 case ev_pointer:
550 if (val.v.pointer.def) {
551 EMIT_DEF_OFS (pr.near_data, D_INT (cn),
552 val.v.pointer.def);
553 }
554 break;
555 default:
556 break;
557 }
558
559 memcpy (D_POINTER (void, cn), &val.v, 4 * type_size (type));
560
561 imm = make_def_imm (cn, tab, &val);
562
563 return cn;
564 }
565
566 void
clear_immediates(void)567 clear_immediates (void)
568 {
569 def_t *def;
570 ex_value_t zero_val;
571
572 if (value_table) {
573 Hash_FlushTable (value_table);
574 Hash_FlushTable (string_imm_defs);
575 Hash_FlushTable (float_imm_defs);
576 Hash_FlushTable (vector_imm_defs);
577 Hash_FlushTable (entity_imm_defs);
578 Hash_FlushTable (field_imm_defs);
579 Hash_FlushTable (func_imm_defs);
580 Hash_FlushTable (pointer_imm_defs);
581 Hash_FlushTable (quaternion_imm_defs);
582 Hash_FlushTable (integer_imm_defs);
583 } else {
584 value_table = Hash_NewTable (16381, 0, 0, 0);
585 Hash_SetHashCompare (value_table, value_get_hash, value_compare);
586
587 string_imm_defs = Hash_NewTable (16381, 0, imm_free, &string_imm_defs);
588 Hash_SetHashCompare (string_imm_defs, imm_get_hash, imm_compare);
589
590 float_imm_defs = Hash_NewTable (16381, 0, imm_free, &float_imm_defs);
591 Hash_SetHashCompare (float_imm_defs, imm_get_hash, imm_compare);
592
593 vector_imm_defs = Hash_NewTable (16381, 0, imm_free, &vector_imm_defs);
594 Hash_SetHashCompare (vector_imm_defs, imm_get_hash, imm_compare);
595
596 entity_imm_defs = Hash_NewTable (16381, 0, imm_free, &entity_imm_defs);
597 Hash_SetHashCompare (entity_imm_defs, imm_get_hash, imm_compare);
598
599 field_imm_defs = Hash_NewTable (16381, 0, imm_free, &field_imm_defs);
600 Hash_SetHashCompare (field_imm_defs, imm_get_hash, imm_compare);
601
602 func_imm_defs = Hash_NewTable (16381, 0, imm_free, &func_imm_defs);
603 Hash_SetHashCompare (func_imm_defs, imm_get_hash, imm_compare);
604
605 pointer_imm_defs =
606 Hash_NewTable (16381, 0, imm_free, &pointer_imm_defs);
607 Hash_SetHashCompare (pointer_imm_defs, imm_get_hash, imm_compare);
608
609 quaternion_imm_defs =
610 Hash_NewTable (16381, 0, imm_free, &quaternion_imm_defs);
611 Hash_SetHashCompare (quaternion_imm_defs, imm_get_hash, imm_compare);
612
613 integer_imm_defs =
614 Hash_NewTable (16381, 0, imm_free, &integer_imm_defs);
615 Hash_SetHashCompare (integer_imm_defs, imm_get_hash, imm_compare);
616 }
617
618 def = make_symbol (".zero", &type_zero, 0, sc_extern)->s.def;
619
620 memset (&zero_val, 0, sizeof (zero_val));
621 make_def_imm (def, string_imm_defs, &zero_val);
622 make_def_imm (def, float_imm_defs, &zero_val);
623 make_def_imm (def, entity_imm_defs, &zero_val);
624 make_def_imm (def, pointer_imm_defs, &zero_val);
625 make_def_imm (def, integer_imm_defs, &zero_val);
626 }
627