removed warnings
[libfirm] / ir / debug / debugger.c
1 /*
2  * Project:     libFIRM
3  * File name:   ir/debug/debugger.c
4  * Purpose:     Helper function for integerated debug support
5  * Author:      Michael Beck
6  * Modified by:
7  * Created:     2005
8  * CVS-ID:      $Id$
9  * Copyright:   (c) 2001-2007 Universität Karlsruhe
10  * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
11  */
12 #ifdef HAVE_CONFIG_H
13 #include "config.h"
14 #endif
15
16 #ifdef DEBUG_libfirm
17
18 #ifdef _WIN32
19 #define WIN32_LEAN_AND_MEAN
20 #include <windows.h>
21
22 #define strncasecmp strnicmp
23 #endif
24
25 #ifdef HAVE_STDLIB_H
26 #include <stdlib.h>
27 #endif
28
29 #include <stdio.h>
30 #include <signal.h>
31
32 #ifdef HAVE_STRING_H
33 #include <string.h>
34 #endif
35
36 #include <ctype.h>
37
38 #include "set.h"
39 #include "ident.h"
40 #include "irhooks.h"
41 #include "irgraph_t.h"
42 #include "entity_t.h"
43 #include "irprintf.h"
44 #include "typewalk.h"
45 #include "irdump.h"
46 #include "debug.h"
47
48 #ifdef _WIN32
49 /* Break into the debugger. The Win32 way. */
50 void firm_debug_break(void) {
51         DebugBreak();
52 }
53 #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64))
54 /* Break into the debugger. The ia32/x86_64 way under GCC. */
55 void firm_debug_break(void) {
56         __asm__ __volatile__("int3");
57 }
58 #else
59 /* Break into the debugger. Poor Unix way. */
60 void firm_debug_break(void) {
61         raise(SIGINT);
62 }
63 #endif /* _WIN32 */
64
65 /** supported breakpoint kinds */
66 typedef enum {
67         BP_NR    = 'n',   /**< break on node number. */
68         BP_IDENT = 'i'    /**< break on ident. */
69 } bp_kind;
70
71 /**
72  * Reasons for node number breakpoints.
73  */
74 typedef enum _bp_reasons_t {
75         BP_ON_NEW_NODE,    /**< break if node with number is created */
76         BP_ON_REPLACE,     /**< break if node with number is replaced */
77         BP_ON_LOWER,       /**< break if node with number is lowered */
78         BP_ON_REMIRG,      /**< break if an IRG is removed */
79         BP_ON_NEW_ENT,     /**< break if a new entity is created */
80         BP_ON_NEW_TYPE,    /**< break if a new type is created */
81         BP_MAX_REASON
82 } bp_reasons_t;
83
84 /** A breakpoint. */
85 typedef struct _breakpoint {
86         bp_kind      kind;        /**< the kind of this break point */
87         unsigned     bpnr;        /**< break point number */
88         int          active;      /**< non-zero, if this break point is active */
89         bp_reasons_t reason;      /**< reason for the breakpoint */
90         struct _breakpoint *next; /**< link to the next one */
91 } breakpoint;
92
93 /** A number breakpoint. */
94 typedef struct {
95         breakpoint   bp;       /**< the breakpoint data */
96         long         nr;       /**< the node number */
97 } bp_nr_t;
98
99 /** Calculate the hash value for a node breakpoint. */
100 #define HASH_NR_BP(key) (((key).nr << 2) ^ (key).bp.reason)
101
102 /** An ident breakpoint. */
103 typedef struct {
104         breakpoint   bp;       /**< the breakpoint data */
105         ident        *id;      /**< the ident */
106 } bp_ident_t;
107
108 /** Calculate the hash value for an ident breakpoint. */
109 #define HASH_IDENT_BP(key) (HASH_PTR((key).id) ^ (key).bp.reason)
110
111 /** The set containing the breakpoints on node numbers. */
112 static set *bp_numbers;
113
114 /** The set containing the breakpoints on idents. */
115 static set *bp_idents;
116
117 /**< the list of all breakpoints */
118 static breakpoint *bp_list;
119
120 /** number of the current break point */
121 static unsigned bp_num = 0;
122
123 /** set if break on init command was issued. */
124 static int break_on_init = 0;
125
126 /** the hook entries for the Firm debugger module. */
127 static hook_entry_t debugger_hooks[hook_last];
128
129 /** number of active breakpoints to maintain hooks. */
130 static unsigned num_active_bp[BP_MAX_REASON];
131
132 /**
133  * The debug message buffer
134  */
135 static char firm_dbg_msg_buf[2048];
136
137 /**
138  * If set, the debug extension writes all output to the
139  * firm_dbg_msg_buf buffer
140  */
141 static int redir_output = 0;
142
143 /**
144  * Is set to one, if the debug extension is active
145  */
146 static int is_active = 0;
147
148 /** hook the hook h with function fkt. */
149 #define HOOK(h, fkt) \
150 do {                                      \
151         debugger_hooks[h].hook._##h = fkt;    \
152         register_hook(h, &debugger_hooks[h]); \
153 } while(0)
154
155 /** unhook the hook h */
156 #define UNHOOK(h) \
157 do {                                        \
158         unregister_hook(h, &debugger_hooks[h]); \
159         debugger_hooks[h].hook._##h = NULL;     \
160 } while(0)
161
162 /** returns non-zero if a entry hook h is used */
163 #define IS_HOOKED(h) (debugger_hooks[h].hook._##h != NULL)
164
165 /* some macros needed to create the info string */
166 #define _DBG_VERSION(major, minor)  #major "." #minor
167 #define DBG_VERSION(major, minor)   _DBG_VERSION(major, minor)
168 #define API_VERSION(major, minor)   "API:" DBG_VERSION(major, minor)
169
170 /* the API version: change if needed */
171 #define FIRM_DBG_MAJOR  1
172 #define FIRM_DBG_MINOR  0
173
174 /** for automatic detection of the debug extension */
175 static const char *firm_debug_info_string =
176         API_VERSION(FIRM_DBG_MAJOR, FIRM_DBG_MINOR);
177
178 /**
179  * Returns non-zero, if the debug extension is active
180  */
181 int firm_debug_active(void) {
182         return is_active;
183 }  /* firm_debug_active */
184
185 /**
186  * Reset the debug text buffer.
187  */
188 static void reset_dbg_buf(void) {
189         firm_dbg_msg_buf[0] = '\0';
190 }  /* reset_dbg_buf */
191
192 /**
193  * Add text to the debug text buffer.
194  */
195 static void add_to_dbg_buf(const char *buf) {
196         strncat(firm_dbg_msg_buf, buf, sizeof(firm_dbg_msg_buf));
197 }  /* add_to_dbg_buf */
198
199 /**
200  * Return the content of the debug text buffer.
201  *
202  * To be called from the debugger.
203  */
204 const char *firm_debug_text(void) {
205         firm_dbg_msg_buf[sizeof(firm_dbg_msg_buf) - 1] = '\0';
206         return firm_dbg_msg_buf;
207 }  /* firm_debug_text */
208
209 /**
210  * debug output
211  */
212 static void dbg_printf(const char *fmt, ...)
213 {
214         char buf[1024];
215
216         va_list args;
217         va_start(args, fmt);
218
219         if (fmt[0] != '+')
220                 reset_dbg_buf();
221         else
222                 ++fmt;
223
224         ir_vsnprintf(buf, sizeof(buf), fmt, args);
225         va_end(args);
226
227         if (redir_output)
228                 add_to_dbg_buf(buf);
229         else
230                 puts(buf);
231 }  /* dbg_printf */
232
233 /**
234  * A new node is created.
235  *
236  * @param ctx   the hook context
237  * @param irg   the IR graph on which the node is created
238  * @param node  the new IR node that was created
239  */
240 static void dbg_new_node(void *ctx, ir_graph *irg, ir_node *node)
241 {
242         bp_nr_t key, *elem;
243
244         key.nr        = get_irn_node_nr(node);
245         key.bp.reason = BP_ON_NEW_NODE;
246
247         elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
248         if (elem && elem->bp.active) {
249                 dbg_printf("Firm BP %u reached, %+F created\n", elem->bp.bpnr, node);
250                 firm_debug_break();
251         }
252 }  /* dbg_new_node */
253
254 /**
255  * A node is replaced.
256  *
257  * @param ctx   the hook context
258  * @param old   the IR node the is replaced
259  * @param nw    the new IR node that will replace old
260  */
261 static void dbg_replace(void *ctx, ir_node *old, ir_node *nw)
262 {
263         bp_nr_t key, *elem;
264
265         key.nr        = get_irn_node_nr(old);
266         key.bp.reason = BP_ON_REPLACE;
267
268         elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
269         if (elem && elem->bp.active) {
270                 dbg_printf("Firm BP %u reached, %+F will be replaced by %+F\n", elem->bp.bpnr, old, nw);
271                 firm_debug_break();
272         }
273 }  /* dbg_replace */
274
275 /**
276  * A new node is lowered.
277  *
278  * @param ctx   the hook context
279  * @param node  the new IR node that will be lowered
280  */
281 static void dbg_lower(void *ctx, ir_node *node)
282 {
283         bp_nr_t key, *elem;
284
285         key.nr        = get_irn_node_nr(node);
286         key.bp.reason = BP_ON_LOWER;
287
288         elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
289         if (elem && elem->bp.active) {
290                 dbg_printf("Firm BP %u reached, %+F will be lowered\n", elem->bp.bpnr, node);
291                 firm_debug_break();
292         }
293 }  /* dbg_lower */
294
295 /**
296  * A graph will be deleted.
297  *
298  * @param ctx   the hook context
299  * @param irg   the IR graph that will be deleted
300  */
301 static void dbg_free_graph(void *ctx, ir_graph *irg)
302 {
303         {
304                 bp_nr_t key, *elem;
305                 key.nr        = get_irg_graph_nr(irg);
306                 key.bp.reason = BP_ON_REMIRG;
307
308                 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
309                 if (elem && elem->bp.active) {
310                         ir_printf("Firm BP %u reached, %+F will be deleted\n", elem->bp.bpnr, irg);
311                         firm_debug_break();
312                 }
313         }
314         {
315                 bp_ident_t key, *elem;
316                 ir_entity *ent = get_irg_entity(irg);
317
318                 if (! ent)
319                         return;
320
321                 key.id        = get_entity_ident(ent);
322                 key.bp.reason = BP_ON_REMIRG;
323
324                 elem = set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
325                 if (elem && elem->bp.active) {
326                         dbg_printf("Firm BP %u reached, %+F will be deleted\n", elem->bp.bpnr, ent);
327                         firm_debug_break();
328                 }
329         }
330 }  /* dbg_free_graph */
331
332 /**
333  * An entity was created.
334  *
335  * @param ctx   the hook context
336  * @param ent   the newly created entity
337  */
338 static void dbg_new_entity(void *ctx, ir_entity *ent)
339 {
340         {
341                 bp_ident_t key, *elem;
342
343                 key.id        = get_entity_ident(ent);
344                 key.bp.reason = BP_ON_NEW_ENT;
345
346                 elem = set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
347                 if (elem && elem->bp.active) {
348                         ir_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, ent);
349                         firm_debug_break();
350                 }
351         }
352         {
353                 bp_nr_t key, *elem;
354
355                 key.nr        = get_entity_nr(ent);
356                 key.bp.reason = BP_ON_NEW_ENT;
357
358                 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
359                 if (elem && elem->bp.active) {
360                         dbg_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, ent);
361                         firm_debug_break();
362                 }
363         }
364 }  /* dbg_new_entity */
365
366 /**
367  * A type was created.
368  *
369  * @param ctx   the hook context
370  * @param tp    the newly created type
371  */
372 static void dbg_new_type(void *ctx, ir_type *tp)
373 {
374         {
375                 bp_nr_t key, *elem;
376
377                 key.nr        = get_type_nr(tp);
378                 key.bp.reason = BP_ON_NEW_TYPE;
379
380                 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
381                 if (elem && elem->bp.active) {
382                         ir_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, tp);
383                         firm_debug_break();
384                 }
385         }
386         {
387                 bp_ident_t key, *elem;
388
389                 key.id        = get_type_ident(tp);
390                 key.bp.reason = BP_ON_NEW_TYPE;
391
392                 elem = set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
393                 if (elem && elem->bp.active) {
394                         dbg_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, tp);
395                         firm_debug_break();
396                 }
397         }
398 }  /* dbg_new_type */
399
400 /**
401  * Return the reason string.
402  */
403 static const char *reason_str(bp_reasons_t reason)
404 {
405         switch (reason) {
406         case BP_ON_NEW_NODE: return "node creation";
407         case BP_ON_REPLACE:  return "node replace";
408         case BP_ON_LOWER:    return "node lowering";
409         case BP_ON_REMIRG:   return "removing IRG";
410         case BP_ON_NEW_ENT:  return "entity creation";
411         case BP_ON_NEW_TYPE: return "type creation";
412         default:             assert(0);
413         }
414         return "unknown";
415 }  /* reason_str */
416
417 /**
418  * Compare two number breakpoints.
419  */
420 static int cmp_nr_bp(const void *elt, const void *key, size_t size)
421 {
422         const bp_nr_t *e1 = elt;
423         const bp_nr_t *e2 = key;
424
425         return (e1->nr - e2->nr) | (e1->bp.reason - e2->bp.reason);
426 }  /* cmp_nr_bp */
427
428 /**
429  * Compare two ident breakpoints.
430  */
431 static int cmp_ident_bp(const void *elt, const void *key, size_t size)
432 {
433         const bp_ident_t *e1 = elt;
434         const bp_ident_t *e2 = key;
435
436         return (e1->id != e2->id) | (e1->bp.reason - e2->bp.reason);
437 }  /* cmp_ident_bp */
438
439 /**
440  * Update the hooks.
441  */
442 static void update_hooks(breakpoint *bp)
443 {
444 #define CASE_ON(a, b)  case a: if (! IS_HOOKED(hook_##b)) HOOK(hook_##b, dbg_##b); break
445 #define CASE_OFF(a, b) case a: if (IS_HOOKED(hook_##b)) UNHOOK(hook_##b); break
446
447         if (bp->active)
448                 ++num_active_bp[bp->reason];
449         else
450                 --num_active_bp[bp->reason];
451
452         if (num_active_bp[bp->reason] > 0) {
453                 /* register the hooks on demand */
454                 switch (bp->reason) {
455                 CASE_ON(BP_ON_NEW_NODE, new_node);
456                 CASE_ON(BP_ON_REPLACE, replace);
457                 CASE_ON(BP_ON_LOWER, lower);
458                 CASE_ON(BP_ON_REMIRG, free_graph);
459                 CASE_ON(BP_ON_NEW_ENT, new_entity);
460                 CASE_ON(BP_ON_NEW_TYPE, new_type);
461                 default:
462                         ;
463                 }
464         }
465         else {
466                 /* unregister the hook on demand */
467                 switch (bp->reason) {
468                 CASE_OFF(BP_ON_NEW_NODE, new_node);
469                 CASE_OFF(BP_ON_REPLACE, replace);
470                 CASE_OFF(BP_ON_LOWER, lower);
471                 CASE_OFF(BP_ON_REMIRG, free_graph);
472                 CASE_OFF(BP_ON_NEW_ENT, new_entity);
473                 CASE_OFF(BP_ON_NEW_TYPE, new_type);
474                 default:
475                         ;
476                 }
477         }
478 #undef CASE_ON
479 #undef CASE_OFF
480 }  /* update_hooks */
481
482 /**
483  * Break if nr is reached.
484  */
485 static void break_on_nr(long nr, bp_reasons_t reason)
486 {
487         bp_nr_t key, *elem;
488
489         key.bp.kind   = BP_NR;
490         key.bp.bpnr   = 0;
491         key.bp.active = 1;
492         key.bp.reason = reason;
493         key.nr        = nr;
494
495         elem = set_insert(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
496
497         if (elem->bp.bpnr == 0) {
498                 /* new break point */
499                 elem->bp.bpnr = ++bp_num;
500                 elem->bp.next = bp_list;
501                 bp_list = &elem->bp;
502
503                 dbg_printf("Firm BP %u: %s of Nr %ld\n", elem->bp.bpnr, reason_str(reason), nr);
504
505                 update_hooks(&elem->bp);
506         }
507 }  /* break_on_nr */
508
509 /**
510  * Break if ident name is reached.
511  */
512 static void break_on_ident(const char *name, bp_reasons_t reason) {
513         bp_ident_t key, *elem;
514
515         key.bp.kind   = BP_IDENT;
516         key.bp.bpnr   = 0;
517         key.bp.active = 1;
518         key.bp.reason = reason;
519         key.id        = new_id_from_str(name);
520
521         elem = set_insert(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
522
523         if (elem->bp.bpnr == 0) {
524                 /* new break point */
525                 elem->bp.bpnr = ++bp_num;
526                 elem->bp.next = bp_list;
527                 bp_list = &elem->bp;
528
529                 dbg_printf("Firm BP %u: %s of ident \"%s\"\n", elem->bp.bpnr, reason_str(reason), name);
530
531                 update_hooks(&elem->bp);
532         }
533 }  /* break_on_ident */
534
535 /**
536  * Sets/resets the active flag of breakpoint bp.
537  */
538 static void bp_activate(unsigned bp, int active)
539 {
540         breakpoint *p;
541
542         for (p = bp_list; p; p = p->next) {
543                 if (p->bpnr == bp) {
544                         if (p->active != active) {
545                                 p->active = active;
546                                 update_hooks(p);
547                         }
548
549                         dbg_printf("Firm BP %u is now %s\n", bp, active ? "enabled" : "disabled");
550                         return;
551                 }
552         }
553         dbg_printf("Error: Firm BP %u not exists.\n", bp);
554 }  /* bp_activate */
555
556
557 /**
558  * Show a list of supported commands
559  */
560 static void show_commands(void) {
561         dbg_printf("Internal Firm debugger extension $Revision$ commands:\n"
562                 ".init                  break after initialization\n"
563                 ".create nr             break if node nr was created\n"
564                 ".replace nr            break if node nr is replaced by another node\n"
565                 ".lower nr              break before node nr is lowered\n"
566                 ".remirg nr|name        break if the irg of nr or entity name is deleted\n"
567                 ".newent nr|name        break if the entity nr or name was created\n"
568                 ".newtype nr|name       break if the type nr or name was created\n"
569                 ".bp                    show all breakpoints\n"
570                 ".enable nr             enable breakpoint nr\n"
571                 ".disable nr            disable breakpoint nr\n"
572                 ".showtype nr|name      show content of the type nr or name\n"
573                 ".showent nr|name       show content of the entity nr or name\n"
574                 ".setmask name msk      sets the debug module name to mask msk\n"
575                 ".setlvl  name lvl      sets the debug module name to level lvl\n"
576                 ".setoutfile name file  redirects debug output of module name to file\n"
577                 ".irgname name          prints address and graph number of a method given by its name\n"
578                 ".irgldname ldname      prints address and graph number of a method given by its ldname\n"
579                 ".help                  list all commands\n"
580                 );
581 }  /* show_commands */
582
583 /**
584  * Shows all Firm breakpoints.
585  */
586 static void show_bp(void) {
587         breakpoint *p;
588         bp_nr_t  *node_p;
589         bp_ident_t *ident_p;
590         int have_one = 0;
591
592         dbg_printf("Firm Breakpoints:");
593         for (p = bp_list; p; p = p->next) {
594                 have_one = 1;
595                 dbg_printf("+\n  BP %u: ", p->bpnr);
596
597                 switch (p->kind) {
598                 case BP_NR:
599                         node_p = (bp_nr_t *)p;
600                         dbg_printf("%s of Nr %ld ", reason_str(p->reason), node_p->nr);
601                         break;
602
603                 case BP_IDENT:
604                         ident_p = (bp_ident_t *)p;
605                         dbg_printf("+%s of ident \"%s\" ", reason_str(p->reason), get_id_str(ident_p->id));
606                         break;
607                 }
608
609                 dbg_printf(p->active ? "+enabled" : "+disabled");
610         }
611         dbg_printf(have_one ? "+\n" : "+ NONE\n");
612 }  /* show_bp */
613
614 /**
615  * firm_dbg_register() expects that the name is stored persistent.
616  * So we need this little helper function
617  */
618 static firm_dbg_module_t *dbg_register(const char *name) {
619         ident *id = new_id_from_str(name);
620
621         return firm_dbg_register(get_id_str(id));
622 }  /* dbg_register */
623
624 /**
625  * Sets the debug mask of module name to lvl
626  */
627 static void set_dbg_level(const char *name, unsigned lvl)
628 {
629         firm_dbg_module_t *module = dbg_register(name);
630
631         if (firm_dbg_get_mask(module) != lvl) {
632                 firm_dbg_set_mask(module, lvl);
633
634                 dbg_printf("Setting debug mask of module %s to %u\n", name, lvl);
635         }
636 }  /* set_dbg_level */
637
638 /**
639  * Redirects the debug output of module name to fname
640  */
641 static void set_dbg_outfile(const char *name, const char *fname)
642 {
643         firm_dbg_module_t *module = dbg_register(name);
644         FILE *f = fopen(fname, "w");
645
646         if (! f) {
647                 perror(fname);
648                 return;
649         }
650
651         firm_dbg_set_file(module, f);
652         dbg_printf("Redirecting debug output of module %s to file %s\n", name, fname);
653 }  /* set_dbg_outfile */
654
655 /**
656  * Show info about a firm thing.
657  */
658 static void show_firm_object(void *firm_thing) {
659         FILE *f = stdout;
660
661         if (firm_thing == NULL) {
662                 fprintf(f, "<NULL>\n");
663                 return;
664         }
665         switch (get_kind(firm_thing)) {
666         case k_BAD:
667                 fprintf(f, "BAD: (%p)\n", firm_thing);
668                 break;
669         case k_entity:
670                 dump_entity_to_file(f, firm_thing, dump_verbosity_max);
671                 break;
672         case k_type:
673                 dump_type_to_file(f, firm_thing, dump_verbosity_max);
674                 break;
675         case k_ir_graph:
676         case k_ir_node:
677         case k_ir_mode:
678         case k_ir_op:
679         case k_tarval:
680         case k_ir_loop:
681         case k_ir_compound_graph_path:
682         case k_ir_extblk:
683         case k_ir_prog:
684                 fprintf(f, "NIY\n");
685                 break;
686         default:
687                 fprintf(f, "Cannot identify thing at (%p).\n", firm_thing);
688         }
689 }  /* show_firm_object */
690
691 /**
692  * Find a firm type by its number.
693  */
694 static ir_type *find_type_nr(long nr) {
695         int i, n = get_irp_n_types();
696         ir_type *tp;
697
698         for (i = 0; i < n; ++i) {
699                 tp = get_irp_type(i);
700                 if (get_type_nr(tp) == nr)
701                         return tp;
702         }
703         tp = get_glob_type();
704         if (get_type_nr(tp) == nr)
705                 return tp;
706         return NULL;
707 }  /* find_type_nr */
708
709 /**
710  * Find a firm type by its name.
711  */
712 static ir_type *find_type_name(const char *name) {
713         int i, n = get_irp_n_types();
714         ir_type *tp;
715
716         for (i = 0; i < n; ++i) {
717                 tp = get_irp_type(i);
718                 if (strcmp(get_type_name(tp), name) == 0)
719                         return tp;
720         }
721         tp = get_glob_type();
722         if (strcmp(get_type_name(tp), name) == 0)
723                 return tp;
724         return NULL;
725 }  /* find_type_name */
726
727 /** The environment for the entity search functions. */
728 typedef struct find_env {
729         union {
730                 long        nr;   /**< the number that is searched for */
731                 const char *name; /**< the name that is searched for */
732         } u;
733         ir_entity *res;     /**< the result */
734 } find_env_t;
735
736 /**
737  * Type-walker: Find an entity with given number.
738  */
739 static void check_ent_nr(type_or_ent *tore, void *ctx) {
740         ir_entity *ent = (ir_entity *)tore;
741         find_env_t *env = ctx;
742
743         if (is_entity(ent))
744                 if (get_entity_nr(ent) == env->u.nr) {
745                         env->res = ent;
746                 }
747 }  /* check_ent_nr */
748
749 /**
750  * Type-walker: Find an entity with given name.
751  */
752 static void check_ent_name(type_or_ent *tore, void *ctx) {
753         ir_entity *ent = (ir_entity *)tore;
754         find_env_t *env = ctx;
755
756         if (is_entity(ent))
757                 if (strcmp(get_entity_name(ent), env->u.name) == 0) {
758                         env->res = ent;
759                 }
760 }  /* check_ent_name */
761
762 /**
763  * Find a firm entity by its number.
764  */
765 static ir_entity *find_entity_nr(long nr) {
766         find_env_t env;
767
768         env.u.nr = nr;
769         env.res  = NULL;
770         type_walk(check_ent_nr, NULL, &env);
771         return env.res;
772 }  /* find_entity_nr */
773
774 /**
775  * Find a firm entity by its name.
776  */
777 static ir_entity *find_entity_name(const char *name) {
778         find_env_t env;
779
780         env.u.name = name;
781         env.res    = NULL;
782         type_walk(check_ent_name, NULL, &env);
783         return env.res;
784 }  /* find_entity_name */
785
786 /**
787  * Search methods for a name.
788  */
789 static void show_by_name(type_or_ent *tore, void *env) {
790         ident *id = (ident *)env;
791
792         if (is_entity(tore)) {
793                 ir_entity *ent = (ir_entity *)tore;
794
795                 if (is_method_entity(ent)) {
796                         if (get_entity_ident(ent) == id) {
797                                 ir_type *owner = get_entity_owner(ent);
798                                 ir_graph *irg = get_entity_irg(ent);
799
800                                 if (owner != get_glob_type()) {
801                                         printf("%s::%s", get_type_name(owner), get_id_str(id));
802                                 } else {
803                                         printf("%s", get_id_str(id));
804                                 }
805                                 if (irg)
806                                         printf("[%ld] (%p)\n", get_irg_graph_nr(irg), irg);
807                                 else
808                                         printf(" NULL\n");
809                         }
810                 }
811         }
812 }  /* show_by_name */
813
814 /**
815  * Search methods for a ldname.
816  */
817 static void show_by_ldname(type_or_ent *tore, void *env) {
818         ident *id = (ident *)env;
819
820         if (is_entity(tore)) {
821                 ir_entity *ent = (ir_entity *)tore;
822
823                 if (is_method_entity(ent)) {
824                         if (get_entity_ld_ident(ent) == id) {
825                                 ir_type *owner = get_entity_owner(ent);
826                                 ir_graph *irg = get_entity_irg(ent);
827
828                                 if (owner != get_glob_type()) {
829                                         printf("%s::%s", get_type_name(owner), get_id_str(id));
830                                 } else {
831                                         printf("%s", get_id_str(id));
832                                 }
833                                 if (irg)
834                                         printf("[%ld] (%p)\n", get_irg_graph_nr(irg), irg);
835                                 else
836                                         printf(" NULL\n");
837                         }
838                 }
839         }
840 }  /* show_by_ldname */
841
842 /**
843  * prints the address and graph number of all irgs with given name
844  */
845 static void irg_name(const char *name) {
846         ident *id = new_id_from_str(name);
847
848         type_walk(show_by_name, NULL, (void *)id);
849 }  /* irg_name */
850
851 /**
852  * prints the address and graph number of all irgs with given ld_name
853  */
854 static void irg_ld_name(const char *name) {
855         ident *id = new_id_from_str(name);
856
857         type_walk(show_by_ldname, NULL, (void *)id);
858 }  /* irg_ld_name */
859
860 enum tokens {
861         tok_create = 256,
862         tok_replace,
863         tok_lower,
864         tok_remirg,
865         tok_newent,
866         tok_newtype,
867         tok_showtype,
868         tok_showent,
869         tok_init,
870         tok_bp,
871         tok_enable,
872         tok_disable,
873         tok_setmask,
874         tok_setlvl,
875         tok_setoutfile,
876         tok_irgname,
877         tok_irgldname,
878         tok_help,
879         tok_identifier,
880         tok_number,
881         tok_eof,
882         tok_error
883 };
884
885 static const char *reserved[] = {
886         "create",
887         "replace",
888         "lower",
889         "remirg",
890         "newent",
891         "newtype",
892         "showtype",
893         "showent",
894         "init",
895         "bp",
896         "enable",
897         "disable",
898         "setmask",
899         "setlvl",
900         "setoutfile",
901         "irgname",
902         "irgldname",
903         "help"
904 };
905
906 /**
907  * The Lexer data.
908  */
909 static struct lexer {
910         int has_token;        /**< set if a token is cached. */
911         unsigned cur_token;   /**< current token. */
912         unsigned number;      /**< current token attribute. */
913         const char *s;        /**< current token attribute. */
914         unsigned len;         /**< current token attribute. */
915
916         const char *curr_pos;
917         const char *end_pos;
918         const char *tok_start;
919 } lexer;
920
921 /**
922  * Initialize the lexer.
923  */
924 static void init_lexer(const char *input) {
925         lexer.has_token = 0;
926         lexer.curr_pos  = input;
927         lexer.end_pos   = input + strlen(input);
928 }  /* init_lexer */
929
930
931 /**
932  * Get the next char from the input.
933  */
934 static char next_char(void) {
935         if (lexer.curr_pos >= lexer.end_pos)
936                 return '\0';
937         return *lexer.curr_pos++;
938 }  /* next_char */
939
940 #define unput()         if (lexer.curr_pos < lexer.end_pos) --lexer.curr_pos
941
942 #undef MIN
943 #define MIN(a, b) (a) < (b) ? (a) : (b)
944
945 /**
946  * The lexer.
947  */
948 static unsigned get_token(void) {
949         char c;
950         int i;
951
952         /* skip white space */
953         do {
954                 c = next_char();
955         } while (c != '\0' && isspace(c));
956
957         lexer.tok_start = lexer.curr_pos - 1;
958         if (c == '.') {
959                 /* command begins here */
960                 int len = 0;
961
962                 do {
963                         c = next_char();
964                         ++len;
965                 } while (isalpha(c));
966                 unput();
967
968                 --len;
969                 for (i = sizeof(reserved)/sizeof(reserved[0]) - 1; i >= 0; --i) {
970                         if (strncasecmp(lexer.tok_start + 1, reserved[i], len) == 0 && reserved[i][len] == '\0')
971                                 break;
972                 }
973                 if (i >= 0)
974                         return 256 + i;
975                 return tok_error;
976         } else if (isalpha(c)) {
977                 /* identifier */
978                 lexer.s = lexer.curr_pos - 1;
979
980                 do {
981                         c = next_char();
982                 } while (isgraph(c));
983                 unput();
984                 lexer.len = lexer.curr_pos - lexer.s;
985                 return tok_identifier;
986         } else if (isdigit(c) || c == '-') {
987                 unsigned number = 0;
988                 unsigned sign   = 0;
989
990                 /* we support negative numbers as well, so one can easily set all bits with -1 */
991                 if (c == '-') {
992                         sign = 1;
993                         c    = next_char();
994                 }
995
996                 if (c == '0') {
997                         c = next_char();
998
999                         if (c == 'x' || c == 'X') {
1000                                 for (;;) {
1001                                         c = next_char();
1002
1003                                         if (! isxdigit(c))
1004                                                 break;
1005                                         if (isdigit(c))
1006                                                 number = (number << 4) | (c - '0');
1007                                         else
1008                                                 number = (number << 4) | (toupper(c) - 'A' + 10);
1009                                 }
1010                                 unput();
1011                                 lexer.number = number;
1012                                 return tok_number;
1013                         }
1014                 }
1015                 for (;;) {
1016                         if (! isdigit(c))
1017                                 break;
1018                         number = number * 10 + (c - '0');
1019                         c = next_char();
1020                 }
1021                 unput();
1022                 lexer.number = sign ? 0 - number : number;
1023                 return tok_number;
1024         }
1025         else if (c == '\0')
1026                 return tok_eof;
1027         return c;
1028 }  /* get_token */
1029
1030 /**
1031  * High level function to use from debugger interface
1032  *
1033  * Supported commands:
1034  *  .create nr    break if node nr was created
1035  *  .help         list all commands
1036  */
1037 void firm_debug(const char *cmd) {
1038         char name[1024], fname[1024];
1039         int len;
1040
1041         init_lexer(cmd);
1042
1043         for (;;) {
1044                 unsigned token;
1045
1046                 token = get_token();
1047
1048                 switch (token) {
1049                 case tok_eof:
1050                         goto leave;
1051
1052                 case tok_create:
1053                         token = get_token();
1054                         if (token != tok_number)
1055                                 goto error;
1056                         break_on_nr(lexer.number, BP_ON_NEW_NODE);
1057                         break;
1058
1059                 case tok_replace:
1060                         token = get_token();
1061                         if (token != tok_number)
1062                                 goto error;
1063                         break_on_nr(lexer.number, BP_ON_REPLACE);
1064                         break;
1065
1066                 case tok_lower:
1067                         token = get_token();
1068                         if (token != tok_number)
1069                                 goto error;
1070                         break_on_nr(lexer.number, BP_ON_LOWER);
1071                         break;
1072
1073                 case tok_remirg:
1074                         token = get_token();
1075
1076                         if (token == tok_number)
1077                                 break_on_nr(lexer.number, BP_ON_REMIRG);
1078                         else if (token == tok_identifier) {
1079                                 len = MIN(lexer.len, 1023);
1080                                 strncpy(name, lexer.s, len);
1081                                 name[len] = '\0';
1082                                 break_on_ident(name, BP_ON_REMIRG);
1083                         } else
1084                                 goto error;
1085                         break;
1086
1087                 case tok_newent:
1088                         token = get_token();
1089
1090                         if (token == tok_number)
1091                                 break_on_nr(lexer.number, BP_ON_NEW_ENT);
1092                         else if (token == tok_identifier) {
1093                                 len = MIN(lexer.len, 1023);
1094                                 strncpy(name, lexer.s, len);
1095                                 name[len] = '\0';
1096                                 break_on_ident(name, BP_ON_NEW_ENT);
1097                         } else
1098                                 goto error;
1099                         break;
1100
1101                 case tok_newtype:
1102                         token = get_token();
1103
1104                         if (token == tok_number)
1105                                 break_on_nr(lexer.number, BP_ON_NEW_TYPE);
1106                         else if (token == tok_identifier) {
1107                                 len = MIN(lexer.len, 1023);
1108                                 strncpy(name, lexer.s, len);
1109                                 name[len] = '\0';
1110                                 break_on_ident(name, BP_ON_NEW_TYPE);
1111                         } else
1112                                 goto error;
1113                         break;
1114
1115                 case tok_showtype:
1116                         token = get_token();
1117
1118                         if (token == tok_number)
1119                                 show_firm_object(find_type_nr(lexer.number));
1120                         else if (token == tok_identifier) {
1121                                 len = MIN(lexer.len, 1023);
1122                                 strncpy(name, lexer.s, len);
1123                                 name[len] = '\0';
1124                                 show_firm_object(find_type_name(name));
1125                         } else
1126                                 goto error;
1127                         break;
1128
1129                 case tok_showent:
1130                         token = get_token();
1131
1132                         if (token == tok_number)
1133                                 show_firm_object(find_entity_nr(lexer.number));
1134                         else if (token == tok_identifier) {
1135                                 len = MIN(lexer.len, 1023);
1136                                 strncpy(name, lexer.s, len);
1137                                 name[len] = '\0';
1138                                 show_firm_object(find_entity_name(name));
1139                         } else
1140                                 goto error;
1141                         break;
1142
1143                 case tok_init:
1144                         break_on_init = 1;
1145                         break;
1146
1147                 case tok_bp:
1148                         show_bp();
1149                         break;
1150
1151                 case tok_enable:
1152                         token = get_token();
1153                         if (token != tok_number)
1154                                 goto error;
1155                         bp_activate(lexer.number, 1);
1156                         break;
1157
1158                 case tok_disable:
1159                         token = get_token();
1160                         if (token != tok_number)
1161                                 goto error;
1162                         bp_activate(lexer.number, 0);
1163                         break;
1164
1165                 case tok_setmask:
1166                         token = get_token();
1167                         if (token != tok_identifier)
1168                                 goto error;
1169                         len = MIN(lexer.len, 1023);
1170                         strncpy(name, lexer.s, len);
1171                         name[len] = '\0';
1172
1173                         token = get_token();
1174                         if (token != tok_number)
1175                                 goto error;
1176                         set_dbg_level(name, lexer.number);
1177                         break;
1178
1179                 case tok_setlvl:
1180                         token = get_token();
1181                         if (token != tok_identifier)
1182                                 goto error;
1183                         len = MIN(lexer.len, 1023);
1184                         strncpy(name, lexer.s, len);
1185                         name[len] = '\0';
1186
1187                         token = get_token();
1188                         if (token != tok_number)
1189                                 goto error;
1190                         set_dbg_level(name, (1 << lexer.number) - 1);
1191                         break;
1192
1193                 case tok_setoutfile:
1194                         token = get_token();
1195                         if (token != tok_identifier)
1196                                 goto error;
1197                         len = MIN(lexer.len, 1023);
1198                         strncpy(name, lexer.s, len);
1199                         name[len] = '\0';
1200
1201                         token = get_token();
1202                         if (token != tok_identifier)
1203                                 goto error;
1204                         len = MIN(lexer.len, 1023);
1205                         strncpy(fname, lexer.s, len);
1206                         fname[len] = '\0';
1207                         set_dbg_outfile(name, fname);
1208
1209                 case tok_irgname:
1210                         token = get_token();
1211                         if (token != tok_identifier)
1212                                 goto error;
1213                         len = MIN(lexer.len, 1023);
1214                         strncpy(name, lexer.s, len);
1215                         name[len] = '\0';
1216                         irg_name(name);
1217
1218                 case tok_irgldname:
1219                         token = get_token();
1220                         if (token != tok_identifier)
1221                                 goto error;
1222                         len = MIN(lexer.len, 1023);
1223                         strncpy(name, lexer.s, len);
1224                         name[len] = '\0';
1225                         irg_ld_name(name);
1226                         break;
1227
1228                 case tok_help:
1229                         show_commands();
1230                         break;
1231
1232                 case tok_error:
1233                 default:
1234 error:
1235                         printf("Error: before %s\n", lexer.tok_start);
1236                         show_commands();
1237                         goto leave;
1238                 }
1239
1240                 token = get_token();
1241                 if (token == tok_eof)
1242                         break;
1243                 if (token != ';')
1244                         goto error;
1245         }
1246 leave:
1247         ;
1248 }  /* firm_debug */
1249
1250 /* creates the debugger tables */
1251 void firm_init_debugger(void)
1252 {
1253         char *env;
1254
1255         bp_numbers = new_set(cmp_nr_bp, 8);
1256         bp_idents  = new_set(cmp_ident_bp, 8);
1257
1258         env = getenv("FIRMDBG");
1259
1260         is_active = 1;
1261
1262         if (env)
1263                 firm_debug(env);
1264
1265         if (break_on_init)
1266                 firm_debug_break();
1267 }  /* firm_init_debugger */
1268
1269 #else
1270
1271 /* some picky compiler do not allow empty files */
1272 static int _firm_only_that_you_can_compile_with_NDEBUG_defined;
1273
1274 #endif /* NDEBUG */
1275
1276 /**
1277  * @page debugger   The Firm debugger extension
1278  *
1279  * Firm contains a debugger extension. This allows to set debugger breakpoints
1280  * an various events.
1281  * The extension uses a text interface which can be accessed from most debuggers.
1282  * More than one command can be given separated by ';'.
1283  *
1284  * @section sec_cmd Supported commands
1285  *
1286  * The following commands are currently supported:
1287  *
1288  * @b .init
1289  *
1290  * Break immediately after the debugger extension was initialized.
1291  * Typically this command is used in the environment to stop the execution
1292  * of a Firm compiler right after the initialization, like this:
1293  *
1294  * $export FIRMDBG=".init"
1295  *
1296  * @b .create nr
1297  *
1298  * Break if a new IR-node with node number nr was created.
1299  * Typically used to find the place where wrong nodes are created.
1300  *
1301  * @b .replace nr
1302  *
1303  * Break before IR-node with node number nr is replaced by another node.
1304  *
1305  * @b .lower nr
1306  *
1307  * Break before IR-node with node number nr is lowered.
1308  *
1309  * @b .remirg nr
1310  *
1311  * Break if the irg with graph number nr is deleted.
1312  *
1313  * @b .remirg name
1314  *
1315  * Break if the irg of entity name is deleted.
1316  *
1317  * @b .newent nr
1318  *
1319  * Break if the entity with number nr was created.
1320  *
1321  * @b .newent name
1322  *
1323  * Break if the entity name was created.
1324  *
1325  * @b .newtype nr
1326  *
1327  * Break if the type with number nr was created.
1328  *
1329  * @b .newtype name
1330  *
1331  * Break if the type name was created.
1332  *
1333  * @b .bp
1334  *
1335  * Show all Firm internal breakpoints.
1336  *
1337  * @b .enable nr
1338  *
1339  * Enables breakpoint nr.
1340  *
1341  * @b .disable nr
1342  *
1343  * Disables breakpoint nr.
1344  *
1345  * @b .showent nr
1346  *
1347  * Show the content of entity nr.
1348  *
1349  * @b .showent name
1350  *
1351  * Show the content of entity name.
1352  *
1353  * @b .showtype nr
1354  *
1355  * Show the content of type nr.
1356  *
1357  * @b .showtype name
1358  *
1359  * Show the content of type name.
1360  *
1361  * @b .setmask name msk
1362  *
1363  * Sets the debug module name to mask msk.
1364  *
1365  * @b .setlvl name lvl
1366  *
1367  * Sets the debug module name to level lvl.
1368  *
1369  * @b .setoutfile name file
1370  *
1371  * Redirects debug output of module name to file.
1372  *
1373  * @b .irgname name
1374  *
1375  * Prints address and graph number of a method given by its name.
1376  *
1377  * @b .irgldname name
1378  *
1379  * Prints address and graph number of a method given by its linker name.
1380  *
1381  * @b .help
1382  *
1383  * List all commands.
1384  *
1385  *
1386  * The Firm debugger extension can be accessed using the function firm_debug().
1387  * The following example shows how to set a creation breakpoint in GDB when
1388  * node 2101 is created.
1389  *
1390  * -# set FIRMDBG=".init"
1391  * -# start gdb with your compiler
1392  * -# after gdb breaks, issue
1393  *
1394  * call firm_debug(".create 2101")
1395  *
1396  * On the console the following text should be issued:
1397  *
1398  * Firm BP 1: creation of Node 2101
1399  *
1400  *
1401  * @section gdb_macro GDB macro
1402  *
1403  * Add the following to your .gdbinit file:
1404  * @code
1405  #
1406  # define firm "cmd"  Firm debugger extension
1407  #
1408  define firm
1409  call firm_debug($arg0)
1410  end
1411  * @endcode
1412  *
1413  * Then, all Firm debugger extension commands can be accessed in the gdb
1414  * console using the firm prefix, eg.:
1415  *
1416  * firm ".create 2101"
1417  *
1418  * firm ".help"
1419  */