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