Put a space after if/for/switch/while.
[libfirm] / win32 / firmEvaluator / firm.c
1 /*
2  * Firm - Evaluator
3  *
4  * (C) 2005 Michael Beck    beck@ipd.info.uni-karlsruhe.de
5  */
6 #define WIN32_LEAN_AND_MEAN
7 #include <windows.h>
8 #include <tchar.h>
9 #include <malloc.h>
10 #include <stdarg.h>
11
12 #include "config.h"
13
14 /* ugly, but I must include array.h WITHOUT NDEBUG */
15 #ifdef NDEBUG
16 #undef NDEBUG
17 #include "array_t.h"
18 #define NDEBUG
19 #else
20 #include "array.h"
21 #endif
22
23 #include "entity_t.h"
24 #include "irgraph_t.h"
25 #include "irnode_t.h"
26 #include "irmode_t.h"
27 #include "tv_t.h"
28 #include "irloop_t.h"
29 #include "irextbb_t.h"
30 #include "irprog_t.h"
31 #include "compound_path_t.h"
32 #include "tpop_t.h"
33 #include "strcalc.h"
34 #include "fltcalc.h"
35
36 #include "set.h"
37 #include "pset.h"
38 #include "pdeq.h"
39 #include "bitset.h"
40
41 #include "firmEvaluator.h"
42
43 /** get the address of a pointer */
44 #define ADD_ADR(p, off)  ((void *)((char *)(p) + (off)))
45
46 /** debug output */
47 static void debug(char *fmt, ...)
48 {
49   va_list ap;
50   char buf[1024];
51
52   va_start(ap, fmt);
53   vsprintf(buf, fmt, ap);
54
55   OutputDebugString(buf);
56   va_end(ap);
57 }  /* debug */
58
59 /**
60  * return the size of a firm object
61  */
62 int get_firm_object_size(firm_kind kind)
63 {
64   switch (kind) {
65   case k_entity:     /* an entity */
66     return sizeof(ir_entity);
67   case k_type:       /* a type */
68     return sizeof(ir_type);
69   case k_ir_graph:   /* an ir graph */
70     return sizeof(ir_graph);
71   case k_ir_node:    /* an ir node */
72     return sizeof(ir_node);
73   case k_ir_mode:    /* an ir mode */
74     return sizeof(ir_mode);
75   case k_ir_op:      /* an ir opcode */
76     return sizeof(ir_op);
77   case k_tarval:     /* a tarval */
78     return sizeof(tarval);
79   case k_ir_loop:    /* a loop */
80     return sizeof(ir_loop);
81   case k_ir_compound_graph_path: /* a compound graph path, see entity.h */
82     return sizeof(compound_graph_path);
83   case k_ir_extblk:  /* an extended block */
84     return sizeof(ir_extblk);
85   case k_ir_prog:    /* a program representation (irp) */
86     return sizeof(ir_prog);
87   default:
88     return 0;
89   }
90 }  /* get_firm_object_size */
91
92 /**
93  * returns the string length of a string in debuggee space
94  *
95  * @return string length or negative value on error
96  */
97 static int strlen_debuggee(DEBUGHELPER *pHelper, const void *address, size_t max)
98 {
99   size_t i;
100   char v;
101   const char *p = address;
102
103   for (i = 0; i < max; ++i) {
104     if (copy_from_debuggee(p + i, pHelper, &v, sizeof(v)) != S_OK)
105       return -1;
106
107     if (! v)
108       return i;
109   }
110   return i;
111 }  /* strlen_debuggee */
112
113 /**
114  * Format an ident
115  */
116 HRESULT format_ident(DEBUGHELPER *pHelper, const void *address, char *pResult, size_t max)
117 {
118   set_entry *data = NULL;
119   set_entry id;
120   size_t len, slen;
121
122   if (copy_from_debuggee(address, pHelper, &id, sizeof(id)) != S_OK)
123     return E_FAIL;
124
125   /* safety check */
126   if (id.size < 1 || id.size > 256)
127     return E_FAIL;
128
129   slen = id.size + 1;
130   len = offsetof(set_entry, dptr) + slen;
131
132   data = alloca(len);
133
134   if (copy_from_debuggee(address, pHelper, data, len) != S_OK)
135     return E_FAIL;
136
137   _tcsncpy(pResult, (const char *)data->dptr, max);
138   return S_OK;
139 }  /* format_ident */
140
141 /**
142  * Format a tp_op
143  */
144 static HRESULT format_tp_op(DEBUGHELPER *pHelper, const void *addr, char *pResult, size_t max)
145 {
146   tp_op op;
147
148 #define X(a)     case tpo_##a: _tcsncpy(pResult, #a, max); return S_OK
149 #define Y(a, b)  case tpo_##a: _tcsncpy(pResult, b, max); return S_OK
150
151   if (copy_from_debuggee(addr, pHelper, &op, sizeof(op)) != S_OK)
152     return E_FAIL;
153
154   switch (op.code) {
155   X(uninitialized);
156   X(class);
157   X(struct);
158   X(method);
159   X(union);
160   X(array);
161   Y(enumeration, "enum");
162   Y(pointer, "ptr");
163   Y(primitive, "prim");
164   X(none);
165   X(unknown);
166   default:
167     return E_FAIL;
168   }
169 #undef X
170 #undef Y
171 }  /* format_tp_op */
172
173 /**
174  * Checks whether a type is the global type
175  *
176  * @param type  the address of the type in debuggee's space
177  */
178 static HRESULT is_global_type(DEBUGHELPER *pHelper, const void *type, int *flag)
179 {
180   ir_type tp;
181
182   *flag = 0;
183   if (copy_from_debuggee(type, pHelper, &tp, sizeof(tp)) != S_OK)
184     return E_FAIL;
185
186   *flag = tp.flags & tf_global_type;
187   return S_OK;
188 }  /* is_global_type */
189
190 /**
191  * format an entity
192  */
193 static HRESULT format_entity(DEBUGHELPER *pHelper, int nBase, const void *addr, char *pResult, size_t max, int top)
194 {
195   ir_entity ent;
196   ir_type owner;
197   char name[256];
198   int is_global;
199
200   if (copy_from_debuggee(addr, pHelper, &ent, sizeof(ent)) != S_OK) {
201     return E_FAIL;
202   }
203   if (is_global_type(pHelper, ent.owner, &is_global) != S_OK)
204     return E_FAIL;
205
206   *pResult = '\0';
207   if (top)
208     _tcsncpy(pResult, "ENT: ", max);
209
210   if (! is_global) {
211     if (copy_from_debuggee(ent.owner, pHelper, &owner, sizeof(owner)) != S_OK)
212       return E_FAIL;
213     if (format_ident(pHelper, (void *)owner.name, name, sizeof(name)) != S_OK)
214       return E_FAIL;
215     _tcsncat(pResult, name, max);
216     _tcsncat(pResult, "::", max);
217   }
218
219   if (format_ident(pHelper, (void *)ent.name, name, sizeof(name)) != S_OK)
220     return E_FAIL;
221   _tcsncat(pResult, name, max);
222
223   switch (nBase) {
224   case 16:
225     _snprintf(name, sizeof(name), " [0x%lx]", ent.nr);
226     break;
227   case 8:
228     _snprintf(name, sizeof(name), " [0%lo]", ent.nr);
229     break;
230   default:
231     _snprintf(name, sizeof(name), " [%ld]", ent.nr);
232   }
233   _tcsncat(pResult, name, max);
234
235   return S_OK;
236 }  /* format_entity */
237
238 /**
239  * format a type
240  */
241 static HRESULT format_type(DEBUGHELPER *pHelper, int nBase, const void *addr, char *pResult, size_t max, int top)
242 {
243   ir_type tp;
244   char name[256];
245
246   if (copy_from_debuggee(addr, pHelper, &tp, sizeof(tp)) != S_OK)
247     return E_FAIL;
248
249   pResult[0] = '\0';
250   if (top) {
251     if (format_tp_op(pHelper, tp.type_op, pResult, max) != S_OK)
252       return E_FAIL;
253
254     _tcsncat(pResult, " ", max);
255   }
256
257   if (format_ident(pHelper, tp.name, name, sizeof(name)) != S_OK)
258     return E_FAIL;
259
260   _tcsncat(pResult, name, max);
261   switch (nBase) {
262   case 16:
263     _snprintf(name, sizeof(name), " [0x%lx]", tp.nr);
264     break;
265   case 8:
266     _snprintf(name, sizeof(name), " [0%lo]", tp.nr);
267     break;
268   default:
269     _snprintf(name, sizeof(name), " [%ld]", tp.nr);
270   }
271   _tcsncat(pResult, name, max);
272
273   return S_OK;
274 }  /* format_type */
275
276 /**
277  * format an irg
278  */
279 static HRESULT format_irg(DEBUGHELPER *pHelper, int nBase, const void *addr, char *pResult, size_t max, int top)
280 {
281   ir_graph irg;
282   char name[256];
283
284   if (copy_from_debuggee(addr, pHelper, &irg, sizeof(irg)) != S_OK)
285     return E_FAIL;
286
287   *pResult = '\0';
288   if (top)
289     _tcsncpy(pResult, "IRG: ", max);
290
291   if (irg.ent) {
292     ir_entity ent;
293     ir_type owner;
294     int is_global;
295
296     if (copy_from_debuggee(irg.ent, pHelper, &ent, sizeof(ent)) != S_OK)
297       return E_FAIL;
298     if (is_global_type(pHelper, ent.owner, &is_global) != S_OK)
299       return E_FAIL;
300     if (! is_global) {
301       if (copy_from_debuggee(ent.owner, pHelper, &owner, sizeof(owner)) != S_OK)
302         return E_FAIL;
303       if (format_ident(pHelper, (void *)owner.name, name, sizeof(name)) != S_OK)
304         return E_FAIL;
305       _tcsncat(pResult, name, max);
306       _tcsncat(pResult, "::", max);
307     }
308     if (format_ident(pHelper, ent.name, name, sizeof(name)) != S_OK)
309       return E_FAIL;
310     _tcsncat(pResult, name, max);
311   }
312   else
313     _tcsncat(pResult, "NULL", max);
314
315   switch (nBase) {
316   case 16:
317     _snprintf(name, sizeof(name), " [0x%lx, 0x%u nodes]", irg.graph_nr, irg.last_node_idx);
318     break;
319   case 8:
320     _snprintf(name, sizeof(name), " [0%lo, 0%o nodes]", irg.graph_nr, irg.last_node_idx);
321     break;
322   default:
323     _snprintf(name, sizeof(name), " [%ld, %u nodes]", irg.graph_nr, irg.last_node_idx);
324   }
325   _tcsncat(pResult, name, max);
326   return S_OK;
327 }  /* format_irg */
328
329 /**
330  * format an ir_op
331  */
332 HRESULT format_op(DEBUGHELPER *pHelper, const void *addr, char *pResult, size_t max)
333 {
334   ir_op op;
335
336   if (copy_from_debuggee(addr, pHelper, &op, sizeof(op)) != S_OK)
337     return E_FAIL;
338   if (format_ident(pHelper, op.name, pResult, max) != S_OK)
339     return E_FAIL;
340   return S_OK;
341 }  /* format_op */
342
343 /**
344  * format an ir_mode
345  */
346 static HRESULT format_mode(DEBUGHELPER *pHelper, const void *addr, char *pResult, size_t max)
347 {
348   ir_mode mode;
349
350   if (copy_from_debuggee(addr, pHelper, &mode, sizeof(mode)) != S_OK)
351     return E_FAIL;
352   if (format_ident(pHelper, mode.name, pResult, max) != S_OK)
353     return E_FAIL;
354   return S_OK;
355 }  /* format_mode */
356
357 /** get a temporary string */
358 #define get_string(str)                                         \
359 do {                                                            \
360   int len;                                                      \
361   char *s;                                                      \
362   if (str) {                                                    \
363     len = strlen_debuggee(pHelper, str, 256);                   \
364     if (len < 0)                                                \
365       return E_FAIL;                                            \
366     s = alloca(len + 1);                                        \
367     if (copy_from_debuggee(str, pHelper, s, (DWORD)len) != S_OK) \
368       return E_FAIL;                                            \
369     s[len] = '\0';                                              \
370     str = s;                                                    \
371   }                                                             \
372 } while (0)
373
374 /**
375  * format a tarval
376  */
377 static HRESULT format_tarval(DEBUGHELPER *pHelper, int nBase, const void *addr, char *pResult, size_t max)
378 {
379   tarval tv;
380   char *value;
381   ir_mode mode;
382   unsigned len;
383   tarval_mode_info modinfo;
384
385   {
386     static int initialized = 0;
387
388     if (! initialized) {
389       /* from init_tarval_1() */
390       init_strcalc(68);
391       init_fltcalc(0);
392
393       initialized = 1;
394     }
395   }
396
397   if (copy_from_debuggee(addr, pHelper, &tv, sizeof(tv)) != S_OK)
398     return E_FAIL;
399
400   /* ir_mode */
401   if (tv.mode == NULL)
402     return E_FAIL;
403
404   if (copy_from_debuggee(tv.mode, pHelper, &mode, sizeof(mode)) != S_OK)
405     return E_FAIL;
406
407   tv.mode = &mode;
408
409   if (mode_is_int(&mode)) {
410     switch (nBase) {
411     case 16:
412       modinfo.mode_output = TVO_HEX;
413       modinfo.mode_prefix = "0x";
414       modinfo.mode_suffix = "";
415       break;
416     case 8:
417       modinfo.mode_output = TVO_OCTAL;
418       modinfo.mode_prefix = "0";
419       modinfo.mode_suffix = "";
420       break;
421     default:
422       modinfo.mode_output = TVO_DECIMAL;
423       modinfo.mode_prefix = "";
424       modinfo.mode_suffix = "";
425     }
426   }
427   else {
428     if (mode.tv_priv) {
429       if (copy_from_debuggee(mode.tv_priv, pHelper, &modinfo, sizeof(modinfo)) != S_OK)
430         return E_FAIL;
431
432       get_string(modinfo.mode_prefix);
433       get_string(modinfo.mode_suffix);
434     }
435   }
436   mode.tv_priv = &modinfo;
437
438   len = tv.length;
439   if (len) {
440     if (len > 256)
441       return E_FAIL;
442
443     value = alloca(len);
444
445     if (copy_from_debuggee(tv.value, pHelper, value, len) != S_OK)
446       return E_FAIL;
447
448     tv.value = value;
449
450     tarval_snprintf(pResult, max, &tv);
451   }
452   else {
453     /* might be a reserved tarval */
454     int resid = PTR_TO_INT(tv.value);
455
456     switch (resid) {
457     case resid_tarval_bad:
458       _tcsncat(pResult, "BAD", max);
459       break;
460     case resid_tarval_undefined:
461       _tcsncat(pResult, "UNDEF", max);
462       break;
463     case resid_tarval_b_false:
464       _tcsncat(pResult, "FALSE", max);
465       break;
466     case resid_tarval_b_true:
467       _tcsncat(pResult, "TRUE", max);
468       break;
469     default:
470       /* try it */
471       tarval_snprintf(pResult, max, &tv);
472     }
473   }
474   return S_OK;
475 }  /* format_tarval */
476
477 /**
478  * format an ir_node
479  */
480 static HRESULT format_node(DEBUGHELPER *pHelper, int nBase, const void *addr, char *pResult, size_t max, int top)
481 {
482   ir_node n;
483   char name[256];
484   ir_op op;
485
486   if (copy_from_debuggee(addr, pHelper, &n, sizeof(n)) != S_OK)
487     return E_FAIL;
488
489   /* ir_op */
490   if (format_op(pHelper, n.op, pResult, max) != S_OK)
491     return E_FAIL;
492
493   /* ir_mode */
494   if (format_mode(pHelper, n.mode, name, sizeof(name)) != S_OK)
495     return E_FAIL;
496   _tcsncat(pResult, name, max);
497
498   if (copy_from_debuggee(n.op, pHelper, &op, sizeof(op)) != S_OK)
499     return E_FAIL;
500
501   /* show show node attributes */
502   switch (op.code) {
503   case iro_Const:
504     if (format_tarval(pHelper, nBase, n.attr.con.tv, name, sizeof(name)) != S_OK) {
505       _tcsncat(pResult, "<???>", max);
506     }
507     else {
508       _tcsncat(pResult, "<", max);
509       _tcsncat(pResult, name, max);
510       _tcsncat(pResult, ">", max);
511     }
512     break;
513   case iro_SymConst:
514     _tcsncat(pResult, "<", max);
515     switch (n.attr.symc.kind) {
516     case symconst_type_tag:
517       _tcsncat(pResult, "TAG:", max);
518       if (format_type(pHelper, nBase, n.attr.symc.sym.type_p, name, sizeof(name), 0) != S_OK)
519         return E_FAIL;
520       _tcsncat(pResult, name, max);
521       break;
522     case symconst_type_size:
523       _tcsncat(pResult, "SIZE:", max);
524       if (format_type(pHelper, nBase, n.attr.symc.sym.type_p, name, sizeof(name), 0) != S_OK)
525         return E_FAIL;
526       _tcsncat(pResult, name, max);
527       break;
528     case symconst_type_align:
529       _tcsncat(pResult, "ALGN:", max);
530       if (format_type(pHelper, nBase, n.attr.symc.sym.type_p, name, sizeof(name), 0) != S_OK)
531         return E_FAIL;
532       _tcsncat(pResult, name, max);
533       break;
534     case symconst_addr_name:
535       _tcsncat(pResult, "NAME:", max);
536       if (format_ident(pHelper, n.attr.symc.sym.ident_p, name, sizeof(name)) != S_OK)
537         return E_FAIL;
538       _tcsncat(pResult, name, max);
539       break;
540     case symconst_addr_ent:
541       _tcsncat(pResult, "ENT:", max);
542       if (format_entity(pHelper, nBase, n.attr.symc.sym.entity_p, name, sizeof(name), 0) != S_OK)
543         return E_FAIL;
544       _tcsncat(pResult, name, max);
545       break;
546     }
547     _tcsncat(pResult, ">", max);
548     break;
549   case iro_Sel:
550     _tcsncat(pResult, "<", max);
551     if (format_entity(pHelper, nBase, n.attr.sel.entity, name, sizeof(name), 0) != S_OK)
552       return E_FAIL;
553     _tcsncat(pResult, name, max);
554     _tcsncat(pResult, ">", max);
555     break;
556   case iro_Cast:
557     _tcsncat(pResult, "<", max);
558     if (format_type(pHelper, nBase, n.attr.cast.type, name, sizeof(name), 0) != S_OK)
559       return E_FAIL;
560     _tcsncat(pResult, name, max);
561     _tcsncat(pResult, ">", max);
562     break;
563   case iro_Alloc:
564     _tcsncat(pResult, "<", max);
565     if (format_type(pHelper, nBase, n.attr.alloc.type, name, sizeof(name), 0) != S_OK)
566       return E_FAIL;
567     _tcsncat(pResult, name, max);
568     _snprintf(name, sizeof(name), ", %s", n.attr.alloc.where == stack_alloc ? "stack" : "heap");
569     _tcsncat(pResult, name, max);
570     _tcsncat(pResult, ">", max);
571     break;
572   case iro_Free:
573     _tcsncat(pResult, "<", max);
574     if (format_type(pHelper, nBase, n.attr.free.type, name, sizeof(name), 0) != S_OK)
575       return E_FAIL;
576     _tcsncat(pResult, name, max);
577     _snprintf(name, sizeof(name), ", %s", n.attr.free.where == stack_alloc ? "stack" : "heap");
578     _tcsncat(pResult, name, max);
579     _tcsncat(pResult, ">", max);
580     break;
581   case iro_CopyB:
582     _tcsncat(pResult, "<", max);
583     if (format_type(pHelper, nBase, n.attr.copyb.type, name, sizeof(name), 0) != S_OK)
584       return E_FAIL;
585     _tcsncat(pResult, name, max);
586     _tcsncat(pResult, ">", max);
587     break;
588   }
589
590   switch (nBase) {
591   case 16:
592     _snprintf(name, sizeof(name), " [0x%lx:0x%x]", n.node_nr, n.node_idx);
593     break;
594   case 8:
595     _snprintf(name, sizeof(name), " [0%lo:0%o]", n.node_nr, n.node_idx);
596     break;
597   default:
598     _snprintf(name, sizeof(name), " [%ld:%u]", n.node_nr, n.node_idx);
599   }
600   _tcsncat(pResult, name, max);
601
602   return S_OK;
603 }  /* format_node */
604
605 /**
606  * format a loop
607  */
608 static HRESULT format_loop(DEBUGHELPER *pHelper, const void *addr, char *pResult, size_t max)
609 {
610   ir_loop loop;
611
612   if (copy_from_debuggee(addr, pHelper, &loop, sizeof(loop)) != S_OK)
613     return E_FAIL;
614   return E_FAIL;
615 }  /* format_loop */
616
617 /**
618  * Get an array descriptor
619  */
620 static HRESULT get_array_desc(DEBUGHELPER *pHelper, const void *address, ir_arr_descr *desc)
621 {
622   address = ARR_DESCR(address);
623   if (copy_from_debuggee(address, pHelper, desc, sizeof(*desc)) != S_OK)
624     return E_FAIL;
625
626   return S_OK;
627 }  /* get_array_desc */
628
629 /**
630  * format an extended block
631  */
632 static HRESULT format_extblk(DEBUGHELPER *pHelper, int nBase, const void *addr, char *pResult, size_t max)
633 {
634   ir_extblk extbb;
635   ir_arr_descr blocks;
636   ir_node *blks = NULL;
637   char name[256];
638   int len;
639
640   if (copy_from_debuggee(addr, pHelper, &extbb, sizeof(extbb)) != S_OK)
641     return E_FAIL;
642   if (extbb.blks == NULL)
643     return E_FAIL;
644
645   if (get_array_desc(pHelper, extbb.blks, &blocks) != S_OK)
646     return E_FAIL;
647
648   len = ARR_LEN(&blocks.v.elts);
649
650   if (len > 0) {
651     if (copy_from_debuggee(extbb.blks, pHelper, &blks, sizeof(blks)) != S_OK)
652       return E_FAIL;
653   }
654
655   if (blks) {
656     switch (nBase) {
657     case 16:
658       _snprintf(name, sizeof(name), "0x%x 0x%x blocks", blks->node_nr, len);
659       break;
660     case 8:
661       _snprintf(name, sizeof(name), "0%o 0%o blocks", blks->node_nr, len);
662       break;
663     default:
664       _snprintf(name, sizeof(name), "%d %d blocks", blks->node_nr, len);
665     }
666     _tcsncpy(pResult, name, max);
667   }
668   else
669     _tcsncpy(pResult, "<EMPTY>", max);
670   return S_OK;
671 }  /* format_extblk */
672
673
674 /**
675  * format a ir_prog
676  */
677 static HRESULT format_prog(DEBUGHELPER *pHelper, int nBase, const void *addr, char *pResult, size_t max)
678 {
679   ir_prog irp;
680   ir_arr_descr graphs, types;
681   char name[256];
682
683   if (copy_from_debuggee(addr, pHelper, &irp, sizeof(irp)) != S_OK)
684     return E_FAIL;
685   if (irp.graphs) {
686     if (get_array_desc(pHelper, irp.graphs, &graphs) != S_OK)
687       return E_FAIL;
688
689     irp.graphs = (ir_graph**)&graphs.v.elts;
690   }
691
692   if (irp.types) {
693     if (get_array_desc(pHelper, irp.types, &types) != S_OK)
694       return E_FAIL;
695
696     irp.types = (ir_type**)&types.v.elts;
697   }
698
699   switch (nBase) {
700   case 16:
701     _snprintf(name, sizeof(name), "0x%x graphs 0x%x types", ARR_LEN(irp.graphs), ARR_LEN(irp.types));
702     break;
703   case 8:
704     _snprintf(name, sizeof(name), "0%o graphs 0%o types", ARR_LEN(irp.graphs), ARR_LEN(irp.types));
705     break;
706   default:
707     _snprintf(name, sizeof(name), "%d graphs %d types", ARR_LEN(irp.graphs), ARR_LEN(irp.types));
708   }
709   _tcsncpy(pResult, name, max);
710
711   return S_OK;
712 }  /* format_prog */
713
714 /*
715  * Format an array descriptor
716  */
717 HRESULT format_arr_descr(DEBUGHELPER *pHelper, int nBase, const void *addr, char *pResult, size_t max)
718 {
719   ir_arr_descr desc;
720   char name[256];
721
722   if (copy_from_debuggee(addr, pHelper, &desc, sizeof(desc)) != S_OK)
723     return E_FAIL;
724
725   switch (desc.magic) {
726   case ARR_D_MAGIC:
727     _tcsncpy(pResult, "DynArr ", max); break;
728   case ARR_A_MAGIC:
729     _tcsncpy(pResult, "AutoArr ", max); break;
730   case ARR_F_MAGIC:
731     _tcsncpy(pResult, "FlexArr ", max); break;
732   default:
733     _tcsncpy(pResult, "UNKN ", max);
734   }
735
736   switch (nBase) {
737   case 16:
738     _snprintf(name, sizeof(name), "nelts 0x%x", desc.nelts);
739     break;
740   case 8:
741     _snprintf(name, sizeof(name), "nelts 0%o", desc.nelts);
742     break;
743   default:
744     _snprintf(name, sizeof(name), "nelts %d", desc.nelts);
745   }
746   _tcsncat(pResult, name, max);
747
748   return S_OK;
749 }  /* format_arr_descr */
750
751 /*
752  * format a firm object
753  */
754 HRESULT FormatFirmObject(DEBUGHELPER *pHelper, int nBase, firm_kind kind, const void *addr, char *pResult, size_t max)
755 {
756   switch (kind) {
757   case k_entity:     /* an entity */
758     return format_entity(pHelper, nBase, addr, pResult, max, 1);
759   case k_type:       /* a type */
760     return format_type(pHelper, nBase, addr, pResult, max, 1);
761   case k_ir_graph:   /* an ir graph */
762     return format_irg(pHelper, nBase, addr, pResult, max, 1);
763   case k_ir_node:    /* an ir node */
764     return format_node(pHelper, nBase, addr, pResult, max, 1);
765   case k_ir_mode:    /* an ir mode */
766     return format_mode(pHelper, addr, pResult, max);
767   case k_ir_op:      /* an ir opcode */
768     return format_op(pHelper, addr, pResult, max);
769   case k_tarval:     /* a tarval */
770     return format_tarval(pHelper, nBase, addr, pResult, max);
771   case k_ir_loop:    /* a loop */
772     return format_loop(pHelper, addr, pResult, max);
773   case k_ir_compound_graph_path: /* a compound graph path, see entity.h */
774     return E_FAIL;
775   case k_ir_extblk:  /* an extended block */
776     return format_extblk(pHelper, nBase, addr, pResult, max);
777   case k_ir_prog:    /* a program representation (irp) */
778     return format_prog(pHelper, nBase, addr, pResult, max);
779   default:
780     return E_FAIL;
781   }
782 }  /* FormatFirmObject */
783
784 #define SEGMENT_SIZE_SHIFT      8
785 #define SEGMENT_SIZE            (1 << SEGMENT_SIZE_SHIFT)
786 #define DIRECTORY_SIZE_SHIFT    8
787 #define DIRECTORY_SIZE          (1 << DIRECTORY_SIZE_SHIFT)
788 #define MAX_LOAD_FACTOR         4
789
790 typedef struct pset_element {
791   struct pset_element *chain;   /**< for chaining Elements */
792   pset_entry entry;
793 } pset_Element, *pset_Segment;
794
795 /* not visible from outside */
796 struct pset {
797   unsigned p;              /**< Next bucket to be split */
798   unsigned maxp;           /**< upper bound on p during expansion */
799   unsigned nkey;           /**< current # keys */
800   unsigned nseg;           /**< current # segments */
801   pset_Segment *dir[DIRECTORY_SIZE];
802   int (*cmp)();            /**< function comparing entries */
803   unsigned iter_i, iter_j;
804   pset_Element *iter_tail; /**< non-NULL while iterating over elts */
805   pset_Element *free_list; /**< list of free Elements */
806   struct obstack obst;     /**< obstack for allocation all data */
807 #ifdef STATS
808   int naccess, ncollision, ndups;
809   int max_chain_len;
810 #endif
811 #ifdef DEBUG
812   const char *tag;         /**< an optionally tag for distinguishing sets */
813 #endif
814 };
815
816 typedef struct set_element {
817   struct set_element *chain;    /**< for chaining Elements */
818   set_entry entry;
819 } set_Element, *set_Segment;
820
821 /* not visible from outside */
822 struct set {
823   unsigned p;              /**< Next bucket to be split */
824   unsigned maxp;           /**< upper bound on p during expansion */
825   unsigned nkey;           /**< current # keys */
826   unsigned nseg;           /**< current # segments */
827   set_Segment *dir[DIRECTORY_SIZE];
828   int (*cmp)();            /**< function comparing entries */
829   unsigned iter_i, iter_j;
830   set_Element *iter_tail;  /**< non-NULL while iterating over elts */
831   struct obstack obst;     /**< obstack for allocation all data */
832 #ifdef STATS
833   int naccess, ncollision, ndups;
834   int max_chain_len;
835 #endif
836 #ifdef DEBUG
837   const char *tag;         /**< an optionally tag for distinguishing sets */
838 #endif
839 };
840
841 /**
842  * Find the longest chain of a pset
843  */
844 static HRESULT find_longest_pset_chain(DEBUGHELPER *pHelper, pset *set,
845                                        int *chains, int *lenght, size_t *size) {
846   unsigned i, j;
847   pset_Segment *seg, *curr;
848   pset_Element elem;
849   void *address;
850   int len, nchains = 0, max_len = 0;
851   size_t dyns = 0;
852
853   for (i = 0; i < set->nseg; ++i) {
854     seg = set->dir[i];
855
856     dyns += sizeof(seg[j]) * SEGMENT_SIZE;
857     for (j = 0; j < SEGMENT_SIZE; ++j) {
858       if (copy_from_debuggee(&seg[j], pHelper, &curr, sizeof(curr)) != S_OK)
859         return E_FAIL;
860
861       address = curr;
862       if (address)
863         ++nchains;
864       for (len = 0; address != NULL; address = elem.chain) {
865         if (copy_from_debuggee(address, pHelper, &elem, sizeof(elem)) != S_OK)
866           return E_FAIL;
867         dyns += sizeof(pset_Element);
868         ++len;
869       }
870       if (len > max_len)
871         max_len = len;
872     }
873   }
874
875   *chains = nchains;
876   *lenght = max_len;
877   *size   = dyns;
878   return S_OK;
879 }  /* find_longest_pset_chain */
880
881 /**
882  * Find the longest chain of a set
883  */
884 static HRESULT find_longest_set_chain(DEBUGHELPER *pHelper, set *set,
885                                       int *chains, int *lenght, size_t *size) {
886   unsigned i, j;
887   set_Segment *seg, *curr;
888   set_Element elem;
889   void *address;
890   int len, nchains = 0, max_len = 0;
891   size_t dyns = 0;
892
893   for (i = 0; i < set->nseg; ++i) {
894     seg = set->dir[i];
895
896     dyns += sizeof(seg[j]) * SEGMENT_SIZE;
897     for (j = 0; j < SEGMENT_SIZE; ++j) {
898       if (copy_from_debuggee(&seg[j], pHelper, &curr, sizeof(curr)) != S_OK)
899           return E_FAIL;
900
901       address = curr;
902       if (address)
903         ++nchains;
904       for (len = 0; address != NULL; address = elem.chain) {
905         if (copy_from_debuggee(address, pHelper, &elem, sizeof(elem)) != S_OK)
906           return E_FAIL;
907         dyns += offsetof(set_Element, entry.dptr) + elem.entry.size;
908         ++len;
909       }
910       if (len > max_len)
911         max_len = len;
912     }
913   }
914
915   *chains = nchains;
916   *lenght = max_len;
917   *size   = dyns;
918   return S_OK;
919 }  /* find_longest_set_chain */
920
921 /*
922  * Format a pset
923  */
924 HRESULT format_pset(DEBUGHELPER *pHelper, int nBase, const void *address, char *pResult, size_t max)
925 {
926   pset set;
927   char name[256];
928   int nchains, chain_len;
929   size_t size;
930
931   if (copy_from_debuggee(address, pHelper, &set, sizeof(set)) != S_OK)
932     return E_FAIL;
933
934   if (find_longest_pset_chain(pHelper, &set, &nchains, &chain_len, &size) != S_OK)
935     return E_FAIL;
936
937   switch (nBase) {
938   case 16:
939     _snprintf(name, sizeof(name), "nkey 0x%x nseg 0x%x nchain 0x%x maxlen 0x%x size %u kB", set.nkey, set.nseg, nchains, chain_len, (size + 1023) >> 10);
940     break;
941   case 8:
942     _snprintf(name, sizeof(name), "nkey 0%o nseg 0%o nchain 0%o maxlen 0%o size %u kB", set.nkey, set.nseg, nchains, chain_len, (size + 1023) >> 10);
943     break;
944   default:
945     _snprintf(name, sizeof(name), "nkey %u nseg %d nchain %d maxlen %d size %u kB", set.nkey, set.nseg, nchains, chain_len, (size + 1023) >> 10);
946   }
947   _tcsncpy(pResult, name, max);
948
949   return S_OK;
950 }  /* format_pset */
951
952 /*
953  * Format a set
954  */
955 HRESULT format_set(DEBUGHELPER *pHelper, int nBase, const void *address, char *pResult, size_t max)
956 {
957   set set;
958   char name[256];
959   int nchains, chain_len;
960   size_t size;
961
962   if (copy_from_debuggee(address, pHelper, &set, sizeof(set)) != S_OK)
963     return E_FAIL;
964
965   if (find_longest_set_chain(pHelper, &set, &nchains, &chain_len, &size) != S_OK)
966     return E_FAIL;
967
968   switch (nBase) {
969   case 16:
970     _snprintf(name, sizeof(name), "nkey 0x%x nseg 0x%x nchain 0x%x maxlen 0x%x size %u kB", set.nkey, set.nseg, nchains, chain_len, (size + 1023) >> 10);
971     break;
972   case 8:
973     _snprintf(name, sizeof(name), "nkey 0%o nseg 0%o nchain 0%o maxlen 0%o size %u kB", set.nkey, set.nseg, nchains, chain_len, (size + 1023) >> 10);
974     break;
975   default:
976     _snprintf(name, sizeof(name), "nkey %u nseg %d nchain %d maxlen %d size %u kB", set.nkey, set.nseg, nchains, chain_len, (size + 1023) >> 10);
977   }
978   _tcsncpy(pResult, name, max);
979
980   return S_OK;
981 }  /* format_set */
982
983 struct pdeq {
984   unsigned magic;       /**< debug magic, only available in DEBUG builds */
985   pdeq *l_end, *r_end;  /**< left and right ends of the queue */
986   pdeq *l, *r;          /**< left and right neighbor */
987   int n;                /**< number of elements in the current chunk */
988   int p;                /**< the read/write pointer */
989   const void *data[1];  /**< storage for elements */
990 };
991
992 /** Returns the length of a double ended pointer list. */
993 static int get_pdeq_len(DEBUGHELPER *pHelper, pdeq *dq)
994 {
995   int n;
996   pdeq *q;
997   pdeq pdeq;
998
999   n = 0;
1000   q = dq->l_end;
1001
1002   if (copy_from_debuggee(q, pHelper, &pdeq, sizeof(pdeq)) != S_OK)
1003     return -1;
1004   q = &pdeq;
1005
1006   for (;;) {
1007     n += q->n;
1008     q = q->r;
1009     if (! q)
1010       break;
1011
1012     if (copy_from_debuggee(q, pHelper, &pdeq, sizeof(pdeq)) != S_OK)
1013       return -1;
1014     q = &pdeq;
1015   };
1016
1017   return n;
1018 }  /* get_pdeq_len */
1019
1020 /*
1021  * Format a pdeq
1022  */
1023 HRESULT format_pdeq(DEBUGHELPER *pHelper, int nBase, const void *address, char *pResult, size_t max)
1024 {
1025   pdeq pdeq;
1026   char name[256];
1027   int len;
1028
1029   if (copy_from_debuggee(address, pHelper, &pdeq, sizeof(pdeq)) != S_OK)
1030     return E_FAIL;
1031
1032   len = get_pdeq_len(pHelper, &pdeq);
1033   if (len < 0)
1034     return E_FAIL;
1035
1036   switch (nBase) {
1037   case 16:
1038     _snprintf(name, sizeof(name), "pdeq 0x%x elem", len);
1039     break;
1040   case 8:
1041     _snprintf(name, sizeof(name), "pdeq 0%o elem", len);
1042     break;
1043   default:
1044     _snprintf(name, sizeof(name), "pdeq %d elem", len);
1045   }
1046   _tcsncpy(pResult, name, max);
1047
1048   return S_OK;
1049 }  /* format_pdeq */
1050
1051 /** show the first 2 units */
1052 static HRESULT fill_bits(DEBUGHELPER *pHelper, bitset_t *bs, char *pResult)
1053 {
1054   bitset_pos_t i, units = bs->units;
1055   int l = 0, o = 0, breaked = 0;
1056   unsigned j;
1057
1058   for (i = 0; i < units; ++i) {
1059     bitset_unit_t data;
1060
1061     if (copy_from_debuggee((void *)(BS_DATA(bs)[i]), pHelper, &data, sizeof(data)) != S_OK)
1062       return E_FAIL;
1063
1064     for (j = 0; j < 32; ++j) {
1065       if (data & (1 << j)) {
1066         sprintf(pResult + l, "%d,", i * sizeof(data) * 8 + j);
1067         l += strlen(pResult + l);
1068         ++o;
1069         if (o >= 10) {
1070           breaked = 1;
1071           goto end;
1072         }
1073       }
1074     }
1075   }
1076 end:
1077   if (breaked) {
1078     sprintf(pResult + l, "...");
1079     l += 3;
1080   }
1081   sprintf(pResult + l, "}");
1082   return S_OK;
1083 }  /* fill_bits */
1084
1085 /*
1086  * Format a bitset
1087  */
1088 HRESULT format_bitset(DEBUGHELPER *pHelper, int nBase, const void *address, char *pResult, size_t max)
1089 {
1090   bitset_t bs;
1091   char name[256];
1092   bitset_pos_t l;
1093
1094   if (copy_from_debuggee(address, pHelper, &bs, sizeof(bs)) != S_OK)
1095     return E_FAIL;
1096
1097   switch (nBase) {
1098   case 16:
1099     _snprintf(name, sizeof(name), "bitset{0x%x:", bs.size);
1100     break;
1101   case 8:
1102     _snprintf(name, sizeof(name), "bitset{0%o:", bs.size);
1103     break;
1104   default:
1105     _snprintf(name, sizeof(name), "bitset{%u:", bs.size);
1106   }
1107
1108   l = strlen(name);
1109   if (fill_bits(pHelper, &bs, &name[l]) != S_OK)
1110     return E_FAIL;
1111
1112
1113   _tcsncpy(pResult, name, max);
1114
1115   return S_OK;
1116 }  /* format_bitset */