sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 1 | |
| 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 Hughes | ed39800 | 2017-06-21 14:41:24 -0700 | [diff] [blame^] | 10 | Copyright (C) 2008-2017 OpenWorks LLP |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 11 | 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" |
tom | 588658b | 2009-01-22 13:40:12 +0000 | [diff] [blame] | 37 | #include "pub_core_debuginfo.h" |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 38 | #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 | |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 48 | /* Does this TyEnt denote a type, as opposed to some other kind of |
| 49 | thing? */ |
| 50 | |
florian | 518850b | 2014-10-22 22:25:30 +0000 | [diff] [blame] | 51 | Bool ML_(TyEnt__is_type)( const TyEnt* te ) |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 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; |
bart | 0e947cf | 2012-02-01 14:59:14 +0000 | [diff] [blame] | 57 | 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: |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 61 | return True; |
| 62 | default: |
| 63 | vg_assert(0); |
| 64 | } |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 65 | } |
| 66 | |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 67 | |
| 68 | /* Print a TyEnt, debug-style. */ |
| 69 | |
florian | 518850b | 2014-10-22 22:25:30 +0000 | [diff] [blame] | 70 | static void pp_XArray_of_cuOffs ( const XArray* xa ) |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 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)("}"); |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 81 | } |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 82 | |
florian | 518850b | 2014-10-22 22:25:30 +0000 | [diff] [blame] | 83 | void ML_(pp_TyEnt)( const TyEnt* te ) |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 84 | { |
| 85 | VG_(printf)("0x%05lx ", te->cuOff); |
| 86 | switch (te->tag) { |
| 87 | case Te_EMPTY: |
| 88 | VG_(printf)("EMPTY"); |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 89 | break; |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 90 | case Te_INDIR: |
| 91 | VG_(printf)("INDIR(0x%05lx)", te->Te.INDIR.indR); |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 92 | break; |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 93 | case Te_UNKNOWN: |
| 94 | VG_(printf)("UNKNOWN"); |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 95 | break; |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 96 | case Te_Atom: |
sewardj | f3aaa33 | 2008-10-23 10:54:40 +0000 | [diff] [blame] | 97 | VG_(printf)("Te_Atom(%s%lld,\"%s\")", |
| 98 | te->Te.Atom.valueKnown ? "" : "unknown:", |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 99 | te->Te.Atom.value, te->Te.Atom.name); |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 100 | break; |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 101 | case Te_Field: |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 102 | 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, |
florian | 1636d33 | 2012-11-15 04:27:04 +0000 | [diff] [blame] | 105 | te->Te.Field.name ? te->Te.Field.name : ""); |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 106 | else |
florian | c6e5d76 | 2015-08-05 22:27:24 +0000 | [diff] [blame] | 107 | VG_(printf)("Te_Field(ty=0x%05lx,nLoc=%ld,pos.loc=%p,\"%s\")", |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 108 | te->Te.Field.typeR, te->Te.Field.nLoc, |
| 109 | te->Te.Field.pos.loc, |
florian | 1636d33 | 2012-11-15 04:27:04 +0000 | [diff] [blame] | 110 | te->Te.Field.name ? te->Te.Field.name : ""); |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 111 | break; |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 112 | 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)("]"); |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 124 | break; |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 125 | 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 |
florian | 1636d33 | 2012-11-15 04:27:04 +0000 | [diff] [blame] | 129 | : "(null)" ); |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 130 | break; |
bart | 0e947cf | 2012-02-01 14:59:14 +0000 | [diff] [blame] | 131 | 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, |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 145 | te->Te.TyPorR.typeR); |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 146 | break; |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 147 | 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 |
florian | 1636d33 | 2012-11-15 04:27:04 +0000 | [diff] [blame] | 151 | : "" ); |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 152 | break; |
| 153 | case Te_TyStOrUn: |
| 154 | if (te->Te.TyStOrUn.complete) { |
florian | c6e5d76 | 2015-08-05 22:27:24 +0000 | [diff] [blame] | 155 | VG_(printf)("Te_TyStOrUn(%lu,%c,%p,\"%s\")", |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 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 |
florian | 1636d33 | 2012-11-15 04:27:04 +0000 | [diff] [blame] | 160 | : "" ); |
florian | 5196c3e | 2015-01-04 11:30:11 +0000 | [diff] [blame] | 161 | pp_XArray_of_cuOffs( te->Te.TyStOrUn.fieldRs ); |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 162 | } 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 |
florian | 1636d33 | 2012-11-15 04:27:04 +0000 | [diff] [blame] | 171 | : "" ); |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 172 | 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)" : ""); |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 191 | break; |
| 192 | default: |
| 193 | vg_assert(0); |
| 194 | } |
| 195 | } |
| 196 | |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 197 | |
| 198 | /* Print a whole XArray of TyEnts, debug-style */ |
| 199 | |
florian | 518850b | 2014-10-22 22:25:30 +0000 | [diff] [blame] | 200 | void ML_(pp_TyEnts)( const XArray* tyents, const HChar* who ) |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 201 | { |
| 202 | Word i, n; |
| 203 | VG_(printf)("------ %s ------\n", who); |
| 204 | n = VG_(sizeXA)( tyents ); |
| 205 | for (i = 0; i < n; i++) { |
florian | 3297124 | 2014-10-23 17:47:15 +0000 | [diff] [blame] | 206 | const TyEnt* tyent = VG_(indexXA)( tyents, i ); |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 207 | VG_(printf)(" [%5ld] ", i); |
| 208 | ML_(pp_TyEnt)( tyent ); |
| 209 | VG_(printf)("\n"); |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 210 | } |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 211 | } |
| 212 | |
| 213 | |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 214 | /* Print a TyEnt, C style, chasing stuff as necessary. */ |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 215 | |
florian | 518850b | 2014-10-22 22:25:30 +0000 | [diff] [blame] | 216 | static void pp_TyBound_C_ishly ( const XArray* tyents, UWord cuOff ) |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 217 | { |
| 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); |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 227 | } |
| 228 | else |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 229 | if (ent->Te.Bound.knownL && (!ent->Te.Bound.knownU) |
| 230 | && ent->Te.Bound.boundL == 0) { |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 231 | VG_(printf)("[]"); |
| 232 | } |
| 233 | else |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 234 | ML_(pp_TyEnt)( ent ); |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 235 | } |
| 236 | |
florian | 518850b | 2014-10-22 22:25:30 +0000 | [diff] [blame] | 237 | void ML_(pp_TyEnt_C_ishly)( const XArray* /* of TyEnt */ tyents, |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 238 | UWord cuOff ) |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 239 | { |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 240 | TyEnt* ent = ML_(TyEnts__index_by_cuOff)( tyents, NULL, cuOff ); |
| 241 | if (!ent) { |
| 242 | VG_(printf)("**type-has-invalid-cuOff**"); |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 243 | return; |
| 244 | } |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 245 | switch (ent->tag) { |
| 246 | case Te_TyBase: |
| 247 | if (!ent->Te.TyBase.name) goto unhandled; |
| 248 | VG_(printf)("%s", ent->Te.TyBase.name); |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 249 | break; |
bart | 0e947cf | 2012-02-01 14:59:14 +0000 | [diff] [blame] | 250 | case Te_TyPtr: |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 251 | ML_(pp_TyEnt_C_ishly)(tyents, ent->Te.TyPorR.typeR); |
bart | 0e947cf | 2012-02-01 14:59:14 +0000 | [diff] [blame] | 252 | 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)("&&"); |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 265 | break; |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 266 | case Te_TyEnum: |
mjw | e5cf451 | 2013-11-24 17:19:35 +0000 | [diff] [blame] | 267 | VG_(printf)("enum %s", ent->Te.TyEnum.name ? ent->Te.TyEnum.name |
| 268 | : "<anonymous>" ); |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 269 | break; |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 270 | case Te_TyStOrUn: |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 271 | VG_(printf)("%s %s", |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 272 | ent->Te.TyStOrUn.isStruct ? "struct" : "union", |
sewardj | 50fde23 | 2008-10-20 16:08:55 +0000 | [diff] [blame] | 273 | ent->Te.TyStOrUn.name ? ent->Te.TyStOrUn.name |
florian | 1636d33 | 2012-11-15 04:27:04 +0000 | [diff] [blame] | 274 | : "<anonymous>" ); |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 275 | break; |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 276 | case Te_TyArray: |
| 277 | ML_(pp_TyEnt_C_ishly)(tyents, ent->Te.TyArray.typeR); |
| 278 | if (ent->Te.TyArray.boundRs) { |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 279 | Word w; |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 280 | XArray* xa = ent->Te.TyArray.boundRs; |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 281 | for (w = 0; w < VG_(sizeXA)(xa); w++) { |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 282 | pp_TyBound_C_ishly( tyents, *(UWord*)VG_(indexXA)(xa, w) ); |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 283 | } |
| 284 | } else { |
| 285 | VG_(printf)("%s", "[??]"); |
| 286 | } |
| 287 | break; |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 288 | case Te_TyTyDef: |
mjw | e5cf451 | 2013-11-24 17:19:35 +0000 | [diff] [blame] | 289 | VG_(printf)("%s", ent->Te.TyTyDef.name ? ent->Te.TyTyDef.name |
| 290 | : "<anonymous>" ); |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 291 | break; |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 292 | case Te_TyFn: |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 293 | VG_(printf)("%s", "<function_type>"); |
| 294 | break; |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 295 | case Te_TyQual: |
| 296 | switch (ent->Te.TyQual.qual) { |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 297 | case 'C': VG_(printf)("const "); break; |
| 298 | case 'V': VG_(printf)("volatile "); break; |
mjw | c81436d | 2014-07-15 15:47:25 +0000 | [diff] [blame] | 299 | case 'R': VG_(printf)("restrict "); break; |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 300 | default: goto unhandled; |
| 301 | } |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 302 | ML_(pp_TyEnt_C_ishly)(tyents, ent->Te.TyQual.typeR); |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 303 | break; |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 304 | case Te_TyVoid: |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 305 | VG_(printf)("%svoid", |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 306 | ent->Te.TyVoid.isFake ? "fake" : ""); |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 307 | break; |
sewardj | 50fde23 | 2008-10-20 16:08:55 +0000 | [diff] [blame] | 308 | case Te_UNKNOWN: |
| 309 | ML_(pp_TyEnt)(ent); |
| 310 | break; |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 311 | default: |
| 312 | goto unhandled; |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 313 | } |
| 314 | return; |
| 315 | |
| 316 | unhandled: |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 317 | VG_(printf)("pp_TyEnt_C_ishly:unhandled: "); |
| 318 | ML_(pp_TyEnt)(ent); |
| 319 | vg_assert(0); |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 320 | } |
| 321 | |
| 322 | |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 323 | /* '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 | |
| 328 | void 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 | |
florian | 518850b | 2014-10-22 22:25:30 +0000 | [diff] [blame] | 339 | TyEnt* ML_(TyEnts__index_by_cuOff) ( const XArray* /* of TyEnt */ ents, |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 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 | |
florian | 6bd9dc1 | 2012-11-23 16:17:43 +0000 | [diff] [blame] | 413 | Word ML_(TyEnt__cmp_by_cuOff_only) ( const TyEnt* te1, const TyEnt* te2 ) |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 414 | { |
| 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. */ |
sewardj | c961d36 | 2012-03-31 00:06:04 +0000 | [diff] [blame] | 423 | static inline Word UWord__cmp ( UWord a, UWord b ) { |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 424 | if (a < b) return -1; |
| 425 | if (a > b) return 1; |
| 426 | return 0; |
| 427 | } |
sewardj | c961d36 | 2012-03-31 00:06:04 +0000 | [diff] [blame] | 428 | static inline Word Long__cmp ( Long a, Long b ) { |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 429 | if (a < b) return -1; |
| 430 | if (a > b) return 1; |
| 431 | return 0; |
| 432 | } |
sewardj | c961d36 | 2012-03-31 00:06:04 +0000 | [diff] [blame] | 433 | static inline Word Bool__cmp ( Bool a, Bool b ) { |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 434 | 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 | } |
sewardj | c961d36 | 2012-03-31 00:06:04 +0000 | [diff] [blame] | 440 | static inline Word UChar__cmp ( UChar a, UChar b ) { |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 441 | if (a < b) return -1; |
| 442 | if (a > b) return 1; |
| 443 | return 0; |
| 444 | } |
sewardj | c961d36 | 2012-03-31 00:06:04 +0000 | [diff] [blame] | 445 | static inline Word Int__cmp ( Int a, Int b ) { |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 446 | if (a < b) return -1; |
| 447 | if (a > b) return 1; |
| 448 | return 0; |
| 449 | } |
florian | 518850b | 2014-10-22 22:25:30 +0000 | [diff] [blame] | 450 | static Word XArray_of_UWord__cmp ( const XArray* a, const XArray* b ) { |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 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 | } |
florian | 518850b | 2014-10-22 22:25:30 +0000 | [diff] [blame] | 463 | static Word Bytevector__cmp ( const UChar* a, const UChar* b, Word n ) { |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 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 | } |
florian | 1636d33 | 2012-11-15 04:27:04 +0000 | [diff] [blame] | 472 | static Word Asciiz__cmp ( const HChar* a, const HChar* b ) { |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 473 | /* 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 | |
florian | 6bd9dc1 | 2012-11-23 16:17:43 +0000 | [diff] [blame] | 480 | Word ML_(TyEnt__cmp_by_all_except_cuOff) ( const TyEnt* te1, const TyEnt* te2 ) |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 481 | { |
| 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: |
sewardj | f3aaa33 | 2008-10-23 10:54:40 +0000 | [diff] [blame] | 492 | r = Bool__cmp(te1->Te.Atom.valueKnown, te2->Te.Atom.valueKnown); |
| 493 | if (r != 0) return r; |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 494 | 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; |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 507 | 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); |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 512 | 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; |
bart | 0e947cf | 2012-02-01 14:59:14 +0000 | [diff] [blame] | 529 | case Te_TyPtr: |
| 530 | case Te_TyRef: |
| 531 | case Te_TyPtrMbr: |
| 532 | case Te_TyRvalRef: |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 533 | 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); |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 536 | 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 | |
| 587 | void 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); |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 603 | if (te->Te.Field.nLoc > 0 && te->Te.Field.pos.loc) |
| 604 | ML_(dinfo_free)(te->Te.Field.pos.loc); |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 605 | 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; |
bart | 0e947cf | 2012-02-01 14:59:14 +0000 | [diff] [blame] | 611 | case Te_TyPtr: |
| 612 | case Te_TyRef: |
| 613 | case Te_TyPtrMbr: |
| 614 | case Te_TyRvalRef: |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 615 | 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); |
florian | 5196c3e | 2015-01-04 11:30:11 +0000 | [diff] [blame] | 621 | VG_(deleteXA)(te->Te.TyStOrUn.fieldRs); |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 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 | |
sewardj | 50fde23 | 2008-10-20 16:08:55 +0000 | [diff] [blame] | 650 | static MaybeULong mk_MaybeULong_Nothing ( void ) { |
| 651 | MaybeULong mul; |
| 652 | mul.ul = 0; |
| 653 | mul.b = False; |
| 654 | return mul; |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 655 | } |
sewardj | 50fde23 | 2008-10-20 16:08:55 +0000 | [diff] [blame] | 656 | static MaybeULong mk_MaybeULong_Just ( ULong ul ) { |
| 657 | MaybeULong mul; |
| 658 | mul.ul = ul; |
| 659 | mul.b = True; |
| 660 | return mul; |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 661 | } |
sewardj | 50fde23 | 2008-10-20 16:08:55 +0000 | [diff] [blame] | 662 | static 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; |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 667 | } |
| 668 | |
florian | 518850b | 2014-10-22 22:25:30 +0000 | [diff] [blame] | 669 | MaybeULong ML_(sizeOfType)( const XArray* /* of TyEnt */ tyents, |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 670 | UWord cuOff ) |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 671 | { |
| 672 | Word i; |
sewardj | 50fde23 | 2008-10-20 16:08:55 +0000 | [diff] [blame] | 673 | MaybeULong eszB; |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 674 | 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); |
sewardj | 50fde23 | 2008-10-20 16:08:55 +0000 | [diff] [blame] | 681 | return mk_MaybeULong_Just( ent->Te.TyBase.szB ); |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 682 | 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) |
sewardj | 50fde23 | 2008-10-20 16:08:55 +0000 | [diff] [blame] | 689 | return mk_MaybeULong_Nothing(); /*UNKNOWN*/ |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 690 | return ML_(sizeOfType)( tyents, ent->Te.TyTyDef.typeR ); |
bart | 0e947cf | 2012-02-01 14:59:14 +0000 | [diff] [blame] | 691 | case Te_TyPtr: |
| 692 | case Te_TyRef: |
| 693 | case Te_TyPtrMbr: |
| 694 | case Te_TyRvalRef: |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 695 | vg_assert(ent->Te.TyPorR.szB == 4 || ent->Te.TyPorR.szB == 8); |
sewardj | 50fde23 | 2008-10-20 16:08:55 +0000 | [diff] [blame] | 696 | return mk_MaybeULong_Just( ent->Te.TyPorR.szB ); |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 697 | case Te_TyStOrUn: |
| 698 | return ent->Te.TyStOrUn.complete |
sewardj | 50fde23 | 2008-10-20 16:08:55 +0000 | [diff] [blame] | 699 | ? mk_MaybeULong_Just( ent->Te.TyStOrUn.szB ) |
| 700 | : mk_MaybeULong_Nothing(); |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 701 | case Te_TyEnum: |
sewardj | 50fde23 | 2008-10-20 16:08:55 +0000 | [diff] [blame] | 702 | return mk_MaybeULong_Just( ent->Te.TyEnum.szB ); |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 703 | 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) |
sewardj | 50fde23 | 2008-10-20 16:08:55 +0000 | [diff] [blame] | 708 | return mk_MaybeULong_Nothing(); /*UNKNOWN*/ |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 709 | 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 ); |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 715 | vg_assert(bo); |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 716 | vg_assert(bo->tag == Te_Bound); |
| 717 | if (!(bo->Te.Bound.knownL && bo->Te.Bound.knownU)) |
sewardj | 50fde23 | 2008-10-20 16:08:55 +0000 | [diff] [blame] | 718 | return mk_MaybeULong_Nothing(); /*UNKNOWN*/ |
| 719 | eszB = mul_MaybeULong( |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 720 | eszB, |
sewardj | 50fde23 | 2008-10-20 16:08:55 +0000 | [diff] [blame] | 721 | mk_MaybeULong_Just( (ULong)(bo->Te.Bound.boundU |
| 722 | - bo->Te.Bound.boundL + 1) )); |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 723 | } |
| 724 | return eszB; |
sewardj | bdee918 | 2010-10-08 23:57:25 +0000 | [diff] [blame] | 725 | case Te_TyVoid: |
| 726 | return mk_MaybeULong_Nothing(); /*UNKNOWN*/ |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 727 | default: |
| 728 | VG_(printf)("ML_(sizeOfType): unhandled: "); |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 729 | ML_(pp_TyEnt)(ent); |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 730 | VG_(printf)("\n"); |
| 731 | vg_assert(0); |
| 732 | } |
| 733 | } |
| 734 | |
| 735 | |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 736 | /* Describe where in the type 'offset' falls. Caller must |
| 737 | deallocate the resulting XArray. */ |
| 738 | |
florian | 1636d33 | 2012-11-15 04:27:04 +0000 | [diff] [blame] | 739 | static void copy_UWord_into_XA ( XArray* /* of HChar */ xa, |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 740 | UWord uw ) { |
florian | f44ff62 | 2014-12-20 16:52:08 +0000 | [diff] [blame] | 741 | HChar buf[32]; // large enough |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 742 | VG_(sprintf)(buf, "%lu", uw); |
| 743 | VG_(addBytesToXA)( xa, buf, VG_(strlen)(buf)); |
| 744 | } |
| 745 | |
florian | 1636d33 | 2012-11-15 04:27:04 +0000 | [diff] [blame] | 746 | XArray* /*HChar*/ ML_(describe_type)( /*OUT*/PtrdiffT* residual_offset, |
florian | 518850b | 2014-10-22 22:25:30 +0000 | [diff] [blame] | 747 | const XArray* /* of TyEnt */ tyents, |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 748 | UWord ty_cuOff, |
njn | c4431bf | 2009-01-15 21:29:24 +0000 | [diff] [blame] | 749 | PtrdiffT offset ) |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 750 | { |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 751 | TyEnt* ty; |
| 752 | XArray* xa = VG_(newXA)( ML_(dinfo_zalloc), "di.tytypes.dt.1", |
| 753 | ML_(dinfo_free), |
florian | 1636d33 | 2012-11-15 04:27:04 +0000 | [diff] [blame] | 754 | sizeof(HChar) ); |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 755 | |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 756 | ty = ML_(TyEnts__index_by_cuOff)(tyents, NULL, ty_cuOff); |
| 757 | |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 758 | while (True) { |
| 759 | vg_assert(ty); |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 760 | vg_assert(ML_(TyEnt__is_type)(ty)); |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 761 | |
| 762 | switch (ty->tag) { |
| 763 | |
| 764 | /* These are all atomic types; there is nothing useful we can |
| 765 | do. */ |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 766 | case Te_TyEnum: |
| 767 | case Te_TyFn: |
| 768 | case Te_TyVoid: |
bart | 0e947cf | 2012-02-01 14:59:14 +0000 | [diff] [blame] | 769 | case Te_TyPtr: |
| 770 | case Te_TyRef: |
| 771 | case Te_TyPtrMbr: |
| 772 | case Te_TyRvalRef: |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 773 | case Te_TyBase: |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 774 | goto done; |
| 775 | |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 776 | case Te_TyStOrUn: { |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 777 | Word i; |
| 778 | GXResult res; |
sewardj | 50fde23 | 2008-10-20 16:08:55 +0000 | [diff] [blame] | 779 | MaybeULong mul; |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 780 | XArray* fieldRs; |
| 781 | UWord fieldR; |
| 782 | TyEnt* field = NULL; |
njn | c4431bf | 2009-01-15 21:29:24 +0000 | [diff] [blame] | 783 | PtrdiffT offMin = 0, offMax1 = 0; |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 784 | if (!ty->Te.TyStOrUn.isStruct) goto done; |
| 785 | fieldRs = ty->Te.TyStOrUn.fieldRs; |
florian | 5196c3e | 2015-01-04 11:30:11 +0000 | [diff] [blame] | 786 | if (VG_(sizeXA)(fieldRs) == 0 |
dejanj | 0abc419 | 2014-04-04 10:20:03 +0000 | [diff] [blame] | 787 | && (ty->Te.TyStOrUn.typeR == 0)) goto done; |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 788 | 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); |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 791 | vg_assert(field); |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 792 | vg_assert(field->tag == Te_Field); |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 793 | 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 | } |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 817 | } |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 818 | if (res.kind != GXR_Addr) |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 819 | continue; |
sewardj | 50fde23 | 2008-10-20 16:08:55 +0000 | [diff] [blame] | 820 | mul = ML_(sizeOfType)( tyents, field->Te.Field.typeR ); |
| 821 | if (mul.b != True) |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 822 | goto done; /* size of field is unknown (?!) */ |
| 823 | offMin = res.word; |
njn | c4431bf | 2009-01-15 21:29:24 +0000 | [diff] [blame] | 824 | offMax1 = offMin + (PtrdiffT)mul.ul; |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 825 | 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? */ |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 832 | vg_assert(i >= 0 && i <= VG_(sizeXA)( fieldRs )); |
dejanj | 0abc419 | 2014-04-04 10:20:03 +0000 | [diff] [blame] | 833 | 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 | } |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 841 | /* Yes. 'field' is it. */ |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 842 | vg_assert(field); |
| 843 | if (!field->Te.Field.name) goto done; |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 844 | VG_(addBytesToXA)( xa, ".", 1 ); |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 845 | VG_(addBytesToXA)( xa, field->Te.Field.name, |
| 846 | VG_(strlen)(field->Te.Field.name) ); |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 847 | offset -= offMin; |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 848 | ty = ML_(TyEnts__index_by_cuOff)(tyents, NULL, |
| 849 | field->Te.Field.typeR ); |
florian | e2800c9 | 2014-09-15 20:57:45 +0000 | [diff] [blame] | 850 | vg_assert(ty); |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 851 | if (ty->tag == Te_UNKNOWN) goto done; |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 852 | /* keep going; look inside the field. */ |
| 853 | break; |
| 854 | } |
| 855 | |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 856 | case Te_TyArray: { |
sewardj | 50fde23 | 2008-10-20 16:08:55 +0000 | [diff] [blame] | 857 | MaybeULong mul; |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 858 | UWord size, eszB, ix; |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 859 | UWord boundR; |
| 860 | TyEnt* elemTy; |
| 861 | TyEnt* bound; |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 862 | /* Just deal with the simple, common C-case: 1-D array, |
| 863 | zero based, known size. */ |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 864 | 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) |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 870 | goto done; |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 871 | 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)) |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 879 | goto done; |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 880 | size = bound->Te.Bound.boundU - bound->Te.Bound.boundL + 1; |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 881 | vg_assert(size >= 1); |
sewardj | 50fde23 | 2008-10-20 16:08:55 +0000 | [diff] [blame] | 882 | mul = ML_(sizeOfType)( tyents, ty->Te.TyArray.typeR ); |
| 883 | if (mul.b != True) |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 884 | goto done; /* size of element type not known */ |
sewardj | 50fde23 | 2008-10-20 16:08:55 +0000 | [diff] [blame] | 885 | eszB = mul.ul; |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 886 | 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 ); |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 891 | ty = elemTy; |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 892 | offset -= ix * eszB; |
| 893 | /* keep going; look inside the array element. */ |
| 894 | break; |
| 895 | } |
| 896 | |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 897 | case Te_TyQual: { |
| 898 | ty = ML_(TyEnts__index_by_cuOff)(tyents, NULL, |
| 899 | ty->Te.TyQual.typeR); |
florian | e2800c9 | 2014-09-15 20:57:45 +0000 | [diff] [blame] | 900 | vg_assert(ty); |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 901 | if (ty->tag == Te_UNKNOWN) goto done; |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 902 | break; |
| 903 | } |
| 904 | |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 905 | case Te_TyTyDef: { |
| 906 | ty = ML_(TyEnts__index_by_cuOff)(tyents, NULL, |
| 907 | ty->Te.TyTyDef.typeR); |
florian | e2800c9 | 2014-09-15 20:57:45 +0000 | [diff] [blame] | 908 | vg_assert(ty); |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 909 | if (ty->tag == Te_UNKNOWN) goto done; |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 910 | break; |
| 911 | } |
| 912 | |
| 913 | default: { |
| 914 | VG_(printf)("ML_(describe_type): unhandled: "); |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 915 | ML_(pp_TyEnt)(ty); |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 916 | 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 | /*--------------------------------------------------------------------*/ |