remove extended basic block support
[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 "irprog_t.h"
30 #include "compound_path_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 {
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 {
63   switch (kind) {
64   case k_entity:     /* an entity */
65     return sizeof(ir_entity);
66   case k_type:       /* a type */
67     return sizeof(ir_type);
68   case k_ir_graph:   /* an ir graph */
69     return sizeof(ir_graph);
70   case k_ir_node:    /* an ir node */
71     return sizeof(ir_node);
72   case k_ir_mode:    /* an ir mode */
73     return sizeof(ir_mode);
74   case k_ir_op:      /* an ir opcode */
75     return sizeof(ir_op);
76   case k_tarval:     /* a tarval */
77     return sizeof(tarval);
78   case k_ir_loop:    /* a loop */
79     return sizeof(ir_loop);
80   case k_ir_compound_graph_path: /* a compound graph path, see entity.h */
81     return sizeof(compound_graph_path);
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 {
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(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 {
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 {
192   ir_entity ent;
193   ir_type owner;
194   char name[256];
195   int is_global;
196
197   if (copy_from_debuggee(addr, pHelper, &ent, sizeof(ent)) != S_OK) {
198     return E_FAIL;
199   }
200   if (is_global_type(pHelper, ent.owner, &is_global) != S_OK)
201     return E_FAIL;
202
203   *pResult = '\0';
204   if (top)
205     _tcsncpy(pResult, "ENT: ", max);
206
207   if (! is_global) {
208     if (copy_from_debuggee(ent.owner, pHelper, &owner, sizeof(owner)) != S_OK)
209       return E_FAIL;
210     if (format_ident(pHelper, (void *)owner.name, name, sizeof(name)) != S_OK)
211       return E_FAIL;
212     _tcsncat(pResult, name, max);
213     _tcsncat(pResult, "::", max);
214   }
215
216   if (format_ident(pHelper, (void *)ent.name, name, sizeof(name)) != S_OK)
217     return E_FAIL;
218   _tcsncat(pResult, name, max);
219
220   switch (nBase) {
221   case 16:
222     _snprintf(name, sizeof(name), " [0x%lx]", ent.nr);
223     break;
224   case 8:
225     _snprintf(name, sizeof(name), " [0%lo]", ent.nr);
226     break;
227   default:
228     _snprintf(name, sizeof(name), " [%ld]", ent.nr);
229   }
230   _tcsncat(pResult, name, max);
231
232   return S_OK;
233 }  /* format_entity */
234
235 /**
236  * format an ir_mode
237  */
238 static HRESULT format_mode(DEBUGHELPER *pHelper, const void *addr, char *pResult, size_t max)
239 {
240   ir_mode mode;
241
242   if (copy_from_debuggee(addr, pHelper, &mode, sizeof(mode)) != S_OK)
243     return E_FAIL;
244   if (format_ident(pHelper, mode.name, pResult, max) != S_OK)
245     return E_FAIL;
246   return S_OK;
247 }  /* format_mode */
248
249 /**
250  * format a type
251  */
252 static HRESULT format_type(DEBUGHELPER *pHelper, int nBase, const void *addr, char *pResult, size_t max, int top)
253 {
254   ir_type tp;
255   char name[256];
256
257   if (copy_from_debuggee(addr, pHelper, &tp, sizeof(tp)) != S_OK)
258     return E_FAIL;
259
260   pResult[0] = '\0';
261   if (top) {
262     if (format_tp_op(pHelper, tp.type_op, pResult, max) != S_OK)
263       return E_FAIL;
264
265     _tcsncat(pResult, " ", max);
266   }
267
268   name[0] = '\0';
269   if (tp.name) {
270     if (format_ident(pHelper, tp.name, name, sizeof(name)) != S_OK)
271       return E_FAIL;
272   } else {
273     if (format_mode(pHelper, tp.mode, name, sizeof(name)) != S_OK)
274       return E_FAIL;
275   }
276
277   _tcsncat(pResult, name, max);
278   switch (nBase) {
279   case 16:
280     _snprintf(name, sizeof(name), " [0x%lx]", tp.nr);
281     break;
282   case 8:
283     _snprintf(name, sizeof(name), " [0%lo]", tp.nr);
284     break;
285   default:
286     _snprintf(name, sizeof(name), " [%ld]", tp.nr);
287   }
288   _tcsncat(pResult, name, max);
289
290   return S_OK;
291 }  /* format_type */
292
293 /**
294  * format an irg
295  */
296 static HRESULT format_irg(DEBUGHELPER *pHelper, int nBase, const void *addr, char *pResult, size_t max, int top)
297 {
298   ir_graph irg;
299   char name[256];
300
301   if (copy_from_debuggee(addr, pHelper, &irg, sizeof(irg)) != S_OK)
302     return E_FAIL;
303
304   *pResult = '\0';
305   if (top)
306     _tcsncpy(pResult, "IRG: ", max);
307
308   if (irg.ent) {
309     ir_entity ent;
310     ir_type owner;
311     int is_global;
312
313     if (copy_from_debuggee(irg.ent, pHelper, &ent, sizeof(ent)) != S_OK)
314       return E_FAIL;
315     if (is_global_type(pHelper, ent.owner, &is_global) != S_OK)
316       return E_FAIL;
317     if (! is_global) {
318       if (copy_from_debuggee(ent.owner, pHelper, &owner, sizeof(owner)) != S_OK)
319         return E_FAIL;
320       if (format_ident(pHelper, (void *)owner.name, name, sizeof(name)) != S_OK)
321         return E_FAIL;
322       _tcsncat(pResult, name, max);
323       _tcsncat(pResult, "::", max);
324     }
325     if (format_ident(pHelper, ent.name, name, sizeof(name)) != S_OK)
326       return E_FAIL;
327     _tcsncat(pResult, name, max);
328   }
329   else
330     _tcsncat(pResult, "NULL", max);
331
332   switch (nBase) {
333   case 16:
334     _snprintf(name, sizeof(name), " [0x%lx, 0x%u nodes]", irg.graph_nr, irg.last_node_idx);
335     break;
336   case 8:
337     _snprintf(name, sizeof(name), " [0%lo, 0%o nodes]", irg.graph_nr, irg.last_node_idx);
338     break;
339   default:
340     _snprintf(name, sizeof(name), " [%ld, %u nodes]", irg.graph_nr, irg.last_node_idx);
341   }
342   _tcsncat(pResult, name, max);
343   return S_OK;
344 }  /* format_irg */
345
346 /**
347  * format an ir_op
348  */
349 HRESULT format_op(DEBUGHELPER *pHelper, const void *addr, char *pResult, size_t max)
350 {
351   ir_op op;
352
353   if (copy_from_debuggee(addr, pHelper, &op, sizeof(op)) != S_OK)
354     return E_FAIL;
355   if (format_ident(pHelper, op.name, pResult, max) != S_OK)
356     return E_FAIL;
357   return S_OK;
358 }  /* format_op */
359
360 /** get a temporary string */
361 #define get_string(str)                                         \
362 do {                                                            \
363   int len;                                                      \
364   char *s;                                                      \
365   if (str) {                                                    \
366     len = strlen_debuggee(pHelper, str, 256);                   \
367     if (len < 0)                                                \
368       return E_FAIL;                                            \
369     s = alloca(len + 1);                                        \
370     if (copy_from_debuggee(str, pHelper, s, (DWORD)len) != S_OK) \
371       return E_FAIL;                                            \
372     s[len] = '\0';                                              \
373     str = s;                                                    \
374   }                                                             \
375 } while (0)
376
377 /**
378  * format a tarval
379  */
380 static HRESULT format_tarval(DEBUGHELPER *pHelper, int nBase, const void *addr, char *pResult, size_t max)
381 {
382   tarval tv;
383   char *value;
384   ir_mode mode;
385   unsigned len;
386   tarval_mode_info modinfo;
387
388   {
389     static int initialized = 0;
390
391     if (! initialized) {
392       /* from init_tarval_1() */
393       init_strcalc(68);
394       init_fltcalc(0);
395
396       initialized = 1;
397     }
398   }
399
400   if (copy_from_debuggee(addr, pHelper, &tv, sizeof(tv)) != S_OK)
401     return E_FAIL;
402
403   /* ir_mode */
404   if (tv.mode == NULL)
405     return E_FAIL;
406
407   if (copy_from_debuggee(tv.mode, pHelper, &mode, sizeof(mode)) != S_OK)
408     return E_FAIL;
409
410   tv.mode = &mode;
411
412   if (mode_is_int(&mode)) {
413     switch (nBase) {
414     case 16:
415       modinfo.mode_output = TVO_HEX;
416       modinfo.mode_prefix = "0x";
417       modinfo.mode_suffix = "";
418       break;
419     case 8:
420       modinfo.mode_output = TVO_OCTAL;
421       modinfo.mode_prefix = "0";
422       modinfo.mode_suffix = "";
423       break;
424     default:
425       modinfo.mode_output = TVO_DECIMAL;
426       modinfo.mode_prefix = "";
427       modinfo.mode_suffix = "";
428     }
429   }
430   else {
431     if (mode.tv_priv) {
432       if (copy_from_debuggee(mode.tv_priv, pHelper, &modinfo, sizeof(modinfo)) != S_OK)
433         return E_FAIL;
434
435       get_string(modinfo.mode_prefix);
436       get_string(modinfo.mode_suffix);
437     }
438   }
439   mode.tv_priv = &modinfo;
440
441   len = tv.length;
442   if (len) {
443     if (len > 256)
444       return E_FAIL;
445
446     value = alloca(len);
447
448     if (copy_from_debuggee(tv.value, pHelper, value, len) != S_OK)
449       return E_FAIL;
450
451     tv.value = value;
452
453     tarval_snprintf(pResult, max, &tv);
454   }
455   else {
456     /* might be a reserved tarval */
457     int resid = PTR_TO_INT(tv.value);
458
459     switch (resid) {
460     case resid_tarval_bad:
461       _tcsncat(pResult, "BAD", max);
462       break;
463     case resid_tarval_undefined:
464       _tcsncat(pResult, "UNDEF", max);
465       break;
466     case resid_tarval_b_false:
467       _tcsncat(pResult, "FALSE", max);
468       break;
469     case resid_tarval_b_true:
470       _tcsncat(pResult, "TRUE", max);
471       break;
472     default:
473       /* try it */
474       tarval_snprintf(pResult, max, &tv);
475     }
476   }
477   return S_OK;
478 }  /* format_tarval */
479
480 /**
481  * format an ir_node
482  */
483 static HRESULT format_node(DEBUGHELPER *pHelper, int nBase, const void *addr, char *pResult, size_t max, int top)
484 {
485   ir_node n;
486   char name[256];
487   ir_op op;
488
489   if (copy_from_debuggee(addr, pHelper, &n, sizeof(n)) != S_OK)
490     return E_FAIL;
491
492   /* ir_op */
493   if (format_op(pHelper, n.op, pResult, max) != S_OK)
494     return E_FAIL;
495
496   /* ir_mode */
497   if (format_mode(pHelper, n.mode, name, sizeof(name)) != S_OK)
498     return E_FAIL;
499   _tcsncat(pResult, name, max);
500
501   if (copy_from_debuggee(n.op, pHelper, &op, sizeof(op)) != S_OK)
502     return E_FAIL;
503
504   /* show show node attributes */
505   switch (op.code) {
506   case iro_Const:
507     if (format_tarval(pHelper, nBase, n.attr.con.tarval, name, sizeof(name)) != S_OK) {
508       _tcsncat(pResult, "<???>", max);
509     }
510     else {
511       _tcsncat(pResult, "<", max);
512       _tcsncat(pResult, name, max);
513       _tcsncat(pResult, ">", max);
514     }
515     break;
516   case iro_SymConst:
517     _tcsncat(pResult, "<", max);
518     switch (n.attr.symc.kind) {
519     case symconst_type_size:
520       _tcsncat(pResult, "SIZE:", 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_type_align:
526       _tcsncat(pResult, "ALGN:", max);
527       if (format_type(pHelper, nBase, n.attr.symc.sym.type_p, name, sizeof(name), 0) != 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 a ir_prog
622  */
623 static HRESULT format_prog(DEBUGHELPER *pHelper, int nBase, const void *addr, char *pResult, size_t max)
624 {
625   ir_prog irp;
626   ir_arr_descr graphs, types;
627   char name[256];
628
629   if (copy_from_debuggee(addr, pHelper, &irp, sizeof(irp)) != S_OK)
630     return E_FAIL;
631   if (irp.graphs) {
632     if (get_array_desc(pHelper, irp.graphs, &graphs) != S_OK)
633       return E_FAIL;
634
635     irp.graphs = (ir_graph**)&graphs.v.elts;
636   }
637
638   if (irp.types) {
639     if (get_array_desc(pHelper, irp.types, &types) != S_OK)
640       return E_FAIL;
641
642     irp.types = (ir_type**)&types.v.elts;
643   }
644
645   switch (nBase) {
646   case 16:
647     _snprintf(name, sizeof(name), "0x%x graphs 0x%x types", ARR_LEN(irp.graphs), ARR_LEN(irp.types));
648     break;
649   case 8:
650     _snprintf(name, sizeof(name), "0%o graphs 0%o types", ARR_LEN(irp.graphs), ARR_LEN(irp.types));
651     break;
652   default:
653     _snprintf(name, sizeof(name), "%d graphs %d types", ARR_LEN(irp.graphs), ARR_LEN(irp.types));
654   }
655   _tcsncpy(pResult, name, max);
656
657   return S_OK;
658 }  /* format_prog */
659
660 /*
661  * Format an array descriptor
662  */
663 HRESULT format_arr_descr(DEBUGHELPER *pHelper, int nBase, const void *addr, char *pResult, size_t max)
664 {
665   ir_arr_descr desc;
666   char name[256];
667
668   if (copy_from_debuggee(addr, pHelper, &desc, sizeof(desc)) != S_OK)
669     return E_FAIL;
670
671   switch (desc.magic) {
672   case ARR_D_MAGIC:
673     _tcsncpy(pResult, "DynArr ", max); break;
674   case ARR_A_MAGIC:
675     _tcsncpy(pResult, "AutoArr ", max); break;
676   case ARR_F_MAGIC:
677     _tcsncpy(pResult, "FlexArr ", max); break;
678   default:
679     _tcsncpy(pResult, "UNKN ", max);
680   }
681
682   switch (nBase) {
683   case 16:
684     _snprintf(name, sizeof(name), "nelts 0x%x", desc.nelts);
685     break;
686   case 8:
687     _snprintf(name, sizeof(name), "nelts 0%o", desc.nelts);
688     break;
689   default:
690     _snprintf(name, sizeof(name), "nelts %d", desc.nelts);
691   }
692   _tcsncat(pResult, name, max);
693
694   return S_OK;
695 }  /* format_arr_descr */
696
697 /*
698  * format a firm object
699  */
700 HRESULT FormatFirmObject(DEBUGHELPER *pHelper, int nBase, firm_kind kind, const void *addr, char *pResult, size_t max)
701 {
702   switch (kind) {
703   case k_entity:     /* an entity */
704     return format_entity(pHelper, nBase, addr, pResult, max, 1);
705   case k_type:       /* a type */
706     return format_type(pHelper, nBase, addr, pResult, max, 1);
707   case k_ir_graph:   /* an ir graph */
708     return format_irg(pHelper, nBase, addr, pResult, max, 1);
709   case k_ir_node:    /* an ir node */
710     return format_node(pHelper, nBase, addr, pResult, max, 1);
711   case k_ir_mode:    /* an ir mode */
712     return format_mode(pHelper, addr, pResult, max);
713   case k_ir_op:      /* an ir opcode */
714     return format_op(pHelper, addr, pResult, max);
715   case k_tarval:     /* a tarval */
716     return format_tarval(pHelper, nBase, addr, pResult, max);
717   case k_ir_loop:    /* a loop */
718     return format_loop(pHelper, addr, pResult, max);
719   case k_ir_compound_graph_path: /* a compound graph path, see entity.h */
720     return E_FAIL;
721   case k_ir_prog:    /* a program representation (irp) */
722     return format_prog(pHelper, nBase, addr, pResult, max);
723   default:
724     return E_FAIL;
725   }
726 }  /* FormatFirmObject */
727
728 #define SEGMENT_SIZE_SHIFT      8
729 #define SEGMENT_SIZE            (1 << SEGMENT_SIZE_SHIFT)
730 #define DIRECTORY_SIZE_SHIFT    8
731 #define DIRECTORY_SIZE          (1 << DIRECTORY_SIZE_SHIFT)
732 #define MAX_LOAD_FACTOR         4
733
734 typedef struct pset_element {
735   struct pset_element *chain;   /**< for chaining Elements */
736   pset_entry entry;
737 } pset_Element, *pset_Segment;
738
739 /* not visible from outside */
740 struct pset {
741   unsigned p;              /**< Next bucket to be split */
742   unsigned maxp;           /**< upper bound on p during expansion */
743   unsigned nkey;           /**< current # keys */
744   unsigned nseg;           /**< current # segments */
745   pset_Segment *dir[DIRECTORY_SIZE];
746   int (*cmp)();            /**< function comparing entries */
747   unsigned iter_i, iter_j;
748   pset_Element *iter_tail; /**< non-NULL while iterating over elts */
749   pset_Element *free_list; /**< list of free Elements */
750   struct obstack obst;     /**< obstack for allocation all data */
751 };
752
753 typedef struct set_element {
754   struct set_element *chain;    /**< for chaining Elements */
755   set_entry entry;
756 } set_Element, *set_Segment;
757
758 /* not visible from outside */
759 struct set {
760   unsigned p;              /**< Next bucket to be split */
761   unsigned maxp;           /**< upper bound on p during expansion */
762   unsigned nkey;           /**< current # keys */
763   unsigned nseg;           /**< current # segments */
764   set_Segment *dir[DIRECTORY_SIZE];
765   int (*cmp)();            /**< function comparing entries */
766   unsigned iter_i, iter_j;
767   set_Element *iter_tail;  /**< non-NULL while iterating over elts */
768   struct obstack obst;     /**< obstack for allocation all data */
769 };
770
771 /**
772  * Find the longest chain of a pset
773  */
774 static HRESULT find_longest_pset_chain(DEBUGHELPER *pHelper, pset *set,
775                                        int *chains, int *lenght, size_t *size)
776 {
777   unsigned i, j;
778   pset_Segment *seg, *curr;
779   pset_Element elem;
780   void *address;
781   int len, nchains = 0, max_len = 0;
782   size_t dyns = 0;
783
784   for (i = 0; i < set->nseg; ++i) {
785     seg = set->dir[i];
786
787     dyns += sizeof(seg[j]) * SEGMENT_SIZE;
788     for (j = 0; j < SEGMENT_SIZE; ++j) {
789       if (copy_from_debuggee(&seg[j], pHelper, &curr, sizeof(curr)) != S_OK)
790         return E_FAIL;
791
792       address = curr;
793       if (address)
794         ++nchains;
795       for (len = 0; address != NULL; address = elem.chain) {
796         if (copy_from_debuggee(address, pHelper, &elem, sizeof(elem)) != S_OK)
797           return E_FAIL;
798         dyns += sizeof(pset_Element);
799         ++len;
800       }
801       if (len > max_len)
802         max_len = len;
803     }
804   }
805
806   *chains = nchains;
807   *lenght = max_len;
808   *size   = dyns;
809   return S_OK;
810 }  /* find_longest_pset_chain */
811
812 /**
813  * Find the longest chain of a set
814  */
815 static HRESULT find_longest_set_chain(DEBUGHELPER *pHelper, set *set,
816                                       int *chains, int *lenght, size_t *size)
817 {
818   unsigned i, j;
819   set_Segment *seg, *curr;
820   set_Element elem;
821   void *address;
822   int len, nchains = 0, max_len = 0;
823   size_t dyns = 0;
824
825   for (i = 0; i < set->nseg; ++i) {
826     seg = set->dir[i];
827
828     dyns += sizeof(seg[j]) * SEGMENT_SIZE;
829     for (j = 0; j < SEGMENT_SIZE; ++j) {
830       if (copy_from_debuggee(&seg[j], pHelper, &curr, sizeof(curr)) != S_OK)
831           return E_FAIL;
832
833       address = curr;
834       if (address)
835         ++nchains;
836       for (len = 0; address != NULL; address = elem.chain) {
837         if (copy_from_debuggee(address, pHelper, &elem, sizeof(elem)) != S_OK)
838           return E_FAIL;
839         dyns += offsetof(set_Element, entry.dptr) + elem.entry.size;
840         ++len;
841       }
842       if (len > max_len)
843         max_len = len;
844     }
845   }
846
847   *chains = nchains;
848   *lenght = max_len;
849   *size   = dyns;
850   return S_OK;
851 }  /* find_longest_set_chain */
852
853 /*
854  * Format a pset
855  */
856 HRESULT format_pset(DEBUGHELPER *pHelper, int nBase, const void *address, char *pResult, size_t max)
857 {
858   pset set;
859   char name[256];
860   int nchains, chain_len;
861   size_t size;
862
863   if (copy_from_debuggee(address, pHelper, &set, sizeof(set)) != S_OK)
864     return E_FAIL;
865
866   if (find_longest_pset_chain(pHelper, &set, &nchains, &chain_len, &size) != S_OK)
867     return E_FAIL;
868
869   switch (nBase) {
870   case 16:
871     _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);
872     break;
873   case 8:
874     _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);
875     break;
876   default:
877     _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);
878   }
879   _tcsncpy(pResult, name, max);
880
881   return S_OK;
882 }  /* format_pset */
883
884 /*
885  * Format a set
886  */
887 HRESULT format_set(DEBUGHELPER *pHelper, int nBase, const void *address, char *pResult, size_t max)
888 {
889   set set;
890   char name[256];
891   int nchains, chain_len;
892   size_t size;
893
894   if (copy_from_debuggee(address, pHelper, &set, sizeof(set)) != S_OK)
895     return E_FAIL;
896
897   if (find_longest_set_chain(pHelper, &set, &nchains, &chain_len, &size) != S_OK)
898     return E_FAIL;
899
900   switch (nBase) {
901   case 16:
902     _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);
903     break;
904   case 8:
905     _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);
906     break;
907   default:
908     _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);
909   }
910   _tcsncpy(pResult, name, max);
911
912   return S_OK;
913 }  /* format_set */
914
915 struct pdeq {
916   unsigned magic;       /**< debug magic, only available in DEBUG builds */
917   pdeq *l_end, *r_end;  /**< left and right ends of the queue */
918   pdeq *l, *r;          /**< left and right neighbor */
919   int n;                /**< number of elements in the current chunk */
920   int p;                /**< the read/write pointer */
921   const void *data[1];  /**< storage for elements */
922 };
923
924 /** Returns the length of a double ended pointer list. */
925 static int get_pdeq_len(DEBUGHELPER *pHelper, pdeq *dq)
926 {
927   int n;
928   pdeq *q;
929   pdeq pdeq;
930
931   n = 0;
932   q = dq->l_end;
933
934   if (copy_from_debuggee(q, pHelper, &pdeq, sizeof(pdeq)) != S_OK)
935     return -1;
936   q = &pdeq;
937
938   for (;;) {
939     n += q->n;
940     q = q->r;
941     if (! q)
942       break;
943
944     if (copy_from_debuggee(q, pHelper, &pdeq, sizeof(pdeq)) != S_OK)
945       return -1;
946     q = &pdeq;
947   };
948
949   return n;
950 }  /* get_pdeq_len */
951
952 /*
953  * Format a pdeq
954  */
955 HRESULT format_pdeq(DEBUGHELPER *pHelper, int nBase, const void *address, char *pResult, size_t max)
956 {
957   pdeq pdeq;
958   char name[256];
959   int len;
960
961   if (copy_from_debuggee(address, pHelper, &pdeq, sizeof(pdeq)) != S_OK)
962     return E_FAIL;
963
964   len = get_pdeq_len(pHelper, &pdeq);
965   if (len < 0)
966     return E_FAIL;
967
968   switch (nBase) {
969   case 16:
970     _snprintf(name, sizeof(name), "pdeq 0x%x elem", len);
971     break;
972   case 8:
973     _snprintf(name, sizeof(name), "pdeq 0%o elem", len);
974     break;
975   default:
976     _snprintf(name, sizeof(name), "pdeq %d elem", len);
977   }
978   _tcsncpy(pResult, name, max);
979
980   return S_OK;
981 }  /* format_pdeq */
982
983 /** show the first 2 units */
984 static HRESULT fill_bits(DEBUGHELPER *pHelper, bitset_t *bs, char *pResult)
985 {
986   unsigned i, units = bs->size;
987   int l = 0, o = 0, breaked = 0;
988   unsigned j;
989
990   for (i = 0; i < units; ++i) {
991     unsigned data;
992
993     if (copy_from_debuggee((void *)(&bs->data[i]), pHelper, &data, sizeof(data)) != S_OK)
994       return E_FAIL;
995
996     for (j = 0; j < 32; ++j) {
997       if (data & (1 << j)) {
998         sprintf(pResult + l, "%d,", i * sizeof(data) * 8 + j);
999         l += strlen(pResult + l);
1000         ++o;
1001         if (o >= 10) {
1002           breaked = 1;
1003           goto end;
1004         }
1005       }
1006     }
1007   }
1008 end:
1009   if (breaked) {
1010     sprintf(pResult + l, "...");
1011     l += 3;
1012   }
1013   sprintf(pResult + l, "}");
1014   return S_OK;
1015 }  /* fill_bits */
1016
1017 /*
1018  * Format a bitset
1019  */
1020 HRESULT format_bitset(DEBUGHELPER *pHelper, int nBase, const void *address, char *pResult, size_t max)
1021 {
1022   bitset_t bs;
1023   char name[256];
1024   unsigned l;
1025
1026   if (copy_from_debuggee(address, pHelper, &bs, sizeof(bs)) != S_OK)
1027     return E_FAIL;
1028
1029   switch (nBase) {
1030   case 16:
1031     _snprintf(name, sizeof(name), "bitset{0x%x:", bs.size);
1032     break;
1033   case 8:
1034     _snprintf(name, sizeof(name), "bitset{0%o:", bs.size);
1035     break;
1036   default:
1037     _snprintf(name, sizeof(name), "bitset{%u:", bs.size);
1038   }
1039
1040   l = strlen(name);
1041   if (fill_bits(pHelper, &bs, &name[l]) != S_OK)
1042     return E_FAIL;
1043
1044
1045   _tcsncpy(pResult, name, max);
1046
1047   return S_OK;
1048 }  /* format_bitset */