1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Callgrind                                                    ---*/
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---                                                       dump.c ---*/
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This file is part of Callgrind, a Valgrind tool for call tracing.
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Copyright (C) 2002-2013, Josef Weidendorfer (Josef.Weidendorfer@gmx.de)
10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is free software; you can redistribute it and/or
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modify it under the terms of the GNU General Public License as
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   published by the Free Software Foundation; either version 2 of the
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   License, or (at your option) any later version.
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is distributed in the hope that it will be useful, but
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   WITHOUT ANY WARRANTY; without even the implied warranty of
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   General Public License for more details.
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   You should have received a copy of the GNU General Public License
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   along with this program; if not, write to the Free Software
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   02111-1307, USA.
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The GNU General Public License is contained in the file COPYING.
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "config.h"
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "global.h"
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
32b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_tool_threadstate.h"
33b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_tool_libcfile.h"
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Dump Part Counter */
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int out_counter = 0;
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
39436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic HChar* out_file = 0;
40436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic HChar* out_directory = 0;
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool dumps_initialized = False;
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Command */
44436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic HChar cmdbuf[BUF_LEN];
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Total reads/writes/misses sum over all dumps and threads.
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Updated during CC traversal at dump time.
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownFullCost CLG_(total_cost) = 0;
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic FullCost dump_total_cost = 0;
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownEventMapping* CLG_(dumpmap) = 0;
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Temporary output buffer for
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *  print_fn_pos, fprint_apos, fprint_fcost, fprint_jcc,
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *  fprint_fcc_ln, dump_run_info, dump_state_info
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
58436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic HChar outbuf[FILENAME_LEN + FN_NAME_LEN + OBJ_NAME_LEN + COSTS_LEN];
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt CLG_(get_dump_counter)(void)
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return out_counter;
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
65436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovHChar* CLG_(get_out_file)()
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(init_dumps)();
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return out_file;
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
71436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovHChar* CLG_(get_out_directory)()
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(init_dumps)();
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return out_directory;
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Output file related stuff                            ---*/
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Boolean dumping array */
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool* dump_array = 0;
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int   dump_array_size = 0;
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool* obj_dumped = 0;
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool* file_dumped = 0;
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool* fn_dumped = 0;
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool* cxt_dumped = 0;
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid reset_dump_array(void)
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int i;
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_ASSERT(dump_array != 0);
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i=0;i<dump_array_size;i++)
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	dump_array[i] = False;
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid init_dump_array(void)
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    dump_array_size = CLG_(stat).distinct_objs +
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      CLG_(stat).distinct_files +
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      CLG_(stat).distinct_fns +
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      CLG_(stat).context_counter;
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_ASSERT(dump_array == 0);
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    dump_array = (Bool*) CLG_MALLOC("cl.dump.ida.1",
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    dump_array_size * sizeof(Bool));
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    obj_dumped  = dump_array;
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    file_dumped = obj_dumped + CLG_(stat).distinct_objs;
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    fn_dumped   = file_dumped + CLG_(stat).distinct_files;
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    cxt_dumped  = fn_dumped + CLG_(stat).distinct_fns;
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    reset_dump_array();
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_DEBUG(1, "  init_dump_array: size %d\n", dump_array_size);
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid free_dump_array(void)
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_ASSERT(dump_array != 0);
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(free)(dump_array);
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    dump_array = 0;
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    obj_dumped = 0;
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    file_dumped = 0;
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    fn_dumped = 0;
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    cxt_dumped = 0;
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Initialize to an invalid position */
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid init_fpos(FnPos* p)
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown {
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p->file = 0;
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p->fn = 0;
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p->obj = 0;
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p->cxt = 0;
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p->rec_index = 0;
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if 0
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__
148436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void my_fwrite(Int fd, const HChar* buf, Int len)
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
150436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	VG_(write)(fd, buf, len);
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define FWRITE_BUFSIZE 32000
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define FWRITE_THROUGH 10000
156436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic HChar fwrite_buf[FWRITE_BUFSIZE];
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int fwrite_pos;
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int fwrite_fd = -1;
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid fwrite_flush(void)
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ((fwrite_fd>=0) && (fwrite_pos>0))
164436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	VG_(write)(fwrite_fd, fwrite_buf, fwrite_pos);
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    fwrite_pos = 0;
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
168436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void my_fwrite(Int fd, const HChar* buf, Int len)
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (fwrite_fd != fd) {
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	fwrite_flush();
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	fwrite_fd = fd;
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (len > FWRITE_THROUGH) {
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	fwrite_flush();
176436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	VG_(write)(fd, buf, len);
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	return;
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (FWRITE_BUFSIZE - fwrite_pos <= len) fwrite_flush();
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(strncpy)(fwrite_buf + fwrite_pos, buf, len);
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    fwrite_pos += len;
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
186436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void print_obj(HChar* buf, obj_node* obj)
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    //int n;
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (CLG_(clo).compress_strings) {
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	CLG_ASSERT(obj_dumped != 0);
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (obj_dumped[obj->number])
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    /*n =*/ VG_(sprintf)(buf, "(%d)\n", obj->number);
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	else {
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    /*n =*/ VG_(sprintf)(buf, "(%d) %s\n",
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			     obj->number, obj->name);
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    else
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/*n =*/ VG_(sprintf)(buf, "%s\n", obj->name);
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if 0
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* add mapping parameters the first time a object is dumped
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     * format: mp=0xSTART SIZE 0xOFFSET */
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!obj_dumped[obj->number]) {
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	obj_dumped[obj->number];
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	VG_(sprintf)(buf+n, "mp=%p %p %p\n",
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		     pos->obj->start, pos->obj->size, pos->obj->offset);
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    obj_dumped[obj->number] = True;
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
215436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void print_file(HChar* buf, file_node* file)
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (CLG_(clo).compress_strings) {
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	CLG_ASSERT(file_dumped != 0);
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (file_dumped[file->number])
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    VG_(sprintf)(buf, "(%d)\n", file->number);
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	else {
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    VG_(sprintf)(buf, "(%d) %s\n",
223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			 file->number, file->name);
224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    file_dumped[file->number] = True;
225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    else
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	VG_(sprintf)(buf, "%s\n", file->name);
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * tag can be "fn", "cfn", "jfn"
233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
234436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void print_fn(Int fd, HChar* buf, const HChar* tag, fn_node* fn)
235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int p;
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p = VG_(sprintf)(buf, "%s=",tag);
238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (CLG_(clo).compress_strings) {
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	CLG_ASSERT(fn_dumped != 0);
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (fn_dumped[fn->number])
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    p += VG_(sprintf)(buf+p, "(%d)\n", fn->number);
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	else {
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    p += VG_(sprintf)(buf+p, "(%d) %s\n",
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			      fn->number, fn->name);
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    fn_dumped[fn->number] = True;
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    else
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	p += VG_(sprintf)(buf+p, "%s\n", fn->name);
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    my_fwrite(fd, buf, p);
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
254436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void print_mangled_fn(Int fd, HChar* buf, const HChar* tag,
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			     Context* cxt, int rec_index)
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int p, i;
258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (CLG_(clo).compress_strings && CLG_(clo).compress_mangled) {
260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	int n;
262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	Context* last;
263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	CLG_ASSERT(cxt_dumped != 0);
265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (cxt_dumped[cxt->base_number+rec_index]) {
266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    p = VG_(sprintf)(buf, "%s=(%d)\n",
267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			     tag, cxt->base_number + rec_index);
268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    my_fwrite(fd, buf, p);
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    return;
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	last = 0;
273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* make sure that for all context parts compressed data is written */
274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	for(i=cxt->size;i>0;i--) {
275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    CLG_ASSERT(cxt->fn[i-1]->pure_cxt != 0);
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    n = cxt->fn[i-1]->pure_cxt->base_number;
277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    if (cxt_dumped[n]) continue;
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    p = VG_(sprintf)(buf, "%s=(%d) %s\n",
279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			     tag, n, cxt->fn[i-1]->name);
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    my_fwrite(fd, buf, p);
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    cxt_dumped[n] = True;
283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    last = cxt->fn[i-1]->pure_cxt;
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* If the last context was the context to print, we are finished */
286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if ((last == cxt) && (rec_index == 0)) return;
287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	p = VG_(sprintf)(buf, "%s=(%d) (%d)", tag,
289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			 cxt->base_number + rec_index,
290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			 cxt->fn[0]->pure_cxt->base_number);
291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (rec_index >0)
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    p += VG_(sprintf)(buf+p, "'%d", rec_index +1);
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	for(i=1;i<cxt->size;i++)
294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    p += VG_(sprintf)(buf+p, "'(%d)",
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			      cxt->fn[i]->pure_cxt->base_number);
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	p += VG_(sprintf)(buf+p, "\n");
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	my_fwrite(fd, buf, p);
298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	cxt_dumped[cxt->base_number+rec_index] = True;
300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	return;
301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p = VG_(sprintf)(buf, "%s=", tag);
305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (CLG_(clo).compress_strings) {
306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	CLG_ASSERT(cxt_dumped != 0);
307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (cxt_dumped[cxt->base_number+rec_index]) {
308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    p += VG_(sprintf)(buf+p, "(%d)\n", cxt->base_number + rec_index);
309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    my_fwrite(fd, buf, p);
310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    return;
311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	else {
313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    p += VG_(sprintf)(buf+p, "(%d) ", cxt->base_number + rec_index);
314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    cxt_dumped[cxt->base_number+rec_index] = True;
315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p += VG_(sprintf)(buf+p, "%s", cxt->fn[0]->name);
319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (rec_index >0)
320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	p += VG_(sprintf)(buf+p, "'%d", rec_index +1);
321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i=1;i<cxt->size;i++)
322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	p += VG_(sprintf)(buf+p, "'%s", cxt->fn[i]->name);
323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p += VG_(sprintf)(buf+p, "\n");
325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    my_fwrite(fd, buf, p);
326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Print function position of the BBCC, but only print info differing to
332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * the <last> position, update <last>
333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Return True if something changes.
334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool print_fn_pos(int fd, FnPos* last, BBCC* bbcc)
336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Bool res = False;
338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
339b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    CLG_ASSERT(bbcc && bbcc->cxt);
340b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_DEBUGIF(3) {
342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	CLG_DEBUG(2, "+ print_fn_pos: ");
343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	CLG_(print_cxt)(16, bbcc->cxt, bbcc->rec_index);
344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!CLG_(clo).mangle_names) {
347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (last->rec_index != bbcc->rec_index) {
348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    VG_(sprintf)(outbuf, "rec=%d\n\n", bbcc->rec_index);
349436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	    my_fwrite(fd, outbuf, VG_(strlen)(outbuf));
350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    last->rec_index = bbcc->rec_index;
351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    last->cxt = 0; /* reprint context */
352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    res = True;
353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (last->cxt != bbcc->cxt) {
356b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	    fn_node* last_from = (last->cxt && last->cxt->size >1) ?
357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				 last->cxt->fn[1] : 0;
358b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	    fn_node* curr_from = (bbcc->cxt->size >1) ?
359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				 bbcc->cxt->fn[1] : 0;
360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    if (curr_from == 0) {
361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		if (last_from != 0) {
362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		    /* switch back to no context */
363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		    VG_(sprintf)(outbuf, "frfn=(spontaneous)\n");
364436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov		    my_fwrite(fd, outbuf, VG_(strlen)(outbuf));
365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		    res = True;
366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		}
367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    }
368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    else if (last_from != curr_from) {
369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		print_fn(fd,outbuf,"frfn", curr_from);
370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		res = True;
371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    }
372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    last->cxt = bbcc->cxt;
373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (last->obj != bbcc->cxt->fn[0]->file->obj) {
377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	VG_(sprintf)(outbuf, "ob=");
378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	print_obj(outbuf+3, bbcc->cxt->fn[0]->file->obj);
379436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	my_fwrite(fd, outbuf, VG_(strlen)(outbuf));
380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	last->obj = bbcc->cxt->fn[0]->file->obj;
381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	res = True;
382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (last->file != bbcc->cxt->fn[0]->file) {
385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	VG_(sprintf)(outbuf, "fl=");
386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	print_file(outbuf+3, bbcc->cxt->fn[0]->file);
387436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	my_fwrite(fd, outbuf, VG_(strlen)(outbuf));
388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	last->file = bbcc->cxt->fn[0]->file;
389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	res = True;
390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!CLG_(clo).mangle_names) {
393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (last->fn != bbcc->cxt->fn[0]) {
394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    print_fn(fd,outbuf, "fn", bbcc->cxt->fn[0]);
395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    last->fn = bbcc->cxt->fn[0];
396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    res = True;
397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    else {
400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* Print mangled name if context or rec_index changes */
401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if ((last->rec_index != bbcc->rec_index) ||
402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    (last->cxt != bbcc->cxt)) {
403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    print_mangled_fn(fd, outbuf, "fn", bbcc->cxt, bbcc->rec_index);
405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    last->fn = bbcc->cxt->fn[0];
406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    last->rec_index = bbcc->rec_index;
407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    res = True;
408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    last->cxt = bbcc->cxt;
412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_DEBUG(2, "- print_fn_pos: %s\n", res ? "changed" : "");
414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return res;
416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* the debug lookup cache is useful if BBCC for same BB are
419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * dumped directly in a row. This is a direct mapped cache.
420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEBUG_CACHE_SIZE 1777
422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Addr       debug_cache_addr[DEBUG_CACHE_SIZE];
424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic file_node* debug_cache_file[DEBUG_CACHE_SIZE];
425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int        debug_cache_line[DEBUG_CACHE_SIZE];
426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool       debug_cache_info[DEBUG_CACHE_SIZE];
427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__
429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid init_debug_cache(void)
430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int i;
432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i=0;i<DEBUG_CACHE_SIZE;i++) {
433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	debug_cache_addr[i] = 0;
434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	debug_cache_file[i] = 0;
435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	debug_cache_line[i] = 0;
436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	debug_cache_info[i] = 0;
437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic /* __inline__ */
441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool get_debug_pos(BBCC* bbcc, Addr addr, AddrPos* p)
442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
443436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    HChar file[FILENAME_LEN];
444436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    HChar dir[FILENAME_LEN];
445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Bool found_file_line, found_dirname;
446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int cachepos = addr % DEBUG_CACHE_SIZE;
448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (debug_cache_addr[cachepos] == addr) {
450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	p->line = debug_cache_line[cachepos];
451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	p->file = debug_cache_file[cachepos];
452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	found_file_line = debug_cache_info[cachepos];
453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    else {
455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	found_file_line = VG_(get_filename_linenum)(addr,
456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown						    file, FILENAME_LEN,
457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown						    dir, FILENAME_LEN,
458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown						    &found_dirname,
459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown						    &(p->line));
460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (!found_file_line) {
461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    VG_(strcpy)(file, "???");
462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    p->line = 0;
463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (found_dirname) {
465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    // +1 for the '/'.
466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    CLG_ASSERT(VG_(strlen)(dir) + VG_(strlen)(file) + 1 < FILENAME_LEN);
467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    VG_(strcat)(dir, "/");     // Append '/'
468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    VG_(strcat)(dir, file);    // Append file to dir
469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    VG_(strcpy)(file, dir);    // Move dir+file to file
470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	p->file    = CLG_(get_file_node)(bbcc->bb->obj, file);
472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	debug_cache_info[cachepos] = found_file_line;
474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	debug_cache_addr[cachepos] = addr;
475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	debug_cache_line[cachepos] = p->line;
476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	debug_cache_file[cachepos] = p->file;
477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* Address offset from bbcc start address */
480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p->addr = addr - bbcc->bb->obj->offset;
481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p->bb_addr = bbcc->bb->offset;
482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_DEBUG(3, "  get_debug_pos(%#lx): BB %#lx, fn '%s', file '%s', line %u\n",
484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	     addr, bb_addr(bbcc->bb), bbcc->cxt->fn[0]->name,
485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	     p->file->name, p->line);
486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return found_file_line;
488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* copy file position and init cost */
492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void init_apos(AddrPos* p, Addr addr, Addr bbaddr, file_node* file)
493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p->addr    = addr;
495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p->bb_addr = bbaddr;
496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p->file    = file;
497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p->line    = 0;
498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void copy_apos(AddrPos* dst, AddrPos* src)
501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    dst->addr    = src->addr;
503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    dst->bb_addr = src->bb_addr;
504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    dst->file    = src->file;
505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    dst->line    = src->line;
506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* copy file position and init cost */
509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void init_fcost(AddrCost* c, Addr addr, Addr bbaddr, file_node* file)
510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    init_apos( &(c->p), addr, bbaddr, file);
512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* FIXME: This is a memory leak as a AddrCost is inited multiple times */
513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    c->cost = CLG_(get_eventset_cost)( CLG_(sets).full );
514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(init_cost)( CLG_(sets).full, c->cost );
515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * print position change inside of a BB (last -> curr)
520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * this doesn't update last to curr!
521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void fprint_apos(Int fd, AddrPos* curr, AddrPos* last, file_node* func_file)
523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_ASSERT(curr->file != 0);
525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_DEBUG(2, "    print_apos(file '%s', line %d, bb %#lx, addr %#lx) fnFile '%s'\n",
526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	     curr->file->name, curr->line, curr->bb_addr, curr->addr,
527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	     func_file->name);
528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (curr->file != last->file) {
530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* if we switch back to orig file, use fe=... */
532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (curr->file == func_file)
533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    VG_(sprintf)(outbuf, "fe=");
534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	else
535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    VG_(sprintf)(outbuf, "fi=");
536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	print_file(outbuf+3, curr->file);
537436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	my_fwrite(fd, outbuf, VG_(strlen)(outbuf));
538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (CLG_(clo).dump_bbs) {
541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (curr->line != last->line) {
542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    VG_(sprintf)(outbuf, "ln=%d\n", curr->line);
543436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	    my_fwrite(fd, outbuf, VG_(strlen)(outbuf));
544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Print a position.
552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * This prints out differences if allowed
553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * This doesn't set last to curr afterwards!
555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid fprint_pos(Int fd, AddrPos* curr, AddrPos* last)
558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (0) //CLG_(clo).dump_bbs)
560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	VG_(sprintf)(outbuf, "%lu ", curr->addr - curr->bb_addr);
561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    else {
562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	int p = 0;
563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (CLG_(clo).dump_instr) {
564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    int diff = curr->addr - last->addr;
565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    if ( CLG_(clo).compress_pos && (last->addr >0) &&
566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		 (diff > -100) && (diff < 100)) {
567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		if (diff >0)
568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		    p = VG_(sprintf)(outbuf, "+%d ", diff);
569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		else if (diff==0)
570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		    p = VG_(sprintf)(outbuf, "* ");
571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	        else
572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		    p = VG_(sprintf)(outbuf, "%d ", diff);
573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    }
574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    else
575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		p = VG_(sprintf)(outbuf, "%#lx ", curr->addr);
576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (CLG_(clo).dump_bb) {
579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    int diff = curr->bb_addr - last->bb_addr;
580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    if ( CLG_(clo).compress_pos && (last->bb_addr >0) &&
581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		 (diff > -100) && (diff < 100)) {
582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		if (diff >0)
583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		    p += VG_(sprintf)(outbuf+p, "+%d ", diff);
584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		else if (diff==0)
585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		    p += VG_(sprintf)(outbuf+p, "* ");
586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	        else
587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		    p += VG_(sprintf)(outbuf+p, "%d ", diff);
588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    }
589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    else
590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		p += VG_(sprintf)(outbuf+p, "%#lx ", curr->bb_addr);
591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (CLG_(clo).dump_line) {
594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    int diff = curr->line - last->line;
595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    if ( CLG_(clo).compress_pos && (last->line >0) &&
596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		 (diff > -100) && (diff < 100)) {
597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		if (diff >0)
599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		    VG_(sprintf)(outbuf+p, "+%d ", diff);
600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		else if (diff==0)
601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		    VG_(sprintf)(outbuf+p, "* ");
602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	        else
603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		    VG_(sprintf)(outbuf+p, "%d ", diff);
604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    }
605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    else
606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		VG_(sprintf)(outbuf+p, "%u ", curr->line);
607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
609436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    my_fwrite(fd, outbuf, VG_(strlen)(outbuf));
610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Print events.
615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid fprint_cost(int fd, EventMapping* es, ULong* cost)
619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int p = CLG_(sprint_mappingcost)(outbuf, es, cost);
621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  VG_(sprintf)(outbuf+p, "\n");
622436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov  my_fwrite(fd, outbuf, VG_(strlen)(outbuf));
623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return;
624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Write the cost of a source line; only that parts of the source
629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * position are written that changed relative to last written position.
630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * funcPos is the source position of the first line of actual function.
631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Something is written only if cost != 0; returns True in this case.
632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void fprint_fcost(Int fd, AddrCost* c, AddrPos* last)
634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_DEBUGIF(3) {
636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_DEBUG(2, "   print_fcost(file '%s', line %d, bb %#lx, addr %#lx):\n",
637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	     c->p.file->name, c->p.line, c->p.bb_addr, c->p.addr);
638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(print_cost)(-5, CLG_(sets).full, c->cost);
639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  fprint_pos(fd, &(c->p), last);
642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  copy_apos( last, &(c->p) ); /* update last to current position */
643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  fprint_cost(fd, CLG_(dumpmap), c->cost);
645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  /* add cost to total */
647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_(add_and_zero_cost)( CLG_(sets).full, dump_total_cost, c->cost );
648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Write out the calls from jcc (at pos)
652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void fprint_jcc(Int fd, jCC* jcc, AddrPos* curr, AddrPos* last, ULong ecounter)
654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    static AddrPos target;
656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    file_node* file;
657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    obj_node*  obj;
658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_DEBUGIF(2) {
660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      CLG_DEBUG(2, "   fprint_jcc (jkind %d)\n", jcc->jmpkind);
661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      CLG_(print_jcc)(-10, jcc);
662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
664b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    CLG_ASSERT(jcc->to !=0);
665b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    CLG_ASSERT(jcc->from !=0);
666b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!get_debug_pos(jcc->to, bb_addr(jcc->to->bb), &target)) {
668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* if we don't have debug info, don't switch to file "???" */
669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	target.file = last->file;
670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
672663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng    if ((jcc->jmpkind == jk_CondJump) || (jcc->jmpkind == jk_Jump)) {
673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* this is a JCC for a followed conditional or boring jump. */
675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      CLG_ASSERT(CLG_(is_zero_cost)( CLG_(sets).full, jcc->cost));
676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* objects among jumps should be the same.
678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       * Otherwise this jump would have been changed to a call
679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       *  (see setup_bbcc)
680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       */
681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      CLG_ASSERT(jcc->from->bb->obj == jcc->to->bb->obj);
682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* only print if target position info is usefull */
684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (!CLG_(clo).dump_instr && !CLG_(clo).dump_bb && target.line==0) {
685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  jcc->call_counter = 0;
686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  return;
687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* Different files/functions are possible e.g. with longjmp's
690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 * which change the stack, and thus context
691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 */
692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (last->file != target.file) {
693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    VG_(sprintf)(outbuf, "jfi=");
694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    print_file(outbuf+4, target.file);
695436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	    my_fwrite(fd, outbuf, VG_(strlen)(outbuf));
696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (jcc->from->cxt != jcc->to->cxt) {
699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    if (CLG_(clo).mangle_names)
700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		print_mangled_fn(fd, outbuf, "jfn",
701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				 jcc->to->cxt, jcc->to->rec_index);
702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    else
703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		print_fn(fd, outbuf, "jfn", jcc->to->cxt->fn[0]);
704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
706663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng	if (jcc->jmpkind == jk_CondJump) {
707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    /* format: jcnd=<followed>/<executions> <target> */
708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    VG_(sprintf)(outbuf, "jcnd=%llu/%llu ",
709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			 jcc->call_counter, ecounter);
710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	else {
712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    /* format: jump=<jump count> <target> */
713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    VG_(sprintf)(outbuf, "jump=%llu ",
714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			 jcc->call_counter);
715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
716436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	my_fwrite(fd, outbuf, VG_(strlen)(outbuf));
717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	fprint_pos(fd, &target, last);
719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	my_fwrite(fd, "\n", 1);
720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	fprint_pos(fd, curr, last);
721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	my_fwrite(fd, "\n", 1);
722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	jcc->call_counter = 0;
724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	return;
725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    file = jcc->to->cxt->fn[0]->file;
728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    obj  = jcc->to->bb->obj;
729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* object of called position different to object of this function?*/
731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (jcc->from->cxt->fn[0]->file->obj != obj) {
732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	VG_(sprintf)(outbuf, "cob=");
733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	print_obj(outbuf+4, obj);
734436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	my_fwrite(fd, outbuf, VG_(strlen)(outbuf));
735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* file of called position different to current file? */
738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (last->file != file) {
739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	VG_(sprintf)(outbuf, "cfi=");
740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	print_file(outbuf+4, file);
741436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	my_fwrite(fd, outbuf, VG_(strlen)(outbuf));
742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (CLG_(clo).mangle_names)
745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	print_mangled_fn(fd, outbuf, "cfn", jcc->to->cxt, jcc->to->rec_index);
746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    else
747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	print_fn(fd, outbuf, "cfn", jcc->to->cxt->fn[0]);
748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!CLG_(is_zero_cost)( CLG_(sets).full, jcc->cost)) {
750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(sprintf)(outbuf, "calls=%llu ",
751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		   jcc->call_counter);
752436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	my_fwrite(fd, outbuf, VG_(strlen)(outbuf));
753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	fprint_pos(fd, &target, last);
755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	my_fwrite(fd, "\n", 1);
756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	fprint_pos(fd, curr, last);
757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	fprint_cost(fd, CLG_(dumpmap), jcc->cost);
758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	CLG_(init_cost)( CLG_(sets).full, jcc->cost );
760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	jcc->call_counter = 0;
762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Cost summation of functions.We use alternately ccSum[0/1], thus
768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * ssSum[currSum] for recently read lines with same line number.
769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AddrCost ccSum[2];
771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int currSum;
772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Print all costs of a BBCC:
775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * - FCCs of instructions
776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * - JCCs of the unique jump of this BB
777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * returns True if something was written
778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool fprint_bbcc(Int fd, BBCC* bbcc, AddrPos* last)
780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  InstrInfo* instr_info;
782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ULong ecounter;
783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Bool something_written = False;
784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  jCC* jcc;
785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  AddrCost *currCost, *newCost;
786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Int jcc_count = 0, instr, i, jmp;
787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  BB* bb = bbcc->bb;
788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_ASSERT(bbcc->cxt != 0);
790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_DEBUGIF(1) {
791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(printf)("+ fprint_bbcc (Instr %d): ", bb->instr_count);
792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(print_bbcc)(15, bbcc);
793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_ASSERT(currSum == 0 || currSum == 1);
796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  currCost = &(ccSum[currSum]);
797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  newCost  = &(ccSum[1-currSum]);
798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ecounter = bbcc->ecounter_sum;
800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  jmp = 0;
801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  instr_info = &(bb->instr[0]);
802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for(instr=0; instr<bb->instr_count; instr++, instr_info++) {
803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* get debug info of current instruction address and dump cost
805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     * if CLG_(clo).dump_bbs or file/line has changed
806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     */
807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!get_debug_pos(bbcc, bb_addr(bb) + instr_info->instr_offset,
808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		       &(newCost->p))) {
809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* if we don't have debug info, don't switch to file "???" */
810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      newCost->p.file = bbcc->cxt->fn[0]->file;
811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (CLG_(clo).dump_bbs || CLG_(clo).dump_instr ||
814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	(newCost->p.line != currCost->p.line) ||
815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	(newCost->p.file != currCost->p.file)) {
816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!CLG_(is_zero_cost)( CLG_(sets).full, currCost->cost )) {
818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	something_written = True;
819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	fprint_apos(fd, &(currCost->p), last, bbcc->cxt->fn[0]->file);
821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	fprint_fcost(fd, currCost, last);
822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* switch buffers */
825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      currSum = 1 - currSum;
826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      currCost = &(ccSum[currSum]);
827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      newCost  = &(ccSum[1-currSum]);
828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* add line cost to current cost sum */
831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    (*CLG_(cachesim).add_icost)(currCost->cost, bbcc, instr_info, ecounter);
832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* print jcc's if there are: only jumps */
834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (bb->jmp[jmp].instr == instr) {
835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	jcc_count=0;
836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	for(jcc=bbcc->jmp[jmp].jcc_list; jcc; jcc=jcc->next_from)
837663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng	    if (((jcc->jmpkind != jk_Call) && (jcc->call_counter >0)) ||
838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		(!CLG_(is_zero_cost)( CLG_(sets).full, jcc->cost )))
839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	      jcc_count++;
840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (jcc_count>0) {
842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    if (!CLG_(is_zero_cost)( CLG_(sets).full, currCost->cost )) {
843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		/* no need to switch buffers, as position is the same */
844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		fprint_apos(fd, &(currCost->p), last, bbcc->cxt->fn[0]->file);
845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		fprint_fcost(fd, currCost, last);
846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    }
847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    get_debug_pos(bbcc, bb_addr(bb)+instr_info->instr_offset, &(currCost->p));
848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    fprint_apos(fd, &(currCost->p), last, bbcc->cxt->fn[0]->file);
849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    something_written = True;
850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    for(jcc=bbcc->jmp[jmp].jcc_list; jcc; jcc=jcc->next_from) {
851663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng		if (((jcc->jmpkind != jk_Call) && (jcc->call_counter >0)) ||
852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		    (!CLG_(is_zero_cost)( CLG_(sets).full, jcc->cost )))
853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		    fprint_jcc(fd, jcc, &(currCost->p), last, ecounter);
854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    }
855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* update execution counter */
859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (jmp < bb->cjmp_count)
860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (bb->jmp[jmp].instr == instr) {
861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    ecounter -= bbcc->jmp[jmp].ecounter;
862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    jmp++;
863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  /* jCCs at end? If yes, dump cumulated line info first */
867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  jcc_count = 0;
868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for(jcc=bbcc->jmp[jmp].jcc_list; jcc; jcc=jcc->next_from) {
869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* yes, if JCC only counts jmp arcs or cost >0 */
870663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if ( ((jcc->jmpkind != jk_Call) && (jcc->call_counter >0)) ||
871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	   (!CLG_(is_zero_cost)( CLG_(sets).full, jcc->cost )))
872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  jcc_count++;
873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if ( (bbcc->skipped &&
876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	!CLG_(is_zero_cost)(CLG_(sets).full, bbcc->skipped)) ||
877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       (jcc_count>0) ) {
878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!CLG_(is_zero_cost)( CLG_(sets).full, currCost->cost )) {
880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* no need to switch buffers, as position is the same */
881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprint_apos(fd, &(currCost->p), last, bbcc->cxt->fn[0]->file);
882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprint_fcost(fd, currCost, last);
883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    get_debug_pos(bbcc, bb_jmpaddr(bb), &(currCost->p));
886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    fprint_apos(fd, &(currCost->p), last, bbcc->cxt->fn[0]->file);
887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    something_written = True;
888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* first, print skipped costs for calls */
890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (bbcc->skipped && !CLG_(is_zero_cost)( CLG_(sets).full,
891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown					     bbcc->skipped )) {
892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      CLG_(add_and_zero_cost)( CLG_(sets).full,
893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			      currCost->cost, bbcc->skipped );
894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if 0
895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(sprintf)(outbuf, "# Skipped\n");
896436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      my_fwrite(fd, outbuf, VG_(strlen)(outbuf));
897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprint_fcost(fd, currCost, last);
899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (jcc_count > 0)
902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	for(jcc=bbcc->jmp[jmp].jcc_list; jcc; jcc=jcc->next_from) {
903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    CLG_ASSERT(jcc->jmp == jmp);
904663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng	    if ( ((jcc->jmpkind != jk_Call) && (jcc->call_counter >0)) ||
905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		 (!CLG_(is_zero_cost)( CLG_(sets).full, jcc->cost )))
906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		fprint_jcc(fd, jcc, &(currCost->p), last, ecounter);
908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (CLG_(clo).dump_bbs || CLG_(clo).dump_bb) {
912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!CLG_(is_zero_cost)( CLG_(sets).full, currCost->cost )) {
913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      something_written = True;
914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprint_apos(fd, &(currCost->p), last, bbcc->cxt->fn[0]->file);
916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprint_fcost(fd, currCost, last);
917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
918436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    if (CLG_(clo).dump_bbs) my_fwrite(fd, "\n", 1);
919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* when every cost was immediatly written, we must have done so,
921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     * as this function is only called when there's cost in a BBCC
922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     */
923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_ASSERT(something_written);
924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  bbcc->ecounter_sum = 0;
927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for(i=0; i<=bbcc->bb->cjmp_count; i++)
928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    bbcc->jmp[i].ecounter = 0;
929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  bbcc->ret_counter = 0;
930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_DEBUG(1, "- fprint_bbcc: JCCs %d\n", jcc_count);
932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return something_written;
934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* order by
937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *  recursion,
938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *  from->bb->obj, from->bb->fn
939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *  obj, fn[0]->file, fn
940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *  address
941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int my_cmp(BBCC** pbbcc1, BBCC** pbbcc2)
943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if 0
945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return (*pbbcc1)->bb->offset - (*pbbcc2)->bb->offset;
946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    BBCC *bbcc1 = *pbbcc1;
948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    BBCC *bbcc2 = *pbbcc2;
949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Context* cxt1 = bbcc1->cxt;
950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Context* cxt2 = bbcc2->cxt;
951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int off = 1;
952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (cxt1->fn[0]->file->obj != cxt2->fn[0]->file->obj)
954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	return cxt1->fn[0]->file->obj - cxt2->fn[0]->file->obj;
955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (cxt1->fn[0]->file != cxt2->fn[0]->file)
957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	return cxt1->fn[0]->file - cxt2->fn[0]->file;
958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (cxt1->fn[0] != cxt2->fn[0])
960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	return cxt1->fn[0] - cxt2->fn[0];
961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (bbcc1->rec_index != bbcc2->rec_index)
963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	return bbcc1->rec_index - bbcc2->rec_index;
964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while((off < cxt1->size) && (off < cxt2->size)) {
966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	fn_node* ffn1 = cxt1->fn[off];
967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	fn_node* ffn2 = cxt2->fn[off];
968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (ffn1->file->obj != ffn2->file->obj)
969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    return ffn1->file->obj - ffn2->file->obj;
970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (ffn1 != ffn2)
971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    return ffn1 - ffn2;
972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	off++;
973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if      (cxt1->size > cxt2->size) return 1;
975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    else if (cxt1->size < cxt2->size) return -1;
976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return bbcc1->bb->offset - bbcc2->bb->offset;
978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* modified version of:
986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * qsort -- qsort interface implemented by faster quicksort.
988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * J. L. Bentley and M. D. McIlroy, SPE 23 (1993) 1249-1265.
989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Copyright 1993, John Wiley.
990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__
993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid swapfunc(BBCC** a, BBCC** b, int n)
994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while(n>0) {
996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	BBCC* t = *a; *a = *b; *b = t;
997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	a++, b++;
998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	n--;
999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__
1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid swap(BBCC** a, BBCC** b)
1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    BBCC* t;
1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    t = *a; *a = *b; *b = t;
1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define min(x, y) ((x)<=(y) ? (x) : (y))
1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBBCC** med3(BBCC **a, BBCC **b, BBCC **c, int (*cmp)(BBCC**,BBCC**))
1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{	return cmp(a, b) < 0 ?
1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		  (cmp(b, c) < 0 ? b : cmp(a, c) < 0 ? c : a)
1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		: (cmp(b, c) > 0 ? b : cmp(a, c) > 0 ? c : a);
1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic BBCC** qsort_start = 0;
1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void qsort(BBCC **a, int n, int (*cmp)(BBCC**,BBCC**))
1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	BBCC **pa, **pb, **pc, **pd, **pl, **pm, **pn, **pv;
1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	int s, r;
1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	BBCC* v;
1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	CLG_DEBUG(8, "  qsort(%ld,%ld)\n", a-qsort_start + 0L, n + 0L);
1027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (n < 7) {	 /* Insertion sort on smallest arrays */
1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		for (pm = a+1; pm < a+n; pm++)
1030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			for (pl = pm; pl > a && cmp(pl-1, pl) > 0; pl --)
1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				swap(pl, pl-1);
1032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		CLG_DEBUGIF(8) {
1034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		    for (pm = a; pm < a+n; pm++) {
1035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			VG_(printf)("   %3ld BB %#lx, ",
1036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    pm - qsort_start + 0L,
1037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				    bb_addr((*pm)->bb));
1038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			CLG_(print_cxt)(9, (*pm)->cxt, (*pm)->rec_index);
1039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		    }
1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		}
1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		return;
1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	pm = a + n/2;    /* Small arrays, middle element */
1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (n > 7) {
1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		pl = a;
1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		pn = a + (n-1);
1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		if (n > 40) {    /* Big arrays, pseudomedian of 9 */
1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			s = n/8;
1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			pl = med3(pl, pl+s, pl+2*s, cmp);
1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			pm = med3(pm-s, pm, pm+s, cmp);
1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			pn = med3(pn-2*s, pn-s, pn, cmp);
1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		}
1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		pm = med3(pl, pm, pn, cmp); /* Mid-size, med of 3 */
1054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
1055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	v = *pm;
1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	pv = &v;
1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	pa = pb = a;
1060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	pc = pd = a + (n-1);
1061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	for (;;) {
1062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		while ((pb <= pc) && ((r=cmp(pb, pv)) <= 0)) {
1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		    if (r==0) {
1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			/* same as pivot, to start */
1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			swap(pa,pb); pa++;
1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		    }
1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		    pb ++;
1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		}
1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		while ((pb <= pc) && ((r=cmp(pc, pv)) >= 0)) {
1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		    if (r==0) {
1071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			/* same as pivot, to end */
1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			swap(pc,pd); pd--;
1073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		    }
1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		    pc --;
1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		}
1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		if (pb > pc) { break; }
1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		swap(pb, pc);
1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		pb ++;
1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		pc --;
1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
1081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	pb--;
1082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	pc++;
1083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* put pivot from start into middle */
1085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if ((s = pa-a)>0) { for(r=0;r<s;r++) swap(a+r, pb+1-s+r); }
1086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* put pivot from end into middle */
1087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if ((s = a+n-1-pd)>0) { for(r=0;r<s;r++) swap(pc+r, a+n-s+r); }
1088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	CLG_DEBUGIF(8) {
1090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  VG_(printf)("   PV BB %#lx, ", bb_addr((*pv)->bb));
1091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    CLG_(print_cxt)(9, (*pv)->cxt, (*pv)->rec_index);
1092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    s = pb-pa+1;
1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    VG_(printf)("    Lower %ld - %ld:\n",
1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        a-qsort_start + 0L,
1096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        a+s-1-qsort_start + 0L);
1097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    for (r=0;r<s;r++) {
1098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		pm = a+r;
1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		VG_(printf)("     %3ld BB %#lx, ",
1100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			    pm-qsort_start + 0L,
1101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            bb_addr((*pm)->bb));
1102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		CLG_(print_cxt)(9, (*pm)->cxt, (*pm)->rec_index);
1103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    }
1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    s = pd-pc+1;
1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    VG_(printf)("    Upper %ld - %ld:\n",
1107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			a+n-s-qsort_start + 0L,
1108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        a+n-1-qsort_start + 0L);
1109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    for (r=0;r<s;r++) {
1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		pm = a+n-s+r;
1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		VG_(printf)("     %3ld BB %#lx, ",
1112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			    pm-qsort_start + 0L,
1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            bb_addr((*pm)->bb));
1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		CLG_(print_cxt)(9, (*pm)->cxt, (*pm)->rec_index);
1115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    }
1116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
1117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if ((s = pb+1-pa) > 1) qsort(a,     s, cmp);
1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if ((s = pd+1-pc) > 1) qsort(a+n-s, s, cmp);
1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Helpers for prepare_dump */
1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int    prepare_count;
1126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic BBCC** prepare_ptr;
1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void hash_addCount(BBCC* bbcc)
1130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if ((bbcc->ecounter_sum > 0) || (bbcc->ret_counter>0))
1132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    prepare_count++;
1133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void hash_addPtr(BBCC* bbcc)
1136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if ((bbcc->ecounter_sum == 0) &&
1138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (bbcc->ret_counter == 0)) return;
1139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  *prepare_ptr = bbcc;
1141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  prepare_ptr++;
1142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void cs_addCount(thread_info* ti)
1146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Int i;
1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  BBCC* bbcc;
1149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  /* add BBCCs with active call in call stack of current thread.
1151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * update cost sums for active calls
1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
1153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for(i = 0; i < CLG_(current_call_stack).sp; i++) {
1155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    call_entry* e = &(CLG_(current_call_stack).entry[i]);
1156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (e->jcc == 0) continue;
1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(add_diff_cost_lz)( CLG_(sets).full, &(e->jcc->cost),
1159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			   e->enter_cost, CLG_(current_state).cost);
1160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    bbcc = e->jcc->from;
1161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_DEBUG(1, " [%2d] (tid %d), added active: %s\n",
1163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	     i,CLG_(current_tid),bbcc->cxt->fn[0]->name);
1164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (bbcc->ecounter_sum>0 || bbcc->ret_counter>0) {
1166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* already counted */
1167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      continue;
1168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
1169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    prepare_count++;
1170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void cs_addPtr(thread_info* ti)
1174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Int i;
1176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  BBCC* bbcc;
1177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  /* add BBCCs with active call in call stack of current thread.
1179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * update cost sums for active calls
1180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
1181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for(i = 0; i < CLG_(current_call_stack).sp; i++) {
1183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    call_entry* e = &(CLG_(current_call_stack).entry[i]);
1184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (e->jcc == 0) continue;
1185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    bbcc = e->jcc->from;
1187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (bbcc->ecounter_sum>0 || bbcc->ret_counter>0) {
1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* already counted */
1190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      continue;
1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
1192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    *prepare_ptr = bbcc;
1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    prepare_ptr++;
1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
1196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
1200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Put all BBCCs with costs into a sorted array.
1201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * The returned arrays ends with a null pointer.
1202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Must be freed after dumping.
1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
1204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBBCC** prepare_dump(void)
1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    BBCC **array;
1208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    prepare_count = 0;
1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* if we do not separate among threads, this gives all */
1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* count number of BBCCs with >0 executions */
1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(forall_bbccs)(hash_addCount);
1214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* even if we do not separate among threads,
1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     * call stacks are separated */
1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (CLG_(clo).separate_threads)
1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cs_addCount(0);
1219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    else
1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      CLG_(forall_threads)(cs_addCount);
1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_DEBUG(0, "prepare_dump: %d BBCCs\n", prepare_count);
1223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* allocate bbcc array, insert BBCCs and sort */
1225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    prepare_ptr = array =
1226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (BBCC**) CLG_MALLOC("cl.dump.pd.1",
1227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          (prepare_count+1) * sizeof(BBCC*));
1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(forall_bbccs)(hash_addPtr);
1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (CLG_(clo).separate_threads)
1232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cs_addPtr(0);
1233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    else
1234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      CLG_(forall_threads)(cs_addPtr);
1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_ASSERT(array + prepare_count == prepare_ptr);
1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* end mark */
1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    *prepare_ptr = 0;
1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_DEBUG(0,"             BBCCs inserted\n");
1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    qsort_start = array;
1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    qsort(array, prepare_count, my_cmp);
1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_DEBUG(0,"             BBCCs sorted\n");
1247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return array;
1249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1254436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void fprint_cost_ln(int fd, const HChar* prefix,
1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			   EventMapping* em, ULong* cost)
1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int p;
1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p = VG_(sprintf)(outbuf, "%s", prefix);
1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p += CLG_(sprint_mappingcost)(outbuf + p, em, cost);
1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(sprintf)(outbuf + p, "\n");
1262436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    my_fwrite(fd, outbuf, VG_(strlen)(outbuf));
1263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong bbs_done = 0;
1266436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic HChar* filename = 0;
1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid file_err(void)
1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(message)(Vg_UserMsg,
1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                "Error: can not open cache simulation output file `%s'\n",
1273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                filename );
1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(exit)(1);
1275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
1278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Create a new dump file and write header.
1279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
1280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Naming: <CLG_(clo).filename_base>.<pid>[.<part>][-<tid>]
1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *         <part> is skipped for final dump (trigger==0)
1282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *         <tid>  is skipped for thread 1 with CLG_(clo).separate_threads=no
1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Returns the file descriptor, and -1 on error (no write permission)
1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
1286436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic int new_dumpfile(HChar buf[BUF_LEN], int tid, const HChar* trigger)
1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Bool appending = False;
1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int i, fd;
1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    FullCost sum = 0;
1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    SysRes res;
1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_ASSERT(dumps_initialized);
1294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_ASSERT(filename != 0);
1295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!CLG_(clo).combine_dumps) {
1297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	i = VG_(sprintf)(filename, "%s", out_file);
1298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (trigger)
1300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    i += VG_(sprintf)(filename+i, ".%d", out_counter);
1301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (CLG_(clo).separate_threads)
1303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    VG_(sprintf)(filename+i, "-%02d", tid);
1304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	res = VG_(open)(filename, VKI_O_WRONLY|VKI_O_TRUNC, 0);
1306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
1307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    else {
1308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	VG_(sprintf)(filename, "%s", out_file);
1309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        res = VG_(open)(filename, VKI_O_WRONLY|VKI_O_APPEND, 0);
1310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (!sr_isError(res) && out_counter>1)
1311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    appending = True;
1312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
1313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (sr_isError(res)) {
1315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	res = VG_(open)(filename, VKI_O_CREAT|VKI_O_WRONLY,
1316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			VKI_S_IRUSR|VKI_S_IWUSR);
1317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (sr_isError(res)) {
1318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    /* If the file can not be opened for whatever reason (conflict
1319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       between multiple supervised processes?), give up now. */
1320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    file_err();
1321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
1322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
1323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    fd = (Int) sr_Res(res);
1324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_DEBUG(2, "  new_dumpfile '%s'\n", filename);
1326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!appending)
1328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	reset_dump_array();
1329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!appending) {
1332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* version */
1333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	VG_(sprintf)(buf, "version: 1\n");
1334436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	my_fwrite(fd, buf, VG_(strlen)(buf));
1335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* creator */
1337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	VG_(sprintf)(buf, "creator: callgrind-" VERSION "\n");
1338436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	my_fwrite(fd, buf, VG_(strlen)(buf));
1339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* "pid:" line */
1341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	VG_(sprintf)(buf, "pid: %d\n", VG_(getpid)());
1342436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	my_fwrite(fd, buf, VG_(strlen)(buf));
1343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* "cmd:" line */
1345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	VG_(strcpy)(buf, "cmd: ");
1346436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	my_fwrite(fd, buf, VG_(strlen)(buf));
1347436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	my_fwrite(fd, cmdbuf, VG_(strlen)(cmdbuf));
1348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
1349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(sprintf)(buf, "\npart: %d\n", out_counter);
1351436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    my_fwrite(fd, buf, VG_(strlen)(buf));
1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (CLG_(clo).separate_threads) {
1353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	VG_(sprintf)(buf, "thread: %d\n", tid);
1354436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	my_fwrite(fd, buf, VG_(strlen)(buf));
1355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* "desc:" lines */
1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!appending) {
1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	my_fwrite(fd, "\n", 1);
1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if 0
1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* Global options changing the tracing behaviour */
1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	VG_(sprintf)(buf, "\ndesc: Option: --skip-plt=%s\n",
1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		     CLG_(clo).skip_plt ? "yes" : "no");
1365436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	my_fwrite(fd, buf, VG_(strlen)(buf));
1366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	VG_(sprintf)(buf, "desc: Option: --collect-jumps=%s\n",
1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		     CLG_(clo).collect_jumps ? "yes" : "no");
1368436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	my_fwrite(fd, buf, VG_(strlen)(buf));
1369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	VG_(sprintf)(buf, "desc: Option: --separate-recs=%d\n",
1370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		     CLG_(clo).separate_recursions);
1371436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	my_fwrite(fd, buf, VG_(strlen)(buf));
1372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	VG_(sprintf)(buf, "desc: Option: --separate-callers=%d\n",
1373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		     CLG_(clo).separate_callers);
1374436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	my_fwrite(fd, buf, VG_(strlen)(buf));
1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	VG_(sprintf)(buf, "desc: Option: --dump-bbs=%s\n",
1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		     CLG_(clo).dump_bbs ? "yes" : "no");
1378436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	my_fwrite(fd, buf, VG_(strlen)(buf));
1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	VG_(sprintf)(buf, "desc: Option: --separate-threads=%s\n",
1380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		     CLG_(clo).separate_threads ? "yes" : "no");
1381436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	my_fwrite(fd, buf, VG_(strlen)(buf));
1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	(*CLG_(cachesim).getdesc)(buf);
1385436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	my_fwrite(fd, buf, VG_(strlen)(buf));
1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(sprintf)(buf, "\ndesc: Timerange: Basic block %llu - %llu\n",
1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		 bbs_done, CLG_(stat).bb_executions);
1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1391436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    my_fwrite(fd, buf, VG_(strlen)(buf));
1392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(sprintf)(buf, "desc: Trigger: %s\n",
1393436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov		 trigger ? trigger : "Program termination");
1394436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    my_fwrite(fd, buf, VG_(strlen)(buf));
1395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if 0
1397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Output function specific config
1398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    * FIXME */
1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < N_FNCONFIG_ENTRIES; i++) {
1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       fnc = fnc_table[i];
1401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       while (fnc) {
1402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	   if (fnc->skip) {
1403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       VG_(sprintf)(buf, "desc: Option: --fn-skip=%s\n", fnc->name);
1404436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	       my_fwrite(fd, buf, VG_(strlen)(buf));
1405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	   }
1406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	   if (fnc->dump_at_enter) {
1407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       VG_(sprintf)(buf, "desc: Option: --fn-dump-at-enter=%s\n",
1408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			    fnc->name);
1409436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	       my_fwrite(fd, buf, VG_(strlen)(buf));
1410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	   }
1411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	   if (fnc->dump_at_leave) {
1412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       VG_(sprintf)(buf, "desc: Option: --fn-dump-at-leave=%s\n",
1413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			    fnc->name);
1414436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	       my_fwrite(fd, buf, VG_(strlen)(buf));
1415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	   }
1416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	   if (fnc->separate_callers != CLG_(clo).separate_callers) {
1417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       VG_(sprintf)(buf, "desc: Option: --separate-callers%d=%s\n",
1418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			    fnc->separate_callers, fnc->name);
1419436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	       my_fwrite(fd, buf, VG_(strlen)(buf));
1420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	   }
1421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	   if (fnc->separate_recursions != CLG_(clo).separate_recursions) {
1422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       VG_(sprintf)(buf, "desc: Option: --separate-recs%d=%s\n",
1423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			    fnc->separate_recursions, fnc->name);
1424436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	       my_fwrite(fd, buf, VG_(strlen)(buf));
1425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	   }
1426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	   fnc = fnc->next;
1427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       }
1428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* "positions:" line */
1432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(sprintf)(buf, "\npositions:%s%s%s\n",
1433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		CLG_(clo).dump_instr ? " instr" : "",
1434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		CLG_(clo).dump_bb    ? " bb" : "",
1435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		CLG_(clo).dump_line  ? " line" : "");
1436436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   my_fwrite(fd, buf, VG_(strlen)(buf));
1437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* "events:" line */
1439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i = VG_(sprintf)(buf, "events: ");
1440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CLG_(sprint_eventmapping)(buf+i, CLG_(dumpmap));
1441436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   my_fwrite(fd, buf, VG_(strlen)(buf));
1442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   my_fwrite(fd, "\n", 1);
1443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* summary lines */
1445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sum = CLG_(get_eventset_cost)( CLG_(sets).full );
1446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CLG_(zero_cost)(CLG_(sets).full, sum);
1447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (CLG_(clo).separate_threads) {
1448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     thread_info* ti = CLG_(get_current_thread)();
1449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     CLG_(add_diff_cost)(CLG_(sets).full, sum, ti->lastdump_cost,
1450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			   ti->states.entry[0]->cost);
1451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else {
1453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* This function is called once for thread 1, where
1454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * all costs are summed up when not dumping separate per thread.
1455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * But this is not true for summary: we need to add all threads.
1456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      */
1457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     int t;
1458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     thread_info** thr = CLG_(get_threads)();
1459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     for(t=1;t<VG_N_THREADS;t++) {
1460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       if (!thr[t]) continue;
1461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       CLG_(add_diff_cost)(CLG_(sets).full, sum,
1462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			  thr[t]->lastdump_cost,
1463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			  thr[t]->states.entry[0]->cost);
1464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
1465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   fprint_cost_ln(fd, "summary: ", CLG_(dumpmap), sum);
1467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* all dumped cost will be added to total_fcc */
1469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CLG_(init_cost_lz)( CLG_(sets).full, &dump_total_cost );
1470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   my_fwrite(fd, "\n\n",2);
1472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_verbosity) > 1)
1474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       VG_(message)(Vg_DebugMsg, "Dump to %s\n", filename);
1475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return fd;
1477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void close_dumpfile(int fd)
1481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (fd <0) return;
1483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    fprint_cost_ln(fd, "totals: ", CLG_(dumpmap),
1485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		   dump_total_cost);
1486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    //fprint_fcc_ln(fd, "summary: ", &dump_total_fcc);
1487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(add_cost_lz)(CLG_(sets).full,
1488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		     &CLG_(total_cost), dump_total_cost);
1489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    fwrite_flush();
1491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(close)(fd);
1492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (filename[0] == '.') {
1494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (-1 == VG_(rename) (filename, filename+1)) {
1495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    /* Can not rename to correct file name: give out warning */
1496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    VG_(message)(Vg_DebugMsg, "Warning: Can not rename .%s to %s\n",
1497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			 filename, filename);
1498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       }
1499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Helper for print_bbccs */
1504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int   print_fd;
1506436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic const HChar* print_trigger;
1507436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic HChar print_buf[BUF_LEN];
1508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void print_bbccs_of_thread(thread_info* ti)
1510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  BBCC **p, **array;
1512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FnPos lastFnPos;
1513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  AddrPos lastAPos;
1514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_DEBUG(1, "+ print_bbccs(tid %d)\n", CLG_(current_tid));
1516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  print_fd = new_dumpfile(print_buf, CLG_(current_tid), print_trigger);
1518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (print_fd <0) {
1519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_DEBUG(1, "- print_bbccs(tid %d): No output...\n", CLG_(current_tid));
1520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return;
1521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
1522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  p = array = prepare_dump();
1524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  init_fpos(&lastFnPos);
1525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  init_apos(&lastAPos, 0, 0, 0);
1526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (p) while(1) {
1528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* on context/function change, print old cost buffer before */
1530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (lastFnPos.cxt && ((*p==0) ||
1531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			 (lastFnPos.cxt != (*p)->cxt) ||
1532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			 (lastFnPos.rec_index != (*p)->rec_index))) {
1533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!CLG_(is_zero_cost)( CLG_(sets).full, ccSum[currSum].cost )) {
1534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* no need to switch buffers, as position is the same */
1535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	fprint_apos(print_fd, &(ccSum[currSum].p), &lastAPos,
1536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		    lastFnPos.cxt->fn[0]->file);
1537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	fprint_fcost(print_fd, &ccSum[currSum], &lastAPos);
1538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ccSum[currSum].p.file != lastFnPos.cxt->fn[0]->file) {
1541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* switch back to file of function */
1542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	VG_(sprintf)(print_buf, "fe=");
1543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	print_file(print_buf+3, lastFnPos.cxt->fn[0]->file);
1544436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	my_fwrite(print_fd, print_buf, VG_(strlen)(print_buf));
1545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      my_fwrite(print_fd, "\n", 1);
1547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
1548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (*p == 0) break;
1550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (print_fn_pos(print_fd, &lastFnPos, *p)) {
1552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* new function */
1554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      init_apos(&lastAPos, 0, 0, (*p)->cxt->fn[0]->file);
1555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      init_fcost(&ccSum[0], 0, 0, 0);
1556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      init_fcost(&ccSum[1], 0, 0, 0);
1557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      currSum = 0;
1558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
1559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (CLG_(clo).dump_bbs) {
1561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* FIXME: Specify Object of BB if different to object of fn */
1562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	int i, pos = 0;
1563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	ULong ecounter = (*p)->ecounter_sum;
1564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	pos = VG_(sprintf)(print_buf, "bb=%#lx ", (*p)->bb->offset);
1565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	for(i = 0; i<(*p)->bb->cjmp_count;i++) {
1566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    pos += VG_(sprintf)(print_buf+pos, "%d %llu ",
1567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				(*p)->bb->jmp[i].instr,
1568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				ecounter);
1569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    ecounter -= (*p)->jmp[i].ecounter;
1570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
1571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	VG_(sprintf)(print_buf+pos, "%d %llu\n",
1572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		     (*p)->bb->instr_count,
1573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		     ecounter);
1574436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	my_fwrite(print_fd, print_buf, VG_(strlen)(print_buf));
1575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
1576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    fprint_bbcc(print_fd, *p, &lastAPos);
1578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p++;
1580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
1581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  close_dumpfile(print_fd);
1583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (array) VG_(free)(array);
1584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  /* set counters of last dump */
1586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_(copy_cost)( CLG_(sets).full, ti->lastdump_cost,
1587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		  CLG_(current_state).cost );
1588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_DEBUG(1, "- print_bbccs(tid %d)\n", CLG_(current_tid));
1590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1593436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void print_bbccs(const HChar* trigger, Bool only_current_thread)
1594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  init_dump_array();
1596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  init_debug_cache();
1597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  print_fd = -1;
1599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  print_trigger = trigger;
1600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (!CLG_(clo).separate_threads) {
1602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* All BBCC/JCC costs is stored for thread 1 */
1603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Int orig_tid = CLG_(current_tid);
1604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(switch_thread)(1);
1606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    print_bbccs_of_thread( CLG_(get_current_thread)() );
1607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(switch_thread)(orig_tid);
1608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
1609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  else if (only_current_thread)
1610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    print_bbccs_of_thread( CLG_(get_current_thread)() );
1611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  else
1612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(forall_threads)(print_bbccs_of_thread);
1613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  free_dump_array();
1615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1618436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid CLG_(dump_profile)(const HChar* trigger, Bool only_current_thread)
1619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CLG_DEBUG(2, "+ dump_profile(Trigger '%s')\n",
1621436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	    trigger ? trigger : "Prg.Term.");
1622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CLG_(init_dumps)();
1624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_verbosity) > 1)
1626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       VG_(message)(Vg_DebugMsg, "Start dumping at BB %llu (%s)...\n",
1627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		    CLG_(stat).bb_executions,
1628436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov		    trigger ? trigger : "Prg.Term.");
1629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   out_counter++;
1631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   print_bbccs(trigger, only_current_thread);
1633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bbs_done = CLG_(stat).bb_executions++;
1635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_verbosity) > 1)
1637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     VG_(message)(Vg_DebugMsg, "Dumping done.\n");
1638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1640b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Copy command to cmd buffer. We want to original command line
1641b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * (can change at runtime)
1642b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */
1643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid init_cmdbuf(void)
1645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Int i,j,size = 0;
1647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  HChar* argv;
1648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1649b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  if (VG_(args_the_exename)) {
1650b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      CLG_ASSERT( VG_(strlen)( VG_(args_the_exename) ) < BUF_LEN-1);
1651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      size = VG_(sprintf)(cmdbuf, " %s", VG_(args_the_exename));
1652b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  }
1653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for(i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) {
1655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argv = * (HChar**) VG_(indexXA)( VG_(args_for_client), i );
1656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!argv) continue;
1657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ((size>0) && (size < BUF_LEN)) cmdbuf[size++] = ' ';
1658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for(j=0;argv[j]!=0;j++)
1659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  if (size < BUF_LEN) cmdbuf[size++] = argv[j];
1660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
1661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1662b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  if (size >= BUF_LEN) size = BUF_LEN-1;
1663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  cmdbuf[size] = 0;
1664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
1667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Set up file names for dump output: <out_directory>, <out_file>.
1668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * <out_file> is derived from the output format string, which defaults
1669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * to "callgrind.out.%p", where %p is replaced with the PID.
1670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * For the final file name, on intermediate dumps a counter is appended,
1671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * and further, if separate dumps per thread are requested, the thread ID.
1672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
1673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * <out_file> always starts with a full absolute path.
1674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * If the output format string represents a relative path, the current
1675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * working directory at program start is used.
1676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
1677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * This function has to be called every time a profile dump is generated
1678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * to be able to react on PID changes.
1679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
1680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid CLG_(init_dumps)()
1681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int lastSlash, i;
1683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SysRes res;
1684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   static int thisPID = 0;
1686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int currentPID = VG_(getpid)();
1687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (currentPID == thisPID) {
1688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       /* already initialized, and no PID change */
1689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       CLG_ASSERT(out_file != 0);
1690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       return;
1691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   thisPID = currentPID;
1693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!CLG_(clo).out_format)
1695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     CLG_(clo).out_format = DEFAULT_OUTFORMAT;
1696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* If a file name was already set, clean up before */
1698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (out_file) {
1699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       VG_(free)(out_file);
1700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       VG_(free)(out_directory);
1701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       VG_(free)(filename);
1702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       out_counter = 0;
1703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Setup output filename.
1706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   out_file =
1707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       VG_(expand_file_name)("--callgrind-out-file", CLG_(clo).out_format);
1708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* get base directory for dump/command/result files */
1710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CLG_ASSERT(out_file[0] == '/');
1711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   lastSlash = 0;
1712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i = 1;
1713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while(out_file[i]) {
1714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       if (out_file[i] == '/') lastSlash = i;
1715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       i++;
1716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i = lastSlash;
1718436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   out_directory = (HChar*) CLG_MALLOC("cl.dump.init_dumps.1", i+1);
1719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(strncpy)(out_directory, out_file, i);
1720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   out_directory[i] = 0;
1721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* allocate space big enough for final filenames */
1723436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   filename = (HChar*) CLG_MALLOC("cl.dump.init_dumps.2",
1724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 VG_(strlen)(out_file)+32);
1725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CLG_ASSERT(filename != 0);
1726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Make sure the output base file can be written.
1728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    * This is used for the dump at program termination.
1729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    * We stop with an error here if we can not create the
1730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    * file: This is probably because of missing rights,
1731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    * and trace parts wouldn't be allowed to be written, too.
1732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    */
1733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(strcpy)(filename, out_file);
1734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    res = VG_(open)(filename, VKI_O_WRONLY|VKI_O_TRUNC, 0);
1735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (sr_isError(res)) {
1736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	res = VG_(open)(filename, VKI_O_CREAT|VKI_O_WRONLY,
1737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		       VKI_S_IRUSR|VKI_S_IWUSR);
1738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (sr_isError(res)) {
1739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    file_err();
1740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
1741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
1742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!sr_isError(res)) VG_(close)( (Int)sr_Res(res) );
1743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!dumps_initialized)
1745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	init_cmdbuf();
1746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    dumps_initialized = True;
1748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1749