4 * Copyright (C) 1995-2007 University of Karlsruhe. All right reserved.
6 * This file is part of libFirm.
8 * This file may be distributed and/or modified under the terms of the
9 * GNU General Public License version 2 as published by the Free Software
10 * Foundation and appearing in the file LICENSE.GPL included in the
11 * packaging of this file.
13 * Licensees holding valid libFirm Professional Edition licenses may use
14 * this file in accordance with the libFirm Commercial License.
15 * Agreement provided with the Software.
17 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
18 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * @brief Names for abstract objects
26 * @date Sat Nov 13 19:35:27 CET 2004
34 pto_name: Names for abstract objects
38 # include "pto_name.h"
39 # include "pto_util.h"
44 # include <string.h> /* for memcpy */
53 # include "pto_debug.h"
57 # define obstack_chunk_alloc xmalloc
58 # define obstack_chunk_free free
60 # define NALLOC(size) obstack_alloc (name_obst, size)
62 /* Local Data Types: */
64 /* Local Variables: */
65 struct obstack *qset_obst = NULL;
66 struct obstack *name_obst = NULL;
68 static desc_t *all_descs = NULL;
70 static int name_id = 0;
75 static int last_col_idx = 0;
77 /* Local Prototypes: */
78 static int pto_name_alloc_color (desc_t*);
79 static void pto_name_set_color (desc_t*, int);
80 # endif /* defined PTO_COLOR */
82 /* ===================================================
84 =================================================== */
86 /* set a nice color to an object descriptor */
87 static void pto_name_set_obj_color (obj_desc_t *obj_desc, int col_idx)
91 for (i = 0; i < obj_desc->n_fields; i ++) {
92 qset_t *ptos = obj_desc->values [i];
94 desc_t *tgt = (desc_t*) qset_start (ptos);
97 pto_name_set_color (tgt, col_idx);
99 tgt = (desc_t*) qset_next (ptos);
104 /* set a nice color to an array descriptor */
105 static void pto_name_set_arr_color (arr_desc_t *arr_desc, int col_idx)
107 qset_t *ptos = arr_desc->value;
109 desc_t *tgt = (desc_t*) qset_start (ptos);
111 while (NULL != tgt) {
112 pto_name_set_color (tgt, col_idx);
114 tgt = (desc_t*) qset_next (ptos);
118 /* set a nice color to a descriptor */
119 static void pto_name_set_color (desc_t *desc, int col_idx)
121 /* assert (0 == desc->col_idx); */
123 desc->col_idx = col_idx;
125 if (FALSE == desc->visit) {
127 if (object == desc->kind) {
128 pto_name_set_obj_color ((obj_desc_t*) desc, col_idx);
129 } else if (array == desc->kind) {
130 pto_name_set_arr_color ((arr_desc_t*) desc, col_idx);
138 /* allocate nice colors for an object descriptor */
139 static int pto_name_alloc_obj_color (obj_desc_t *obj_desc)
144 for (i = 0; (0 == col_idx) && (i < obj_desc->n_fields); i ++) {
145 qset_t *ptos = obj_desc->values [i];
146 desc_t *tgt = (desc_t*) qset_start (ptos);
148 while ((0 == col_idx) && (NULL != tgt)) {
149 col_idx = pto_name_alloc_color (tgt);
151 tgt = (desc_t*) qset_next (ptos);
158 /* allocate nice colors for an array descriptor */
159 static int pto_name_alloc_arr_color (arr_desc_t *arr_desc)
163 qset_t *ptos = arr_desc->value;
165 desc_t *tgt = (desc_t*) qset_start (ptos);
167 while ((NULL != tgt) && (0 == col_idx)) {
168 col_idx = pto_name_alloc_color (tgt);
169 tgt = (desc_t*) qset_next (ptos);
175 /* allocate nice colors for the given descriptor */
176 static int pto_name_alloc_color (desc_t *desc)
180 if (0 != desc->col_idx) {
181 return (desc->col_idx);
184 if (FALSE == desc->visit) {
186 if (object == desc->kind) {
187 col_idx = pto_name_alloc_obj_color ((obj_desc_t*) desc);
188 } else if (array == desc->kind) {
189 col_idx = pto_name_alloc_arr_color ((arr_desc_t*) desc);
195 col_idx = ++ last_col_idx;
198 pto_name_set_color (desc, col_idx);
203 /* allocate nice colors */
204 static void pto_name_alloc_colors (void)
206 desc_t *desc = all_descs;
208 while (NULL != desc) {
209 pto_name_alloc_color (desc);
214 # endif /* defined PTO_COLOR */
216 /* See whether the given entity is a field. */
217 static int is_field (ir_entity *ent)
219 ir_type *tp = get_entity_type (ent);
221 if (is_Primitive_type (tp) || is_Pointer_type (tp)) {
222 /* actually, we don't get by by restricting ourselves to pointer types */
229 /* Helper to collect_fields(ir_type*): collect all fields of the given
230 clazz and its super classes into the given obstack. */
231 static void _collect_fields (ir_type *clazz, struct obstack *obst)
233 int n_members = get_class_n_members (clazz);
234 int n_supers = get_class_n_supertypes (clazz);
237 for (i = 0; i < n_members; i ++) {
238 ir_entity *ent = get_class_member (clazz, i);
240 if (is_field (ent)) {
241 if (allocation_static != get_entity_allocation (ent)) {
242 obstack_ptr_grow (obst, ent);
247 for (i = 0; i < n_supers; i ++) {
248 ir_type *s_clazz = get_class_supertype (clazz, i);
250 _collect_fields (s_clazz, obst);
254 /* Collect the fields of the given class and its super classes into an array.
255 The last entry of the array is written NULL. */
256 static ir_entity **collect_fields (ir_type *clazz)
263 if (NULL != get_type_link (clazz)) {
264 DBGPRINT (3, (stdout, "%s: reusing field list for \"%s\"\n",
266 get_type_name (clazz)));
268 return ((ir_entity **) get_type_link (clazz));
270 DBGPRINT (2, (stdout, "%s: new field list for \"%s\"\n",
272 get_type_name (clazz)));
275 obstack_init (&obst);
277 _collect_fields (clazz, &obst);
279 /* append terminating NULL */
280 obstack_ptr_grow (&obst, NULL);
282 n_fields = obstack_object_size (&obst) / sizeof (void*);
284 fields = NALLOC (n_fields * sizeof (ir_entity*));
285 tmp = obstack_finish(&obst);
287 memcpy (fields, tmp, n_fields * sizeof (ir_entity*));
289 obstack_free (&obst, NULL);
291 set_type_link (clazz, fields);
296 /* Write the intro text for a name dump into the given stream */
297 static void pto_name_dump_start (FILE *stream)
300 pto_name_alloc_colors ();
301 # endif /* defined PTO_COLOR */
303 fprintf (stream, "digraph \"Names\" {\n");
304 fprintf (stream, "\tgraph [rankdir=\"LR\", ordering=\"out\", size=\"11,7\", rotate=\"90\"];\n");
305 fprintf (stream, "\tnode [shape=\"record\", style=\"filled\"];\n");
306 fprintf (stream, "\tedge [color=\"black\"];\n");
307 fprintf (stream, "\n");
310 /* Write the extro text for a name dump into the given stream */
311 static void pto_name_dump_finish (FILE *stream)
313 fprintf (stream, "}\n");
316 /* Write a node for the given descriptor into the given stream */
317 static void pto_name_dump_desc (desc_t *desc, FILE *stream)
319 ir_type *tp = desc->tp;
320 const char *tp_name = get_type_name (tp);
323 fprintf (stream, "\t/* %s \"%s\" */\n",
324 object == desc->kind ? "Object" : "Array",
327 fprintf (stream, "\tdesc_%i [label=\"<HEAD>type \\[%i\\]",
330 if (-1 != desc->ctx) {
331 fprintf (stream, ", ctx = %i", desc->ctx);
333 fprintf (stream, " (global)");
336 fprintf (stream, "\\lname=\\\"%s\\\"",
342 ir_graph *graph = get_irn_irg (nd);
343 ir_entity *method = get_irg_entity (graph);
344 const char *ent_name = get_entity_name (method);
345 const char *own_name = get_type_name (get_entity_owner (method));
347 fprintf (stream, "\\lnode=%s\\[%li\\]",
348 get_op_name (get_irn_op (nd)),
349 get_irn_node_nr (nd));
350 fprintf (stream, "\\lgraph=\\\"%s.%s\\\"",
355 if (desc->kind == object) {
356 obj_desc_t *obj_desc = (obj_desc_t*) desc;
359 for (i = 0; i < obj_desc->n_fields; i ++) {
360 ir_entity *field = obj_desc->fields [i];
362 if (is_Pointer_type (get_entity_type (field))) {
363 const char *ent_name = get_entity_name (field);
365 fprintf (stream, "|<%i>%s", i, ent_name);
368 } else if (array == desc->kind) {
369 fprintf (stream, "|<arr>[]");
371 assert (0 && "invalid descriptor");
374 /* end label string */
375 fprintf (stream, "\"");
379 const char *fontcolor;
380 int col_idx = desc->col_idx;
381 float hue = (float) col_idx / (float) last_col_idx;
382 float sat = 1.000f; /* 0.300 .. 1.000 */
383 float val = 0.800f; /* 0.300 .. 1.000 */
385 # define MAX_COLORS 12
386 if (last_col_idx > MAX_COLORS) {
387 /* too many colors ... vary value too */
388 float div = (float) MAX_COLORS / (float) last_col_idx;
390 sat = (div * ((col_idx / MAX_COLORS)));
391 val = (div * ((col_idx / MAX_COLORS)));
393 col_idx = col_idx % MAX_COLORS;
394 hue = (float) col_idx / (float) MAX_COLORS;
396 // re-adjust sat and val
398 const float sat_min = 0.200f; /* 0.200 .. 0.400 */
399 const float val_min = 0.300f; /* 0.300 .. 0.400 */
401 sat = sat_min + ((1.0f - sat_min) * sat);
402 val = val_min + ((1.0f - val_min) * val);
407 fprintf (stream, ", color=\"%01.3f, %01.3f, %01.3f\"", hue, sat, val);
409 if ((hue > 0.3) && (sat < 0.5)) {
411 } else if (sat < 0.4) {
417 fprintf (stream, ", fontcolor=\"%s\"", fontcolor);
419 # else /* if defined PTO_COLOR */
420 fprintf (stream, ", color=\"lightgrey\"");
421 # endif /* defined PTO_COLOR */
424 fprintf (stream, "];\n");
425 fprintf (stream, "\n");
428 if (desc->kind == object) {
429 obj_desc_t *obj_desc = (obj_desc_t*) desc;
432 for (i = 0; i < obj_desc->n_fields; i ++) {
433 desc_t *tgt = (desc_t*) qset_start (obj_desc->values [i]);
435 while (NULL != tgt) {
436 fprintf (stream, "\tdesc_%i:%i -> desc_%i:HEAD;\n",
437 desc->id, i, tgt->id);
439 tgt = (desc_t*) qset_next (obj_desc->values [i]);
442 } else if (array == desc->kind) {
443 arr_desc_t *arr_desc = (arr_desc_t*) desc;
445 desc_t *tgt = (desc_t*) qset_start (arr_desc->value);
447 while (NULL != tgt) {
448 fprintf (stream, "\tdesc_%i:arr -> desc_%i:HEAD;\n",
451 tgt = (desc_t*) qset_next (arr_desc->value);
455 fprintf (stream, "\n");
459 /* ===================================================
460 Exported Implementation:
461 =================================================== */
462 /* Find the given descriptor's entry for the given entity */
463 qset_t *get_entry (desc_t *desc, ir_entity *ent)
466 if (desc->kind == object) {
467 obj_desc_t *obj_desc = (obj_desc_t*) desc;
469 const int n_fields = obj_desc->n_fields;
471 for (i = 0; i < n_fields; i ++) {
472 if (ent == obj_desc->fields [i]) {
473 return (obj_desc->values [i]);
477 assert (0 && "entry not found");
478 } else if (desc->kind == array) {
479 arr_desc_t *arr_desc = (arr_desc_t*) desc;
481 return (arr_desc->value);
483 assert (0 && "invalid descriptor");
489 /* get a new descriptor for the given type at the given node */
490 desc_t *new_name (ir_type *tp, ir_node *node, int ctx)
494 assert ((is_Class_type (tp) || is_Array_type (tp)) && "unsuitable type");
496 DBGPRINT (2, (stdout, "%s: new name for type \"%s\"\n",
498 get_type_name (tp)));
501 if (is_Class_type (tp)) {
502 obj_desc_t *obj_desc = NALLOC (sizeof (obj_desc_t));
506 obj_desc->kind = object;
507 obj_desc->fields = collect_fields (tp);
509 for (n_fields = 0; (NULL != obj_desc->fields [n_fields]); n_fields ++) {
510 /* nothing, just count ... */
513 obj_desc->n_fields = n_fields;
514 obj_desc->values = (qset_t**) NALLOC (n_fields * sizeof (qset_t*));
516 for (i = 0; i < n_fields; i ++) {
517 obj_desc->values [i] = qset_new (N_INITIAL_OJBS, qset_obst);
520 desc = (desc_t*) obj_desc;
521 } else if (is_Array_type (tp)) {
522 arr_desc_t *arr_desc = (arr_desc_t*) NALLOC (sizeof (arr_desc_t));
524 arr_desc->kind = array;
525 arr_desc->value = qset_new (N_INITIAL_OJBS, qset_obst);
527 desc = (desc_t*) arr_desc;
530 desc->id = name_id ++;
537 desc->prev = all_descs;
543 # define N_GLOB_INITIAL_FIELDS 20
544 static obj_desc_t *obj_glob = NULL;
545 static int n_glob_fields = N_GLOB_INITIAL_FIELDS;
547 /* get a new descriptor for the given (presumably static) entity */
548 desc_t *new_ent_name (ir_entity *ent)
552 ir_type *tp = get_entity_type (ent);
554 assert (is_Pointer_type (tp));
555 tp = get_pointer_points_to_type (tp);
556 assert (is_Class_type (tp));
558 DBGPRINT (2, (stdout, "%s: new name for entity \"%s\"\n",
560 get_entity_name (ent)));
561 DBGEXE (2, (fflush (stdout)));
563 assert (((allocation_static == get_entity_allocation (ent)) ||
564 (allocation_automatic == get_entity_allocation (ent))) &&
565 "not a static/automatic field");
567 if (NULL == obj_glob) {
568 obj_glob = (obj_desc_t*) NALLOC (sizeof (obj_desc_t));
570 obj_glob->id = name_id ++;
572 obj_glob->col_idx = 0;
573 obj_glob->visit = FALSE;
574 obj_glob->kind = object;
575 obj_glob->tp = get_glob_type ();
576 obj_glob->node = NULL;
578 obj_glob->n_fields = 0;
579 obj_glob->fields = (ir_entity**) NALLOC (N_GLOB_INITIAL_FIELDS * sizeof (ir_entity*));
580 obj_glob->values = (qset_t**) NALLOC (N_GLOB_INITIAL_FIELDS * sizeof (qset_t*));
582 obj_glob->prev = all_descs;
583 all_descs = (desc_t*) obj_glob;
586 for (i = 0; missing && (i < obj_glob->n_fields); i ++) {
587 if (ent == obj_glob->fields [i]) {
593 if (obj_glob->n_fields == n_glob_fields) {
594 ir_entity **fields = obj_glob->fields;
595 qset_t **values = obj_glob->values;
598 obj_glob->fields = (ir_entity**) NALLOC (n_glob_fields * sizeof (ir_entity*));
599 obj_glob->values = (qset_t**) NALLOC (n_glob_fields * sizeof (qset_t*));
601 memcpy (obj_glob->fields, fields, obj_glob->n_fields * sizeof (ir_entity*));
602 memcpy (obj_glob->values, values, obj_glob->n_fields * sizeof (qset_t*));
608 obj_glob->fields [obj_glob->n_fields ] = ent;
609 obj_glob->values [obj_glob->n_fields ++] = qset_new (N_INITIAL_OJBS, qset_obst);
612 return ((desc_t*) obj_glob);
614 # undef N_GLOB_INITIAL_FIELDS
616 /* Dump all names to a file of the given name */
617 void pto_dump_names (const char *name)
619 desc_t *desc = all_descs;
620 FILE *stream = fopen (name, "w");
623 if (NULL == stream) {
624 fprintf (stderr, "%s: unable to open %s (%s)\n",
625 __FUNCTION__, name, strerror (errno));
629 pto_name_dump_start (stream);
631 while (NULL != desc) {
632 pto_name_dump_desc (desc, stream);
637 pto_name_dump_finish (stream);
641 /* Initialise the name module */
642 void pto_name_init (void)
644 DBGPRINT (3, (stdout, "%s\n", __FUNCTION__));
645 assert (NULL == name_obst);
646 assert (NULL == qset_obst);
648 name_obst = xmalloc (sizeof (struct obstack));
649 qset_obst = xmalloc (sizeof (struct obstack));
651 obstack_init (name_obst);
652 obstack_init (qset_obst);
655 /* Cleanup the name module */
656 void pto_name_cleanup (void)
658 DBGPRINT (3, (stdout, "%s\n", __FUNCTION__));
659 obstack_free (name_obst, NULL);
660 obstack_free (qset_obst, NULL);
662 memset (name_obst, 0x00, sizeof (struct obstack));
663 memset (qset_obst, 0x00, sizeof (struct obstack));
675 Revision 1.19 2006/12/13 19:46:47 beck
676 rename type entity into ir_entity
678 Revision 1.18 2006/01/13 22:56:21 beck
679 renamed all types 'type' to 'ir_type'
681 Revision 1.17 2005/12/16 16:59:54 grund
682 *** empty log message ***
684 Revision 1.16 2005/12/05 12:19:54 beck
685 added missing include <assert.h> (not anymore included in libFirm)
687 Revision 1.15 2005/03/02 10:14:38 beck
688 placed a return on all execution pathes
690 Revision 1.14 2005/02/17 08:45:38 liekweg
691 Don't return a value for an invalid descriptor
693 Revision 1.13 2005/02/11 10:21:28 beck
694 get_entry now always returns a value
696 Revision 1.12 2005/01/14 14:13:56 liekweg
697 fix gnu extension, fix fprintf's, fix allocs
699 Revision 1.11 2005/01/05 14:25:54 beck
700 renames all is_x*_type() functions to is_X*_type() to prevent name clash with EDG fronten
702 Revision 1.10 2004/12/22 14:43:14 beck
703 made allocations C-like
705 Revision 1.9 2004/12/21 15:34:09 beck
706 removed C99 constructs
710 Revision 1.8 2004/12/15 13:30:30 liekweg
711 use DBGEXE correctly; print yet nicer names
713 Revision 1.7 2004/12/15 09:18:18 liekweg
716 Revision 1.6 2004/12/06 12:52:09 liekweg
719 Revision 1.4 2004/11/30 15:49:27 liekweg
722 Revision 1.3 2004/11/30 14:47:54 liekweg
723 fix initialisation; do correct iteration
725 Revision 1.2 2004/11/24 14:53:56 liekweg
728 Revision 1.1 2004/11/18 16:37:34 liekweg