remove symconst_type_tag
[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_t.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 an ir_mode
240  */
241 static HRESULT format_mode(DEBUGHELPER *pHelper, const void *addr, char *pResult, size_t max)
242 {
243   ir_mode mode;
244
245   if (copy_from_debuggee(addr, pHelper, &mode, sizeof(mode)) != S_OK)
246     return E_FAIL;
247   if (format_ident(pHelper, mode.name, pResult, max) != S_OK)
248     return E_FAIL;
249   return S_OK;
250 }  /* format_mode */
251
252 /**
253  * format a type
254  */
255 static HRESULT format_type(DEBUGHELPER *pHelper, int nBase, const void *addr, char *pResult, size_t max, int top)
256 {
257   ir_type tp;
258   char name[256];
259
260   if (copy_from_debuggee(addr, pHelper, &tp, sizeof(tp)) != S_OK)
261     return E_FAIL;
262
263   pResult[0] = '\0';
264   if (top) {
265     if (format_tp_op(pHelper, tp.type_op, pResult, max) != S_OK)
266       return E_FAIL;
267
268     _tcsncat(pResult, " ", max);
269   }
270
271   name[0] = '\0';
272   if (tp.name) {
273     if (format_ident(pHelper, tp.name, name, sizeof(name)) != S_OK)
274       return E_FAIL;
275   } else {
276     if (format_mode(pHelper, tp.mode, name, sizeof(name)) != S_OK)
277       return E_FAIL;
278   }
279
280   _tcsncat(pResult, name, max);
281   switch (nBase) {
282   case 16:
283     _snprintf(name, sizeof(name), " [0x%lx]", tp.nr);
284     break;
285   case 8:
286     _snprintf(name, sizeof(name), " [0%lo]", tp.nr);
287     break;
288   default:
289     _snprintf(name, sizeof(name), " [%ld]", tp.nr);
290   }
291   _tcsncat(pResult, name, max);
292
293   return S_OK;
294 }  /* format_type */
295
296 /**
297  * format an irg
298  */
299 static HRESULT format_irg(DEBUGHELPER *pHelper, int nBase, const void *addr, char *pResult, size_t max, int top)
300 {
301   ir_graph irg;
302   char name[256];
303
304   if (copy_from_debuggee(addr, pHelper, &irg, sizeof(irg)) != S_OK)
305     return E_FAIL;
306
307   *pResult = '\0';
308   if (top)
309     _tcsncpy(pResult, "IRG: ", max);
310
311   if (irg.ent) {
312     ir_entity ent;
313     ir_type owner;
314     int is_global;
315
316     if (copy_from_debuggee(irg.ent, pHelper, &ent, sizeof(ent)) != S_OK)
317       return E_FAIL;
318     if (is_global_type(pHelper, ent.owner, &is_global) != S_OK)
319       return E_FAIL;
320     if (! is_global) {
321       if (copy_from_debuggee(ent.owner, pHelper, &owner, sizeof(owner)) != S_OK)
322         return E_FAIL;
323       if (format_ident(pHelper, (void *)owner.name, name, sizeof(name)) != S_OK)
324         return E_FAIL;
325       _tcsncat(pResult, name, max);
326       _tcsncat(pResult, "::", max);
327     }
328     if (format_ident(pHelper, ent.name, name, sizeof(name)) != S_OK)
329       return E_FAIL;
330     _tcsncat(pResult, name, max);
331   }
332   else
333     _tcsncat(pResult, "NULL", max);
334
335   switch (nBase) {
336   case 16:
337     _snprintf(name, sizeof(name), " [0x%lx, 0x%u nodes]", irg.graph_nr, irg.last_node_idx);
338     break;
339   case 8:
340     _snprintf(name, sizeof(name), " [0%lo, 0%o nodes]", irg.graph_nr, irg.last_node_idx);
341     break;
342   default:
343     _snprintf(name, sizeof(name), " [%ld, %u nodes]", irg.graph_nr, irg.last_node_idx);
344   }
345   _tcsncat(pResult, name, max);
346   return S_OK;
347 }  /* format_irg */
348
349 /**
350  * format an ir_op
351  */
352 HRESULT format_op(DEBUGHELPER *pHelper, const void *addr, char *pResult, size_t max)
353 {
354   ir_op op;
355
356   if (copy_from_debuggee(addr, pHelper, &op, sizeof(op)) != S_OK)
357     return E_FAIL;
358   if (format_ident(pHelper, op.name, pResult, max) != S_OK)
359     return E_FAIL;
360   return S_OK;
361 }  /* format_op */
362
363 /** get a temporary string */
364 #define get_string(str)                                         \
365 do {                                                            \
366   int len;                                                      \
367   char *s;                                                      \
368   if (str) {                                                    \
369     len = strlen_debuggee(pHelper, str, 256);                   \
370     if (len < 0)                                                \
371       return E_FAIL;                                            \
372     s = alloca(len + 1);                                        \
373     if (copy_from_debuggee(str, pHelper, s, (DWORD)len) != S_OK) \
374       return E_FAIL;                                            \
375     s[len] = '\0';                                              \
376     str = s;                                                    \
377   }                                                             \
378 } while (0)
379
380 /**
381  * format a tarval
382  */
383 static HRESULT format_tarval(DEBUGHELPER *pHelper, int nBase, const void *addr, char *pResult, size_t max)
384 {
385   tarval tv;
386   char *value;
387   ir_mode mode;
388   unsigned len;
389   tarval_mode_info modinfo;
390
391   {
392     static int initialized = 0;
393
394     if (! initialized) {
395       /* from init_tarval_1() */
396       init_strcalc(68);
397       init_fltcalc(0);
398
399       initialized = 1;
400     }
401   }
402
403   if (copy_from_debuggee(addr, pHelper, &tv, sizeof(tv)) != S_OK)
404     return E_FAIL;
405
406   /* ir_mode */
407   if (tv.mode == NULL)
408     return E_FAIL;
409
410   if (copy_from_debuggee(tv.mode, pHelper, &mode, sizeof(mode)) != S_OK)
411     return E_FAIL;
412
413   tv.mode = &mode;
414
415   if (mode_is_int(&mode)) {
416     switch (nBase) {
417     case 16:
418       modinfo.mode_output = TVO_HEX;
419       modinfo.mode_prefix = "0x";
420       modinfo.mode_suffix = "";
421       break;
422     case 8:
423       modinfo.mode_output = TVO_OCTAL;
424       modinfo.mode_prefix = "0";
425       modinfo.mode_suffix = "";
426       break;
427     default:
428       modinfo.mode_output = TVO_DECIMAL;
429       modinfo.mode_prefix = "";
430       modinfo.mode_suffix = "";
431     }
432   }
433   else {
434     if (mode.tv_priv) {
435       if (copy_from_debuggee(mode.tv_priv, pHelper, &modinfo, sizeof(modinfo)) != S_OK)
436         return E_FAIL;
437
438       get_string(modinfo.mode_prefix);
439       get_string(modinfo.mode_suffix);
440     }
441   }
442   mode.tv_priv = &modinfo;
443
444   len = tv.length;
445   if (len) {
446     if (len > 256)
447       return E_FAIL;
448
449     value = alloca(len);
450
451     if (copy_from_debuggee(tv.value, pHelper, value, len) != S_OK)
452       return E_FAIL;
453
454     tv.value = value;
455
456     tarval_snprintf(pResult, max, &tv);
457   }
458   else {
459     /* might be a reserved tarval */
460     int resid = PTR_TO_INT(tv.value);
461
462     switch (resid) {
463     case resid_tarval_bad:
464       _tcsncat(pResult, "BAD", max);
465       break;
466     case resid_tarval_undefined:
467       _tcsncat(pResult, "UNDEF", max);
468       break;
469     case resid_tarval_b_false:
470       _tcsncat(pResult, "FALSE", max);
471       break;
472     case resid_tarval_b_true:
473       _tcsncat(pResult, "TRUE", max);
474       break;
475     default:
476       /* try it */
477       tarval_snprintf(pResult, max, &tv);
478     }
479   }
480   return S_OK;
481 }  /* format_tarval */
482
483 /**
484  * format an ir_node
485  */
486 static HRESULT format_node(DEBUGHELPER *pHelper, int nBase, const void *addr, char *pResult, size_t max, int top)
487 {
488   ir_node n;
489   char name[256];
490   ir_op op;
491
492   if (copy_from_debuggee(addr, pHelper, &n, sizeof(n)) != S_OK)
493     return E_FAIL;
494
495   /* ir_op */
496   if (format_op(pHelper, n.op, pResult, max) != S_OK)
497     return E_FAIL;
498
499   /* ir_mode */
500   if (format_mode(pHelper, n.mode, name, sizeof(name)) != S_OK)
501     return E_FAIL;
502   _tcsncat(pResult, name, max);
503
504   if (copy_from_debuggee(n.op, pHelper, &op, sizeof(op)) != S_OK)
505     return E_FAIL;
506
507   /* show show node attributes */
508   switch (op.code) {
509   case iro_Const:
510     if (format_tarval(pHelper, nBase, n.attr.con.tarval, name, sizeof(name)) != S_OK) {
511       _tcsncat(pResult, "<???>", max);
512     }
513     else {
514       _tcsncat(pResult, "<", max);
515       _tcsncat(pResult, name, max);
516       _tcsncat(pResult, ">", max);
517     }
518     break;
519   case iro_SymConst:
520     _tcsncat(pResult, "<", max);
521     switch (n.attr.symc.kind) {
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_ent:
535       _tcsncat(pResult, "ENT:", max);
536       if (format_entity(pHelper, nBase, n.attr.symc.sym.entity_p, name, sizeof(name), 0) != S_OK)
537         return E_FAIL;
538       _tcsncat(pResult, name, max);
539       break;
540     }
541     _tcsncat(pResult, ">", max);
542     break;
543   case iro_Sel:
544     _tcsncat(pResult, "<", max);
545     if (format_entity(pHelper, nBase, n.attr.sel.entity, name, sizeof(name), 0) != S_OK)
546       return E_FAIL;
547     _tcsncat(pResult, name, max);
548     _tcsncat(pResult, ">", max);
549     break;
550   case iro_Cast:
551     _tcsncat(pResult, "<", max);
552     if (format_type(pHelper, nBase, n.attr.cast.type, name, sizeof(name), 0) != S_OK)
553       return E_FAIL;
554     _tcsncat(pResult, name, max);
555     _tcsncat(pResult, ">", max);
556     break;
557   case iro_Alloc:
558     _tcsncat(pResult, "<", max);
559     if (format_type(pHelper, nBase, n.attr.alloc.type, name, sizeof(name), 0) != S_OK)
560       return E_FAIL;
561     _tcsncat(pResult, name, max);
562     _snprintf(name, sizeof(name), ", %s", n.attr.alloc.where == stack_alloc ? "stack" : "heap");
563     _tcsncat(pResult, name, max);
564     _tcsncat(pResult, ">", max);
565     break;
566   case iro_Free:
567     _tcsncat(pResult, "<", max);
568     if (format_type(pHelper, nBase, n.attr.free.type, name, sizeof(name), 0) != S_OK)
569       return E_FAIL;
570     _tcsncat(pResult, name, max);
571     _snprintf(name, sizeof(name), ", %s", n.attr.free.where == stack_alloc ? "stack" : "heap");
572     _tcsncat(pResult, name, max);
573     _tcsncat(pResult, ">", max);
574     break;
575   case iro_CopyB:
576     _tcsncat(pResult, "<", max);
577     if (format_type(pHelper, nBase, n.attr.copyb.type, name, sizeof(name), 0) != S_OK)
578       return E_FAIL;
579     _tcsncat(pResult, name, max);
580     _tcsncat(pResult, ">", max);
581     break;
582   }
583
584   switch (nBase) {
585   case 16:
586     _snprintf(name, sizeof(name), " [0x%lx:0x%x]", n.node_nr, n.node_idx);
587     break;
588   case 8:
589     _snprintf(name, sizeof(name), " [0%lo:0%o]", n.node_nr, n.node_idx);
590     break;
591   default:
592     _snprintf(name, sizeof(name), " [%ld:%u]", n.node_nr, n.node_idx);
593   }
594   _tcsncat(pResult, name, max);
595
596   return S_OK;
597 }  /* format_node */
598
599 /**
600  * format a loop
601  */
602 static HRESULT format_loop(DEBUGHELPER *pHelper, const void *addr, char *pResult, size_t max)
603 {
604   ir_loop loop;
605
606   if (copy_from_debuggee(addr, pHelper, &loop, sizeof(loop)) != S_OK)
607     return E_FAIL;
608   return E_FAIL;
609 }  /* format_loop */
610
611 /**
612  * Get an array descriptor
613  */
614 static HRESULT get_array_desc(DEBUGHELPER *pHelper, const void *address, ir_arr_descr *desc)
615 {
616   address = ARR_DESCR(address);
617   if (copy_from_debuggee(address, pHelper, desc, sizeof(*desc)) != S_OK)
618     return E_FAIL;
619
620   return S_OK;
621 }  /* get_array_desc */
622
623 /**
624  * format an extended block
625  */
626 static HRESULT format_extblk(DEBUGHELPER *pHelper, int nBase, const void *addr, char *pResult, size_t max)
627 {
628   ir_extblk extbb;
629   ir_arr_descr blocks;
630   ir_node *blks = NULL;
631   char name[256];
632   int len;
633
634   if (copy_from_debuggee(addr, pHelper, &extbb, sizeof(extbb)) != S_OK)
635     return E_FAIL;
636   if (extbb.blks == NULL)
637     return E_FAIL;
638
639   if (get_array_desc(pHelper, extbb.blks, &blocks) != S_OK)
640     return E_FAIL;
641
642   len = ARR_LEN(&blocks.v.elts);
643
644   if (len > 0) {
645     if (copy_from_debuggee(extbb.blks, pHelper, &blks, sizeof(blks)) != S_OK)
646       return E_FAIL;
647   }
648
649   if (blks) {
650     switch (nBase) {
651     case 16:
652       _snprintf(name, sizeof(name), "0x%x 0x%x blocks", blks->node_nr, len);
653       break;
654     case 8:
655       _snprintf(name, sizeof(name), "0%o 0%o blocks", blks->node_nr, len);
656       break;
657     default:
658       _snprintf(name, sizeof(name), "%d %d blocks", blks->node_nr, len);
659     }
660     _tcsncpy(pResult, name, max);
661   }
662   else
663     _tcsncpy(pResult, "<EMPTY>", max);
664   return S_OK;
665 }  /* format_extblk */
666
667
668 /**
669  * format a ir_prog
670  */
671 static HRESULT format_prog(DEBUGHELPER *pHelper, int nBase, const void *addr, char *pResult, size_t max)
672 {
673   ir_prog irp;
674   ir_arr_descr graphs, types;
675   char name[256];
676
677   if (copy_from_debuggee(addr, pHelper, &irp, sizeof(irp)) != S_OK)
678     return E_FAIL;
679   if (irp.graphs) {
680     if (get_array_desc(pHelper, irp.graphs, &graphs) != S_OK)
681       return E_FAIL;
682
683     irp.graphs = (ir_graph**)&graphs.v.elts;
684   }
685
686   if (irp.types) {
687     if (get_array_desc(pHelper, irp.types, &types) != S_OK)
688       return E_FAIL;
689
690     irp.types = (ir_type**)&types.v.elts;
691   }
692
693   switch (nBase) {
694   case 16:
695     _snprintf(name, sizeof(name), "0x%x graphs 0x%x types", ARR_LEN(irp.graphs), ARR_LEN(irp.types));
696     break;
697   case 8:
698     _snprintf(name, sizeof(name), "0%o graphs 0%o types", ARR_LEN(irp.graphs), ARR_LEN(irp.types));
699     break;
700   default:
701     _snprintf(name, sizeof(name), "%d graphs %d types", ARR_LEN(irp.graphs), ARR_LEN(irp.types));
702   }
703   _tcsncpy(pResult, name, max);
704
705   return S_OK;
706 }  /* format_prog */
707
708 /*
709  * Format an array descriptor
710  */
711 HRESULT format_arr_descr(DEBUGHELPER *pHelper, int nBase, const void *addr, char *pResult, size_t max)
712 {
713   ir_arr_descr desc;
714   char name[256];
715
716   if (copy_from_debuggee(addr, pHelper, &desc, sizeof(desc)) != S_OK)
717     return E_FAIL;
718
719   switch (desc.magic) {
720   case ARR_D_MAGIC:
721     _tcsncpy(pResult, "DynArr ", max); break;
722   case ARR_A_MAGIC:
723     _tcsncpy(pResult, "AutoArr ", max); break;
724   case ARR_F_MAGIC:
725     _tcsncpy(pResult, "FlexArr ", max); break;
726   default:
727     _tcsncpy(pResult, "UNKN ", max);
728   }
729
730   switch (nBase) {
731   case 16:
732     _snprintf(name, sizeof(name), "nelts 0x%x", desc.nelts);
733     break;
734   case 8:
735     _snprintf(name, sizeof(name), "nelts 0%o", desc.nelts);
736     break;
737   default:
738     _snprintf(name, sizeof(name), "nelts %d", desc.nelts);
739   }
740   _tcsncat(pResult, name, max);
741
742   return S_OK;
743 }  /* format_arr_descr */
744
745 /*
746  * format a firm object
747  */
748 HRESULT FormatFirmObject(DEBUGHELPER *pHelper, int nBase, firm_kind kind, const void *addr, char *pResult, size_t max)
749 {
750   switch (kind) {
751   case k_entity:     /* an entity */
752     return format_entity(pHelper, nBase, addr, pResult, max, 1);
753   case k_type:       /* a type */
754     return format_type(pHelper, nBase, addr, pResult, max, 1);
755   case k_ir_graph:   /* an ir graph */
756     return format_irg(pHelper, nBase, addr, pResult, max, 1);
757   case k_ir_node:    /* an ir node */
758     return format_node(pHelper, nBase, addr, pResult, max, 1);
759   case k_ir_mode:    /* an ir mode */
760     return format_mode(pHelper, addr, pResult, max);
761   case k_ir_op:      /* an ir opcode */
762     return format_op(pHelper, addr, pResult, max);
763   case k_tarval:     /* a tarval */
764     return format_tarval(pHelper, nBase, addr, pResult, max);
765   case k_ir_loop:    /* a loop */
766     return format_loop(pHelper, addr, pResult, max);
767   case k_ir_compound_graph_path: /* a compound graph path, see entity.h */
768     return E_FAIL;
769   case k_ir_extblk:  /* an extended block */
770     return format_extblk(pHelper, nBase, addr, pResult, max);
771   case k_ir_prog:    /* a program representation (irp) */
772     return format_prog(pHelper, nBase, addr, pResult, max);
773   default:
774     return E_FAIL;
775   }
776 }  /* FormatFirmObject */
777
778 #define SEGMENT_SIZE_SHIFT      8
779 #define SEGMENT_SIZE            (1 << SEGMENT_SIZE_SHIFT)
780 #define DIRECTORY_SIZE_SHIFT    8
781 #define DIRECTORY_SIZE          (1 << DIRECTORY_SIZE_SHIFT)
782 #define MAX_LOAD_FACTOR         4
783
784 typedef struct pset_element {
785   struct pset_element *chain;   /**< for chaining Elements */
786   pset_entry entry;
787 } pset_Element, *pset_Segment;
788
789 /* not visible from outside */
790 struct pset {
791   unsigned p;              /**< Next bucket to be split */
792   unsigned maxp;           /**< upper bound on p during expansion */
793   unsigned nkey;           /**< current # keys */
794   unsigned nseg;           /**< current # segments */
795   pset_Segment *dir[DIRECTORY_SIZE];
796   int (*cmp)();            /**< function comparing entries */
797   unsigned iter_i, iter_j;
798   pset_Element *iter_tail; /**< non-NULL while iterating over elts */
799   pset_Element *free_list; /**< list of free Elements */
800   struct obstack obst;     /**< obstack for allocation all data */
801 #ifdef STATS
802   int naccess, ncollision, ndups;
803   int max_chain_len;
804 #endif
805 #ifdef DEBUG
806   const char *tag;         /**< an optionally tag for distinguishing sets */
807 #endif
808 };
809
810 typedef struct set_element {
811   struct set_element *chain;    /**< for chaining Elements */
812   set_entry entry;
813 } set_Element, *set_Segment;
814
815 /* not visible from outside */
816 struct set {
817   unsigned p;              /**< Next bucket to be split */
818   unsigned maxp;           /**< upper bound on p during expansion */
819   unsigned nkey;           /**< current # keys */
820   unsigned nseg;           /**< current # segments */
821   set_Segment *dir[DIRECTORY_SIZE];
822   int (*cmp)();            /**< function comparing entries */
823   unsigned iter_i, iter_j;
824   set_Element *iter_tail;  /**< non-NULL while iterating over elts */
825   struct obstack obst;     /**< obstack for allocation all data */
826 #ifdef STATS
827   int naccess, ncollision, ndups;
828   int max_chain_len;
829 #endif
830 #ifdef DEBUG
831   const char *tag;         /**< an optionally tag for distinguishing sets */
832 #endif
833 };
834
835 /**
836  * Find the longest chain of a pset
837  */
838 static HRESULT find_longest_pset_chain(DEBUGHELPER *pHelper, pset *set,
839                                        int *chains, int *lenght, size_t *size)
840 {
841   unsigned i, j;
842   pset_Segment *seg, *curr;
843   pset_Element elem;
844   void *address;
845   int len, nchains = 0, max_len = 0;
846   size_t dyns = 0;
847
848   for (i = 0; i < set->nseg; ++i) {
849     seg = set->dir[i];
850
851     dyns += sizeof(seg[j]) * SEGMENT_SIZE;
852     for (j = 0; j < SEGMENT_SIZE; ++j) {
853       if (copy_from_debuggee(&seg[j], pHelper, &curr, sizeof(curr)) != S_OK)
854         return E_FAIL;
855
856       address = curr;
857       if (address)
858         ++nchains;
859       for (len = 0; address != NULL; address = elem.chain) {
860         if (copy_from_debuggee(address, pHelper, &elem, sizeof(elem)) != S_OK)
861           return E_FAIL;
862         dyns += sizeof(pset_Element);
863         ++len;
864       }
865       if (len > max_len)
866         max_len = len;
867     }
868   }
869
870   *chains = nchains;
871   *lenght = max_len;
872   *size   = dyns;
873   return S_OK;
874 }  /* find_longest_pset_chain */
875
876 /**
877  * Find the longest chain of a set
878  */
879 static HRESULT find_longest_set_chain(DEBUGHELPER *pHelper, set *set,
880                                       int *chains, int *lenght, size_t *size)
881 {
882   unsigned i, j;
883   set_Segment *seg, *curr;
884   set_Element elem;
885   void *address;
886   int len, nchains = 0, max_len = 0;
887   size_t dyns = 0;
888
889   for (i = 0; i < set->nseg; ++i) {
890     seg = set->dir[i];
891
892     dyns += sizeof(seg[j]) * SEGMENT_SIZE;
893     for (j = 0; j < SEGMENT_SIZE; ++j) {
894       if (copy_from_debuggee(&seg[j], pHelper, &curr, sizeof(curr)) != S_OK)
895           return E_FAIL;
896
897       address = curr;
898       if (address)
899         ++nchains;
900       for (len = 0; address != NULL; address = elem.chain) {
901         if (copy_from_debuggee(address, pHelper, &elem, sizeof(elem)) != S_OK)
902           return E_FAIL;
903         dyns += offsetof(set_Element, entry.dptr) + elem.entry.size;
904         ++len;
905       }
906       if (len > max_len)
907         max_len = len;
908     }
909   }
910
911   *chains = nchains;
912   *lenght = max_len;
913   *size   = dyns;
914   return S_OK;
915 }  /* find_longest_set_chain */
916
917 /*
918  * Format a pset
919  */
920 HRESULT format_pset(DEBUGHELPER *pHelper, int nBase, const void *address, char *pResult, size_t max)
921 {
922   pset set;
923   char name[256];
924   int nchains, chain_len;
925   size_t size;
926
927   if (copy_from_debuggee(address, pHelper, &set, sizeof(set)) != S_OK)
928     return E_FAIL;
929
930   if (find_longest_pset_chain(pHelper, &set, &nchains, &chain_len, &size) != S_OK)
931     return E_FAIL;
932
933   switch (nBase) {
934   case 16:
935     _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);
936     break;
937   case 8:
938     _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);
939     break;
940   default:
941     _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);
942   }
943   _tcsncpy(pResult, name, max);
944
945   return S_OK;
946 }  /* format_pset */
947
948 /*
949  * Format a set
950  */
951 HRESULT format_set(DEBUGHELPER *pHelper, int nBase, const void *address, char *pResult, size_t max)
952 {
953   set set;
954   char name[256];
955   int nchains, chain_len;
956   size_t size;
957
958   if (copy_from_debuggee(address, pHelper, &set, sizeof(set)) != S_OK)
959     return E_FAIL;
960
961   if (find_longest_set_chain(pHelper, &set, &nchains, &chain_len, &size) != S_OK)
962     return E_FAIL;
963
964   switch (nBase) {
965   case 16:
966     _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);
967     break;
968   case 8:
969     _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);
970     break;
971   default:
972     _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);
973   }
974   _tcsncpy(pResult, name, max);
975
976   return S_OK;
977 }  /* format_set */
978
979 struct pdeq {
980   unsigned magic;       /**< debug magic, only available in DEBUG builds */
981   pdeq *l_end, *r_end;  /**< left and right ends of the queue */
982   pdeq *l, *r;          /**< left and right neighbor */
983   int n;                /**< number of elements in the current chunk */
984   int p;                /**< the read/write pointer */
985   const void *data[1];  /**< storage for elements */
986 };
987
988 /** Returns the length of a double ended pointer list. */
989 static int get_pdeq_len(DEBUGHELPER *pHelper, pdeq *dq)
990 {
991   int n;
992   pdeq *q;
993   pdeq pdeq;
994
995   n = 0;
996   q = dq->l_end;
997
998   if (copy_from_debuggee(q, pHelper, &pdeq, sizeof(pdeq)) != S_OK)
999     return -1;
1000   q = &pdeq;
1001
1002   for (;;) {
1003     n += q->n;
1004     q = q->r;
1005     if (! q)
1006       break;
1007
1008     if (copy_from_debuggee(q, pHelper, &pdeq, sizeof(pdeq)) != S_OK)
1009       return -1;
1010     q = &pdeq;
1011   };
1012
1013   return n;
1014 }  /* get_pdeq_len */
1015
1016 /*
1017  * Format a pdeq
1018  */
1019 HRESULT format_pdeq(DEBUGHELPER *pHelper, int nBase, const void *address, char *pResult, size_t max)
1020 {
1021   pdeq pdeq;
1022   char name[256];
1023   int len;
1024
1025   if (copy_from_debuggee(address, pHelper, &pdeq, sizeof(pdeq)) != S_OK)
1026     return E_FAIL;
1027
1028   len = get_pdeq_len(pHelper, &pdeq);
1029   if (len < 0)
1030     return E_FAIL;
1031
1032   switch (nBase) {
1033   case 16:
1034     _snprintf(name, sizeof(name), "pdeq 0x%x elem", len);
1035     break;
1036   case 8:
1037     _snprintf(name, sizeof(name), "pdeq 0%o elem", len);
1038     break;
1039   default:
1040     _snprintf(name, sizeof(name), "pdeq %d elem", len);
1041   }
1042   _tcsncpy(pResult, name, max);
1043
1044   return S_OK;
1045 }  /* format_pdeq */
1046
1047 /** show the first 2 units */
1048 static HRESULT fill_bits(DEBUGHELPER *pHelper, bitset_t *bs, char *pResult)
1049 {
1050   unsigned i, units = bs->size;
1051   int l = 0, o = 0, breaked = 0;
1052   unsigned j;
1053
1054   for (i = 0; i < units; ++i) {
1055     unsigned data;
1056
1057     if (copy_from_debuggee((void *)(&bs->data[i]), pHelper, &data, sizeof(data)) != S_OK)
1058       return E_FAIL;
1059
1060     for (j = 0; j < 32; ++j) {
1061       if (data & (1 << j)) {
1062         sprintf(pResult + l, "%d,", i * sizeof(data) * 8 + j);
1063         l += strlen(pResult + l);
1064         ++o;
1065         if (o >= 10) {
1066           breaked = 1;
1067           goto end;
1068         }
1069       }
1070     }
1071   }
1072 end:
1073   if (breaked) {
1074     sprintf(pResult + l, "...");
1075     l += 3;
1076   }
1077   sprintf(pResult + l, "}");
1078   return S_OK;
1079 }  /* fill_bits */
1080
1081 /*
1082  * Format a bitset
1083  */
1084 HRESULT format_bitset(DEBUGHELPER *pHelper, int nBase, const void *address, char *pResult, size_t max)
1085 {
1086   bitset_t bs;
1087   char name[256];
1088   unsigned l;
1089
1090   if (copy_from_debuggee(address, pHelper, &bs, sizeof(bs)) != S_OK)
1091     return E_FAIL;
1092
1093   switch (nBase) {
1094   case 16:
1095     _snprintf(name, sizeof(name), "bitset{0x%x:", bs.size);
1096     break;
1097   case 8:
1098     _snprintf(name, sizeof(name), "bitset{0%o:", bs.size);
1099     break;
1100   default:
1101     _snprintf(name, sizeof(name), "bitset{%u:", bs.size);
1102   }
1103
1104   l = strlen(name);
1105   if (fill_bits(pHelper, &bs, &name[l]) != S_OK)
1106     return E_FAIL;
1107
1108
1109   _tcsncpy(pResult, name, max);
1110
1111   return S_OK;
1112 }  /* format_bitset */