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