1 /*--------------------------------------------------------------------*/
4 /*--------------------------------------------------------------------*/
7 This file is part of Callgrind, a Valgrind tool for call tracing.
9 Copyright (C) 2002-2010, Josef Weidendorfer (Josef.Weidendorfer@gmx.de)
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License as
13 published by the Free Software Foundation; either version 2 of the
14 License, or (at your option) any later version.
16 This program is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 The GNU General Public License is contained in the file COPYING.
31 #define MAX_EVENTTYPE 20
33 static EventType eventtype[MAX_EVENTTYPE];
34 static Int eventtype_count = 0;
36 EventType* CLG_(register_eventtype)(Char* name)
40 if (eventtype_count == MAX_EVENTTYPE) {
41 VG_(printf)("\nMore than %d event types used!\n"
42 "Increase MAX_EVENTTYPE in ct_events.c and recomile this tool!\n",
44 VG_(tool_panic)("Too many event types requested.");
47 et = &(eventtype[eventtype_count]);
48 et->id = eventtype_count;
49 et->name = (UChar*) VG_(strdup)("cl.events.re.1", name);
58 EventType* CLG_(get_eventtype)(Char* name)
62 for(i=0;i<eventtype_count;i++)
63 if (VG_(strcmp)(eventtype[i].name, name) == 0)
68 EventType* CLG_(get_eventtype_byindex)(Int id)
70 if ((id >= 0) && (id < eventtype_count))
75 /* Allocate space for an event set */
76 EventSet* CLG_(get_eventset)(Char* n, Int capacity)
80 es = (EventSet*) CLG_MALLOC("cl.events.geSet.1",
82 capacity * sizeof(EventSetEntry));
83 es->capacity = capacity;
90 /* Incorporate a event type into a set, get start offset */
91 Int CLG_(add_eventtype)(EventSet* es, EventType* t)
93 Int offset = es->size;
94 if (es->capacity - offset < 1) return -1;
97 es->e[offset].type = t;
98 es->e[offset].nextTop = es->size;
103 /* Incorporate one event set into another, get start offset */
104 Int CLG_(add_eventset)(EventSet* dst, EventSet* src)
106 Int offset = dst->size, i;
107 if (!src || (src->size == 0)) return offset;
109 if (dst->capacity - offset < src->size) return -1;
111 for(i=0;i<src->size;i++) {
112 dst->e[offset+i].type = src->e[i].type;
113 dst->e[offset+i].nextTop = src->e[i].nextTop + offset;
115 dst->size += src->size;
120 /* Incorporate two event types into a set, with second < first */
121 Int CLG_(add_dep_event2)(EventSet* es, EventType* e1, EventType* e2)
123 Int offset = es->size;
125 if (es->capacity - offset < 2) return -1;
128 es->e[offset].type = e1;
129 es->e[offset].nextTop = es->size;
130 es->e[offset+1].type = e2;
131 es->e[offset+1].nextTop = es->size;
136 /* Incorporate 3 event types into a set, with third < second < first */
137 Int CLG_(add_dep_event3)(EventSet* es,
138 EventType* e1, EventType* e2, EventType* e3)
140 Int offset = es->size;
142 if (es->capacity - offset < 3) return -1;
145 es->e[offset].type = e1;
146 es->e[offset].nextTop = es->size;
147 es->e[offset+1].type = e2;
148 es->e[offset+1].nextTop = es->size;
149 es->e[offset+2].type = e3;
150 es->e[offset+2].nextTop = es->size;
155 Int CLG_(add_dep_event4)(EventSet* es,
156 EventType* e1, EventType* e2,
157 EventType* e3, EventType* e4)
159 Int offset = es->size;
161 if (es->capacity - offset < 4) return -1;
164 es->e[offset].type = e1;
165 es->e[offset].nextTop = es->size;
166 es->e[offset+1].type = e2;
167 es->e[offset+1].nextTop = es->size;
168 es->e[offset+2].type = e3;
169 es->e[offset+2].nextTop = es->size;
170 es->e[offset+3].type = e4;
171 es->e[offset+3].nextTop = es->size;
176 /* Returns number of characters written */
177 Int CLG_(sprint_eventset)(Char* buf, EventSet* es)
181 for(i=0; i< es->size; i++) {
182 if (pos>0) buf[pos++] = ' ';
183 pos += VG_(sprintf)(buf + pos, "%s", es->e[i].type->name);
190 /* Get cost array for an event set */
191 ULong* CLG_(get_eventset_cost)(EventSet* es)
193 return CLG_(get_costarray)(es->capacity);
196 /* Set all costs of an event set to zero */
197 void CLG_(init_cost)(EventSet* es, ULong* cost)
203 for(i=0;i<es->capacity;i++)
207 /* Set all costs of an event set to zero */
208 void CLG_(init_cost_lz)(EventSet* es, ULong** cost)
212 CLG_ASSERT(cost != 0);
214 *cost = CLG_(get_eventset_cost)(es);
216 for(i=0;i<es->capacity;i++)
220 void CLG_(zero_cost)(EventSet* es, ULong* cost)
226 for(i=0;i<es->size;i++)
230 Bool CLG_(is_zero_cost)(EventSet* es, ULong* cost)
234 if (!cost) return True;
237 if (cost[i] != 0) return False;
238 i = es->e[i].nextTop;
243 Bool CLG_(is_equal_cost)(EventSet* es, ULong* c1, ULong* c2)
247 if (!c1) return CLG_(is_zero_cost)(es,c2);
248 if (!c2) return CLG_(is_zero_cost)(es,c1);
251 if (c1[i] != c2[i]) return False;
253 i = es->e[i].nextTop;
260 void CLG_(copy_cost)(EventSet* es, ULong* dst, ULong* src)
265 CLG_(zero_cost)(es, dst);
268 CLG_ASSERT(dst != 0);
270 for(i=0;i<es->size;i++)
274 void CLG_(copy_cost_lz)(EventSet* es, ULong** pdst, ULong* src)
279 CLG_ASSERT(pdst != 0);
282 CLG_(zero_cost)(es, *pdst);
287 dst = *pdst = CLG_(get_eventset_cost)(es);
289 for(i=0;i<es->size;i++)
293 void CLG_(add_cost)(EventSet* es, ULong* dst, ULong* src)
298 CLG_ASSERT(dst != 0);
302 i = es->e[i].nextTop;
310 void CLG_(add_cost_lz)(EventSet* es, ULong** pdst, ULong* src)
316 CLG_ASSERT(pdst != 0);
320 dst = *pdst = CLG_(get_eventset_cost)(es);
321 CLG_(copy_cost)(es,dst,src);
328 i = es->e[i].nextTop;
336 /* Adds src to dst and zeros src. Returns false if nothing changed */
337 Bool CLG_(add_and_zero_cost)(EventSet* es, ULong* dst, ULong* src)
342 CLG_DEBUG(6, " add_and_zero_cost(%s, dst %p, src %p)\n", es->name, dst, src);
343 CLG_(print_cost)(-5, es, src);
346 if (!es || !src) return False;
350 i = es->e[i].nextTop;
362 /* Adds src to dst and zeros src. Returns false if nothing changed */
363 Bool CLG_(add_and_zero_cost_lz)(EventSet* es, ULong** pdst, ULong* src)
368 if (!src) return False;
372 if (i >= es->size) return False;
373 if (src[i] != 0) break;
374 i = es->e[i].nextTop;
377 CLG_ASSERT(pdst != 0);
380 dst = *pdst = CLG_(get_eventset_cost)(es);
381 CLG_(copy_cost)(es,dst,src);
382 CLG_(zero_cost)(es,src);
392 i = es->e[i].nextTop;
402 /* Adds difference of new and old to dst, and set old to new.
403 * Returns false if nothing changed */
404 Bool CLG_(add_diff_cost)(EventSet* es, ULong* dst, ULong* old, ULong* new_cost)
409 if (new_cost[i] == old[i])
410 i = es->e[i].nextTop;
412 dst[i] += new_cost[i] - old[i];
413 old[i] = new_cost[i];
422 /* Adds difference of new and old to dst, and set old to new.
423 * Returns false if nothing changed */
424 Bool CLG_(add_diff_cost_lz)(EventSet* es, ULong** pdst,
425 ULong* old, ULong* new_cost)
430 if (!old && !new_cost) return False;
431 CLG_ASSERT(old && new_cost);
435 if (i >= es->size) return False;
436 if (old[i] != new_cost[i]) break;
437 i = es->e[i].nextTop;
440 CLG_ASSERT(pdst != 0);
443 dst = *pdst = CLG_(get_eventset_cost)(es);
444 CLG_(zero_cost)(es,dst);
447 dst[i] += new_cost[i] - old[i];
448 old[i] = new_cost[i];
452 if (new_cost[i] == old[i])
453 i = es->e[i].nextTop;
455 dst[i] += new_cost[i] - old[i];
456 old[i] = new_cost[i];
464 /* Returns number of characters written */
465 Int CLG_(sprint_cost)(Char* buf, EventSet* es, ULong* c)
467 Int i, pos, skipped = 0;
469 if (!c || es->size==0) return 0;
471 /* At least one entry */
472 pos = VG_(sprintf)(buf, "%llu", c[0]);
477 skipped += es->e[i].nextTop - i;
478 i = es->e[i].nextTop;
487 pos += VG_(sprintf)(buf+pos, "%llu", c[i]);
496 /* Allocate space for an event mapping */
497 EventMapping* CLG_(get_eventmapping)(EventSet* es)
503 em = (EventMapping*) CLG_MALLOC("cl.events.geMapping.1",
504 sizeof(EventMapping) +
505 es->capacity * sizeof(Int));
506 em->capacity = es->capacity;
513 void CLG_(append_event)(EventMapping* em, Char* n)
519 for(i=0; i<em->set->size; i++)
520 if (VG_(strcmp)(n, em->set->e[i].type->name)==0)
523 if (i == em->set->size) return;
525 CLG_ASSERT(em->capacity > em->size);
527 em->index[em->size] = i;
532 /* Returns number of characters written */
533 Int CLG_(sprint_eventmapping)(Char* buf, EventMapping* em)
539 for(i=0; i< em->size; i++) {
540 if (pos>0) buf[pos++] = ' ';
541 pos += VG_(sprintf)(buf + pos, "%s", em->set->e[em->index[i]].type->name);
548 /* Returns number of characters written */
549 Int CLG_(sprint_mappingcost)(Char* buf, EventMapping* em, ULong* c)
551 Int i, pos, skipped = 0;
553 if (!c || em->size==0) return 0;
555 /* At least one entry */
556 pos = VG_(sprintf)(buf, "%llu", c[em->index[0]]);
560 if (c[em->index[i]] == 0) {
571 pos += VG_(sprintf)(buf+pos, "%llu", c[em->index[i]]);