tv.c 39.6 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
2
/*
 * This file is part of libFirm.
3
 * Copyright (C) 2012 University of Karlsruhe.
Christian Würdig's avatar
Christian Würdig committed
4
5
 */

Michael Beck's avatar
Michael Beck committed
6
7
8
9
10
11
/**
 * @file
 * @brief    Representation of and static computations on target machine
 *           values.
 * @date     2003
 * @author   Mathias Heil
yb9976's avatar
yb9976 committed
12
 * @brief
13
 *
Michael Beck's avatar
Michael Beck committed
14
15
16
17
 * Values are stored in a format depending upon chosen arithmetic
 * module. Default uses strcalc and fltcalc.
 * This implementation assumes:
 *  - target has IEEE-754 floating-point arithmetic.
18
 */
19
20
#include <assert.h>
#include <stdlib.h>
21
#include <string.h>
22
#include <stdlib.h>
23
#include <strings.h>
24

25
#include "bitfiddle.h"
26
#include "tv_t.h"
27
28
#include "set.h"
#include "entity_t.h"
Michael Beck's avatar
Michael Beck committed
29
#include "irmode_t.h"
30
#include "irnode.h"
31
32
#include "strcalc.h"
#include "fltcalc.h"
33
#include "util.h"
Michael Beck's avatar
Michael Beck committed
34
#include "xmalloc.h"
Michael Beck's avatar
Michael Beck committed
35
#include "firm_common.h"
Matthias Braun's avatar
Matthias Braun committed
36
#include "panic.h"
Christian Schäfer's avatar
Christian Schäfer committed
37

Matthias Braun's avatar
Matthias Braun committed
38
39
/** Size of hash tables.  Should correspond to average number of distinct
 * constant target values */
40
#define N_CONSTANTS 2048
Götz Lindenmaier's avatar
Götz Lindenmaier committed
41

42
43
44
/****************************************************************************
 *   local definitions and macros
 ****************************************************************************/
45
#define INSERT_TARVAL(tv) (set_insert(ir_tarval, tarvals, (tv), offsetof(ir_tarval, value) + (tv)->length, hash_tv((tv))))
46

Michael Beck's avatar
Michael Beck committed
47
48
49
/** A set containing all existing tarvals. */
static struct set *tarvals = NULL;

50
51
static unsigned sc_value_length;

Michael Beck's avatar
Michael Beck committed
52
/** The integer overflow mode. */
53
static tarval_int_overflow_mode_t int_overflow_mode = TV_OVERFLOW_WRAP;
54

55
/** Hash a value. Treat it as a byte array. */
56
static unsigned hash_val(unsigned char const *value, size_t length)
57
{
Michael Beck's avatar
Michael Beck committed
58
	/* scramble the byte - array */
Matthias Braun's avatar
Matthias Braun committed
59
60
	unsigned hash = 0;
	for (size_t i = 0; i < length; ++i) {
61
		hash += (hash << 5) ^ (hash >> 27) ^ value[i];
Michael Beck's avatar
Michael Beck committed
62
63
64
		hash += (hash << 11) ^ (hash >> 17);
	}
	return hash;
Christian Schäfer's avatar
Christian Schäfer committed
65
66
}

67
68
69
70
71
72
/** Hash a tarval. */
static unsigned hash_tv(const ir_tarval *tv)
{
	return (unsigned)((hash_val(tv->value, tv->length) ^ PTR_TO_INT(tv->mode)) + tv->length);
}

73
74
static int cmp_tv(const void *p1, const void *p2, size_t n)
{
Matthias Braun's avatar
Matthias Braun committed
75
76
	const ir_tarval *tv1 = (const ir_tarval*) p1;
	const ir_tarval *tv2 = (const ir_tarval*) p2;
77
78
79
80
	(void) n;

	assert(tv1->kind == k_tarval);
	assert(tv2->kind == k_tarval);
81
	if (tv1->mode < tv2->mode)
82
		return -1;
83
	if (tv1->mode > tv2->mode)
84
		return 1;
85
	if (tv1->length < tv2->length)
86
		return -1;
87
	if (tv1->length > tv2->length)
88
		return 1;
89
	return memcmp(tv1->value, tv2->value, tv1->length);
90
91
}

Michael Beck's avatar
Michael Beck committed
92
/** finds tarval with value/mode or creates new tarval */
93
static ir_tarval *get_tarval(const void *value, size_t length, ir_mode *mode)
94
{
95
96
97
98
99
100
101
102
103
104
	ir_tarval *const tv = ALLOCAF(ir_tarval, value, length);
	tv->kind   = k_tarval;
	tv->mode   = mode;
	tv->length = length;
	memcpy(tv->value, value, length);
	if (get_mode_arithmetic(mode) == irma_twos_complement) {
		if (mode_is_signed(mode)) {
			sc_sign_extend((sc_word*)tv->value, get_mode_size_bits(mode));
		} else {
			sc_zero_extend((sc_word*)tv->value, get_mode_size_bits(mode));
105
		}
Michael Beck's avatar
Michael Beck committed
106
107
108
	}
	/* if there is such a tarval, it is returned, else tv is copied
	 * into the set */
109
	return INSERT_TARVAL(tv);
Christian Schäfer's avatar
Christian Schäfer committed
110
111
}

Matthias Braun's avatar
Matthias Braun committed
112
113
114
/** handle overflow */
static ir_tarval *get_tarval_overflow(const void *value, size_t length,
                                      ir_mode *mode)
Christian Schäfer's avatar
Christian Schäfer committed
115
{
Michael Beck's avatar
Michael Beck committed
116
	switch (get_mode_sort(mode)) {
Matthias Braun's avatar
Matthias Braun committed
117
	case irms_reference: {
118
		/* addresses always wrap around */
119
120
		sc_word *temp = ALLOCAN(sc_word, sc_value_length);
		memcpy(temp, value, sc_value_length);
121
		unsigned bits = get_mode_size_bits(mode);
122
		/* the sc_ module expects that all bits are set ... */
123
124
125
126
127
		if (mode_is_signed(mode)) {
			sc_sign_extend(temp, bits);
		} else {
			sc_zero_extend(temp, bits);
		}
128
		return get_tarval(temp, length, mode);
Matthias Braun's avatar
Matthias Braun committed
129
	}
130

Michael Beck's avatar
Michael Beck committed
131
	case irms_int_number:
132
		if (sc_comp(value, get_mode_max(mode)->value) == ir_relation_greater) {
133
			switch (tarval_get_integer_overflow_mode()) {
Michael Beck's avatar
Michael Beck committed
134
135
			case TV_OVERFLOW_SATURATE:
				return get_mode_max(mode);
Matthias Braun's avatar
Matthias Braun committed
136
			case TV_OVERFLOW_WRAP: {
137
138
				sc_word *temp = ALLOCAN(sc_word, sc_value_length);
				memcpy(temp, value, sc_value_length);
139
				unsigned bits = get_mode_size_bits(mode);
140
				/* the sc_ module expects that all bits are set ... */
141
142
143
144
145
				if (mode_is_signed(mode)) {
					sc_sign_extend(temp, bits);
				} else {
					sc_zero_extend(temp, bits);
				}
146
				return get_tarval(temp, length, mode);
Matthias Braun's avatar
Matthias Braun committed
147
			}
Michael Beck's avatar
Michael Beck committed
148
149
150
151
152
153
			case TV_OVERFLOW_BAD:
				return tarval_bad;
			default:
				return get_tarval(value, length, mode);
			}
		}
154
		if (sc_comp(value, get_mode_min(mode)->value) == ir_relation_less) {
155
			switch (tarval_get_integer_overflow_mode()) {
Michael Beck's avatar
Michael Beck committed
156
157
158
			case TV_OVERFLOW_SATURATE:
				return get_mode_min(mode);
			case TV_OVERFLOW_WRAP: {
159
160
				sc_word *temp = ALLOCAN(sc_word, sc_value_length);
				memcpy(temp, value, sc_value_length);
Michael Beck's avatar
Michael Beck committed
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
				return get_tarval(temp, length, mode);
			}
			case TV_OVERFLOW_BAD:
				return tarval_bad;
			default:
				return get_tarval(value, length, mode);
			}
		}
		break;

	case irms_float_number:
		break;

	default:
		break;
	}
	return get_tarval(value, length, mode);
Christian Schäfer's avatar
Christian Schäfer committed
178
179
}

180
181
static ir_tarval tarval_bad_obj;
static ir_tarval tarval_unknown_obj;
182

183
184
ir_tarval       *tarval_b_false;
ir_tarval       *tarval_b_true;
185
186
ir_tarval *const tarval_bad     = &tarval_bad_obj;
ir_tarval *const tarval_unknown = &tarval_unknown_obj;
Christian Schäfer's avatar
Christian Schäfer committed
187

Michael Beck's avatar
Michael Beck committed
188
189
190
/**
 * get the float descriptor for given mode.
 */
191
192
193
static const float_descriptor_t *get_descriptor(const ir_mode *mode)
{
	return &mode->float_desc;
Michael Beck's avatar
Michael Beck committed
194
195
}

Matthias Braun's avatar
Matthias Braun committed
196
static ir_tarval *get_tarval_from_fp_value(const fp_value *val, ir_mode *mode)
197
198
199
200
201
202
203
204
205
{
	const float_descriptor_t *desc          = get_descriptor(mode);
	const int                 buffer_length = fc_get_buffer_length();
	fp_value                 *tmp           = alloca(buffer_length);
	memcpy(tmp, val, buffer_length);
	fp_value *casted_val = fc_cast(tmp, desc, NULL);
	return get_tarval(casted_val, buffer_length, mode);
}

206
207
208
ir_tarval *new_integer_tarval_from_str(const char *str, size_t len,
                                       int negative, unsigned char base,
                                       ir_mode *mode)
209
{
210
	sc_word *buffer = ALLOCAN(sc_word, sc_value_length);
211
	bool ok = sc_val_from_str(negative, base, str, len, buffer);
212
213
214
	if (!ok)
		return tarval_bad;

215
	return get_tarval_overflow(buffer, sc_value_length, mode);
216
}
217

Matthias Braun's avatar
Matthias Braun committed
218
219
static ir_tarval *new_tarval_from_str_int(const char *str, size_t len,
                                          ir_mode *mode)
220
221
222
223
224
225
226
227
228
229
{
	/* skip leading spaces */
	while (len > 0 && str[0] == ' ') {
		++str;
		--len;
	}
	if (len == 0)
		return tarval_bad;

	/* 1 sign character allowed */
230
	bool negative = false;
231
	if (str[0] == '-') {
232
		negative = true;
233
234
235
236
237
238
239
240
241
		++str;
		--len;
	} else if (str[0] == '+') {
		++str;
		--len;
	}

	/* a number starting with '0x' is hexadeciaml,
	 * a number starting with '0' (and at least 1 more char) is octal */
Matthias Braun's avatar
Matthias Braun committed
242
	unsigned base = 10;
243
244
245
246
247
	if (len >= 2 && str[0] == '0') {
		if (str[1] == 'x' || str[1] == 'X') {
			str += 2;
			len -= 2;
			base = 16;
248
249
250
251
		} else if (str[1] == 'b' || str[1] == 'B') {
			str += 2;
			len -= 2;
			base = 2;
252
253
254
255
256
257
258
259
260
		} else {
			++str;
			--len;
			base = 8;
		}
	}
	if (len == 0)
		return tarval_bad;

261
	sc_word *buffer = ALLOCAN(sc_word, sc_value_length);
262
	bool     ok     = sc_val_from_str(negative, base, str, len, buffer);
263
264
265
	if (!ok)
		return tarval_bad;

266
	return get_tarval_overflow(buffer, sc_value_length, mode);
267
268
}

Matthias Braun's avatar
Matthias Braun committed
269
ir_tarval *new_tarval_from_str(const char *str, size_t len, ir_mode *mode)
270
{
Matthias Braun's avatar
Matthias Braun committed
271
272
	assert(str != NULL);
	assert(len > 0);
Michael Beck's avatar
Michael Beck committed
273
274
275
276

	switch (get_mode_sort(mode)) {
	case irms_internal_boolean:
		/* match [tT][rR][uU][eE]|[fF][aA][lL][sS][eE] */
277
		if (!strcasecmp(str, "true"))
278
			return tarval_b_true;
279
280
		else if (!strcasecmp(str, "false"))
			return tarval_b_false;
Michael Beck's avatar
Michael Beck committed
281
282
283
284
		else
			/* XXX This is C semantics */
			return atoi(str) ? tarval_b_true : tarval_b_false;

285
286
287
288
	case irms_float_number: {
		fp_value *val = fc_val_from_str(str, len, NULL);
		return get_tarval_from_fp_value(val, mode);
	}
Michael Beck's avatar
Michael Beck committed
289
	case irms_reference:
290
		if (!strcasecmp(str, "null"))
291
			return get_mode_null(mode);
292
		/* FALLTHROUGH */
Michael Beck's avatar
Michael Beck committed
293
	case irms_int_number:
294
		return new_tarval_from_str_int(str, len, mode);
295
	default:
296
		panic("unsupported tarval creation with mode %F", mode);
Michael Beck's avatar
Michael Beck committed
297
	}
298
}
Christian Schäfer's avatar
Christian Schäfer committed
299

Matthias Braun's avatar
Matthias Braun committed
300
ir_tarval *new_tarval_from_long(long l, ir_mode *mode)
301
{
302
	switch (get_mode_sort(mode))   {
Michael Beck's avatar
Michael Beck committed
303
304
305
306
307
308
	case irms_internal_boolean:
		/* XXX C semantics ! */
		return l ? tarval_b_true : tarval_b_false ;

	case irms_reference:
		/* same as integer modes */
309
	case irms_int_number: {
310
		sc_word *buffer = ALLOCAN(sc_word, sc_value_length);
311
		sc_val_from_long(l, buffer);
312
		return get_tarval(buffer, sc_value_length, mode);
313
	}
Michael Beck's avatar
Michael Beck committed
314
315
316
317
318

	case irms_float_number:
		return new_tarval_from_double((long double)l, mode);

	default:
319
		panic("unsupported mode sort");
Michael Beck's avatar
Michael Beck committed
320
	}
Christian Schäfer's avatar
Christian Schäfer committed
321
}
Michael Beck's avatar
Michael Beck committed
322

Matthias Braun's avatar
Matthias Braun committed
323
324
325
326
ir_tarval *new_tarval_from_bytes(unsigned char const *buf,
                                 ir_mode *mode, int big_endian)
{
	switch (get_mode_arithmetic(mode)) {
327
	case irma_twos_complement: {
Matthias Braun's avatar
Matthias Braun committed
328
329
		if (get_mode_size_bytes(mode) == (unsigned)-1)
			return tarval_bad;
330
		sc_word *dest = ALLOCAN(sc_word, sc_value_length);
331
		sc_val_from_bytes(buf, get_mode_size_bytes(mode), big_endian, dest);
332
		return get_tarval(dest, sc_value_length, mode);
333
	}
Matthias Braun's avatar
Matthias Braun committed
334
	case irma_ieee754:
335
336
337
338
339
340
341
	case irma_x86_extended_float: {
		if (big_endian) {
			unsigned       size = get_mode_size_bytes(mode);
			unsigned char *temp = ALLOCAN(unsigned char, size);
			for (unsigned i = 0; i < size; ++i) {
				temp[i] = buf[size-i-1];
			}
342
			buf = temp;
343
		}
344
		fc_val_from_bytes(NULL, buf, get_descriptor(mode));
345
346
		return get_tarval_from_fp_value(fc_get_buffer(), mode);
	}
Matthias Braun's avatar
Matthias Braun committed
347
348
349
350
351
352
	case irma_none:
		break;
	}
	panic("tarval from byte requested for non storable mode");
}

yb9976's avatar
yb9976 committed
353
int tarval_is_long(const ir_tarval *tv)
354
{
355
356
357
358
359
360
361
362
	ir_mode *mode = get_tarval_mode(tv);
	if (get_mode_arithmetic(mode) != irma_twos_complement)
		return false;
	if (get_mode_size_bytes(mode) <= sizeof(long))
		return true;

	/* the value might be too big to fit in a long */
	size_t long_bits = sizeof(long)*8;
363
	sc_word *temp = ALLOCAN(sc_word, sc_value_length);
364
365
	sc_max_from_bits(long_bits, mode_is_signed(mode), temp);
	if (sc_comp(tv->value, temp) == ir_relation_greater)
366
367
		return false;
	if (mode_is_signed(mode)) {
368
		sc_word *min = ALLOCAN(sc_word, sc_value_length);
369
		sc_min_from_bits(long_bits, true, min);
370
		sc_sign_extend(min, long_bits);
371
372
		if (sc_comp(tv->value, min) == ir_relation_less)
			return false;
Michael Beck's avatar
Michael Beck committed
373
	}
374
	return true;
375
}
Michael Beck's avatar
Michael Beck committed
376

yb9976's avatar
yb9976 committed
377
long get_tarval_long(const ir_tarval* tv)
378
{
379
	assert(tarval_is_long(tv));
Michael Beck's avatar
Michael Beck committed
380
	return sc_val_to_long(tv->value);
381
}
Christian Schäfer's avatar
Christian Schäfer committed
382

yb9976's avatar
yb9976 committed
383
bool tarval_is_uint64(const ir_tarval *tv)
384
{
385
386
	ir_mode *mode = get_tarval_mode(tv);
	if (get_mode_arithmetic(mode) != irma_twos_complement)
387
		return false;
388
389
	if (get_mode_size_bytes(mode) <= sizeof(uint64_t))
		return true;
390

391
	/* the value might be too big to fit in a long */
392
	sc_word *temp = ALLOCAN(sc_word, sc_value_length);
393
394
	sc_max_from_bits(sizeof(uint64_t)*8, 0, temp);
	return sc_comp(tv->value, temp) & ir_relation_less_equal;
395
396
}

yb9976's avatar
yb9976 committed
397
uint64_t get_tarval_uint64(const ir_tarval *tv)
398
399
400
401
402
{
	assert(tarval_is_uint64(tv));
	return sc_val_to_uint64(tv->value);
}

403
ir_tarval *new_tarval_from_long_double(long double d, ir_mode *mode)
404
{
Michael Beck's avatar
Michael Beck committed
405
	assert(mode && (get_mode_sort(mode) == irms_float_number));
406
407
	fp_value *val = fc_val_from_ieee754(d, NULL);
	return get_tarval_from_fp_value(val, mode);
Christian Schäfer's avatar
Christian Schäfer committed
408
}
Michael Beck's avatar
Michael Beck committed
409

410
411
412
413
414
ir_tarval *new_tarval_from_double(double d, ir_mode *mode)
{
	return new_tarval_from_long_double(d, mode);
}

yb9976's avatar
yb9976 committed
415
int tarval_is_double(const ir_tarval *tv)
416
{
Matthias Braun's avatar
Matthias Braun committed
417
	return get_mode_sort(tv->mode) == irms_float_number;
418
}
Michael Beck's avatar
Michael Beck committed
419

yb9976's avatar
yb9976 committed
420
long double get_tarval_long_double(const ir_tarval *tv)
421
{
Michael Beck's avatar
Michael Beck committed
422
	assert(tarval_is_double(tv));
423
	return fc_val_to_ieee754((const fp_value*) tv->value);
424
}
Christian Schäfer's avatar
Christian Schäfer committed
425

yb9976's avatar
yb9976 committed
426
double get_tarval_double(const ir_tarval *tv)
427
428
429
430
{
	return get_tarval_long_double(tv);
}

yb9976's avatar
yb9976 committed
431
ir_mode *(get_tarval_mode)(const ir_tarval *tv)
432
{
433
	return get_tarval_mode_(tv);
434
435
}

436
437
438
439
440
441
442
/*
 * Special value query functions ============================================
 *
 * These functions calculate and return a tarval representing the requested
 * value.
 * The functions get_mode_{Max,Min,...} return tarvals retrieved from these
 * functions, but these are stored on initialization of the irmode module and
Michael Beck's avatar
Michael Beck committed
443
 * therefore the irmode functions should be preferred to the functions below.
444
 */
Christian Schäfer's avatar
Christian Schäfer committed
445

446
447
448
449
450
int (tarval_is_constant)(const ir_tarval *tv)
{
	return tarval_is_constant_(tv);
}

Matthias Braun's avatar
Matthias Braun committed
451
ir_tarval *(get_tarval_bad)(void)
452
{
453
	return get_tarval_bad_();
454
}
Michael Beck's avatar
Michael Beck committed
455

456
ir_tarval *(get_tarval_unknown)(void)
457
{
458
	return get_tarval_unknown_();
459
}
Michael Beck's avatar
Michael Beck committed
460

Matthias Braun's avatar
Matthias Braun committed
461
ir_tarval *(get_tarval_b_false)(void)
462
{
463
	return get_tarval_b_false_();
464
}
Michael Beck's avatar
Michael Beck committed
465

Matthias Braun's avatar
Matthias Braun committed
466
ir_tarval *(get_tarval_b_true)(void)
467
{
468
	return get_tarval_b_true_();
469
}
Michael Beck's avatar
Michael Beck committed
470

471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
ir_tarval *get_tarval_small(ir_mode *mode)
{
	if (!mode_is_float(mode))
		panic("mode %+F does not support small value");
	const float_descriptor_t *desc = get_descriptor(mode);
	fc_get_small(desc, NULL);
	return get_tarval(fc_get_buffer(), fc_get_buffer_length(), mode);
}

ir_tarval *get_tarval_epsilon(ir_mode *mode)
{
	if (!mode_is_float(mode))
		panic("mode %+F does not support small value");
	const float_descriptor_t *desc = get_descriptor(mode);
	fc_get_epsilon(desc, NULL);
	return get_tarval(fc_get_buffer(), fc_get_buffer_length(), mode);
}

489
ir_tarval *get_tarval_minus_inf(ir_mode *mode)
490
{
491
492
493
494
495
	if (get_mode_sort(mode) != irms_float_number)
		panic("mode %F does not support -inf value", mode);
	const float_descriptor_t *desc = get_descriptor(mode);
	fc_get_inf(desc, NULL, true);
	return get_tarval(fc_get_buffer(), fc_get_buffer_length(), mode);
Christian Schäfer's avatar
Christian Schäfer committed
496
497
}

498
void init_mode_values(ir_mode* mode)
499
{
Michael Beck's avatar
Michael Beck committed
500
	switch (get_mode_sort(mode)) {
501
502
503
504
505
506
507
508
509
510
511
	case irms_float_number: {
		const float_descriptor_t *desc   = get_descriptor(mode);
		unsigned                  buflen = fc_get_buffer_length();
		fp_value                 *buf    = alloca(buflen);
		mode->all_one     = tarval_bad;
		fc_get_inf(desc, buf, false);
		mode->infinity    = get_tarval(buf, buflen, mode);
		fc_get_qnan(desc, buf);
		mode->nan         = get_tarval(buf, buflen, mode);
		fc_get_max(desc, buf, true); // min = negative maximum
		mode->min         = get_tarval(buf, buflen, mode);
512
513
		fc_get_max(desc, buf, false);
		mode->max         = get_tarval(buf, buflen, mode);
514
515
516
		mode->null        = new_tarval_from_double(0.0, mode);
		mode->one         = new_tarval_from_double(1.0, mode);
		break;
Michael Beck's avatar
Michael Beck committed
517
	}
518

519
	case irms_internal_boolean:
520
521
522
523
524
525
526
527
		mode->all_one   = tarval_b_true;
		mode->infinity  = tarval_bad;
		mode->nan       = tarval_bad;
		mode->min       = tarval_b_false;
		mode->max       = tarval_b_true;
		mode->null      = tarval_b_false;
		mode->one       = tarval_b_true;
		break;
528

529
	case irms_reference:
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
	case irms_int_number: {
		sc_word *buf    = ALLOCAN(sc_word, sc_value_length);
		unsigned buflen = sc_value_length * sizeof(buf[0]);
		unsigned bits   = get_mode_size_bits(mode);
		bool     sign   = mode_is_signed(mode);
		sc_max_from_bits(bits, false, buf);
		mode->all_one   = get_tarval(buf, buflen, mode);
		mode->infinity  = tarval_bad;
		mode->nan       = tarval_bad;
		sc_min_from_bits(bits, sign, buf);
		mode->min       = get_tarval(buf, buflen, mode);
		sc_max_from_bits(bits, sign, buf);
		mode->max       = get_tarval(buf, buflen, mode);
		sc_zero(buf);
		mode->null      = get_tarval(buf, buflen, mode);
		sc_set_bit_at(buf, 0);
		mode->one       = get_tarval(buf, buflen, mode);
		break;
	}
549

550
551
	case irms_auxiliary:
	case irms_data:
552
553
554
555
556
557
558
559
		mode->all_one   = tarval_bad;
		mode->min       = tarval_bad;
		mode->max       = tarval_bad;
		mode->null      = tarval_bad;
		mode->one       = tarval_bad;
		mode->infinity  = tarval_bad;
		mode->nan       = tarval_bad;
		break;
Michael Beck's avatar
Michael Beck committed
560
	}
561
562
}

563
/*
564
 * Arithmetic operations on tarvals ========================================
565
 */
Christian Schäfer's avatar
Christian Schäfer committed
566

yb9976's avatar
yb9976 committed
567
int tarval_is_negative(const ir_tarval *a)
568
{
Michael Beck's avatar
Michael Beck committed
569
570
	switch (get_mode_sort(a->mode)) {
	case irms_int_number:
571
	case irms_reference:
Matthias Braun's avatar
Matthias Braun committed
572
573
574
		if (!mode_is_signed(a->mode)) {
			return 0;
		} else {
575
			return sc_comp(a->value, get_mode_null(a->mode)->value) == ir_relation_less ? 1 : 0;
Matthias Braun's avatar
Matthias Braun committed
576
		}
Michael Beck's avatar
Michael Beck committed
577
578

	case irms_float_number:
579
		return fc_is_negative((const fp_value*) a->value);
Michael Beck's avatar
Michael Beck committed
580

581
582
583
	case irms_auxiliary:
	case irms_internal_boolean:
	case irms_data:
584
		panic("mode %F does not support negation value", a->mode);
Michael Beck's avatar
Michael Beck committed
585
	}
586
	panic("invalid mode sort");
Christian Schäfer's avatar
Christian Schäfer committed
587
588
}

589
int tarval_is_null(const ir_tarval *tv)
590
{
591
	return tv == get_tarval_mode(tv)->null && tv != tarval_bad;
Michael Beck's avatar
Michael Beck committed
592
593
}

594
int tarval_is_one(const ir_tarval *tv)
595
{
596
	return tv == get_tarval_mode(tv)->one && tv != tarval_bad;
597
}
Michael Beck's avatar
Michael Beck committed
598

yb9976's avatar
yb9976 committed
599
int tarval_is_all_one(const ir_tarval *tv)
600
{
601
	return tv == get_tarval_mode(tv)->all_one && tv != tarval_bad;
Michael Beck's avatar
Michael Beck committed
602
603
}

604
bool tarval_is_minus_one(const ir_tarval *tv)
605
{
yb9976's avatar
yb9976 committed
606
	assert(mode_is_float(get_tarval_mode(tv)));
607
608
609
	const fp_value *val = (const fp_value*)tv->value;
	return fc_is_negative(val) && fc_zero_mantissa(val)
	    && fc_get_exponent(val) == 0 && !fc_is_inf(val) && !fc_is_nan(val);
Michael Beck's avatar
Michael Beck committed
610
611
}

yb9976's avatar
yb9976 committed
612
ir_relation tarval_cmp(const ir_tarval *a, const ir_tarval *b)
613
{
614
615
616
	if (a == tarval_unknown || b == tarval_unknown)
		return ir_relation_true;
	if (a == tarval_bad || b == tarval_bad || a->mode != b->mode)
617
		return ir_relation_false;
Michael Beck's avatar
Michael Beck committed
618
619
620
621
622
623
624
625

	/* Here the two tarvals are unequal and of the same mode */
	switch (get_mode_sort(a->mode)) {
	case irms_float_number:
		/*
		 * BEWARE: we cannot compare a == b here, because
		 * a NaN is always Unordered to any other value, even to itself!
		 */
626
627
		return fc_comp((fp_value const*)a->value, (fp_value const*)b->value);

628
	case irms_reference:
Michael Beck's avatar
Michael Beck committed
629
630
	case irms_int_number:
		if (a == b)
631
			return ir_relation_equal;
632
		return sc_comp(a->value, b->value);
Michael Beck's avatar
Michael Beck committed
633
634
635

	case irms_internal_boolean:
		if (a == b)
636
637
			return ir_relation_equal;
		return a == tarval_b_true ? ir_relation_greater : ir_relation_less;
638
639
640

	default:
		panic("can't compare values of mode %F", a->mode);
Michael Beck's avatar
Michael Beck committed
641
	}
642
643
}

Matthias Braun's avatar
Matthias Braun committed
644
ir_tarval *tarval_convert_to(ir_tarval *src, ir_mode *dst_mode)
645
{
646
647
	if (src->mode == dst_mode)
		return src;
Michael Beck's avatar
Michael Beck committed
648
649

	switch (get_mode_sort(src->mode)) {
650
	/* cast float to something */
Michael Beck's avatar
Michael Beck committed
651
	case irms_float_number:
652
		switch (get_mode_sort(dst_mode)) {
Matthias Braun's avatar
Matthias Braun committed
653
654
		case irms_float_number: {
			const float_descriptor_t *desc = get_descriptor(dst_mode);
655
			fc_cast((const fp_value*) src->value, desc, NULL);
656
			return get_tarval(fc_get_buffer(), fc_get_buffer_length(), dst_mode);
Matthias Braun's avatar
Matthias Braun committed
657
		}
Michael Beck's avatar
Michael Beck committed
658

Matthias Braun's avatar
Matthias Braun committed
659
		case irms_int_number: {
660
			fp_value *res    = fc_int((const fp_value*) src->value, NULL);
661
			sc_word  *buffer = ALLOCAN(sc_word, sc_value_length);
Matthias Braun's avatar
Matthias Braun committed
662
663
664
			flt2int_result_t cres
				= fc_flt2int(res, buffer, get_mode_size_bits(dst_mode),
				             mode_is_signed(dst_mode));
665
666
			switch (cres) {
			case FLT2INT_POSITIVE_OVERFLOW:
667
668
669
670
671
672
673
				switch (get_mode_float_int_overflow(src->mode)) {
				case ir_overflow_indefinite:
					return get_mode_min(dst_mode);
				case ir_overflow_min_max:
					return get_mode_max(dst_mode);
				}
				break;
674
675
			case FLT2INT_NEGATIVE_OVERFLOW:
				return get_mode_min(dst_mode);
676
			case FLT2INT_BAD:
677
				return tarval_bad;
678
			case FLT2INT_OK:
679
				return get_tarval(buffer, sc_value_length, dst_mode);
680
			}
Matthias Braun's avatar
Matthias Braun committed
681
		}
Michael Beck's avatar
Michael Beck committed
682
683

		default:
684
			break;
Michael Beck's avatar
Michael Beck committed
685
		}
686
687
		/* the rest can't be converted */
		return tarval_bad;
Michael Beck's avatar
Michael Beck committed
688

689
	/* cast int/characters to something */
Michael Beck's avatar
Michael Beck committed
690
	case irms_int_number:
691
		switch (get_mode_sort(dst_mode)) {
692
693

		case irms_reference:
Matthias Braun's avatar
Matthias Braun committed
694
		case irms_int_number: {
695
696
			sc_word *buffer = ALLOCAN(sc_word, sc_value_length);
			memcpy(buffer, src->value, sc_value_length);
697
			return get_tarval_overflow(buffer, src->length, dst_mode);
Matthias Braun's avatar
Matthias Braun committed
698
		}
Michael Beck's avatar
Michael Beck committed
699

Matthias Braun's avatar
Matthias Braun committed
700
		case irms_float_number: {
Michael Beck's avatar
Michael Beck committed
701
702
703
			/* XXX floating point unit does not understand internal integer
			 * representation, convert to string first, then create float from
			 * string */
Matthias Braun's avatar
Matthias Braun committed
704
			char *buffer = ALLOCAN(char, 100);
Michael Beck's avatar
Michael Beck committed
705
706
			/* decimal string representation because hexadecimal output is
			 * interpreted unsigned by fc_val_from_str, so this is a HACK */
Matthias Braun's avatar
Matthias Braun committed
707
			int len = snprintf(buffer, 100, "%s",
Michael Beck's avatar
Michael Beck committed
708
709
710
				sc_print(src->value, get_mode_size_bits(src->mode), SC_DEC, mode_is_signed(src->mode)));
			buffer[100 - 1] = '\0';

711
712
			fp_value *val = fc_val_from_str(buffer, len, NULL);
			return get_tarval_from_fp_value(val, dst_mode);
Matthias Braun's avatar
Matthias Braun committed
713
		}
714
715
716
		case irms_auxiliary:
		case irms_data:
		case irms_internal_boolean:
Michael Beck's avatar
Michael Beck committed
717
718
719
720
721
			break;
		}
		break;

	case irms_reference:
722
		if (get_mode_sort(dst_mode) == irms_int_number) {
723
724
			sc_word *buffer = ALLOCAN(sc_word, sc_value_length);
			memcpy(buffer, src->value, sc_value_length);
725
726
727
728
729
730
			unsigned bits = get_mode_size_bits(src->mode);
			if (mode_is_signed(src->mode)) {
				sc_sign_extend(buffer, bits);
			} else {
				sc_zero_extend(buffer, bits);
			}
731
			return get_tarval_overflow(buffer, src->length, dst_mode);
732
		}
Michael Beck's avatar
Michael Beck committed
733
		break;
734
735
736
737

	case irms_auxiliary:
	case irms_data:
	case irms_internal_boolean:
738
		return tarval_bad;
Michael Beck's avatar
Michael Beck committed
739
740
741
	}

	return tarval_bad;
742
}
Christian Schäfer's avatar
Christian Schäfer committed
743

Matthias Braun's avatar
Matthias Braun committed
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
ir_tarval *tarval_bitcast(ir_tarval *src, ir_mode *dst_mode)
{
	const ir_mode *src_mode = get_tarval_mode(src);
	if (src_mode == dst_mode)
		return src;
	unsigned size = get_mode_size_bits(src_mode);
	assert(get_mode_size_bits(dst_mode) == size);
	assert(size % 8 == 0);

	size_t         buf_len = size / 8;
	unsigned char *buffer  = ALLOCAN(unsigned char, buf_len);
	switch (get_mode_arithmetic(src_mode)) {
	case irma_ieee754:
	case irma_x86_extended_float:
		fc_val_to_bytes((const fp_value*)src->value, buffer);
		break;
	case irma_twos_complement:
		sc_val_to_bytes((const sc_word*)src->value, buffer, buf_len);
		break;
	default:
		panic("unexpected arithmetic mode in tarval_bitcast");
	}

	return new_tarval_from_bytes(buffer, dst_mode, false);
}

Matthias Braun's avatar
Matthias Braun committed
770
ir_tarval *tarval_not(ir_tarval *a)
771
{
Michael Beck's avatar
Michael Beck committed
772
	switch (get_mode_sort(a->mode)) {
773
	case irms_reference:
Matthias Braun's avatar
Matthias Braun committed
774
	case irms_int_number: {
775
		sc_word *buffer = ALLOCAN(sc_word, sc_value_length);
Michael Beck's avatar
Michael Beck committed
776
777
		sc_not(a->value, buffer);
		return get_tarval(buffer, a->length, a->mode);
Matthias Braun's avatar
Matthias Braun committed
778
	}
Michael Beck's avatar
Michael Beck committed
779
780
781
782
783
784
785
786

	case irms_internal_boolean:
		if (a == tarval_b_true)
			return tarval_b_false;
		if (a == tarval_b_false)
			return tarval_b_true;
		return tarval_bad;

787
788
789
	case irms_auxiliary:
	case irms_data:
	case irms_float_number:
790
		panic("bitwise negation is only allowed for integer and boolean");
Michael Beck's avatar
Michael Beck committed
791
	}
792
	panic("invalid mode sort");
793
794
}

Matthias Braun's avatar
Matthias Braun committed
795
ir_tarval *tarval_neg(ir_tarval *a)
796
{
Michael Beck's avatar
Michael Beck committed
797
	assert(mode_is_num(a->mode)); /* negation only for numerical values */
798

Michael Beck's avatar
Michael Beck committed
799
	/* note: negation is allowed even for unsigned modes. */
Christian Schäfer's avatar
Christian Schäfer committed
800

Michael Beck's avatar
Michael Beck committed
801
	switch (get_mode_sort(a->mode)) {
802
803
	case irms_int_number:
	case irms_reference: {
804
		sc_word *buffer = ALLOCAN(sc_word, sc_value_length);
Michael Beck's avatar
Michael Beck committed
805
806
		sc_neg(a->value, buffer);
		return get_tarval_overflow(buffer, a->length, a->mode);
Matthias Braun's avatar
Matthias Braun committed
807
	}
Christian Schäfer's avatar
Christian Schäfer committed
808

Michael Beck's avatar
Michael Beck committed
809
	case irms_float_number:
810
		fc_neg((const fp_value*) a->value, NULL);
Michael Beck's avatar
Michael Beck committed
811
		return get_tarval_overflow(fc_get_buffer(), fc_get_buffer_length(), a->mode);
Christian Schäfer's avatar
Christian Schäfer committed
812

813
814
815
	case irms_auxiliary:
	case irms_data:
	case irms_internal_boolean:
Michael Beck's avatar
Michael Beck committed
816
817
		return tarval_bad;
	}
818
	panic("invalid mode sort");
Christian Schäfer's avatar
Christian Schäfer committed
819
820
}

Matthias Braun's avatar
Matthias Braun committed
821
ir_tarval *tarval_add(ir_tarval *a, ir_tarval *b)
822
{
823
824
825
826
	if (mode_is_reference(a->mode) && a->mode != b->mode) {
		b = tarval_convert_to(b, a->mode);
	} else if (mode_is_reference(b->mode) && b->mode != a->mode) {
		a = tarval_convert_to(a, b->mode);
827
828
829
830
	}

	assert(a->mode == b->mode);

Michael Beck's avatar
Michael Beck committed
831
	switch (get_mode_sort(a->mode)) {
832
	case irms_reference:
Matthias Braun's avatar
Matthias Braun committed
833
	case irms_int_number: {
Michael Beck's avatar
Michael Beck committed
834
		/* modes of a,b are equal, so result has mode of a as this might be the character */
835
		sc_word *buffer = ALLOCAN(sc_word, sc_value_length);
Michael Beck's avatar
Michael Beck committed
836
		sc_add(a->value, b->value, buffer);
837
		return get_tarval_overflow(buffer, a->length, a->mode);
Matthias Braun's avatar
Matthias Braun committed
838
	}
Michael Beck's avatar
Michael Beck committed
839
840

	case irms_float_number:
841
		fc_add((const fp_value*) a->value, (const fp_value*) b->value, NULL);
842
		return get_tarval_overflow(fc_get_buffer(), fc_get_buffer_length(), a->mode);
Michael Beck's avatar
Michael Beck committed
843

844
845
846
	case irms_auxiliary:
	case irms_data:
	case irms_internal_boolean:
Michael Beck's avatar
Michael Beck committed
847
848
		return tarval_bad;
	}
849
	panic("invalid mode sort");
Christian Schäfer's avatar
Christian Schäfer committed
850
851
}

Matthias Braun's avatar
Matthias Braun committed
852
ir_tarval *tarval_sub(ir_tarval *a, ir_tarval *b, ir_mode *dst_mode)
853
{
854
	if (dst_mode != NULL) {
855
		if (a->mode != dst_mode)
856
			a = tarval_convert_to(a, dst_mode);
857
		if (b->mode != dst_mode)
858
			b = tarval_convert_to(b, dst_mode);
859
860
861
	}
	assert(a->mode == b->mode);

Michael Beck's avatar
Michael Beck committed
862
	switch (get_mode_sort(a->mode)) {
863
	case irms_reference:
Matthias Braun's avatar
Matthias Braun committed
864
	case irms_int_number: {
Michael Beck's avatar
Michael Beck committed
865
		/* modes of a,b are equal, so result has mode of a as this might be the character */
866
		sc_word *buffer = ALLOCAN(sc_word, sc_value_length);
Michael Beck's avatar
Michael Beck committed
867
		sc_sub(a->value, b->value, buffer);
868
		return get_tarval_overflow(buffer, a->length, a->mode);