blob: 30f431d3b717fad427bfe0ea560713dce0c8b2f3 [file] [log] [blame]
sewardjb8b79ad2008-03-03 01:35:41 +00001
2/*--------------------------------------------------------------------*/
3/*--- Representation of source level types. tytypes.c ---*/
4/*--------------------------------------------------------------------*/
5
6/*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
9
sewardj0f157dd2013-10-18 14:27:36 +000010 Copyright (C) 2008-2013 OpenWorks LLP
sewardjb8b79ad2008-03-03 01:35:41 +000011 info@open-works.co.uk
12
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29
30 Neither the names of the U.S. Department of Energy nor the
31 University of California nor the names of its contributors may be
32 used to endorse or promote products derived from this software
33 without prior written permission.
34*/
35
36#include "pub_core_basics.h"
tom588658b2009-01-22 13:40:12 +000037#include "pub_core_debuginfo.h"
sewardjb8b79ad2008-03-03 01:35:41 +000038#include "pub_core_libcassert.h"
39#include "pub_core_libcbase.h"
40#include "pub_core_libcprint.h"
41#include "pub_core_xarray.h" /* to keep priv_tytypes.h happy */
42
43#include "priv_misc.h" /* dinfo_zalloc/free/strdup */
44#include "priv_d3basics.h" /* ML_(evaluate_Dwarf3_Expr) et al */
45#include "priv_tytypes.h" /* self */
46
47
sewardj9c606bd2008-09-18 18:12:50 +000048/* Does this TyEnt denote a type, as opposed to some other kind of
49 thing? */
50
51Bool ML_(TyEnt__is_type)( TyEnt* te )
52{
53 switch (te->tag) {
54 case Te_EMPTY: case Te_INDIR: case Te_UNKNOWN:
55 case Te_Atom: case Te_Field: case Te_Bound:
56 return False;
bart0e947cf2012-02-01 14:59:14 +000057 case Te_TyBase: case Te_TyPtr: case Te_TyRef:
58 case Te_TyPtrMbr: case Te_TyRvalRef: case Te_TyTyDef:
59 case Te_TyStOrUn: case Te_TyEnum: case Te_TyArray:
60 case Te_TyFn: case Te_TyQual: case Te_TyVoid:
sewardj9c606bd2008-09-18 18:12:50 +000061 return True;
62 default:
63 vg_assert(0);
64 }
sewardjb8b79ad2008-03-03 01:35:41 +000065}
66
sewardj9c606bd2008-09-18 18:12:50 +000067
68/* Print a TyEnt, debug-style. */
69
70static void pp_XArray_of_cuOffs ( XArray* xa )
71{
72 Word i;
73 VG_(printf)("{");
74 for (i = 0; i < VG_(sizeXA)(xa); i++) {
75 UWord cuOff = *(UWord*)VG_(indexXA)(xa, i);
76 VG_(printf)("0x%05lx", cuOff);
77 if (i+1 < VG_(sizeXA)(xa))
78 VG_(printf)(",");
79 }
80 VG_(printf)("}");
sewardjb8b79ad2008-03-03 01:35:41 +000081}
sewardj9c606bd2008-09-18 18:12:50 +000082
83void ML_(pp_TyEnt)( TyEnt* te )
84{
85 VG_(printf)("0x%05lx ", te->cuOff);
86 switch (te->tag) {
87 case Te_EMPTY:
88 VG_(printf)("EMPTY");
sewardjb8b79ad2008-03-03 01:35:41 +000089 break;
sewardj9c606bd2008-09-18 18:12:50 +000090 case Te_INDIR:
91 VG_(printf)("INDIR(0x%05lx)", te->Te.INDIR.indR);
sewardjb8b79ad2008-03-03 01:35:41 +000092 break;
sewardj9c606bd2008-09-18 18:12:50 +000093 case Te_UNKNOWN:
94 VG_(printf)("UNKNOWN");
sewardjb8b79ad2008-03-03 01:35:41 +000095 break;
sewardj9c606bd2008-09-18 18:12:50 +000096 case Te_Atom:
sewardjf3aaa332008-10-23 10:54:40 +000097 VG_(printf)("Te_Atom(%s%lld,\"%s\")",
98 te->Te.Atom.valueKnown ? "" : "unknown:",
sewardj9c606bd2008-09-18 18:12:50 +000099 te->Te.Atom.value, te->Te.Atom.name);
sewardjb8b79ad2008-03-03 01:35:41 +0000100 break;
sewardj9c606bd2008-09-18 18:12:50 +0000101 case Te_Field:
tom3c9cf342009-11-12 13:28:34 +0000102 if (te->Te.Field.nLoc == -1)
103 VG_(printf)("Te_Field(ty=0x%05lx,pos.offset=%ld,\"%s\")",
104 te->Te.Field.typeR, te->Te.Field.pos.offset,
florian1636d332012-11-15 04:27:04 +0000105 te->Te.Field.name ? te->Te.Field.name : "");
tom3c9cf342009-11-12 13:28:34 +0000106 else
107 VG_(printf)("Te_Field(ty=0x%05lx,nLoc=%lu,pos.loc=%p,\"%s\")",
108 te->Te.Field.typeR, te->Te.Field.nLoc,
109 te->Te.Field.pos.loc,
florian1636d332012-11-15 04:27:04 +0000110 te->Te.Field.name ? te->Te.Field.name : "");
sewardjb8b79ad2008-03-03 01:35:41 +0000111 break;
sewardj9c606bd2008-09-18 18:12:50 +0000112 case Te_Bound:
113 VG_(printf)("Te_Bound[");
114 if (te->Te.Bound.knownL)
115 VG_(printf)("%lld", te->Te.Bound.boundL);
116 else
117 VG_(printf)("??");
118 VG_(printf)(",");
119 if (te->Te.Bound.knownU)
120 VG_(printf)("%lld", te->Te.Bound.boundU);
121 else
122 VG_(printf)("??");
123 VG_(printf)("]");
sewardjb8b79ad2008-03-03 01:35:41 +0000124 break;
sewardj9c606bd2008-09-18 18:12:50 +0000125 case Te_TyBase:
126 VG_(printf)("Te_TyBase(%d,%c,\"%s\")",
127 te->Te.TyBase.szB, te->Te.TyBase.enc,
128 te->Te.TyBase.name ? te->Te.TyBase.name
florian1636d332012-11-15 04:27:04 +0000129 : "(null)" );
sewardjb8b79ad2008-03-03 01:35:41 +0000130 break;
bart0e947cf2012-02-01 14:59:14 +0000131 case Te_TyPtr:
132 VG_(printf)("Te_TyPtr(%d,0x%05lx)", te->Te.TyPorR.szB,
133 te->Te.TyPorR.typeR);
134 break;
135 case Te_TyRef:
136 VG_(printf)("Te_TyRef(%d,0x%05lx)", te->Te.TyPorR.szB,
137 te->Te.TyPorR.typeR);
138 break;
139 case Te_TyPtrMbr:
140 VG_(printf)("Te_TyMbr(%d,0x%05lx)", te->Te.TyPorR.szB,
141 te->Te.TyPorR.typeR);
142 break;
143 case Te_TyRvalRef:
144 VG_(printf)("Te_TyRvalRef(%d,0x%05lx)", te->Te.TyPorR.szB,
sewardj9c606bd2008-09-18 18:12:50 +0000145 te->Te.TyPorR.typeR);
sewardjb8b79ad2008-03-03 01:35:41 +0000146 break;
sewardj9c606bd2008-09-18 18:12:50 +0000147 case Te_TyTyDef:
148 VG_(printf)("Te_TyTyDef(0x%05lx,\"%s\")",
149 te->Te.TyTyDef.typeR,
150 te->Te.TyTyDef.name ? te->Te.TyTyDef.name
florian1636d332012-11-15 04:27:04 +0000151 : "" );
sewardj9c606bd2008-09-18 18:12:50 +0000152 break;
153 case Te_TyStOrUn:
154 if (te->Te.TyStOrUn.complete) {
155 VG_(printf)("Te_TyStOrUn(%ld,%c,%p,\"%s\")",
156 te->Te.TyStOrUn.szB,
157 te->Te.TyStOrUn.isStruct ? 'S' : 'U',
158 te->Te.TyStOrUn.fieldRs,
159 te->Te.TyStOrUn.name ? te->Te.TyStOrUn.name
florian1636d332012-11-15 04:27:04 +0000160 : "" );
sewardj9c606bd2008-09-18 18:12:50 +0000161 if (te->Te.TyStOrUn.fieldRs)
162 pp_XArray_of_cuOffs( te->Te.TyStOrUn.fieldRs );
163 } else {
164 VG_(printf)("Te_TyStOrUn(INCOMPLETE,\"%s\")",
165 te->Te.TyStOrUn.name);
166 }
167 break;
168 case Te_TyEnum:
169 VG_(printf)("Te_TyEnum(%d,%p,\"%s\")",
170 te->Te.TyEnum.szB, te->Te.TyEnum.atomRs,
171 te->Te.TyEnum.name ? te->Te.TyEnum.name
florian1636d332012-11-15 04:27:04 +0000172 : "" );
sewardj9c606bd2008-09-18 18:12:50 +0000173 if (te->Te.TyEnum.atomRs)
174 pp_XArray_of_cuOffs( te->Te.TyEnum.atomRs );
175 break;
176 case Te_TyArray:
177 VG_(printf)("Te_TyArray(0x%05lx,%p)",
178 te->Te.TyArray.typeR, te->Te.TyArray.boundRs);
179 if (te->Te.TyArray.boundRs)
180 pp_XArray_of_cuOffs( te->Te.TyArray.boundRs );
181 break;
182 case Te_TyFn:
183 VG_(printf)("Te_TyFn");
184 break;
185 case Te_TyQual:
186 VG_(printf)("Te_TyQual(%c,0x%05lx)", te->Te.TyQual.qual,
187 te->Te.TyQual.typeR);
188 break;
189 case Te_TyVoid:
190 VG_(printf)("Te_TyVoid%s",
191 te->Te.TyVoid.isFake ? "(fake)" : "");
sewardjb8b79ad2008-03-03 01:35:41 +0000192 break;
193 default:
194 vg_assert(0);
195 }
196}
197
sewardj9c606bd2008-09-18 18:12:50 +0000198
199/* Print a whole XArray of TyEnts, debug-style */
200
florian6bd9dc12012-11-23 16:17:43 +0000201void ML_(pp_TyEnts)( XArray* tyents, const HChar* who )
sewardj9c606bd2008-09-18 18:12:50 +0000202{
203 Word i, n;
204 VG_(printf)("------ %s ------\n", who);
205 n = VG_(sizeXA)( tyents );
206 for (i = 0; i < n; i++) {
207 TyEnt* tyent = (TyEnt*)VG_(indexXA)( tyents, i );
208 VG_(printf)(" [%5ld] ", i);
209 ML_(pp_TyEnt)( tyent );
210 VG_(printf)("\n");
sewardjb8b79ad2008-03-03 01:35:41 +0000211 }
sewardjb8b79ad2008-03-03 01:35:41 +0000212}
213
214
sewardj9c606bd2008-09-18 18:12:50 +0000215/* Print a TyEnt, C style, chasing stuff as necessary. */
sewardjb8b79ad2008-03-03 01:35:41 +0000216
sewardj9c606bd2008-09-18 18:12:50 +0000217static void pp_TyBound_C_ishly ( XArray* tyents, UWord cuOff )
218{
219 TyEnt* ent = ML_(TyEnts__index_by_cuOff)( tyents, NULL, cuOff );
220 if (!ent) {
221 VG_(printf)("**bounds-have-invalid-cuOff**");
222 return;
223 }
224 vg_assert(ent->tag == Te_Bound);
225 if (ent->Te.Bound.knownL && ent->Te.Bound.knownU
226 && ent->Te.Bound.boundL == 0) {
227 VG_(printf)("[%lld]", 1 + ent->Te.Bound.boundU);
sewardjb8b79ad2008-03-03 01:35:41 +0000228 }
229 else
sewardj9c606bd2008-09-18 18:12:50 +0000230 if (ent->Te.Bound.knownL && (!ent->Te.Bound.knownU)
231 && ent->Te.Bound.boundL == 0) {
sewardjb8b79ad2008-03-03 01:35:41 +0000232 VG_(printf)("[]");
233 }
234 else
sewardj9c606bd2008-09-18 18:12:50 +0000235 ML_(pp_TyEnt)( ent );
sewardjb8b79ad2008-03-03 01:35:41 +0000236}
237
sewardj9c606bd2008-09-18 18:12:50 +0000238void ML_(pp_TyEnt_C_ishly)( XArray* /* of TyEnt */ tyents,
239 UWord cuOff )
sewardjb8b79ad2008-03-03 01:35:41 +0000240{
sewardj9c606bd2008-09-18 18:12:50 +0000241 TyEnt* ent = ML_(TyEnts__index_by_cuOff)( tyents, NULL, cuOff );
242 if (!ent) {
243 VG_(printf)("**type-has-invalid-cuOff**");
sewardjb8b79ad2008-03-03 01:35:41 +0000244 return;
245 }
sewardj9c606bd2008-09-18 18:12:50 +0000246 switch (ent->tag) {
247 case Te_TyBase:
248 if (!ent->Te.TyBase.name) goto unhandled;
249 VG_(printf)("%s", ent->Te.TyBase.name);
sewardjb8b79ad2008-03-03 01:35:41 +0000250 break;
bart0e947cf2012-02-01 14:59:14 +0000251 case Te_TyPtr:
sewardj9c606bd2008-09-18 18:12:50 +0000252 ML_(pp_TyEnt_C_ishly)(tyents, ent->Te.TyPorR.typeR);
bart0e947cf2012-02-01 14:59:14 +0000253 VG_(printf)("*");
254 break;
255 case Te_TyRef:
256 ML_(pp_TyEnt_C_ishly)(tyents, ent->Te.TyPorR.typeR);
257 VG_(printf)("&");
258 break;
259 case Te_TyPtrMbr:
260 ML_(pp_TyEnt_C_ishly)(tyents, ent->Te.TyPorR.typeR);
261 VG_(printf)("*");
262 break;
263 case Te_TyRvalRef:
264 ML_(pp_TyEnt_C_ishly)(tyents, ent->Te.TyPorR.typeR);
265 VG_(printf)("&&");
sewardjb8b79ad2008-03-03 01:35:41 +0000266 break;
sewardj9c606bd2008-09-18 18:12:50 +0000267 case Te_TyEnum:
mjwe5cf4512013-11-24 17:19:35 +0000268 VG_(printf)("enum %s", ent->Te.TyEnum.name ? ent->Te.TyEnum.name
269 : "<anonymous>" );
sewardjb8b79ad2008-03-03 01:35:41 +0000270 break;
sewardj9c606bd2008-09-18 18:12:50 +0000271 case Te_TyStOrUn:
sewardjb8b79ad2008-03-03 01:35:41 +0000272 VG_(printf)("%s %s",
sewardj9c606bd2008-09-18 18:12:50 +0000273 ent->Te.TyStOrUn.isStruct ? "struct" : "union",
sewardj50fde232008-10-20 16:08:55 +0000274 ent->Te.TyStOrUn.name ? ent->Te.TyStOrUn.name
florian1636d332012-11-15 04:27:04 +0000275 : "<anonymous>" );
sewardjb8b79ad2008-03-03 01:35:41 +0000276 break;
sewardj9c606bd2008-09-18 18:12:50 +0000277 case Te_TyArray:
278 ML_(pp_TyEnt_C_ishly)(tyents, ent->Te.TyArray.typeR);
279 if (ent->Te.TyArray.boundRs) {
sewardjb8b79ad2008-03-03 01:35:41 +0000280 Word w;
sewardj9c606bd2008-09-18 18:12:50 +0000281 XArray* xa = ent->Te.TyArray.boundRs;
sewardjb8b79ad2008-03-03 01:35:41 +0000282 for (w = 0; w < VG_(sizeXA)(xa); w++) {
sewardj9c606bd2008-09-18 18:12:50 +0000283 pp_TyBound_C_ishly( tyents, *(UWord*)VG_(indexXA)(xa, w) );
sewardjb8b79ad2008-03-03 01:35:41 +0000284 }
285 } else {
286 VG_(printf)("%s", "[??]");
287 }
288 break;
sewardj9c606bd2008-09-18 18:12:50 +0000289 case Te_TyTyDef:
mjwe5cf4512013-11-24 17:19:35 +0000290 VG_(printf)("%s", ent->Te.TyTyDef.name ? ent->Te.TyTyDef.name
291 : "<anonymous>" );
sewardjb8b79ad2008-03-03 01:35:41 +0000292 break;
sewardj9c606bd2008-09-18 18:12:50 +0000293 case Te_TyFn:
sewardjb8b79ad2008-03-03 01:35:41 +0000294 VG_(printf)("%s", "<function_type>");
295 break;
sewardj9c606bd2008-09-18 18:12:50 +0000296 case Te_TyQual:
297 switch (ent->Te.TyQual.qual) {
sewardjb8b79ad2008-03-03 01:35:41 +0000298 case 'C': VG_(printf)("const "); break;
299 case 'V': VG_(printf)("volatile "); break;
300 default: goto unhandled;
301 }
sewardj9c606bd2008-09-18 18:12:50 +0000302 ML_(pp_TyEnt_C_ishly)(tyents, ent->Te.TyQual.typeR);
sewardjb8b79ad2008-03-03 01:35:41 +0000303 break;
sewardj9c606bd2008-09-18 18:12:50 +0000304 case Te_TyVoid:
sewardjb8b79ad2008-03-03 01:35:41 +0000305 VG_(printf)("%svoid",
sewardj9c606bd2008-09-18 18:12:50 +0000306 ent->Te.TyVoid.isFake ? "fake" : "");
sewardjb8b79ad2008-03-03 01:35:41 +0000307 break;
sewardj50fde232008-10-20 16:08:55 +0000308 case Te_UNKNOWN:
309 ML_(pp_TyEnt)(ent);
310 break;
sewardj9c606bd2008-09-18 18:12:50 +0000311 default:
312 goto unhandled;
sewardjb8b79ad2008-03-03 01:35:41 +0000313 }
314 return;
315
316 unhandled:
sewardj9c606bd2008-09-18 18:12:50 +0000317 VG_(printf)("pp_TyEnt_C_ishly:unhandled: ");
318 ML_(pp_TyEnt)(ent);
319 vg_assert(0);
sewardjb8b79ad2008-03-03 01:35:41 +0000320}
321
322
sewardj9c606bd2008-09-18 18:12:50 +0000323/* 'ents' is an XArray of TyEnts, sorted by their .cuOff fields. Find
324 the entry which has .cuOff field as specified. Returns NULL if not
325 found. Asserts if more than one entry has the specified .cuOff
326 value. */
327
328void ML_(TyEntIndexCache__invalidate) ( TyEntIndexCache* cache )
329{
330 Word i;
331 for (i = 0; i < N_TYENT_INDEX_CACHE; i++) {
332 cache->ce[i].cuOff0 = 0; /* not actually necessary */
333 cache->ce[i].ent0 = NULL; /* "invalid entry" */
334 cache->ce[i].cuOff1 = 0; /* not actually necessary */
335 cache->ce[i].ent1 = NULL; /* "invalid entry" */
336 }
337}
338
339TyEnt* ML_(TyEnts__index_by_cuOff) ( XArray* /* of TyEnt */ ents,
340 TyEntIndexCache* cache,
341 UWord cuOff_to_find )
342{
343 Bool found;
344 Word first, last;
345 TyEnt key, *res;
346
347 /* crude stats, aggregated over all caches */
348 static UWord cacheQs = 0 - 1;
349 static UWord cacheHits = 0;
350
351 if (0 && 0 == (cacheQs & 0xFFFF))
352 VG_(printf)("cache: %'lu queries, %'lu misses\n",
353 cacheQs, cacheQs - cacheHits);
354
355 if (LIKELY(cache != NULL)) {
356 UWord h = cuOff_to_find % (UWord)N_TYENT_INDEX_CACHE;
357 cacheQs++;
358 // dude, like, way 0, dude.
359 if (cache->ce[h].cuOff0 == cuOff_to_find && cache->ce[h].ent0 != NULL) {
360 // dude, way 0 is a total hit!
361 cacheHits++;
362 return cache->ce[h].ent0;
363 }
364 // dude, check out way 1, dude.
365 if (cache->ce[h].cuOff1 == cuOff_to_find && cache->ce[h].ent1 != NULL) {
366 // way 1 hit
367 UWord tc;
368 TyEnt* te;
369 cacheHits++;
370 // dude, way 1 is the new way 0. move with the times, dude.
371 tc = cache->ce[h].cuOff0;
372 te = cache->ce[h].ent0;
373 cache->ce[h].cuOff0 = cache->ce[h].cuOff1;
374 cache->ce[h].ent0 = cache->ce[h].ent1;
375 cache->ce[h].cuOff1 = tc;
376 cache->ce[h].ent1 = te;
377 return cache->ce[h].ent0;
378 }
379 }
380
381 /* We'll have to do it the hard way */
382 key.cuOff = cuOff_to_find;
383 key.tag = Te_EMPTY;
384 found = VG_(lookupXA)( ents, &key, &first, &last );
385 //found = VG_(lookupXA_UNBOXED)( ents, cuOff_to_find, &first, &last,
386 // offsetof(TyEnt,cuOff) );
387 if (!found)
388 return NULL;
389 /* If this fails, the array is invalid in the sense that there is
390 more than one entry with .cuOff == cuOff_to_find. */
391 vg_assert(first == last);
392 res = (TyEnt*)VG_(indexXA)( ents, first );
393
394 if (LIKELY(cache != NULL) && LIKELY(res != NULL)) {
395 /* this is a bit stupid, computing this twice. Oh well.
396 Perhaps some magic gcc transformation will common them up.
397 re "res != NULL", since .ent of NULL denotes 'invalid entry',
398 we can't cache the result when res == NULL. */
399 UWord h = cuOff_to_find % (UWord)N_TYENT_INDEX_CACHE;
400 cache->ce[h].cuOff1 = cache->ce[h].cuOff0;
401 cache->ce[h].ent1 = cache->ce[h].ent0;
402 cache->ce[h].cuOff0 = cuOff_to_find;
403 cache->ce[h].ent0 = res;
404 }
405
406 return res;
407}
408
409
410/* Generates a total ordering on TyEnts based only on their .cuOff
411 fields. */
412
florian6bd9dc12012-11-23 16:17:43 +0000413Word ML_(TyEnt__cmp_by_cuOff_only) ( const TyEnt* te1, const TyEnt* te2 )
sewardj9c606bd2008-09-18 18:12:50 +0000414{
415 if (te1->cuOff < te2->cuOff) return -1;
416 if (te1->cuOff > te2->cuOff) return 1;
417 return 0;
418}
419
420
421/* Generates a total ordering on TyEnts based on everything except
422 their .cuOff fields. */
sewardjc961d362012-03-31 00:06:04 +0000423static inline Word UWord__cmp ( UWord a, UWord b ) {
sewardj9c606bd2008-09-18 18:12:50 +0000424 if (a < b) return -1;
425 if (a > b) return 1;
426 return 0;
427}
sewardjc961d362012-03-31 00:06:04 +0000428static inline Word Long__cmp ( Long a, Long b ) {
sewardj9c606bd2008-09-18 18:12:50 +0000429 if (a < b) return -1;
430 if (a > b) return 1;
431 return 0;
432}
sewardjc961d362012-03-31 00:06:04 +0000433static inline Word Bool__cmp ( Bool a, Bool b ) {
sewardj9c606bd2008-09-18 18:12:50 +0000434 vg_assert( ((UWord)a) <= 1 );
435 vg_assert( ((UWord)b) <= 1 );
436 if (a < b) return -1;
437 if (a > b) return 1;
438 return 0;
439}
sewardjc961d362012-03-31 00:06:04 +0000440static inline Word UChar__cmp ( UChar a, UChar b ) {
sewardj9c606bd2008-09-18 18:12:50 +0000441 if (a < b) return -1;
442 if (a > b) return 1;
443 return 0;
444}
sewardjc961d362012-03-31 00:06:04 +0000445static inline Word Int__cmp ( Int a, Int b ) {
sewardj9c606bd2008-09-18 18:12:50 +0000446 if (a < b) return -1;
447 if (a > b) return 1;
448 return 0;
449}
450static Word XArray_of_UWord__cmp ( XArray* a, XArray* b ) {
451 Word i, r;
452 Word aN = VG_(sizeXA)( a );
453 Word bN = VG_(sizeXA)( b );
454 if (aN < bN) return -1;
455 if (aN > bN) return 1;
456 for (i = 0; i < aN; i++) {
457 r = UWord__cmp( *(UWord*)VG_(indexXA)( a, i ),
458 *(UWord*)VG_(indexXA)( b, i ) );
459 if (r != 0) return r;
460 }
461 return 0;
462}
463static Word Bytevector__cmp ( UChar* a, UChar* b, Word n ) {
464 Word i, r;
465 vg_assert(n >= 0);
466 for (i = 0; i < n; i++) {
467 r = UChar__cmp( a[i], b[i] );
468 if (r != 0) return r;
469 }
470 return 0;
471}
florian1636d332012-11-15 04:27:04 +0000472static Word Asciiz__cmp ( const HChar* a, const HChar* b ) {
sewardj9c606bd2008-09-18 18:12:50 +0000473 /* A wrapper around strcmp that handles NULL strings safely. */
474 if (a == NULL && b == NULL) return 0;
475 if (a == NULL && b != NULL) return -1;
476 if (a != NULL && b == NULL) return 1;
477 return VG_(strcmp)(a, b);
478}
479
florian6bd9dc12012-11-23 16:17:43 +0000480Word ML_(TyEnt__cmp_by_all_except_cuOff) ( const TyEnt* te1, const TyEnt* te2 )
sewardj9c606bd2008-09-18 18:12:50 +0000481{
482 Word r;
483 if (te1->tag < te2->tag) return -1;
484 if (te1->tag > te2->tag) return 1;
485 switch (te1->tag) {
486 case Te_EMPTY:
487 return 0;
488 case Te_INDIR:
489 r = UWord__cmp(te1->Te.INDIR.indR, te2->Te.INDIR.indR);
490 return r;
491 case Te_Atom:
sewardjf3aaa332008-10-23 10:54:40 +0000492 r = Bool__cmp(te1->Te.Atom.valueKnown, te2->Te.Atom.valueKnown);
493 if (r != 0) return r;
sewardj9c606bd2008-09-18 18:12:50 +0000494 r = Long__cmp(te1->Te.Atom.value, te2->Te.Atom.value);
495 if (r != 0) return r;
496 r = Asciiz__cmp(te1->Te.Atom.name, te2->Te.Atom.name);
497 return r;
498 case Te_Field:
499 r = Bool__cmp(te1->Te.Field.isStruct, te2->Te.Field.isStruct);
500 if (r != 0) return r;
501 r = UWord__cmp(te1->Te.Field.typeR, te2->Te.Field.typeR);
502 if (r != 0) return r;
503 r = Asciiz__cmp(te1->Te.Field.name, te2->Te.Field.name);
504 if (r != 0) return r;
505 r = UWord__cmp(te1->Te.Field.nLoc, te2->Te.Field.nLoc);
506 if (r != 0) return r;
tom3c9cf342009-11-12 13:28:34 +0000507 if (te1->Te.Field.nLoc == -1)
508 r = Long__cmp(te1->Te.Field.pos.offset, te2->Te.Field.pos.offset);
509 else
510 r = Bytevector__cmp(te1->Te.Field.pos.loc, te2->Te.Field.pos.loc,
511 te1->Te.Field.nLoc);
sewardj9c606bd2008-09-18 18:12:50 +0000512 return r;
513 case Te_Bound:
514 r = Bool__cmp(te1->Te.Bound.knownL, te2->Te.Bound.knownL);
515 if (r != 0) return r;
516 r = Bool__cmp(te1->Te.Bound.knownU, te2->Te.Bound.knownU);
517 if (r != 0) return r;
518 r = Long__cmp(te1->Te.Bound.boundL, te2->Te.Bound.boundL);
519 if (r != 0) return r;
520 r = Long__cmp(te1->Te.Bound.boundU, te2->Te.Bound.boundU);
521 return r;
522 case Te_TyBase:
523 r = UChar__cmp(te1->Te.TyBase.enc, te2->Te.TyBase.enc);
524 if (r != 0) return r;
525 r = Int__cmp(te1->Te.TyBase.szB, te2->Te.TyBase.szB);
526 if (r != 0) return r;
527 r = Asciiz__cmp(te1->Te.TyBase.name, te2->Te.TyBase.name);
528 return r;
bart0e947cf2012-02-01 14:59:14 +0000529 case Te_TyPtr:
530 case Te_TyRef:
531 case Te_TyPtrMbr:
532 case Te_TyRvalRef:
sewardj9c606bd2008-09-18 18:12:50 +0000533 r = Int__cmp(te1->Te.TyPorR.szB, te2->Te.TyPorR.szB);
534 if (r != 0) return r;
535 r = UWord__cmp(te1->Te.TyPorR.typeR, te2->Te.TyPorR.typeR);
sewardj9c606bd2008-09-18 18:12:50 +0000536 return r;
537 case Te_TyTyDef:
538 r = UWord__cmp(te1->Te.TyTyDef.typeR, te2->Te.TyTyDef.typeR);
539 if (r != 0) return r;
540 r = Asciiz__cmp(te1->Te.TyTyDef.name, te2->Te.TyTyDef.name);
541 return r;
542 case Te_TyStOrUn:
543 r = Bool__cmp(te1->Te.TyStOrUn.isStruct, te2->Te.TyStOrUn.isStruct);
544 if (r != 0) return r;
545 r = Bool__cmp(te1->Te.TyStOrUn.complete, te2->Te.TyStOrUn.complete);
546 if (r != 0) return r;
547 r = UWord__cmp(te1->Te.TyStOrUn.szB, te2->Te.TyStOrUn.szB);
548 if (r != 0) return r;
549 r = Asciiz__cmp(te1->Te.TyStOrUn.name, te2->Te.TyStOrUn.name);
550 if (r != 0) return r;
551 r = XArray_of_UWord__cmp(te1->Te.TyStOrUn.fieldRs,
552 te2->Te.TyStOrUn.fieldRs);
553 return r;
554 case Te_TyEnum:
555 r = Int__cmp(te1->Te.TyEnum.szB, te2->Te.TyEnum.szB);
556 if (r != 0) return r;
557 r = Asciiz__cmp(te1->Te.TyEnum.name, te2->Te.TyEnum.name);
558 if (r != 0) return r;
559 r = XArray_of_UWord__cmp(te1->Te.TyEnum.atomRs, te2->Te.TyEnum.atomRs);
560 return r;
561 case Te_TyArray:
562 r = UWord__cmp(te1->Te.TyArray.typeR, te2->Te.TyArray.typeR);
563 if (r != 0) return r;
564 r = XArray_of_UWord__cmp(te1->Te.TyArray.boundRs,
565 te2->Te.TyArray.boundRs);
566 return r;
567 case Te_TyFn:
568 return 0;
569 case Te_TyQual:
570 r = UWord__cmp(te1->Te.TyQual.typeR, te2->Te.TyQual.typeR);
571 if (r != 0) return r;
572 r = UChar__cmp(te1->Te.TyQual.qual, te2->Te.TyQual.qual);
573 return r;
574 case Te_TyVoid:
575 r = Bool__cmp(te1->Te.TyVoid.isFake, te2->Te.TyVoid.isFake);
576 return r;
577 default:
578 vg_assert(0);
579 }
580}
581
582
583/* Free up all directly or indirectly heap-allocated stuff attached to
584 this TyEnt, and set its tag to Te_EMPTY. The .cuOff field is
585 unchanged. */
586
587void ML_(TyEnt__make_EMPTY) ( TyEnt* te )
588{
589 UWord saved_cuOff;
590 /* First, free up any fields in mallocville. */
591 switch (te->tag) {
592 case Te_EMPTY:
593 break;
594 case Te_INDIR:
595 break;
596 case Te_UNKNOWN:
597 break;
598 case Te_Atom:
599 if (te->Te.Atom.name) ML_(dinfo_free)(te->Te.Atom.name);
600 break;
601 case Te_Field:
602 if (te->Te.Field.name) ML_(dinfo_free)(te->Te.Field.name);
tom3c9cf342009-11-12 13:28:34 +0000603 if (te->Te.Field.nLoc > 0 && te->Te.Field.pos.loc)
604 ML_(dinfo_free)(te->Te.Field.pos.loc);
sewardj9c606bd2008-09-18 18:12:50 +0000605 break;
606 case Te_Bound:
607 break;
608 case Te_TyBase:
609 if (te->Te.TyBase.name) ML_(dinfo_free)(te->Te.TyBase.name);
610 break;
bart0e947cf2012-02-01 14:59:14 +0000611 case Te_TyPtr:
612 case Te_TyRef:
613 case Te_TyPtrMbr:
614 case Te_TyRvalRef:
sewardj9c606bd2008-09-18 18:12:50 +0000615 break;
616 case Te_TyTyDef:
617 if (te->Te.TyTyDef.name) ML_(dinfo_free)(te->Te.TyTyDef.name);
618 break;
619 case Te_TyStOrUn:
620 if (te->Te.TyStOrUn.name) ML_(dinfo_free)(te->Te.TyStOrUn.name);
621 if (te->Te.TyStOrUn.fieldRs) VG_(deleteXA)(te->Te.TyStOrUn.fieldRs);
622 break;
623 case Te_TyEnum:
624 if (te->Te.TyEnum.name) ML_(dinfo_free)(te->Te.TyEnum.name);
625 if (te->Te.TyEnum.atomRs) VG_(deleteXA)(te->Te.TyEnum.atomRs);
626 break;
627 case Te_TyArray:
628 if (te->Te.TyArray.boundRs) VG_(deleteXA)(te->Te.TyArray.boundRs);
629 break;
630 case Te_TyFn:
631 break;
632 case Te_TyQual:
633 break;
634 case Te_TyVoid:
635 break;
636 default:
637 vg_assert(0);
638 }
639 /* Now clear it out and set to Te_EMPTY. */
640 saved_cuOff = te->cuOff;
641 VG_(memset)(te, 0, sizeof(*te));
642 te->cuOff = saved_cuOff;
643 te->tag = Te_EMPTY;
644}
645
646
647/* How big is this type? If .b in the returned struct is False, the
648 size is unknown. */
649
sewardj50fde232008-10-20 16:08:55 +0000650static MaybeULong mk_MaybeULong_Nothing ( void ) {
651 MaybeULong mul;
652 mul.ul = 0;
653 mul.b = False;
654 return mul;
sewardjb8b79ad2008-03-03 01:35:41 +0000655}
sewardj50fde232008-10-20 16:08:55 +0000656static MaybeULong mk_MaybeULong_Just ( ULong ul ) {
657 MaybeULong mul;
658 mul.ul = ul;
659 mul.b = True;
660 return mul;
sewardjb8b79ad2008-03-03 01:35:41 +0000661}
sewardj50fde232008-10-20 16:08:55 +0000662static MaybeULong mul_MaybeULong ( MaybeULong mul1, MaybeULong mul2 ) {
663 if (!mul1.b) { vg_assert(mul1.ul == 0); return mul1; }
664 if (!mul2.b) { vg_assert(mul2.ul == 0); return mul2; }
665 mul1.ul *= mul2.ul;
666 return mul1;
sewardjb8b79ad2008-03-03 01:35:41 +0000667}
668
sewardj50fde232008-10-20 16:08:55 +0000669MaybeULong ML_(sizeOfType)( XArray* /* of TyEnt */ tyents,
sewardj9c606bd2008-09-18 18:12:50 +0000670 UWord cuOff )
sewardjb8b79ad2008-03-03 01:35:41 +0000671{
672 Word i;
sewardj50fde232008-10-20 16:08:55 +0000673 MaybeULong eszB;
sewardj9c606bd2008-09-18 18:12:50 +0000674 TyEnt* ent = ML_(TyEnts__index_by_cuOff)(tyents, NULL, cuOff);
675 TyEnt* ent2;
676 vg_assert(ent);
677 vg_assert(ML_(TyEnt__is_type)(ent));
678 switch (ent->tag) {
679 case Te_TyBase:
680 vg_assert(ent->Te.TyBase.szB > 0);
sewardj50fde232008-10-20 16:08:55 +0000681 return mk_MaybeULong_Just( ent->Te.TyBase.szB );
sewardj9c606bd2008-09-18 18:12:50 +0000682 case Te_TyQual:
683 return ML_(sizeOfType)( tyents, ent->Te.TyQual.typeR );
684 case Te_TyTyDef:
685 ent2 = ML_(TyEnts__index_by_cuOff)(tyents, NULL,
686 ent->Te.TyTyDef.typeR);
687 vg_assert(ent2);
688 if (ent2->tag == Te_UNKNOWN)
sewardj50fde232008-10-20 16:08:55 +0000689 return mk_MaybeULong_Nothing(); /*UNKNOWN*/
sewardj9c606bd2008-09-18 18:12:50 +0000690 return ML_(sizeOfType)( tyents, ent->Te.TyTyDef.typeR );
bart0e947cf2012-02-01 14:59:14 +0000691 case Te_TyPtr:
692 case Te_TyRef:
693 case Te_TyPtrMbr:
694 case Te_TyRvalRef:
sewardj9c606bd2008-09-18 18:12:50 +0000695 vg_assert(ent->Te.TyPorR.szB == 4 || ent->Te.TyPorR.szB == 8);
sewardj50fde232008-10-20 16:08:55 +0000696 return mk_MaybeULong_Just( ent->Te.TyPorR.szB );
sewardj9c606bd2008-09-18 18:12:50 +0000697 case Te_TyStOrUn:
698 return ent->Te.TyStOrUn.complete
sewardj50fde232008-10-20 16:08:55 +0000699 ? mk_MaybeULong_Just( ent->Te.TyStOrUn.szB )
700 : mk_MaybeULong_Nothing();
sewardj9c606bd2008-09-18 18:12:50 +0000701 case Te_TyEnum:
sewardj50fde232008-10-20 16:08:55 +0000702 return mk_MaybeULong_Just( ent->Te.TyEnum.szB );
sewardj9c606bd2008-09-18 18:12:50 +0000703 case Te_TyArray:
704 ent2 = ML_(TyEnts__index_by_cuOff)(tyents, NULL,
705 ent->Te.TyArray.typeR);
706 vg_assert(ent2);
707 if (ent2->tag == Te_UNKNOWN)
sewardj50fde232008-10-20 16:08:55 +0000708 return mk_MaybeULong_Nothing(); /*UNKNOWN*/
sewardj9c606bd2008-09-18 18:12:50 +0000709 eszB = ML_(sizeOfType)( tyents, ent->Te.TyArray.typeR );
710 for (i = 0; i < VG_(sizeXA)( ent->Te.TyArray.boundRs ); i++) {
711 UWord bo_cuOff
712 = *(UWord*)VG_(indexXA)(ent->Te.TyArray.boundRs, i);
713 TyEnt* bo
714 = ML_(TyEnts__index_by_cuOff)( tyents, NULL, bo_cuOff );
sewardjb8b79ad2008-03-03 01:35:41 +0000715 vg_assert(bo);
sewardj9c606bd2008-09-18 18:12:50 +0000716 vg_assert(bo->tag == Te_Bound);
717 if (!(bo->Te.Bound.knownL && bo->Te.Bound.knownU))
sewardj50fde232008-10-20 16:08:55 +0000718 return mk_MaybeULong_Nothing(); /*UNKNOWN*/
719 eszB = mul_MaybeULong(
sewardjb8b79ad2008-03-03 01:35:41 +0000720 eszB,
sewardj50fde232008-10-20 16:08:55 +0000721 mk_MaybeULong_Just( (ULong)(bo->Te.Bound.boundU
722 - bo->Te.Bound.boundL + 1) ));
sewardjb8b79ad2008-03-03 01:35:41 +0000723 }
724 return eszB;
sewardjbdee9182010-10-08 23:57:25 +0000725 case Te_TyVoid:
726 return mk_MaybeULong_Nothing(); /*UNKNOWN*/
sewardjb8b79ad2008-03-03 01:35:41 +0000727 default:
728 VG_(printf)("ML_(sizeOfType): unhandled: ");
sewardj9c606bd2008-09-18 18:12:50 +0000729 ML_(pp_TyEnt)(ent);
sewardjb8b79ad2008-03-03 01:35:41 +0000730 VG_(printf)("\n");
731 vg_assert(0);
732 }
733}
734
735
sewardj9c606bd2008-09-18 18:12:50 +0000736/* Describe where in the type 'offset' falls. Caller must
737 deallocate the resulting XArray. */
738
florian1636d332012-11-15 04:27:04 +0000739static void copy_UWord_into_XA ( XArray* /* of HChar */ xa,
sewardjb8b79ad2008-03-03 01:35:41 +0000740 UWord uw ) {
florian1636d332012-11-15 04:27:04 +0000741 HChar buf[32];
sewardjb8b79ad2008-03-03 01:35:41 +0000742 VG_(memset)(buf, 0, sizeof(buf));
743 VG_(sprintf)(buf, "%lu", uw);
744 VG_(addBytesToXA)( xa, buf, VG_(strlen)(buf));
745}
746
florian1636d332012-11-15 04:27:04 +0000747XArray* /*HChar*/ ML_(describe_type)( /*OUT*/PtrdiffT* residual_offset,
sewardj9c606bd2008-09-18 18:12:50 +0000748 XArray* /* of TyEnt */ tyents,
749 UWord ty_cuOff,
njnc4431bf2009-01-15 21:29:24 +0000750 PtrdiffT offset )
sewardjb8b79ad2008-03-03 01:35:41 +0000751{
sewardj9c606bd2008-09-18 18:12:50 +0000752 TyEnt* ty;
753 XArray* xa = VG_(newXA)( ML_(dinfo_zalloc), "di.tytypes.dt.1",
754 ML_(dinfo_free),
florian1636d332012-11-15 04:27:04 +0000755 sizeof(HChar) );
sewardjb8b79ad2008-03-03 01:35:41 +0000756 vg_assert(xa);
757
sewardj9c606bd2008-09-18 18:12:50 +0000758 ty = ML_(TyEnts__index_by_cuOff)(tyents, NULL, ty_cuOff);
759
sewardjb8b79ad2008-03-03 01:35:41 +0000760 while (True) {
761 vg_assert(ty);
sewardj9c606bd2008-09-18 18:12:50 +0000762 vg_assert(ML_(TyEnt__is_type)(ty));
sewardjb8b79ad2008-03-03 01:35:41 +0000763
764 switch (ty->tag) {
765
766 /* These are all atomic types; there is nothing useful we can
767 do. */
sewardj9c606bd2008-09-18 18:12:50 +0000768 case Te_TyEnum:
769 case Te_TyFn:
770 case Te_TyVoid:
bart0e947cf2012-02-01 14:59:14 +0000771 case Te_TyPtr:
772 case Te_TyRef:
773 case Te_TyPtrMbr:
774 case Te_TyRvalRef:
sewardj9c606bd2008-09-18 18:12:50 +0000775 case Te_TyBase:
sewardjb8b79ad2008-03-03 01:35:41 +0000776 goto done;
777
sewardj9c606bd2008-09-18 18:12:50 +0000778 case Te_TyStOrUn: {
sewardjb8b79ad2008-03-03 01:35:41 +0000779 Word i;
780 GXResult res;
sewardj50fde232008-10-20 16:08:55 +0000781 MaybeULong mul;
sewardj9c606bd2008-09-18 18:12:50 +0000782 XArray* fieldRs;
783 UWord fieldR;
784 TyEnt* field = NULL;
njnc4431bf2009-01-15 21:29:24 +0000785 PtrdiffT offMin = 0, offMax1 = 0;
sewardj9c606bd2008-09-18 18:12:50 +0000786 if (!ty->Te.TyStOrUn.isStruct) goto done;
787 fieldRs = ty->Te.TyStOrUn.fieldRs;
dejanj0abc4192014-04-04 10:20:03 +0000788 if (((!fieldRs) || VG_(sizeXA)(fieldRs) == 0)
789 && (ty->Te.TyStOrUn.typeR == 0)) goto done;
sewardj9c606bd2008-09-18 18:12:50 +0000790 for (i = 0; i < VG_(sizeXA)( fieldRs ); i++ ) {
791 fieldR = *(UWord*)VG_(indexXA)( fieldRs, i );
792 field = ML_(TyEnts__index_by_cuOff)(tyents, NULL, fieldR);
sewardjb8b79ad2008-03-03 01:35:41 +0000793 vg_assert(field);
sewardj9c606bd2008-09-18 18:12:50 +0000794 vg_assert(field->tag == Te_Field);
tom3c9cf342009-11-12 13:28:34 +0000795 vg_assert(field->Te.Field.nLoc < 0
796 || (field->Te.Field.nLoc > 0
797 && field->Te.Field.pos.loc));
798 if (field->Te.Field.nLoc == -1) {
799 res.kind = GXR_Addr;
800 res.word = field->Te.Field.pos.offset;
801 } else {
802 /* Re data_bias in this call, we should really send in
803 a legitimate value. But the expression is expected
804 to be a constant expression, evaluation of which
805 will not need to use DW_OP_addr and hence we can
806 avoid the trouble of plumbing the data bias through
807 to this point (if, indeed, it has any meaning; from
808 which DebugInfo would we take the data bias? */
809 res = ML_(evaluate_Dwarf3_Expr)(
810 field->Te.Field.pos.loc, field->Te.Field.nLoc,
811 NULL/*fbGX*/, NULL/*RegSummary*/,
812 0/*data_bias*/,
813 True/*push_initial_zero*/);
814 if (0) {
815 VG_(printf)("QQQ ");
816 ML_(pp_GXResult)(res);
817 VG_(printf)("\n");
818 }
sewardjb8b79ad2008-03-03 01:35:41 +0000819 }
tom3c9cf342009-11-12 13:28:34 +0000820 if (res.kind != GXR_Addr)
sewardjb8b79ad2008-03-03 01:35:41 +0000821 continue;
sewardj50fde232008-10-20 16:08:55 +0000822 mul = ML_(sizeOfType)( tyents, field->Te.Field.typeR );
823 if (mul.b != True)
sewardjb8b79ad2008-03-03 01:35:41 +0000824 goto done; /* size of field is unknown (?!) */
825 offMin = res.word;
njnc4431bf2009-01-15 21:29:24 +0000826 offMax1 = offMin + (PtrdiffT)mul.ul;
sewardjb8b79ad2008-03-03 01:35:41 +0000827 if (offMin == offMax1)
828 continue;
829 vg_assert(offMin < offMax1);
830 if (offset >= offMin && offset < offMax1)
831 break;
832 }
833 /* Did we find a suitable field? */
sewardj9c606bd2008-09-18 18:12:50 +0000834 vg_assert(i >= 0 && i <= VG_(sizeXA)( fieldRs ));
dejanj0abc4192014-04-04 10:20:03 +0000835 if (i == VG_(sizeXA)( fieldRs )) {
836 ty = ML_(TyEnts__index_by_cuOff)(tyents, NULL,
837 ty->Te.TyStOrUn.typeR);
838 vg_assert(ty);
839 if (ty->tag == Te_UNKNOWN) goto done;
840 vg_assert(ML_(TyEnt__is_type)(ty));
841 continue;
842 }
sewardjb8b79ad2008-03-03 01:35:41 +0000843 /* Yes. 'field' is it. */
sewardj9c606bd2008-09-18 18:12:50 +0000844 vg_assert(field);
845 if (!field->Te.Field.name) goto done;
sewardjb8b79ad2008-03-03 01:35:41 +0000846 VG_(addBytesToXA)( xa, ".", 1 );
sewardj9c606bd2008-09-18 18:12:50 +0000847 VG_(addBytesToXA)( xa, field->Te.Field.name,
848 VG_(strlen)(field->Te.Field.name) );
sewardjb8b79ad2008-03-03 01:35:41 +0000849 offset -= offMin;
sewardj9c606bd2008-09-18 18:12:50 +0000850 ty = ML_(TyEnts__index_by_cuOff)(tyents, NULL,
851 field->Te.Field.typeR );
852 tl_assert(ty);
853 if (ty->tag == Te_UNKNOWN) goto done;
sewardjb8b79ad2008-03-03 01:35:41 +0000854 /* keep going; look inside the field. */
855 break;
856 }
857
sewardj9c606bd2008-09-18 18:12:50 +0000858 case Te_TyArray: {
sewardj50fde232008-10-20 16:08:55 +0000859 MaybeULong mul;
sewardjb8b79ad2008-03-03 01:35:41 +0000860 UWord size, eszB, ix;
sewardj9c606bd2008-09-18 18:12:50 +0000861 UWord boundR;
862 TyEnt* elemTy;
863 TyEnt* bound;
sewardjb8b79ad2008-03-03 01:35:41 +0000864 /* Just deal with the simple, common C-case: 1-D array,
865 zero based, known size. */
sewardj9c606bd2008-09-18 18:12:50 +0000866 elemTy = ML_(TyEnts__index_by_cuOff)(tyents, NULL,
867 ty->Te.TyArray.typeR);
868 vg_assert(elemTy);
869 if (elemTy->tag == Te_UNKNOWN) goto done;
870 vg_assert(ML_(TyEnt__is_type)(elemTy));
871 if (!ty->Te.TyArray.boundRs)
sewardjb8b79ad2008-03-03 01:35:41 +0000872 goto done;
sewardj9c606bd2008-09-18 18:12:50 +0000873 if (VG_(sizeXA)( ty->Te.TyArray.boundRs ) != 1) goto done;
874 boundR = *(UWord*)VG_(indexXA)( ty->Te.TyArray.boundRs, 0 );
875 bound = ML_(TyEnts__index_by_cuOff)(tyents, NULL, boundR);
876 vg_assert(bound);
877 vg_assert(bound->tag == Te_Bound);
878 if (!(bound->Te.Bound.knownL && bound->Te.Bound.knownU
879 && bound->Te.Bound.boundL == 0
880 && bound->Te.Bound.boundU >= bound->Te.Bound.boundL))
sewardjb8b79ad2008-03-03 01:35:41 +0000881 goto done;
sewardj9c606bd2008-09-18 18:12:50 +0000882 size = bound->Te.Bound.boundU - bound->Te.Bound.boundL + 1;
sewardjb8b79ad2008-03-03 01:35:41 +0000883 vg_assert(size >= 1);
sewardj50fde232008-10-20 16:08:55 +0000884 mul = ML_(sizeOfType)( tyents, ty->Te.TyArray.typeR );
885 if (mul.b != True)
sewardjb8b79ad2008-03-03 01:35:41 +0000886 goto done; /* size of element type not known */
sewardj50fde232008-10-20 16:08:55 +0000887 eszB = mul.ul;
sewardjb8b79ad2008-03-03 01:35:41 +0000888 if (eszB == 0) goto done;
889 ix = offset / eszB;
890 VG_(addBytesToXA)( xa, "[", 1 );
891 copy_UWord_into_XA( xa, ix );
892 VG_(addBytesToXA)( xa, "]", 1 );
sewardj9c606bd2008-09-18 18:12:50 +0000893 ty = elemTy;
sewardjb8b79ad2008-03-03 01:35:41 +0000894 offset -= ix * eszB;
895 /* keep going; look inside the array element. */
896 break;
897 }
898
sewardj9c606bd2008-09-18 18:12:50 +0000899 case Te_TyQual: {
900 ty = ML_(TyEnts__index_by_cuOff)(tyents, NULL,
901 ty->Te.TyQual.typeR);
902 tl_assert(ty);
903 if (ty->tag == Te_UNKNOWN) goto done;
sewardjb8b79ad2008-03-03 01:35:41 +0000904 break;
905 }
906
sewardj9c606bd2008-09-18 18:12:50 +0000907 case Te_TyTyDef: {
908 ty = ML_(TyEnts__index_by_cuOff)(tyents, NULL,
909 ty->Te.TyTyDef.typeR);
910 tl_assert(ty);
911 if (ty->tag == Te_UNKNOWN) goto done;
sewardjb8b79ad2008-03-03 01:35:41 +0000912 break;
913 }
914
915 default: {
916 VG_(printf)("ML_(describe_type): unhandled: ");
sewardj9c606bd2008-09-18 18:12:50 +0000917 ML_(pp_TyEnt)(ty);
sewardjb8b79ad2008-03-03 01:35:41 +0000918 VG_(printf)("\n");
919 vg_assert(0);
920 }
921
922 }
923 }
924
925 done:
926 *residual_offset = offset;
927 VG_(addBytesToXA)( xa, "\0", 1 );
928 return xa;
929}
930
931/*--------------------------------------------------------------------*/
932/*--- end tytypes.c ---*/
933/*--------------------------------------------------------------------*/