blob: 9491dca6303eea01b9e2e6ab49410f2358e32727 [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
Elliott Hughesed398002017-06-21 14:41:24 -070010 Copyright (C) 2008-2017 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
florian518850b2014-10-22 22:25:30 +000051Bool ML_(TyEnt__is_type)( const TyEnt* te )
sewardj9c606bd2008-09-18 18:12:50 +000052{
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
florian518850b2014-10-22 22:25:30 +000070static void pp_XArray_of_cuOffs ( const XArray* xa )
sewardj9c606bd2008-09-18 18:12:50 +000071{
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
florian518850b2014-10-22 22:25:30 +000083void ML_(pp_TyEnt)( const TyEnt* te )
sewardj9c606bd2008-09-18 18:12:50 +000084{
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
florianc6e5d762015-08-05 22:27:24 +0000107 VG_(printf)("Te_Field(ty=0x%05lx,nLoc=%ld,pos.loc=%p,\"%s\")",
tom3c9cf342009-11-12 13:28:34 +0000108 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) {
florianc6e5d762015-08-05 22:27:24 +0000155 VG_(printf)("Te_TyStOrUn(%lu,%c,%p,\"%s\")",
sewardj9c606bd2008-09-18 18:12:50 +0000156 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 : "" );
florian5196c3e2015-01-04 11:30:11 +0000161 pp_XArray_of_cuOffs( te->Te.TyStOrUn.fieldRs );
sewardj9c606bd2008-09-18 18:12:50 +0000162 } else {
163 VG_(printf)("Te_TyStOrUn(INCOMPLETE,\"%s\")",
164 te->Te.TyStOrUn.name);
165 }
166 break;
167 case Te_TyEnum:
168 VG_(printf)("Te_TyEnum(%d,%p,\"%s\")",
169 te->Te.TyEnum.szB, te->Te.TyEnum.atomRs,
170 te->Te.TyEnum.name ? te->Te.TyEnum.name
florian1636d332012-11-15 04:27:04 +0000171 : "" );
sewardj9c606bd2008-09-18 18:12:50 +0000172 if (te->Te.TyEnum.atomRs)
173 pp_XArray_of_cuOffs( te->Te.TyEnum.atomRs );
174 break;
175 case Te_TyArray:
176 VG_(printf)("Te_TyArray(0x%05lx,%p)",
177 te->Te.TyArray.typeR, te->Te.TyArray.boundRs);
178 if (te->Te.TyArray.boundRs)
179 pp_XArray_of_cuOffs( te->Te.TyArray.boundRs );
180 break;
181 case Te_TyFn:
182 VG_(printf)("Te_TyFn");
183 break;
184 case Te_TyQual:
185 VG_(printf)("Te_TyQual(%c,0x%05lx)", te->Te.TyQual.qual,
186 te->Te.TyQual.typeR);
187 break;
188 case Te_TyVoid:
189 VG_(printf)("Te_TyVoid%s",
190 te->Te.TyVoid.isFake ? "(fake)" : "");
sewardjb8b79ad2008-03-03 01:35:41 +0000191 break;
192 default:
193 vg_assert(0);
194 }
195}
196
sewardj9c606bd2008-09-18 18:12:50 +0000197
198/* Print a whole XArray of TyEnts, debug-style */
199
florian518850b2014-10-22 22:25:30 +0000200void ML_(pp_TyEnts)( const XArray* tyents, const HChar* who )
sewardj9c606bd2008-09-18 18:12:50 +0000201{
202 Word i, n;
203 VG_(printf)("------ %s ------\n", who);
204 n = VG_(sizeXA)( tyents );
205 for (i = 0; i < n; i++) {
florian32971242014-10-23 17:47:15 +0000206 const TyEnt* tyent = VG_(indexXA)( tyents, i );
sewardj9c606bd2008-09-18 18:12:50 +0000207 VG_(printf)(" [%5ld] ", i);
208 ML_(pp_TyEnt)( tyent );
209 VG_(printf)("\n");
sewardjb8b79ad2008-03-03 01:35:41 +0000210 }
sewardjb8b79ad2008-03-03 01:35:41 +0000211}
212
213
sewardj9c606bd2008-09-18 18:12:50 +0000214/* Print a TyEnt, C style, chasing stuff as necessary. */
sewardjb8b79ad2008-03-03 01:35:41 +0000215
florian518850b2014-10-22 22:25:30 +0000216static void pp_TyBound_C_ishly ( const XArray* tyents, UWord cuOff )
sewardj9c606bd2008-09-18 18:12:50 +0000217{
218 TyEnt* ent = ML_(TyEnts__index_by_cuOff)( tyents, NULL, cuOff );
219 if (!ent) {
220 VG_(printf)("**bounds-have-invalid-cuOff**");
221 return;
222 }
223 vg_assert(ent->tag == Te_Bound);
224 if (ent->Te.Bound.knownL && ent->Te.Bound.knownU
225 && ent->Te.Bound.boundL == 0) {
226 VG_(printf)("[%lld]", 1 + ent->Te.Bound.boundU);
sewardjb8b79ad2008-03-03 01:35:41 +0000227 }
228 else
sewardj9c606bd2008-09-18 18:12:50 +0000229 if (ent->Te.Bound.knownL && (!ent->Te.Bound.knownU)
230 && ent->Te.Bound.boundL == 0) {
sewardjb8b79ad2008-03-03 01:35:41 +0000231 VG_(printf)("[]");
232 }
233 else
sewardj9c606bd2008-09-18 18:12:50 +0000234 ML_(pp_TyEnt)( ent );
sewardjb8b79ad2008-03-03 01:35:41 +0000235}
236
florian518850b2014-10-22 22:25:30 +0000237void ML_(pp_TyEnt_C_ishly)( const XArray* /* of TyEnt */ tyents,
sewardj9c606bd2008-09-18 18:12:50 +0000238 UWord cuOff )
sewardjb8b79ad2008-03-03 01:35:41 +0000239{
sewardj9c606bd2008-09-18 18:12:50 +0000240 TyEnt* ent = ML_(TyEnts__index_by_cuOff)( tyents, NULL, cuOff );
241 if (!ent) {
242 VG_(printf)("**type-has-invalid-cuOff**");
sewardjb8b79ad2008-03-03 01:35:41 +0000243 return;
244 }
sewardj9c606bd2008-09-18 18:12:50 +0000245 switch (ent->tag) {
246 case Te_TyBase:
247 if (!ent->Te.TyBase.name) goto unhandled;
248 VG_(printf)("%s", ent->Te.TyBase.name);
sewardjb8b79ad2008-03-03 01:35:41 +0000249 break;
bart0e947cf2012-02-01 14:59:14 +0000250 case Te_TyPtr:
sewardj9c606bd2008-09-18 18:12:50 +0000251 ML_(pp_TyEnt_C_ishly)(tyents, ent->Te.TyPorR.typeR);
bart0e947cf2012-02-01 14:59:14 +0000252 VG_(printf)("*");
253 break;
254 case Te_TyRef:
255 ML_(pp_TyEnt_C_ishly)(tyents, ent->Te.TyPorR.typeR);
256 VG_(printf)("&");
257 break;
258 case Te_TyPtrMbr:
259 ML_(pp_TyEnt_C_ishly)(tyents, ent->Te.TyPorR.typeR);
260 VG_(printf)("*");
261 break;
262 case Te_TyRvalRef:
263 ML_(pp_TyEnt_C_ishly)(tyents, ent->Te.TyPorR.typeR);
264 VG_(printf)("&&");
sewardjb8b79ad2008-03-03 01:35:41 +0000265 break;
sewardj9c606bd2008-09-18 18:12:50 +0000266 case Te_TyEnum:
mjwe5cf4512013-11-24 17:19:35 +0000267 VG_(printf)("enum %s", ent->Te.TyEnum.name ? ent->Te.TyEnum.name
268 : "<anonymous>" );
sewardjb8b79ad2008-03-03 01:35:41 +0000269 break;
sewardj9c606bd2008-09-18 18:12:50 +0000270 case Te_TyStOrUn:
sewardjb8b79ad2008-03-03 01:35:41 +0000271 VG_(printf)("%s %s",
sewardj9c606bd2008-09-18 18:12:50 +0000272 ent->Te.TyStOrUn.isStruct ? "struct" : "union",
sewardj50fde232008-10-20 16:08:55 +0000273 ent->Te.TyStOrUn.name ? ent->Te.TyStOrUn.name
florian1636d332012-11-15 04:27:04 +0000274 : "<anonymous>" );
sewardjb8b79ad2008-03-03 01:35:41 +0000275 break;
sewardj9c606bd2008-09-18 18:12:50 +0000276 case Te_TyArray:
277 ML_(pp_TyEnt_C_ishly)(tyents, ent->Te.TyArray.typeR);
278 if (ent->Te.TyArray.boundRs) {
sewardjb8b79ad2008-03-03 01:35:41 +0000279 Word w;
sewardj9c606bd2008-09-18 18:12:50 +0000280 XArray* xa = ent->Te.TyArray.boundRs;
sewardjb8b79ad2008-03-03 01:35:41 +0000281 for (w = 0; w < VG_(sizeXA)(xa); w++) {
sewardj9c606bd2008-09-18 18:12:50 +0000282 pp_TyBound_C_ishly( tyents, *(UWord*)VG_(indexXA)(xa, w) );
sewardjb8b79ad2008-03-03 01:35:41 +0000283 }
284 } else {
285 VG_(printf)("%s", "[??]");
286 }
287 break;
sewardj9c606bd2008-09-18 18:12:50 +0000288 case Te_TyTyDef:
mjwe5cf4512013-11-24 17:19:35 +0000289 VG_(printf)("%s", ent->Te.TyTyDef.name ? ent->Te.TyTyDef.name
290 : "<anonymous>" );
sewardjb8b79ad2008-03-03 01:35:41 +0000291 break;
sewardj9c606bd2008-09-18 18:12:50 +0000292 case Te_TyFn:
sewardjb8b79ad2008-03-03 01:35:41 +0000293 VG_(printf)("%s", "<function_type>");
294 break;
sewardj9c606bd2008-09-18 18:12:50 +0000295 case Te_TyQual:
296 switch (ent->Te.TyQual.qual) {
sewardjb8b79ad2008-03-03 01:35:41 +0000297 case 'C': VG_(printf)("const "); break;
298 case 'V': VG_(printf)("volatile "); break;
mjwc81436d2014-07-15 15:47:25 +0000299 case 'R': VG_(printf)("restrict "); break;
sewardjb8b79ad2008-03-03 01:35:41 +0000300 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
florian518850b2014-10-22 22:25:30 +0000339TyEnt* ML_(TyEnts__index_by_cuOff) ( const XArray* /* of TyEnt */ ents,
sewardj9c606bd2008-09-18 18:12:50 +0000340 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}
florian518850b2014-10-22 22:25:30 +0000450static Word XArray_of_UWord__cmp ( const XArray* a, const XArray* b ) {
sewardj9c606bd2008-09-18 18:12:50 +0000451 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}
florian518850b2014-10-22 22:25:30 +0000463static Word Bytevector__cmp ( const UChar* a, const UChar* b, Word n ) {
sewardj9c606bd2008-09-18 18:12:50 +0000464 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);
florian5196c3e2015-01-04 11:30:11 +0000621 VG_(deleteXA)(te->Te.TyStOrUn.fieldRs);
sewardj9c606bd2008-09-18 18:12:50 +0000622 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
florian518850b2014-10-22 22:25:30 +0000669MaybeULong ML_(sizeOfType)( const 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 ) {
florianf44ff622014-12-20 16:52:08 +0000741 HChar buf[32]; // large enough
sewardjb8b79ad2008-03-03 01:35:41 +0000742 VG_(sprintf)(buf, "%lu", uw);
743 VG_(addBytesToXA)( xa, buf, VG_(strlen)(buf));
744}
745
florian1636d332012-11-15 04:27:04 +0000746XArray* /*HChar*/ ML_(describe_type)( /*OUT*/PtrdiffT* residual_offset,
florian518850b2014-10-22 22:25:30 +0000747 const XArray* /* of TyEnt */ tyents,
sewardj9c606bd2008-09-18 18:12:50 +0000748 UWord ty_cuOff,
njnc4431bf2009-01-15 21:29:24 +0000749 PtrdiffT offset )
sewardjb8b79ad2008-03-03 01:35:41 +0000750{
sewardj9c606bd2008-09-18 18:12:50 +0000751 TyEnt* ty;
752 XArray* xa = VG_(newXA)( ML_(dinfo_zalloc), "di.tytypes.dt.1",
753 ML_(dinfo_free),
florian1636d332012-11-15 04:27:04 +0000754 sizeof(HChar) );
sewardjb8b79ad2008-03-03 01:35:41 +0000755
sewardj9c606bd2008-09-18 18:12:50 +0000756 ty = ML_(TyEnts__index_by_cuOff)(tyents, NULL, ty_cuOff);
757
sewardjb8b79ad2008-03-03 01:35:41 +0000758 while (True) {
759 vg_assert(ty);
sewardj9c606bd2008-09-18 18:12:50 +0000760 vg_assert(ML_(TyEnt__is_type)(ty));
sewardjb8b79ad2008-03-03 01:35:41 +0000761
762 switch (ty->tag) {
763
764 /* These are all atomic types; there is nothing useful we can
765 do. */
sewardj9c606bd2008-09-18 18:12:50 +0000766 case Te_TyEnum:
767 case Te_TyFn:
768 case Te_TyVoid:
bart0e947cf2012-02-01 14:59:14 +0000769 case Te_TyPtr:
770 case Te_TyRef:
771 case Te_TyPtrMbr:
772 case Te_TyRvalRef:
sewardj9c606bd2008-09-18 18:12:50 +0000773 case Te_TyBase:
sewardjb8b79ad2008-03-03 01:35:41 +0000774 goto done;
775
sewardj9c606bd2008-09-18 18:12:50 +0000776 case Te_TyStOrUn: {
sewardjb8b79ad2008-03-03 01:35:41 +0000777 Word i;
778 GXResult res;
sewardj50fde232008-10-20 16:08:55 +0000779 MaybeULong mul;
sewardj9c606bd2008-09-18 18:12:50 +0000780 XArray* fieldRs;
781 UWord fieldR;
782 TyEnt* field = NULL;
njnc4431bf2009-01-15 21:29:24 +0000783 PtrdiffT offMin = 0, offMax1 = 0;
sewardj9c606bd2008-09-18 18:12:50 +0000784 if (!ty->Te.TyStOrUn.isStruct) goto done;
785 fieldRs = ty->Te.TyStOrUn.fieldRs;
florian5196c3e2015-01-04 11:30:11 +0000786 if (VG_(sizeXA)(fieldRs) == 0
dejanj0abc4192014-04-04 10:20:03 +0000787 && (ty->Te.TyStOrUn.typeR == 0)) goto done;
sewardj9c606bd2008-09-18 18:12:50 +0000788 for (i = 0; i < VG_(sizeXA)( fieldRs ); i++ ) {
789 fieldR = *(UWord*)VG_(indexXA)( fieldRs, i );
790 field = ML_(TyEnts__index_by_cuOff)(tyents, NULL, fieldR);
sewardjb8b79ad2008-03-03 01:35:41 +0000791 vg_assert(field);
sewardj9c606bd2008-09-18 18:12:50 +0000792 vg_assert(field->tag == Te_Field);
tom3c9cf342009-11-12 13:28:34 +0000793 vg_assert(field->Te.Field.nLoc < 0
794 || (field->Te.Field.nLoc > 0
795 && field->Te.Field.pos.loc));
796 if (field->Te.Field.nLoc == -1) {
797 res.kind = GXR_Addr;
798 res.word = field->Te.Field.pos.offset;
799 } else {
800 /* Re data_bias in this call, we should really send in
801 a legitimate value. But the expression is expected
802 to be a constant expression, evaluation of which
803 will not need to use DW_OP_addr and hence we can
804 avoid the trouble of plumbing the data bias through
805 to this point (if, indeed, it has any meaning; from
806 which DebugInfo would we take the data bias? */
807 res = ML_(evaluate_Dwarf3_Expr)(
808 field->Te.Field.pos.loc, field->Te.Field.nLoc,
809 NULL/*fbGX*/, NULL/*RegSummary*/,
810 0/*data_bias*/,
811 True/*push_initial_zero*/);
812 if (0) {
813 VG_(printf)("QQQ ");
814 ML_(pp_GXResult)(res);
815 VG_(printf)("\n");
816 }
sewardjb8b79ad2008-03-03 01:35:41 +0000817 }
tom3c9cf342009-11-12 13:28:34 +0000818 if (res.kind != GXR_Addr)
sewardjb8b79ad2008-03-03 01:35:41 +0000819 continue;
sewardj50fde232008-10-20 16:08:55 +0000820 mul = ML_(sizeOfType)( tyents, field->Te.Field.typeR );
821 if (mul.b != True)
sewardjb8b79ad2008-03-03 01:35:41 +0000822 goto done; /* size of field is unknown (?!) */
823 offMin = res.word;
njnc4431bf2009-01-15 21:29:24 +0000824 offMax1 = offMin + (PtrdiffT)mul.ul;
sewardjb8b79ad2008-03-03 01:35:41 +0000825 if (offMin == offMax1)
826 continue;
827 vg_assert(offMin < offMax1);
828 if (offset >= offMin && offset < offMax1)
829 break;
830 }
831 /* Did we find a suitable field? */
sewardj9c606bd2008-09-18 18:12:50 +0000832 vg_assert(i >= 0 && i <= VG_(sizeXA)( fieldRs ));
dejanj0abc4192014-04-04 10:20:03 +0000833 if (i == VG_(sizeXA)( fieldRs )) {
834 ty = ML_(TyEnts__index_by_cuOff)(tyents, NULL,
835 ty->Te.TyStOrUn.typeR);
836 vg_assert(ty);
837 if (ty->tag == Te_UNKNOWN) goto done;
838 vg_assert(ML_(TyEnt__is_type)(ty));
839 continue;
840 }
sewardjb8b79ad2008-03-03 01:35:41 +0000841 /* Yes. 'field' is it. */
sewardj9c606bd2008-09-18 18:12:50 +0000842 vg_assert(field);
843 if (!field->Te.Field.name) goto done;
sewardjb8b79ad2008-03-03 01:35:41 +0000844 VG_(addBytesToXA)( xa, ".", 1 );
sewardj9c606bd2008-09-18 18:12:50 +0000845 VG_(addBytesToXA)( xa, field->Te.Field.name,
846 VG_(strlen)(field->Te.Field.name) );
sewardjb8b79ad2008-03-03 01:35:41 +0000847 offset -= offMin;
sewardj9c606bd2008-09-18 18:12:50 +0000848 ty = ML_(TyEnts__index_by_cuOff)(tyents, NULL,
849 field->Te.Field.typeR );
floriane2800c92014-09-15 20:57:45 +0000850 vg_assert(ty);
sewardj9c606bd2008-09-18 18:12:50 +0000851 if (ty->tag == Te_UNKNOWN) goto done;
sewardjb8b79ad2008-03-03 01:35:41 +0000852 /* keep going; look inside the field. */
853 break;
854 }
855
sewardj9c606bd2008-09-18 18:12:50 +0000856 case Te_TyArray: {
sewardj50fde232008-10-20 16:08:55 +0000857 MaybeULong mul;
sewardjb8b79ad2008-03-03 01:35:41 +0000858 UWord size, eszB, ix;
sewardj9c606bd2008-09-18 18:12:50 +0000859 UWord boundR;
860 TyEnt* elemTy;
861 TyEnt* bound;
sewardjb8b79ad2008-03-03 01:35:41 +0000862 /* Just deal with the simple, common C-case: 1-D array,
863 zero based, known size. */
sewardj9c606bd2008-09-18 18:12:50 +0000864 elemTy = ML_(TyEnts__index_by_cuOff)(tyents, NULL,
865 ty->Te.TyArray.typeR);
866 vg_assert(elemTy);
867 if (elemTy->tag == Te_UNKNOWN) goto done;
868 vg_assert(ML_(TyEnt__is_type)(elemTy));
869 if (!ty->Te.TyArray.boundRs)
sewardjb8b79ad2008-03-03 01:35:41 +0000870 goto done;
sewardj9c606bd2008-09-18 18:12:50 +0000871 if (VG_(sizeXA)( ty->Te.TyArray.boundRs ) != 1) goto done;
872 boundR = *(UWord*)VG_(indexXA)( ty->Te.TyArray.boundRs, 0 );
873 bound = ML_(TyEnts__index_by_cuOff)(tyents, NULL, boundR);
874 vg_assert(bound);
875 vg_assert(bound->tag == Te_Bound);
876 if (!(bound->Te.Bound.knownL && bound->Te.Bound.knownU
877 && bound->Te.Bound.boundL == 0
878 && bound->Te.Bound.boundU >= bound->Te.Bound.boundL))
sewardjb8b79ad2008-03-03 01:35:41 +0000879 goto done;
sewardj9c606bd2008-09-18 18:12:50 +0000880 size = bound->Te.Bound.boundU - bound->Te.Bound.boundL + 1;
sewardjb8b79ad2008-03-03 01:35:41 +0000881 vg_assert(size >= 1);
sewardj50fde232008-10-20 16:08:55 +0000882 mul = ML_(sizeOfType)( tyents, ty->Te.TyArray.typeR );
883 if (mul.b != True)
sewardjb8b79ad2008-03-03 01:35:41 +0000884 goto done; /* size of element type not known */
sewardj50fde232008-10-20 16:08:55 +0000885 eszB = mul.ul;
sewardjb8b79ad2008-03-03 01:35:41 +0000886 if (eszB == 0) goto done;
887 ix = offset / eszB;
888 VG_(addBytesToXA)( xa, "[", 1 );
889 copy_UWord_into_XA( xa, ix );
890 VG_(addBytesToXA)( xa, "]", 1 );
sewardj9c606bd2008-09-18 18:12:50 +0000891 ty = elemTy;
sewardjb8b79ad2008-03-03 01:35:41 +0000892 offset -= ix * eszB;
893 /* keep going; look inside the array element. */
894 break;
895 }
896
sewardj9c606bd2008-09-18 18:12:50 +0000897 case Te_TyQual: {
898 ty = ML_(TyEnts__index_by_cuOff)(tyents, NULL,
899 ty->Te.TyQual.typeR);
floriane2800c92014-09-15 20:57:45 +0000900 vg_assert(ty);
sewardj9c606bd2008-09-18 18:12:50 +0000901 if (ty->tag == Te_UNKNOWN) goto done;
sewardjb8b79ad2008-03-03 01:35:41 +0000902 break;
903 }
904
sewardj9c606bd2008-09-18 18:12:50 +0000905 case Te_TyTyDef: {
906 ty = ML_(TyEnts__index_by_cuOff)(tyents, NULL,
907 ty->Te.TyTyDef.typeR);
floriane2800c92014-09-15 20:57:45 +0000908 vg_assert(ty);
sewardj9c606bd2008-09-18 18:12:50 +0000909 if (ty->tag == Te_UNKNOWN) goto done;
sewardjb8b79ad2008-03-03 01:35:41 +0000910 break;
911 }
912
913 default: {
914 VG_(printf)("ML_(describe_type): unhandled: ");
sewardj9c606bd2008-09-18 18:12:50 +0000915 ML_(pp_TyEnt)(ty);
sewardjb8b79ad2008-03-03 01:35:41 +0000916 VG_(printf)("\n");
917 vg_assert(0);
918 }
919
920 }
921 }
922
923 done:
924 *residual_offset = offset;
925 VG_(addBytesToXA)( xa, "\0", 1 );
926 return xa;
927}
928
929/*--------------------------------------------------------------------*/
930/*--- end tytypes.c ---*/
931/*--------------------------------------------------------------------*/