1 /* Callgraph implementation.
2 Copyright (C) 2011 Free Software Foundation, Inc.
3 Contributed by Sriraman Tallam (tmsriram@google.com)
4 and Easwaran Raman (eraman@google.com).
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
28 #include "libiberty.h"
30 /* All heap allocations are tracked to be cleaned up later. */
31 #define XNEW_ALLOC(A, T) A = XNEW (T); push_allocated_ptr (A);
32 #define XNEWVEC_ALLOC(A, T, N) A = XNEWVEC (T,N); push_allocated_ptr (A);
34 /* Push a pointer that should be freed after the plugin is done. */
35 void push_allocated_ptr (void *ptr
);
38 typedef struct edge_d Edge
;
40 /* Maintain a list of edges. */
41 typedef struct edge_list_d
44 struct edge_list_d
*next
;
45 struct edge_list_d
*prev
;
48 inline static Edge_list
*
49 make_edge_list (Edge
*e
)
52 XNEW_ALLOC (list
, Edge_list
);
59 /* Represents a node in the call graph. */
64 /* Chain all the Nodes created. */
66 /* Pointer to the next node in the chain of merged nodes. */
67 struct node_d
*merge_next
;
68 /* List of all edges with this node. */
70 /* Pointer to the last node in the chain of merged nodes. */
71 struct node_d
*last_merge_node
;
72 unsigned int is_merged
;
73 /* 1 if the function corresponding to this node can be re-ordered. */
74 unsigned int is_real_node
;
78 make_node (unsigned int id
, char *name
)
81 XNEW_ALLOC (node
, Node
);
84 node
->is_real_node
= 0;
86 node
->edge_list
= NULL
;
87 node
->last_merge_node
= node
;
89 node
->merge_next
= NULL
;
93 /* Chain the nodes that are merged. Maintain a pointer to the last
94 node in the chain. After merging at the end, the last node in the
95 current chain is the last node in the chain of the merged node. */
97 merge_node (Node
*merger
, Node
*mergee
)
99 merger
->last_merge_node
->merge_next
= mergee
;
100 merger
->last_merge_node
= mergee
->last_merge_node
;
101 mergee
->is_merged
= 1;
105 add_edge_to_node (Node
*n
, Edge
*e
)
108 assert (n
!= NULL
&& e
!= NULL
);
109 list
= make_edge_list (e
);
110 list
->next
= n
->edge_list
;
111 if (n
->edge_list
!= NULL
)
112 n
->edge_list
->prev
= list
;
116 /* A node is real only if the function can be reordered. */
118 set_as_real_node (Node
*node
)
120 node
->is_real_node
= 1;
123 /* WEAK if one of the nodes is not real. STRONG if both
125 typedef enum edge_type_
131 /*Represents an edge in the call graph. */
134 Node
*first_function
;
135 Node
*second_function
;
138 /* 1 if the nodes corresponding to this edge have been merged. */
139 unsigned int is_merged
;
140 /* Doubly linked chain of created edges. */
146 make_edge (Node
*first
, Node
*second
, unsigned int weight
)
149 XNEW_ALLOC (edge
, Edge
);
150 edge
->first_function
= first
;
151 edge
->second_function
= second
;
152 edge
->weight
= weight
;
153 edge
->type
= WEAK_EDGE
;
157 add_edge_to_node (first
, edge
);
158 add_edge_to_node (second
, edge
);
163 set_edge_type (Edge
*edge
)
165 if (edge
->first_function
->is_real_node
166 && edge
->second_function
->is_real_node
)
167 edge
->type
= STRONG_EDGE
;
169 edge
->type
= WEAK_EDGE
;
172 inline static unsigned int
173 edge_lower (Edge
*e1
, Edge
*e2
)
175 if (e1
->type
== e2
->type
)
176 return (e1
->weight
< e2
->weight
) ? 1 : 0;
177 if (e1
->type
== STRONG_EDGE
)
183 reset_functions (Edge
*e
, Node
*n1
, Node
*n2
)
186 assert (n1
->id
!= n2
->id
);
189 e
->first_function
= n1
;
190 e
->second_function
= n2
;
194 e
->first_function
= n2
;
195 e
->second_function
= n1
;
199 /* A Section is represented by its object handle and the section index. */
200 typedef struct section_id_
202 /* Name of the function. */
204 /* Full name of the section. */
208 /* Type of prefix in section name. */
210 /* Pointer to the next section in the same comdat_group. */
211 struct section_id_
*comdat_group
;
212 /* Chain all the sections created. */
213 struct section_id_
*next
;
214 /* Used for grouping sections. */
215 struct section_id_
*group
;
216 /* Check if this section has been considered for output. */
220 inline static Section_id
*
221 make_section_id (char *name
, char *full_name
,
223 void *handle
, int shndx
)
226 XNEW_ALLOC (s
, Section_id
);
228 s
->full_name
= full_name
;
229 s
->section_type
= section_type
;
232 s
->comdat_group
= NULL
;
240 /* A pair of nodes make a raw edge. Also, N1->id < N2->id. */
248 init_raw_edge (Raw_edge
*r
, Node
*n1
, Node
*n2
)
250 assert (n1
->id
!= n2
->id
);
263 inline static int is_prefix_of (const char *prefix
, const char *str
)
265 return strncmp (prefix
, str
, strlen (prefix
)) == 0;
268 /* Maps the function corresponding to section name to its
269 corresponding object handle and the section index. */
271 map_section_name_to_index (char *section_name
, void *handle
, int shndx
);
274 parse_callgraph_section_contents (void *handle
,
275 unsigned char *section_contents
,
276 unsigned int length
);
278 void dump_functions ();
280 void find_pettis_hansen_function_layout (FILE *fp
);
282 unsigned int get_layout (FILE *fp
, void*** handles
,
283 unsigned int** shndx
);
286 /* Returns 1 if callgraph is empty. */
287 unsigned int is_callgraph_empty ();