1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Callgrind ---*/ 4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- main.c ---*/ 5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This file is part of Callgrind, a Valgrind tool for call graph 9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown profiling programs. 10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 11663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Copyright (C) 2002-2012, Josef Weidendorfer (Josef.Weidendorfer@gmx.de) 12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This tool is derived from and contains code from Cachegrind 14663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Copyright (C) 2002-2012 Nicholas Nethercote (njn@valgrind.org) 15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is free software; you can redistribute it and/or 17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown modify it under the terms of the GNU General Public License as 18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown published by the Free Software Foundation; either version 2 of the 19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown License, or (at your option) any later version. 20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is distributed in the hope that it will be useful, but 22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown WITHOUT ANY WARRANTY; without even the implied warranty of 23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown General Public License for more details. 25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown You should have received a copy of the GNU General Public License 27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown along with this program; if not, write to the Free Software 28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 02111-1307, USA. 30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The GNU General Public License is contained in the file COPYING. 32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "config.h" 35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "callgrind.h" 36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "global.h" 37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 38b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_tool_threadstate.h" 39b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_tool_gdbserver.h" 40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "cg_branchpred.c" 42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Global variables ---*/ 45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* for all threads */ 48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownCommandLineOptions CLG_(clo); 49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownStatistics CLG_(stat); 50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool CLG_(instrument_state) = True; /* Instrumentation on ? */ 51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* thread and signal handler specific */ 53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownexec_state CLG_(current_state); 54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 55663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* min of L1 and LL cache line sizes. This only gets set to a 56663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng non-zero value if we are doing cache simulation. */ 57663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengInt CLG_(min_line_size) = 0; 58663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Statistics ---*/ 62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void CLG_(init_statistics)(Statistics* s) 65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s->call_counter = 0; 67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s->jcnd_counter = 0; 68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s->jump_counter = 0; 69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s->rec_call_counter = 0; 70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s->ret_counter = 0; 71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s->bb_executions = 0; 72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s->context_counter = 0; 74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s->bb_retranslations = 0; 75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s->distinct_objs = 0; 77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s->distinct_files = 0; 78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s->distinct_fns = 0; 79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s->distinct_contexts = 0; 80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s->distinct_bbs = 0; 81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s->distinct_bbccs = 0; 82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s->distinct_instrs = 0; 83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s->distinct_skips = 0; 84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s->bb_hash_resizes = 0; 86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s->bbcc_hash_resizes = 0; 87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s->jcc_hash_resizes = 0; 88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s->cxt_hash_resizes = 0; 89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s->fn_array_resizes = 0; 90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s->call_stack_resizes = 0; 91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s->fn_stack_resizes = 0; 92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s->full_debug_BBs = 0; 94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s->file_line_debug_BBs = 0; 95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s->fn_name_debug_BBs = 0; 96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s->no_debug_BBs = 0; 97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s->bbcc_lru_misses = 0; 98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s->jcc_lru_misses = 0; 99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s->cxt_lru_misses = 0; 100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s->bbcc_clones = 0; 101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Simple callbacks (not cache similator) ---*/ 106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVG_REGPARM(1) 109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void log_global_event(InstrInfo* ii) 110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong* cost_Bus; 112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_DEBUG(6, "log_global_event: Ir %#lx/%u\n", 114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(bb_base) + ii->instr_offset, ii->instr_size); 115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!CLG_(current_state).collect) return; 117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_ASSERT( (ii->eventset->mask & (1u<<EG_BUS))>0 ); 119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(current_state).cost[ fullOffset(EG_BUS) ]++; 121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (CLG_(current_state).nonskipped) 123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cost_Bus = CLG_(current_state).nonskipped->skipped + fullOffset(EG_BUS); 124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cost_Bus = CLG_(cost_base) + ii->cost_offset + ii->eventset->offset[EG_BUS]; 126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cost_Bus[0]++; 127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* For branches, we consult two different predictors, one which 131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown predicts taken/untaken for conditional branches, and the other 132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown which predicts the branch target address for indirect branches 133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (jump-to-register style ones). */ 134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic VG_REGPARM(2) 136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid log_cond_branch(InstrInfo* ii, Word taken) 137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool miss; 139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int fullOffset_Bc; 140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong* cost_Bc; 141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_DEBUG(6, "log_cond_branch: Ir %#lx, taken %lu\n", 143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(bb_base) + ii->instr_offset, taken); 144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown miss = 1 & do_cond_branch_predict(CLG_(bb_base) + ii->instr_offset, taken); 146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!CLG_(current_state).collect) return; 148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_ASSERT( (ii->eventset->mask & (1u<<EG_BC))>0 ); 150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (CLG_(current_state).nonskipped) 152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cost_Bc = CLG_(current_state).nonskipped->skipped + fullOffset(EG_BC); 153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cost_Bc = CLG_(cost_base) + ii->cost_offset + ii->eventset->offset[EG_BC]; 155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fullOffset_Bc = fullOffset(EG_BC); 157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(current_state).cost[ fullOffset_Bc ]++; 158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cost_Bc[0]++; 159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (miss) { 160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(current_state).cost[ fullOffset_Bc+1 ]++; 161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cost_Bc[1]++; 162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic VG_REGPARM(2) 166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid log_ind_branch(InstrInfo* ii, UWord actual_dst) 167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool miss; 169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int fullOffset_Bi; 170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong* cost_Bi; 171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_DEBUG(6, "log_ind_branch: Ir %#lx, dst %#lx\n", 173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(bb_base) + ii->instr_offset, actual_dst); 174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown miss = 1 & do_ind_branch_predict(CLG_(bb_base) + ii->instr_offset, actual_dst); 176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!CLG_(current_state).collect) return; 178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_ASSERT( (ii->eventset->mask & (1u<<EG_BI))>0 ); 180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (CLG_(current_state).nonskipped) 182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cost_Bi = CLG_(current_state).nonskipped->skipped + fullOffset(EG_BI); 183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cost_Bi = CLG_(cost_base) + ii->cost_offset + ii->eventset->offset[EG_BI]; 185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fullOffset_Bi = fullOffset(EG_BI); 187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(current_state).cost[ fullOffset_Bi ]++; 188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cost_Bi[0]++; 189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (miss) { 190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(current_state).cost[ fullOffset_Bi+1 ]++; 191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cost_Bi[1]++; 192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Instrumentation structures and event queue handling ---*/ 197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Maintain an ordered list of memory events which are outstanding, in 200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the sense that no IR has yet been generated to do the relevant 201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown helper calls. The BB is scanned top to bottom and memory events 202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown are added to the end of the list, merging with the most recent 203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown notified event where possible (Dw immediately following Dr and 204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown having the same size and EA can be merged). 205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This merging is done so that for architectures which have 207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown load-op-store instructions (x86, amd64), the insn is treated as if 208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown it makes just one memory reference (a modify), rather than two (a 209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown read followed by a write at the same address). 210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown At various points the list will need to be flushed, that is, IR 212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown generated from it. That must happen before any possible exit from 213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the block (the end, or an IRStmt_Exit). Flushing also takes place 214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown when there is no space to add a new event. 215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown If we require the simulation statistics to be up to date with 217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown respect to possible memory exceptions, then the list would have to 218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown be flushed before each memory reference. That would however lose 219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown performance by inhibiting event-merging during flushing. 220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Flushing the list consists of walking it start to end and emitting 222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown instrumentation IR for each event, in the order in which they 223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown appear. It may be possible to emit a single call for two adjacent 224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown events in order to reduce the number of helper function calls made. 225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown For example, it could well be profitable to handle two adjacent Ir 226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown events with a single helper call. */ 227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef 229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr 230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRAtom; 231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef 233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown enum { 234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Ev_Ir, // Instruction read 235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Ev_Dr, // Data read 236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Ev_Dw, // Data write 237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Ev_Dm, // Data modify (read then write) 238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Ev_Bc, // branch conditional 239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Ev_Bi, // branch indirect (to unknown destination) 240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Ev_G // Global bus event 241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown EventTag; 243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef 245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct { 246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown EventTag tag; 247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown InstrInfo* inode; 248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown union { 249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct { 250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } Ir; 251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct { 252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRAtom* ea; 253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int szB; 254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } Dr; 255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct { 256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRAtom* ea; 257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int szB; 258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } Dw; 259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct { 260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRAtom* ea; 261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int szB; 262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } Dm; 263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct { 264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRAtom* taken; /* :: Ity_I1 */ 265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } Bc; 266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct { 267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRAtom* dst; 268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } Bi; 269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct { 270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } G; 271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } Ev; 272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Event; 274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void init_Event ( Event* ev ) { 276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(ev, 0, sizeof(Event)); 277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* get_Event_dea ( Event* ev ) { 280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (ev->tag) { 281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ev_Dr: return ev->Ev.Dr.ea; 282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ev_Dw: return ev->Ev.Dw.ea; 283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ev_Dm: return ev->Ev.Dm.ea; 284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: tl_assert(0); 285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int get_Event_dszB ( Event* ev ) { 289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (ev->tag) { 290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ev_Dr: return ev->Ev.Dr.szB; 291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ev_Dw: return ev->Ev.Dw.szB; 292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ev_Dm: return ev->Ev.Dm.szB; 293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: tl_assert(0); 294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Up to this many unnotified events are allowed. Number is 299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arbitrary. Larger numbers allow more event merging to occur, but 300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown potentially induce more spilling due to extending live ranges of 301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown address temporaries. */ 302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define N_EVENTS 16 303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* A struct which holds all the running state during instrumentation. 306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Mostly to avoid passing loads of parameters everywhere. */ 307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct { 308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* The current outstanding-memory-event list. */ 309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Event events[N_EVENTS]; 310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int events_used; 311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* The array of InstrInfo's is part of BB struct. */ 313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown BB* bb; 314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* BB seen before (ie. re-instrumentation) */ 316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool seen_before; 317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Number InstrInfo bins 'used' so far. */ 319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt ii_index; 320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // current offset of guest instructions from BB start 322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt instr_offset; 323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* The output SB being constructed. */ 325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRSB* sbOut; 326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} ClgState; 327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void showEvent ( Event* ev ) 330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (ev->tag) { 332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ev_Ir: 333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("Ir (InstrInfo %p) at +%d\n", 334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ev->inode, ev->inode->instr_offset); 335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ev_Dr: 337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("Dr (InstrInfo %p) at +%d %d EA=", 338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ev->inode, ev->inode->instr_offset, ev->Ev.Dr.szB); 339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIRExpr(ev->Ev.Dr.ea); 340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("\n"); 341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ev_Dw: 343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("Dw (InstrInfo %p) at +%d %d EA=", 344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ev->inode, ev->inode->instr_offset, ev->Ev.Dw.szB); 345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIRExpr(ev->Ev.Dw.ea); 346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("\n"); 347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ev_Dm: 349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("Dm (InstrInfo %p) at +%d %d EA=", 350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ev->inode, ev->inode->instr_offset, ev->Ev.Dm.szB); 351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIRExpr(ev->Ev.Dm.ea); 352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("\n"); 353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ev_Bc: 355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("Bc %p GA=", ev->inode); 356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIRExpr(ev->Ev.Bc.taken); 357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("\n"); 358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ev_Bi: 360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("Bi %p DST=", ev->inode); 361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIRExpr(ev->Ev.Bi.dst); 362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("\n"); 363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ev_G: 365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("G %p\n", ev->inode); 366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(0); 369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate code for all outstanding memory events, and mark the queue 374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown empty. Code is generated into cgs->sbOut, and this activity 375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 'consumes' slots in cgs->bb. */ 376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void flushEvents ( ClgState* clgs ) 378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i, regparms, inew; 380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char* helperName; 381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void* helperAddr; 382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr** argv; 383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr* i_node_expr; 384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRDirty* di; 385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Event* ev; 386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Event* ev2; 387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Event* ev3; 388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!clgs->seen_before) { 390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // extend event sets as needed 391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // available sets: D0 Dr 392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for(i=0; i<clgs->events_used; i++) { 393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ev = &clgs->events[i]; 394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(ev->tag) { 395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ev_Ir: 396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Ir event always is first for a guest instruction 397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_ASSERT(ev->inode->eventset == 0); 398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ev->inode->eventset = CLG_(sets).base; 399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ev_Dr: 401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // extend event set by Dr counters 402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ev->inode->eventset = CLG_(add_event_group)(ev->inode->eventset, 403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown EG_DR); 404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ev_Dw: 406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ev_Dm: 407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // extend event set by Dw counters 408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ev->inode->eventset = CLG_(add_event_group)(ev->inode->eventset, 409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown EG_DW); 410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ev_Bc: 412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // extend event set by Bc counters 413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ev->inode->eventset = CLG_(add_event_group)(ev->inode->eventset, 414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown EG_BC); 415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ev_Bi: 417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // extend event set by Bi counters 418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ev->inode->eventset = CLG_(add_event_group)(ev->inode->eventset, 419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown EG_BI); 420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ev_G: 422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // extend event set by Bus counter 423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ev->inode->eventset = CLG_(add_event_group)(ev->inode->eventset, 424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown EG_BUS); 425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(0); 428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for(i = 0; i < clgs->events_used; i = inew) { 433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown helperName = NULL; 435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown helperAddr = NULL; 436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argv = NULL; 437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown regparms = 0; 438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* generate IR to notify event i and possibly the ones 440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown immediately following it. */ 441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(i >= 0 && i < clgs->events_used); 442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ev = &clgs->events[i]; 444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ev2 = ( i < clgs->events_used-1 ? &clgs->events[i+1] : NULL ); 445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ev3 = ( i < clgs->events_used-2 ? &clgs->events[i+2] : NULL ); 446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_DEBUGIF(5) { 448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)(" flush "); 449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown showEvent( ev ); 450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i_node_expr = mkIRExpr_HWord( (HWord)ev->inode ); 453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Decide on helper fn to call and args to pass it, and advance 455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i appropriately. 456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Dm events have same effect as Dw events */ 457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (ev->tag) { 458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ev_Ir: 459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Merge an Ir with a following Dr. */ 460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ev2 && ev2->tag == Ev_Dr) { 461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Why is this true? It's because we're merging an Ir 462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown with a following Dr. The Ir derives from the 463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown instruction's IMark and the Dr from data 464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown references which follow it. In short it holds 465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown because each insn starts with an IMark, hence an 466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Ev_Ir, and so these Dr must pertain to the 467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown immediately preceding Ir. Same applies to analogous 468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown assertions in the subsequent cases. */ 469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(ev2->inode == ev->inode); 470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown helperName = CLG_(cachesim).log_1I1Dr_name; 471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown helperAddr = CLG_(cachesim).log_1I1Dr; 472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argv = mkIRExprVec_3( i_node_expr, 473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown get_Event_dea(ev2), 474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkIRExpr_HWord( get_Event_dszB(ev2) ) ); 475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown regparms = 3; 476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown inew = i+2; 477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Merge an Ir with a following Dw/Dm. */ 479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ev2 && (ev2->tag == Ev_Dw || ev2->tag == Ev_Dm)) { 481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(ev2->inode == ev->inode); 482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown helperName = CLG_(cachesim).log_1I1Dw_name; 483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown helperAddr = CLG_(cachesim).log_1I1Dw; 484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argv = mkIRExprVec_3( i_node_expr, 485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown get_Event_dea(ev2), 486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkIRExpr_HWord( get_Event_dszB(ev2) ) ); 487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown regparms = 3; 488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown inew = i+2; 489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Merge an Ir with two following Irs. */ 491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ev2 && ev3 && ev2->tag == Ev_Ir && ev3->tag == Ev_Ir) { 493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown helperName = CLG_(cachesim).log_3I0D_name; 494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown helperAddr = CLG_(cachesim).log_3I0D; 495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argv = mkIRExprVec_3( i_node_expr, 496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkIRExpr_HWord( (HWord)ev2->inode ), 497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkIRExpr_HWord( (HWord)ev3->inode ) ); 498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown regparms = 3; 499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown inew = i+3; 500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Merge an Ir with one following Ir. */ 502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ev2 && ev2->tag == Ev_Ir) { 504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown helperName = CLG_(cachesim).log_2I0D_name; 505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown helperAddr = CLG_(cachesim).log_2I0D; 506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argv = mkIRExprVec_2( i_node_expr, 507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkIRExpr_HWord( (HWord)ev2->inode ) ); 508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown regparms = 2; 509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown inew = i+2; 510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* No merging possible; emit as-is. */ 512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else { 513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown helperName = CLG_(cachesim).log_1I0D_name; 514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown helperAddr = CLG_(cachesim).log_1I0D; 515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argv = mkIRExprVec_1( i_node_expr ); 516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown regparms = 1; 517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown inew = i+1; 518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ev_Dr: 521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Data read or modify */ 522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown helperName = CLG_(cachesim).log_0I1Dr_name; 523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown helperAddr = CLG_(cachesim).log_0I1Dr; 524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argv = mkIRExprVec_3( i_node_expr, 525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown get_Event_dea(ev), 526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkIRExpr_HWord( get_Event_dszB(ev) ) ); 527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown regparms = 3; 528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown inew = i+1; 529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ev_Dw: 531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ev_Dm: 532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Data write */ 533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown helperName = CLG_(cachesim).log_0I1Dw_name; 534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown helperAddr = CLG_(cachesim).log_0I1Dw; 535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argv = mkIRExprVec_3( i_node_expr, 536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown get_Event_dea(ev), 537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkIRExpr_HWord( get_Event_dszB(ev) ) ); 538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown regparms = 3; 539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown inew = i+1; 540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ev_Bc: 542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Conditional branch */ 543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown helperName = "log_cond_branch"; 544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown helperAddr = &log_cond_branch; 545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argv = mkIRExprVec_2( i_node_expr, ev->Ev.Bc.taken ); 546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown regparms = 2; 547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown inew = i+1; 548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ev_Bi: 550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Branch to an unknown destination */ 551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown helperName = "log_ind_branch"; 552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown helperAddr = &log_ind_branch; 553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argv = mkIRExprVec_2( i_node_expr, ev->Ev.Bi.dst ); 554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown regparms = 2; 555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown inew = i+1; 556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ev_G: 558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Global bus event (CAS, LOCK-prefix, LL-SC, etc) */ 559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown helperName = "log_global_event"; 560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown helperAddr = &log_global_event; 561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argv = mkIRExprVec_1( i_node_expr ); 562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown regparms = 1; 563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown inew = i+1; 564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(0); 567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_DEBUGIF(5) { 570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (inew > i+1) { 571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)(" merge "); 572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown showEvent( ev2 ); 573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (inew > i+2) { 575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)(" merge "); 576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown showEvent( ev3 ); 577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (helperAddr) 579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)(" call %s (%p)\n", 580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown helperName, helperAddr); 581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* helper could be unset depending on the simulator used */ 584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (helperAddr == 0) continue; 585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Add the helper. */ 587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(helperName); 588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(helperAddr); 589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(argv); 590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di = unsafeIRDirty_0_N( regparms, 591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown helperName, VG_(fnptr_to_fnentry)( helperAddr ), 592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argv ); 593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( clgs->sbOut, IRStmt_Dirty(di) ); 594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown clgs->events_used = 0; 597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void addEvent_Ir ( ClgState* clgs, InstrInfo* inode ) 600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Event* evt; 602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(clgs->seen_before || (inode->eventset == 0)); 603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!CLG_(clo).simulate_cache) return; 604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (clgs->events_used == N_EVENTS) 606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown flushEvents(clgs); 607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(clgs->events_used >= 0 && clgs->events_used < N_EVENTS); 608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown evt = &clgs->events[clgs->events_used]; 609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown init_Event(evt); 610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown evt->tag = Ev_Ir; 611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown evt->inode = inode; 612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown clgs->events_used++; 613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid addEvent_Dr ( ClgState* clgs, InstrInfo* inode, Int datasize, IRAtom* ea ) 617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Event* evt; 619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(isIRAtom(ea)); 620663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng tl_assert(datasize >= 1); 621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!CLG_(clo).simulate_cache) return; 622663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng tl_assert(datasize <= CLG_(min_line_size)); 623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (clgs->events_used == N_EVENTS) 625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown flushEvents(clgs); 626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(clgs->events_used >= 0 && clgs->events_used < N_EVENTS); 627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown evt = &clgs->events[clgs->events_used]; 628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown init_Event(evt); 629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown evt->tag = Ev_Dr; 630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown evt->inode = inode; 631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown evt->Ev.Dr.szB = datasize; 632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown evt->Ev.Dr.ea = ea; 633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown clgs->events_used++; 634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid addEvent_Dw ( ClgState* clgs, InstrInfo* inode, Int datasize, IRAtom* ea ) 638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Event* lastEvt; 640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Event* evt; 641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(isIRAtom(ea)); 642663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng tl_assert(datasize >= 1); 643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!CLG_(clo).simulate_cache) return; 644663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng tl_assert(datasize <= CLG_(min_line_size)); 645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Is it possible to merge this write with the preceding read? */ 647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lastEvt = &clgs->events[clgs->events_used-1]; 648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (clgs->events_used > 0 649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && lastEvt->tag == Ev_Dr 650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && lastEvt->Ev.Dr.szB == datasize 651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && lastEvt->inode == inode 652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && eqIRAtom(lastEvt->Ev.Dr.ea, ea)) 653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lastEvt->tag = Ev_Dm; 655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* No. Add as normal. */ 659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (clgs->events_used == N_EVENTS) 660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown flushEvents(clgs); 661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(clgs->events_used >= 0 && clgs->events_used < N_EVENTS); 662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown evt = &clgs->events[clgs->events_used]; 663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown init_Event(evt); 664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown evt->tag = Ev_Dw; 665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown evt->inode = inode; 666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown evt->Ev.Dw.szB = datasize; 667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown evt->Ev.Dw.ea = ea; 668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown clgs->events_used++; 669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid addEvent_Bc ( ClgState* clgs, InstrInfo* inode, IRAtom* guard ) 673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Event* evt; 675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(isIRAtom(guard)); 676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(typeOfIRExpr(clgs->sbOut->tyenv, guard) 677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown == (sizeof(HWord)==4 ? Ity_I32 : Ity_I64)); 678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!CLG_(clo).simulate_branch) return; 679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (clgs->events_used == N_EVENTS) 681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown flushEvents(clgs); 682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(clgs->events_used >= 0 && clgs->events_used < N_EVENTS); 683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown evt = &clgs->events[clgs->events_used]; 684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown init_Event(evt); 685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown evt->tag = Ev_Bc; 686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown evt->inode = inode; 687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown evt->Ev.Bc.taken = guard; 688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown clgs->events_used++; 689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid addEvent_Bi ( ClgState* clgs, InstrInfo* inode, IRAtom* whereTo ) 693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Event* evt; 695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(isIRAtom(whereTo)); 696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(typeOfIRExpr(clgs->sbOut->tyenv, whereTo) 697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown == (sizeof(HWord)==4 ? Ity_I32 : Ity_I64)); 698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!CLG_(clo).simulate_branch) return; 699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (clgs->events_used == N_EVENTS) 701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown flushEvents(clgs); 702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(clgs->events_used >= 0 && clgs->events_used < N_EVENTS); 703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown evt = &clgs->events[clgs->events_used]; 704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown init_Event(evt); 705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown evt->tag = Ev_Bi; 706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown evt->inode = inode; 707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown evt->Ev.Bi.dst = whereTo; 708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown clgs->events_used++; 709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid addEvent_G ( ClgState* clgs, InstrInfo* inode ) 713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Event* evt; 715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!CLG_(clo).collect_bus) return; 716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (clgs->events_used == N_EVENTS) 718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown flushEvents(clgs); 719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(clgs->events_used >= 0 && clgs->events_used < N_EVENTS); 720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown evt = &clgs->events[clgs->events_used]; 721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown init_Event(evt); 722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown evt->tag = Ev_G; 723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown evt->inode = inode; 724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown clgs->events_used++; 725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Initialise or check (if already seen before) an InstrInfo for next insn. 728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown We only can set instr_offset/instr_size here. The required event set and 729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown resulting cost offset depend on events (Ir/Dr/Dw/Dm) in guest 730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown instructions. The event set is extended as required on flush of the event 731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown queue (when Dm events were determined), cost offsets are determined at 732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown end of BB instrumentation. */ 733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInstrInfo* next_InstrInfo ( ClgState* clgs, UInt instr_size ) 735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown InstrInfo* ii; 737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(clgs->ii_index >= 0); 738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(clgs->ii_index < clgs->bb->instr_count); 739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ii = &clgs->bb->instr[ clgs->ii_index ]; 740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (clgs->seen_before) { 742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_ASSERT(ii->instr_offset == clgs->instr_offset); 743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_ASSERT(ii->instr_size == instr_size); 744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else { 746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ii->instr_offset = clgs->instr_offset; 747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ii->instr_size = instr_size; 748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ii->cost_offset = 0; 749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ii->eventset = 0; 750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown clgs->ii_index++; 753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown clgs->instr_offset += instr_size; 754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(stat).distinct_instrs++; 755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ii; 757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// return total number of cost values needed for this BB 760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUInt update_cost_offsets( ClgState* clgs ) 762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown InstrInfo* ii; 765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt cost_offset = 0; 766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_ASSERT(clgs->bb->instr_count == clgs->ii_index); 768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for(i=0; i<clgs->ii_index; i++) { 769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ii = &clgs->bb->instr[i]; 770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (clgs->seen_before) { 771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_ASSERT(ii->cost_offset == cost_offset); 772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else 773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ii->cost_offset = cost_offset; 774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cost_offset += ii->eventset ? ii->eventset->size : 0; 775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return cost_offset; 778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Instrumentation ---*/ 782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VG_BIGENDIAN) 785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define CLGEndness Iend_BE 786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VG_LITTLEENDIAN) 787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define CLGEndness Iend_LE 788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unknown endianness" 790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAddr IRConst2Addr(IRConst* con) 794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr addr; 796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sizeof(Addr) == 4) { 798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_ASSERT( con->tag == Ico_U32 ); 799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addr = con->Ico.U32; 800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else if (sizeof(Addr) == 8) { 802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_ASSERT( con->tag == Ico_U64 ); 803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addr = con->Ico.U64; 804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(tool_panic)("Callgrind: invalid Addr type"); 807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return addr; 809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* First pass over a BB to instrument, counting instructions and jumps 812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * This is needed for the size of the BB struct to allocate 813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * 814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Called from CLG_(get_bb) 815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid CLG_(collectBlockInfo)(IRSB* sbIn, 817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*INOUT*/ UInt* instrs, 818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*INOUT*/ UInt* cjmps, 819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*INOUT*/ Bool* cjmp_inverted) 820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRStmt* st; 823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr instrAddr =0, jumpDst; 824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt instrLen = 0; 825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool toNextInstr = False; 826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Ist_Exit has to be ignored in preamble code, before first IMark: 828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // preamble code is added by VEX for self modifying code, and has 829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // nothing to do with client code 830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool inPreamble = True; 831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!sbIn) return; 833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < sbIn->stmts_used; i++) { 835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown st = sbIn->stmts[i]; 836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (Ist_IMark == st->tag) { 837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown inPreamble = False; 838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown instrAddr = (Addr)ULong_to_Ptr(st->Ist.IMark.addr); 840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown instrLen = st->Ist.IMark.len; 841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (*instrs)++; 843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown toNextInstr = False; 844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (inPreamble) continue; 846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (Ist_Exit == st->tag) { 847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown jumpDst = IRConst2Addr(st->Ist.Exit.dst); 848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown toNextInstr = (jumpDst == instrAddr + instrLen); 849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (*cjmps)++; 851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* if the last instructions of BB conditionally jumps to next instruction 855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * (= first instruction of next BB in memory), this is a inverted by VEX. 856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *cjmp_inverted = toNextInstr; 858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid addConstMemStoreStmt( IRSB* bbOut, UWord addr, UInt val, IRType hWordTy) 862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( bbOut, 864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRStmt_Store(CLGEndness, 865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr_Const(hWordTy == Ity_I32 ? 866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRConst_U32( addr ) : 867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRConst_U64( addr )), 868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr_Const(IRConst_U32(val)) )); 869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* add helper call to setup_bbcc, with pointer to BB struct as argument 873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * 874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * precondition for setup_bbcc: 875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * - jmps_passed has number of cond.jumps passed in last executed BB 876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * - current_bbcc has a pointer to the BBCC of the last executed BB 877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Thus, if bbcc_jmpkind is != -1 (JmpNone), 878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * current_bbcc->bb->jmp_addr 879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * gives the address of the jump source. 880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * 881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * the setup does 2 things: 882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * - trace call: 883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * * Unwind own call stack, i.e sync our ESP with real ESP 884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * This is for ESP manipulation (longjmps, C++ exec handling) and RET 885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * * For CALLs or JMPs crossing objects, record call arg + 886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * push are on own call stack 887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * 888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * - prepare for cache log functions: 889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * set current_bbcc to BBCC that gets the costs for this BB execution 890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * attached 891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid addBBSetupCall(ClgState* clgs) 894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRDirty* di; 896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr *arg1, **argv; 897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg1 = mkIRExpr_HWord( (HWord)clgs->bb ); 899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argv = mkIRExprVec_1(arg1); 900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di = unsafeIRDirty_0_N( 1, "setup_bbcc", 901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(fnptr_to_fnentry)( & CLG_(setup_bbcc) ), 902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argv); 903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( clgs->sbOut, IRStmt_Dirty(di) ); 904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRSB* CLG_(instrument)( VgCallbackClosure* closure, 909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRSB* sbIn, 910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestLayout* layout, 911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestExtents* vge, 912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType gWordTy, IRType hWordTy ) 913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 914663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Int i; 915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRStmt* st; 916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr origAddr; 917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown InstrInfo* curr_inode = NULL; 918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ClgState clgs; 919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt cJumps = 0; 920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (gWordTy != hWordTy) { 923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We don't currently support this case. */ 924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(tool_panic)("host/guest word size mismatch"); 925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // No instrumentation if it is switched off 928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (! CLG_(instrument_state)) { 929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_DEBUG(5, "instrument(BB %#lx) [Instrumentation OFF]\n", 930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)closure->readdr); 931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sbIn; 932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_DEBUG(3, "+ instrument(BB %#lx)\n", (Addr)closure->readdr); 935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Set up SB for instrumented IR */ 937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown clgs.sbOut = deepCopyIRSBExceptStmts(sbIn); 938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Copy verbatim any IR preamble preceding the first IMark 940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i = 0; 941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (i < sbIn->stmts_used && sbIn->stmts[i]->tag != Ist_IMark) { 942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( clgs.sbOut, sbIn->stmts[i] ); 943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i++; 944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Get the first statement, and origAddr from it 947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_ASSERT(sbIn->stmts_used >0); 948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_ASSERT(i < sbIn->stmts_used); 949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown st = sbIn->stmts[i]; 950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_ASSERT(Ist_IMark == st->tag); 951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 952663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng origAddr = (Addr)st->Ist.IMark.addr + (Addr)st->Ist.IMark.delta; 953663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng CLG_ASSERT(origAddr == st->Ist.IMark.addr 954663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng + st->Ist.IMark.delta); // XXX: check no overflow 955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Get BB struct (creating if necessary). 957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * JS: The hash table is keyed with orig_addr_noredir -- important! 958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * JW: Why? If it is because of different chasing of the redirection, 959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * this is not needed, as chasing is switched off in callgrind 960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown clgs.bb = CLG_(get_bb)(origAddr, sbIn, &(clgs.seen_before)); 962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addBBSetupCall(&clgs); 964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Set up running state 966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown clgs.events_used = 0; 967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown clgs.ii_index = 0; 968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown clgs.instr_offset = 0; 969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (/*use current i*/; i < sbIn->stmts_used; i++) { 971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown st = sbIn->stmts[i]; 973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_ASSERT(isFlatIRStmt(st)); 974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (st->tag) { 976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_NoOp: 977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_AbiHint: 978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_Put: 979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_PutI: 980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_MBE: 981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_IMark: { 984663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Addr64 cia = st->Ist.IMark.addr + st->Ist.IMark.delta; 985663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Int isize = st->Ist.IMark.len; 986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_ASSERT(clgs.instr_offset == (Addr)cia - origAddr); 987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // If Vex fails to decode an instruction, the size will be zero. 988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Pretend otherwise. 989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isize == 0) isize = VG_MIN_INSTR_SZB; 990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Sanity-check size. 992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert( (VG_MIN_INSTR_SZB <= isize && isize <= VG_MAX_INSTR_SZB) 993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || VG_CLREQ_SZB == isize ); 994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Init the inode, record it as the current one. 996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Subsequent Dr/Dw/Dm events from the same instruction will 997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // also use it. 998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown curr_inode = next_InstrInfo (&clgs, isize); 999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addEvent_Ir( &clgs, curr_inode ); 1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_WrTmp: { 1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr* data = st->Ist.WrTmp.data; 1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (data->tag == Iex_Load) { 1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr* aexpr = data->Iex.Load.addr; 1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Note also, endianness info is ignored. I guess 1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // that's not interesting. 1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addEvent_Dr( &clgs, curr_inode, 1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sizeofIRType(data->Iex.Load.ty), aexpr ); 1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_Store: { 1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr* data = st->Ist.Store.data; 1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr* aexpr = st->Ist.Store.addr; 1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addEvent_Dw( &clgs, curr_inode, 1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sizeofIRType(typeOfIRExpr(sbIn->tyenv, data)), aexpr ); 1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_Dirty: { 1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int dataSize; 1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRDirty* d = st->Ist.Dirty.details; 1027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (d->mFx != Ifx_None) { 1028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* This dirty helper accesses memory. Collect the details. */ 1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(d->mAddr != NULL); 1030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(d->mSize != 0); 1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dataSize = d->mSize; 1032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Large (eg. 28B, 108B, 512B on x86) data-sized 1033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // instructions will be done inaccurately, but they're 1034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // very rare and this avoids errors from hitting more 1035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // than two cache lines in the simulation. 1036663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (CLG_(clo).simulate_cache && dataSize > CLG_(min_line_size)) 1037663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng dataSize = CLG_(min_line_size); 1038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) 1039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addEvent_Dr( &clgs, curr_inode, dataSize, d->mAddr ); 1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) 1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addEvent_Dw( &clgs, curr_inode, dataSize, d->mAddr ); 1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(d->mAddr == NULL); 1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(d->mSize == 0); 1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_CAS: { 1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We treat it as a read and a write of the location. I 1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown think that is the same behaviour as it was before IRCAS 1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown was introduced, since prior to that point, the Vex 1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown front ends would translate a lock-prefixed instruction 1054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown into a (normal) read followed by a (normal) write. */ 1055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int dataSize; 1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRCAS* cas = st->Ist.CAS.details; 1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_ASSERT(cas->addr && isIRAtom(cas->addr)); 1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_ASSERT(cas->dataLo); 1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dataSize = sizeofIRType(typeOfIRExpr(sbIn->tyenv, cas->dataLo)); 1060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (cas->dataHi != NULL) 1061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dataSize *= 2; /* since this is a doubleword-cas */ 1062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addEvent_Dr( &clgs, curr_inode, dataSize, cas->addr ); 1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addEvent_Dw( &clgs, curr_inode, dataSize, cas->addr ); 1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addEvent_G( &clgs, curr_inode ); 1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_LLSC: { 1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType dataTy; 1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (st->Ist.LLSC.storedata == NULL) { 1071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* LL */ 1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dataTy = typeOfIRTemp(sbIn->tyenv, st->Ist.LLSC.result); 1073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addEvent_Dr( &clgs, curr_inode, 1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sizeofIRType(dataTy), st->Ist.LLSC.addr ); 1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* SC */ 1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dataTy = typeOfIRExpr(sbIn->tyenv, st->Ist.LLSC.storedata); 1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addEvent_Dw( &clgs, curr_inode, 1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sizeofIRType(dataTy), st->Ist.LLSC.addr ); 1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* I don't know whether the global-bus-lock cost should 1081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown be attributed to the LL or the SC, but it doesn't 1082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown really matter since they always have to be used in 1083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pairs anyway. Hence put it (quite arbitrarily) on 1084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the SC. */ 1085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addEvent_G( &clgs, curr_inode ); 1086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_Exit: { 1091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool guest_exit, inverted; 1092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* VEX code generation sometimes inverts conditional branches. 1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * As Callgrind counts (conditional) jumps, it has to correct 1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * inversions. The heuristic is the following: 1096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * (1) Callgrind switches off SB chasing and unrolling, and 1097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * therefore it assumes that a candidate for inversion only is 1098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * the last conditional branch in an SB. 1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * (2) inversion is assumed if the branch jumps to the address of 1100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * the next guest instruction in memory. 1101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * This heuristic is precalculated in CLG_(collectBlockInfo)(). 1102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * 1103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Branching behavior is also used for branch prediction. Note that 1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * above heuristic is different from what Cachegrind does. 1105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Cachegrind uses (2) for all branches. 1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 1107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (cJumps+1 == clgs.bb->cjmp_count) 1108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown inverted = clgs.bb->cjmp_inverted; 1109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown inverted = False; 1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // call branch predictor only if this is a branch in guest code 1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown guest_exit = (st->Ist.Exit.jk == Ijk_Boring) || 1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (st->Ist.Exit.jk == Ijk_Call) || 1115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (st->Ist.Exit.jk == Ijk_Ret); 1116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (guest_exit) { 1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Stuff to widen the guard expression to a host word, so 1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown we can pass it to the branch predictor simulation 1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown functions easily. */ 1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType tyW = hWordTy; 1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IROp widen = tyW==Ity_I32 ? Iop_1Uto32 : Iop_1Uto64; 1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IROp opXOR = tyW==Ity_I32 ? Iop_Xor32 : Iop_Xor64; 1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRTemp guard1 = newIRTemp(clgs.sbOut->tyenv, Ity_I1); 1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRTemp guardW = newIRTemp(clgs.sbOut->tyenv, tyW); 1126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRTemp guard = newIRTemp(clgs.sbOut->tyenv, tyW); 1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr* one = tyW==Ity_I32 ? IRExpr_Const(IRConst_U32(1)) 1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown : IRExpr_Const(IRConst_U64(1)); 1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Widen the guard expression. */ 1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( clgs.sbOut, 1132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRStmt_WrTmp( guard1, st->Ist.Exit.guard )); 1133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( clgs.sbOut, 1134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRStmt_WrTmp( guardW, 1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr_Unop(widen, 1136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr_RdTmp(guard1))) ); 1137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If the exit is inverted, invert the sense of the guard. */ 1138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( 1139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown clgs.sbOut, 1140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRStmt_WrTmp( 1141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown guard, 1142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown inverted ? IRExpr_Binop(opXOR, IRExpr_RdTmp(guardW), one) 1143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown : IRExpr_RdTmp(guardW) 1144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown )); 1145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* And post the event. */ 1146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addEvent_Bc( &clgs, curr_inode, IRExpr_RdTmp(guard) ); 1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We may never reach the next statement, so need to flush 1150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown all outstanding transactions now. */ 1151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown flushEvents( &clgs ); 1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_ASSERT(clgs.ii_index>0); 1154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!clgs.seen_before) { 1155663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ClgJumpKind jk; 1156663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 1157663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (st->Ist.Exit.jk == Ijk_Call) jk = jk_Call; 1158663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng else if (st->Ist.Exit.jk == Ijk_Ret) jk = jk_Return; 1159663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng else { 1160663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (IRConst2Addr(st->Ist.Exit.dst) == 1161663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng origAddr + curr_inode->instr_offset + curr_inode->instr_size) 1162663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng jk = jk_None; 1163663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng else 1164663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng jk = jk_Jump; 1165663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 1166663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 1167663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng clgs.bb->jmp[cJumps].instr = clgs.ii_index-1; 1168663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng clgs.bb->jmp[cJumps].jmpkind = jk; 1169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Update global variable jmps_passed before the jump 1172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * A correction is needed if VEX inverted the last jump condition 1173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 1174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addConstMemStoreStmt( clgs.sbOut, 1175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (UWord) &CLG_(current_state).jmps_passed, 1176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown inverted ? cJumps+1 : cJumps, hWordTy); 1177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cJumps++; 1178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 1183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(0); 1184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Copy the original statement */ 1188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( clgs.sbOut, st ); 1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_DEBUGIF(5) { 1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)(" pass "); 1192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIRStmt(st); 1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("\n"); 1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Deal with branches to unknown destinations. Except ignore ones 1198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown which are function returns as we assume the return stack 1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown predictor never mispredicts. */ 1200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((sbIn->jumpkind == Ijk_Boring) || (sbIn->jumpkind == Ijk_Call)) { 1201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) { ppIRExpr( sbIn->next ); VG_(printf)("\n"); } 1202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (sbIn->next->tag) { 1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iex_Const: 1204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; /* boring - branch to known address */ 1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iex_RdTmp: 1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* looks like an indirect branch (branch to unknown) */ 1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addEvent_Bi( &clgs, curr_inode, sbIn->next ); 1208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* shouldn't happen - if the incoming IR is properly 1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown flattened, should only have tmp and const cases to 1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown consider. */ 1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(0); 1214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* At the end of the bb. Flush outstandings. */ 1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown flushEvents( &clgs ); 1219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Always update global variable jmps_passed at end of bb. 1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * A correction is needed if VEX inverted the last jump condition 1222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 1223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt jmps_passed = cJumps; 1225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (clgs.bb->cjmp_inverted) jmps_passed--; 1226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addConstMemStoreStmt( clgs.sbOut, 1227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (UWord) &CLG_(current_state).jmps_passed, 1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown jmps_passed, hWordTy); 1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_ASSERT(clgs.bb->cjmp_count == cJumps); 1231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_ASSERT(clgs.bb->instr_count = clgs.ii_index); 1232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1233663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Info for final exit from BB */ 1234663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng { 1235663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ClgJumpKind jk; 1236663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 1237663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (sbIn->jumpkind == Ijk_Call) jk = jk_Call; 1238663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng else if (sbIn->jumpkind == Ijk_Ret) jk = jk_Return; 1239663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng else { 1240663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng jk = jk_Jump; 1241663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if ((sbIn->next->tag == Iex_Const) && 1242663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng (IRConst2Addr(sbIn->next->Iex.Const.con) == 1243663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng origAddr + clgs.instr_offset)) 1244663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng jk = jk_None; 1245663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 1246663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng clgs.bb->jmp[cJumps].jmpkind = jk; 1247663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Instruction index of the call/ret at BB end 1248663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng * (it is wrong for fall-through, but does not matter) */ 1249663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng clgs.bb->jmp[cJumps].instr = clgs.ii_index-1; 1250663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 1251663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 1252663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* swap information of last exit with final exit if inverted */ 1253663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (clgs.bb->cjmp_inverted) { 1254663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ClgJumpKind jk; 1255663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng UInt instr; 1256663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 1257663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng jk = clgs.bb->jmp[cJumps].jmpkind; 1258663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng clgs.bb->jmp[cJumps].jmpkind = clgs.bb->jmp[cJumps-1].jmpkind; 1259663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng clgs.bb->jmp[cJumps-1].jmpkind = jk; 1260663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng instr = clgs.bb->jmp[cJumps].instr; 1261663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng clgs.bb->jmp[cJumps].instr = clgs.bb->jmp[cJumps-1].instr; 1262663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng clgs.bb->jmp[cJumps-1].instr = instr; 1263663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (clgs.seen_before) { 1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_ASSERT(clgs.bb->cost_count == update_cost_offsets(&clgs)); 1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_ASSERT(clgs.bb->instr_len = clgs.instr_offset); 1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else { 1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown clgs.bb->cost_count = update_cost_offsets(&clgs); 1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown clgs.bb->instr_len = clgs.instr_offset; 1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_DEBUG(3, "- instrument(BB %#lx): byteLen %u, CJumps %u, CostLen %u\n", 1275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown origAddr, clgs.bb->instr_len, 1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown clgs.bb->cjmp_count, clgs.bb->cost_count); 1277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (cJumps>0) { 1278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_DEBUG(3, " [ "); 1279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i=0;i<cJumps;i++) 1280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_DEBUG(3, "%d ", clgs.bb->jmp[i].instr); 1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_DEBUG(3, "], last inverted: %s \n", 1282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown clgs.bb->cjmp_inverted ? "yes":"no"); 1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return clgs.sbOut; 1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Discarding BB info ---*/ 1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Called when a translation is removed from the translation cache for 1293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// any reason at all: to free up space, because the guest code was 1294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// unmapped or modified, or for any arbitrary reason. 1295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 1296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid clg_discard_superblock_info ( Addr64 orig_addr64, VexGuestExtents vge ) 1297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr orig_addr = (Addr)orig_addr64; 1299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(vge.n_used > 0); 1301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) 1303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( "discard_superblock_info: %p, %p, %llu\n", 1304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void*)(Addr)orig_addr, 1305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void*)(Addr)vge.base[0], (ULong)vge.len[0]); 1306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Get BB info, remove from table, free BB info. Simple! Note that we 1308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // use orig_addr, not the first instruction address in vge. 1309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(delete_bb)(orig_addr); 1310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 1314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- CLG_(fini)() and related function ---*/ 1315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 1316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void zero_thread_cost(thread_info* t) 1320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 1322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for(i = 0; i < CLG_(current_call_stack).sp; i++) { 1324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!CLG_(current_call_stack).entry[i].jcc) continue; 1325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* reset call counters to current for active calls */ 1327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(copy_cost)( CLG_(sets).full, 1328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(current_call_stack).entry[i].enter_cost, 1329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(current_state).cost ); 1330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(current_call_stack).entry[i].jcc->call_counter = 0; 1331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(forall_bbccs)(CLG_(zero_bbcc)); 1334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* set counter for last dump */ 1336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(copy_cost)( CLG_(sets).full, 1337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown t->lastdump_cost, CLG_(current_state).cost ); 1338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid CLG_(zero_all_cost)(Bool only_current_thread) 1341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_verbosity) > 1) 1343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, " Zeroing costs...\n"); 1344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (only_current_thread) 1346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zero_thread_cost(CLG_(get_current_thread)()); 1347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 1348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(forall_threads)(zero_thread_cost); 1349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_verbosity) > 1) 1351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, " ...done\n"); 1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 1355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid unwind_thread(thread_info* t) 1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* unwind signal handlers */ 1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while(CLG_(current_state).sig !=0) 1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(post_signal)(CLG_(current_tid),CLG_(current_state).sig); 1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* unwind regular call stack */ 1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while(CLG_(current_call_stack).sp>0) 1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(pop_call_stack)(); 1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* reset context and function stack for context generation */ 1366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(init_exec_state)( &CLG_(current_state) ); 1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(current_fn_stack).top = CLG_(current_fn_stack).bottom; 1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 1371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid zero_state_cost(thread_info* t) 1372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(zero_cost)( CLG_(sets).full, CLG_(current_state).cost ); 1374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1376b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Ups, this can go very wrong... */ 1377b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovextern void VG_(discard_translations) ( Addr64 start, ULong range, HChar* who ); 1378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid CLG_(set_instrument_state)(Char* reason, Bool state) 1380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (CLG_(instrument_state) == state) { 1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_DEBUG(2, "%s: instrumentation already %s\n", 1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown reason, state ? "ON" : "OFF"); 1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(instrument_state) = state; 1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_DEBUG(2, "%s: Switching instrumentation %s ...\n", 1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown reason, state ? "ON" : "OFF"); 1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1390b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(discard_translations)( (Addr64)0x1000, (ULong) ~0xfffl, "callgrind"); 1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* reset internal state: call stacks, simulator */ 1393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(forall_threads)(unwind_thread); 1394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(forall_threads)(zero_state_cost); 1395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (*CLG_(cachesim).clear)(); 1396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_verbosity) > 1) 1398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "%s: instrumentation switched %s\n", 1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown reason, state ? "ON" : "OFF"); 1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1401b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1402b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* helper for dump_state_togdb */ 1403b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void dump_state_of_thread_togdb(thread_info* ti) 1404b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 1405b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov static Char buf[512]; 1406b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov static FullCost sum = 0, tmp = 0; 1407b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Int t, p, i; 1408b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov BBCC *from, *to; 1409b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov call_entry* ce; 1410b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1411b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov t = CLG_(current_tid); 1412b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov CLG_(init_cost_lz)( CLG_(sets).full, &sum ); 1413b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov CLG_(copy_cost_lz)( CLG_(sets).full, &tmp, ti->lastdump_cost ); 1414b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov CLG_(add_diff_cost)( CLG_(sets).full, sum, ti->lastdump_cost, 1415b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ti->states.entry[0]->cost); 1416b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov CLG_(copy_cost)( CLG_(sets).full, ti->lastdump_cost, tmp ); 1417b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov CLG_(sprint_mappingcost)(buf, CLG_(dumpmap), sum); 1418b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(gdb_printf)("events-%d: %s\n", t, buf); 1419b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(gdb_printf)("frames-%d: %d\n", t, CLG_(current_call_stack).sp); 1420b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1421b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ce = 0; 1422b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov for(i = 0; i < CLG_(current_call_stack).sp; i++) { 1423b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ce = CLG_(get_call_entry)(i); 1424b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* if this frame is skipped, we don't have counters */ 1425b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (!ce->jcc) continue; 1426b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1427b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov from = ce->jcc->from; 1428b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(gdb_printf)("function-%d-%d: %s\n",t, i, from->cxt->fn[0]->name); 1429b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(gdb_printf)("calls-%d-%d: %llu\n",t, i, ce->jcc->call_counter); 1430b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1431b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* FIXME: EventSets! */ 1432b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov CLG_(copy_cost)( CLG_(sets).full, sum, ce->jcc->cost ); 1433b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov CLG_(copy_cost)( CLG_(sets).full, tmp, ce->enter_cost ); 1434b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov CLG_(add_diff_cost)( CLG_(sets).full, sum, 1435b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ce->enter_cost, CLG_(current_state).cost ); 1436b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov CLG_(copy_cost)( CLG_(sets).full, ce->enter_cost, tmp ); 1437b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1438b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov p = VG_(sprintf)(buf, "events-%d-%d: ",t, i); 1439b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov CLG_(sprint_mappingcost)(buf + p, CLG_(dumpmap), sum ); 1440b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(gdb_printf)("%s\n", buf); 1441b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1442b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (ce && ce->jcc) { 1443b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov to = ce->jcc->to; 1444b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(gdb_printf)("function-%d-%d: %s\n",t, i, to->cxt->fn[0]->name ); 1445b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1446b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 1447b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1448b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Dump current state */ 1449b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void dump_state_togdb(void) 1450b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 1451b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov static Char buf[512]; 1452b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov thread_info** th; 1453b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov int t, p; 1454b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Int orig_tid = CLG_(current_tid); 1455b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1456b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(gdb_printf)("instrumentation: %s\n", 1457b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov CLG_(instrument_state) ? "on":"off"); 1458b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (!CLG_(instrument_state)) return; 1459b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1460b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(gdb_printf)("executed-bbs: %llu\n", CLG_(stat).bb_executions); 1461b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(gdb_printf)("executed-calls: %llu\n", CLG_(stat).call_counter); 1462b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(gdb_printf)("distinct-bbs: %d\n", CLG_(stat).distinct_bbs); 1463b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(gdb_printf)("distinct-calls: %d\n", CLG_(stat).distinct_jccs); 1464b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(gdb_printf)("distinct-functions: %d\n", CLG_(stat).distinct_fns); 1465b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(gdb_printf)("distinct-contexts: %d\n", CLG_(stat).distinct_contexts); 1466b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1467b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* "events:" line. Given here because it will be dynamic in the future */ 1468b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov p = VG_(sprintf)(buf, "events: "); 1469b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov CLG_(sprint_eventmapping)(buf+p, CLG_(dumpmap)); 1470b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(gdb_printf)("%s\n", buf); 1471b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* "part:" line (number of last part. Is 0 at start */ 1472b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(gdb_printf)("part: %d\n", CLG_(get_dump_counter)()); 1473b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1474b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* threads */ 1475b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov th = CLG_(get_threads)(); 1476b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov p = VG_(sprintf)(buf, "threads:"); 1477b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov for(t=1;t<VG_N_THREADS;t++) { 1478b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (!th[t]) continue; 1479b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov p += VG_(sprintf)(buf+p, " %d", t); 1480b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1481b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(gdb_printf)("%s\n", buf); 1482b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(gdb_printf)("current-tid: %d\n", orig_tid); 1483b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov CLG_(forall_threads)(dump_state_of_thread_togdb); 1484b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 1485b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1487b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void print_monitor_help ( void ) 1488b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 1489b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(gdb_printf) ("\n"); 1490b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(gdb_printf) ("callgrind monitor commands:\n"); 1491b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(gdb_printf) (" dump [<dump_hint>]\n"); 1492b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(gdb_printf) (" dump counters\n"); 1493b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(gdb_printf) (" zero\n"); 1494b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(gdb_printf) (" zero counters\n"); 1495b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(gdb_printf) (" status\n"); 1496b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(gdb_printf) (" print status\n"); 1497b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(gdb_printf) (" instrumentation [on|off]\n"); 1498b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(gdb_printf) (" get/set (if on/off given) instrumentation state\n"); 1499b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(gdb_printf) ("\n"); 1500b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 1501b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1502b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* return True if request recognised, False otherwise */ 1503b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic Bool handle_gdb_monitor_command (ThreadId tid, Char *req) 1504b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 1505b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Char* wcmd; 1506b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Char s[VG_(strlen(req))]; /* copy for strtok_r */ 1507b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Char *ssaveptr; 1508b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1509b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(strcpy) (s, req); 1510b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1511b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov wcmd = VG_(strtok_r) (s, " ", &ssaveptr); 1512b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov switch (VG_(keyword_id) ("help dump zero status instrumentation", 1513b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov wcmd, kwd_report_duplicated_matches)) { 1514b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case -2: /* multiple matches */ 1515b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return True; 1516b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case -1: /* not found */ 1517b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return False; 1518b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case 0: /* help */ 1519b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov print_monitor_help(); 1520b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return True; 1521b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case 1: { /* dump */ 1522b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov CLG_(dump_profile)(req, False); 1523b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return True; 1524b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1525b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case 2: { /* zero */ 1526b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov CLG_(zero_all_cost)(False); 1527b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return True; 1528b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1529b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1530b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case 3: { /* status */ 1531b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Char* arg = VG_(strtok_r) (0, " ", &ssaveptr); 1532b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (arg && (VG_(strcmp)(arg, "internal") == 0)) { 1533b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* internal interface to callgrind_control */ 1534b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov dump_state_togdb(); 1535b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return True; 1536b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1537b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1538b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (!CLG_(instrument_state)) { 1539b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(gdb_printf)("No status available as instrumentation is switched off\n"); 1540b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } else { 1541b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // Status information to be improved ... 1542b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov thread_info** th = CLG_(get_threads)(); 1543b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Int t, tcount = 0; 1544b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov for(t=1;t<VG_N_THREADS;t++) 1545b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (th[t]) tcount++; 1546b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(gdb_printf)("%d thread(s) running.\n", tcount); 1547b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1548b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return True; 1549b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1550b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1551b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case 4: { /* instrumentation */ 1552b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Char* arg = VG_(strtok_r) (0, " ", &ssaveptr); 1553b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (!arg) { 1554b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(gdb_printf)("instrumentation: %s\n", 1555b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov CLG_(instrument_state) ? "on":"off"); 1556b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1557b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov else 1558b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov CLG_(set_instrument_state)("Command", VG_(strcmp)(arg,"off")!=0); 1559b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return True; 1560b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1561b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1562b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov default: 1563b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov tl_assert(0); 1564b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return False; 1565b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1566b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 1567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 1569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool CLG_(handle_client_request)(ThreadId tid, UWord *args, UWord *ret) 1570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1571b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (!VG_IS_TOOL_USERREQ('C','T',args[0]) 1572b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov && VG_USERREQ__GDB_MONITOR_COMMAND != args[0]) 1573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 1574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(args[0]) { 1576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__DUMP_STATS: 1577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(dump_profile)("Client Request", True); 1578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *ret = 0; /* meaningless */ 1579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__DUMP_STATS_AT: 1582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 1583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char buf[512]; 1584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(buf,"Client Request: %s", (Char*)args[1]); 1585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(dump_profile)(buf, True); 1586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *ret = 0; /* meaningless */ 1587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__ZERO_STATS: 1591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(zero_all_cost)(True); 1592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *ret = 0; /* meaningless */ 1593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__TOGGLE_COLLECT: 1596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(current_state).collect = !CLG_(current_state).collect; 1597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_DEBUG(2, "Client Request: toggled collection state to %s\n", 1598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(current_state).collect ? "ON" : "OFF"); 1599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *ret = 0; /* meaningless */ 1600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__START_INSTRUMENTATION: 1603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(set_instrument_state)("Client Request", True); 1604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *ret = 0; /* meaningless */ 1605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__STOP_INSTRUMENTATION: 1608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(set_instrument_state)("Client Request", False); 1609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *ret = 0; /* meaningless */ 1610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1612b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case VG_USERREQ__GDB_MONITOR_COMMAND: { 1613b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Bool handled = handle_gdb_monitor_command (tid, (Char*)args[1]); 1614b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (handled) 1615b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *ret = 1; 1616b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov else 1617b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *ret = 0; 1618b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return handled; 1619b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 1621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 1622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 1625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Syscall Timing */ 1629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* struct timeval syscalltime[VG_N_THREADS]; */ 1631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if CLG_MICROSYSTIME 1632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <sys/time.h> 1633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <sys/syscall.h> 1634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownextern Int VG_(do_syscall) ( UInt, ... ); 1635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong syscalltime[VG_N_THREADS]; 1637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 1638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUInt syscalltime[VG_N_THREADS]; 1639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 1642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid CLG_(pre_syscalltime)(ThreadId tid, UInt syscallno, 1643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord* args, UInt nArgs) 1644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (CLG_(clo).collect_systime) { 1646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if CLG_MICROSYSTIME 1647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_timeval tv_now; 1648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(do_syscall)(__NR_gettimeofday, (UInt)&tv_now, (UInt)NULL); 1649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown syscalltime[tid] = tv_now.tv_sec * 1000000ULL + tv_now.tv_usec; 1650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 1651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown syscalltime[tid] = VG_(read_millisecond_timer)(); 1652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 1657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid CLG_(post_syscalltime)(ThreadId tid, UInt syscallno, 1658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord* args, UInt nArgs, SysRes res) 1659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (CLG_(clo).collect_systime && 1661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(current_state).bbcc) { 1662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int o; 1663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if CLG_MICROSYSTIME 1664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_timeval tv_now; 1665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong diff; 1666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(do_syscall)(__NR_gettimeofday, (UInt)&tv_now, (UInt)NULL); 1668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown diff = (tv_now.tv_sec * 1000000ULL + tv_now.tv_usec) - syscalltime[tid]; 1669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 1670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt diff = VG_(read_millisecond_timer)() - syscalltime[tid]; 1671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* offset o is for "SysCount", o+1 for "SysTime" */ 1674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown o = fullOffset(EG_SYS); 1675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_ASSERT(o>=0); 1676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_DEBUG(0," Time (Off %d) for Syscall %d: %ull\n", o, syscallno, diff); 1677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(current_state).cost[o] ++; 1679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(current_state).cost[o+1] += diff; 1680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!CLG_(current_state).bbcc->skipped) 1681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(init_cost_lz)(CLG_(sets).full, 1682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown &(CLG_(current_state).bbcc->skipped)); 1683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(current_state).bbcc->skipped[o] ++; 1684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(current_state).bbcc->skipped[o+1] += diff; 1685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt ULong_width(ULong n) 1689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt w = 0; 1691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (n > 0) { 1692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n = n / 10; 1693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown w++; 1694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (w == 0) w = 1; 1696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return w + (w-1)/3; // add space for commas 1697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 1700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid branchsim_printstat(int l1, int l2, int l3) 1701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static Char buf1[128], buf2[128], buf3[128], fmt[128]; 1703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown FullCost total; 1704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong Bc_total_b, Bc_total_mp, Bi_total_b, Bi_total_mp; 1705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong B_total_b, B_total_mp; 1706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown total = CLG_(total_cost); 1708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bc_total_b = total[ fullOffset(EG_BC) ]; 1709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bc_total_mp = total[ fullOffset(EG_BC)+1 ]; 1710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bi_total_b = total[ fullOffset(EG_BI) ]; 1711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bi_total_mp = total[ fullOffset(EG_BI)+1 ]; 1712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Make format string, getting width right for numbers */ 1714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(fmt, "%%s %%,%dllu (%%,%dllu cond + %%,%dllu ind)\n", 1715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown l1, l2, l3); 1716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0 == Bc_total_b) Bc_total_b = 1; 1718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0 == Bi_total_b) Bi_total_b = 1; 1719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown B_total_b = Bc_total_b + Bi_total_b; 1720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown B_total_mp = Bc_total_mp + Bi_total_mp; 1721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)("\n"); 1723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)(fmt, "Branches: ", 1724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown B_total_b, Bc_total_b, Bi_total_b); 1725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)(fmt, "Mispredicts: ", 1727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown B_total_mp, Bc_total_mp, Bi_total_mp); 1728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(percentify)(B_total_mp, B_total_b, 1, l1+1, buf1); 1730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(percentify)(Bc_total_mp, Bc_total_b, 1, l2+1, buf2); 1731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(percentify)(Bi_total_mp, Bi_total_b, 1, l3+1, buf3); 1732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)("Mispred rate: %s (%s + %s )\n", buf1, buf2,buf3); 1734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 1738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid finish(void) 1739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char buf[32+COSTS_LEN], fmt[128]; 1741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int l1, l2, l3; 1742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown FullCost total; 1743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_DEBUG(0, "finish()\n"); 1745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (*CLG_(cachesim).finish)(); 1747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* pop all remaining items from CallStack for correct sum 1749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 1750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(forall_threads)(unwind_thread); 1751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(dump_profile)(0, False); 1753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_verbosity) == 0) return; 1755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Hash table stats */ 1757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_stats)) { 1758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int BB_lookups = 1759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(stat).full_debug_BBs + 1760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(stat).fn_name_debug_BBs + 1761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(stat).file_line_debug_BBs + 1762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(stat).no_debug_BBs; 1763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "\n"); 1765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "Distinct objects: %d\n", 1766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(stat).distinct_objs); 1767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "Distinct files: %d\n", 1768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(stat).distinct_files); 1769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "Distinct fns: %d\n", 1770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(stat).distinct_fns); 1771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "Distinct contexts:%d\n", 1772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(stat).distinct_contexts); 1773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "Distinct BBs: %d\n", 1774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(stat).distinct_bbs); 1775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "Cost entries: %d (Chunks %d)\n", 1776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(costarray_entries), CLG_(costarray_chunks)); 1777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "Distinct BBCCs: %d\n", 1778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(stat).distinct_bbccs); 1779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "Distinct JCCs: %d\n", 1780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(stat).distinct_jccs); 1781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "Distinct skips: %d\n", 1782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(stat).distinct_skips); 1783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "BB lookups: %d\n", 1784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown BB_lookups); 1785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (BB_lookups>0) { 1786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "With full debug info:%3d%% (%d)\n", 1787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(stat).full_debug_BBs * 100 / BB_lookups, 1788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(stat).full_debug_BBs); 1789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "With file/line debug info:%3d%% (%d)\n", 1790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(stat).file_line_debug_BBs * 100 / BB_lookups, 1791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(stat).file_line_debug_BBs); 1792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "With fn name debug info:%3d%% (%d)\n", 1793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(stat).fn_name_debug_BBs * 100 / BB_lookups, 1794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(stat).fn_name_debug_BBs); 1795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "With no debug info:%3d%% (%d)\n", 1796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(stat).no_debug_BBs * 100 / BB_lookups, 1797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(stat).no_debug_BBs); 1798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "BBCC Clones: %d\n", 1800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(stat).bbcc_clones); 1801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "BBs Retranslated: %d\n", 1802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(stat).bb_retranslations); 1803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "Distinct instrs: %d\n", 1804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(stat).distinct_instrs); 1805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, ""); 1806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "LRU Contxt Misses: %d\n", 1808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(stat).cxt_lru_misses); 1809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "LRU BBCC Misses: %d\n", 1810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(stat).bbcc_lru_misses); 1811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "LRU JCC Misses: %d\n", 1812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(stat).jcc_lru_misses); 1813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "BBs Executed: %llu\n", 1814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(stat).bb_executions); 1815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "Calls: %llu\n", 1816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(stat).call_counter); 1817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "CondJMP followed: %llu\n", 1818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(stat).jcnd_counter); 1819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "Boring JMPs: %llu\n", 1820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(stat).jump_counter); 1821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "Recursive calls: %llu\n", 1822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(stat).rec_call_counter); 1823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "Returns: %llu\n", 1824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(stat).ret_counter); 1825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, ""); 1827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(sprint_eventmapping)(buf, CLG_(dumpmap)); 1830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "Events : %s\n", buf); 1831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(sprint_mappingcost)(buf, CLG_(dumpmap), CLG_(total_cost)); 1832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "Collected : %s\n", buf); 1833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "\n"); 1834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* determine value widths for statistics */ 1836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown total = CLG_(total_cost); 1837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown l1 = ULong_width( total[fullOffset(EG_IR)] ); 1838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown l2 = l3 = 0; 1839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (CLG_(clo).simulate_cache) { 1840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown l2 = ULong_width( total[fullOffset(EG_DR)] ); 1841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown l3 = ULong_width( total[fullOffset(EG_DW)] ); 1842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (CLG_(clo).simulate_branch) { 1844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int l2b = ULong_width( total[fullOffset(EG_BC)] ); 1845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int l3b = ULong_width( total[fullOffset(EG_BI)] ); 1846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (l2b > l2) l2 = l2b; 1847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (l3b > l3) l3 = l3b; 1848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Make format string, getting width right for numbers */ 1851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(fmt, "%%s %%,%dllu\n", l1); 1852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Always print this */ 1854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)(fmt, "I refs: ", total[fullOffset(EG_IR)] ); 1855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (CLG_(clo).simulate_cache) 1857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (*CLG_(cachesim).printstat)(l1, l2, l3); 1858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (CLG_(clo).simulate_branch) 1860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown branchsim_printstat(l1, l2, l3); 1861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid CLG_(fini)(Int exitcode) 1866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown finish(); 1868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 1872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Setup ---*/ 1873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 1874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void clg_start_client_code_callback ( ThreadId tid, ULong blocks_done ) 1876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static ULong last_blocks_done = 0; 1878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) 1880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("%d R %llu\n", (Int)tid, blocks_done); 1881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* throttle calls to CLG_(run_thread) by number of BBs executed */ 1883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (blocks_done - last_blocks_done < 5000) return; 1884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown last_blocks_done = blocks_done; 1885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(run_thread)( tid ); 1887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 1890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid CLG_(post_clo_init)(void) 1891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(clo_vex_control).iropt_unroll_thresh = 0; 1893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(clo_vex_control).guest_chase_thresh = 0; 1894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_DEBUG(1, " dump threads: %s\n", CLG_(clo).separate_threads ? "Yes":"No"); 1896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_DEBUG(1, " call sep. : %d\n", CLG_(clo).separate_callers); 1897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_DEBUG(1, " rec. sep. : %d\n", CLG_(clo).separate_recursions); 1898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!CLG_(clo).dump_line && !CLG_(clo).dump_instr && !CLG_(clo).dump_bb) { 1900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "Using source line as position.\n"); 1901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(clo).dump_line = True; 1902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(init_dumps)(); 1905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (*CLG_(cachesim).post_clo_init)(); 1907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(init_eventsets)(); 1909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(init_statistics)(& CLG_(stat)); 1910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(init_cost_lz)( CLG_(sets).full, &CLG_(total_cost) ); 1911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* initialize hash tables */ 1913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(init_obj_table)(); 1914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(init_cxt_table)(); 1915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(init_bb_hash)(); 1916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(init_threads)(); 1918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(run_thread)(1); 1919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(instrument_state) = CLG_(clo).instrument_atstart; 1921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_verbosity > 0)) { 1923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, 1924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "For interactive control, run 'callgrind_control -h'.\n"); 1925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 1929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid CLG_(pre_clo_init)(void) 1930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(details_name) ("Callgrind"); 1932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(details_version) (NULL); 1933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(details_description) ("a call-graph generating cache profiler"); 1934663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(details_copyright_author)("Copyright (C) 2002-2012, and GNU GPL'd, " 1935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "by Josef Weidendorfer et al."); 1936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(details_bug_reports_to) (VG_BUGS_TO); 1937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(details_avg_translation_sizeB) ( 500 ); 1938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(basic_tool_funcs) (CLG_(post_clo_init), 1940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(instrument), 1941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(fini)); 1942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(needs_superblock_discards)(clg_discard_superblock_info); 1944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(needs_command_line_options)(CLG_(process_cmd_line_option), 1947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(print_usage), 1948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(print_debug_usage)); 1949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(needs_client_requests)(CLG_(handle_client_request)); 1951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(needs_syscall_wrapper)(CLG_(pre_syscalltime), 1952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(post_syscalltime)); 1953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(track_start_client_code) ( & clg_start_client_code_callback ); 1955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(track_pre_deliver_signal) ( & CLG_(pre_signal) ); 1956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(track_post_deliver_signal)( & CLG_(post_signal) ); 1957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(set_clo_defaults)(); 1959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVG_DETERMINE_INTERFACE_VERSION(CLG_(pre_clo_init)) 1962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 1964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end main.c ---*/ 1965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 1966