10
10
This file is part of LibVEX, a library for dynamic binary
11
11
instrumentation and translation.
13
Copyright (C) 2004-2005 OpenWorks LLP. All rights reserved.
13
Copyright (C) 2004-2006 OpenWorks LLP. All rights reserved.
15
15
This library is made available under a dual licensing scheme.
156
156
/* Does this instruction mention a particular reg? */
157
157
static Bool instrMentionsReg (
158
void (*getRegUsage) (HRegUsage*, HInstr*),
158
void (*getRegUsage) (HRegUsage*, HInstr*, Bool),
164
165
HRegUsage reg_usage;
165
(*getRegUsage)(®_usage, instr);
166
(*getRegUsage)(®_usage, instr, mode64);
166
167
for (i = 0; i < reg_usage.n_used; i++)
167
168
if (reg_usage.hreg[i] == r)
184
185
spill, or -1 if none was found. */
186
187
Int findMostDistantlyMentionedVReg (
187
void (*getRegUsage) (HRegUsage*, HInstr*),
188
void (*getRegUsage) (HRegUsage*, HInstr*, Bool),
188
189
HInstrArray* instrs_in,
189
190
Int search_from_instr,
190
191
RRegState* state,
201
203
vassert(state[k].disp == Bound);
202
204
for (m = search_from_instr; m < instrs_in->arr_used; m++) {
203
205
if (instrMentionsReg(getRegUsage,
204
instrs_in->arr[m], state[k].vreg))
206
instrs_in->arr[m], state[k].vreg, mode64))
207
209
if (m > furthest) {
259
261
/* Return True iff the given insn is a reg-reg move, in which
260
262
case also return the src and dst regs. */
261
Bool (*isMove) (HInstr*, HReg*, HReg*),
263
Bool (*isMove) ( HInstr*, HReg*, HReg* ),
263
265
/* Get info about register usage in this insn. */
264
void (*getRegUsage) (HRegUsage*, HInstr*),
266
void (*getRegUsage) ( HRegUsage*, HInstr*, Bool ),
266
268
/* Apply a reg-reg mapping to an insn. */
267
void (*mapRegs) (HRegRemap*, HInstr*),
269
void (*mapRegs) ( HRegRemap*, HInstr*, Bool ),
269
271
/* Return an insn to spill/restore a real reg to a spill slot
271
HInstr* (*genSpill) ( HReg, Int ),
272
HInstr* (*genReload) ( HReg, Int ),
273
HInstr* (*genSpill) ( HReg, Int, Bool ),
274
HInstr* (*genReload) ( HReg, Int, Bool ),
275
277
/* For debug printing only. */
276
void (*ppInstr) ( HInstr* ),
277
void (*ppReg) ( HReg )
278
void (*ppInstr) ( HInstr*, Bool ),
279
void (*ppReg) ( HReg ),
280
285
# define N_SPILL64S (LibVEX_N_SPILL_BYTES / 8)
452
457
for (ii = 0; ii < instrs_in->arr_used; ii++) {
454
(*getRegUsage)( ®_usage, instrs_in->arr[ii] );
459
(*getRegUsage)( ®_usage, instrs_in->arr[ii], mode64 );
457
462
vex_printf("\n%d stage1: ", ii);
458
(*ppInstr)(instrs_in->arr[ii]);
463
(*ppInstr)(instrs_in->arr[ii], mode64);
459
464
vex_printf("\n");
460
465
ppHRegUsage(®_usage);
472
477
k = hregNumber(vreg);
473
478
if (k < 0 || k >= n_vregs) {
474
479
vex_printf("\n");
475
(*ppInstr)(instrs_in->arr[ii]);
480
(*ppInstr)(instrs_in->arr[ii], mode64);
476
481
vex_printf("\n");
477
482
vex_printf("vreg %d, n_vregs %d\n", k, n_vregs);
478
483
vpanic("doRegisterAllocation: out-of-range vreg");
561
566
(*ppReg)(available_real_regs[k]);
562
567
vex_printf("\n");
563
568
vex_printf("\nOFFENDING instr = ");
564
(*ppInstr)(instrs_in->arr[ii]);
569
(*ppInstr)(instrs_in->arr[ii], mode64);
565
570
vex_printf("\n");
566
571
vpanic("doRegisterAllocation: "
567
572
"first event for rreg is Read");
574
579
(*ppReg)(available_real_regs[k]);
575
580
vex_printf("\n");
576
581
vex_printf("\nOFFENDING instr = ");
577
(*ppInstr)(instrs_in->arr[ii]);
582
(*ppInstr)(instrs_in->arr[ii], mode64);
578
583
vex_printf("\n");
579
584
vpanic("doRegisterAllocation: "
580
585
"first event for rreg is Modify");
786
791
# if DEBUG_REGALLOC
787
792
vex_printf("\n====----====---- Insn %d ----====----====\n", ii);
788
793
vex_printf("---- ");
789
(*ppInstr)(instrs_in->arr[ii]);
794
(*ppInstr)(instrs_in->arr[ii], mode64);
790
795
vex_printf("\n\nInitial state:\n");
792
797
vex_printf("\n");
1009
1014
if (vreg_lrs[m].dead_before > ii) {
1010
1015
vassert(vreg_lrs[m].reg_class != HRcINVALID);
1011
1016
EMIT_INSTR( (*genSpill)( rreg_state[k].rreg,
1012
vreg_lrs[m].spill_offset ) );
1017
vreg_lrs[m].spill_offset,
1015
1021
rreg_state[k].disp = Unavail;
1033
1039
We also build up the final vreg->rreg mapping to be applied
1034
1040
to the insn. */
1036
(*getRegUsage)( ®_usage, instrs_in->arr[ii] );
1042
(*getRegUsage)( ®_usage, instrs_in->arr[ii], mode64 );
1038
1044
initHRegRemap(&remap);
1098
1104
if (reg_usage.mode[j] != HRmWrite) {
1099
1105
vassert(vreg_lrs[m].reg_class != HRcINVALID);
1100
1106
EMIT_INSTR( (*genReload)( rreg_state[k].rreg,
1101
vreg_lrs[m].spill_offset ) );
1107
vreg_lrs[m].spill_offset,
1133
1140
of consequent reloads required. */
1135
1142
= findMostDistantlyMentionedVReg (
1136
getRegUsage, instrs_in, ii+1, rreg_state, n_rregs );
1143
getRegUsage, instrs_in, ii+1, rreg_state, n_rregs, mode64 );
1138
1145
if (spillee == -1) {
1139
1146
/* Hmmmmm. There don't appear to be any spill candidates.
1161
1168
vassert(vreg_lrs[m].dead_before > ii);
1162
1169
vassert(vreg_lrs[m].reg_class != HRcINVALID);
1163
1170
EMIT_INSTR( (*genSpill)( rreg_state[spillee].rreg,
1164
vreg_lrs[m].spill_offset ) );
1171
vreg_lrs[m].spill_offset,
1166
1174
/* Update the rreg_state to reflect the new assignment for this
1177
1185
if (reg_usage.mode[j] != HRmWrite) {
1178
1186
vassert(vreg_lrs[m].reg_class != HRcINVALID);
1179
1187
EMIT_INSTR( (*genReload)( rreg_state[spillee].rreg,
1180
vreg_lrs[m].spill_offset ) );
1188
vreg_lrs[m].spill_offset,
1183
1192
/* So after much twisting and turning, we have vreg mapped to
1200
1209
/* NOTE, DESTRUCTIVELY MODIFIES instrs_in->arr[ii]. */
1201
(*mapRegs)( &remap, instrs_in->arr[ii] );
1210
(*mapRegs)( &remap, instrs_in->arr[ii], mode64 );
1202
1211
EMIT_INSTR( instrs_in->arr[ii] );
1204
1213
# if DEBUG_REGALLOC