blob: 30a0cce17cba83a4a8ef4c82847c4e5fced4d0bb [file] [log] [blame]
weidendoa17f2a32006-03-20 10:27:30 +00001
2/*--------------------------------------------------------------------*/
3/*--- Callgrind ---*/
4/*--- main.c ---*/
5/*--------------------------------------------------------------------*/
6
7/*
8 This file is part of Callgrind, a Valgrind tool for call graph
9 profiling programs.
10
sewardj0f157dd2013-10-18 14:27:36 +000011 Copyright (C) 2002-2013, Josef Weidendorfer (Josef.Weidendorfer@gmx.de)
weidendoa17f2a32006-03-20 10:27:30 +000012
njn9a0cba42007-04-15 22:15:57 +000013 This tool is derived from and contains code from Cachegrind
sewardj0f157dd2013-10-18 14:27:36 +000014 Copyright (C) 2002-2013 Nicholas Nethercote (njn@valgrind.org)
weidendoa17f2a32006-03-20 10:27:30 +000015
16 This program is free software; you can redistribute it and/or
17 modify it under the terms of the GNU General Public License as
18 published by the Free Software Foundation; either version 2 of the
19 License, or (at your option) any later version.
20
21 This program is distributed in the hope that it will be useful, but
22 WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 General Public License for more details.
25
26 You should have received a copy of the GNU General Public License
27 along with this program; if not, write to the Free Software
28 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
29 02111-1307, USA.
30
31 The GNU General Public License is contained in the file COPYING.
32*/
33
34#include "config.h"
35#include "callgrind.h"
36#include "global.h"
37
sewardje7a50822011-04-20 11:54:32 +000038#include "pub_tool_threadstate.h"
sewardj3b290482011-05-06 21:02:55 +000039#include "pub_tool_gdbserver.h"
weidendoa17f2a32006-03-20 10:27:30 +000040
weidendo320705f2010-07-02 19:56:23 +000041#include "cg_branchpred.c"
42
weidendoa17f2a32006-03-20 10:27:30 +000043/*------------------------------------------------------------*/
44/*--- Global variables ---*/
45/*------------------------------------------------------------*/
46
47/* for all threads */
48CommandLineOptions CLG_(clo);
49Statistics CLG_(stat);
50Bool CLG_(instrument_state) = True; /* Instrumentation on ? */
51
52/* thread and signal handler specific */
53exec_state CLG_(current_state);
54
sewardjc4ebde32012-06-03 23:10:55 +000055/* min of L1 and LL cache line sizes. This only gets set to a
56 non-zero value if we are doing cache simulation. */
57Int CLG_(min_line_size) = 0;
58
weidendoa17f2a32006-03-20 10:27:30 +000059
60/*------------------------------------------------------------*/
61/*--- Statistics ---*/
62/*------------------------------------------------------------*/
63
64static void CLG_(init_statistics)(Statistics* s)
65{
66 s->call_counter = 0;
67 s->jcnd_counter = 0;
68 s->jump_counter = 0;
69 s->rec_call_counter = 0;
70 s->ret_counter = 0;
71 s->bb_executions = 0;
72
73 s->context_counter = 0;
74 s->bb_retranslations = 0;
75
76 s->distinct_objs = 0;
77 s->distinct_files = 0;
78 s->distinct_fns = 0;
79 s->distinct_contexts = 0;
80 s->distinct_bbs = 0;
81 s->distinct_bbccs = 0;
82 s->distinct_instrs = 0;
83 s->distinct_skips = 0;
84
85 s->bb_hash_resizes = 0;
86 s->bbcc_hash_resizes = 0;
87 s->jcc_hash_resizes = 0;
88 s->cxt_hash_resizes = 0;
89 s->fn_array_resizes = 0;
90 s->call_stack_resizes = 0;
91 s->fn_stack_resizes = 0;
92
93 s->full_debug_BBs = 0;
94 s->file_line_debug_BBs = 0;
95 s->fn_name_debug_BBs = 0;
96 s->no_debug_BBs = 0;
97 s->bbcc_lru_misses = 0;
98 s->jcc_lru_misses = 0;
99 s->cxt_lru_misses = 0;
100 s->bbcc_clones = 0;
101}
102
103
weidendoa17f2a32006-03-20 10:27:30 +0000104/*------------------------------------------------------------*/
weidendoaeb86222010-06-09 22:33:02 +0000105/*--- Simple callbacks (not cache similator) ---*/
106/*------------------------------------------------------------*/
107
108VG_REGPARM(1)
109static void log_global_event(InstrInfo* ii)
110{
111 ULong* cost_Bus;
112
weidendo320705f2010-07-02 19:56:23 +0000113 CLG_DEBUG(6, "log_global_event: Ir %#lx/%u\n",
weidendoaeb86222010-06-09 22:33:02 +0000114 CLG_(bb_base) + ii->instr_offset, ii->instr_size);
115
116 if (!CLG_(current_state).collect) return;
117
weidendo320705f2010-07-02 19:56:23 +0000118 CLG_ASSERT( (ii->eventset->mask & (1u<<EG_BUS))>0 );
119
weidendoaeb86222010-06-09 22:33:02 +0000120 CLG_(current_state).cost[ fullOffset(EG_BUS) ]++;
121
122 if (CLG_(current_state).nonskipped)
123 cost_Bus = CLG_(current_state).nonskipped->skipped + fullOffset(EG_BUS);
124 else
125 cost_Bus = CLG_(cost_base) + ii->cost_offset + ii->eventset->offset[EG_BUS];
126 cost_Bus[0]++;
127}
128
129
weidendo320705f2010-07-02 19:56:23 +0000130/* For branches, we consult two different predictors, one which
131 predicts taken/untaken for conditional branches, and the other
132 which predicts the branch target address for indirect branches
133 (jump-to-register style ones). */
134
135static VG_REGPARM(2)
136void log_cond_branch(InstrInfo* ii, Word taken)
137{
138 Bool miss;
139 Int fullOffset_Bc;
140 ULong* cost_Bc;
141
142 CLG_DEBUG(6, "log_cond_branch: Ir %#lx, taken %lu\n",
143 CLG_(bb_base) + ii->instr_offset, taken);
144
145 miss = 1 & do_cond_branch_predict(CLG_(bb_base) + ii->instr_offset, taken);
146
147 if (!CLG_(current_state).collect) return;
148
149 CLG_ASSERT( (ii->eventset->mask & (1u<<EG_BC))>0 );
150
151 if (CLG_(current_state).nonskipped)
152 cost_Bc = CLG_(current_state).nonskipped->skipped + fullOffset(EG_BC);
153 else
154 cost_Bc = CLG_(cost_base) + ii->cost_offset + ii->eventset->offset[EG_BC];
155
156 fullOffset_Bc = fullOffset(EG_BC);
157 CLG_(current_state).cost[ fullOffset_Bc ]++;
158 cost_Bc[0]++;
159 if (miss) {
160 CLG_(current_state).cost[ fullOffset_Bc+1 ]++;
161 cost_Bc[1]++;
162 }
163}
164
165static VG_REGPARM(2)
166void log_ind_branch(InstrInfo* ii, UWord actual_dst)
167{
168 Bool miss;
169 Int fullOffset_Bi;
170 ULong* cost_Bi;
171
172 CLG_DEBUG(6, "log_ind_branch: Ir %#lx, dst %#lx\n",
173 CLG_(bb_base) + ii->instr_offset, actual_dst);
174
175 miss = 1 & do_ind_branch_predict(CLG_(bb_base) + ii->instr_offset, actual_dst);
176
177 if (!CLG_(current_state).collect) return;
178
179 CLG_ASSERT( (ii->eventset->mask & (1u<<EG_BI))>0 );
180
181 if (CLG_(current_state).nonskipped)
182 cost_Bi = CLG_(current_state).nonskipped->skipped + fullOffset(EG_BI);
183 else
184 cost_Bi = CLG_(cost_base) + ii->cost_offset + ii->eventset->offset[EG_BI];
185
186 fullOffset_Bi = fullOffset(EG_BI);
187 CLG_(current_state).cost[ fullOffset_Bi ]++;
188 cost_Bi[0]++;
189 if (miss) {
190 CLG_(current_state).cost[ fullOffset_Bi+1 ]++;
191 cost_Bi[1]++;
192 }
193}
194
weidendoaeb86222010-06-09 22:33:02 +0000195/*------------------------------------------------------------*/
weidendo0a1951d2009-06-15 00:16:36 +0000196/*--- Instrumentation structures and event queue handling ---*/
weidendoa17f2a32006-03-20 10:27:30 +0000197/*------------------------------------------------------------*/
198
weidendo0a1951d2009-06-15 00:16:36 +0000199/* Maintain an ordered list of memory events which are outstanding, in
200 the sense that no IR has yet been generated to do the relevant
201 helper calls. The BB is scanned top to bottom and memory events
202 are added to the end of the list, merging with the most recent
203 notified event where possible (Dw immediately following Dr and
204 having the same size and EA can be merged).
weidendoa17f2a32006-03-20 10:27:30 +0000205
weidendo0a1951d2009-06-15 00:16:36 +0000206 This merging is done so that for architectures which have
207 load-op-store instructions (x86, amd64), the insn is treated as if
208 it makes just one memory reference (a modify), rather than two (a
209 read followed by a write at the same address).
210
211 At various points the list will need to be flushed, that is, IR
212 generated from it. That must happen before any possible exit from
213 the block (the end, or an IRStmt_Exit). Flushing also takes place
214 when there is no space to add a new event.
215
216 If we require the simulation statistics to be up to date with
217 respect to possible memory exceptions, then the list would have to
218 be flushed before each memory reference. That would however lose
219 performance by inhibiting event-merging during flushing.
220
221 Flushing the list consists of walking it start to end and emitting
222 instrumentation IR for each event, in the order in which they
223 appear. It may be possible to emit a single call for two adjacent
224 events in order to reduce the number of helper function calls made.
225 For example, it could well be profitable to handle two adjacent Ir
226 events with a single helper call. */
227
228typedef
229 IRExpr
230 IRAtom;
231
232typedef
233 enum {
234 Ev_Ir, // Instruction read
235 Ev_Dr, // Data read
236 Ev_Dw, // Data write
237 Ev_Dm, // Data modify (read then write)
weidendo320705f2010-07-02 19:56:23 +0000238 Ev_Bc, // branch conditional
239 Ev_Bi, // branch indirect (to unknown destination)
weidendoaeb86222010-06-09 22:33:02 +0000240 Ev_G // Global bus event
weidendo0a1951d2009-06-15 00:16:36 +0000241 }
242 EventTag;
243
244typedef
245 struct {
246 EventTag tag;
247 InstrInfo* inode;
248 union {
249 struct {
250 } Ir;
251 struct {
252 IRAtom* ea;
253 Int szB;
254 } Dr;
255 struct {
256 IRAtom* ea;
257 Int szB;
258 } Dw;
259 struct {
260 IRAtom* ea;
261 Int szB;
262 } Dm;
weidendo320705f2010-07-02 19:56:23 +0000263 struct {
264 IRAtom* taken; /* :: Ity_I1 */
265 } Bc;
266 struct {
267 IRAtom* dst;
268 } Bi;
weidendoaeb86222010-06-09 22:33:02 +0000269 struct {
270 } G;
weidendo0a1951d2009-06-15 00:16:36 +0000271 } Ev;
272 }
273 Event;
274
275static void init_Event ( Event* ev ) {
276 VG_(memset)(ev, 0, sizeof(Event));
weidendoa17f2a32006-03-20 10:27:30 +0000277}
278
weidendo0a1951d2009-06-15 00:16:36 +0000279static IRAtom* get_Event_dea ( Event* ev ) {
280 switch (ev->tag) {
281 case Ev_Dr: return ev->Ev.Dr.ea;
282 case Ev_Dw: return ev->Ev.Dw.ea;
283 case Ev_Dm: return ev->Ev.Dm.ea;
284 default: tl_assert(0);
285 }
286}
weidendoa17f2a32006-03-20 10:27:30 +0000287
weidendo0a1951d2009-06-15 00:16:36 +0000288static Int get_Event_dszB ( Event* ev ) {
289 switch (ev->tag) {
290 case Ev_Dr: return ev->Ev.Dr.szB;
291 case Ev_Dw: return ev->Ev.Dw.szB;
292 case Ev_Dm: return ev->Ev.Dm.szB;
293 default: tl_assert(0);
294 }
295}
296
297
298/* Up to this many unnotified events are allowed. Number is
299 arbitrary. Larger numbers allow more event merging to occur, but
300 potentially induce more spilling due to extending live ranges of
301 address temporaries. */
302#define N_EVENTS 16
303
304
305/* A struct which holds all the running state during instrumentation.
306 Mostly to avoid passing loads of parameters everywhere. */
307typedef struct {
308 /* The current outstanding-memory-event list. */
309 Event events[N_EVENTS];
310 Int events_used;
311
312 /* The array of InstrInfo's is part of BB struct. */
313 BB* bb;
314
315 /* BB seen before (ie. re-instrumentation) */
316 Bool seen_before;
317
318 /* Number InstrInfo bins 'used' so far. */
319 UInt ii_index;
320
321 // current offset of guest instructions from BB start
322 UInt instr_offset;
323
324 /* The output SB being constructed. */
325 IRSB* sbOut;
326} ClgState;
327
328
329static void showEvent ( Event* ev )
330{
331 switch (ev->tag) {
332 case Ev_Ir:
333 VG_(printf)("Ir (InstrInfo %p) at +%d\n",
334 ev->inode, ev->inode->instr_offset);
335 break;
336 case Ev_Dr:
337 VG_(printf)("Dr (InstrInfo %p) at +%d %d EA=",
338 ev->inode, ev->inode->instr_offset, ev->Ev.Dr.szB);
339 ppIRExpr(ev->Ev.Dr.ea);
340 VG_(printf)("\n");
341 break;
342 case Ev_Dw:
343 VG_(printf)("Dw (InstrInfo %p) at +%d %d EA=",
344 ev->inode, ev->inode->instr_offset, ev->Ev.Dw.szB);
345 ppIRExpr(ev->Ev.Dw.ea);
346 VG_(printf)("\n");
347 break;
348 case Ev_Dm:
349 VG_(printf)("Dm (InstrInfo %p) at +%d %d EA=",
350 ev->inode, ev->inode->instr_offset, ev->Ev.Dm.szB);
351 ppIRExpr(ev->Ev.Dm.ea);
352 VG_(printf)("\n");
353 break;
weidendo320705f2010-07-02 19:56:23 +0000354 case Ev_Bc:
355 VG_(printf)("Bc %p GA=", ev->inode);
356 ppIRExpr(ev->Ev.Bc.taken);
357 VG_(printf)("\n");
358 break;
359 case Ev_Bi:
360 VG_(printf)("Bi %p DST=", ev->inode);
361 ppIRExpr(ev->Ev.Bi.dst);
362 VG_(printf)("\n");
363 break;
weidendoaeb86222010-06-09 22:33:02 +0000364 case Ev_G:
365 VG_(printf)("G %p\n", ev->inode);
366 break;
weidendo0a1951d2009-06-15 00:16:36 +0000367 default:
368 tl_assert(0);
369 break;
370 }
371}
372
373/* Generate code for all outstanding memory events, and mark the queue
374 empty. Code is generated into cgs->sbOut, and this activity
375 'consumes' slots in cgs->bb. */
376
377static void flushEvents ( ClgState* clgs )
378{
379 Int i, regparms, inew;
florian25f6c572012-10-21 02:55:56 +0000380 const HChar* helperName;
weidendo0a1951d2009-06-15 00:16:36 +0000381 void* helperAddr;
382 IRExpr** argv;
383 IRExpr* i_node_expr;
384 IRDirty* di;
385 Event* ev;
386 Event* ev2;
387 Event* ev3;
388
389 if (!clgs->seen_before) {
390 // extend event sets as needed
391 // available sets: D0 Dr
392 for(i=0; i<clgs->events_used; i++) {
393 ev = &clgs->events[i];
394 switch(ev->tag) {
395 case Ev_Ir:
396 // Ir event always is first for a guest instruction
397 CLG_ASSERT(ev->inode->eventset == 0);
weidendo5bba5252010-06-09 22:32:53 +0000398 ev->inode->eventset = CLG_(sets).base;
weidendo0a1951d2009-06-15 00:16:36 +0000399 break;
400 case Ev_Dr:
weidendo320705f2010-07-02 19:56:23 +0000401 // extend event set by Dr counters
weidendo5bba5252010-06-09 22:32:53 +0000402 ev->inode->eventset = CLG_(add_event_group)(ev->inode->eventset,
403 EG_DR);
weidendo0a1951d2009-06-15 00:16:36 +0000404 break;
405 case Ev_Dw:
406 case Ev_Dm:
weidendo320705f2010-07-02 19:56:23 +0000407 // extend event set by Dw counters
weidendo5bba5252010-06-09 22:32:53 +0000408 ev->inode->eventset = CLG_(add_event_group)(ev->inode->eventset,
409 EG_DW);
weidendo0a1951d2009-06-15 00:16:36 +0000410 break;
weidendo320705f2010-07-02 19:56:23 +0000411 case Ev_Bc:
412 // extend event set by Bc counters
413 ev->inode->eventset = CLG_(add_event_group)(ev->inode->eventset,
414 EG_BC);
415 break;
416 case Ev_Bi:
417 // extend event set by Bi counters
418 ev->inode->eventset = CLG_(add_event_group)(ev->inode->eventset,
419 EG_BI);
420 break;
weidendoaeb86222010-06-09 22:33:02 +0000421 case Ev_G:
weidendo320705f2010-07-02 19:56:23 +0000422 // extend event set by Bus counter
weidendoaeb86222010-06-09 22:33:02 +0000423 ev->inode->eventset = CLG_(add_event_group)(ev->inode->eventset,
424 EG_BUS);
425 break;
weidendo0a1951d2009-06-15 00:16:36 +0000426 default:
427 tl_assert(0);
428 }
429 }
430 }
431
432 for(i = 0; i < clgs->events_used; i = inew) {
433
434 helperName = NULL;
435 helperAddr = NULL;
436 argv = NULL;
437 regparms = 0;
438
439 /* generate IR to notify event i and possibly the ones
440 immediately following it. */
441 tl_assert(i >= 0 && i < clgs->events_used);
442
443 ev = &clgs->events[i];
444 ev2 = ( i < clgs->events_used-1 ? &clgs->events[i+1] : NULL );
445 ev3 = ( i < clgs->events_used-2 ? &clgs->events[i+2] : NULL );
446
447 CLG_DEBUGIF(5) {
448 VG_(printf)(" flush ");
449 showEvent( ev );
450 }
451
452 i_node_expr = mkIRExpr_HWord( (HWord)ev->inode );
453
454 /* Decide on helper fn to call and args to pass it, and advance
455 i appropriately.
456 Dm events have same effect as Dw events */
457 switch (ev->tag) {
458 case Ev_Ir:
459 /* Merge an Ir with a following Dr. */
460 if (ev2 && ev2->tag == Ev_Dr) {
461 /* Why is this true? It's because we're merging an Ir
462 with a following Dr. The Ir derives from the
463 instruction's IMark and the Dr from data
464 references which follow it. In short it holds
465 because each insn starts with an IMark, hence an
466 Ev_Ir, and so these Dr must pertain to the
467 immediately preceding Ir. Same applies to analogous
468 assertions in the subsequent cases. */
469 tl_assert(ev2->inode == ev->inode);
470 helperName = CLG_(cachesim).log_1I1Dr_name;
471 helperAddr = CLG_(cachesim).log_1I1Dr;
472 argv = mkIRExprVec_3( i_node_expr,
473 get_Event_dea(ev2),
474 mkIRExpr_HWord( get_Event_dszB(ev2) ) );
475 regparms = 3;
476 inew = i+2;
477 }
478 /* Merge an Ir with a following Dw/Dm. */
479 else
480 if (ev2 && (ev2->tag == Ev_Dw || ev2->tag == Ev_Dm)) {
481 tl_assert(ev2->inode == ev->inode);
482 helperName = CLG_(cachesim).log_1I1Dw_name;
483 helperAddr = CLG_(cachesim).log_1I1Dw;
484 argv = mkIRExprVec_3( i_node_expr,
485 get_Event_dea(ev2),
486 mkIRExpr_HWord( get_Event_dszB(ev2) ) );
487 regparms = 3;
488 inew = i+2;
489 }
490 /* Merge an Ir with two following Irs. */
491 else
492 if (ev2 && ev3 && ev2->tag == Ev_Ir && ev3->tag == Ev_Ir) {
493 helperName = CLG_(cachesim).log_3I0D_name;
494 helperAddr = CLG_(cachesim).log_3I0D;
495 argv = mkIRExprVec_3( i_node_expr,
496 mkIRExpr_HWord( (HWord)ev2->inode ),
497 mkIRExpr_HWord( (HWord)ev3->inode ) );
498 regparms = 3;
499 inew = i+3;
500 }
501 /* Merge an Ir with one following Ir. */
502 else
503 if (ev2 && ev2->tag == Ev_Ir) {
504 helperName = CLG_(cachesim).log_2I0D_name;
505 helperAddr = CLG_(cachesim).log_2I0D;
506 argv = mkIRExprVec_2( i_node_expr,
507 mkIRExpr_HWord( (HWord)ev2->inode ) );
508 regparms = 2;
509 inew = i+2;
510 }
511 /* No merging possible; emit as-is. */
512 else {
513 helperName = CLG_(cachesim).log_1I0D_name;
514 helperAddr = CLG_(cachesim).log_1I0D;
515 argv = mkIRExprVec_1( i_node_expr );
516 regparms = 1;
517 inew = i+1;
518 }
519 break;
520 case Ev_Dr:
521 /* Data read or modify */
weidendoa17f2a32006-03-20 10:27:30 +0000522 helperName = CLG_(cachesim).log_0I1Dr_name;
523 helperAddr = CLG_(cachesim).log_0I1Dr;
weidendo0a1951d2009-06-15 00:16:36 +0000524 argv = mkIRExprVec_3( i_node_expr,
525 get_Event_dea(ev),
526 mkIRExpr_HWord( get_Event_dszB(ev) ) );
527 regparms = 3;
528 inew = i+1;
529 break;
530 case Ev_Dw:
531 case Ev_Dm:
532 /* Data write */
weidendoa17f2a32006-03-20 10:27:30 +0000533 helperName = CLG_(cachesim).log_0I1Dw_name;
534 helperAddr = CLG_(cachesim).log_0I1Dw;
weidendo0a1951d2009-06-15 00:16:36 +0000535 argv = mkIRExprVec_3( i_node_expr,
536 get_Event_dea(ev),
537 mkIRExpr_HWord( get_Event_dszB(ev) ) );
538 regparms = 3;
539 inew = i+1;
540 break;
weidendo320705f2010-07-02 19:56:23 +0000541 case Ev_Bc:
542 /* Conditional branch */
543 helperName = "log_cond_branch";
544 helperAddr = &log_cond_branch;
545 argv = mkIRExprVec_2( i_node_expr, ev->Ev.Bc.taken );
546 regparms = 2;
547 inew = i+1;
548 break;
549 case Ev_Bi:
550 /* Branch to an unknown destination */
551 helperName = "log_ind_branch";
552 helperAddr = &log_ind_branch;
553 argv = mkIRExprVec_2( i_node_expr, ev->Ev.Bi.dst );
554 regparms = 2;
555 inew = i+1;
556 break;
weidendoaeb86222010-06-09 22:33:02 +0000557 case Ev_G:
558 /* Global bus event (CAS, LOCK-prefix, LL-SC, etc) */
559 helperName = "log_global_event";
560 helperAddr = &log_global_event;
561 argv = mkIRExprVec_1( i_node_expr );
562 regparms = 1;
563 inew = i+1;
564 break;
weidendo0a1951d2009-06-15 00:16:36 +0000565 default:
566 tl_assert(0);
567 }
weidendoa17f2a32006-03-20 10:27:30 +0000568
weidendo0a1951d2009-06-15 00:16:36 +0000569 CLG_DEBUGIF(5) {
570 if (inew > i+1) {
571 VG_(printf)(" merge ");
572 showEvent( ev2 );
573 }
574 if (inew > i+2) {
575 VG_(printf)(" merge ");
576 showEvent( ev3 );
577 }
578 if (helperAddr)
579 VG_(printf)(" call %s (%p)\n",
580 helperName, helperAddr);
581 }
weidendoa17f2a32006-03-20 10:27:30 +0000582
weidendo0a1951d2009-06-15 00:16:36 +0000583 /* helper could be unset depending on the simulator used */
584 if (helperAddr == 0) continue;
weidendoa17f2a32006-03-20 10:27:30 +0000585
weidendo0a1951d2009-06-15 00:16:36 +0000586 /* Add the helper. */
587 tl_assert(helperName);
588 tl_assert(helperAddr);
589 tl_assert(argv);
590 di = unsafeIRDirty_0_N( regparms,
591 helperName, VG_(fnptr_to_fnentry)( helperAddr ),
592 argv );
593 addStmtToIRSB( clgs->sbOut, IRStmt_Dirty(di) );
weidendoa17f2a32006-03-20 10:27:30 +0000594 }
595
weidendo0a1951d2009-06-15 00:16:36 +0000596 clgs->events_used = 0;
597}
weidendoa17f2a32006-03-20 10:27:30 +0000598
weidendo0a1951d2009-06-15 00:16:36 +0000599static void addEvent_Ir ( ClgState* clgs, InstrInfo* inode )
600{
601 Event* evt;
602 tl_assert(clgs->seen_before || (inode->eventset == 0));
603 if (!CLG_(clo).simulate_cache) return;
weidendoa17f2a32006-03-20 10:27:30 +0000604
weidendo0a1951d2009-06-15 00:16:36 +0000605 if (clgs->events_used == N_EVENTS)
606 flushEvents(clgs);
607 tl_assert(clgs->events_used >= 0 && clgs->events_used < N_EVENTS);
608 evt = &clgs->events[clgs->events_used];
609 init_Event(evt);
610 evt->tag = Ev_Ir;
611 evt->inode = inode;
612 clgs->events_used++;
613}
weidendoa17f2a32006-03-20 10:27:30 +0000614
weidendo0a1951d2009-06-15 00:16:36 +0000615static
616void addEvent_Dr ( ClgState* clgs, InstrInfo* inode, Int datasize, IRAtom* ea )
617{
618 Event* evt;
619 tl_assert(isIRAtom(ea));
sewardjc4ebde32012-06-03 23:10:55 +0000620 tl_assert(datasize >= 1);
weidendo0a1951d2009-06-15 00:16:36 +0000621 if (!CLG_(clo).simulate_cache) return;
sewardjc4ebde32012-06-03 23:10:55 +0000622 tl_assert(datasize <= CLG_(min_line_size));
weidendoc8e76152006-05-27 15:30:58 +0000623
weidendo0a1951d2009-06-15 00:16:36 +0000624 if (clgs->events_used == N_EVENTS)
625 flushEvents(clgs);
626 tl_assert(clgs->events_used >= 0 && clgs->events_used < N_EVENTS);
627 evt = &clgs->events[clgs->events_used];
628 init_Event(evt);
629 evt->tag = Ev_Dr;
630 evt->inode = inode;
631 evt->Ev.Dr.szB = datasize;
632 evt->Ev.Dr.ea = ea;
633 clgs->events_used++;
634}
weidendoc8e76152006-05-27 15:30:58 +0000635
weidendo0a1951d2009-06-15 00:16:36 +0000636static
637void addEvent_Dw ( ClgState* clgs, InstrInfo* inode, Int datasize, IRAtom* ea )
638{
639 Event* lastEvt;
640 Event* evt;
641 tl_assert(isIRAtom(ea));
sewardjc4ebde32012-06-03 23:10:55 +0000642 tl_assert(datasize >= 1);
weidendo0a1951d2009-06-15 00:16:36 +0000643 if (!CLG_(clo).simulate_cache) return;
sewardjc4ebde32012-06-03 23:10:55 +0000644 tl_assert(datasize <= CLG_(min_line_size));
weidendoc8e76152006-05-27 15:30:58 +0000645
weidendo0a1951d2009-06-15 00:16:36 +0000646 /* Is it possible to merge this write with the preceding read? */
647 lastEvt = &clgs->events[clgs->events_used-1];
648 if (clgs->events_used > 0
649 && lastEvt->tag == Ev_Dr
650 && lastEvt->Ev.Dr.szB == datasize
651 && lastEvt->inode == inode
652 && eqIRAtom(lastEvt->Ev.Dr.ea, ea))
653 {
654 lastEvt->tag = Ev_Dm;
655 return;
656 }
weidendoc8e76152006-05-27 15:30:58 +0000657
weidendo0a1951d2009-06-15 00:16:36 +0000658 /* No. Add as normal. */
659 if (clgs->events_used == N_EVENTS)
660 flushEvents(clgs);
661 tl_assert(clgs->events_used >= 0 && clgs->events_used < N_EVENTS);
662 evt = &clgs->events[clgs->events_used];
663 init_Event(evt);
664 evt->tag = Ev_Dw;
665 evt->inode = inode;
666 evt->Ev.Dw.szB = datasize;
667 evt->Ev.Dw.ea = ea;
668 clgs->events_used++;
669}
670
weidendoaeb86222010-06-09 22:33:02 +0000671static
sewardjcafe5052013-01-17 14:24:35 +0000672void addEvent_D_guarded ( ClgState* clgs, InstrInfo* inode,
673 Int datasize, IRAtom* ea, IRAtom* guard,
674 Bool isWrite )
675{
676 tl_assert(isIRAtom(ea));
677 tl_assert(guard);
678 tl_assert(isIRAtom(guard));
679 tl_assert(datasize >= 1);
680 if (!CLG_(clo).simulate_cache) return;
681 tl_assert(datasize <= CLG_(min_line_size));
682
683 /* Adding guarded memory actions and merging them with the existing
684 queue is too complex. Simply flush the queue and add this
685 action immediately. Since guarded loads and stores are pretty
686 rare, this is not thought likely to cause any noticeable
687 performance loss as a result of the loss of event-merging
688 opportunities. */
689 tl_assert(clgs->events_used >= 0);
690 flushEvents(clgs);
691 tl_assert(clgs->events_used == 0);
692 /* Same as case Ev_Dw / case Ev_Dr in flushEvents, except with guard */
693 IRExpr* i_node_expr;
694 const HChar* helperName;
695 void* helperAddr;
696 IRExpr** argv;
697 Int regparms;
698 IRDirty* di;
699 i_node_expr = mkIRExpr_HWord( (HWord)inode );
700 helperName = isWrite ? CLG_(cachesim).log_0I1Dw_name
701 : CLG_(cachesim).log_0I1Dr_name;
702 helperAddr = isWrite ? CLG_(cachesim).log_0I1Dw
703 : CLG_(cachesim).log_0I1Dr;
704 argv = mkIRExprVec_3( i_node_expr,
705 ea, mkIRExpr_HWord( datasize ) );
706 regparms = 3;
707 di = unsafeIRDirty_0_N(
708 regparms,
709 helperName, VG_(fnptr_to_fnentry)( helperAddr ),
710 argv );
711 di->guard = guard;
712 addStmtToIRSB( clgs->sbOut, IRStmt_Dirty(di) );
713}
714
715static
weidendo320705f2010-07-02 19:56:23 +0000716void addEvent_Bc ( ClgState* clgs, InstrInfo* inode, IRAtom* guard )
717{
718 Event* evt;
719 tl_assert(isIRAtom(guard));
720 tl_assert(typeOfIRExpr(clgs->sbOut->tyenv, guard)
721 == (sizeof(HWord)==4 ? Ity_I32 : Ity_I64));
722 if (!CLG_(clo).simulate_branch) return;
723
724 if (clgs->events_used == N_EVENTS)
725 flushEvents(clgs);
726 tl_assert(clgs->events_used >= 0 && clgs->events_used < N_EVENTS);
727 evt = &clgs->events[clgs->events_used];
728 init_Event(evt);
729 evt->tag = Ev_Bc;
730 evt->inode = inode;
731 evt->Ev.Bc.taken = guard;
732 clgs->events_used++;
733}
734
735static
736void addEvent_Bi ( ClgState* clgs, InstrInfo* inode, IRAtom* whereTo )
737{
738 Event* evt;
739 tl_assert(isIRAtom(whereTo));
740 tl_assert(typeOfIRExpr(clgs->sbOut->tyenv, whereTo)
741 == (sizeof(HWord)==4 ? Ity_I32 : Ity_I64));
742 if (!CLG_(clo).simulate_branch) return;
743
744 if (clgs->events_used == N_EVENTS)
745 flushEvents(clgs);
746 tl_assert(clgs->events_used >= 0 && clgs->events_used < N_EVENTS);
747 evt = &clgs->events[clgs->events_used];
748 init_Event(evt);
749 evt->tag = Ev_Bi;
750 evt->inode = inode;
751 evt->Ev.Bi.dst = whereTo;
752 clgs->events_used++;
753}
754
755static
weidendoaeb86222010-06-09 22:33:02 +0000756void addEvent_G ( ClgState* clgs, InstrInfo* inode )
757{
758 Event* evt;
759 if (!CLG_(clo).collect_bus) return;
weidendo320705f2010-07-02 19:56:23 +0000760
weidendoaeb86222010-06-09 22:33:02 +0000761 if (clgs->events_used == N_EVENTS)
762 flushEvents(clgs);
763 tl_assert(clgs->events_used >= 0 && clgs->events_used < N_EVENTS);
764 evt = &clgs->events[clgs->events_used];
765 init_Event(evt);
766 evt->tag = Ev_G;
767 evt->inode = inode;
768 clgs->events_used++;
769}
770
weidendo0a1951d2009-06-15 00:16:36 +0000771/* Initialise or check (if already seen before) an InstrInfo for next insn.
772 We only can set instr_offset/instr_size here. The required event set and
773 resulting cost offset depend on events (Ir/Dr/Dw/Dm) in guest
774 instructions. The event set is extended as required on flush of the event
775 queue (when Dm events were determined), cost offsets are determined at
776 end of BB instrumentation. */
777static
778InstrInfo* next_InstrInfo ( ClgState* clgs, UInt instr_size )
779{
780 InstrInfo* ii;
781 tl_assert(clgs->ii_index >= 0);
782 tl_assert(clgs->ii_index < clgs->bb->instr_count);
783 ii = &clgs->bb->instr[ clgs->ii_index ];
784
785 if (clgs->seen_before) {
786 CLG_ASSERT(ii->instr_offset == clgs->instr_offset);
787 CLG_ASSERT(ii->instr_size == instr_size);
weidendoa17f2a32006-03-20 10:27:30 +0000788 }
789 else {
weidendo0a1951d2009-06-15 00:16:36 +0000790 ii->instr_offset = clgs->instr_offset;
791 ii->instr_size = instr_size;
792 ii->cost_offset = 0;
793 ii->eventset = 0;
weidendoa17f2a32006-03-20 10:27:30 +0000794 }
795
weidendo0a1951d2009-06-15 00:16:36 +0000796 clgs->ii_index++;
797 clgs->instr_offset += instr_size;
798 CLG_(stat).distinct_instrs++;
weidendoa17f2a32006-03-20 10:27:30 +0000799
weidendo0a1951d2009-06-15 00:16:36 +0000800 return ii;
weidendoa17f2a32006-03-20 10:27:30 +0000801}
802
weidendo0a1951d2009-06-15 00:16:36 +0000803// return total number of cost values needed for this BB
804static
805UInt update_cost_offsets( ClgState* clgs )
806{
807 Int i;
808 InstrInfo* ii;
809 UInt cost_offset = 0;
810
811 CLG_ASSERT(clgs->bb->instr_count == clgs->ii_index);
812 for(i=0; i<clgs->ii_index; i++) {
813 ii = &clgs->bb->instr[i];
814 if (clgs->seen_before) {
815 CLG_ASSERT(ii->cost_offset == cost_offset);
816 } else
817 ii->cost_offset = cost_offset;
818 cost_offset += ii->eventset ? ii->eventset->size : 0;
819 }
820
821 return cost_offset;
822}
823
824/*------------------------------------------------------------*/
825/*--- Instrumentation ---*/
826/*------------------------------------------------------------*/
827
weidendoa17f2a32006-03-20 10:27:30 +0000828#if defined(VG_BIGENDIAN)
829# define CLGEndness Iend_BE
830#elif defined(VG_LITTLEENDIAN)
831# define CLGEndness Iend_LE
832#else
833# error "Unknown endianness"
834#endif
835
836static
837Addr IRConst2Addr(IRConst* con)
838{
839 Addr addr;
840
841 if (sizeof(Addr) == 4) {
842 CLG_ASSERT( con->tag == Ico_U32 );
843 addr = con->Ico.U32;
844 }
845 else if (sizeof(Addr) == 8) {
846 CLG_ASSERT( con->tag == Ico_U64 );
847 addr = con->Ico.U64;
848 }
849 else
850 VG_(tool_panic)("Callgrind: invalid Addr type");
851
852 return addr;
853}
854
855/* First pass over a BB to instrument, counting instructions and jumps
856 * This is needed for the size of the BB struct to allocate
857 *
858 * Called from CLG_(get_bb)
859 */
weidendo0a1951d2009-06-15 00:16:36 +0000860void CLG_(collectBlockInfo)(IRSB* sbIn,
weidendoa17f2a32006-03-20 10:27:30 +0000861 /*INOUT*/ UInt* instrs,
862 /*INOUT*/ UInt* cjmps,
863 /*INOUT*/ Bool* cjmp_inverted)
864{
865 Int i;
866 IRStmt* st;
867 Addr instrAddr =0, jumpDst;
868 UInt instrLen = 0;
869 Bool toNextInstr = False;
870
871 // Ist_Exit has to be ignored in preamble code, before first IMark:
872 // preamble code is added by VEX for self modifying code, and has
873 // nothing to do with client code
874 Bool inPreamble = True;
875
weidendo0a1951d2009-06-15 00:16:36 +0000876 if (!sbIn) return;
weidendoa17f2a32006-03-20 10:27:30 +0000877
weidendo0a1951d2009-06-15 00:16:36 +0000878 for (i = 0; i < sbIn->stmts_used; i++) {
879 st = sbIn->stmts[i];
weidendoa17f2a32006-03-20 10:27:30 +0000880 if (Ist_IMark == st->tag) {
881 inPreamble = False;
882
florianf466eef2015-01-02 17:32:40 +0000883 instrAddr = st->Ist.IMark.addr;
weidendoa17f2a32006-03-20 10:27:30 +0000884 instrLen = st->Ist.IMark.len;
885
886 (*instrs)++;
887 toNextInstr = False;
888 }
889 if (inPreamble) continue;
890 if (Ist_Exit == st->tag) {
891 jumpDst = IRConst2Addr(st->Ist.Exit.dst);
892 toNextInstr = (jumpDst == instrAddr + instrLen);
weidendo0a1951d2009-06-15 00:16:36 +0000893
weidendoa17f2a32006-03-20 10:27:30 +0000894 (*cjmps)++;
895 }
896 }
897
898 /* if the last instructions of BB conditionally jumps to next instruction
899 * (= first instruction of next BB in memory), this is a inverted by VEX.
900 */
901 *cjmp_inverted = toNextInstr;
902}
903
904static
sewardj0b9d74a2006-12-24 02:24:11 +0000905void addConstMemStoreStmt( IRSB* bbOut, UWord addr, UInt val, IRType hWordTy)
weidendoa17f2a32006-03-20 10:27:30 +0000906{
sewardj0b9d74a2006-12-24 02:24:11 +0000907 addStmtToIRSB( bbOut,
weidendoa17f2a32006-03-20 10:27:30 +0000908 IRStmt_Store(CLGEndness,
909 IRExpr_Const(hWordTy == Ity_I32 ?
910 IRConst_U32( addr ) :
911 IRConst_U64( addr )),
912 IRExpr_Const(IRConst_U32(val)) ));
913}
914
weidendo0a1951d2009-06-15 00:16:36 +0000915
916/* add helper call to setup_bbcc, with pointer to BB struct as argument
917 *
918 * precondition for setup_bbcc:
919 * - jmps_passed has number of cond.jumps passed in last executed BB
920 * - current_bbcc has a pointer to the BBCC of the last executed BB
921 * Thus, if bbcc_jmpkind is != -1 (JmpNone),
922 * current_bbcc->bb->jmp_addr
923 * gives the address of the jump source.
924 *
925 * the setup does 2 things:
926 * - trace call:
927 * * Unwind own call stack, i.e sync our ESP with real ESP
928 * This is for ESP manipulation (longjmps, C++ exec handling) and RET
929 * * For CALLs or JMPs crossing objects, record call arg +
930 * push are on own call stack
931 *
932 * - prepare for cache log functions:
933 * set current_bbcc to BBCC that gets the costs for this BB execution
934 * attached
935 */
936static
937void addBBSetupCall(ClgState* clgs)
938{
939 IRDirty* di;
940 IRExpr *arg1, **argv;
941
942 arg1 = mkIRExpr_HWord( (HWord)clgs->bb );
943 argv = mkIRExprVec_1(arg1);
944 di = unsafeIRDirty_0_N( 1, "setup_bbcc",
945 VG_(fnptr_to_fnentry)( & CLG_(setup_bbcc) ),
946 argv);
947 addStmtToIRSB( clgs->sbOut, IRStmt_Dirty(di) );
948}
949
950
weidendoa17f2a32006-03-20 10:27:30 +0000951static
sewardj0b9d74a2006-12-24 02:24:11 +0000952IRSB* CLG_(instrument)( VgCallbackClosure* closure,
florian3c0c9472014-09-24 12:06:55 +0000953 IRSB* sbIn,
954 const VexGuestLayout* layout,
955 const VexGuestExtents* vge,
956 const VexArchInfo* archinfo_host,
weidendoa17f2a32006-03-20 10:27:30 +0000957 IRType gWordTy, IRType hWordTy )
958{
sewardjcafe5052013-01-17 14:24:35 +0000959 Int i;
960 IRStmt* st;
961 Addr origAddr;
weidendo0a1951d2009-06-15 00:16:36 +0000962 InstrInfo* curr_inode = NULL;
sewardjcafe5052013-01-17 14:24:35 +0000963 ClgState clgs;
964 UInt cJumps = 0;
965 IRTypeEnv* tyenv = sbIn->tyenv;
weidendoa17f2a32006-03-20 10:27:30 +0000966
967 if (gWordTy != hWordTy) {
968 /* We don't currently support this case. */
969 VG_(tool_panic)("host/guest word size mismatch");
970 }
971
972 // No instrumentation if it is switched off
973 if (! CLG_(instrument_state)) {
barta0b6b2c2008-07-07 06:49:24 +0000974 CLG_DEBUG(5, "instrument(BB %#lx) [Instrumentation OFF]\n",
weidendoa17f2a32006-03-20 10:27:30 +0000975 (Addr)closure->readdr);
weidendo0a1951d2009-06-15 00:16:36 +0000976 return sbIn;
weidendoa17f2a32006-03-20 10:27:30 +0000977 }
978
barta0b6b2c2008-07-07 06:49:24 +0000979 CLG_DEBUG(3, "+ instrument(BB %#lx)\n", (Addr)closure->readdr);
weidendoa17f2a32006-03-20 10:27:30 +0000980
sewardj0b9d74a2006-12-24 02:24:11 +0000981 /* Set up SB for instrumented IR */
weidendo0a1951d2009-06-15 00:16:36 +0000982 clgs.sbOut = deepCopyIRSBExceptStmts(sbIn);
weidendoa17f2a32006-03-20 10:27:30 +0000983
984 // Copy verbatim any IR preamble preceding the first IMark
985 i = 0;
weidendo0a1951d2009-06-15 00:16:36 +0000986 while (i < sbIn->stmts_used && sbIn->stmts[i]->tag != Ist_IMark) {
987 addStmtToIRSB( clgs.sbOut, sbIn->stmts[i] );
weidendoa17f2a32006-03-20 10:27:30 +0000988 i++;
989 }
990
991 // Get the first statement, and origAddr from it
weidendo0a1951d2009-06-15 00:16:36 +0000992 CLG_ASSERT(sbIn->stmts_used >0);
993 CLG_ASSERT(i < sbIn->stmts_used);
994 st = sbIn->stmts[i];
weidendoa17f2a32006-03-20 10:27:30 +0000995 CLG_ASSERT(Ist_IMark == st->tag);
weidendo0a1951d2009-06-15 00:16:36 +0000996
florianf466eef2015-01-02 17:32:40 +0000997 origAddr = st->Ist.IMark.addr + st->Ist.IMark.delta;
sewardj6ab7f2d2011-11-08 19:32:57 +0000998 CLG_ASSERT(origAddr == st->Ist.IMark.addr
999 + st->Ist.IMark.delta); // XXX: check no overflow
weidendoa17f2a32006-03-20 10:27:30 +00001000
weidendo0a1951d2009-06-15 00:16:36 +00001001 /* Get BB struct (creating if necessary).
weidendoa17f2a32006-03-20 10:27:30 +00001002 * JS: The hash table is keyed with orig_addr_noredir -- important!
1003 * JW: Why? If it is because of different chasing of the redirection,
1004 * this is not needed, as chasing is switched off in callgrind
1005 */
weidendo0a1951d2009-06-15 00:16:36 +00001006 clgs.bb = CLG_(get_bb)(origAddr, sbIn, &(clgs.seen_before));
weidendoa17f2a32006-03-20 10:27:30 +00001007
weidendo0a1951d2009-06-15 00:16:36 +00001008 addBBSetupCall(&clgs);
weidendoa17f2a32006-03-20 10:27:30 +00001009
weidendo0a1951d2009-06-15 00:16:36 +00001010 // Set up running state
1011 clgs.events_used = 0;
1012 clgs.ii_index = 0;
1013 clgs.instr_offset = 0;
weidendoa17f2a32006-03-20 10:27:30 +00001014
weidendo0a1951d2009-06-15 00:16:36 +00001015 for (/*use current i*/; i < sbIn->stmts_used; i++) {
weidendoa17f2a32006-03-20 10:27:30 +00001016
weidendo0a1951d2009-06-15 00:16:36 +00001017 st = sbIn->stmts[i];
1018 CLG_ASSERT(isFlatIRStmt(st));
weidendoa17f2a32006-03-20 10:27:30 +00001019
weidendo0a1951d2009-06-15 00:16:36 +00001020 switch (st->tag) {
1021 case Ist_NoOp:
1022 case Ist_AbiHint:
1023 case Ist_Put:
1024 case Ist_PutI:
1025 case Ist_MBE:
1026 break;
weidendoa17f2a32006-03-20 10:27:30 +00001027
weidendo0a1951d2009-06-15 00:16:36 +00001028 case Ist_IMark: {
florianf466eef2015-01-02 17:32:40 +00001029 Addr cia = st->Ist.IMark.addr + st->Ist.IMark.delta;
1030 UInt isize = st->Ist.IMark.len;
1031 CLG_ASSERT(clgs.instr_offset == cia - origAddr);
weidendo0a1951d2009-06-15 00:16:36 +00001032 // If Vex fails to decode an instruction, the size will be zero.
1033 // Pretend otherwise.
1034 if (isize == 0) isize = VG_MIN_INSTR_SZB;
weidendoa17f2a32006-03-20 10:27:30 +00001035
weidendo0a1951d2009-06-15 00:16:36 +00001036 // Sanity-check size.
1037 tl_assert( (VG_MIN_INSTR_SZB <= isize && isize <= VG_MAX_INSTR_SZB)
1038 || VG_CLREQ_SZB == isize );
weidendoa17f2a32006-03-20 10:27:30 +00001039
weidendo0a1951d2009-06-15 00:16:36 +00001040 // Init the inode, record it as the current one.
1041 // Subsequent Dr/Dw/Dm events from the same instruction will
1042 // also use it.
1043 curr_inode = next_InstrInfo (&clgs, isize);
weidendoa17f2a32006-03-20 10:27:30 +00001044
weidendo0a1951d2009-06-15 00:16:36 +00001045 addEvent_Ir( &clgs, curr_inode );
1046 break;
1047 }
weidendoa17f2a32006-03-20 10:27:30 +00001048
weidendo0a1951d2009-06-15 00:16:36 +00001049 case Ist_WrTmp: {
1050 IRExpr* data = st->Ist.WrTmp.data;
1051 if (data->tag == Iex_Load) {
1052 IRExpr* aexpr = data->Iex.Load.addr;
1053 // Note also, endianness info is ignored. I guess
1054 // that's not interesting.
1055 addEvent_Dr( &clgs, curr_inode,
1056 sizeofIRType(data->Iex.Load.ty), aexpr );
1057 }
1058 break;
1059 }
weidendoa17f2a32006-03-20 10:27:30 +00001060
weidendo0a1951d2009-06-15 00:16:36 +00001061 case Ist_Store: {
1062 IRExpr* data = st->Ist.Store.data;
1063 IRExpr* aexpr = st->Ist.Store.addr;
1064 addEvent_Dw( &clgs, curr_inode,
1065 sizeofIRType(typeOfIRExpr(sbIn->tyenv, data)), aexpr );
1066 break;
1067 }
weidendoa17f2a32006-03-20 10:27:30 +00001068
sewardjcafe5052013-01-17 14:24:35 +00001069 case Ist_StoreG: {
1070 IRStoreG* sg = st->Ist.StoreG.details;
1071 IRExpr* data = sg->data;
1072 IRExpr* addr = sg->addr;
1073 IRType type = typeOfIRExpr(tyenv, data);
1074 tl_assert(type != Ity_INVALID);
1075 addEvent_D_guarded( &clgs, curr_inode,
1076 sizeofIRType(type), addr, sg->guard,
1077 True/*isWrite*/ );
1078 break;
1079 }
1080
1081 case Ist_LoadG: {
1082 IRLoadG* lg = st->Ist.LoadG.details;
1083 IRType type = Ity_INVALID; /* loaded type */
1084 IRType typeWide = Ity_INVALID; /* after implicit widening */
1085 IRExpr* addr = lg->addr;
1086 typeOfIRLoadGOp(lg->cvt, &typeWide, &type);
1087 tl_assert(type != Ity_INVALID);
1088 addEvent_D_guarded( &clgs, curr_inode,
1089 sizeofIRType(type), addr, lg->guard,
1090 False/*!isWrite*/ );
1091 break;
1092 }
1093
weidendo0a1951d2009-06-15 00:16:36 +00001094 case Ist_Dirty: {
1095 Int dataSize;
1096 IRDirty* d = st->Ist.Dirty.details;
1097 if (d->mFx != Ifx_None) {
1098 /* This dirty helper accesses memory. Collect the details. */
1099 tl_assert(d->mAddr != NULL);
1100 tl_assert(d->mSize != 0);
1101 dataSize = d->mSize;
1102 // Large (eg. 28B, 108B, 512B on x86) data-sized
1103 // instructions will be done inaccurately, but they're
1104 // very rare and this avoids errors from hitting more
1105 // than two cache lines in the simulation.
sewardjc4ebde32012-06-03 23:10:55 +00001106 if (CLG_(clo).simulate_cache && dataSize > CLG_(min_line_size))
1107 dataSize = CLG_(min_line_size);
weidendo0a1951d2009-06-15 00:16:36 +00001108 if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify)
1109 addEvent_Dr( &clgs, curr_inode, dataSize, d->mAddr );
1110 if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify)
1111 addEvent_Dw( &clgs, curr_inode, dataSize, d->mAddr );
1112 } else {
1113 tl_assert(d->mAddr == NULL);
1114 tl_assert(d->mSize == 0);
1115 }
1116 break;
1117 }
weidendoa17f2a32006-03-20 10:27:30 +00001118
sewardj1c0ce7a2009-07-01 08:10:49 +00001119 case Ist_CAS: {
1120 /* We treat it as a read and a write of the location. I
1121 think that is the same behaviour as it was before IRCAS
1122 was introduced, since prior to that point, the Vex
1123 front ends would translate a lock-prefixed instruction
1124 into a (normal) read followed by a (normal) write. */
1125 Int dataSize;
1126 IRCAS* cas = st->Ist.CAS.details;
1127 CLG_ASSERT(cas->addr && isIRAtom(cas->addr));
1128 CLG_ASSERT(cas->dataLo);
1129 dataSize = sizeofIRType(typeOfIRExpr(sbIn->tyenv, cas->dataLo));
1130 if (cas->dataHi != NULL)
1131 dataSize *= 2; /* since this is a doubleword-cas */
1132 addEvent_Dr( &clgs, curr_inode, dataSize, cas->addr );
1133 addEvent_Dw( &clgs, curr_inode, dataSize, cas->addr );
weidendoaeb86222010-06-09 22:33:02 +00001134 addEvent_G( &clgs, curr_inode );
sewardj1c0ce7a2009-07-01 08:10:49 +00001135 break;
1136 }
sewardjdb5907d2009-11-26 17:20:21 +00001137
1138 case Ist_LLSC: {
1139 IRType dataTy;
1140 if (st->Ist.LLSC.storedata == NULL) {
1141 /* LL */
1142 dataTy = typeOfIRTemp(sbIn->tyenv, st->Ist.LLSC.result);
1143 addEvent_Dr( &clgs, curr_inode,
1144 sizeofIRType(dataTy), st->Ist.LLSC.addr );
petarjad1162a2012-11-23 00:01:36 +00001145 /* flush events before LL, should help SC to succeed */
1146 flushEvents( &clgs );
sewardjdb5907d2009-11-26 17:20:21 +00001147 } else {
1148 /* SC */
1149 dataTy = typeOfIRExpr(sbIn->tyenv, st->Ist.LLSC.storedata);
1150 addEvent_Dw( &clgs, curr_inode,
1151 sizeofIRType(dataTy), st->Ist.LLSC.addr );
weidendoaeb86222010-06-09 22:33:02 +00001152 /* I don't know whether the global-bus-lock cost should
1153 be attributed to the LL or the SC, but it doesn't
1154 really matter since they always have to be used in
1155 pairs anyway. Hence put it (quite arbitrarily) on
1156 the SC. */
1157 addEvent_G( &clgs, curr_inode );
sewardjdb5907d2009-11-26 17:20:21 +00001158 }
1159 break;
1160 }
1161
1162 case Ist_Exit: {
weidendo320705f2010-07-02 19:56:23 +00001163 Bool guest_exit, inverted;
1164
1165 /* VEX code generation sometimes inverts conditional branches.
1166 * As Callgrind counts (conditional) jumps, it has to correct
1167 * inversions. The heuristic is the following:
1168 * (1) Callgrind switches off SB chasing and unrolling, and
1169 * therefore it assumes that a candidate for inversion only is
1170 * the last conditional branch in an SB.
1171 * (2) inversion is assumed if the branch jumps to the address of
1172 * the next guest instruction in memory.
1173 * This heuristic is precalculated in CLG_(collectBlockInfo)().
1174 *
1175 * Branching behavior is also used for branch prediction. Note that
1176 * above heuristic is different from what Cachegrind does.
1177 * Cachegrind uses (2) for all branches.
1178 */
1179 if (cJumps+1 == clgs.bb->cjmp_count)
1180 inverted = clgs.bb->cjmp_inverted;
1181 else
1182 inverted = False;
1183
1184 // call branch predictor only if this is a branch in guest code
1185 guest_exit = (st->Ist.Exit.jk == Ijk_Boring) ||
1186 (st->Ist.Exit.jk == Ijk_Call) ||
1187 (st->Ist.Exit.jk == Ijk_Ret);
1188
1189 if (guest_exit) {
1190 /* Stuff to widen the guard expression to a host word, so
1191 we can pass it to the branch predictor simulation
1192 functions easily. */
1193 IRType tyW = hWordTy;
1194 IROp widen = tyW==Ity_I32 ? Iop_1Uto32 : Iop_1Uto64;
1195 IROp opXOR = tyW==Ity_I32 ? Iop_Xor32 : Iop_Xor64;
1196 IRTemp guard1 = newIRTemp(clgs.sbOut->tyenv, Ity_I1);
1197 IRTemp guardW = newIRTemp(clgs.sbOut->tyenv, tyW);
1198 IRTemp guard = newIRTemp(clgs.sbOut->tyenv, tyW);
1199 IRExpr* one = tyW==Ity_I32 ? IRExpr_Const(IRConst_U32(1))
1200 : IRExpr_Const(IRConst_U64(1));
1201
1202 /* Widen the guard expression. */
1203 addStmtToIRSB( clgs.sbOut,
1204 IRStmt_WrTmp( guard1, st->Ist.Exit.guard ));
1205 addStmtToIRSB( clgs.sbOut,
1206 IRStmt_WrTmp( guardW,
1207 IRExpr_Unop(widen,
1208 IRExpr_RdTmp(guard1))) );
1209 /* If the exit is inverted, invert the sense of the guard. */
1210 addStmtToIRSB(
1211 clgs.sbOut,
1212 IRStmt_WrTmp(
1213 guard,
1214 inverted ? IRExpr_Binop(opXOR, IRExpr_RdTmp(guardW), one)
1215 : IRExpr_RdTmp(guardW)
1216 ));
1217 /* And post the event. */
1218 addEvent_Bc( &clgs, curr_inode, IRExpr_RdTmp(guard) );
1219 }
weidendoa17f2a32006-03-20 10:27:30 +00001220
weidendo0a1951d2009-06-15 00:16:36 +00001221 /* We may never reach the next statement, so need to flush
1222 all outstanding transactions now. */
1223 flushEvents( &clgs );
weidendoa17f2a32006-03-20 10:27:30 +00001224
weidendo0a1951d2009-06-15 00:16:36 +00001225 CLG_ASSERT(clgs.ii_index>0);
1226 if (!clgs.seen_before) {
weidendo28a23c02011-11-14 21:16:25 +00001227 ClgJumpKind jk;
1228
1229 if (st->Ist.Exit.jk == Ijk_Call) jk = jk_Call;
1230 else if (st->Ist.Exit.jk == Ijk_Ret) jk = jk_Return;
1231 else {
1232 if (IRConst2Addr(st->Ist.Exit.dst) ==
1233 origAddr + curr_inode->instr_offset + curr_inode->instr_size)
1234 jk = jk_None;
1235 else
1236 jk = jk_Jump;
1237 }
1238
1239 clgs.bb->jmp[cJumps].instr = clgs.ii_index-1;
1240 clgs.bb->jmp[cJumps].jmpkind = jk;
weidendo0a1951d2009-06-15 00:16:36 +00001241 }
1242
1243 /* Update global variable jmps_passed before the jump
1244 * A correction is needed if VEX inverted the last jump condition
1245 */
weidendod7341d82013-11-12 15:32:58 +00001246 UInt val = inverted ? cJumps+1 : cJumps;
weidendo0a1951d2009-06-15 00:16:36 +00001247 addConstMemStoreStmt( clgs.sbOut,
1248 (UWord) &CLG_(current_state).jmps_passed,
weidendod7341d82013-11-12 15:32:58 +00001249 val, hWordTy);
weidendo0a1951d2009-06-15 00:16:36 +00001250 cJumps++;
1251
1252 break;
1253 }
1254
1255 default:
1256 tl_assert(0);
1257 break;
1258 }
1259
1260 /* Copy the original statement */
1261 addStmtToIRSB( clgs.sbOut, st );
1262
1263 CLG_DEBUGIF(5) {
1264 VG_(printf)(" pass ");
1265 ppIRStmt(st);
1266 VG_(printf)("\n");
1267 }
weidendoa17f2a32006-03-20 10:27:30 +00001268 }
weidendoa17f2a32006-03-20 10:27:30 +00001269
weidendo320705f2010-07-02 19:56:23 +00001270 /* Deal with branches to unknown destinations. Except ignore ones
1271 which are function returns as we assume the return stack
1272 predictor never mispredicts. */
weidendocb3ccf32010-07-07 18:51:59 +00001273 if ((sbIn->jumpkind == Ijk_Boring) || (sbIn->jumpkind == Ijk_Call)) {
weidendo320705f2010-07-02 19:56:23 +00001274 if (0) { ppIRExpr( sbIn->next ); VG_(printf)("\n"); }
1275 switch (sbIn->next->tag) {
1276 case Iex_Const:
1277 break; /* boring - branch to known address */
1278 case Iex_RdTmp:
1279 /* looks like an indirect branch (branch to unknown) */
1280 addEvent_Bi( &clgs, curr_inode, sbIn->next );
1281 break;
1282 default:
1283 /* shouldn't happen - if the incoming IR is properly
1284 flattened, should only have tmp and const cases to
1285 consider. */
1286 tl_assert(0);
1287 }
1288 }
1289
weidendo0a1951d2009-06-15 00:16:36 +00001290 /* At the end of the bb. Flush outstandings. */
1291 flushEvents( &clgs );
1292
weidendod7341d82013-11-12 15:32:58 +00001293 /* Update global variable jmps_passed at end of SB.
1294 * As CLG_(current_state).jmps_passed is reset to 0 in setup_bbcc,
1295 * this can be omitted if there is no conditional jump in this SB.
weidendoa17f2a32006-03-20 10:27:30 +00001296 * A correction is needed if VEX inverted the last jump condition
1297 */
weidendod7341d82013-11-12 15:32:58 +00001298 if (cJumps>0) {
weidendo0a1951d2009-06-15 00:16:36 +00001299 UInt jmps_passed = cJumps;
1300 if (clgs.bb->cjmp_inverted) jmps_passed--;
1301 addConstMemStoreStmt( clgs.sbOut,
1302 (UWord) &CLG_(current_state).jmps_passed,
1303 jmps_passed, hWordTy);
1304 }
1305 CLG_ASSERT(clgs.bb->cjmp_count == cJumps);
florianba74a112013-01-21 13:51:21 +00001306 CLG_ASSERT(clgs.bb->instr_count == clgs.ii_index);
weidendoa17f2a32006-03-20 10:27:30 +00001307
weidendo28a23c02011-11-14 21:16:25 +00001308 /* Info for final exit from BB */
1309 {
1310 ClgJumpKind jk;
1311
1312 if (sbIn->jumpkind == Ijk_Call) jk = jk_Call;
1313 else if (sbIn->jumpkind == Ijk_Ret) jk = jk_Return;
1314 else {
1315 jk = jk_Jump;
1316 if ((sbIn->next->tag == Iex_Const) &&
1317 (IRConst2Addr(sbIn->next->Iex.Const.con) ==
1318 origAddr + clgs.instr_offset))
1319 jk = jk_None;
1320 }
1321 clgs.bb->jmp[cJumps].jmpkind = jk;
1322 /* Instruction index of the call/ret at BB end
1323 * (it is wrong for fall-through, but does not matter) */
1324 clgs.bb->jmp[cJumps].instr = clgs.ii_index-1;
1325 }
1326
1327 /* swap information of last exit with final exit if inverted */
1328 if (clgs.bb->cjmp_inverted) {
1329 ClgJumpKind jk;
1330 UInt instr;
1331
1332 jk = clgs.bb->jmp[cJumps].jmpkind;
1333 clgs.bb->jmp[cJumps].jmpkind = clgs.bb->jmp[cJumps-1].jmpkind;
1334 clgs.bb->jmp[cJumps-1].jmpkind = jk;
1335 instr = clgs.bb->jmp[cJumps].instr;
1336 clgs.bb->jmp[cJumps].instr = clgs.bb->jmp[cJumps-1].instr;
1337 clgs.bb->jmp[cJumps-1].instr = instr;
1338 }
weidendoa17f2a32006-03-20 10:27:30 +00001339
weidendo0a1951d2009-06-15 00:16:36 +00001340 if (clgs.seen_before) {
1341 CLG_ASSERT(clgs.bb->cost_count == update_cost_offsets(&clgs));
florianba74a112013-01-21 13:51:21 +00001342 CLG_ASSERT(clgs.bb->instr_len == clgs.instr_offset);
weidendoa17f2a32006-03-20 10:27:30 +00001343 }
1344 else {
weidendo0a1951d2009-06-15 00:16:36 +00001345 clgs.bb->cost_count = update_cost_offsets(&clgs);
1346 clgs.bb->instr_len = clgs.instr_offset;
weidendoa17f2a32006-03-20 10:27:30 +00001347 }
weidendo0a1951d2009-06-15 00:16:36 +00001348
barta0b6b2c2008-07-07 06:49:24 +00001349 CLG_DEBUG(3, "- instrument(BB %#lx): byteLen %u, CJumps %u, CostLen %u\n",
weidendo0a1951d2009-06-15 00:16:36 +00001350 origAddr, clgs.bb->instr_len,
1351 clgs.bb->cjmp_count, clgs.bb->cost_count);
weidendoa17f2a32006-03-20 10:27:30 +00001352 if (cJumps>0) {
1353 CLG_DEBUG(3, " [ ");
1354 for (i=0;i<cJumps;i++)
weidendo0a1951d2009-06-15 00:16:36 +00001355 CLG_DEBUG(3, "%d ", clgs.bb->jmp[i].instr);
1356 CLG_DEBUG(3, "], last inverted: %s \n",
1357 clgs.bb->cjmp_inverted ? "yes":"no");
weidendoa17f2a32006-03-20 10:27:30 +00001358 }
1359
weidendo0a1951d2009-06-15 00:16:36 +00001360 return clgs.sbOut;
weidendoa17f2a32006-03-20 10:27:30 +00001361}
1362
1363/*--------------------------------------------------------------------*/
1364/*--- Discarding BB info ---*/
1365/*--------------------------------------------------------------------*/
1366
1367// Called when a translation is removed from the translation cache for
1368// any reason at all: to free up space, because the guest code was
1369// unmapped or modified, or for any arbitrary reason.
1370static
florianddd61ff2015-01-04 17:20:45 +00001371void clg_discard_superblock_info ( Addr orig_addr, VexGuestExtents vge )
weidendoa17f2a32006-03-20 10:27:30 +00001372{
weidendoa17f2a32006-03-20 10:27:30 +00001373 tl_assert(vge.n_used > 0);
1374
1375 if (0)
sewardj0b9d74a2006-12-24 02:24:11 +00001376 VG_(printf)( "discard_superblock_info: %p, %p, %llu\n",
florianddd61ff2015-01-04 17:20:45 +00001377 (void*)orig_addr,
1378 (void*)vge.base[0], (ULong)vge.len[0]);
weidendoa17f2a32006-03-20 10:27:30 +00001379
weidendo04df7f22015-01-08 14:15:18 +00001380 // Get BB info, remove from table, free BB info. Simple!
1381 // When created, the BB is keyed by the first instruction address,
1382 // (not orig_addr, but eventually redirected address). Thus, we
1383 // use the first instruction address in vge.
1384 CLG_(delete_bb)(vge.base[0]);
weidendoa17f2a32006-03-20 10:27:30 +00001385}
1386
1387
1388/*------------------------------------------------------------*/
1389/*--- CLG_(fini)() and related function ---*/
1390/*------------------------------------------------------------*/
1391
1392
1393
1394static void zero_thread_cost(thread_info* t)
1395{
1396 Int i;
1397
1398 for(i = 0; i < CLG_(current_call_stack).sp; i++) {
1399 if (!CLG_(current_call_stack).entry[i].jcc) continue;
1400
1401 /* reset call counters to current for active calls */
1402 CLG_(copy_cost)( CLG_(sets).full,
1403 CLG_(current_call_stack).entry[i].enter_cost,
1404 CLG_(current_state).cost );
weidendoceb06de2009-08-11 20:53:57 +00001405 CLG_(current_call_stack).entry[i].jcc->call_counter = 0;
weidendoa17f2a32006-03-20 10:27:30 +00001406 }
1407
1408 CLG_(forall_bbccs)(CLG_(zero_bbcc));
1409
1410 /* set counter for last dump */
1411 CLG_(copy_cost)( CLG_(sets).full,
1412 t->lastdump_cost, CLG_(current_state).cost );
1413}
1414
1415void CLG_(zero_all_cost)(Bool only_current_thread)
1416{
1417 if (VG_(clo_verbosity) > 1)
sewardj0f33adf2009-07-15 14:51:03 +00001418 VG_(message)(Vg_DebugMsg, " Zeroing costs...\n");
weidendoa17f2a32006-03-20 10:27:30 +00001419
1420 if (only_current_thread)
1421 zero_thread_cost(CLG_(get_current_thread)());
1422 else
1423 CLG_(forall_threads)(zero_thread_cost);
1424
1425 if (VG_(clo_verbosity) > 1)
sewardj0f33adf2009-07-15 14:51:03 +00001426 VG_(message)(Vg_DebugMsg, " ...done\n");
weidendoa17f2a32006-03-20 10:27:30 +00001427}
1428
1429static
1430void unwind_thread(thread_info* t)
1431{
1432 /* unwind signal handlers */
1433 while(CLG_(current_state).sig !=0)
1434 CLG_(post_signal)(CLG_(current_tid),CLG_(current_state).sig);
1435
1436 /* unwind regular call stack */
1437 while(CLG_(current_call_stack).sp>0)
1438 CLG_(pop_call_stack)();
weidendof3e0b492006-09-10 22:34:20 +00001439
1440 /* reset context and function stack for context generation */
1441 CLG_(init_exec_state)( &CLG_(current_state) );
1442 CLG_(current_fn_stack).top = CLG_(current_fn_stack).bottom;
weidendoa17f2a32006-03-20 10:27:30 +00001443}
1444
weidendoe8914872009-08-11 20:53:59 +00001445static
1446void zero_state_cost(thread_info* t)
1447{
1448 CLG_(zero_cost)( CLG_(sets).full, CLG_(current_state).cost );
1449}
1450
florian6bd9dc12012-11-23 16:17:43 +00001451/* Ups, this can go very wrong...
1452 FIXME: We should export this function or provide other means to get a handle */
florianddd61ff2015-01-04 17:20:45 +00001453extern void VG_(discard_translations) ( Addr start, ULong range, const HChar* who );
weidendoa17f2a32006-03-20 10:27:30 +00001454
florian25f6c572012-10-21 02:55:56 +00001455void CLG_(set_instrument_state)(const HChar* reason, Bool state)
weidendoa17f2a32006-03-20 10:27:30 +00001456{
1457 if (CLG_(instrument_state) == state) {
1458 CLG_DEBUG(2, "%s: instrumentation already %s\n",
1459 reason, state ? "ON" : "OFF");
1460 return;
1461 }
1462 CLG_(instrument_state) = state;
1463 CLG_DEBUG(2, "%s: Switching instrumentation %s ...\n",
1464 reason, state ? "ON" : "OFF");
1465
florianddd61ff2015-01-04 17:20:45 +00001466 VG_(discard_translations)( (Addr)0x1000, (ULong) ~0xfffl, "callgrind");
weidendoa17f2a32006-03-20 10:27:30 +00001467
1468 /* reset internal state: call stacks, simulator */
1469 CLG_(forall_threads)(unwind_thread);
weidendoe8914872009-08-11 20:53:59 +00001470 CLG_(forall_threads)(zero_state_cost);
weidendoa17f2a32006-03-20 10:27:30 +00001471 (*CLG_(cachesim).clear)();
weidendoa17f2a32006-03-20 10:27:30 +00001472
weidendoa17f2a32006-03-20 10:27:30 +00001473 if (VG_(clo_verbosity) > 1)
sewardj0f33adf2009-07-15 14:51:03 +00001474 VG_(message)(Vg_DebugMsg, "%s: instrumentation switched %s\n",
weidendoa17f2a32006-03-20 10:27:30 +00001475 reason, state ? "ON" : "OFF");
1476}
weidendo584c9ef2011-07-11 14:46:41 +00001477
1478/* helper for dump_state_togdb */
1479static void dump_state_of_thread_togdb(thread_info* ti)
1480{
weidendo584c9ef2011-07-11 14:46:41 +00001481 static FullCost sum = 0, tmp = 0;
florian5ee42a42014-11-06 21:43:44 +00001482 Int t, i;
weidendo584c9ef2011-07-11 14:46:41 +00001483 BBCC *from, *to;
1484 call_entry* ce;
florian5ee42a42014-11-06 21:43:44 +00001485 HChar *mcost;
weidendo584c9ef2011-07-11 14:46:41 +00001486
1487 t = CLG_(current_tid);
1488 CLG_(init_cost_lz)( CLG_(sets).full, &sum );
1489 CLG_(copy_cost_lz)( CLG_(sets).full, &tmp, ti->lastdump_cost );
1490 CLG_(add_diff_cost)( CLG_(sets).full, sum, ti->lastdump_cost,
1491 ti->states.entry[0]->cost);
1492 CLG_(copy_cost)( CLG_(sets).full, ti->lastdump_cost, tmp );
florian5ee42a42014-11-06 21:43:44 +00001493 mcost = CLG_(mappingcost_as_string)(CLG_(dumpmap), sum);
1494 VG_(gdb_printf)("events-%d: %s\n", t, mcost);
1495 VG_(free)(mcost);
weidendo584c9ef2011-07-11 14:46:41 +00001496 VG_(gdb_printf)("frames-%d: %d\n", t, CLG_(current_call_stack).sp);
1497
1498 ce = 0;
1499 for(i = 0; i < CLG_(current_call_stack).sp; i++) {
1500 ce = CLG_(get_call_entry)(i);
1501 /* if this frame is skipped, we don't have counters */
1502 if (!ce->jcc) continue;
1503
1504 from = ce->jcc->from;
1505 VG_(gdb_printf)("function-%d-%d: %s\n",t, i, from->cxt->fn[0]->name);
1506 VG_(gdb_printf)("calls-%d-%d: %llu\n",t, i, ce->jcc->call_counter);
1507
1508 /* FIXME: EventSets! */
1509 CLG_(copy_cost)( CLG_(sets).full, sum, ce->jcc->cost );
1510 CLG_(copy_cost)( CLG_(sets).full, tmp, ce->enter_cost );
1511 CLG_(add_diff_cost)( CLG_(sets).full, sum,
1512 ce->enter_cost, CLG_(current_state).cost );
1513 CLG_(copy_cost)( CLG_(sets).full, ce->enter_cost, tmp );
1514
florian5ee42a42014-11-06 21:43:44 +00001515 mcost = CLG_(mappingcost_as_string)(CLG_(dumpmap), sum);
1516 VG_(gdb_printf)("events-%d-%d: %s\n",t, i, mcost);
1517 VG_(free)(mcost);
weidendo584c9ef2011-07-11 14:46:41 +00001518 }
1519 if (ce && ce->jcc) {
1520 to = ce->jcc->to;
1521 VG_(gdb_printf)("function-%d-%d: %s\n",t, i, to->cxt->fn[0]->name );
1522 }
1523}
1524
1525/* Dump current state */
1526static void dump_state_togdb(void)
1527{
weidendo584c9ef2011-07-11 14:46:41 +00001528 thread_info** th;
florian48b1cf12014-11-06 22:01:15 +00001529 int t;
weidendo584c9ef2011-07-11 14:46:41 +00001530 Int orig_tid = CLG_(current_tid);
1531
1532 VG_(gdb_printf)("instrumentation: %s\n",
1533 CLG_(instrument_state) ? "on":"off");
1534 if (!CLG_(instrument_state)) return;
1535
1536 VG_(gdb_printf)("executed-bbs: %llu\n", CLG_(stat).bb_executions);
1537 VG_(gdb_printf)("executed-calls: %llu\n", CLG_(stat).call_counter);
1538 VG_(gdb_printf)("distinct-bbs: %d\n", CLG_(stat).distinct_bbs);
1539 VG_(gdb_printf)("distinct-calls: %d\n", CLG_(stat).distinct_jccs);
1540 VG_(gdb_printf)("distinct-functions: %d\n", CLG_(stat).distinct_fns);
1541 VG_(gdb_printf)("distinct-contexts: %d\n", CLG_(stat).distinct_contexts);
1542
1543 /* "events:" line. Given here because it will be dynamic in the future */
florian5ee42a42014-11-06 21:43:44 +00001544 HChar *evmap = CLG_(eventmapping_as_string)(CLG_(dumpmap));
1545 VG_(gdb_printf)("events: %s\n", evmap);
1546 VG_(free)(evmap);
weidendo584c9ef2011-07-11 14:46:41 +00001547 /* "part:" line (number of last part. Is 0 at start */
1548 VG_(gdb_printf)("part: %d\n", CLG_(get_dump_counter)());
1549
1550 /* threads */
1551 th = CLG_(get_threads)();
florian48b1cf12014-11-06 22:01:15 +00001552 VG_(gdb_printf)("threads:");
weidendo584c9ef2011-07-11 14:46:41 +00001553 for(t=1;t<VG_N_THREADS;t++) {
1554 if (!th[t]) continue;
florian48b1cf12014-11-06 22:01:15 +00001555 VG_(gdb_printf)(" %d", t);
weidendo584c9ef2011-07-11 14:46:41 +00001556 }
florian48b1cf12014-11-06 22:01:15 +00001557 VG_(gdb_printf)("\n");
weidendo584c9ef2011-07-11 14:46:41 +00001558 VG_(gdb_printf)("current-tid: %d\n", orig_tid);
1559 CLG_(forall_threads)(dump_state_of_thread_togdb);
1560}
1561
weidendoa17f2a32006-03-20 10:27:30 +00001562
sewardj3b290482011-05-06 21:02:55 +00001563static void print_monitor_help ( void )
1564{
1565 VG_(gdb_printf) ("\n");
1566 VG_(gdb_printf) ("callgrind monitor commands:\n");
sewardj30b3eca2011-06-28 08:20:39 +00001567 VG_(gdb_printf) (" dump [<dump_hint>]\n");
sewardj3b290482011-05-06 21:02:55 +00001568 VG_(gdb_printf) (" dump counters\n");
sewardj30b3eca2011-06-28 08:20:39 +00001569 VG_(gdb_printf) (" zero\n");
sewardj3b290482011-05-06 21:02:55 +00001570 VG_(gdb_printf) (" zero counters\n");
weidendo584c9ef2011-07-11 14:46:41 +00001571 VG_(gdb_printf) (" status\n");
weidendoce6489f2011-09-06 19:08:35 +00001572 VG_(gdb_printf) (" print status\n");
weidendo584c9ef2011-07-11 14:46:41 +00001573 VG_(gdb_printf) (" instrumentation [on|off]\n");
1574 VG_(gdb_printf) (" get/set (if on/off given) instrumentation state\n");
sewardj3b290482011-05-06 21:02:55 +00001575 VG_(gdb_printf) ("\n");
1576}
1577
1578/* return True if request recognised, False otherwise */
florian19f91bb2012-11-10 22:29:54 +00001579static Bool handle_gdb_monitor_command (ThreadId tid, const HChar *req)
sewardj3b290482011-05-06 21:02:55 +00001580{
florian19f91bb2012-11-10 22:29:54 +00001581 HChar* wcmd;
dejanjc29761f2014-03-19 11:58:35 +00001582 HChar s[VG_(strlen(req)) + 1]; /* copy for strtok_r */
florian19f91bb2012-11-10 22:29:54 +00001583 HChar *ssaveptr;
sewardj3b290482011-05-06 21:02:55 +00001584
1585 VG_(strcpy) (s, req);
1586
1587 wcmd = VG_(strtok_r) (s, " ", &ssaveptr);
weidendo584c9ef2011-07-11 14:46:41 +00001588 switch (VG_(keyword_id) ("help dump zero status instrumentation",
sewardj3b290482011-05-06 21:02:55 +00001589 wcmd, kwd_report_duplicated_matches)) {
1590 case -2: /* multiple matches */
1591 return True;
1592 case -1: /* not found */
1593 return False;
1594 case 0: /* help */
1595 print_monitor_help();
1596 return True;
sewardj30b3eca2011-06-28 08:20:39 +00001597 case 1: { /* dump */
sewardj3b290482011-05-06 21:02:55 +00001598 CLG_(dump_profile)(req, False);
1599 return True;
1600 }
sewardj30b3eca2011-06-28 08:20:39 +00001601 case 2: { /* zero */
sewardj3b290482011-05-06 21:02:55 +00001602 CLG_(zero_all_cost)(False);
1603 return True;
1604 }
weidendoce6489f2011-09-06 19:08:35 +00001605
weidendo584c9ef2011-07-11 14:46:41 +00001606 case 3: { /* status */
florian19f91bb2012-11-10 22:29:54 +00001607 HChar* arg = VG_(strtok_r) (0, " ", &ssaveptr);
weidendoce6489f2011-09-06 19:08:35 +00001608 if (arg && (VG_(strcmp)(arg, "internal") == 0)) {
1609 /* internal interface to callgrind_control */
1610 dump_state_togdb();
1611 return True;
1612 }
1613
1614 if (!CLG_(instrument_state)) {
1615 VG_(gdb_printf)("No status available as instrumentation is switched off\n");
1616 } else {
1617 // Status information to be improved ...
1618 thread_info** th = CLG_(get_threads)();
1619 Int t, tcount = 0;
1620 for(t=1;t<VG_N_THREADS;t++)
1621 if (th[t]) tcount++;
1622 VG_(gdb_printf)("%d thread(s) running.\n", tcount);
1623 }
weidendo584c9ef2011-07-11 14:46:41 +00001624 return True;
1625 }
weidendoce6489f2011-09-06 19:08:35 +00001626
weidendo584c9ef2011-07-11 14:46:41 +00001627 case 4: { /* instrumentation */
florian19f91bb2012-11-10 22:29:54 +00001628 HChar* arg = VG_(strtok_r) (0, " ", &ssaveptr);
weidendo584c9ef2011-07-11 14:46:41 +00001629 if (!arg) {
1630 VG_(gdb_printf)("instrumentation: %s\n",
1631 CLG_(instrument_state) ? "on":"off");
1632 }
1633 else
1634 CLG_(set_instrument_state)("Command", VG_(strcmp)(arg,"off")!=0);
1635 return True;
1636 }
sewardj3b290482011-05-06 21:02:55 +00001637
1638 default:
1639 tl_assert(0);
1640 return False;
1641 }
1642}
weidendoa17f2a32006-03-20 10:27:30 +00001643
1644static
1645Bool CLG_(handle_client_request)(ThreadId tid, UWord *args, UWord *ret)
1646{
sewardj3b290482011-05-06 21:02:55 +00001647 if (!VG_IS_TOOL_USERREQ('C','T',args[0])
1648 && VG_USERREQ__GDB_MONITOR_COMMAND != args[0])
weidendoa17f2a32006-03-20 10:27:30 +00001649 return False;
1650
1651 switch(args[0]) {
1652 case VG_USERREQ__DUMP_STATS:
1653 CLG_(dump_profile)("Client Request", True);
1654 *ret = 0; /* meaningless */
1655 break;
1656
1657 case VG_USERREQ__DUMP_STATS_AT:
1658 {
florian7b7d5942014-12-19 20:29:22 +00001659 const HChar *arg = (HChar*)args[1];
1660 HChar buf[30 + VG_(strlen)(arg)]; // large enough
1661 VG_(sprintf)(buf,"Client Request: %s", arg);
weidendoa17f2a32006-03-20 10:27:30 +00001662 CLG_(dump_profile)(buf, True);
1663 *ret = 0; /* meaningless */
1664 }
1665 break;
1666
1667 case VG_USERREQ__ZERO_STATS:
1668 CLG_(zero_all_cost)(True);
1669 *ret = 0; /* meaningless */
1670 break;
1671
1672 case VG_USERREQ__TOGGLE_COLLECT:
1673 CLG_(current_state).collect = !CLG_(current_state).collect;
1674 CLG_DEBUG(2, "Client Request: toggled collection state to %s\n",
1675 CLG_(current_state).collect ? "ON" : "OFF");
1676 *ret = 0; /* meaningless */
1677 break;
1678
1679 case VG_USERREQ__START_INSTRUMENTATION:
1680 CLG_(set_instrument_state)("Client Request", True);
1681 *ret = 0; /* meaningless */
1682 break;
1683
1684 case VG_USERREQ__STOP_INSTRUMENTATION:
1685 CLG_(set_instrument_state)("Client Request", False);
1686 *ret = 0; /* meaningless */
1687 break;
1688
sewardj3b290482011-05-06 21:02:55 +00001689 case VG_USERREQ__GDB_MONITOR_COMMAND: {
florian19f91bb2012-11-10 22:29:54 +00001690 Bool handled = handle_gdb_monitor_command (tid, (HChar*)args[1]);
sewardj3b290482011-05-06 21:02:55 +00001691 if (handled)
1692 *ret = 1;
1693 else
1694 *ret = 0;
1695 return handled;
1696 }
weidendoa17f2a32006-03-20 10:27:30 +00001697 default:
1698 return False;
1699 }
1700
1701 return True;
1702}
1703
1704
1705/* Syscall Timing */
1706
1707/* struct timeval syscalltime[VG_N_THREADS]; */
1708#if CLG_MICROSYSTIME
1709#include <sys/time.h>
1710#include <sys/syscall.h>
1711extern Int VG_(do_syscall) ( UInt, ... );
1712
1713ULong syscalltime[VG_N_THREADS];
1714#else
1715UInt syscalltime[VG_N_THREADS];
1716#endif
1717
1718static
sewardj1c0ce7a2009-07-01 08:10:49 +00001719void CLG_(pre_syscalltime)(ThreadId tid, UInt syscallno,
1720 UWord* args, UInt nArgs)
weidendoa17f2a32006-03-20 10:27:30 +00001721{
1722 if (CLG_(clo).collect_systime) {
1723#if CLG_MICROSYSTIME
1724 struct vki_timeval tv_now;
1725 VG_(do_syscall)(__NR_gettimeofday, (UInt)&tv_now, (UInt)NULL);
1726 syscalltime[tid] = tv_now.tv_sec * 1000000ULL + tv_now.tv_usec;
1727#else
1728 syscalltime[tid] = VG_(read_millisecond_timer)();
1729#endif
1730 }
1731}
1732
1733static
sewardj1c0ce7a2009-07-01 08:10:49 +00001734void CLG_(post_syscalltime)(ThreadId tid, UInt syscallno,
1735 UWord* args, UInt nArgs, SysRes res)
weidendoa17f2a32006-03-20 10:27:30 +00001736{
weidendoae0bb6f2007-02-16 13:12:43 +00001737 if (CLG_(clo).collect_systime &&
1738 CLG_(current_state).bbcc) {
weidendo5bba5252010-06-09 22:32:53 +00001739 Int o;
weidendoa17f2a32006-03-20 10:27:30 +00001740#if CLG_MICROSYSTIME
1741 struct vki_timeval tv_now;
1742 ULong diff;
1743
1744 VG_(do_syscall)(__NR_gettimeofday, (UInt)&tv_now, (UInt)NULL);
1745 diff = (tv_now.tv_sec * 1000000ULL + tv_now.tv_usec) - syscalltime[tid];
1746#else
1747 UInt diff = VG_(read_millisecond_timer)() - syscalltime[tid];
1748#endif
weidendo5bba5252010-06-09 22:32:53 +00001749
1750 /* offset o is for "SysCount", o+1 for "SysTime" */
1751 o = fullOffset(EG_SYS);
1752 CLG_ASSERT(o>=0);
weidendoa17f2a32006-03-20 10:27:30 +00001753 CLG_DEBUG(0," Time (Off %d) for Syscall %d: %ull\n", o, syscallno, diff);
1754
weidendoa17f2a32006-03-20 10:27:30 +00001755 CLG_(current_state).cost[o] ++;
1756 CLG_(current_state).cost[o+1] += diff;
1757 if (!CLG_(current_state).bbcc->skipped)
1758 CLG_(init_cost_lz)(CLG_(sets).full,
1759 &(CLG_(current_state).bbcc->skipped));
1760 CLG_(current_state).bbcc->skipped[o] ++;
1761 CLG_(current_state).bbcc->skipped[o+1] += diff;
1762 }
1763}
1764
weidendo320705f2010-07-02 19:56:23 +00001765static UInt ULong_width(ULong n)
1766{
1767 UInt w = 0;
1768 while (n > 0) {
1769 n = n / 10;
1770 w++;
1771 }
1772 if (w == 0) w = 1;
1773 return w + (w-1)/3; // add space for commas
1774}
1775
1776static
1777void branchsim_printstat(int l1, int l2, int l3)
1778{
florian73382952014-11-13 22:45:58 +00001779 static HChar fmt[128]; // large enough
weidendo320705f2010-07-02 19:56:23 +00001780 FullCost total;
1781 ULong Bc_total_b, Bc_total_mp, Bi_total_b, Bi_total_mp;
1782 ULong B_total_b, B_total_mp;
1783
1784 total = CLG_(total_cost);
1785 Bc_total_b = total[ fullOffset(EG_BC) ];
1786 Bc_total_mp = total[ fullOffset(EG_BC)+1 ];
1787 Bi_total_b = total[ fullOffset(EG_BI) ];
1788 Bi_total_mp = total[ fullOffset(EG_BI)+1 ];
1789
1790 /* Make format string, getting width right for numbers */
1791 VG_(sprintf)(fmt, "%%s %%,%dllu (%%,%dllu cond + %%,%dllu ind)\n",
1792 l1, l2, l3);
1793
1794 if (0 == Bc_total_b) Bc_total_b = 1;
1795 if (0 == Bi_total_b) Bi_total_b = 1;
1796 B_total_b = Bc_total_b + Bi_total_b;
1797 B_total_mp = Bc_total_mp + Bi_total_mp;
1798
1799 VG_(umsg)("\n");
1800 VG_(umsg)(fmt, "Branches: ",
1801 B_total_b, Bc_total_b, Bi_total_b);
1802
1803 VG_(umsg)(fmt, "Mispredicts: ",
1804 B_total_mp, Bc_total_mp, Bi_total_mp);
1805
florian227a1ec2014-12-12 19:32:10 +00001806 VG_(umsg)("Mispred rate: %*.1f%% (%*.1f%% + %*.1f%% )\n",
1807 l1, B_total_mp * 100.0 / B_total_b,
1808 l2, Bc_total_mp * 100.0 / Bc_total_b,
1809 l3, Bi_total_mp * 100.0 / Bi_total_b);
weidendo320705f2010-07-02 19:56:23 +00001810}
1811
weidendo6a8aa582013-12-17 15:12:06 +00001812static
1813void clg_print_stats(void)
1814{
1815 int BB_lookups =
1816 CLG_(stat).full_debug_BBs +
1817 CLG_(stat).fn_name_debug_BBs +
1818 CLG_(stat).file_line_debug_BBs +
1819 CLG_(stat).no_debug_BBs;
1820
1821 /* Hash table stats */
1822 VG_(message)(Vg_DebugMsg, "Distinct objects: %d\n",
1823 CLG_(stat).distinct_objs);
1824 VG_(message)(Vg_DebugMsg, "Distinct files: %d\n",
1825 CLG_(stat).distinct_files);
1826 VG_(message)(Vg_DebugMsg, "Distinct fns: %d\n",
1827 CLG_(stat).distinct_fns);
1828 VG_(message)(Vg_DebugMsg, "Distinct contexts:%d\n",
1829 CLG_(stat).distinct_contexts);
1830 VG_(message)(Vg_DebugMsg, "Distinct BBs: %d\n",
1831 CLG_(stat).distinct_bbs);
1832 VG_(message)(Vg_DebugMsg, "Cost entries: %d (Chunks %d)\n",
1833 CLG_(costarray_entries), CLG_(costarray_chunks));
1834 VG_(message)(Vg_DebugMsg, "Distinct BBCCs: %d\n",
1835 CLG_(stat).distinct_bbccs);
1836 VG_(message)(Vg_DebugMsg, "Distinct JCCs: %d\n",
1837 CLG_(stat).distinct_jccs);
1838 VG_(message)(Vg_DebugMsg, "Distinct skips: %d\n",
1839 CLG_(stat).distinct_skips);
1840 VG_(message)(Vg_DebugMsg, "BB lookups: %d\n",
1841 BB_lookups);
1842 if (BB_lookups>0) {
1843 VG_(message)(Vg_DebugMsg, "With full debug info:%3d%% (%d)\n",
1844 CLG_(stat).full_debug_BBs * 100 / BB_lookups,
1845 CLG_(stat).full_debug_BBs);
1846 VG_(message)(Vg_DebugMsg, "With file/line debug info:%3d%% (%d)\n",
1847 CLG_(stat).file_line_debug_BBs * 100 / BB_lookups,
1848 CLG_(stat).file_line_debug_BBs);
1849 VG_(message)(Vg_DebugMsg, "With fn name debug info:%3d%% (%d)\n",
1850 CLG_(stat).fn_name_debug_BBs * 100 / BB_lookups,
1851 CLG_(stat).fn_name_debug_BBs);
1852 VG_(message)(Vg_DebugMsg, "With no debug info:%3d%% (%d)\n",
1853 CLG_(stat).no_debug_BBs * 100 / BB_lookups,
1854 CLG_(stat).no_debug_BBs);
1855 }
1856 VG_(message)(Vg_DebugMsg, "BBCC Clones: %d\n",
1857 CLG_(stat).bbcc_clones);
1858 VG_(message)(Vg_DebugMsg, "BBs Retranslated: %d\n",
1859 CLG_(stat).bb_retranslations);
1860 VG_(message)(Vg_DebugMsg, "Distinct instrs: %d\n",
1861 CLG_(stat).distinct_instrs);
weidendo6a8aa582013-12-17 15:12:06 +00001862
1863 VG_(message)(Vg_DebugMsg, "LRU Contxt Misses: %d\n",
1864 CLG_(stat).cxt_lru_misses);
1865 VG_(message)(Vg_DebugMsg, "LRU BBCC Misses: %d\n",
1866 CLG_(stat).bbcc_lru_misses);
1867 VG_(message)(Vg_DebugMsg, "LRU JCC Misses: %d\n",
1868 CLG_(stat).jcc_lru_misses);
1869 VG_(message)(Vg_DebugMsg, "BBs Executed: %llu\n",
1870 CLG_(stat).bb_executions);
1871 VG_(message)(Vg_DebugMsg, "Calls: %llu\n",
1872 CLG_(stat).call_counter);
1873 VG_(message)(Vg_DebugMsg, "CondJMP followed: %llu\n",
1874 CLG_(stat).jcnd_counter);
1875 VG_(message)(Vg_DebugMsg, "Boring JMPs: %llu\n",
1876 CLG_(stat).jump_counter);
1877 VG_(message)(Vg_DebugMsg, "Recursive calls: %llu\n",
1878 CLG_(stat).rec_call_counter);
1879 VG_(message)(Vg_DebugMsg, "Returns: %llu\n",
1880 CLG_(stat).ret_counter);
1881}
1882
weidendo320705f2010-07-02 19:56:23 +00001883
weidendoa17f2a32006-03-20 10:27:30 +00001884static
1885void finish(void)
1886{
florian5ee42a42014-11-06 21:43:44 +00001887 HChar fmt[128]; // large enough
weidendo320705f2010-07-02 19:56:23 +00001888 Int l1, l2, l3;
1889 FullCost total;
weidendoa17f2a32006-03-20 10:27:30 +00001890
1891 CLG_DEBUG(0, "finish()\n");
1892
1893 (*CLG_(cachesim).finish)();
1894
1895 /* pop all remaining items from CallStack for correct sum
1896 */
1897 CLG_(forall_threads)(unwind_thread);
sewardje45a7992006-10-17 02:24:18 +00001898
weidendoa17f2a32006-03-20 10:27:30 +00001899 CLG_(dump_profile)(0, False);
sewardje45a7992006-10-17 02:24:18 +00001900
weidendoa17f2a32006-03-20 10:27:30 +00001901 if (VG_(clo_verbosity) == 0) return;
1902
sewardj2d9e8742009-08-07 15:46:56 +00001903 if (VG_(clo_stats)) {
sewardj0f33adf2009-07-15 14:51:03 +00001904 VG_(message)(Vg_DebugMsg, "\n");
weidendo6a8aa582013-12-17 15:12:06 +00001905 clg_print_stats();
1906 VG_(message)(Vg_DebugMsg, "\n");
weidendoa17f2a32006-03-20 10:27:30 +00001907 }
1908
florian5ee42a42014-11-06 21:43:44 +00001909 HChar *evmap = CLG_(eventmapping_as_string)(CLG_(dumpmap));
1910 VG_(message)(Vg_UserMsg, "Events : %s\n", evmap);
1911 VG_(free)(evmap);
1912 HChar *mcost = CLG_(mappingcost_as_string)(CLG_(dumpmap), CLG_(total_cost));
1913 VG_(message)(Vg_UserMsg, "Collected : %s\n", mcost);
1914 VG_(free)(mcost);
sewardj0f33adf2009-07-15 14:51:03 +00001915 VG_(message)(Vg_UserMsg, "\n");
weidendoa17f2a32006-03-20 10:27:30 +00001916
weidendo320705f2010-07-02 19:56:23 +00001917 /* determine value widths for statistics */
1918 total = CLG_(total_cost);
1919 l1 = ULong_width( total[fullOffset(EG_IR)] );
1920 l2 = l3 = 0;
1921 if (CLG_(clo).simulate_cache) {
1922 l2 = ULong_width( total[fullOffset(EG_DR)] );
1923 l3 = ULong_width( total[fullOffset(EG_DW)] );
1924 }
1925 if (CLG_(clo).simulate_branch) {
1926 int l2b = ULong_width( total[fullOffset(EG_BC)] );
1927 int l3b = ULong_width( total[fullOffset(EG_BI)] );
1928 if (l2b > l2) l2 = l2b;
1929 if (l3b > l3) l3 = l3b;
1930 }
1931
1932 /* Make format string, getting width right for numbers */
1933 VG_(sprintf)(fmt, "%%s %%,%dllu\n", l1);
1934
1935 /* Always print this */
1936 VG_(umsg)(fmt, "I refs: ", total[fullOffset(EG_IR)] );
1937
1938 if (CLG_(clo).simulate_cache)
1939 (*CLG_(cachesim).printstat)(l1, l2, l3);
1940
1941 if (CLG_(clo).simulate_branch)
1942 branchsim_printstat(l1, l2, l3);
1943
weidendoa17f2a32006-03-20 10:27:30 +00001944}
1945
1946
1947void CLG_(fini)(Int exitcode)
1948{
1949 finish();
1950}
1951
1952
1953/*--------------------------------------------------------------------*/
1954/*--- Setup ---*/
1955/*--------------------------------------------------------------------*/
1956
njn3e32c872006-12-24 07:51:17 +00001957static void clg_start_client_code_callback ( ThreadId tid, ULong blocks_done )
sewardj97561812006-12-23 01:21:12 +00001958{
weidendo134657c2006-12-23 23:11:20 +00001959 static ULong last_blocks_done = 0;
1960
sewardj97561812006-12-23 01:21:12 +00001961 if (0)
njn3e32c872006-12-24 07:51:17 +00001962 VG_(printf)("%d R %llu\n", (Int)tid, blocks_done);
weidendo134657c2006-12-23 23:11:20 +00001963
1964 /* throttle calls to CLG_(run_thread) by number of BBs executed */
1965 if (blocks_done - last_blocks_done < 5000) return;
1966 last_blocks_done = blocks_done;
1967
1968 CLG_(run_thread)( tid );
sewardj97561812006-12-23 01:21:12 +00001969}
1970
weidendoa17f2a32006-03-20 10:27:30 +00001971static
1972void CLG_(post_clo_init)(void)
1973{
philippe5b240c22012-08-14 22:28:31 +00001974 if (VG_(clo_vex_control).iropt_register_updates
1975 != VexRegUpdSpAtMemAccess) {
1976 CLG_DEBUG(1, " Using user specified value for "
1977 "--vex-iropt-register-updates\n");
1978 } else {
1979 CLG_DEBUG(1,
1980 " Using default --vex-iropt-register-updates="
1981 "sp-at-mem-access\n");
1982 }
weidendoa17f2a32006-03-20 10:27:30 +00001983
philippe5b240c22012-08-14 22:28:31 +00001984 if (VG_(clo_vex_control).iropt_unroll_thresh != 0) {
1985 VG_(message)(Vg_UserMsg,
1986 "callgrind only works with --vex-iropt-unroll-thresh=0\n"
1987 "=> resetting it back to 0\n");
1988 VG_(clo_vex_control).iropt_unroll_thresh = 0; // cannot be overriden.
1989 }
1990 if (VG_(clo_vex_control).guest_chase_thresh != 0) {
1991 VG_(message)(Vg_UserMsg,
1992 "callgrind only works with --vex-guest-chase-thresh=0\n"
1993 "=> resetting it back to 0\n");
1994 VG_(clo_vex_control).guest_chase_thresh = 0; // cannot be overriden.
1995 }
1996
weidendoa17f2a32006-03-20 10:27:30 +00001997 CLG_DEBUG(1, " dump threads: %s\n", CLG_(clo).separate_threads ? "Yes":"No");
1998 CLG_DEBUG(1, " call sep. : %d\n", CLG_(clo).separate_callers);
1999 CLG_DEBUG(1, " rec. sep. : %d\n", CLG_(clo).separate_recursions);
2000
2001 if (!CLG_(clo).dump_line && !CLG_(clo).dump_instr && !CLG_(clo).dump_bb) {
sewardj0f33adf2009-07-15 14:51:03 +00002002 VG_(message)(Vg_UserMsg, "Using source line as position.\n");
weidendoa17f2a32006-03-20 10:27:30 +00002003 CLG_(clo).dump_line = True;
2004 }
2005
weidendo4ce5e792006-09-20 21:29:39 +00002006 CLG_(init_dumps)();
weidendoa17f2a32006-03-20 10:27:30 +00002007
2008 (*CLG_(cachesim).post_clo_init)();
2009
weidendo5bba5252010-06-09 22:32:53 +00002010 CLG_(init_eventsets)();
weidendoa17f2a32006-03-20 10:27:30 +00002011 CLG_(init_statistics)(& CLG_(stat));
2012 CLG_(init_cost_lz)( CLG_(sets).full, &CLG_(total_cost) );
2013
2014 /* initialize hash tables */
2015 CLG_(init_obj_table)();
2016 CLG_(init_cxt_table)();
2017 CLG_(init_bb_hash)();
2018
2019 CLG_(init_threads)();
2020 CLG_(run_thread)(1);
2021
2022 CLG_(instrument_state) = CLG_(clo).instrument_atstart;
2023
weidendoca472c52006-03-31 19:34:51 +00002024 if (VG_(clo_verbosity > 0)) {
weidendoca472c52006-03-31 19:34:51 +00002025 VG_(message)(Vg_UserMsg,
philippecffe2a52014-01-11 13:56:48 +00002026 "For interactive control, run 'callgrind_control%s%s -h'.\n",
2027 (VG_(arg_vgdb_prefix) ? " " : ""),
2028 (VG_(arg_vgdb_prefix) ? VG_(arg_vgdb_prefix) : ""));
weidendoca472c52006-03-31 19:34:51 +00002029 }
weidendoa17f2a32006-03-20 10:27:30 +00002030}
2031
2032static
2033void CLG_(pre_clo_init)(void)
2034{
2035 VG_(details_name) ("Callgrind");
weidendoca472c52006-03-31 19:34:51 +00002036 VG_(details_version) (NULL);
weidendoa17f2a32006-03-20 10:27:30 +00002037 VG_(details_description) ("a call-graph generating cache profiler");
sewardj0f157dd2013-10-18 14:27:36 +00002038 VG_(details_copyright_author)("Copyright (C) 2002-2013, and GNU GPL'd, "
weidendoca472c52006-03-31 19:34:51 +00002039 "by Josef Weidendorfer et al.");
weidendodb70ed72006-05-27 15:39:45 +00002040 VG_(details_bug_reports_to) (VG_BUGS_TO);
sewardje45a7992006-10-17 02:24:18 +00002041 VG_(details_avg_translation_sizeB) ( 500 );
weidendoa17f2a32006-03-20 10:27:30 +00002042
philippe5b240c22012-08-14 22:28:31 +00002043 VG_(clo_vex_control).iropt_register_updates
2044 = VexRegUpdSpAtMemAccess; // overridable by the user.
2045 VG_(clo_vex_control).iropt_unroll_thresh = 0; // cannot be overriden.
2046 VG_(clo_vex_control).guest_chase_thresh = 0; // cannot be overriden.
2047
weidendoa17f2a32006-03-20 10:27:30 +00002048 VG_(basic_tool_funcs) (CLG_(post_clo_init),
2049 CLG_(instrument),
2050 CLG_(fini));
2051
sewardj0b9d74a2006-12-24 02:24:11 +00002052 VG_(needs_superblock_discards)(clg_discard_superblock_info);
weidendoa17f2a32006-03-20 10:27:30 +00002053
2054
2055 VG_(needs_command_line_options)(CLG_(process_cmd_line_option),
2056 CLG_(print_usage),
2057 CLG_(print_debug_usage));
2058
2059 VG_(needs_client_requests)(CLG_(handle_client_request));
weidendo6a8aa582013-12-17 15:12:06 +00002060 VG_(needs_print_stats) (clg_print_stats);
weidendoa17f2a32006-03-20 10:27:30 +00002061 VG_(needs_syscall_wrapper)(CLG_(pre_syscalltime),
2062 CLG_(post_syscalltime));
2063
njn3e32c872006-12-24 07:51:17 +00002064 VG_(track_start_client_code) ( & clg_start_client_code_callback );
2065 VG_(track_pre_deliver_signal) ( & CLG_(pre_signal) );
2066 VG_(track_post_deliver_signal)( & CLG_(post_signal) );
weidendoa17f2a32006-03-20 10:27:30 +00002067
2068 CLG_(set_clo_defaults)();
2069}
2070
2071VG_DETERMINE_INTERFACE_VERSION(CLG_(pre_clo_init))
2072
2073/*--------------------------------------------------------------------*/
2074/*--- end main.c ---*/
2075/*--------------------------------------------------------------------*/