Bug 497723 - forgot to restore callgrind output cleanup
[valgrind.git] / VEX / priv / host_generic_regs.c
blob803950a5d7decdf7ad17de613d0f7e1f8052b495
2 /*---------------------------------------------------------------*/
3 /*--- begin host_generic_regs.c ---*/
4 /*---------------------------------------------------------------*/
6 /*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
10 Copyright (C) 2004-2017 OpenWorks LLP
11 info@open-works.net
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, see <http://www.gnu.org/licenses/>.
26 The GNU General Public License is contained in the file COPYING.
28 Neither the names of the U.S. Department of Energy nor the
29 University of California nor the names of its contributors may be
30 used to endorse or promote products derived from this software
31 without prior written permission.
34 #include "libvex_basictypes.h"
35 #include "libvex.h"
37 #include "main_util.h"
38 #include "host_generic_regs.h"
41 /*---------------------------------------------------------*/
42 /*--- Representing HOST REGISTERS ---*/
43 /*---------------------------------------------------------*/
45 void ppHRegClass ( HRegClass hrc )
47 switch (hrc) {
48 case HRcInt32: vex_printf("HRcInt32"); break;
49 case HRcInt64: vex_printf("HRcInt64"); break;
50 case HRcFlt32: vex_printf("HRcFlt32"); break;
51 case HRcFlt64: vex_printf("HRcFlt64"); break;
52 case HRcVec64: vex_printf("HRcVec64"); break;
53 case HRcVec128: vex_printf("HRcVec128"); break;
54 default: vpanic("ppHRegClass");
58 /* Generic printing for registers. */
59 UInt ppHReg ( HReg r )
61 if (hregIsInvalid(r)) {
62 return vex_printf("HReg_INVALID");
64 const Bool isV = hregIsVirtual(r);
65 const HChar* maybe_v = isV ? "v" : "";
66 const UInt regNN = isV ? hregIndex(r) : hregEncoding(r);
67 /* For real registers, we show the encoding. But the encoding is
68 always zero for virtual registers, so that's pointless -- hence
69 show the index number instead. */
70 switch (hregClass(r)) {
71 case HRcInt32: return vex_printf("%%%sr%u", maybe_v, regNN);
72 case HRcInt64: return vex_printf("%%%sR%u", maybe_v, regNN);
73 case HRcFlt32: return vex_printf("%%%sF%u", maybe_v, regNN);
74 case HRcFlt64: return vex_printf("%%%sD%u", maybe_v, regNN);
75 case HRcVec64: return vex_printf("%%%sv%u", maybe_v, regNN);
76 case HRcVec128: return vex_printf("%%%sV%u", maybe_v, regNN);
77 default: vpanic("ppHReg");
82 /*---------------------------------------------------------*/
83 /*--- Real register Universes. ---*/
84 /*---------------------------------------------------------*/
86 void RRegUniverse__init ( /*OUT*/RRegUniverse* univ )
88 *univ = (RRegUniverse){};
89 univ->size = 0;
90 univ->allocable = 0;
91 for (UInt i = 0; i < N_RREGUNIVERSE_REGS; i++) {
92 univ->regs[i] = INVALID_HREG;
95 for (UInt i = 0; i <= HrcLAST; i++) {
96 univ->allocable_start[i] = N_RREGUNIVERSE_REGS;
97 univ->allocable_end[i] = N_RREGUNIVERSE_REGS;
101 void RRegUniverse__check_is_sane ( const RRegUniverse* univ )
103 /* Check Real-Register-Universe invariants. All of these are
104 important. */
105 vassert(univ->size > 0);
106 vassert(univ->size <= N_RREGUNIVERSE_REGS);
107 vassert(univ->allocable <= univ->size);
108 for (UInt i = 0; i < univ->size; i++) {
109 HReg reg = univ->regs[i];
110 vassert(!hregIsInvalid(reg));
111 vassert(!hregIsVirtual(reg));
112 vassert(hregIndex(reg) == i);
114 for (UInt i = univ->size; i < N_RREGUNIVERSE_REGS; i++) {
115 HReg reg = univ->regs[i];
116 vassert(hregIsInvalid(reg));
119 /* Determine register classes used and if they form contiguous range. */
120 Bool regclass_used[HrcLAST + 1];
121 for (UInt i = 0; i <= HrcLAST; i++) {
122 regclass_used[i] = False;
125 for (UInt i = 0; i < univ->allocable; i++) {
126 HReg reg = univ->regs[i];
127 HRegClass regclass = hregClass(reg);
128 if (!regclass_used[regclass]) {
129 regclass_used[regclass] = True;
133 UInt regs_visited = 0;
134 for (UInt i = 0; i <= HrcLAST; i++) {
135 if (regclass_used[i]) {
136 for (UInt j = univ->allocable_start[i];
137 j <= univ->allocable_end[i]; j++) {
138 vassert(hregClass(univ->regs[j]) == i);
139 regs_visited += 1;
144 vassert(regs_visited == univ->allocable);
148 /*---------------------------------------------------------*/
149 /*--- Helpers for recording reg usage (for reg-alloc) ---*/
150 /*---------------------------------------------------------*/
152 void ppHRegUsage ( const RRegUniverse* univ, HRegUsage* tab )
154 /* This is going to fail miserably if N_RREGUNIVERSE_REGS exceeds
155 64. So let's cause it to fail in an obvious way. */
156 vassert(N_RREGUNIVERSE_REGS == 64);
158 vex_printf("HRegUsage {\n");
159 /* First print the real regs */
160 for (UInt i = 0; i < N_RREGUNIVERSE_REGS; i++) {
161 Bool rRd = (tab->rRead & (1ULL << i)) != 0;
162 Bool rWr = (tab->rWritten & (1ULL << i)) != 0;
163 const HChar* str = "Modify ";
164 /**/ if (!rRd && !rWr) { continue; }
165 else if ( rRd && !rWr) { str = "Read "; }
166 else if (!rRd && rWr) { str = "Write "; }
167 /* else "Modify" is correct */
168 vex_printf(" %s ", str);
169 ppHReg(univ->regs[i]);
170 vex_printf("\n");
172 /* and now the virtual registers */
173 for (UInt i = 0; i < tab->n_vRegs; i++) {
174 const HChar* str = NULL;
175 switch (tab->vMode[i]) {
176 case HRmRead: str = "Read "; break;
177 case HRmWrite: str = "Write "; break;
178 case HRmModify: str = "Modify "; break;
179 default: vpanic("ppHRegUsage");
181 vex_printf(" %s ", str);
182 ppHReg(tab->vRegs[i]);
183 vex_printf("\n");
185 if (tab->isRegRegMove) {
186 vex_printf(" (is a reg-reg move)\n");
188 vex_printf("}\n");
192 /* Add a register to a usage table. Combines incoming read uses with
193 existing write uses into a modify use, and vice versa. Does not
194 create duplicate entries -- each reg is only mentioned once.
196 void addHRegUse ( HRegUsage* tab, HRegMode mode, HReg reg )
198 /* Because real and virtual registers are represented differently,
199 they have completely different paths here. */
200 if (LIKELY(hregIsVirtual(reg))) {
201 /* Virtual register */
202 UInt i;
203 /* Find it ... */
204 for (i = 0; i < tab->n_vRegs; i++)
205 if (sameHReg(tab->vRegs[i], reg))
206 break;
207 if (i == tab->n_vRegs) {
208 /* Not found, add new entry. */
209 vassert(tab->n_vRegs < N_HREGUSAGE_VREGS);
210 tab->vRegs[tab->n_vRegs] = reg;
211 tab->vMode[tab->n_vRegs] = mode;
212 tab->n_vRegs++;
213 } else {
214 /* Found: combine or ignore. */
215 /* This is a greatest-lower-bound operation in the poset:
221 Need to do: tab->mode[i] = GLB(tab->mode, mode). In this
222 case very simple -- if tab->mode[i] != mode then result must
223 be M.
225 if (tab->vMode[i] == mode) {
226 /* duplicate, ignore */
227 } else {
228 tab->vMode[i] = HRmModify;
231 } else {
232 /* Real register */
233 UInt ix = hregIndex(reg);
234 vassert(ix < N_RREGUNIVERSE_REGS);
235 ULong mask = 1ULL << ix;
236 switch (mode) {
237 case HRmRead: tab->rRead |= mask; break;
238 case HRmWrite: tab->rWritten |= mask; break;
239 case HRmModify: tab->rRead |= mask; tab->rWritten |= mask; break;
240 default: vassert(0);
245 Bool HRegUsage__contains ( const HRegUsage* tab, HReg reg )
247 vassert(!hregIsInvalid(reg));
248 if (hregIsVirtual(reg)) {
249 for (UInt i = 0; i < tab->n_vRegs; i++) {
250 if (sameHReg(reg, tab->vRegs[i]))
251 return True;
253 return False;
254 } else {
255 UInt ix = hregIndex(reg);
256 vassert(ix < N_RREGUNIVERSE_REGS);
257 ULong mentioned = tab->rRead | tab->rWritten;
258 return (mentioned & (1ULL << ix)) != 0;
260 /*NOTREACHED*/
264 /*---------------------------------------------------------*/
265 /*--- Indicating register remappings (for reg-alloc) ---*/
266 /*---------------------------------------------------------*/
268 void ppHRegRemap ( HRegRemap* map )
270 Int i;
271 vex_printf("HRegRemap {\n");
272 for (i = 0; i < map->n_used; i++) {
273 vex_printf(" ");
274 ppHReg(map->orig[i]);
275 vex_printf(" --> ");
276 ppHReg(map->replacement[i]);
277 vex_printf("\n");
279 vex_printf("}\n");
283 void addToHRegRemap ( HRegRemap* map, HReg orig, HReg replacement )
285 Int i;
286 for (i = 0; i < map->n_used; i++)
287 if (sameHReg(map->orig[i], orig))
288 vpanic("addToHRegMap: duplicate entry");
289 if (!hregIsVirtual(orig))
290 vpanic("addToHRegMap: orig is not a vreg");
291 if (hregIsVirtual(replacement))
292 vpanic("addToHRegMap: replacement is a vreg");
294 vassert(map->n_used+1 < N_HREG_REMAP);
295 map->orig[map->n_used] = orig;
296 map->replacement[map->n_used] = replacement;
297 map->n_used++;
301 HReg lookupHRegRemap ( HRegRemap* map, HReg orig )
303 Int i;
304 if (!hregIsVirtual(orig))
305 return orig;
306 for (i = 0; i < map->n_used; i++)
307 if (sameHReg(map->orig[i], orig))
308 return map->replacement[i];
309 vpanic("lookupHRegRemap: not found");
313 /*---------------------------------------------------------*/
314 /*--- Abstract instructions ---*/
315 /*---------------------------------------------------------*/
317 HInstrArray* newHInstrArray ( void )
319 HInstrArray* ha = LibVEX_Alloc_inline(sizeof(HInstrArray));
320 ha->arr_size = 4;
321 ha->arr_used = 0;
322 ha->arr = LibVEX_Alloc_inline(ha->arr_size * sizeof(HInstr*));
323 ha->n_vregs = 0;
324 return ha;
327 __attribute__((noinline))
328 void addHInstr_SLOW ( HInstrArray* ha, HInstr* instr )
330 vassert(ha->arr_used == ha->arr_size);
331 Int i;
332 HInstr** arr2 = LibVEX_Alloc_inline(ha->arr_size * 2 * sizeof(HInstr*));
333 for (i = 0; i < ha->arr_size; i++) {
334 arr2[i] = ha->arr[i];
336 ha->arr_size *= 2;
337 ha->arr = arr2;
338 addHInstr(ha, instr);
342 /*---------------------------------------------------------*/
343 /*--- C-Call return-location actions ---*/
344 /*---------------------------------------------------------*/
346 void ppRetLoc ( RetLoc ska )
348 switch (ska.pri) {
349 case RLPri_INVALID:
350 vex_printf("RLPri_INVALID"); return;
351 case RLPri_None:
352 vex_printf("RLPri_None"); return;
353 case RLPri_Int:
354 vex_printf("RLPri_Int"); return;
355 case RLPri_2Int:
356 vex_printf("RLPri_2Int"); return;
357 case RLPri_V128SpRel:
358 vex_printf("RLPri_V128SpRel(%d)", ska.spOff); return;
359 case RLPri_V256SpRel:
360 vex_printf("RLPri_V256SpRel(%d)", ska.spOff); return;
361 default:
362 vpanic("ppRetLoc");
367 /*---------------------------------------------------------------*/
368 /*--- end host_generic_regs.c ---*/
369 /*---------------------------------------------------------------*/