debugger.c 31.5 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
2
/*
 * This file is part of libFirm.
3
 * Copyright (C) 2012 University of Karlsruhe.
Christian Würdig's avatar
Christian Würdig committed
4
5
 */

Matthias Braun's avatar
Matthias Braun committed
6
7
/**
 * @file
Michael Beck's avatar
Michael Beck committed
8
 * @brief     Helper function for integrated debug support
Matthias Braun's avatar
Matthias Braun committed
9
10
 * @author    Michael Beck
 * @date      2005
Michael Beck's avatar
Michael Beck committed
11
12
13
 */
#include "config.h"

14
#ifdef DEBUG_libfirm
Michael Beck's avatar
Michael Beck committed
15
16
17
18
19
20

#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif

21
22
#include "debugger.h"

Michael Beck's avatar
Michael Beck committed
23
24
25
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
Michael Beck's avatar
Michael Beck committed
26
#include <string.h>
Michael Beck's avatar
Michael Beck committed
27
#include <strings.h>
28
#include <time.h>
Michael Beck's avatar
Michael Beck committed
29
30
31

#include <ctype.h>

Michael Beck's avatar
Michael Beck committed
32
#include "set.h"
Michael Beck's avatar
Michael Beck committed
33
#include "ident.h"
Michael Beck's avatar
Michael Beck committed
34
#include "irhooks.h"
Michael Beck's avatar
Michael Beck committed
35
36
#include "irgraph_t.h"
#include "entity_t.h"
Michael Beck's avatar
Michael Beck committed
37
#include "irprintf.h"
38
#include "irdump.h"
Matthias Braun's avatar
Matthias Braun committed
39
#include "iredges_t.h"
Michael Beck's avatar
Michael Beck committed
40
#include "debug.h"
41
#include "error.h"
42
#include "util.h"
Michael Beck's avatar
Michael Beck committed
43
44

#ifdef _WIN32
45
/* Break into the debugger. The Win32 way. */
46
47
void firm_debug_break(void)
{
48
	DebugBreak();
Michael Beck's avatar
Michael Beck committed
49
}
Michael Beck's avatar
Michael Beck committed
50
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64))
51
/* Break into the debugger. The ia32/x86_64 way under GCC. */
52
53
void firm_debug_break(void)
{
54
	__asm__ __volatile__("int3");
Michael Beck's avatar
Michael Beck committed
55
}
Michael Beck's avatar
Michael Beck committed
56
#else
57
/* Break into the debugger. Poor Unix way. */
58
59
void firm_debug_break(void)
{
60
	raise(SIGINT);
Michael Beck's avatar
Michael Beck committed
61
62
63
64
65
}
#endif /* _WIN32 */

/** supported breakpoint kinds */
typedef enum {
66
67
	BP_NR    = 'n',   /**< break on node number. */
	BP_IDENT = 'i'    /**< break on ident. */
Michael Beck's avatar
Michael Beck committed
68
69
} bp_kind;

70
71
72
/**
 * Reasons for node number breakpoints.
 */
73
typedef enum bp_reasons_t {
74
	BP_ON_NEW_THING,   /**< break if node, entity or type with number is created */
75
76
77
78
79
	BP_ON_REPLACE,     /**< break if node with number is replaced */
	BP_ON_LOWER,       /**< break if node with number is lowered */
	BP_ON_REMIRG,      /**< break if an IRG is removed */
	BP_ON_NEW_ENT,     /**< break if a new entity is created */
	BP_MAX_REASON
80
81
} bp_reasons_t;

Michael Beck's avatar
Michael Beck committed
82
/** A breakpoint. */
83
typedef struct breakpoint {
84
85
86
87
	bp_kind      kind;        /**< the kind of this break point */
	unsigned     bpnr;        /**< break point number */
	int          active;      /**< non-zero, if this break point is active */
	bp_reasons_t reason;      /**< reason for the breakpoint */
88
	struct breakpoint *next; /**< link to the next one */
Michael Beck's avatar
Michael Beck committed
89
90
} breakpoint;

91
/** A number breakpoint. */
Michael Beck's avatar
Michael Beck committed
92
typedef struct {
93
94
	breakpoint   bp;       /**< the breakpoint data */
	long         nr;       /**< the node number */
95
} bp_nr_t;
Michael Beck's avatar
Michael Beck committed
96

97
/** Calculate the hash value for a node breakpoint. */
98
#define HASH_NR_BP(key) (((key).nr << 2) ^ (key).bp.reason)
Michael Beck's avatar
Michael Beck committed
99

100
/** An ident breakpoint. */
Michael Beck's avatar
Michael Beck committed
101
typedef struct {
102
103
	breakpoint   bp;       /**< the breakpoint data */
	ident        *id;      /**< the ident */
Michael Beck's avatar
Michael Beck committed
104
105
} bp_ident_t;

106
/** Calculate the hash value for an ident breakpoint. */
107
#define HASH_IDENT_BP(key) (hash_ptr((key).id) ^ (key).bp.reason)
Michael Beck's avatar
Michael Beck committed
108

109
/** The set containing the breakpoints on node numbers. */
110
static set *bp_numbers;
Michael Beck's avatar
Michael Beck committed
111

Michael Beck's avatar
Michael Beck committed
112
113
114
/** The set containing the breakpoints on idents. */
static set *bp_idents;

Michael Beck's avatar
Michael Beck committed
115
116
117
118
119
120
121
122
123
/**< the list of all breakpoints */
static breakpoint *bp_list;

/** number of the current break point */
static unsigned bp_num = 0;

/** set if break on init command was issued. */
static int break_on_init = 0;

Michael Beck's avatar
Michael Beck committed
124
125
126
/** the hook entries for the Firm debugger module. */
static hook_entry_t debugger_hooks[hook_last];

Michael Beck's avatar
Michael Beck committed
127
/** number of active breakpoints to maintain hooks. */
Michael Beck's avatar
Michael Beck committed
128
129
static unsigned num_active_bp[BP_MAX_REASON];

Michael Beck's avatar
Michael Beck committed
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/**
 * The debug message buffer
 */
static char firm_dbg_msg_buf[2048];

/**
 * If set, the debug extension writes all output to the
 * firm_dbg_msg_buf buffer
 */
static int redir_output = 0;

/**
 * Is set to one, if the debug extension is active
 */
static int is_active = 0;

Michael Beck's avatar
Michael Beck committed
146
147
/** hook the hook h with function fkt. */
#define HOOK(h, fkt) \
148
149
150
do {                                      \
	debugger_hooks[h].hook._##h = fkt;    \
	register_hook(h, &debugger_hooks[h]); \
151
} while (0)
Michael Beck's avatar
Michael Beck committed
152
153

/** unhook the hook h */
Christian Würdig's avatar
Christian Würdig committed
154
#define UNHOOK(h) \
155
156
157
do {                                        \
	unregister_hook(h, &debugger_hooks[h]); \
	debugger_hooks[h].hook._##h = NULL;     \
158
} while (0)
Michael Beck's avatar
Michael Beck committed
159
160

/** returns non-zero if a entry hook h is used */
Christian Würdig's avatar
Christian Würdig committed
161
#define IS_HOOKED(h) (debugger_hooks[h].hook._##h != NULL)
Michael Beck's avatar
Michael Beck committed
162

Michael Beck's avatar
Michael Beck committed
163
164
165
166
167
168
169
170
171
172
/* some macros needed to create the info string */
#define _DBG_VERSION(major, minor)  #major "." #minor
#define DBG_VERSION(major, minor)   _DBG_VERSION(major, minor)
#define API_VERSION(major, minor)   "API:" DBG_VERSION(major, minor)

/* the API version: change if needed */
#define FIRM_DBG_MAJOR  1
#define FIRM_DBG_MINOR  0

/** for automatic detection of the debug extension */
173
static const char __attribute__((used)) firm_debug_info_string[] =
174
	API_VERSION(FIRM_DBG_MAJOR, FIRM_DBG_MINOR);
Michael Beck's avatar
Michael Beck committed
175

176
177
int firm_debug_active(void)
{
178
	return is_active;
179
}
Michael Beck's avatar
Michael Beck committed
180
181

/**
182
 * Reset the debug text buffer.
Michael Beck's avatar
Michael Beck committed
183
 */
184
185
static void reset_dbg_buf(void)
{
186
	firm_dbg_msg_buf[0] = '\0';
187
}
Michael Beck's avatar
Michael Beck committed
188

189
190
const char *firm_debug_text(void)
{
191
192
	firm_dbg_msg_buf[sizeof(firm_dbg_msg_buf) - 1] = '\0';
	return firm_dbg_msg_buf;
193
}
Michael Beck's avatar
Michael Beck committed
194
195
196
197
198
199

/**
 * debug output
 */
static void dbg_printf(const char *fmt, ...)
{
200
201
202
203
	if (fmt[0] != '+')
		reset_dbg_buf();
	else
		++fmt;
Michael Beck's avatar
Michael Beck committed
204

205
206
207
208
209
210
211
212
	va_list args;
	va_start(args, fmt);
	if (redir_output) {
		size_t const cur = strlen(firm_dbg_msg_buf);
		ir_vsnprintf(firm_dbg_msg_buf + cur, sizeof(firm_dbg_msg_buf) - cur, fmt, args);
	} else {
		ir_vprintf(fmt, args);
	}
213
	va_end(args);
214
}
Michael Beck's avatar
Michael Beck committed
215

Michael Beck's avatar
Michael Beck committed
216
217
218
219
220
221
222
223
224
/**
 * A new node is created.
 *
 * @param ctx   the hook context
 * @param irg   the IR graph on which the node is created
 * @param node  the new IR node that was created
 */
static void dbg_new_node(void *ctx, ir_graph *irg, ir_node *node)
{
225
	bp_nr_t key, *elem;
Matthias Braun's avatar
Matthias Braun committed
226
227
	(void) ctx;
	(void) irg;
Michael Beck's avatar
Michael Beck committed
228

229
	key.nr        = get_irn_node_nr(node);
230
	key.bp.reason = BP_ON_NEW_THING;
Michael Beck's avatar
Michael Beck committed
231

232
	elem = set_find(bp_nr_t, bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
233
234
235
236
	if (elem && elem->bp.active) {
		dbg_printf("Firm BP %u reached, %+F created\n", elem->bp.bpnr, node);
		firm_debug_break();
	}
237
}
Michael Beck's avatar
Michael Beck committed
238
239
240
241
242
243
244
245
246
247

/**
 * A node is replaced.
 *
 * @param ctx   the hook context
 * @param old   the IR node the is replaced
 * @param nw    the new IR node that will replace old
 */
static void dbg_replace(void *ctx, ir_node *old, ir_node *nw)
{
248
	bp_nr_t key, *elem;
Matthias Braun's avatar
Matthias Braun committed
249
	(void) ctx;
Michael Beck's avatar
Michael Beck committed
250

251
252
	key.nr        = get_irn_node_nr(old);
	key.bp.reason = BP_ON_REPLACE;
Michael Beck's avatar
Michael Beck committed
253

254
	elem = set_find(bp_nr_t, bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
255
256
257
258
	if (elem && elem->bp.active) {
		dbg_printf("Firm BP %u reached, %+F will be replaced by %+F\n", elem->bp.bpnr, old, nw);
		firm_debug_break();
	}
259
}
Michael Beck's avatar
Michael Beck committed
260
261
262
263
264
265
266

/**
 * A new node is lowered.
 *
 * @param ctx   the hook context
 * @param node  the new IR node that will be lowered
 */
Michael Beck's avatar
Michael Beck committed
267
static void dbg_lower(void *ctx, ir_node *node)
Michael Beck's avatar
Michael Beck committed
268
{
269
	bp_nr_t key, *elem;
Matthias Braun's avatar
Matthias Braun committed
270
	(void) ctx;
Michael Beck's avatar
Michael Beck committed
271

272
273
	key.nr        = get_irn_node_nr(node);
	key.bp.reason = BP_ON_LOWER;
Michael Beck's avatar
Michael Beck committed
274

275
	elem = set_find(bp_nr_t, bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
276
277
278
279
	if (elem && elem->bp.active) {
		dbg_printf("Firm BP %u reached, %+F will be lowered\n", elem->bp.bpnr, node);
		firm_debug_break();
	}
280
}
Michael Beck's avatar
Michael Beck committed
281

Michael Beck's avatar
Michael Beck committed
282
283
284
285
286
287
/**
 * A graph will be deleted.
 *
 * @param ctx   the hook context
 * @param irg   the IR graph that will be deleted
 */
Michael Beck's avatar
Michael Beck committed
288
static void dbg_free_graph(void *ctx, ir_graph *irg)
Michael Beck's avatar
Michael Beck committed
289
{
Matthias Braun's avatar
Matthias Braun committed
290
	(void) ctx;
291
292
293
294
295
	{
		bp_nr_t key, *elem;
		key.nr        = get_irg_graph_nr(irg);
		key.bp.reason = BP_ON_REMIRG;

296
		elem = set_find(bp_nr_t, bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
		if (elem && elem->bp.active) {
			ir_printf("Firm BP %u reached, %+F will be deleted\n", elem->bp.bpnr, irg);
			firm_debug_break();
		}
	}
	{
		bp_ident_t key, *elem;
		ir_entity *ent = get_irg_entity(irg);

		if (! ent)
			return;

		key.id        = get_entity_ident(ent);
		key.bp.reason = BP_ON_REMIRG;

312
		elem = set_find(bp_ident_t, bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
313
314
315
316
317
		if (elem && elem->bp.active) {
			dbg_printf("Firm BP %u reached, %+F will be deleted\n", elem->bp.bpnr, ent);
			firm_debug_break();
		}
	}
318
}
Michael Beck's avatar
Michael Beck committed
319

Michael Beck's avatar
Michael Beck committed
320
321
322
323
324
325
/**
 * An entity was created.
 *
 * @param ctx   the hook context
 * @param ent   the newly created entity
 */
326
static void dbg_new_entity(void *ctx, ir_entity *ent)
Michael Beck's avatar
Michael Beck committed
327
{
Matthias Braun's avatar
Matthias Braun committed
328
	(void) ctx;
329
330
331
332
333
334
	{
		bp_ident_t key, *elem;

		key.id        = get_entity_ident(ent);
		key.bp.reason = BP_ON_NEW_ENT;

335
		elem = set_find(bp_ident_t, bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
336
337
338
339
340
341
342
343
344
		if (elem && elem->bp.active) {
			ir_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, ent);
			firm_debug_break();
		}
	}
	{
		bp_nr_t key, *elem;

		key.nr        = get_entity_nr(ent);
345
		key.bp.reason = BP_ON_NEW_THING;
346

347
		elem = set_find(bp_nr_t, bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
348
349
350
351
352
		if (elem && elem->bp.active) {
			dbg_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, ent);
			firm_debug_break();
		}
	}
353
}
Michael Beck's avatar
Michael Beck committed
354

Michael Beck's avatar
Michael Beck committed
355
356
357
358
359
360
/**
 * A type was created.
 *
 * @param ctx   the hook context
 * @param tp    the newly created type
 */
361
static void dbg_new_type(void *ctx, ir_type *tp)
Michael Beck's avatar
Michael Beck committed
362
{
Matthias Braun's avatar
Matthias Braun committed
363
	(void) ctx;
364
365
366
367
	{
		bp_nr_t key, *elem;

		key.nr        = get_type_nr(tp);
368
		key.bp.reason = BP_ON_NEW_THING;
369

370
		elem = set_find(bp_nr_t, bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
371
372
373
374
375
		if (elem && elem->bp.active) {
			ir_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, tp);
			firm_debug_break();
		}
	}
376
}
Michael Beck's avatar
Michael Beck committed
377

Michael Beck's avatar
Michael Beck committed
378
/**
379
 * Return the reason string.
Michael Beck's avatar
Michael Beck committed
380
 */
381
static const char *reason_str(bp_reasons_t reason)
Michael Beck's avatar
Michael Beck committed
382
{
383
	switch (reason) {
384
385
386
387
388
389
	case BP_ON_NEW_THING: return "node, entity or type creation";
	case BP_ON_REPLACE:   return "node replace";
	case BP_ON_LOWER:     return "node lowering";
	case BP_ON_REMIRG:    return "removing IRG";
	case BP_ON_NEW_ENT:   return "entity creation";
	case BP_MAX_REASON:   break;
390
	}
391
	panic("unsupported reason");
392
}
393
394

/**
395
 * Compare two number breakpoints.
396
 */
397
static int cmp_nr_bp(const void *elt, const void *key, size_t size)
398
{
399
400
	const bp_nr_t *e1 = (const bp_nr_t*)elt;
	const bp_nr_t *e2 = (const bp_nr_t*)key;
Matthias Braun's avatar
Matthias Braun committed
401
	(void) size;
402

403
	return (e1->nr - e2->nr) | (e1->bp.reason - e2->bp.reason);
404
}
Michael Beck's avatar
Michael Beck committed
405
406

/**
407
 * Compare two ident breakpoints.
Michael Beck's avatar
Michael Beck committed
408
409
410
 */
static int cmp_ident_bp(const void *elt, const void *key, size_t size)
{
411
412
	const bp_ident_t *e1 = (const bp_ident_t*)elt;
	const bp_ident_t *e2 = (const bp_ident_t*)key;
Matthias Braun's avatar
Matthias Braun committed
413
	(void) size;
Michael Beck's avatar
Michael Beck committed
414

415
	return (e1->id != e2->id) | (e1->bp.reason - e2->bp.reason);
416
}
Michael Beck's avatar
Michael Beck committed
417

Michael Beck's avatar
Michael Beck committed
418
/**
419
 * Update the hooks.
Michael Beck's avatar
Michael Beck committed
420
421
422
 */
static void update_hooks(breakpoint *bp)
{
423
424
#define CASE_ON(a, hook, handler)  case a: if (! IS_HOOKED(hook)) HOOK(hook, handler); break
#define CASE_OFF(a, hook) case a: if (IS_HOOKED(hook)) UNHOOK(hook); break
Michael Beck's avatar
Michael Beck committed
425

426
427
428
429
430
431
432
433
	if (bp->active)
		++num_active_bp[bp->reason];
	else
		--num_active_bp[bp->reason];

	if (num_active_bp[bp->reason] > 0) {
		/* register the hooks on demand */
		switch (bp->reason) {
434
435
436
437
438
439
440
441
442
443
444
445
		CASE_ON(BP_ON_REPLACE, hook_replace,    dbg_replace);
		CASE_ON(BP_ON_LOWER,   hook_lower,      dbg_lower);
		CASE_ON(BP_ON_REMIRG,  hook_free_graph, dbg_free_graph);
		CASE_ON(BP_ON_NEW_ENT, hook_new_entity, dbg_new_entity);
		case BP_ON_NEW_THING:
			if (!IS_HOOKED(hook_new_node))
				HOOK(hook_new_node, dbg_new_node);
			if (!IS_HOOKED(hook_new_type))
				HOOK(hook_new_type, dbg_new_type);
			if (!IS_HOOKED(hook_new_entity))
				HOOK(hook_new_entity, dbg_new_entity);
			break;
446
		default:
447
			break;
448
449
450
451
452
		}
	}
	else {
		/* unregister the hook on demand */
		switch (bp->reason) {
453
454
455
456
457
458
459
460
461
462
463
464
		CASE_OFF(BP_ON_REPLACE,  hook_replace);
		CASE_OFF(BP_ON_LOWER,    hook_lower);
		CASE_OFF(BP_ON_REMIRG,   hook_free_graph);
		CASE_OFF(BP_ON_NEW_ENT,  hook_new_entity);
		case BP_ON_NEW_THING:
			if (IS_HOOKED(hook_new_node))
				UNHOOK(hook_new_node);
			if (IS_HOOKED(hook_new_type))
				UNHOOK(hook_new_type);
			if (IS_HOOKED(hook_new_entity))
				UNHOOK(hook_new_entity);
			break;
465
		default:
466
			break;
467
468
		}
	}
Michael Beck's avatar
Michael Beck committed
469
470
#undef CASE_ON
#undef CASE_OFF
471
}
Michael Beck's avatar
Michael Beck committed
472

Michael Beck's avatar
Michael Beck committed
473
/**
474
 * Break if nr is reached.
Michael Beck's avatar
Michael Beck committed
475
 */
476
static void break_on_nr(long nr, bp_reasons_t reason)
Michael Beck's avatar
Michael Beck committed
477
{
478
	bp_nr_t key, *elem;
Michael Beck's avatar
Michael Beck committed
479

480
481
482
483
484
	key.bp.kind   = BP_NR;
	key.bp.bpnr   = 0;
	key.bp.active = 1;
	key.bp.reason = reason;
	key.nr        = nr;
Michael Beck's avatar
Michael Beck committed
485

486
	elem = set_insert(bp_nr_t, bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
Michael Beck's avatar
Michael Beck committed
487

488
489
490
491
492
	if (elem->bp.bpnr == 0) {
		/* new break point */
		elem->bp.bpnr = ++bp_num;
		elem->bp.next = bp_list;
		bp_list = &elem->bp;
Michael Beck's avatar
Michael Beck committed
493

494
		dbg_printf("Firm BP %u: %s of Nr %ld\n", elem->bp.bpnr, reason_str(reason), nr);
Michael Beck's avatar
Michael Beck committed
495

496
497
		update_hooks(&elem->bp);
	}
498
}
Michael Beck's avatar
Michael Beck committed
499

Michael Beck's avatar
Michael Beck committed
500
501
502
/**
 * Break if ident name is reached.
 */
503
504
static void break_on_ident(const char *name, bp_reasons_t reason)
{
505
	bp_ident_t key, *elem;
Michael Beck's avatar
Michael Beck committed
506

507
508
509
510
511
	key.bp.kind   = BP_IDENT;
	key.bp.bpnr   = 0;
	key.bp.active = 1;
	key.bp.reason = reason;
	key.id        = new_id_from_str(name);
Michael Beck's avatar
Michael Beck committed
512

513
	elem = set_insert(bp_ident_t, bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
Michael Beck's avatar
Michael Beck committed
514

515
516
517
518
519
	if (elem->bp.bpnr == 0) {
		/* new break point */
		elem->bp.bpnr = ++bp_num;
		elem->bp.next = bp_list;
		bp_list = &elem->bp;
Michael Beck's avatar
Michael Beck committed
520

521
		dbg_printf("Firm BP %u: %s of ident \"%s\"\n", elem->bp.bpnr, reason_str(reason), name);
Michael Beck's avatar
Michael Beck committed
522

523
524
		update_hooks(&elem->bp);
	}
525
}
Michael Beck's avatar
Michael Beck committed
526

Michael Beck's avatar
Michael Beck committed
527
528
529
530
531
/**
 * Sets/resets the active flag of breakpoint bp.
 */
static void bp_activate(unsigned bp, int active)
{
532
533
534
535
536
537
538
539
540
541
542
543
544
545
	breakpoint *p;

	for (p = bp_list; p; p = p->next) {
		if (p->bpnr == bp) {
			if (p->active != active) {
				p->active = active;
				update_hooks(p);
			}

			dbg_printf("Firm BP %u is now %s\n", bp, active ? "enabled" : "disabled");
			return;
		}
	}
	dbg_printf("Error: Firm BP %u not exists.\n", bp);
546
}
Michael Beck's avatar
Michael Beck committed
547
548
549
550
551


/**
 * Show a list of supported commands
 */
552
553
static void show_commands(void)
{
554
	dbg_printf("Internal Firm debugger extension commands:\n"
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
		"init                  break after initialization\n"
		"create nr             break if node nr was created\n"
		"replace nr            break if node nr is replaced by another node\n"
		"lower nr              break before node nr is lowered\n"
		"remirg nr|name        break if the irg of nr or entity name is deleted\n"
		"newent nr|name        break if the entity nr or name was created\n"
		"newtype nr|name       break if the type nr or name was created\n"
		"bp                    show all breakpoints\n"
		"enable nr             enable breakpoint nr\n"
		"disable nr            disable breakpoint nr\n"
		"showtype nr|name      show content of the type nr or name\n"
		"showent nr|name       show content of the entity nr or name\n"
		"setmask name msk      sets the debug module name to mask msk\n"
		"setlvl  name lvl      sets the debug module name to level lvl\n"
		"setoutfile name file  redirects debug output of module name to file\n"
		"irgname name          prints address and graph number of a method given by its name\n"
		"irgldname ldname      prints address and graph number of a method given by its ldname\n"
572
		"initialnodenr n|rand  set initial node number to n or random number\n"
573
		"help                  list all commands\n"
574
		);
575
}
Michael Beck's avatar
Michael Beck committed
576
577
578
579

/**
 * Shows all Firm breakpoints.
 */
580
581
static void show_bp(void)
{
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
	breakpoint *p;
	bp_nr_t  *node_p;
	bp_ident_t *ident_p;
	int have_one = 0;

	dbg_printf("Firm Breakpoints:");
	for (p = bp_list; p; p = p->next) {
		have_one = 1;
		dbg_printf("+\n  BP %u: ", p->bpnr);

		switch (p->kind) {
		case BP_NR:
			node_p = (bp_nr_t *)p;
			dbg_printf("%s of Nr %ld ", reason_str(p->reason), node_p->nr);
			break;

		case BP_IDENT:
			ident_p = (bp_ident_t *)p;
			dbg_printf("+%s of ident \"%s\" ", reason_str(p->reason), get_id_str(ident_p->id));
			break;
		}

		dbg_printf(p->active ? "+enabled" : "+disabled");
	}
	dbg_printf(have_one ? "+\n" : "+ NONE\n");
607
}
Michael Beck's avatar
Michael Beck committed
608

609
610
611
612
/**
 * firm_dbg_register() expects that the name is stored persistent.
 * So we need this little helper function
 */
613
614
static firm_dbg_module_t *dbg_register(const char *name)
{
615
	ident *id = new_id_from_str(name);
616

617
	return firm_dbg_register(get_id_str(id));
618
}
619

Michael Beck's avatar
Michael Beck committed
620
621
622
623
624
/**
 * Sets the debug mask of module name to lvl
 */
static void set_dbg_level(const char *name, unsigned lvl)
{
625
	firm_dbg_module_t *module = dbg_register(name);
Michael Beck's avatar
Michael Beck committed
626

627
628
	if (firm_dbg_get_mask(module) != lvl) {
		firm_dbg_set_mask(module, lvl);
Michael Beck's avatar
Michael Beck committed
629

630
631
		dbg_printf("Setting debug mask of module %s to %u\n", name, lvl);
	}
632
}
Michael Beck's avatar
Michael Beck committed
633

634
635
636
637
638
/**
 * Redirects the debug output of module name to fname
 */
static void set_dbg_outfile(const char *name, const char *fname)
{
639
640
	firm_dbg_module_t *module = dbg_register(name);
	FILE *f = fopen(fname, "w");
641

642
643
644
645
	if (! f) {
		perror(fname);
		return;
	}
646

647
648
	firm_dbg_set_file(module, f);
	dbg_printf("Redirecting debug output of module %s to file %s\n", name, fname);
649
}
650
651
652
653

/**
 * Show info about a firm thing.
 */
654
655
static void show_firm_object(void *firm_thing)
{
656
657
658
659
660
661
662
663
664
665
666
	FILE *f = stdout;

	if (firm_thing == NULL) {
		fprintf(f, "<NULL>\n");
		return;
	}
	switch (get_kind(firm_thing)) {
	case k_BAD:
		fprintf(f, "BAD: (%p)\n", firm_thing);
		break;
	case k_entity:
667
		dump_entity_to_file(f, (ir_entity*)firm_thing);
668
669
		break;
	case k_type:
670
		dump_type_to_file(f, (ir_type*)firm_thing);
671
672
673
674
675
676
677
678
679
680
681
682
683
		break;
	case k_ir_graph:
	case k_ir_node:
	case k_ir_mode:
	case k_ir_op:
	case k_tarval:
	case k_ir_loop:
	case k_ir_prog:
		fprintf(f, "NIY\n");
		break;
	default:
		fprintf(f, "Cannot identify thing at (%p).\n", firm_thing);
	}
684
}
685
686
687
688

/**
 * Find a firm type by its number.
 */
689
690
static ir_type *find_type_nr(long nr)
{
691
692
693
694
695
696
697
698
699
700
701
702
	int i, n = get_irp_n_types();
	ir_type *tp;

	for (i = 0; i < n; ++i) {
		tp = get_irp_type(i);
		if (get_type_nr(tp) == nr)
			return tp;
	}
	tp = get_glob_type();
	if (get_type_nr(tp) == nr)
		return tp;
	return NULL;
703
}
704
705
706
707

/**
 * Find a firm type by its name.
 */
708
709
static ir_type *find_type_name(const char *name)
{
710
711
712
713
714
	int i, n = get_irp_n_types();
	ir_type *tp;

	for (i = 0; i < n; ++i) {
		tp = get_irp_type(i);
715
716
717
718
		if (!is_compound_type(tp))
			continue;

		if (strcmp(get_compound_name(tp), name) == 0)
719
720
721
			return tp;
	}
	tp = get_glob_type();
722
	if (strcmp(get_compound_name(tp), name) == 0)
723
724
		return tp;
	return NULL;
725
}
726
727
728

/** The environment for the entity search functions. */
typedef struct find_env {
729
730
731
732
733
	union {
		long        nr;   /**< the number that is searched for */
		const char *name; /**< the name that is searched for */
	} u;
	ir_entity *res;     /**< the result */
734
735
736
737
738
} find_env_t;

/**
 * Type-walker: Find an entity with given number.
 */
739
740
static void check_ent_nr(type_or_ent tore, void *ctx)
{
741
	find_env_t *env = (find_env_t*)ctx;
742

743
744
745
	if (is_entity(tore.ent)) {
		if (get_entity_nr(tore.ent) == env->u.nr) {
			env->res = tore.ent;
746
		}
747
	}
748
}
749
750
751
752

/**
 * Type-walker: Find an entity with given name.
 */
753
754
static void check_ent_name(type_or_ent tore, void *ctx)
{
755
	find_env_t *env = (find_env_t*)ctx;
756

757
758
759
	if (is_entity(tore.ent))
		if (strcmp(get_entity_name(tore.ent), env->u.name) == 0) {
			env->res = tore.ent;
760
		}
761
}
762
763
764
765

/**
 * Find a firm entity by its number.
 */
766
767
static ir_entity *find_entity_nr(long nr)
{
768
	find_env_t env;
769

770
771
772
773
	env.u.nr = nr;
	env.res  = NULL;
	type_walk(check_ent_nr, NULL, &env);
	return env.res;
774
}
775
776
777
778

/**
 * Find a firm entity by its name.
 */
779
780
static ir_entity *find_entity_name(const char *name)
{
781
	find_env_t env;
782

783
784
785
786
	env.u.name = name;
	env.res    = NULL;
	type_walk(check_ent_name, NULL, &env);
	return env.res;
787
}
788

789
790
791
/**
 * Search methods for a name.
 */
792
793
static void show_by_name(type_or_ent tore, void *env)
{
794
795
	ident *id = (ident *)env;

796
797
	if (is_entity(tore.ent)) {
		ir_entity *ent = tore.ent;
798
799
800
801
802
803
804

		if (is_method_entity(ent)) {
			if (get_entity_ident(ent) == id) {
				ir_type *owner = get_entity_owner(ent);
				ir_graph *irg = get_entity_irg(ent);

				if (owner != get_glob_type()) {
805
					printf("%s::%s", get_compound_name(owner), get_id_str(id));
806
807
808
809
				} else {
					printf("%s", get_id_str(id));
				}
				if (irg)
Matthias Braun's avatar
Matthias Braun committed
810
					printf("[%ld] (%p)\n", get_irg_graph_nr(irg), (void*)irg);
811
812
813
814
815
				else
					printf(" NULL\n");
			}
		}
	}
816
}
Matthias Braun's avatar
Matthias Braun committed
817

818
819
820
/**
 * Search methods for a ldname.
 */
821
822
static void show_by_ldname(type_or_ent tore, void *env)
{
823
824
	ident *id = (ident *)env;

825
826
	if (is_entity(tore.ent)) {
		ir_entity *ent = tore.ent;
827
828
829
830
831
832
833

		if (is_method_entity(ent)) {
			if (get_entity_ld_ident(ent) == id) {
				ir_type *owner = get_entity_owner(ent);
				ir_graph *irg = get_entity_irg(ent);

				if (owner != get_glob_type()) {
834
					printf("%s::%s", get_compound_name(owner), get_id_str(id));
835
836
837
838
				} else {
					printf("%s", get_id_str(id));
				}
				if (irg)
Matthias Braun's avatar
Matthias Braun committed
839
					printf("[%ld] (%p)\n", get_irg_graph_nr(irg), (void*)irg);
840
841
842
843
844
				else
					printf(" NULL\n");
			}
		}
	}
845
}
846
847
848
849

/**
 * prints the address and graph number of all irgs with given name
 */
850
851
static void irg_name(const char *name)
{
852
	ident *id = new_id_from_str(name);
853

854
	type_walk(show_by_name, NULL, (void *)id);
855
}
856
857
858
859

/**
 * prints the address and graph number of all irgs with given ld_name
 */
860
861
static void irg_ld_name(const char *name)
{
862
	ident *id = new_id_from_str(name);
863

864
	type_walk(show_by_ldname, NULL, (void *)id);
865
}
Matthias Braun's avatar
Matthias Braun committed
866

867
enum tokens {
868
869
870
871
872
873
874
875
876
877
	first_token = 256,
	tok_bp = first_token,
	tok_create,
	tok_disable,
	tok_dumpfilter,
	tok_enable,
	tok_help,
	tok_init,
	tok_irgldname,
	tok_irgname,
878
879
	tok_lower,
	tok_newent,
880
881
	tok_remirg,
	tok_replace,
882
	tok_setlvl,
883
	tok_setmask,
884
	tok_setoutfile,
885
886
	tok_showent,
	tok_showtype,
887
	tok_initialnodenr,
888
889
890
891
892
893
894
	tok_identifier,
	tok_number,
	tok_eof,
	tok_error
};

static const char *reserved[] = {
895
	"bp",
896
	"create",
897
898
899
	"disable",
	"dumpfilter",
	"enable",
Matthias Braun's avatar
Matthias Braun committed
900
	"help",
901
902
903
	"init",
	"irgldname",
	"irgname",
904
905
	"lower",
	"newent",
906
907
	"remirg",
	"replace",
908
	"setlvl",
909
	"setmask",
910
	"setoutfile",
911
912
	"showent",
	"showtype",
913
	"initialnodenr",
914
915
916
917
918
919
920
921
922
923
};

/**
 * The Lexer data.
 */
static struct lexer {
	int has_token;        /**< set if a token is cached. */
	unsigned cur_token;   /**< current token. */
	unsigned number;      /**< current token attribute. */
	const char *s;        /**< current token attribute. */
924
	size_t len;           /**< current token attribute. */
925
926
927
928
929
930
931
932
933

	const char *curr_pos;
	const char *end_pos;
	const char *tok_start;
} lexer;

/**
 * Initialize the lexer.
 */
934
935
static void init_lexer(const char *input)
{
936
937
938
	lexer.has_token = 0;
	lexer.curr_pos  = input;
	lexer.end_pos   = input + strlen(input);
939
}
940
941
942
943
944


/**
 * Get the next char from the input.
 */
945
946
static char next_char(void)
{
947
948
949
	if (lexer.curr_pos >= lexer.end_pos)
		return '\0';
	return *lexer.curr_pos++;
950
}
951

952
#define unput()    if (lexer.curr_pos < lexer.end_pos) --lexer.curr_pos
953
954
955
956

/**
 * The lexer.
 */
957
958
static unsigned get_token(void)
{
959
	char c;
960
	size_t i;
961
962
963
964

	/* skip white space */
	do {
		c = next_char();
965
	} while (c != '\0' && isspace((unsigned char)c));
966
967

	lexer.tok_start = lexer.curr_pos - 1;
968
	if (c == '.' || isalpha((unsigned char)c)) {
969
		/* command begins here */
970
971
		int         len = 0;
		const char* tok_start;
972
973
974
975

		do {
			c = next_char();
			++len;
976
		} while (isgraph((unsigned char)c));
977
978
		unput();

979
980
981
982
983
		tok_start = lexer.tok_start;
		if (*tok_start == '.') {
			++tok_start;
			--len;
		}
984
		for (i = ARRAY_SIZE(reserved); i-- != 0;) {
985
			if (strncasecmp(tok_start, reserved[i], len) == 0 && reserved[i][len] == '\0')
986
				return first_token + i;
987
988
		}

989
990
		/* identifier */
		lexer.s   = lexer.tok_start;
991
992
		lexer.len = lexer.curr_pos - lexer.s;
		return tok_identifier;
993
	} else if (isdigit((unsigned char)c) || c == '-') {
994
		unsigned number = 0;
995
996
997
998
999
1000
1001
		unsigned sign   = 0;

		/* we support negative numbers as well, so one can easily set all bits with -1 */
		if (c == '-') {
			sign = 1;
			c    = next_char();
		}
1002
1003
1004
1005
1006
1007
1008
1009

		if (c == '0') {
			c = next_char();

			if (c == 'x' || c == 'X') {
				for (;;) {
					c = next_char();

1010
					if (! isxdigit((unsigned char)c))
1011
						break;
1012
					if (isdigit((unsigned char)c))
1013
1014
						number = (number << 4) | (c - '0');
					else
1015
						number = (number << 4) | (toupper((unsigned char)c) - 'A' + 10);
1016
1017
1018
1019
1020
1021
1022
				}
				unput();
				lexer.number = number;
				return tok_number;
			}
		}
		for (;;) {
1023
			if (! isdigit((unsigned char)c))
1024
				break;
Michael Beck's avatar
Michael Beck committed
1025
			number = number * 10 + (c -