Revision 641d5fbe tcg/tcg.c
b/tcg/tcg.c | ||
---|---|---|
269 | 269 |
int i; |
270 | 270 |
tcg_pool_reset(s); |
271 | 271 |
s->nb_temps = s->nb_globals; |
272 |
for(i = 0; i < TCG_TYPE_COUNT; i++)
|
|
272 |
for(i = 0; i < (TCG_TYPE_COUNT * 2); i++)
|
|
273 | 273 |
s->first_free_temp[i] = -1; |
274 | 274 |
s->labels = tcg_malloc(sizeof(TCGLabel) * TCG_MAX_LABELS); |
275 | 275 |
s->nb_labels = 0; |
... | ... | |
407 | 407 |
return MAKE_TCGV(idx); |
408 | 408 |
} |
409 | 409 |
|
410 |
TCGv tcg_temp_new(TCGType type)
|
|
410 |
TCGv tcg_temp_new_internal(TCGType type, int temp_local)
|
|
411 | 411 |
{ |
412 | 412 |
TCGContext *s = &tcg_ctx; |
413 | 413 |
TCGTemp *ts; |
414 |
int idx; |
|
414 |
int idx, k;
|
|
415 | 415 |
|
416 |
idx = s->first_free_temp[type]; |
|
416 |
k = type; |
|
417 |
if (temp_local) |
|
418 |
k += TCG_TYPE_COUNT; |
|
419 |
idx = s->first_free_temp[k]; |
|
417 | 420 |
if (idx != -1) { |
418 | 421 |
/* There is already an available temp with the |
419 | 422 |
right type */ |
420 | 423 |
ts = &s->temps[idx]; |
421 |
s->first_free_temp[type] = ts->next_free_temp;
|
|
424 |
s->first_free_temp[k] = ts->next_free_temp;
|
|
422 | 425 |
ts->temp_allocated = 1; |
426 |
assert(ts->temp_local == temp_local); |
|
423 | 427 |
} else { |
424 | 428 |
idx = s->nb_temps; |
425 | 429 |
#if TCG_TARGET_REG_BITS == 32 |
... | ... | |
429 | 433 |
ts->base_type = type; |
430 | 434 |
ts->type = TCG_TYPE_I32; |
431 | 435 |
ts->temp_allocated = 1; |
436 |
ts->temp_local = temp_local; |
|
432 | 437 |
ts->name = NULL; |
433 | 438 |
ts++; |
434 | 439 |
ts->base_type = TCG_TYPE_I32; |
435 | 440 |
ts->type = TCG_TYPE_I32; |
436 | 441 |
ts->temp_allocated = 1; |
442 |
ts->temp_local = temp_local; |
|
437 | 443 |
ts->name = NULL; |
438 | 444 |
s->nb_temps += 2; |
439 | 445 |
} else |
... | ... | |
444 | 450 |
ts->base_type = type; |
445 | 451 |
ts->type = type; |
446 | 452 |
ts->temp_allocated = 1; |
453 |
ts->temp_local = temp_local; |
|
447 | 454 |
ts->name = NULL; |
448 | 455 |
s->nb_temps++; |
449 | 456 |
} |
... | ... | |
456 | 463 |
TCGContext *s = &tcg_ctx; |
457 | 464 |
TCGTemp *ts; |
458 | 465 |
int idx = GET_TCGV(arg); |
459 |
TCGType type;
|
|
466 |
int k;
|
|
460 | 467 |
|
461 | 468 |
assert(idx >= s->nb_globals && idx < s->nb_temps); |
462 | 469 |
ts = &s->temps[idx]; |
463 | 470 |
assert(ts->temp_allocated != 0); |
464 | 471 |
ts->temp_allocated = 0; |
465 |
type = ts->base_type; |
|
466 |
ts->next_free_temp = s->first_free_temp[type]; |
|
467 |
s->first_free_temp[type] = idx; |
|
472 |
k = ts->base_type; |
|
473 |
if (ts->temp_local) |
|
474 |
k += TCG_TYPE_COUNT; |
|
475 |
ts->next_free_temp = s->first_free_temp[k]; |
|
476 |
s->first_free_temp[k] = idx; |
|
468 | 477 |
} |
469 | 478 |
|
470 | 479 |
|
... | ... | |
683 | 692 |
if (idx < s->nb_globals) { |
684 | 693 |
pstrcpy(buf, buf_size, ts->name); |
685 | 694 |
} else { |
686 |
snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals); |
|
695 |
if (ts->temp_local) |
|
696 |
snprintf(buf, buf_size, "loc%d", idx - s->nb_globals); |
|
697 |
else |
|
698 |
snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals); |
|
687 | 699 |
} |
688 | 700 |
return buf; |
689 | 701 |
} |
... | ... | |
987 | 999 |
} |
988 | 1000 |
} |
989 | 1001 |
|
990 |
/* liveness analysis: end of basic block: globals are live, temps are dead */ |
|
991 |
static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps) |
|
1002 |
/* liveness analysis: end of function: globals are live, temps are |
|
1003 |
dead. */ |
|
1004 |
/* XXX: at this stage, not used as there would be little gains because |
|
1005 |
most TBs end with a conditional jump. */ |
|
1006 |
static inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps) |
|
992 | 1007 |
{ |
993 | 1008 |
memset(dead_temps, 0, s->nb_globals); |
994 | 1009 |
memset(dead_temps + s->nb_globals, 1, s->nb_temps - s->nb_globals); |
995 | 1010 |
} |
996 | 1011 |
|
1012 |
/* liveness analysis: end of basic block: globals are live, temps are |
|
1013 |
dead, local temps are live. */ |
|
1014 |
static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps) |
|
1015 |
{ |
|
1016 |
int i; |
|
1017 |
TCGTemp *ts; |
|
1018 |
|
|
1019 |
memset(dead_temps, 0, s->nb_globals); |
|
1020 |
ts = &s->temps[s->nb_globals]; |
|
1021 |
for(i = s->nb_globals; i < s->nb_temps; i++) { |
|
1022 |
if (ts->temp_local) |
|
1023 |
dead_temps[i] = 0; |
|
1024 |
else |
|
1025 |
dead_temps[i] = 1; |
|
1026 |
ts++; |
|
1027 |
} |
|
1028 |
} |
|
1029 |
|
|
997 | 1030 |
/* Liveness analysis : update the opc_dead_iargs array to tell if a |
998 | 1031 |
given input arguments is dead. Instructions updating dead |
999 | 1032 |
temporaries are removed. */ |
... | ... | |
1366 | 1399 |
tcg_abort(); |
1367 | 1400 |
} |
1368 | 1401 |
|
1402 |
/* save a temporary to memory. 'allocated_regs' is used in case a |
|
1403 |
temporary registers needs to be allocated to store a constant. */ |
|
1404 |
static void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs) |
|
1405 |
{ |
|
1406 |
TCGTemp *ts; |
|
1407 |
int reg; |
|
1408 |
|
|
1409 |
ts = &s->temps[temp]; |
|
1410 |
if (!ts->fixed_reg) { |
|
1411 |
switch(ts->val_type) { |
|
1412 |
case TEMP_VAL_REG: |
|
1413 |
tcg_reg_free(s, ts->reg); |
|
1414 |
break; |
|
1415 |
case TEMP_VAL_DEAD: |
|
1416 |
ts->val_type = TEMP_VAL_MEM; |
|
1417 |
break; |
|
1418 |
case TEMP_VAL_CONST: |
|
1419 |
reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], |
|
1420 |
allocated_regs); |
|
1421 |
if (!ts->mem_allocated) |
|
1422 |
temp_allocate_frame(s, temp); |
|
1423 |
tcg_out_movi(s, ts->type, reg, ts->val); |
|
1424 |
tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset); |
|
1425 |
ts->val_type = TEMP_VAL_MEM; |
|
1426 |
break; |
|
1427 |
case TEMP_VAL_MEM: |
|
1428 |
break; |
|
1429 |
default: |
|
1430 |
tcg_abort(); |
|
1431 |
} |
|
1432 |
} |
|
1433 |
} |
|
1434 |
|
|
1369 | 1435 |
/* save globals to their cannonical location and assume they can be |
1370 | 1436 |
modified be the following code. 'allocated_regs' is used in case a |
1371 | 1437 |
temporary registers needs to be allocated to store a constant. */ |
1372 | 1438 |
static void save_globals(TCGContext *s, TCGRegSet allocated_regs) |
1373 | 1439 |
{ |
1374 |
TCGTemp *ts; |
|
1375 |
int i, reg; |
|
1440 |
int i; |
|
1376 | 1441 |
|
1377 | 1442 |
for(i = 0; i < s->nb_globals; i++) { |
1378 |
ts = &s->temps[i]; |
|
1379 |
if (!ts->fixed_reg) { |
|
1380 |
switch(ts->val_type) { |
|
1381 |
case TEMP_VAL_REG: |
|
1382 |
tcg_reg_free(s, ts->reg); |
|
1383 |
break; |
|
1384 |
case TEMP_VAL_DEAD: |
|
1385 |
ts->val_type = TEMP_VAL_MEM; |
|
1386 |
break; |
|
1387 |
case TEMP_VAL_CONST: |
|
1388 |
reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], |
|
1389 |
allocated_regs); |
|
1390 |
tcg_out_movi(s, ts->type, reg, ts->val); |
|
1391 |
tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset); |
|
1392 |
ts->val_type = TEMP_VAL_MEM; |
|
1393 |
break; |
|
1394 |
case TEMP_VAL_MEM: |
|
1395 |
break; |
|
1396 |
default: |
|
1397 |
tcg_abort(); |
|
1398 |
} |
|
1399 |
} |
|
1443 |
temp_save(s, i, allocated_regs); |
|
1400 | 1444 |
} |
1401 | 1445 |
} |
1402 | 1446 |
|
... | ... | |
1409 | 1453 |
|
1410 | 1454 |
for(i = s->nb_globals; i < s->nb_temps; i++) { |
1411 | 1455 |
ts = &s->temps[i]; |
1412 |
if (ts->val_type == TEMP_VAL_REG) { |
|
1413 |
s->reg_to_temp[ts->reg] = -1; |
|
1456 |
if (ts->temp_local) { |
|
1457 |
temp_save(s, i, allocated_regs); |
|
1458 |
} else { |
|
1459 |
if (ts->val_type == TEMP_VAL_REG) { |
|
1460 |
s->reg_to_temp[ts->reg] = -1; |
|
1461 |
} |
|
1462 |
ts->val_type = TEMP_VAL_DEAD; |
|
1414 | 1463 |
} |
1415 |
ts->val_type = TEMP_VAL_DEAD; |
|
1416 | 1464 |
} |
1417 | 1465 |
|
1418 | 1466 |
save_globals(s, allocated_regs); |
Also available in: Unified diff