libcpp, c, middle-end: Optimize initializers using #embed in C
[official-gcc.git] / gcc / dwarf2codeview.cc
blobd593795b58861ef7f0bb3e2ed40a452b4876bd97
1 /* Generate CodeView debugging info from the GCC DWARF.
2 Copyright (C) 2023 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
9 version.
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 for more details.
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
20 /* See gas/codeview.h in binutils for more about the constants and structs
21 listed below. References to Microsoft files refer to Microsoft's PDB
22 repository: https://github.com/microsoft/microsoft-pdb. */
24 #include "config.h"
25 #include "system.h"
26 #include "coretypes.h"
27 #include "target.h"
28 #include "output.h"
29 #include "errors.h"
30 #include "md5.h"
31 #include "function.h"
32 #include "version.h"
33 #include "tree.h"
34 #include "langhooks.h"
35 #include "dwarf2out.h"
36 #include "dwarf2codeview.h"
37 #include "rtl.h"
39 #ifdef CODEVIEW_DEBUGGING_INFO
41 #define CV_SIGNATURE_C13 4
43 #define DEBUG_S_SYMBOLS 0xf1
44 #define DEBUG_S_LINES 0xf2
45 #define DEBUG_S_STRINGTABLE 0xf3
46 #define DEBUG_S_FILECHKSMS 0xf4
48 #define CHKSUM_TYPE_MD5 1
50 #define CV_CFL_80386 0x03
51 #define CV_CFL_X64 0xD0
53 #define CV_CFL_C 0x00
54 #define CV_CFL_CXX 0x01
56 #define FIRST_TYPE 0x1000
58 #define LINE_LABEL "Lcvline"
59 #define END_FUNC_LABEL "Lcvendfunc"
60 #define SYMBOL_START_LABEL "Lcvsymstart"
61 #define SYMBOL_END_LABEL "Lcvsymend"
63 /* There's two bytes available for each type's size, but follow MSVC's lead in
64 capping the LF_FIELDLIST size at fb00 (minus 8 bytes for the LF_INDEX
65 pointing to the overflow entry). */
66 #define MAX_FIELDLIST_SIZE 0xfaf8
68 #define HASH_SIZE 16
70 /* This is enum SYM_ENUM_e in Microsoft's cvinfo.h. */
72 enum cv_sym_type {
73 S_END = 0x0006,
74 S_FRAMEPROC = 0x1012,
75 S_BLOCK32 = 0x1103,
76 S_REGISTER = 0x1106,
77 S_LDATA32 = 0x110c,
78 S_GDATA32 = 0x110d,
79 S_REGREL32 = 0x1111,
80 S_COMPILE3 = 0x113c,
81 S_LOCAL = 0x113e,
82 S_DEFRANGE_REGISTER = 0x1141,
83 S_DEFRANGE_REGISTER_REL = 0x1145,
84 S_LPROC32_ID = 0x1146,
85 S_GPROC32_ID = 0x1147,
86 S_PROC_ID_END = 0x114f
89 /* This is enum LEAF_ENUM_e in Microsoft's cvinfo.h. */
91 enum cv_leaf_type {
92 LF_PAD1 = 0xf1,
93 LF_PAD2 = 0xf2,
94 LF_PAD3 = 0xf3,
95 LF_MODIFIER = 0x1001,
96 LF_POINTER = 0x1002,
97 LF_PROCEDURE = 0x1008,
98 LF_MFUNCTION = 0x1009,
99 LF_ARGLIST = 0x1201,
100 LF_FIELDLIST = 0x1203,
101 LF_BITFIELD = 0x1205,
102 LF_METHODLIST = 0x1206,
103 LF_INDEX = 0x1404,
104 LF_ENUMERATE = 0x1502,
105 LF_ARRAY = 0x1503,
106 LF_CLASS = 0x1504,
107 LF_STRUCTURE = 0x1505,
108 LF_UNION = 0x1506,
109 LF_ENUM = 0x1507,
110 LF_MEMBER = 0x150d,
111 LF_STMEMBER = 0x150e,
112 LF_METHOD = 0x150f,
113 LF_ONEMETHOD = 0x1511,
114 LF_FUNC_ID = 0x1601,
115 LF_MFUNC_ID = 0x1602,
116 LF_STRING_ID = 0x1605,
117 LF_CHAR = 0x8000,
118 LF_SHORT = 0x8001,
119 LF_USHORT = 0x8002,
120 LF_LONG = 0x8003,
121 LF_ULONG = 0x8004,
122 LF_QUADWORD = 0x8009,
123 LF_UQUADWORD = 0x800a
126 /* These come from enum CV_HREG_e in Microsoft's cvconst.h. */
128 enum cv_x86_register {
129 CV_REG_NONE = 0,
130 CV_REG_AL = 1,
131 CV_REG_CL = 2,
132 CV_REG_DL = 3,
133 CV_REG_BL = 4,
134 CV_REG_AH = 5,
135 CV_REG_CH = 6,
136 CV_REG_DH = 7,
137 CV_REG_BH = 8,
138 CV_REG_AX = 9,
139 CV_REG_CX = 10,
140 CV_REG_DX = 11,
141 CV_REG_BX = 12,
142 CV_REG_SP = 13,
143 CV_REG_BP = 14,
144 CV_REG_SI = 15,
145 CV_REG_DI = 16,
146 CV_REG_EAX = 17,
147 CV_REG_ECX = 18,
148 CV_REG_EDX = 19,
149 CV_REG_EBX = 20,
150 CV_REG_ESP = 21,
151 CV_REG_EBP = 22,
152 CV_REG_ESI = 23,
153 CV_REG_EDI = 24,
154 CV_REG_ES = 25,
155 CV_REG_CS = 26,
156 CV_REG_SS = 27,
157 CV_REG_DS = 28,
158 CV_REG_FS = 29,
159 CV_REG_GS = 30,
160 CV_REG_IP = 31,
161 CV_REG_FLAGS = 32,
162 CV_REG_EIP = 33,
163 CV_REG_EFLAGS = 34,
164 CV_REG_TEMP = 40,
165 CV_REG_TEMPH = 41,
166 CV_REG_QUOTE = 42,
167 CV_REG_PCDR3 = 43,
168 CV_REG_PCDR4 = 44,
169 CV_REG_PCDR5 = 45,
170 CV_REG_PCDR6 = 46,
171 CV_REG_PCDR7 = 47,
172 CV_REG_CR0 = 80,
173 CV_REG_CR1 = 81,
174 CV_REG_CR2 = 82,
175 CV_REG_CR3 = 83,
176 CV_REG_CR4 = 84,
177 CV_REG_DR0 = 90,
178 CV_REG_DR1 = 91,
179 CV_REG_DR2 = 92,
180 CV_REG_DR3 = 93,
181 CV_REG_DR4 = 94,
182 CV_REG_DR5 = 95,
183 CV_REG_DR6 = 96,
184 CV_REG_DR7 = 97,
185 CV_REG_GDTR = 110,
186 CV_REG_GDTL = 111,
187 CV_REG_IDTR = 112,
188 CV_REG_IDTL = 113,
189 CV_REG_LDTR = 114,
190 CV_REG_TR = 115,
191 CV_REG_PSEUDO1 = 116,
192 CV_REG_PSEUDO2 = 117,
193 CV_REG_PSEUDO3 = 118,
194 CV_REG_PSEUDO4 = 119,
195 CV_REG_PSEUDO5 = 120,
196 CV_REG_PSEUDO6 = 121,
197 CV_REG_PSEUDO7 = 122,
198 CV_REG_PSEUDO8 = 123,
199 CV_REG_PSEUDO9 = 124,
200 CV_REG_ST0 = 128,
201 CV_REG_ST1 = 129,
202 CV_REG_ST2 = 130,
203 CV_REG_ST3 = 131,
204 CV_REG_ST4 = 132,
205 CV_REG_ST5 = 133,
206 CV_REG_ST6 = 134,
207 CV_REG_ST7 = 135,
208 CV_REG_CTRL = 136,
209 CV_REG_STAT = 137,
210 CV_REG_TAG = 138,
211 CV_REG_FPIP = 139,
212 CV_REG_FPCS = 140,
213 CV_REG_FPDO = 141,
214 CV_REG_FPDS = 142,
215 CV_REG_ISEM = 143,
216 CV_REG_FPEIP = 144,
217 CV_REG_FPEDO = 145,
218 CV_REG_MM0 = 146,
219 CV_REG_MM1 = 147,
220 CV_REG_MM2 = 148,
221 CV_REG_MM3 = 149,
222 CV_REG_MM4 = 150,
223 CV_REG_MM5 = 151,
224 CV_REG_MM6 = 152,
225 CV_REG_MM7 = 153,
226 CV_REG_XMM0 = 154,
227 CV_REG_XMM1 = 155,
228 CV_REG_XMM2 = 156,
229 CV_REG_XMM3 = 157,
230 CV_REG_XMM4 = 158,
231 CV_REG_XMM5 = 159,
232 CV_REG_XMM6 = 160,
233 CV_REG_XMM7 = 161,
234 CV_REG_XMM00 = 162,
235 CV_REG_XMM01 = 163,
236 CV_REG_XMM02 = 164,
237 CV_REG_XMM03 = 165,
238 CV_REG_XMM10 = 166,
239 CV_REG_XMM11 = 167,
240 CV_REG_XMM12 = 168,
241 CV_REG_XMM13 = 169,
242 CV_REG_XMM20 = 170,
243 CV_REG_XMM21 = 171,
244 CV_REG_XMM22 = 172,
245 CV_REG_XMM23 = 173,
246 CV_REG_XMM30 = 174,
247 CV_REG_XMM31 = 175,
248 CV_REG_XMM32 = 176,
249 CV_REG_XMM33 = 177,
250 CV_REG_XMM40 = 178,
251 CV_REG_XMM41 = 179,
252 CV_REG_XMM42 = 180,
253 CV_REG_XMM43 = 181,
254 CV_REG_XMM50 = 182,
255 CV_REG_XMM51 = 183,
256 CV_REG_XMM52 = 184,
257 CV_REG_XMM53 = 185,
258 CV_REG_XMM60 = 186,
259 CV_REG_XMM61 = 187,
260 CV_REG_XMM62 = 188,
261 CV_REG_XMM63 = 189,
262 CV_REG_XMM70 = 190,
263 CV_REG_XMM71 = 191,
264 CV_REG_XMM72 = 192,
265 CV_REG_XMM73 = 193,
266 CV_REG_XMM0L = 194,
267 CV_REG_XMM1L = 195,
268 CV_REG_XMM2L = 196,
269 CV_REG_XMM3L = 197,
270 CV_REG_XMM4L = 198,
271 CV_REG_XMM5L = 199,
272 CV_REG_XMM6L = 200,
273 CV_REG_XMM7L = 201,
274 CV_REG_XMM0H = 202,
275 CV_REG_XMM1H = 203,
276 CV_REG_XMM2H = 204,
277 CV_REG_XMM3H = 205,
278 CV_REG_XMM4H = 206,
279 CV_REG_XMM5H = 207,
280 CV_REG_XMM6H = 208,
281 CV_REG_XMM7H = 209,
282 CV_REG_MXCSR = 211,
283 CV_REG_EDXEAX = 212,
284 CV_REG_EMM0L = 220,
285 CV_REG_EMM1L = 221,
286 CV_REG_EMM2L = 222,
287 CV_REG_EMM3L = 223,
288 CV_REG_EMM4L = 224,
289 CV_REG_EMM5L = 225,
290 CV_REG_EMM6L = 226,
291 CV_REG_EMM7L = 227,
292 CV_REG_EMM0H = 228,
293 CV_REG_EMM1H = 229,
294 CV_REG_EMM2H = 230,
295 CV_REG_EMM3H = 231,
296 CV_REG_EMM4H = 232,
297 CV_REG_EMM5H = 233,
298 CV_REG_EMM6H = 234,
299 CV_REG_EMM7H = 235,
300 CV_REG_MM00 = 236,
301 CV_REG_MM01 = 237,
302 CV_REG_MM10 = 238,
303 CV_REG_MM11 = 239,
304 CV_REG_MM20 = 240,
305 CV_REG_MM21 = 241,
306 CV_REG_MM30 = 242,
307 CV_REG_MM31 = 243,
308 CV_REG_MM40 = 244,
309 CV_REG_MM41 = 245,
310 CV_REG_MM50 = 246,
311 CV_REG_MM51 = 247,
312 CV_REG_MM60 = 248,
313 CV_REG_MM61 = 249,
314 CV_REG_MM70 = 250,
315 CV_REG_MM71 = 251,
316 CV_REG_YMM0 = 252,
317 CV_REG_YMM1 = 253,
318 CV_REG_YMM2 = 254,
319 CV_REG_YMM3 = 255,
320 CV_REG_YMM4 = 256,
321 CV_REG_YMM5 = 257,
322 CV_REG_YMM6 = 258,
323 CV_REG_YMM7 = 259,
324 CV_REG_YMM0H = 260,
325 CV_REG_YMM1H = 261,
326 CV_REG_YMM2H = 262,
327 CV_REG_YMM3H = 263,
328 CV_REG_YMM4H = 264,
329 CV_REG_YMM5H = 265,
330 CV_REG_YMM6H = 266,
331 CV_REG_YMM7H = 267,
332 CV_REG_YMM0I0 = 268,
333 CV_REG_YMM0I1 = 269,
334 CV_REG_YMM0I2 = 270,
335 CV_REG_YMM0I3 = 271,
336 CV_REG_YMM1I0 = 272,
337 CV_REG_YMM1I1 = 273,
338 CV_REG_YMM1I2 = 274,
339 CV_REG_YMM1I3 = 275,
340 CV_REG_YMM2I0 = 276,
341 CV_REG_YMM2I1 = 277,
342 CV_REG_YMM2I2 = 278,
343 CV_REG_YMM2I3 = 279,
344 CV_REG_YMM3I0 = 280,
345 CV_REG_YMM3I1 = 281,
346 CV_REG_YMM3I2 = 282,
347 CV_REG_YMM3I3 = 283,
348 CV_REG_YMM4I0 = 284,
349 CV_REG_YMM4I1 = 285,
350 CV_REG_YMM4I2 = 286,
351 CV_REG_YMM4I3 = 287,
352 CV_REG_YMM5I0 = 288,
353 CV_REG_YMM5I1 = 289,
354 CV_REG_YMM5I2 = 290,
355 CV_REG_YMM5I3 = 291,
356 CV_REG_YMM6I0 = 292,
357 CV_REG_YMM6I1 = 293,
358 CV_REG_YMM6I2 = 294,
359 CV_REG_YMM6I3 = 295,
360 CV_REG_YMM7I0 = 296,
361 CV_REG_YMM7I1 = 297,
362 CV_REG_YMM7I2 = 298,
363 CV_REG_YMM7I3 = 299,
364 CV_REG_YMM0F0 = 300,
365 CV_REG_YMM0F1 = 301,
366 CV_REG_YMM0F2 = 302,
367 CV_REG_YMM0F3 = 303,
368 CV_REG_YMM0F4 = 304,
369 CV_REG_YMM0F5 = 305,
370 CV_REG_YMM0F6 = 306,
371 CV_REG_YMM0F7 = 307,
372 CV_REG_YMM1F0 = 308,
373 CV_REG_YMM1F1 = 309,
374 CV_REG_YMM1F2 = 310,
375 CV_REG_YMM1F3 = 311,
376 CV_REG_YMM1F4 = 312,
377 CV_REG_YMM1F5 = 313,
378 CV_REG_YMM1F6 = 314,
379 CV_REG_YMM1F7 = 315,
380 CV_REG_YMM2F0 = 316,
381 CV_REG_YMM2F1 = 317,
382 CV_REG_YMM2F2 = 318,
383 CV_REG_YMM2F3 = 319,
384 CV_REG_YMM2F4 = 320,
385 CV_REG_YMM2F5 = 321,
386 CV_REG_YMM2F6 = 322,
387 CV_REG_YMM2F7 = 323,
388 CV_REG_YMM3F0 = 324,
389 CV_REG_YMM3F1 = 325,
390 CV_REG_YMM3F2 = 326,
391 CV_REG_YMM3F3 = 327,
392 CV_REG_YMM3F4 = 328,
393 CV_REG_YMM3F5 = 329,
394 CV_REG_YMM3F6 = 330,
395 CV_REG_YMM3F7 = 331,
396 CV_REG_YMM4F0 = 332,
397 CV_REG_YMM4F1 = 333,
398 CV_REG_YMM4F2 = 334,
399 CV_REG_YMM4F3 = 335,
400 CV_REG_YMM4F4 = 336,
401 CV_REG_YMM4F5 = 337,
402 CV_REG_YMM4F6 = 338,
403 CV_REG_YMM4F7 = 339,
404 CV_REG_YMM5F0 = 340,
405 CV_REG_YMM5F1 = 341,
406 CV_REG_YMM5F2 = 342,
407 CV_REG_YMM5F3 = 343,
408 CV_REG_YMM5F4 = 344,
409 CV_REG_YMM5F5 = 345,
410 CV_REG_YMM5F6 = 346,
411 CV_REG_YMM5F7 = 347,
412 CV_REG_YMM6F0 = 348,
413 CV_REG_YMM6F1 = 349,
414 CV_REG_YMM6F2 = 350,
415 CV_REG_YMM6F3 = 351,
416 CV_REG_YMM6F4 = 352,
417 CV_REG_YMM6F5 = 353,
418 CV_REG_YMM6F6 = 354,
419 CV_REG_YMM6F7 = 355,
420 CV_REG_YMM7F0 = 356,
421 CV_REG_YMM7F1 = 357,
422 CV_REG_YMM7F2 = 358,
423 CV_REG_YMM7F3 = 359,
424 CV_REG_YMM7F4 = 360,
425 CV_REG_YMM7F5 = 361,
426 CV_REG_YMM7F6 = 362,
427 CV_REG_YMM7F7 = 363,
428 CV_REG_YMM0D0 = 364,
429 CV_REG_YMM0D1 = 365,
430 CV_REG_YMM0D2 = 366,
431 CV_REG_YMM0D3 = 367,
432 CV_REG_YMM1D0 = 368,
433 CV_REG_YMM1D1 = 369,
434 CV_REG_YMM1D2 = 370,
435 CV_REG_YMM1D3 = 371,
436 CV_REG_YMM2D0 = 372,
437 CV_REG_YMM2D1 = 373,
438 CV_REG_YMM2D2 = 374,
439 CV_REG_YMM2D3 = 375,
440 CV_REG_YMM3D0 = 376,
441 CV_REG_YMM3D1 = 377,
442 CV_REG_YMM3D2 = 378,
443 CV_REG_YMM3D3 = 379,
444 CV_REG_YMM4D0 = 380,
445 CV_REG_YMM4D1 = 381,
446 CV_REG_YMM4D2 = 382,
447 CV_REG_YMM4D3 = 383,
448 CV_REG_YMM5D0 = 384,
449 CV_REG_YMM5D1 = 385,
450 CV_REG_YMM5D2 = 386,
451 CV_REG_YMM5D3 = 387,
452 CV_REG_YMM6D0 = 388,
453 CV_REG_YMM6D1 = 389,
454 CV_REG_YMM6D2 = 390,
455 CV_REG_YMM6D3 = 391,
456 CV_REG_YMM7D0 = 392,
457 CV_REG_YMM7D1 = 393,
458 CV_REG_YMM7D2 = 394,
459 CV_REG_YMM7D3 = 395,
460 CV_REG_BND0 = 396,
461 CV_REG_BND1 = 397,
462 CV_REG_BND2 = 398,
463 CV_REG_BND3 = 399
466 enum cv_amd64_register {
467 CV_AMD64_NOREG = 0,
468 CV_AMD64_AL = 1,
469 CV_AMD64_CL = 2,
470 CV_AMD64_DL = 3,
471 CV_AMD64_BL = 4,
472 CV_AMD64_AH = 5,
473 CV_AMD64_CH = 6,
474 CV_AMD64_DH = 7,
475 CV_AMD64_BH = 8,
476 CV_AMD64_AX = 9,
477 CV_AMD64_CX = 10,
478 CV_AMD64_DX = 11,
479 CV_AMD64_BX = 12,
480 CV_AMD64_SP = 13,
481 CV_AMD64_BP = 14,
482 CV_AMD64_SI = 15,
483 CV_AMD64_DI = 16,
484 CV_AMD64_EAX = 17,
485 CV_AMD64_ECX = 18,
486 CV_AMD64_EDX = 19,
487 CV_AMD64_EBX = 20,
488 CV_AMD64_ESP = 21,
489 CV_AMD64_EBP = 22,
490 CV_AMD64_ESI = 23,
491 CV_AMD64_EDI = 24,
492 CV_AMD64_ES = 25,
493 CV_AMD64_CS = 26,
494 CV_AMD64_SS = 27,
495 CV_AMD64_DS = 28,
496 CV_AMD64_FS = 29,
497 CV_AMD64_GS = 30,
498 CV_AMD64_FLAGS = 32,
499 CV_AMD64_RIP = 33,
500 CV_AMD64_EFLAGS = 34,
501 CV_AMD64_CR0 = 80,
502 CV_AMD64_CR1 = 81,
503 CV_AMD64_CR2 = 82,
504 CV_AMD64_CR3 = 83,
505 CV_AMD64_CR4 = 84,
506 CV_AMD64_CR8 = 88,
507 CV_AMD64_DR0 = 90,
508 CV_AMD64_DR1 = 91,
509 CV_AMD64_DR2 = 92,
510 CV_AMD64_DR3 = 93,
511 CV_AMD64_DR4 = 94,
512 CV_AMD64_DR5 = 95,
513 CV_AMD64_DR6 = 96,
514 CV_AMD64_DR7 = 97,
515 CV_AMD64_DR8 = 98,
516 CV_AMD64_DR9 = 99,
517 CV_AMD64_DR10 = 100,
518 CV_AMD64_DR11 = 101,
519 CV_AMD64_DR12 = 102,
520 CV_AMD64_DR13 = 103,
521 CV_AMD64_DR14 = 104,
522 CV_AMD64_DR15 = 105,
523 CV_AMD64_GDTR = 110,
524 CV_AMD64_GDTL = 111,
525 CV_AMD64_IDTR = 112,
526 CV_AMD64_IDTL = 113,
527 CV_AMD64_LDTR = 114,
528 CV_AMD64_TR = 115,
529 CV_AMD64_ST0 = 128,
530 CV_AMD64_ST1 = 129,
531 CV_AMD64_ST2 = 130,
532 CV_AMD64_ST3 = 131,
533 CV_AMD64_ST4 = 132,
534 CV_AMD64_ST5 = 133,
535 CV_AMD64_ST6 = 134,
536 CV_AMD64_ST7 = 135,
537 CV_AMD64_CTRL = 136,
538 CV_AMD64_STAT = 137,
539 CV_AMD64_TAG = 138,
540 CV_AMD64_FPIP = 139,
541 CV_AMD64_FPCS = 140,
542 CV_AMD64_FPDO = 141,
543 CV_AMD64_FPDS = 142,
544 CV_AMD64_ISEM = 143,
545 CV_AMD64_FPEIP = 144,
546 CV_AMD64_FPEDO = 145,
547 CV_AMD64_MM0 = 146,
548 CV_AMD64_MM1 = 147,
549 CV_AMD64_MM2 = 148,
550 CV_AMD64_MM3 = 149,
551 CV_AMD64_MM4 = 150,
552 CV_AMD64_MM5 = 151,
553 CV_AMD64_MM6 = 152,
554 CV_AMD64_MM7 = 153,
555 CV_AMD64_XMM0 = 154,
556 CV_AMD64_XMM1 = 155,
557 CV_AMD64_XMM2 = 156,
558 CV_AMD64_XMM3 = 157,
559 CV_AMD64_XMM4 = 158,
560 CV_AMD64_XMM5 = 159,
561 CV_AMD64_XMM6 = 160,
562 CV_AMD64_XMM7 = 161,
563 CV_AMD64_XMM0_0 = 162,
564 CV_AMD64_XMM0_1 = 163,
565 CV_AMD64_XMM0_2 = 164,
566 CV_AMD64_XMM0_3 = 165,
567 CV_AMD64_XMM1_0 = 166,
568 CV_AMD64_XMM1_1 = 167,
569 CV_AMD64_XMM1_2 = 168,
570 CV_AMD64_XMM1_3 = 169,
571 CV_AMD64_XMM2_0 = 170,
572 CV_AMD64_XMM2_1 = 171,
573 CV_AMD64_XMM2_2 = 172,
574 CV_AMD64_XMM2_3 = 173,
575 CV_AMD64_XMM3_0 = 174,
576 CV_AMD64_XMM3_1 = 175,
577 CV_AMD64_XMM3_2 = 176,
578 CV_AMD64_XMM3_3 = 177,
579 CV_AMD64_XMM4_0 = 178,
580 CV_AMD64_XMM4_1 = 179,
581 CV_AMD64_XMM4_2 = 180,
582 CV_AMD64_XMM4_3 = 181,
583 CV_AMD64_XMM5_0 = 182,
584 CV_AMD64_XMM5_1 = 183,
585 CV_AMD64_XMM5_2 = 184,
586 CV_AMD64_XMM5_3 = 185,
587 CV_AMD64_XMM6_0 = 186,
588 CV_AMD64_XMM6_1 = 187,
589 CV_AMD64_XMM6_2 = 188,
590 CV_AMD64_XMM6_3 = 189,
591 CV_AMD64_XMM7_0 = 190,
592 CV_AMD64_XMM7_1 = 191,
593 CV_AMD64_XMM7_2 = 192,
594 CV_AMD64_XMM7_3 = 193,
595 CV_AMD64_XMM0L = 194,
596 CV_AMD64_XMM1L = 195,
597 CV_AMD64_XMM2L = 196,
598 CV_AMD64_XMM3L = 197,
599 CV_AMD64_XMM4L = 198,
600 CV_AMD64_XMM5L = 199,
601 CV_AMD64_XMM6L = 200,
602 CV_AMD64_XMM7L = 201,
603 CV_AMD64_XMM0H = 202,
604 CV_AMD64_XMM1H = 203,
605 CV_AMD64_XMM2H = 204,
606 CV_AMD64_XMM3H = 205,
607 CV_AMD64_XMM4H = 206,
608 CV_AMD64_XMM5H = 207,
609 CV_AMD64_XMM6H = 208,
610 CV_AMD64_XMM7H = 209,
611 CV_AMD64_MXCSR = 211,
612 CV_AMD64_EMM0L = 220,
613 CV_AMD64_EMM1L = 221,
614 CV_AMD64_EMM2L = 222,
615 CV_AMD64_EMM3L = 223,
616 CV_AMD64_EMM4L = 224,
617 CV_AMD64_EMM5L = 225,
618 CV_AMD64_EMM6L = 226,
619 CV_AMD64_EMM7L = 227,
620 CV_AMD64_EMM0H = 228,
621 CV_AMD64_EMM1H = 229,
622 CV_AMD64_EMM2H = 230,
623 CV_AMD64_EMM3H = 231,
624 CV_AMD64_EMM4H = 232,
625 CV_AMD64_EMM5H = 233,
626 CV_AMD64_EMM6H = 234,
627 CV_AMD64_EMM7H = 235,
628 CV_AMD64_MM00 = 236,
629 CV_AMD64_MM01 = 237,
630 CV_AMD64_MM10 = 238,
631 CV_AMD64_MM11 = 239,
632 CV_AMD64_MM20 = 240,
633 CV_AMD64_MM21 = 241,
634 CV_AMD64_MM30 = 242,
635 CV_AMD64_MM31 = 243,
636 CV_AMD64_MM40 = 244,
637 CV_AMD64_MM41 = 245,
638 CV_AMD64_MM50 = 246,
639 CV_AMD64_MM51 = 247,
640 CV_AMD64_MM60 = 248,
641 CV_AMD64_MM61 = 249,
642 CV_AMD64_MM70 = 250,
643 CV_AMD64_MM71 = 251,
644 CV_AMD64_XMM8 = 252,
645 CV_AMD64_XMM9 = 253,
646 CV_AMD64_XMM10 = 254,
647 CV_AMD64_XMM11 = 255,
648 CV_AMD64_XMM12 = 256,
649 CV_AMD64_XMM13 = 257,
650 CV_AMD64_XMM14 = 258,
651 CV_AMD64_XMM15 = 259,
652 CV_AMD64_XMM8_0 = 260,
653 CV_AMD64_XMM8_1 = 261,
654 CV_AMD64_XMM8_2 = 262,
655 CV_AMD64_XMM8_3 = 263,
656 CV_AMD64_XMM9_0 = 264,
657 CV_AMD64_XMM9_1 = 265,
658 CV_AMD64_XMM9_2 = 266,
659 CV_AMD64_XMM9_3 = 267,
660 CV_AMD64_XMM10_0 = 268,
661 CV_AMD64_XMM10_1 = 269,
662 CV_AMD64_XMM10_2 = 270,
663 CV_AMD64_XMM10_3 = 271,
664 CV_AMD64_XMM11_0 = 272,
665 CV_AMD64_XMM11_1 = 273,
666 CV_AMD64_XMM11_2 = 274,
667 CV_AMD64_XMM11_3 = 275,
668 CV_AMD64_XMM12_0 = 276,
669 CV_AMD64_XMM12_1 = 277,
670 CV_AMD64_XMM12_2 = 278,
671 CV_AMD64_XMM12_3 = 279,
672 CV_AMD64_XMM13_0 = 280,
673 CV_AMD64_XMM13_1 = 281,
674 CV_AMD64_XMM13_2 = 282,
675 CV_AMD64_XMM13_3 = 283,
676 CV_AMD64_XMM14_0 = 284,
677 CV_AMD64_XMM14_1 = 285,
678 CV_AMD64_XMM14_2 = 286,
679 CV_AMD64_XMM14_3 = 287,
680 CV_AMD64_XMM15_0 = 288,
681 CV_AMD64_XMM15_1 = 289,
682 CV_AMD64_XMM15_2 = 290,
683 CV_AMD64_XMM15_3 = 291,
684 CV_AMD64_XMM8L = 292,
685 CV_AMD64_XMM9L = 293,
686 CV_AMD64_XMM10L = 294,
687 CV_AMD64_XMM11L = 295,
688 CV_AMD64_XMM12L = 296,
689 CV_AMD64_XMM13L = 297,
690 CV_AMD64_XMM14L = 298,
691 CV_AMD64_XMM15L = 299,
692 CV_AMD64_XMM8H = 300,
693 CV_AMD64_XMM9H = 301,
694 CV_AMD64_XMM10H = 302,
695 CV_AMD64_XMM11H = 303,
696 CV_AMD64_XMM12H = 304,
697 CV_AMD64_XMM13H = 305,
698 CV_AMD64_XMM14H = 306,
699 CV_AMD64_XMM15H = 307,
700 CV_AMD64_EMM8L = 308,
701 CV_AMD64_EMM9L = 309,
702 CV_AMD64_EMM10L = 310,
703 CV_AMD64_EMM11L = 311,
704 CV_AMD64_EMM12L = 312,
705 CV_AMD64_EMM13L = 313,
706 CV_AMD64_EMM14L = 314,
707 CV_AMD64_EMM15L = 315,
708 CV_AMD64_EMM8H = 316,
709 CV_AMD64_EMM9H = 317,
710 CV_AMD64_EMM10H = 318,
711 CV_AMD64_EMM11H = 319,
712 CV_AMD64_EMM12H = 320,
713 CV_AMD64_EMM13H = 321,
714 CV_AMD64_EMM14H = 322,
715 CV_AMD64_EMM15H = 323,
716 CV_AMD64_SIL = 324,
717 CV_AMD64_DIL = 325,
718 CV_AMD64_BPL = 326,
719 CV_AMD64_SPL = 327,
720 CV_AMD64_RAX = 328,
721 CV_AMD64_RBX = 329,
722 CV_AMD64_RCX = 330,
723 CV_AMD64_RDX = 331,
724 CV_AMD64_RSI = 332,
725 CV_AMD64_RDI = 333,
726 CV_AMD64_RBP = 334,
727 CV_AMD64_RSP = 335,
728 CV_AMD64_R8 = 336,
729 CV_AMD64_R9 = 337,
730 CV_AMD64_R10 = 338,
731 CV_AMD64_R11 = 339,
732 CV_AMD64_R12 = 340,
733 CV_AMD64_R13 = 341,
734 CV_AMD64_R14 = 342,
735 CV_AMD64_R15 = 343,
736 CV_AMD64_R8B = 344,
737 CV_AMD64_R9B = 345,
738 CV_AMD64_R10B = 346,
739 CV_AMD64_R11B = 347,
740 CV_AMD64_R12B = 348,
741 CV_AMD64_R13B = 349,
742 CV_AMD64_R14B = 350,
743 CV_AMD64_R15B = 351,
744 CV_AMD64_R8W = 352,
745 CV_AMD64_R9W = 353,
746 CV_AMD64_R10W = 354,
747 CV_AMD64_R11W = 355,
748 CV_AMD64_R12W = 356,
749 CV_AMD64_R13W = 357,
750 CV_AMD64_R14W = 358,
751 CV_AMD64_R15W = 359,
752 CV_AMD64_R8D = 360,
753 CV_AMD64_R9D = 361,
754 CV_AMD64_R10D = 362,
755 CV_AMD64_R11D = 363,
756 CV_AMD64_R12D = 364,
757 CV_AMD64_R13D = 365,
758 CV_AMD64_R14D = 366,
759 CV_AMD64_R15D = 367,
760 CV_AMD64_YMM0 = 368,
761 CV_AMD64_YMM1 = 369,
762 CV_AMD64_YMM2 = 370,
763 CV_AMD64_YMM3 = 371,
764 CV_AMD64_YMM4 = 372,
765 CV_AMD64_YMM5 = 373,
766 CV_AMD64_YMM6 = 374,
767 CV_AMD64_YMM7 = 375,
768 CV_AMD64_YMM8 = 376,
769 CV_AMD64_YMM9 = 377,
770 CV_AMD64_YMM10 = 378,
771 CV_AMD64_YMM11 = 379,
772 CV_AMD64_YMM12 = 380,
773 CV_AMD64_YMM13 = 381,
774 CV_AMD64_YMM14 = 382,
775 CV_AMD64_YMM15 = 383,
776 CV_AMD64_YMM0H = 384,
777 CV_AMD64_YMM1H = 385,
778 CV_AMD64_YMM2H = 386,
779 CV_AMD64_YMM3H = 387,
780 CV_AMD64_YMM4H = 388,
781 CV_AMD64_YMM5H = 389,
782 CV_AMD64_YMM6H = 390,
783 CV_AMD64_YMM7H = 391,
784 CV_AMD64_YMM8H = 392,
785 CV_AMD64_YMM9H = 393,
786 CV_AMD64_YMM10H = 394,
787 CV_AMD64_YMM11H = 395,
788 CV_AMD64_YMM12H = 396,
789 CV_AMD64_YMM13H = 397,
790 CV_AMD64_YMM14H = 398,
791 CV_AMD64_YMM15H = 399,
792 CV_AMD64_XMM0IL = 400,
793 CV_AMD64_XMM1IL = 401,
794 CV_AMD64_XMM2IL = 402,
795 CV_AMD64_XMM3IL = 403,
796 CV_AMD64_XMM4IL = 404,
797 CV_AMD64_XMM5IL = 405,
798 CV_AMD64_XMM6IL = 406,
799 CV_AMD64_XMM7IL = 407,
800 CV_AMD64_XMM8IL = 408,
801 CV_AMD64_XMM9IL = 409,
802 CV_AMD64_XMM10IL = 410,
803 CV_AMD64_XMM11IL = 411,
804 CV_AMD64_XMM12IL = 412,
805 CV_AMD64_XMM13IL = 413,
806 CV_AMD64_XMM14IL = 414,
807 CV_AMD64_XMM15IL = 415,
808 CV_AMD64_XMM0IH = 416,
809 CV_AMD64_XMM1IH = 417,
810 CV_AMD64_XMM2IH = 418,
811 CV_AMD64_XMM3IH = 419,
812 CV_AMD64_XMM4IH = 420,
813 CV_AMD64_XMM5IH = 421,
814 CV_AMD64_XMM6IH = 422,
815 CV_AMD64_XMM7IH = 423,
816 CV_AMD64_XMM8IH = 424,
817 CV_AMD64_XMM9IH = 425,
818 CV_AMD64_XMM10IH = 426,
819 CV_AMD64_XMM11IH = 427,
820 CV_AMD64_XMM12IH = 428,
821 CV_AMD64_XMM13IH = 429,
822 CV_AMD64_XMM14IH = 430,
823 CV_AMD64_XMM15IH = 431,
824 CV_AMD64_YMM0I0 = 432,
825 CV_AMD64_YMM0I1 = 433,
826 CV_AMD64_YMM0I2 = 434,
827 CV_AMD64_YMM0I3 = 435,
828 CV_AMD64_YMM1I0 = 436,
829 CV_AMD64_YMM1I1 = 437,
830 CV_AMD64_YMM1I2 = 438,
831 CV_AMD64_YMM1I3 = 439,
832 CV_AMD64_YMM2I0 = 440,
833 CV_AMD64_YMM2I1 = 441,
834 CV_AMD64_YMM2I2 = 442,
835 CV_AMD64_YMM2I3 = 443,
836 CV_AMD64_YMM3I0 = 444,
837 CV_AMD64_YMM3I1 = 445,
838 CV_AMD64_YMM3I2 = 446,
839 CV_AMD64_YMM3I3 = 447,
840 CV_AMD64_YMM4I0 = 448,
841 CV_AMD64_YMM4I1 = 449,
842 CV_AMD64_YMM4I2 = 450,
843 CV_AMD64_YMM4I3 = 451,
844 CV_AMD64_YMM5I0 = 452,
845 CV_AMD64_YMM5I1 = 453,
846 CV_AMD64_YMM5I2 = 454,
847 CV_AMD64_YMM5I3 = 455,
848 CV_AMD64_YMM6I0 = 456,
849 CV_AMD64_YMM6I1 = 457,
850 CV_AMD64_YMM6I2 = 458,
851 CV_AMD64_YMM6I3 = 459,
852 CV_AMD64_YMM7I0 = 460,
853 CV_AMD64_YMM7I1 = 461,
854 CV_AMD64_YMM7I2 = 462,
855 CV_AMD64_YMM7I3 = 463,
856 CV_AMD64_YMM8I0 = 464,
857 CV_AMD64_YMM8I1 = 465,
858 CV_AMD64_YMM8I2 = 466,
859 CV_AMD64_YMM8I3 = 467,
860 CV_AMD64_YMM9I0 = 468,
861 CV_AMD64_YMM9I1 = 469,
862 CV_AMD64_YMM9I2 = 470,
863 CV_AMD64_YMM9I3 = 471,
864 CV_AMD64_YMM10I0 = 472,
865 CV_AMD64_YMM10I1 = 473,
866 CV_AMD64_YMM10I2 = 474,
867 CV_AMD64_YMM10I3 = 475,
868 CV_AMD64_YMM11I0 = 476,
869 CV_AMD64_YMM11I1 = 477,
870 CV_AMD64_YMM11I2 = 478,
871 CV_AMD64_YMM11I3 = 479,
872 CV_AMD64_YMM12I0 = 480,
873 CV_AMD64_YMM12I1 = 481,
874 CV_AMD64_YMM12I2 = 482,
875 CV_AMD64_YMM12I3 = 483,
876 CV_AMD64_YMM13I0 = 484,
877 CV_AMD64_YMM13I1 = 485,
878 CV_AMD64_YMM13I2 = 486,
879 CV_AMD64_YMM13I3 = 487,
880 CV_AMD64_YMM14I0 = 488,
881 CV_AMD64_YMM14I1 = 489,
882 CV_AMD64_YMM14I2 = 490,
883 CV_AMD64_YMM14I3 = 491,
884 CV_AMD64_YMM15I0 = 492,
885 CV_AMD64_YMM15I1 = 493,
886 CV_AMD64_YMM15I2 = 494,
887 CV_AMD64_YMM15I3 = 495,
888 CV_AMD64_YMM0F0 = 496,
889 CV_AMD64_YMM0F1 = 497,
890 CV_AMD64_YMM0F2 = 498,
891 CV_AMD64_YMM0F3 = 499,
892 CV_AMD64_YMM0F4 = 500,
893 CV_AMD64_YMM0F5 = 501,
894 CV_AMD64_YMM0F6 = 502,
895 CV_AMD64_YMM0F7 = 503,
896 CV_AMD64_YMM1F0 = 504,
897 CV_AMD64_YMM1F1 = 505,
898 CV_AMD64_YMM1F2 = 506,
899 CV_AMD64_YMM1F3 = 507,
900 CV_AMD64_YMM1F4 = 508,
901 CV_AMD64_YMM1F5 = 509,
902 CV_AMD64_YMM1F6 = 510,
903 CV_AMD64_YMM1F7 = 511,
904 CV_AMD64_YMM2F0 = 512,
905 CV_AMD64_YMM2F1 = 513,
906 CV_AMD64_YMM2F2 = 514,
907 CV_AMD64_YMM2F3 = 515,
908 CV_AMD64_YMM2F4 = 516,
909 CV_AMD64_YMM2F5 = 517,
910 CV_AMD64_YMM2F6 = 518,
911 CV_AMD64_YMM2F7 = 519,
912 CV_AMD64_YMM3F0 = 520,
913 CV_AMD64_YMM3F1 = 521,
914 CV_AMD64_YMM3F2 = 522,
915 CV_AMD64_YMM3F3 = 523,
916 CV_AMD64_YMM3F4 = 524,
917 CV_AMD64_YMM3F5 = 525,
918 CV_AMD64_YMM3F6 = 526,
919 CV_AMD64_YMM3F7 = 527,
920 CV_AMD64_YMM4F0 = 528,
921 CV_AMD64_YMM4F1 = 529,
922 CV_AMD64_YMM4F2 = 530,
923 CV_AMD64_YMM4F3 = 531,
924 CV_AMD64_YMM4F4 = 532,
925 CV_AMD64_YMM4F5 = 533,
926 CV_AMD64_YMM4F6 = 534,
927 CV_AMD64_YMM4F7 = 535,
928 CV_AMD64_YMM5F0 = 536,
929 CV_AMD64_YMM5F1 = 537,
930 CV_AMD64_YMM5F2 = 538,
931 CV_AMD64_YMM5F3 = 539,
932 CV_AMD64_YMM5F4 = 540,
933 CV_AMD64_YMM5F5 = 541,
934 CV_AMD64_YMM5F6 = 542,
935 CV_AMD64_YMM5F7 = 543,
936 CV_AMD64_YMM6F0 = 544,
937 CV_AMD64_YMM6F1 = 545,
938 CV_AMD64_YMM6F2 = 546,
939 CV_AMD64_YMM6F3 = 547,
940 CV_AMD64_YMM6F4 = 548,
941 CV_AMD64_YMM6F5 = 549,
942 CV_AMD64_YMM6F6 = 550,
943 CV_AMD64_YMM6F7 = 551,
944 CV_AMD64_YMM7F0 = 552,
945 CV_AMD64_YMM7F1 = 553,
946 CV_AMD64_YMM7F2 = 554,
947 CV_AMD64_YMM7F3 = 555,
948 CV_AMD64_YMM7F4 = 556,
949 CV_AMD64_YMM7F5 = 557,
950 CV_AMD64_YMM7F6 = 558,
951 CV_AMD64_YMM7F7 = 559,
952 CV_AMD64_YMM8F0 = 560,
953 CV_AMD64_YMM8F1 = 561,
954 CV_AMD64_YMM8F2 = 562,
955 CV_AMD64_YMM8F3 = 563,
956 CV_AMD64_YMM8F4 = 564,
957 CV_AMD64_YMM8F5 = 565,
958 CV_AMD64_YMM8F6 = 566,
959 CV_AMD64_YMM8F7 = 567,
960 CV_AMD64_YMM9F0 = 568,
961 CV_AMD64_YMM9F1 = 569,
962 CV_AMD64_YMM9F2 = 570,
963 CV_AMD64_YMM9F3 = 571,
964 CV_AMD64_YMM9F4 = 572,
965 CV_AMD64_YMM9F5 = 573,
966 CV_AMD64_YMM9F6 = 574,
967 CV_AMD64_YMM9F7 = 575,
968 CV_AMD64_YMM10F0 = 576,
969 CV_AMD64_YMM10F1 = 577,
970 CV_AMD64_YMM10F2 = 578,
971 CV_AMD64_YMM10F3 = 579,
972 CV_AMD64_YMM10F4 = 580,
973 CV_AMD64_YMM10F5 = 581,
974 CV_AMD64_YMM10F6 = 582,
975 CV_AMD64_YMM10F7 = 583,
976 CV_AMD64_YMM11F0 = 584,
977 CV_AMD64_YMM11F1 = 585,
978 CV_AMD64_YMM11F2 = 586,
979 CV_AMD64_YMM11F3 = 587,
980 CV_AMD64_YMM11F4 = 588,
981 CV_AMD64_YMM11F5 = 589,
982 CV_AMD64_YMM11F6 = 590,
983 CV_AMD64_YMM11F7 = 591,
984 CV_AMD64_YMM12F0 = 592,
985 CV_AMD64_YMM12F1 = 593,
986 CV_AMD64_YMM12F2 = 594,
987 CV_AMD64_YMM12F3 = 595,
988 CV_AMD64_YMM12F4 = 596,
989 CV_AMD64_YMM12F5 = 597,
990 CV_AMD64_YMM12F6 = 598,
991 CV_AMD64_YMM12F7 = 599,
992 CV_AMD64_YMM13F0 = 600,
993 CV_AMD64_YMM13F1 = 601,
994 CV_AMD64_YMM13F2 = 602,
995 CV_AMD64_YMM13F3 = 603,
996 CV_AMD64_YMM13F4 = 604,
997 CV_AMD64_YMM13F5 = 605,
998 CV_AMD64_YMM13F6 = 606,
999 CV_AMD64_YMM13F7 = 607,
1000 CV_AMD64_YMM14F0 = 608,
1001 CV_AMD64_YMM14F1 = 609,
1002 CV_AMD64_YMM14F2 = 610,
1003 CV_AMD64_YMM14F3 = 611,
1004 CV_AMD64_YMM14F4 = 612,
1005 CV_AMD64_YMM14F5 = 613,
1006 CV_AMD64_YMM14F6 = 614,
1007 CV_AMD64_YMM14F7 = 615,
1008 CV_AMD64_YMM15F0 = 616,
1009 CV_AMD64_YMM15F1 = 617,
1010 CV_AMD64_YMM15F2 = 618,
1011 CV_AMD64_YMM15F3 = 619,
1012 CV_AMD64_YMM15F4 = 620,
1013 CV_AMD64_YMM15F5 = 621,
1014 CV_AMD64_YMM15F6 = 622,
1015 CV_AMD64_YMM15F7 = 623,
1016 CV_AMD64_YMM0D0 = 624,
1017 CV_AMD64_YMM0D1 = 625,
1018 CV_AMD64_YMM0D2 = 626,
1019 CV_AMD64_YMM0D3 = 627,
1020 CV_AMD64_YMM1D0 = 628,
1021 CV_AMD64_YMM1D1 = 629,
1022 CV_AMD64_YMM1D2 = 630,
1023 CV_AMD64_YMM1D3 = 631,
1024 CV_AMD64_YMM2D0 = 632,
1025 CV_AMD64_YMM2D1 = 633,
1026 CV_AMD64_YMM2D2 = 634,
1027 CV_AMD64_YMM2D3 = 635,
1028 CV_AMD64_YMM3D0 = 636,
1029 CV_AMD64_YMM3D1 = 637,
1030 CV_AMD64_YMM3D2 = 638,
1031 CV_AMD64_YMM3D3 = 639,
1032 CV_AMD64_YMM4D0 = 640,
1033 CV_AMD64_YMM4D1 = 641,
1034 CV_AMD64_YMM4D2 = 642,
1035 CV_AMD64_YMM4D3 = 643,
1036 CV_AMD64_YMM5D0 = 644,
1037 CV_AMD64_YMM5D1 = 645,
1038 CV_AMD64_YMM5D2 = 646,
1039 CV_AMD64_YMM5D3 = 647,
1040 CV_AMD64_YMM6D0 = 648,
1041 CV_AMD64_YMM6D1 = 649,
1042 CV_AMD64_YMM6D2 = 650,
1043 CV_AMD64_YMM6D3 = 651,
1044 CV_AMD64_YMM7D0 = 652,
1045 CV_AMD64_YMM7D1 = 653,
1046 CV_AMD64_YMM7D2 = 654,
1047 CV_AMD64_YMM7D3 = 655,
1048 CV_AMD64_YMM8D0 = 656,
1049 CV_AMD64_YMM8D1 = 657,
1050 CV_AMD64_YMM8D2 = 658,
1051 CV_AMD64_YMM8D3 = 659,
1052 CV_AMD64_YMM9D0 = 660,
1053 CV_AMD64_YMM9D1 = 661,
1054 CV_AMD64_YMM9D2 = 662,
1055 CV_AMD64_YMM9D3 = 663,
1056 CV_AMD64_YMM10D0 = 664,
1057 CV_AMD64_YMM10D1 = 665,
1058 CV_AMD64_YMM10D2 = 666,
1059 CV_AMD64_YMM10D3 = 667,
1060 CV_AMD64_YMM11D0 = 668,
1061 CV_AMD64_YMM11D1 = 669,
1062 CV_AMD64_YMM11D2 = 670,
1063 CV_AMD64_YMM11D3 = 671,
1064 CV_AMD64_YMM12D0 = 672,
1065 CV_AMD64_YMM12D1 = 673,
1066 CV_AMD64_YMM12D2 = 674,
1067 CV_AMD64_YMM12D3 = 675,
1068 CV_AMD64_YMM13D0 = 676,
1069 CV_AMD64_YMM13D1 = 677,
1070 CV_AMD64_YMM13D2 = 678,
1071 CV_AMD64_YMM13D3 = 679,
1072 CV_AMD64_YMM14D0 = 680,
1073 CV_AMD64_YMM14D1 = 681,
1074 CV_AMD64_YMM14D2 = 682,
1075 CV_AMD64_YMM14D3 = 683,
1076 CV_AMD64_YMM15D0 = 684,
1077 CV_AMD64_YMM15D1 = 685,
1078 CV_AMD64_YMM15D2 = 686,
1079 CV_AMD64_YMM15D3 = 687
1082 struct codeview_string
1084 codeview_string *next;
1085 uint32_t offset;
1086 char *string;
1089 struct string_hasher : free_ptr_hash <struct codeview_string>
1091 typedef const char *compare_type;
1093 static hashval_t hash (const codeview_string *x)
1095 return htab_hash_string (x->string);
1098 static bool equal (const codeview_string *x, const char *y)
1100 return !strcmp (x->string, y);
1103 static void mark_empty (codeview_string *x)
1105 if (x->string)
1107 free (x->string);
1108 x->string = NULL;
1112 static void remove (codeview_string *&x)
1114 free (x->string);
1118 struct codeview_source_file
1120 codeview_source_file *next;
1121 unsigned int file_num;
1122 uint32_t string_offset;
1123 char *filename;
1124 uint8_t hash[HASH_SIZE];
1127 struct codeview_line
1129 codeview_line *next;
1130 unsigned int line_no;
1131 unsigned int label_num;
1134 struct codeview_line_block
1136 codeview_line_block *next;
1137 uint32_t file_id;
1138 unsigned int num_lines;
1139 codeview_line *lines, *last_line;
1142 struct codeview_function
1144 codeview_function *next;
1145 function *func;
1146 unsigned int end_label;
1147 codeview_line_block *blocks, *last_block;
1150 struct codeview_symbol
1152 codeview_symbol *next;
1153 enum cv_sym_type kind;
1155 union
1157 struct
1159 uint32_t type;
1160 char *name;
1161 dw_die_ref die;
1162 } data_symbol;
1163 struct
1165 uint32_t parent;
1166 uint32_t end;
1167 uint32_t next;
1168 uint32_t type;
1169 uint8_t flags;
1170 char *name;
1171 dw_die_ref die;
1172 } function;
1176 struct codeview_type
1178 dw_die_ref die;
1179 uint32_t num;
1180 bool is_fwd_ref;
1183 struct die_hasher : free_ptr_hash <codeview_type>
1185 typedef dw_die_ref compare_type;
1187 static hashval_t hash (const codeview_type *x)
1189 return htab_hash_pointer (x->die);
1192 static bool equal (const codeview_type *x, const dw_die_ref y)
1194 return x->die == y;
1198 struct codeview_integer
1200 bool neg;
1201 uint64_t num;
1204 struct codeview_subtype
1206 struct codeview_subtype *next;
1207 enum cv_leaf_type kind;
1209 union
1211 struct
1213 char *name;
1214 struct codeview_integer value;
1215 } lf_enumerate;
1216 struct
1218 uint32_t type_num;
1219 } lf_index;
1220 struct
1222 uint16_t attributes;
1223 uint32_t type;
1224 codeview_integer offset;
1225 char *name;
1226 } lf_member;
1227 struct
1229 uint16_t attributes;
1230 uint32_t type;
1231 char *name;
1232 } lf_static_member;
1233 struct
1235 uint16_t method_attribute;
1236 uint32_t method_type;
1237 char *name;
1238 } lf_onemethod;
1239 struct
1241 uint16_t count;
1242 uint32_t method_list;
1243 char *name;
1244 } lf_method;
1248 struct lf_methodlist_entry
1250 uint16_t method_attribute;
1251 uint32_t method_type;
1254 struct codeview_custom_type
1256 struct codeview_custom_type *next;
1257 uint32_t num;
1258 enum cv_leaf_type kind;
1260 union
1262 struct
1264 uint32_t base_type;
1265 uint32_t attributes;
1266 } lf_pointer;
1267 struct
1269 uint32_t base_type;
1270 uint16_t modifier;
1271 } lf_modifier;
1272 struct
1274 size_t length;
1275 codeview_subtype *subtypes;
1276 codeview_subtype *last_subtype;
1277 } lf_fieldlist;
1278 struct
1280 uint16_t count;
1281 uint16_t properties;
1282 uint32_t underlying_type;
1283 uint32_t fieldlist;
1284 char *name;
1285 } lf_enum;
1286 struct
1288 uint16_t num_members;
1289 uint16_t properties;
1290 uint32_t field_list;
1291 uint32_t derived_from;
1292 uint32_t vshape;
1293 codeview_integer length;
1294 char *name;
1295 } lf_structure;
1296 struct
1298 uint32_t element_type;
1299 uint32_t index_type;
1300 codeview_integer length_in_bytes;
1301 } lf_array;
1302 struct
1304 uint32_t base_type;
1305 uint8_t length;
1306 uint8_t position;
1307 } lf_bitfield;
1308 struct
1310 uint32_t return_type;
1311 uint8_t calling_convention;
1312 uint8_t attributes;
1313 uint16_t num_parameters;
1314 uint32_t arglist;
1315 } lf_procedure;
1316 struct
1318 uint32_t num_entries;
1319 uint32_t *args;
1320 } lf_arglist;
1321 struct
1323 uint32_t parent_scope;
1324 uint32_t function_type;
1325 char *name;
1326 } lf_func_id;
1327 struct
1329 uint32_t parent_type;
1330 uint32_t function_type;
1331 char *name;
1332 } lf_mfunc_id;
1333 struct
1335 uint32_t substring;
1336 char *string;
1337 } lf_string_id;
1338 struct
1340 uint32_t return_type;
1341 uint32_t containing_class_type;
1342 uint32_t this_type;
1343 uint8_t calling_convention;
1344 uint8_t attributes;
1345 uint16_t num_parameters;
1346 uint32_t arglist;
1347 int32_t this_adjustment;
1348 } lf_mfunction;
1349 struct
1351 unsigned int count;
1352 lf_methodlist_entry *entries;
1353 } lf_methodlist;
1357 struct codeview_deferred_type
1359 struct codeview_deferred_type *next;
1360 dw_die_ref type;
1363 struct string_id_hasher : nofree_ptr_hash <struct codeview_custom_type>
1365 typedef const char *compare_type;
1367 static hashval_t hash (const codeview_custom_type *x)
1369 return htab_hash_string (x->lf_string_id.string);
1372 static bool equal (const codeview_custom_type *x, const char *y)
1374 return !strcmp (x->lf_string_id.string, y);
1378 struct codeview_method
1380 uint16_t attribute;
1381 uint32_t type;
1382 char *name;
1383 unsigned int count;
1384 struct codeview_method *next;
1385 struct codeview_method *last;
1388 struct method_hasher : nofree_ptr_hash <struct codeview_method>
1390 typedef const char *compare_type;
1392 static hashval_t hash (const codeview_method *x)
1394 return htab_hash_string (x->name);
1397 static bool equal (const codeview_method *x, const char *y)
1399 return !strcmp (x->name, y);
1403 static unsigned int line_label_num;
1404 static unsigned int func_label_num;
1405 static unsigned int sym_label_num;
1406 static codeview_source_file *files, *last_file;
1407 static unsigned int num_files;
1408 static uint32_t string_offset = 1;
1409 static hash_table<string_hasher> *strings_htab;
1410 static codeview_string *strings, *last_string;
1411 static codeview_function *funcs, *last_func;
1412 static const char* last_filename;
1413 static uint32_t last_file_id;
1414 static codeview_symbol *sym, *last_sym;
1415 static hash_table<die_hasher> *types_htab;
1416 static codeview_custom_type *custom_types, *last_custom_type;
1417 static codeview_deferred_type *deferred_types, *last_deferred_type;
1418 static hash_table<string_id_hasher> *string_id_htab;
1420 static uint32_t get_type_num (dw_die_ref type, bool in_struct, bool no_fwd_ref);
1421 static uint32_t get_type_num_subroutine_type (dw_die_ref type, bool in_struct,
1422 uint32_t containing_class_type,
1423 uint32_t this_type,
1424 int32_t this_adjustment);
1426 /* Record new line number against the current function. */
1428 void
1429 codeview_source_line (unsigned int line_no, const char *filename)
1431 codeview_line *l;
1432 uint32_t file_id = last_file_id;
1433 unsigned int label_num = ++line_label_num;
1435 targetm.asm_out.internal_label (asm_out_file, LINE_LABEL, label_num);
1437 if (!last_func || last_func->func != cfun)
1439 codeview_function *f = (codeview_function *)
1440 xmalloc (sizeof (codeview_function));
1442 f->next = NULL;
1443 f->func = cfun;
1444 f->end_label = 0;
1445 f->blocks = f->last_block = NULL;
1447 if (!funcs)
1448 funcs = f;
1449 else
1450 last_func->next = f;
1452 last_func = f;
1455 if (filename != last_filename)
1457 codeview_source_file *sf = files;
1459 while (sf)
1461 if (!strcmp (sf->filename, filename))
1463 /* 0x18 is the size of the checksum entry for each file.
1464 0x6 bytes for the header, plus 0x10 bytes for the hash,
1465 then padded to a multiple of 4. */
1467 file_id = sf->file_num * 0x18;
1468 last_filename = filename;
1469 last_file_id = file_id;
1470 break;
1473 sf = sf->next;
1477 if (!last_func->last_block || last_func->last_block->file_id != file_id)
1479 codeview_line_block *b;
1481 b = (codeview_line_block *) xmalloc (sizeof (codeview_line_block));
1483 b->next = NULL;
1484 b->file_id = file_id;
1485 b->num_lines = 0;
1486 b->lines = b->last_line = NULL;
1488 if (!last_func->blocks)
1489 last_func->blocks = b;
1490 else
1491 last_func->last_block->next = b;
1493 last_func->last_block = b;
1496 if (last_func->last_block->last_line
1497 && last_func->last_block->last_line->line_no == line_no)
1498 return;
1500 l = (codeview_line *) xmalloc (sizeof (codeview_line));
1502 l->next = NULL;
1503 l->line_no = line_no;
1504 l->label_num = label_num;
1506 if (!last_func->last_block->lines)
1507 last_func->last_block->lines = l;
1508 else
1509 last_func->last_block->last_line->next = l;
1511 last_func->last_block->last_line = l;
1512 last_func->last_block->num_lines++;
1515 /* Adds string to the string table, returning its offset. If already present,
1516 this returns the offset of the existing string. */
1518 static uint32_t
1519 add_string (const char *string)
1521 codeview_string **slot;
1522 codeview_string *s;
1523 size_t len;
1525 if (!strings_htab)
1526 strings_htab = new hash_table<string_hasher> (10);
1528 slot = strings_htab->find_slot_with_hash (string, htab_hash_string (string),
1529 INSERT);
1531 if (*slot)
1532 return (*slot)->offset;
1534 s = (codeview_string *) xmalloc (sizeof (codeview_string));
1535 len = strlen (string);
1537 s->next = NULL;
1539 s->offset = string_offset;
1540 string_offset += len + 1;
1542 s->string = xstrdup (string);
1544 if (last_string)
1545 last_string->next = s;
1546 else
1547 strings = s;
1549 last_string = s;
1551 *slot = s;
1553 return s->offset;
1556 /* A new source file has been encountered - record the details and calculate
1557 its hash. */
1559 void
1560 codeview_start_source_file (const char *filename)
1562 codeview_source_file *sf;
1563 char *path;
1564 uint32_t string_offset;
1565 FILE *f;
1567 path = lrealpath (filename);
1568 string_offset = add_string (path);
1569 free (path);
1571 sf = files;
1572 while (sf)
1574 if (sf->string_offset == string_offset)
1575 return;
1577 sf = sf->next;
1580 sf = (codeview_source_file *) xmalloc (sizeof (codeview_source_file));
1581 sf->next = NULL;
1582 sf->file_num = num_files;
1583 sf->string_offset = string_offset;
1584 sf->filename = xstrdup (filename);
1586 f = fopen (filename, "r");
1587 if (!f)
1588 internal_error ("could not open %s for reading", filename);
1590 if (md5_stream (f, sf->hash))
1592 fclose (f);
1593 internal_error ("md5_stream failed");
1596 fclose (f);
1598 if (last_file)
1599 last_file->next = sf;
1600 else
1601 files = sf;
1603 last_file = sf;
1604 num_files++;
1607 /* Write out the strings table into the .debug$S section. The linker will
1608 parse this, and handle the deduplication and hashing for all the object
1609 files. */
1611 static void
1612 write_strings_table (void)
1614 codeview_string *string;
1616 fputs (integer_asm_op (4, false), asm_out_file);
1617 fprint_whex (asm_out_file, DEBUG_S_STRINGTABLE);
1618 putc ('\n', asm_out_file);
1620 fputs (integer_asm_op (4, false), asm_out_file);
1621 asm_fprintf (asm_out_file, "%LLcv_strings_end - %LLcv_strings_start\n");
1623 asm_fprintf (asm_out_file, "%LLcv_strings_start:\n");
1625 /* The first entry is always an empty string. */
1626 fputs (integer_asm_op (1, false), asm_out_file);
1627 fprint_whex (asm_out_file, 0);
1628 putc ('\n', asm_out_file);
1630 string = strings;
1631 while (string)
1633 ASM_OUTPUT_ASCII (asm_out_file, string->string,
1634 strlen (string->string) + 1);
1636 string = string->next;
1639 delete strings_htab;
1641 asm_fprintf (asm_out_file, "%LLcv_strings_end:\n");
1643 ASM_OUTPUT_ALIGN (asm_out_file, 2);
1646 /* Write out the file checksums data into the .debug$S section. */
1648 static void
1649 write_source_files (void)
1651 fputs (integer_asm_op (4, false), asm_out_file);
1652 fprint_whex (asm_out_file, DEBUG_S_FILECHKSMS);
1653 putc ('\n', asm_out_file);
1655 fputs (integer_asm_op (4, false), asm_out_file);
1656 asm_fprintf (asm_out_file,
1657 "%LLcv_filechksms_end - %LLcv_filechksms_start\n");
1659 asm_fprintf (asm_out_file, "%LLcv_filechksms_start:\n");
1661 while (files)
1663 codeview_source_file *next = files->next;
1665 /* This is struct file_checksum in binutils, or filedata in Microsoft's
1666 dumpsym7.cpp:
1668 struct file_checksum
1670 uint32_t file_id;
1671 uint8_t checksum_length;
1672 uint8_t checksum_type;
1673 } ATTRIBUTE_PACKED;
1675 followed then by the bytes of the hash, padded to the next 4 bytes.
1676 file_id here is actually the offset in the strings table. */
1678 fputs (integer_asm_op (4, false), asm_out_file);
1679 fprint_whex (asm_out_file, files->string_offset);
1680 putc ('\n', asm_out_file);
1682 fputs (integer_asm_op (1, false), asm_out_file);
1683 fprint_whex (asm_out_file, HASH_SIZE);
1684 putc ('\n', asm_out_file);
1686 fputs (integer_asm_op (1, false), asm_out_file);
1687 fprint_whex (asm_out_file, CHKSUM_TYPE_MD5);
1688 putc ('\n', asm_out_file);
1690 for (unsigned int i = 0; i < HASH_SIZE; i++)
1692 fputs (integer_asm_op (1, false), asm_out_file);
1693 fprint_whex (asm_out_file, files->hash[i]);
1694 putc ('\n', asm_out_file);
1697 ASM_OUTPUT_ALIGN (asm_out_file, 2);
1699 free (files->filename);
1700 free (files);
1702 files = next;
1705 asm_fprintf (asm_out_file, "%LLcv_filechksms_end:\n");
1708 /* Write out the line number information for each function into the
1709 .debug$S section. */
1711 static void
1712 write_line_numbers (void)
1714 unsigned int func_num = 0;
1716 while (funcs)
1718 codeview_function *next = funcs->next;
1719 unsigned int first_label_num;
1721 fputs (integer_asm_op (4, false), asm_out_file);
1722 fprint_whex (asm_out_file, DEBUG_S_LINES);
1723 putc ('\n', asm_out_file);
1725 fputs (integer_asm_op (4, false), asm_out_file);
1726 asm_fprintf (asm_out_file, "%LLcv_lines%u_end - %LLcv_lines%u_start\n",
1727 func_num, func_num);
1729 asm_fprintf (asm_out_file, "%LLcv_lines%u_start:\n", func_num);
1731 /* Output the header (struct cv_lines_header in binutils or
1732 CV_DebugSLinesHeader_t in Microsoft's cvinfo.h):
1734 struct cv_lines_header
1736 uint32_t offset;
1737 uint16_t section;
1738 uint16_t flags;
1739 uint32_t length;
1743 asm_fprintf (asm_out_file, "\t.secrel32\t%L" LINE_LABEL "%u\n",
1744 funcs->blocks->lines->label_num);
1745 asm_fprintf (asm_out_file, "\t.secidx\t%L" LINE_LABEL "%u\n",
1746 funcs->blocks->lines->label_num);
1748 /* flags */
1749 fputs (integer_asm_op (2, false), asm_out_file);
1750 fprint_whex (asm_out_file, 0);
1751 putc ('\n', asm_out_file);
1753 first_label_num = funcs->blocks->lines->label_num;
1755 /* length */
1756 fputs (integer_asm_op (4, false), asm_out_file);
1757 asm_fprintf (asm_out_file,
1758 "%L" END_FUNC_LABEL "%u - %L" LINE_LABEL "%u\n",
1759 funcs->end_label, first_label_num);
1761 while (funcs->blocks)
1763 codeview_line_block *next = funcs->blocks->next;
1765 /* Next comes the blocks, each block being a part of a function
1766 within the same source file (struct cv_lines_block in binutils or
1767 CV_DebugSLinesFileBlockHeader_t in Microsoft's cvinfo.h):
1769 struct cv_lines_block
1771 uint32_t file_id;
1772 uint32_t num_lines;
1773 uint32_t length;
1777 /* file ID */
1778 fputs (integer_asm_op (4, false), asm_out_file);
1779 fprint_whex (asm_out_file, funcs->blocks->file_id);
1780 putc ('\n', asm_out_file);
1782 /* number of lines */
1783 fputs (integer_asm_op (4, false), asm_out_file);
1784 fprint_whex (asm_out_file, funcs->blocks->num_lines);
1785 putc ('\n', asm_out_file);
1787 /* length of code block: (num_lines * sizeof (struct cv_line)) +
1788 sizeof (struct cv_lines_block) */
1789 fputs (integer_asm_op (4, false), asm_out_file);
1790 fprint_whex (asm_out_file, (funcs->blocks->num_lines * 0x8) + 0xc);
1791 putc ('\n', asm_out_file);
1793 while (funcs->blocks->lines)
1795 codeview_line *next = funcs->blocks->lines->next;
1797 /* Finally comes the line number information (struct cv_line in
1798 binutils or CV_Line_t in Microsoft's cvinfo.h):
1800 struct cv_line
1802 uint32_t offset;
1803 uint32_t line_no;
1806 Strictly speaking line_no is a bitfield: the bottom 24 bits
1807 are the line number, and the top bit means "is a statement".
1810 fputs (integer_asm_op (4, false), asm_out_file);
1811 asm_fprintf (asm_out_file,
1812 "%L" LINE_LABEL "%u - %L" LINE_LABEL "%u\n",
1813 funcs->blocks->lines->label_num, first_label_num);
1815 fputs (integer_asm_op (4, false), asm_out_file);
1816 fprint_whex (asm_out_file,
1817 0x80000000
1818 | (funcs->blocks->lines->line_no & 0xffffff));
1819 putc ('\n', asm_out_file);
1821 free (funcs->blocks->lines);
1823 funcs->blocks->lines = next;
1826 free (funcs->blocks);
1828 funcs->blocks = next;
1831 free (funcs);
1833 asm_fprintf (asm_out_file, "%LLcv_lines%u_end:\n", func_num);
1834 func_num++;
1836 funcs = next;
1840 /* Treat cold sections as separate functions, for the purposes of line
1841 numbers. */
1843 void
1844 codeview_switch_text_section (void)
1846 codeview_function *f;
1848 if (last_func && last_func->end_label == 0)
1850 unsigned int label_num = ++func_label_num;
1852 targetm.asm_out.internal_label (asm_out_file, END_FUNC_LABEL,
1853 label_num);
1855 last_func->end_label = label_num;
1858 f = (codeview_function *) xmalloc (sizeof (codeview_function));
1860 f->next = NULL;
1861 f->func = cfun;
1862 f->end_label = 0;
1863 f->blocks = f->last_block = NULL;
1865 if (!funcs)
1866 funcs = f;
1867 else
1868 last_func->next = f;
1870 last_func = f;
1873 /* Mark the end of the current function. */
1875 void
1876 codeview_end_epilogue (void)
1878 if (last_func && last_func->end_label == 0)
1880 unsigned int label_num = ++func_label_num;
1882 targetm.asm_out.internal_label (asm_out_file, END_FUNC_LABEL,
1883 label_num);
1885 last_func->end_label = label_num;
1889 /* Return the CodeView constant for the selected architecture. */
1891 static uint16_t
1892 target_processor (void)
1894 if (TARGET_64BIT)
1895 return CV_CFL_X64;
1896 else
1897 return CV_CFL_80386;
1900 /* Return the CodeView constant for the language being used. */
1902 static uint32_t
1903 language_constant (void)
1905 const char *language_string = lang_hooks.name;
1907 if (startswith (language_string, "GNU C++"))
1908 return CV_CFL_CXX;
1909 else if (startswith (language_string, "GNU C"))
1910 return CV_CFL_C;
1912 return 0;
1915 /* Write a S_COMPILE3 symbol, which records the details of the compiler
1916 being used. */
1918 static void
1919 write_compile3_symbol (void)
1921 unsigned int label_num = ++sym_label_num;
1923 static const char compiler_name[] = "GCC ";
1925 /* This is struct COMPILESYM3 in binutils and Microsoft's cvinfo.h:
1927 struct COMPILESYM3
1929 uint16_t length;
1930 uint16_t type;
1931 uint32_t flags;
1932 uint16_t machine;
1933 uint16_t frontend_major;
1934 uint16_t frontend_minor;
1935 uint16_t frontend_build;
1936 uint16_t frontend_qfe;
1937 uint16_t backend_major;
1938 uint16_t backend_minor;
1939 uint16_t backend_build;
1940 uint16_t backend_qfe;
1941 } ATTRIBUTE_PACKED;
1944 fputs (integer_asm_op (2, false), asm_out_file);
1945 asm_fprintf (asm_out_file,
1946 "%L" SYMBOL_END_LABEL "%u - %L" SYMBOL_START_LABEL "%u\n",
1947 label_num, label_num);
1949 targetm.asm_out.internal_label (asm_out_file, SYMBOL_START_LABEL, label_num);
1951 fputs (integer_asm_op (2, false), asm_out_file);
1952 fprint_whex (asm_out_file, S_COMPILE3);
1953 putc ('\n', asm_out_file);
1955 /* Microsoft has the flags as a bitfield, with the bottom 8 bits being the
1956 language constant, and the reset being MSVC-specific stuff. */
1957 fputs (integer_asm_op (4, false), asm_out_file);
1958 fprint_whex (asm_out_file, language_constant ());
1959 putc ('\n', asm_out_file);
1961 fputs (integer_asm_op (2, false), asm_out_file);
1962 fprint_whex (asm_out_file, target_processor ());
1963 putc ('\n', asm_out_file);
1965 /* Write 8 uint16_ts for the frontend and backend versions. As with GAS, we
1966 zero these, as it's easier to record the version in the compiler
1967 string. */
1968 for (unsigned int i = 0; i < 8; i++)
1970 fputs (integer_asm_op (2, false), asm_out_file);
1971 fprint_whex (asm_out_file, 0);
1972 putc ('\n', asm_out_file);
1975 ASM_OUTPUT_ASCII (asm_out_file, compiler_name, sizeof (compiler_name) - 1);
1976 ASM_OUTPUT_ASCII (asm_out_file, version_string, strlen (version_string) + 1);
1978 ASM_OUTPUT_ALIGN (asm_out_file, 2);
1980 targetm.asm_out.internal_label (asm_out_file, SYMBOL_END_LABEL, label_num);
1983 /* Write an S_GDATA32 symbol, representing a global variable, or an S_LDATA32
1984 symbol, for a static global variable. */
1986 static void
1987 write_data_symbol (codeview_symbol *s)
1989 unsigned int label_num = ++sym_label_num;
1990 dw_attr_node *loc;
1991 dw_loc_descr_ref loc_ref;
1993 /* This is struct datasym in binutils:
1995 struct datasym
1997 uint16_t size;
1998 uint16_t kind;
1999 uint32_t type;
2000 uint32_t offset;
2001 uint16_t section;
2002 char name[];
2003 } ATTRIBUTE_PACKED;
2006 /* Extract the DW_AT_location attribute from the DIE, and make sure it's in
2007 in a format we can parse. */
2009 loc = get_AT (s->data_symbol.die, DW_AT_location);
2010 if (!loc)
2011 goto end;
2013 if (loc->dw_attr_val.val_class != dw_val_class_loc)
2014 goto end;
2016 loc_ref = loc->dw_attr_val.v.val_loc;
2017 if (!loc_ref || loc_ref->dw_loc_opc != DW_OP_addr)
2018 goto end;
2020 /* Output the S_GDATA32 / S_LDATA32 record. */
2022 fputs (integer_asm_op (2, false), asm_out_file);
2023 asm_fprintf (asm_out_file,
2024 "%L" SYMBOL_END_LABEL "%u - %L" SYMBOL_START_LABEL "%u\n",
2025 label_num, label_num);
2027 targetm.asm_out.internal_label (asm_out_file, SYMBOL_START_LABEL, label_num);
2029 fputs (integer_asm_op (2, false), asm_out_file);
2030 fprint_whex (asm_out_file, s->kind);
2031 putc ('\n', asm_out_file);
2033 fputs (integer_asm_op (4, false), asm_out_file);
2034 fprint_whex (asm_out_file, s->data_symbol.type);
2035 putc ('\n', asm_out_file);
2037 asm_fprintf (asm_out_file, "\t.secrel32 ");
2038 output_addr_const (asm_out_file, loc_ref->dw_loc_oprnd1.v.val_addr);
2039 fputc ('\n', asm_out_file);
2041 asm_fprintf (asm_out_file, "\t.secidx ");
2042 output_addr_const (asm_out_file, loc_ref->dw_loc_oprnd1.v.val_addr);
2043 fputc ('\n', asm_out_file);
2045 ASM_OUTPUT_ASCII (asm_out_file, s->data_symbol.name,
2046 strlen (s->data_symbol.name) + 1);
2048 ASM_OUTPUT_ALIGN (asm_out_file, 2);
2050 targetm.asm_out.internal_label (asm_out_file, SYMBOL_END_LABEL, label_num);
2052 end:
2053 free (s->data_symbol.name);
2056 /* Write an S_LOCAL symbol, representing an optimized variable. This is then
2057 followed by various S_DEFRANGE_* symbols, which describe how to find the
2058 value of a variable and the range for which this is valid. */
2060 static void
2061 write_s_local (dw_die_ref die)
2063 unsigned int label_num = ++sym_label_num;
2064 const char *name = get_AT_string (die, DW_AT_name);
2065 uint32_t type;
2067 /* This is struct LOCALSYM in Microsoft's cvinfo.h:
2069 struct LOCALSYM {
2070 uint16_t reclen;
2071 uint16_t rectyp;
2072 uint32_t typind;
2073 uint16_t flags;
2074 char name[];
2078 fputs (integer_asm_op (2, false), asm_out_file);
2079 asm_fprintf (asm_out_file,
2080 "%L" SYMBOL_END_LABEL "%u - %L" SYMBOL_START_LABEL "%u\n",
2081 label_num, label_num);
2083 targetm.asm_out.internal_label (asm_out_file, SYMBOL_START_LABEL, label_num);
2085 fputs (integer_asm_op (2, false), asm_out_file);
2086 fprint_whex (asm_out_file, S_LOCAL);
2087 putc ('\n', asm_out_file);
2089 type = get_type_num (get_AT_ref (die, DW_AT_type), false, false);
2091 fputs (integer_asm_op (4, false), asm_out_file);
2092 fprint_whex (asm_out_file, type);
2093 putc ('\n', asm_out_file);
2095 fputs (integer_asm_op (2, false), asm_out_file);
2096 fprint_whex (asm_out_file, 0);
2097 putc ('\n', asm_out_file);
2099 ASM_OUTPUT_ASCII (asm_out_file, name, strlen (name) + 1);
2101 ASM_OUTPUT_ALIGN (asm_out_file, 2);
2103 targetm.asm_out.internal_label (asm_out_file, SYMBOL_END_LABEL, label_num);
2106 /* Write an S_LDATA32 symbol, representing a static variable within a function.
2107 This symbol can also appear outside of a function block - see
2108 write_data_symbol. */
2110 static void
2111 write_local_s_ldata32 (dw_die_ref die, dw_loc_descr_ref loc_ref)
2113 unsigned int label_num = ++sym_label_num;
2114 const char *name = get_AT_string (die, DW_AT_name);
2115 uint32_t type;
2117 /* This is struct datasym in binutils:
2119 struct datasym
2121 uint16_t size;
2122 uint16_t kind;
2123 uint32_t type;
2124 uint32_t offset;
2125 uint16_t section;
2126 char name[];
2127 } ATTRIBUTE_PACKED;
2130 fputs (integer_asm_op (2, false), asm_out_file);
2131 asm_fprintf (asm_out_file,
2132 "%L" SYMBOL_END_LABEL "%u - %L" SYMBOL_START_LABEL "%u\n",
2133 label_num, label_num);
2135 targetm.asm_out.internal_label (asm_out_file, SYMBOL_START_LABEL, label_num);
2137 fputs (integer_asm_op (2, false), asm_out_file);
2138 fprint_whex (asm_out_file, S_LDATA32);
2139 putc ('\n', asm_out_file);
2141 type = get_type_num (get_AT_ref (die, DW_AT_type), false, false);
2143 fputs (integer_asm_op (4, false), asm_out_file);
2144 fprint_whex (asm_out_file, type);
2145 putc ('\n', asm_out_file);
2147 asm_fprintf (asm_out_file, "\t.secrel32 ");
2148 output_addr_const (asm_out_file, loc_ref->dw_loc_oprnd1.v.val_addr);
2149 fputc ('\n', asm_out_file);
2151 asm_fprintf (asm_out_file, "\t.secidx ");
2152 output_addr_const (asm_out_file, loc_ref->dw_loc_oprnd1.v.val_addr);
2153 fputc ('\n', asm_out_file);
2155 ASM_OUTPUT_ASCII (asm_out_file, name, strlen (name) + 1);
2157 ASM_OUTPUT_ALIGN (asm_out_file, 2);
2159 targetm.asm_out.internal_label (asm_out_file, SYMBOL_END_LABEL, label_num);
2162 /* Try to translate a DWARF register number into its CodeView equivalent. */
2164 static uint16_t
2165 dwarf_reg_to_cv (unsigned int regno)
2167 static const cv_amd64_register amd64_reg_mapping[] = {
2168 CV_AMD64_RAX,
2169 CV_AMD64_RDX,
2170 CV_AMD64_RCX,
2171 CV_AMD64_RBX,
2172 CV_AMD64_RSI,
2173 CV_AMD64_RDI,
2174 CV_AMD64_RBP,
2175 CV_AMD64_RSP,
2176 CV_AMD64_R8,
2177 CV_AMD64_R9,
2178 CV_AMD64_R10,
2179 CV_AMD64_R11,
2180 CV_AMD64_R12,
2181 CV_AMD64_R13,
2182 CV_AMD64_R14,
2183 CV_AMD64_R15,
2184 CV_AMD64_RIP,
2185 CV_AMD64_XMM0,
2186 CV_AMD64_XMM1,
2187 CV_AMD64_XMM2,
2188 CV_AMD64_XMM3,
2189 CV_AMD64_XMM4,
2190 CV_AMD64_XMM5,
2191 CV_AMD64_XMM6,
2192 CV_AMD64_XMM7,
2193 CV_AMD64_XMM8,
2194 CV_AMD64_XMM9,
2195 CV_AMD64_XMM10,
2196 CV_AMD64_XMM11,
2197 CV_AMD64_XMM12,
2198 CV_AMD64_XMM13,
2199 CV_AMD64_XMM14,
2200 CV_AMD64_XMM15,
2201 CV_AMD64_ST0,
2202 CV_AMD64_ST1,
2203 CV_AMD64_ST2,
2204 CV_AMD64_ST3,
2205 CV_AMD64_ST4,
2206 CV_AMD64_ST5,
2207 CV_AMD64_ST6,
2208 CV_AMD64_ST7,
2209 CV_AMD64_NOREG,
2210 CV_AMD64_NOREG,
2211 CV_AMD64_NOREG,
2212 CV_AMD64_NOREG,
2213 CV_AMD64_NOREG,
2214 CV_AMD64_NOREG,
2215 CV_AMD64_NOREG,
2216 CV_AMD64_NOREG,
2217 CV_AMD64_EFLAGS,
2218 CV_AMD64_ES,
2219 CV_AMD64_CS,
2220 CV_AMD64_SS,
2221 CV_AMD64_DS,
2222 CV_AMD64_FS,
2223 CV_AMD64_GS,
2224 CV_AMD64_NOREG,
2225 CV_AMD64_NOREG,
2226 CV_AMD64_NOREG,
2227 CV_AMD64_NOREG,
2228 CV_AMD64_NOREG,
2229 CV_AMD64_NOREG,
2230 CV_AMD64_TR,
2231 CV_AMD64_LDTR,
2232 CV_AMD64_MXCSR,
2233 CV_AMD64_CTRL,
2234 CV_AMD64_STAT
2237 static const cv_x86_register x86_reg_mapping[] = {
2238 CV_REG_EAX,
2239 CV_REG_ECX,
2240 CV_REG_EDX,
2241 CV_REG_EBX,
2242 CV_REG_EBP,
2243 CV_REG_ESP,
2244 CV_REG_ESI,
2245 CV_REG_EDI,
2246 CV_REG_EIP,
2247 CV_REG_EFLAGS,
2248 CV_REG_CS,
2249 CV_REG_SS,
2250 CV_REG_DS,
2251 CV_REG_ES,
2252 CV_REG_FS,
2253 CV_REG_GS,
2254 CV_REG_ST0,
2255 CV_REG_ST1,
2256 CV_REG_ST2,
2257 CV_REG_ST3,
2258 CV_REG_ST4,
2259 CV_REG_ST5,
2260 CV_REG_ST6,
2261 CV_REG_ST7,
2262 CV_REG_CTRL,
2263 CV_REG_STAT,
2264 CV_REG_TAG,
2265 CV_REG_FPCS,
2266 CV_REG_FPIP,
2267 CV_REG_FPDS,
2268 CV_REG_FPDO,
2269 CV_REG_NONE,
2270 CV_REG_XMM0,
2271 CV_REG_XMM1,
2272 CV_REG_XMM2,
2273 CV_REG_XMM3,
2274 CV_REG_XMM4,
2275 CV_REG_XMM5,
2276 CV_REG_XMM6,
2277 CV_REG_XMM7,
2278 CV_REG_MXCSR
2281 if (TARGET_64BIT)
2283 if (regno < sizeof (amd64_reg_mapping) / sizeof (*amd64_reg_mapping))
2284 return amd64_reg_mapping[regno];
2286 return CV_AMD64_NOREG;
2288 else
2290 if (regno < sizeof (x86_reg_mapping) / sizeof (*x86_reg_mapping))
2291 return x86_reg_mapping[regno];
2293 return CV_REG_NONE;
2297 /* Write an S_REGISTER symbol, representing an unoptimized variable that has
2298 been assigned to a register. */
2300 static void
2301 write_s_register (dw_die_ref die, dw_loc_descr_ref loc_ref)
2303 unsigned int label_num = ++sym_label_num;
2304 const char *name = get_AT_string (die, DW_AT_name);
2305 uint16_t regno;
2306 uint32_t type;
2308 /* This is struct regsym in binutils and REGSYM in Microsoft's cvinfo.h:
2310 struct regsym
2312 uint16_t size;
2313 uint16_t kind;
2314 uint32_t type;
2315 uint16_t reg;
2316 char name[];
2317 } ATTRIBUTE_PACKED;
2320 if (loc_ref->dw_loc_opc == DW_OP_regx)
2321 regno = dwarf_reg_to_cv (loc_ref->dw_loc_oprnd1.v.val_int);
2322 else
2323 regno = dwarf_reg_to_cv (loc_ref->dw_loc_opc - DW_OP_reg0);
2325 if (regno == 0)
2326 return;
2328 fputs (integer_asm_op (2, false), asm_out_file);
2329 asm_fprintf (asm_out_file,
2330 "%L" SYMBOL_END_LABEL "%u - %L" SYMBOL_START_LABEL "%u\n",
2331 label_num, label_num);
2333 targetm.asm_out.internal_label (asm_out_file, SYMBOL_START_LABEL, label_num);
2335 fputs (integer_asm_op (2, false), asm_out_file);
2336 fprint_whex (asm_out_file, S_REGISTER);
2337 putc ('\n', asm_out_file);
2339 type = get_type_num (get_AT_ref (die, DW_AT_type), false, false);
2341 fputs (integer_asm_op (4, false), asm_out_file);
2342 fprint_whex (asm_out_file, type);
2343 putc ('\n', asm_out_file);
2345 fputs (integer_asm_op (2, false), asm_out_file);
2346 fprint_whex (asm_out_file, regno);
2347 putc ('\n', asm_out_file);
2349 ASM_OUTPUT_ASCII (asm_out_file, name, strlen (name) + 1);
2351 ASM_OUTPUT_ALIGN (asm_out_file, 2);
2353 targetm.asm_out.internal_label (asm_out_file, SYMBOL_END_LABEL, label_num);
2356 /* Write an S_REGREL32 symbol in order to represent an unoptimized stack
2357 variable. The memory address is given by a register value plus an offset,
2358 so we need to parse the function's DW_AT_frame_base attribute for this. */
2360 static void
2361 write_fbreg_variable (dw_die_ref die, dw_loc_descr_ref loc_ref,
2362 dw_loc_descr_ref fbloc)
2364 unsigned int label_num = ++sym_label_num;
2365 const char *name = get_AT_string (die, DW_AT_name);
2366 uint32_t type;
2367 uint16_t regno;
2368 int offset;
2370 /* This is struct regrel in binutils and REGREL32 in Microsoft's cvinfo.h:
2372 struct regrel
2374 uint16_t size;
2375 uint16_t kind;
2376 uint32_t offset;
2377 uint32_t type;
2378 uint16_t reg;
2379 char name[];
2380 } ATTRIBUTE_PACKED;
2383 if (!fbloc)
2384 return;
2386 if (fbloc->dw_loc_opc >= DW_OP_breg0 && fbloc->dw_loc_opc <= DW_OP_breg31)
2388 regno = dwarf_reg_to_cv (fbloc->dw_loc_opc - DW_OP_breg0);
2389 offset = fbloc->dw_loc_oprnd1.v.val_int;
2391 else if (fbloc->dw_loc_opc == DW_OP_bregx)
2393 regno = dwarf_reg_to_cv (fbloc->dw_loc_oprnd1.v.val_int);
2394 offset = fbloc->dw_loc_oprnd2.v.val_int;
2396 else
2398 return;
2401 if (loc_ref->dw_loc_oprnd1.val_class != dw_val_class_unsigned_const)
2402 return;
2404 offset += loc_ref->dw_loc_oprnd1.v.val_int;
2406 fputs (integer_asm_op (2, false), asm_out_file);
2407 asm_fprintf (asm_out_file,
2408 "%L" SYMBOL_END_LABEL "%u - %L" SYMBOL_START_LABEL "%u\n",
2409 label_num, label_num);
2411 targetm.asm_out.internal_label (asm_out_file, SYMBOL_START_LABEL, label_num);
2413 fputs (integer_asm_op (2, false), asm_out_file);
2414 fprint_whex (asm_out_file, S_REGREL32);
2415 putc ('\n', asm_out_file);
2417 fputs (integer_asm_op (4, false), asm_out_file);
2418 fprint_whex (asm_out_file, offset);
2419 putc ('\n', asm_out_file);
2421 type = get_type_num (get_AT_ref (die, DW_AT_type), false, false);
2423 fputs (integer_asm_op (4, false), asm_out_file);
2424 fprint_whex (asm_out_file, type);
2425 putc ('\n', asm_out_file);
2427 fputs (integer_asm_op (2, false), asm_out_file);
2428 fprint_whex (asm_out_file, regno);
2429 putc ('\n', asm_out_file);
2431 ASM_OUTPUT_ASCII (asm_out_file, name, strlen (name) + 1);
2433 ASM_OUTPUT_ALIGN (asm_out_file, 2);
2435 targetm.asm_out.internal_label (asm_out_file, SYMBOL_END_LABEL, label_num);
2438 /* Write an S_DEFRANGE_REGISTER symbol, which describes a range for which an
2439 S_LOCAL variable is held in a certain register. */
2441 static void
2442 write_defrange_register (dw_loc_descr_ref expr, rtx range_start, rtx range_end)
2444 unsigned int label_num = ++sym_label_num;
2445 uint16_t regno;
2447 /* This is defrange_register in binutils and DEFRANGESYMREGISTER in
2448 Microsoft's cvinfo.h:
2450 struct lvar_addr_range
2452 uint32_t offset;
2453 uint16_t section;
2454 uint16_t length;
2455 } ATTRIBUTE_PACKED;
2457 struct lvar_addr_gap {
2458 uint16_t offset;
2459 uint16_t length;
2460 } ATTRIBUTE_PACKED;
2462 struct defrange_register
2464 uint16_t size;
2465 uint16_t kind;
2466 uint16_t reg;
2467 uint16_t attributes;
2468 struct lvar_addr_range range;
2469 struct lvar_addr_gap gaps[];
2470 } ATTRIBUTE_PACKED;
2473 if (expr->dw_loc_opc == DW_OP_regx)
2474 regno = dwarf_reg_to_cv (expr->dw_loc_oprnd1.v.val_int);
2475 else
2476 regno = dwarf_reg_to_cv (expr->dw_loc_opc - DW_OP_reg0);
2478 if (regno == 0)
2479 return;
2481 fputs (integer_asm_op (2, false), asm_out_file);
2482 asm_fprintf (asm_out_file,
2483 "%L" SYMBOL_END_LABEL "%u - %L" SYMBOL_START_LABEL "%u\n",
2484 label_num, label_num);
2486 targetm.asm_out.internal_label (asm_out_file, SYMBOL_START_LABEL, label_num);
2488 fputs (integer_asm_op (2, false), asm_out_file);
2489 fprint_whex (asm_out_file, S_DEFRANGE_REGISTER);
2490 putc ('\n', asm_out_file);
2492 fputs (integer_asm_op (2, false), asm_out_file);
2493 fprint_whex (asm_out_file, regno);
2494 putc ('\n', asm_out_file);
2496 fputs (integer_asm_op (2, false), asm_out_file);
2497 fprint_whex (asm_out_file, 0);
2498 putc ('\n', asm_out_file);
2500 asm_fprintf (asm_out_file, "\t.secrel32 ");
2501 output_addr_const (asm_out_file, range_start);
2502 fputc ('\n', asm_out_file);
2504 asm_fprintf (asm_out_file, "\t.secidx ");
2505 output_addr_const (asm_out_file, range_start);
2506 fputc ('\n', asm_out_file);
2508 fputs (integer_asm_op (2, false), asm_out_file);
2509 output_addr_const (asm_out_file, range_end);
2510 fputs (" - ", asm_out_file);
2511 output_addr_const (asm_out_file, range_start);
2512 putc ('\n', asm_out_file);
2514 targetm.asm_out.internal_label (asm_out_file, SYMBOL_END_LABEL, label_num);
2517 /* Write an S_DEFRANGE_REGISTER_REL symbol, which describes a range for which
2518 an S_LOCAL variable is held in memory given by the value of a certain
2519 register plus an offset. */
2521 static void
2522 write_defrange_register_rel (dw_loc_descr_ref expr, dw_loc_descr_ref fbloc,
2523 rtx range_start, rtx range_end)
2525 unsigned int label_num = ++sym_label_num;
2526 uint16_t regno;
2527 int offset;
2529 /* This is defrange_register_rel in binutils and DEFRANGESYMREGISTERREL in
2530 Microsoft's cvinfo.h:
2532 struct lvar_addr_range
2534 uint32_t offset;
2535 uint16_t section;
2536 uint16_t length;
2537 } ATTRIBUTE_PACKED;
2539 struct lvar_addr_gap {
2540 uint16_t offset;
2541 uint16_t length;
2542 } ATTRIBUTE_PACKED;
2544 struct defrange_register_rel
2546 uint16_t size;
2547 uint16_t kind;
2548 uint16_t reg;
2549 uint16_t offset_parent;
2550 uint32_t offset_register;
2551 struct lvar_addr_range range;
2552 struct lvar_addr_gap gaps[];
2553 } ATTRIBUTE_PACKED;
2556 if (!fbloc)
2557 return;
2559 if (fbloc->dw_loc_opc >= DW_OP_breg0 && fbloc->dw_loc_opc <= DW_OP_breg31)
2561 regno = dwarf_reg_to_cv (fbloc->dw_loc_opc - DW_OP_breg0);
2562 offset = fbloc->dw_loc_oprnd1.v.val_int;
2564 else if (fbloc->dw_loc_opc == DW_OP_bregx)
2566 regno = dwarf_reg_to_cv (fbloc->dw_loc_oprnd1.v.val_int);
2567 offset = fbloc->dw_loc_oprnd2.v.val_int;
2569 else
2571 return;
2574 if (expr->dw_loc_oprnd1.val_class != dw_val_class_unsigned_const)
2575 return;
2577 offset += expr->dw_loc_oprnd1.v.val_int;
2579 fputs (integer_asm_op (2, false), asm_out_file);
2580 asm_fprintf (asm_out_file,
2581 "%L" SYMBOL_END_LABEL "%u - %L" SYMBOL_START_LABEL "%u\n",
2582 label_num, label_num);
2584 targetm.asm_out.internal_label (asm_out_file, SYMBOL_START_LABEL, label_num);
2586 fputs (integer_asm_op (2, false), asm_out_file);
2587 fprint_whex (asm_out_file, S_DEFRANGE_REGISTER_REL);
2588 putc ('\n', asm_out_file);
2590 fputs (integer_asm_op (2, false), asm_out_file);
2591 fprint_whex (asm_out_file, regno);
2592 putc ('\n', asm_out_file);
2594 fputs (integer_asm_op (2, false), asm_out_file);
2595 fprint_whex (asm_out_file, 0);
2596 putc ('\n', asm_out_file);
2598 fputs (integer_asm_op (4, false), asm_out_file);
2599 fprint_whex (asm_out_file, offset);
2600 putc ('\n', asm_out_file);
2602 asm_fprintf (asm_out_file, "\t.secrel32 ");
2603 output_addr_const (asm_out_file, range_start);
2604 fputc ('\n', asm_out_file);
2606 asm_fprintf (asm_out_file, "\t.secidx ");
2607 output_addr_const (asm_out_file, range_start);
2608 fputc ('\n', asm_out_file);
2610 fputs (integer_asm_op (2, false), asm_out_file);
2611 output_addr_const (asm_out_file, range_end);
2612 fputs (" - ", asm_out_file);
2613 output_addr_const (asm_out_file, range_start);
2614 putc ('\n', asm_out_file);
2616 targetm.asm_out.internal_label (asm_out_file, SYMBOL_END_LABEL, label_num);
2619 /* Try to write an S_DEFRANGE_* symbol for the given DWARF location. */
2621 static void
2622 write_optimized_local_variable_loc (dw_loc_descr_ref expr,
2623 dw_loc_descr_ref fbloc, rtx range_start,
2624 rtx range_end)
2626 if (expr->dw_loc_next)
2627 return;
2629 if (!range_start)
2630 return;
2632 if (!range_end)
2633 return;
2635 switch (expr->dw_loc_opc)
2637 case DW_OP_reg0:
2638 case DW_OP_reg1:
2639 case DW_OP_reg2:
2640 case DW_OP_reg3:
2641 case DW_OP_reg4:
2642 case DW_OP_reg5:
2643 case DW_OP_reg6:
2644 case DW_OP_reg7:
2645 case DW_OP_reg8:
2646 case DW_OP_reg9:
2647 case DW_OP_reg10:
2648 case DW_OP_reg11:
2649 case DW_OP_reg12:
2650 case DW_OP_reg13:
2651 case DW_OP_reg14:
2652 case DW_OP_reg15:
2653 case DW_OP_reg16:
2654 case DW_OP_reg17:
2655 case DW_OP_reg18:
2656 case DW_OP_reg19:
2657 case DW_OP_reg20:
2658 case DW_OP_reg21:
2659 case DW_OP_reg22:
2660 case DW_OP_reg23:
2661 case DW_OP_reg24:
2662 case DW_OP_reg25:
2663 case DW_OP_reg26:
2664 case DW_OP_reg27:
2665 case DW_OP_reg28:
2666 case DW_OP_reg29:
2667 case DW_OP_reg30:
2668 case DW_OP_reg31:
2669 case DW_OP_regx:
2670 write_defrange_register (expr, range_start, range_end);
2671 break;
2673 case DW_OP_fbreg:
2674 write_defrange_register_rel (expr, fbloc, range_start, range_end);
2675 break;
2677 default:
2678 break;
2682 /* Write an optimized local variable, given by an S_LOCAL symbol followed by
2683 any number of S_DEFRANGE_* symbols. We can't mix and match optimized and
2684 unoptimized variables in the same function, so even if it stays in the same
2685 place for the whole block we need to write an S_LOCAL. */
2687 static void
2688 write_optimized_local_variable (dw_die_ref die, dw_loc_descr_ref fbloc,
2689 rtx block_start, rtx block_end)
2691 dw_attr_node *loc;
2692 dw_loc_list_ref loc_list;
2694 loc = get_AT (die, DW_AT_location);
2695 if (!loc)
2696 return;
2698 switch (loc->dw_attr_val.val_class)
2700 case dw_val_class_loc_list:
2701 loc_list = loc->dw_attr_val.v.val_loc_list;
2703 write_s_local (die);
2705 while (loc_list)
2707 rtx range_start = NULL, range_end = NULL;
2709 if (loc_list->begin)
2710 range_start = gen_rtx_SYMBOL_REF (Pmode, loc_list->begin);
2712 if (loc_list->end)
2713 range_end = gen_rtx_SYMBOL_REF (Pmode, loc_list->end);
2715 write_optimized_local_variable_loc (loc_list->expr, fbloc,
2716 range_start, range_end);
2718 loc_list = loc_list->dw_loc_next;
2720 break;
2722 case dw_val_class_loc:
2723 write_s_local (die);
2725 write_optimized_local_variable_loc (loc->dw_attr_val.v.val_loc, fbloc,
2726 block_start, block_end);
2727 break;
2729 default:
2730 break;
2734 /* Write a symbol representing an unoptimized variable within a function, if
2735 we're able to translate the DIE's DW_AT_location into its CodeView
2736 equivalent. */
2738 static void
2739 write_unoptimized_local_variable (dw_die_ref die, dw_loc_descr_ref fbloc)
2741 dw_attr_node *loc;
2742 dw_loc_descr_ref loc_ref;
2744 loc = get_AT (die, DW_AT_location);
2745 if (!loc)
2746 return;
2748 if (loc->dw_attr_val.val_class != dw_val_class_loc)
2749 return;
2751 loc_ref = loc->dw_attr_val.v.val_loc;
2752 if (!loc_ref)
2753 return;
2755 switch (loc_ref->dw_loc_opc)
2757 case DW_OP_addr:
2758 write_local_s_ldata32 (die, loc_ref);
2759 break;
2761 case DW_OP_reg0:
2762 case DW_OP_reg1:
2763 case DW_OP_reg2:
2764 case DW_OP_reg3:
2765 case DW_OP_reg4:
2766 case DW_OP_reg5:
2767 case DW_OP_reg6:
2768 case DW_OP_reg7:
2769 case DW_OP_reg8:
2770 case DW_OP_reg9:
2771 case DW_OP_reg10:
2772 case DW_OP_reg11:
2773 case DW_OP_reg12:
2774 case DW_OP_reg13:
2775 case DW_OP_reg14:
2776 case DW_OP_reg15:
2777 case DW_OP_reg16:
2778 case DW_OP_reg17:
2779 case DW_OP_reg18:
2780 case DW_OP_reg19:
2781 case DW_OP_reg20:
2782 case DW_OP_reg21:
2783 case DW_OP_reg22:
2784 case DW_OP_reg23:
2785 case DW_OP_reg24:
2786 case DW_OP_reg25:
2787 case DW_OP_reg26:
2788 case DW_OP_reg27:
2789 case DW_OP_reg28:
2790 case DW_OP_reg29:
2791 case DW_OP_reg30:
2792 case DW_OP_reg31:
2793 case DW_OP_regx:
2794 write_s_register (die, loc_ref);
2795 break;
2797 case DW_OP_fbreg:
2798 write_fbreg_variable (die, loc_ref, fbloc);
2799 break;
2801 default:
2802 break;
2806 /* Translate a DW_TAG_lexical_block DIE into an S_BLOCK32 symbol, representing
2807 a block within an unoptimized function. Returns false if we're not able
2808 to resolve the location, which will prevent the caller from issuing an
2809 unneeded S_END. */
2811 static bool
2812 write_s_block32 (dw_die_ref die)
2814 unsigned int label_num = ++sym_label_num;
2815 dw_attr_node *loc_low, *loc_high;
2816 const char *label_low, *label_high;
2817 rtx rtx_low, rtx_high;
2819 /* This is struct blocksym in binutils and BLOCKSYM32 in Microsoft's
2820 cvinfo.h:
2822 struct blocksym
2824 uint16_t size;
2825 uint16_t kind;
2826 uint32_t parent;
2827 uint32_t end;
2828 uint32_t len;
2829 uint32_t offset;
2830 uint16_t section;
2831 char name[];
2832 } ATTRIBUTE_PACKED;
2835 loc_low = get_AT (die, DW_AT_low_pc);
2836 if (!loc_low)
2837 return false;
2839 if (loc_low->dw_attr_val.val_class != dw_val_class_lbl_id)
2840 return false;
2842 label_low = loc_low->dw_attr_val.v.val_lbl_id;
2843 if (!label_low)
2844 return false;
2846 rtx_low = gen_rtx_SYMBOL_REF (Pmode, label_low);
2848 loc_high = get_AT (die, DW_AT_high_pc);
2849 if (!loc_high)
2850 return false;
2852 if (loc_high->dw_attr_val.val_class != dw_val_class_high_pc)
2853 return false;
2855 label_high = loc_high->dw_attr_val.v.val_lbl_id;
2856 if (!label_high)
2857 return false;
2859 rtx_high = gen_rtx_SYMBOL_REF (Pmode, label_high);
2861 fputs (integer_asm_op (2, false), asm_out_file);
2862 asm_fprintf (asm_out_file,
2863 "%L" SYMBOL_END_LABEL "%u - %L" SYMBOL_START_LABEL "%u\n",
2864 label_num, label_num);
2866 targetm.asm_out.internal_label (asm_out_file, SYMBOL_START_LABEL, label_num);
2868 fputs (integer_asm_op (2, false), asm_out_file);
2869 fprint_whex (asm_out_file, S_BLOCK32);
2870 putc ('\n', asm_out_file);
2872 /* The parent and end fields get filled in by the linker. */
2874 fputs (integer_asm_op (4, false), asm_out_file);
2875 fprint_whex (asm_out_file, 0);
2876 putc ('\n', asm_out_file);
2878 fputs (integer_asm_op (4, false), asm_out_file);
2879 fprint_whex (asm_out_file, 0);
2880 putc ('\n', asm_out_file);
2882 fputs (integer_asm_op (4, false), asm_out_file);
2883 output_addr_const (asm_out_file, rtx_high);
2884 fputs (" - ", asm_out_file);
2885 output_addr_const (asm_out_file, rtx_low);
2886 putc ('\n', asm_out_file);
2888 asm_fprintf (asm_out_file, "\t.secrel32 ");
2889 output_addr_const (asm_out_file, rtx_low);
2890 fputc ('\n', asm_out_file);
2892 asm_fprintf (asm_out_file, "\t.secidx ");
2893 output_addr_const (asm_out_file, rtx_low);
2894 fputc ('\n', asm_out_file);
2896 ASM_OUTPUT_ASCII (asm_out_file, "", 1);
2898 ASM_OUTPUT_ALIGN (asm_out_file, 2);
2900 targetm.asm_out.internal_label (asm_out_file, SYMBOL_END_LABEL, label_num);
2902 return true;
2905 /* Write an S_END symbol, which is used to finish off a number of different
2906 symbol types. Here we use it to mark the S_BLOCK32 as finished. */
2908 static void
2909 write_s_end (void)
2911 unsigned int label_num = ++sym_label_num;
2913 fputs (integer_asm_op (2, false), asm_out_file);
2914 asm_fprintf (asm_out_file,
2915 "%L" SYMBOL_END_LABEL "%u - %L" SYMBOL_START_LABEL "%u\n",
2916 label_num, label_num);
2918 targetm.asm_out.internal_label (asm_out_file, SYMBOL_START_LABEL, label_num);
2920 fputs (integer_asm_op (2, false), asm_out_file);
2921 fprint_whex (asm_out_file, S_END);
2922 putc ('\n', asm_out_file);
2924 ASM_OUTPUT_ALIGN (asm_out_file, 2);
2926 targetm.asm_out.internal_label (asm_out_file, SYMBOL_END_LABEL, label_num);
2929 /* Write the S_FRAMEPROC symbol, which is supposed to give information about
2930 the function frame. It doesn't seem to be really used in modern versions of
2931 MSVC, which is why we zero-out everything here. You still need to write it
2932 though, otherwise windbg won't necessarily show all the local variables. */
2934 static void
2935 write_s_frameproc (void)
2937 unsigned int label_num = ++sym_label_num;
2939 /* This is struct FRAMEPROCSYM in Microsoft's cvinfo.h:
2941 struct frameprocsym
2943 uint16_t size;
2944 uint16_t kind;
2945 uint32_t frame_size;
2946 uint32_t padding_size;
2947 uint32_t padding_offset;
2948 uint32_t saved_registers_size;
2949 uint32_t exception_handler_offset;
2950 uint16_t exception_handler_section;
2951 uint32_t flags;
2952 } ATTRIBUTE_PACKED;
2955 fputs (integer_asm_op (2, false), asm_out_file);
2956 asm_fprintf (asm_out_file,
2957 "%L" SYMBOL_END_LABEL "%u - %L" SYMBOL_START_LABEL "%u\n",
2958 label_num, label_num);
2960 targetm.asm_out.internal_label (asm_out_file, SYMBOL_START_LABEL, label_num);
2962 fputs (integer_asm_op (2, false), asm_out_file);
2963 fprint_whex (asm_out_file, S_FRAMEPROC);
2964 putc ('\n', asm_out_file);
2966 fputs (integer_asm_op (4, false), asm_out_file);
2967 fprint_whex (asm_out_file, 0);
2968 putc ('\n', asm_out_file);
2970 fputs (integer_asm_op (4, false), asm_out_file);
2971 fprint_whex (asm_out_file, 0);
2972 putc ('\n', asm_out_file);
2974 fputs (integer_asm_op (4, false), asm_out_file);
2975 fprint_whex (asm_out_file, 0);
2976 putc ('\n', asm_out_file);
2978 fputs (integer_asm_op (4, false), asm_out_file);
2979 fprint_whex (asm_out_file, 0);
2980 putc ('\n', asm_out_file);
2982 fputs (integer_asm_op (4, false), asm_out_file);
2983 fprint_whex (asm_out_file, 0);
2984 putc ('\n', asm_out_file);
2986 fputs (integer_asm_op (2, false), asm_out_file);
2987 fprint_whex (asm_out_file, 0);
2988 putc ('\n', asm_out_file);
2990 fputs (integer_asm_op (4, false), asm_out_file);
2991 fprint_whex (asm_out_file, 0);
2992 putc ('\n', asm_out_file);
2994 targetm.asm_out.internal_label (asm_out_file, SYMBOL_END_LABEL, label_num);
2997 /* Loop through the DIEs in an unoptimized function, writing out any variables
2998 or blocks that we encounter. */
3000 static void
3001 write_unoptimized_function_vars (dw_die_ref die, dw_loc_descr_ref fbloc)
3003 dw_die_ref first_child, c;
3005 first_child = dw_get_die_child (die);
3007 if (!first_child)
3008 return;
3010 c = first_child;
3013 c = dw_get_die_sib (c);
3015 switch (dw_get_die_tag (c))
3017 case DW_TAG_formal_parameter:
3018 case DW_TAG_variable:
3019 write_unoptimized_local_variable (c, fbloc);
3020 break;
3022 case DW_TAG_lexical_block:
3024 bool block_started = write_s_block32 (c);
3026 write_unoptimized_function_vars (c, fbloc);
3028 if (block_started)
3029 write_s_end ();
3031 break;
3034 default:
3035 break;
3038 while (c != first_child);
3041 /* Write the variables in an optimized function or block. There's no S_BLOCK32s
3042 here, with the range determining the lifetime of a variable. Unfortunately
3043 for us CodeView is much less expressive than DWARF when it comes to variable
3044 locations, so some degree of "optimized out"s is inevitable. */
3046 static void
3047 write_optimized_function_vars (dw_die_ref die, dw_loc_descr_ref fbloc,
3048 rtx block_start, rtx block_end)
3050 dw_die_ref first_child, c;
3052 first_child = dw_get_die_child (die);
3054 if (!first_child)
3055 return;
3057 c = first_child;
3060 c = dw_get_die_sib (c);
3062 switch (dw_get_die_tag (c))
3064 case DW_TAG_formal_parameter:
3065 case DW_TAG_variable:
3066 write_optimized_local_variable (c, fbloc, block_start, block_end);
3067 break;
3069 case DW_TAG_lexical_block:
3071 dw_attr_node *loc_low, *loc_high;
3072 const char *label_low, *label_high;
3073 rtx rtx_low, rtx_high;
3075 loc_low = get_AT (die, DW_AT_low_pc);
3076 if (!loc_low)
3077 break;
3079 if (loc_low->dw_attr_val.val_class != dw_val_class_lbl_id)
3080 break;
3082 label_low = loc_low->dw_attr_val.v.val_lbl_id;
3083 if (!label_low)
3084 break;
3086 rtx_low = gen_rtx_SYMBOL_REF (Pmode, label_low);
3088 loc_high = get_AT (die, DW_AT_high_pc);
3089 if (!loc_high)
3090 break;
3092 if (loc_high->dw_attr_val.val_class != dw_val_class_high_pc)
3093 break;
3095 label_high = loc_high->dw_attr_val.v.val_lbl_id;
3096 if (!label_high)
3097 break;
3099 rtx_high = gen_rtx_SYMBOL_REF (Pmode, label_high);
3101 write_optimized_function_vars (c, fbloc, rtx_low, rtx_high);
3103 break;
3106 default:
3107 break;
3110 while (c != first_child);
3113 /* There's no way to mark the range of a static local variable in an optimized
3114 function: there's no S_DEFRANGE_* symbol for this, and you can't have
3115 S_BLOCK32 symbols. So instead we have to loop through after the S_FRAMEPROC
3116 has been written, and write the S_LDATA32s at the end. */
3118 static void
3119 write_optimized_static_local_vars (dw_die_ref die)
3121 dw_die_ref first_child, c;
3123 first_child = dw_get_die_child (die);
3125 if (!first_child)
3126 return;
3128 c = first_child;
3131 c = dw_get_die_sib (c);
3133 switch (dw_get_die_tag (c))
3135 case DW_TAG_variable:
3137 dw_attr_node *loc;
3138 dw_loc_descr_ref loc_ref;
3140 loc = get_AT (c, DW_AT_location);
3141 if (!loc)
3142 break;
3144 if (loc->dw_attr_val.val_class != dw_val_class_loc)
3145 break;
3147 loc_ref = loc->dw_attr_val.v.val_loc;
3148 if (!loc_ref)
3149 break;
3151 if (loc_ref->dw_loc_opc != DW_OP_addr)
3152 break;
3154 write_local_s_ldata32 (c, loc_ref);
3155 break;
3158 case DW_TAG_lexical_block:
3159 write_optimized_static_local_vars (c);
3160 break;
3162 default:
3163 break;
3166 while (c != first_child);
3169 /* Write an S_GPROC32_ID symbol, representing a global function, or an
3170 S_LPROC32_ID symbol, for a static function. */
3172 static void
3173 write_function (codeview_symbol *s)
3175 unsigned int label_num = ++sym_label_num;
3176 dw_attr_node *loc_low, *loc_high, *frame_base;
3177 const char *label_low, *label_high;
3178 rtx rtx_low, rtx_high;
3179 dw_loc_descr_ref fbloc = NULL;
3181 /* This is struct procsym in binutils and PROCSYM32 in Microsoft's cvinfo.h:
3183 struct procsym
3185 uint16_t size;
3186 uint16_t kind;
3187 uint32_t parent;
3188 uint32_t end;
3189 uint32_t next;
3190 uint32_t proc_len;
3191 uint32_t debug_start;
3192 uint32_t debug_end;
3193 uint32_t type;
3194 uint32_t offset;
3195 uint16_t section;
3196 uint8_t flags;
3197 char name[];
3198 } ATTRIBUTE_PACKED;
3201 loc_low = get_AT (s->function.die, DW_AT_low_pc);
3202 if (!loc_low)
3203 goto end;
3205 if (loc_low->dw_attr_val.val_class != dw_val_class_lbl_id)
3206 goto end;
3208 label_low = loc_low->dw_attr_val.v.val_lbl_id;
3209 if (!label_low)
3210 goto end;
3212 rtx_low = gen_rtx_SYMBOL_REF (Pmode, label_low);
3214 loc_high = get_AT (s->function.die, DW_AT_high_pc);
3215 if (!loc_high)
3216 goto end;
3218 if (loc_high->dw_attr_val.val_class != dw_val_class_high_pc)
3219 goto end;
3221 label_high = loc_high->dw_attr_val.v.val_lbl_id;
3222 if (!label_high)
3223 goto end;
3225 rtx_high = gen_rtx_SYMBOL_REF (Pmode, label_high);
3227 /* Output the S_GPROC32_ID / S_LPROC32_ID record. */
3229 fputs (integer_asm_op (2, false), asm_out_file);
3230 asm_fprintf (asm_out_file,
3231 "%L" SYMBOL_END_LABEL "%u - %L" SYMBOL_START_LABEL "%u\n",
3232 label_num, label_num);
3234 targetm.asm_out.internal_label (asm_out_file, SYMBOL_START_LABEL, label_num);
3236 fputs (integer_asm_op (2, false), asm_out_file);
3237 fprint_whex (asm_out_file, s->kind);
3238 putc ('\n', asm_out_file);
3240 fputs (integer_asm_op (4, false), asm_out_file);
3241 fprint_whex (asm_out_file, s->function.parent);
3242 putc ('\n', asm_out_file);
3244 fputs (integer_asm_op (4, false), asm_out_file);
3245 fprint_whex (asm_out_file, s->function.end);
3246 putc ('\n', asm_out_file);
3248 fputs (integer_asm_op (4, false), asm_out_file);
3249 fprint_whex (asm_out_file, s->function.next);
3250 putc ('\n', asm_out_file);
3252 fputs (integer_asm_op (4, false), asm_out_file);
3253 output_addr_const (asm_out_file, rtx_high);
3254 fputs (" - ", asm_out_file);
3255 output_addr_const (asm_out_file, rtx_low);
3256 putc ('\n', asm_out_file);
3258 /* FIXME - debug_start should be the end of the prologue, and debug_end
3259 the beginning of the epilogue. Do the whole function for
3260 now. */
3262 fputs (integer_asm_op (4, false), asm_out_file);
3263 fprint_whex (asm_out_file, 0);
3264 putc ('\n', asm_out_file);
3266 fputs (integer_asm_op (4, false), asm_out_file);
3267 output_addr_const (asm_out_file, rtx_high);
3268 fputs (" - ", asm_out_file);
3269 output_addr_const (asm_out_file, rtx_low);
3270 putc ('\n', asm_out_file);
3272 fputs (integer_asm_op (4, false), asm_out_file);
3273 fprint_whex (asm_out_file, s->function.type);
3274 putc ('\n', asm_out_file);
3276 asm_fprintf (asm_out_file, "\t.secrel32 ");
3277 output_addr_const (asm_out_file, rtx_low);
3278 fputc ('\n', asm_out_file);
3280 asm_fprintf (asm_out_file, "\t.secidx ");
3281 output_addr_const (asm_out_file, rtx_low);
3282 fputc ('\n', asm_out_file);
3284 fputs (integer_asm_op (1, false), asm_out_file);
3285 fprint_whex (asm_out_file, s->function.flags);
3286 putc ('\n', asm_out_file);
3288 ASM_OUTPUT_ASCII (asm_out_file, s->function.name,
3289 strlen (s->function.name) + 1);
3291 ASM_OUTPUT_ALIGN (asm_out_file, 2);
3293 targetm.asm_out.internal_label (asm_out_file, SYMBOL_END_LABEL, label_num);
3295 frame_base = get_AT (s->function.die, DW_AT_frame_base);
3297 if (frame_base && frame_base->dw_attr_val.val_class == dw_val_class_loc)
3298 fbloc = frame_base->dw_attr_val.v.val_loc;
3300 if (flag_var_tracking)
3302 write_optimized_function_vars (s->function.die, fbloc, rtx_low,
3303 rtx_high);
3304 write_s_frameproc ();
3305 write_optimized_static_local_vars (s->function.die);
3307 else
3309 write_s_frameproc ();
3310 write_unoptimized_function_vars (s->function.die, fbloc);
3313 /* Output the S_PROC_ID_END record. */
3315 label_num = ++sym_label_num;
3317 fputs (integer_asm_op (2, false), asm_out_file);
3318 asm_fprintf (asm_out_file,
3319 "%L" SYMBOL_END_LABEL "%u - %L" SYMBOL_START_LABEL "%u\n",
3320 label_num, label_num);
3322 targetm.asm_out.internal_label (asm_out_file, SYMBOL_START_LABEL, label_num);
3324 fputs (integer_asm_op (2, false), asm_out_file);
3325 fprint_whex (asm_out_file, S_PROC_ID_END);
3326 putc ('\n', asm_out_file);
3328 targetm.asm_out.internal_label (asm_out_file, SYMBOL_END_LABEL, label_num);
3330 end:
3331 free (s->function.name);
3334 /* Write the CodeView symbols into the .debug$S section. */
3336 static void
3337 write_codeview_symbols (void)
3339 fputs (integer_asm_op (4, false), asm_out_file);
3340 fprint_whex (asm_out_file, DEBUG_S_SYMBOLS);
3341 putc ('\n', asm_out_file);
3343 fputs (integer_asm_op (4, false), asm_out_file);
3344 asm_fprintf (asm_out_file, "%LLcv_syms_end - %LLcv_syms_start\n");
3346 asm_fprintf (asm_out_file, "%LLcv_syms_start:\n");
3348 write_compile3_symbol ();
3350 while (sym)
3352 codeview_symbol *n = sym->next;
3354 switch (sym->kind)
3356 case S_LDATA32:
3357 case S_GDATA32:
3358 write_data_symbol (sym);
3359 break;
3360 case S_LPROC32_ID:
3361 case S_GPROC32_ID:
3362 write_function (sym);
3363 break;
3364 default:
3365 break;
3368 free (sym);
3369 sym = n;
3372 asm_fprintf (asm_out_file, "%LLcv_syms_end:\n");
3375 /* Write an LF_POINTER type. */
3377 static void
3378 write_lf_pointer (codeview_custom_type *t)
3380 /* This is lf_pointer in binutils and lfPointer in Microsoft's cvinfo.h:
3382 struct lf_pointer
3384 uint16_t size;
3385 uint16_t kind;
3386 uint32_t base_type;
3387 uint32_t attributes;
3388 } ATTRIBUTE_PACKED;
3391 fputs (integer_asm_op (2, false), asm_out_file);
3392 asm_fprintf (asm_out_file, "%LLcv_type%x_end - %LLcv_type%x_start\n",
3393 t->num, t->num);
3395 asm_fprintf (asm_out_file, "%LLcv_type%x_start:\n", t->num);
3397 fputs (integer_asm_op (2, false), asm_out_file);
3398 fprint_whex (asm_out_file, t->kind);
3399 putc ('\n', asm_out_file);
3401 fputs (integer_asm_op (4, false), asm_out_file);
3402 fprint_whex (asm_out_file, t->lf_pointer.base_type);
3403 putc ('\n', asm_out_file);
3405 fputs (integer_asm_op (4, false), asm_out_file);
3406 fprint_whex (asm_out_file, t->lf_pointer.attributes);
3407 putc ('\n', asm_out_file);
3409 asm_fprintf (asm_out_file, "%LLcv_type%x_end:\n", t->num);
3412 /* All CodeView type definitions have to be aligned to a four-byte boundary,
3413 so write some padding bytes if necessary. These have to be specific values:
3414 LF_PAD3, LF_PAD2, LF_PAD1. */
3416 static void
3417 write_cv_padding (size_t padding)
3419 if (padding == 4 || padding == 0)
3420 return;
3422 if (padding == 3)
3424 fputs (integer_asm_op (1, false), asm_out_file);
3425 fprint_whex (asm_out_file, LF_PAD3);
3426 putc ('\n', asm_out_file);
3429 if (padding >= 2)
3431 fputs (integer_asm_op (1, false), asm_out_file);
3432 fprint_whex (asm_out_file, LF_PAD2);
3433 putc ('\n', asm_out_file);
3436 fputs (integer_asm_op (1, false), asm_out_file);
3437 fprint_whex (asm_out_file, LF_PAD1);
3438 putc ('\n', asm_out_file);
3441 /* Write an LF_MODIFIER type, representing a const and/or volatile modification
3442 of another type. */
3444 static void
3445 write_lf_modifier (codeview_custom_type *t)
3447 /* This is lf_modifier in binutils and lfModifier in Microsoft's cvinfo.h:
3449 struct lf_modifier
3451 uint16_t size;
3452 uint16_t kind;
3453 uint32_t base_type;
3454 uint16_t modifier;
3455 uint16_t padding;
3456 } ATTRIBUTE_PACKED;
3459 fputs (integer_asm_op (2, false), asm_out_file);
3460 asm_fprintf (asm_out_file, "%LLcv_type%x_end - %LLcv_type%x_start\n",
3461 t->num, t->num);
3463 asm_fprintf (asm_out_file, "%LLcv_type%x_start:\n", t->num);
3465 fputs (integer_asm_op (2, false), asm_out_file);
3466 fprint_whex (asm_out_file, t->kind);
3467 putc ('\n', asm_out_file);
3469 fputs (integer_asm_op (4, false), asm_out_file);
3470 fprint_whex (asm_out_file, t->lf_modifier.base_type);
3471 putc ('\n', asm_out_file);
3473 fputs (integer_asm_op (2, false), asm_out_file);
3474 fprint_whex (asm_out_file, t->lf_modifier.modifier);
3475 putc ('\n', asm_out_file);
3477 write_cv_padding (2);
3479 asm_fprintf (asm_out_file, "%LLcv_type%x_end:\n", t->num);
3482 /* Write a CodeView extensible integer. If the value is non-negative and
3483 < 0x8000, the value gets written directly as an uint16_t. Otherwise, we
3484 output two bytes for the integer type (LF_CHAR, LF_SHORT, ...), and the
3485 actual value follows. Returns the total number of bytes written. */
3487 static size_t
3488 write_cv_integer (codeview_integer *i)
3490 if (i->neg)
3492 if (i->num <= 0x80)
3494 fputs (integer_asm_op (2, false), asm_out_file);
3495 fprint_whex (asm_out_file, LF_CHAR);
3496 putc ('\n', asm_out_file);
3498 fputs (integer_asm_op (1, false), asm_out_file);
3499 fprint_whex (asm_out_file, -i->num);
3500 putc ('\n', asm_out_file);
3502 return 3;
3504 else if (i->num <= 0x8000)
3506 fputs (integer_asm_op (2, false), asm_out_file);
3507 fprint_whex (asm_out_file, LF_SHORT);
3508 putc ('\n', asm_out_file);
3510 fputs (integer_asm_op (2, false), asm_out_file);
3511 fprint_whex (asm_out_file, -i->num);
3512 putc ('\n', asm_out_file);
3514 return 4;
3516 else if (i->num <= 0x80000000)
3518 fputs (integer_asm_op (2, false), asm_out_file);
3519 fprint_whex (asm_out_file, LF_LONG);
3520 putc ('\n', asm_out_file);
3522 fputs (integer_asm_op (4, false), asm_out_file);
3523 fprint_whex (asm_out_file, -i->num);
3524 putc ('\n', asm_out_file);
3526 return 6;
3528 else
3530 fputs (integer_asm_op (2, false), asm_out_file);
3531 fprint_whex (asm_out_file, LF_QUADWORD);
3532 putc ('\n', asm_out_file);
3534 fputs (integer_asm_op (8, false), asm_out_file);
3535 fprint_whex (asm_out_file, -i->num);
3536 putc ('\n', asm_out_file);
3538 return 10;
3541 else
3543 if (i->num <= 0x7fff)
3545 fputs (integer_asm_op (2, false), asm_out_file);
3546 fprint_whex (asm_out_file, i->num);
3547 putc ('\n', asm_out_file);
3549 return 2;
3551 else if (i->num <= 0xffff)
3553 fputs (integer_asm_op (2, false), asm_out_file);
3554 fprint_whex (asm_out_file, LF_USHORT);
3555 putc ('\n', asm_out_file);
3557 fputs (integer_asm_op (2, false), asm_out_file);
3558 fprint_whex (asm_out_file, i->num);
3559 putc ('\n', asm_out_file);
3561 return 4;
3563 else if (i->num <= 0xffffffff)
3565 fputs (integer_asm_op (2, false), asm_out_file);
3566 fprint_whex (asm_out_file, LF_ULONG);
3567 putc ('\n', asm_out_file);
3569 fputs (integer_asm_op (4, false), asm_out_file);
3570 fprint_whex (asm_out_file, i->num);
3571 putc ('\n', asm_out_file);
3573 return 6;
3575 else
3577 fputs (integer_asm_op (2, false), asm_out_file);
3578 fprint_whex (asm_out_file, LF_UQUADWORD);
3579 putc ('\n', asm_out_file);
3581 fputs (integer_asm_op (8, false), asm_out_file);
3582 fprint_whex (asm_out_file, i->num);
3583 putc ('\n', asm_out_file);
3585 return 10;
3590 /* Return the extra size needed for an extensible integer. */
3592 static size_t
3593 cv_integer_len (codeview_integer *i)
3595 if (i->neg)
3597 if (i->num <= 0x80)
3598 return sizeof (int8_t);
3599 else if (i->num <= 0x8000)
3600 return sizeof (int16_t);
3601 else if (i->num <= 0x80000000)
3602 return sizeof (int32_t);
3603 else
3604 return sizeof (int64_t);
3606 else
3608 if (i->num <= 0x7fff)
3609 return 0;
3610 else if (i->num <= 0xffff)
3611 return sizeof (uint16_t);
3612 else if (i->num <= 0xffffffff)
3613 return sizeof (uint32_t);
3614 else
3615 return sizeof (uint64_t);
3619 /* Write an LF_FIELDLIST type, which is a container for various subtypes. This
3620 has two uses: for the values in an enum, and for the member, operators etc.
3621 for a struct, class, or union. */
3623 static void
3624 write_lf_fieldlist (codeview_custom_type *t)
3626 fputs (integer_asm_op (2, false), asm_out_file);
3627 asm_fprintf (asm_out_file, "%LLcv_type%x_end - %LLcv_type%x_start\n",
3628 t->num, t->num);
3630 asm_fprintf (asm_out_file, "%LLcv_type%x_start:\n", t->num);
3632 fputs (integer_asm_op (2, false), asm_out_file);
3633 fprint_whex (asm_out_file, t->kind);
3634 putc ('\n', asm_out_file);
3636 while (t->lf_fieldlist.subtypes)
3638 codeview_subtype *v = t->lf_fieldlist.subtypes;
3639 codeview_subtype *next = v->next;
3640 size_t name_len, leaf_len;
3642 switch (v->kind)
3644 case LF_ENUMERATE:
3645 /* This is lf_enumerate in binutils and lfEnumerate in Microsoft's
3646 cvinfo.h:
3648 struct lf_enumerate
3650 uint16_t kind;
3651 uint16_t attributes;
3652 uint16_t value;
3653 (then actual value if value >= 0x8000)
3654 char name[];
3655 } ATTRIBUTE_PACKED;
3658 fputs (integer_asm_op (2, false), asm_out_file);
3659 fprint_whex (asm_out_file, LF_ENUMERATE);
3660 putc ('\n', asm_out_file);
3662 fputs (integer_asm_op (2, false), asm_out_file);
3663 fprint_whex (asm_out_file, CV_ACCESS_PUBLIC);
3664 putc ('\n', asm_out_file);
3666 leaf_len = 4 + write_cv_integer (&v->lf_enumerate.value);
3668 name_len = strlen (v->lf_enumerate.name) + 1;
3669 ASM_OUTPUT_ASCII (asm_out_file, v->lf_enumerate.name, name_len);
3671 leaf_len += name_len;
3672 write_cv_padding (4 - (leaf_len % 4));
3674 free (v->lf_enumerate.name);
3675 break;
3677 case LF_MEMBER:
3678 /* This is lf_member in binutils and lfMember in Microsoft's
3679 cvinfo.h:
3681 struct lf_member
3683 uint16_t kind;
3684 uint16_t attributes;
3685 uint32_t type;
3686 uint16_t offset;
3687 char name[];
3688 } ATTRIBUTE_PACKED;
3691 fputs (integer_asm_op (2, false), asm_out_file);
3692 fprint_whex (asm_out_file, LF_MEMBER);
3693 putc ('\n', asm_out_file);
3695 fputs (integer_asm_op (2, false), asm_out_file);
3696 fprint_whex (asm_out_file, v->lf_member.attributes);
3697 putc ('\n', asm_out_file);
3699 fputs (integer_asm_op (4, false), asm_out_file);
3700 fprint_whex (asm_out_file, v->lf_member.type);
3701 putc ('\n', asm_out_file);
3703 leaf_len = 8 + write_cv_integer (&v->lf_member.offset);
3705 if (v->lf_member.name)
3707 name_len = strlen (v->lf_member.name) + 1;
3708 ASM_OUTPUT_ASCII (asm_out_file, v->lf_member.name, name_len);
3710 else
3712 name_len = 1;
3713 ASM_OUTPUT_ASCII (asm_out_file, "", name_len);
3716 leaf_len += name_len;
3717 write_cv_padding (4 - (leaf_len % 4));
3719 free (v->lf_member.name);
3720 break;
3722 case LF_INDEX:
3723 /* This is lf_index in binutils and lfIndex in Microsoft's cvinfo.h:
3725 struct lf_index
3727 uint16_t kind;
3728 uint16_t padding;
3729 uint32_t index;
3730 } ATTRIBUTE_PACKED;
3733 fputs (integer_asm_op (2, false), asm_out_file);
3734 fprint_whex (asm_out_file, LF_INDEX);
3735 putc ('\n', asm_out_file);
3737 fputs (integer_asm_op (2, false), asm_out_file);
3738 fprint_whex (asm_out_file, 0);
3739 putc ('\n', asm_out_file);
3741 fputs (integer_asm_op (4, false), asm_out_file);
3742 fprint_whex (asm_out_file, v->lf_index.type_num);
3743 putc ('\n', asm_out_file);
3745 break;
3747 case LF_STMEMBER:
3748 /* This is lf_static_member in binutils and lfSTMember in Microsoft's
3749 cvinfo.h:
3751 struct lf_static_member
3753 uint16_t kind;
3754 uint16_t attributes;
3755 uint32_t type;
3756 char name[];
3757 } ATTRIBUTE_PACKED;
3760 fputs (integer_asm_op (2, false), asm_out_file);
3761 fprint_whex (asm_out_file, LF_STMEMBER);
3762 putc ('\n', asm_out_file);
3764 fputs (integer_asm_op (2, false), asm_out_file);
3765 fprint_whex (asm_out_file, v->lf_static_member.attributes);
3766 putc ('\n', asm_out_file);
3768 fputs (integer_asm_op (4, false), asm_out_file);
3769 fprint_whex (asm_out_file, v->lf_static_member.type);
3770 putc ('\n', asm_out_file);
3772 name_len = strlen (v->lf_static_member.name) + 1;
3773 ASM_OUTPUT_ASCII (asm_out_file, v->lf_static_member.name, name_len);
3775 leaf_len = 8 + name_len;
3776 write_cv_padding (4 - (leaf_len % 4));
3778 free (v->lf_static_member.name);
3779 break;
3781 case LF_ONEMETHOD:
3782 /* This is lf_onemethod in binutils and lfOneMethod in Microsoft's
3783 cvinfo.h:
3785 struct lf_onemethod
3787 uint16_t kind;
3788 uint16_t method_attribute;
3789 uint32_t method_type;
3790 char name[];
3791 } ATTRIBUTE_PACKED;
3794 fputs (integer_asm_op (2, false), asm_out_file);
3795 fprint_whex (asm_out_file, LF_ONEMETHOD);
3796 putc ('\n', asm_out_file);
3798 fputs (integer_asm_op (2, false), asm_out_file);
3799 fprint_whex (asm_out_file, v->lf_onemethod.method_attribute);
3800 putc ('\n', asm_out_file);
3802 fputs (integer_asm_op (4, false), asm_out_file);
3803 fprint_whex (asm_out_file, v->lf_onemethod.method_type);
3804 putc ('\n', asm_out_file);
3806 name_len = strlen (v->lf_onemethod.name) + 1;
3807 ASM_OUTPUT_ASCII (asm_out_file, v->lf_onemethod.name, name_len);
3809 leaf_len = 8 + name_len;
3810 write_cv_padding (4 - (leaf_len % 4));
3812 free (v->lf_onemethod.name);
3813 break;
3815 case LF_METHOD:
3816 /* This is lf_method in binutils and lfMethod in Microsoft's
3817 cvinfo.h:
3819 struct lf_method
3821 uint16_t kind;
3822 uint16_t count;
3823 uint32_t method_list;
3824 char name[];
3825 } ATTRIBUTE_PACKED;
3828 fputs (integer_asm_op (2, false), asm_out_file);
3829 fprint_whex (asm_out_file, LF_METHOD);
3830 putc ('\n', asm_out_file);
3832 fputs (integer_asm_op (2, false), asm_out_file);
3833 fprint_whex (asm_out_file, v->lf_method.count);
3834 putc ('\n', asm_out_file);
3836 fputs (integer_asm_op (4, false), asm_out_file);
3837 fprint_whex (asm_out_file, v->lf_method.method_list);
3838 putc ('\n', asm_out_file);
3840 name_len = strlen (v->lf_method.name) + 1;
3841 ASM_OUTPUT_ASCII (asm_out_file, v->lf_method.name, name_len);
3843 leaf_len = 8 + name_len;
3844 write_cv_padding (4 - (leaf_len % 4));
3846 free (v->lf_method.name);
3847 break;
3849 default:
3850 break;
3853 t->lf_fieldlist.subtypes = next;
3854 free (v);
3857 asm_fprintf (asm_out_file, "%LLcv_type%x_end:\n", t->num);
3860 /* Write an LF_ENUM type. */
3862 static void
3863 write_lf_enum (codeview_custom_type *t)
3865 size_t name_len, leaf_len;
3867 /* This is lf_enum in binutils and lfEnum in Microsoft's cvinfo.h:
3869 struct lf_enum
3871 uint16_t size;
3872 uint16_t kind;
3873 uint16_t num_elements;
3874 uint16_t properties;
3875 uint32_t underlying_type;
3876 uint32_t field_list;
3877 char name[];
3878 } ATTRIBUTE_PACKED;
3881 fputs (integer_asm_op (2, false), asm_out_file);
3882 asm_fprintf (asm_out_file, "%LLcv_type%x_end - %LLcv_type%x_start\n",
3883 t->num, t->num);
3885 asm_fprintf (asm_out_file, "%LLcv_type%x_start:\n", t->num);
3887 fputs (integer_asm_op (2, false), asm_out_file);
3888 fprint_whex (asm_out_file, t->kind);
3889 putc ('\n', asm_out_file);
3891 fputs (integer_asm_op (2, false), asm_out_file);
3892 fprint_whex (asm_out_file, t->lf_enum.count);
3893 putc ('\n', asm_out_file);
3895 fputs (integer_asm_op (2, false), asm_out_file);
3896 fprint_whex (asm_out_file, t->lf_enum.properties);
3897 putc ('\n', asm_out_file);
3899 fputs (integer_asm_op (4, false), asm_out_file);
3900 fprint_whex (asm_out_file, t->lf_enum.underlying_type);
3901 putc ('\n', asm_out_file);
3903 fputs (integer_asm_op (4, false), asm_out_file);
3904 fprint_whex (asm_out_file, t->lf_enum.fieldlist);
3905 putc ('\n', asm_out_file);
3907 name_len = strlen (t->lf_enum.name) + 1;
3908 ASM_OUTPUT_ASCII (asm_out_file, t->lf_enum.name, name_len);
3910 leaf_len = 14 + name_len;
3911 write_cv_padding (4 - (leaf_len % 4));
3913 free (t->lf_enum.name);
3915 asm_fprintf (asm_out_file, "%LLcv_type%x_end:\n", t->num);
3918 /* Write an LF_STRUCTURE or LF_CLASS type (the two have the same structure). */
3920 static void
3921 write_lf_structure (codeview_custom_type *t)
3923 size_t name_len, leaf_len;
3925 /* This is lf_class in binutils and lfClass in Microsoft's cvinfo.h:
3927 struct lf_class
3929 uint16_t size;
3930 uint16_t kind;
3931 uint16_t num_members;
3932 uint16_t properties;
3933 uint32_t field_list;
3934 uint32_t derived_from;
3935 uint32_t vshape;
3936 uint16_t length;
3937 char name[];
3938 } ATTRIBUTE_PACKED;
3941 fputs (integer_asm_op (2, false), asm_out_file);
3942 asm_fprintf (asm_out_file, "%LLcv_type%x_end - %LLcv_type%x_start\n",
3943 t->num, t->num);
3945 asm_fprintf (asm_out_file, "%LLcv_type%x_start:\n", t->num);
3947 fputs (integer_asm_op (2, false), asm_out_file);
3948 fprint_whex (asm_out_file, t->kind);
3949 putc ('\n', asm_out_file);
3951 fputs (integer_asm_op (2, false), asm_out_file);
3952 fprint_whex (asm_out_file, t->lf_structure.num_members);
3953 putc ('\n', asm_out_file);
3955 fputs (integer_asm_op (2, false), asm_out_file);
3956 fprint_whex (asm_out_file, t->lf_structure.properties);
3957 putc ('\n', asm_out_file);
3959 fputs (integer_asm_op (4, false), asm_out_file);
3960 fprint_whex (asm_out_file, t->lf_structure.field_list);
3961 putc ('\n', asm_out_file);
3963 fputs (integer_asm_op (4, false), asm_out_file);
3964 fprint_whex (asm_out_file, t->lf_structure.derived_from);
3965 putc ('\n', asm_out_file);
3967 fputs (integer_asm_op (4, false), asm_out_file);
3968 fprint_whex (asm_out_file, t->lf_structure.vshape);
3969 putc ('\n', asm_out_file);
3971 leaf_len = 20 + write_cv_integer (&t->lf_structure.length);
3973 if (t->lf_structure.name)
3975 name_len = strlen (t->lf_structure.name) + 1;
3976 ASM_OUTPUT_ASCII (asm_out_file, t->lf_structure.name, name_len);
3978 else
3980 static const char unnamed_struct[] = "<unnamed-tag>";
3982 name_len = sizeof (unnamed_struct);
3983 ASM_OUTPUT_ASCII (asm_out_file, unnamed_struct, name_len);
3986 leaf_len += name_len;
3987 write_cv_padding (4 - (leaf_len % 4));
3989 free (t->lf_structure.name);
3991 asm_fprintf (asm_out_file, "%LLcv_type%x_end:\n", t->num);
3994 /* Write an LF_UNION type. */
3996 static void
3997 write_lf_union (codeview_custom_type *t)
3999 size_t name_len, leaf_len;
4001 /* This is lf_union in binutils and lfUnion in Microsoft's cvinfo.h:
4003 struct lf_union
4005 uint16_t size;
4006 uint16_t kind;
4007 uint16_t num_members;
4008 uint16_t properties;
4009 uint32_t field_list;
4010 uint16_t length;
4011 char name[];
4012 } ATTRIBUTE_PACKED;
4015 fputs (integer_asm_op (2, false), asm_out_file);
4016 asm_fprintf (asm_out_file, "%LLcv_type%x_end - %LLcv_type%x_start\n",
4017 t->num, t->num);
4019 asm_fprintf (asm_out_file, "%LLcv_type%x_start:\n", t->num);
4021 fputs (integer_asm_op (2, false), asm_out_file);
4022 fprint_whex (asm_out_file, t->kind);
4023 putc ('\n', asm_out_file);
4025 fputs (integer_asm_op (2, false), asm_out_file);
4026 fprint_whex (asm_out_file, t->lf_structure.num_members);
4027 putc ('\n', asm_out_file);
4029 fputs (integer_asm_op (2, false), asm_out_file);
4030 fprint_whex (asm_out_file, t->lf_structure.properties);
4031 putc ('\n', asm_out_file);
4033 fputs (integer_asm_op (4, false), asm_out_file);
4034 fprint_whex (asm_out_file, t->lf_structure.field_list);
4035 putc ('\n', asm_out_file);
4037 leaf_len = 12 + write_cv_integer (&t->lf_structure.length);
4039 if (t->lf_structure.name)
4041 name_len = strlen (t->lf_structure.name) + 1;
4042 ASM_OUTPUT_ASCII (asm_out_file, t->lf_structure.name, name_len);
4044 else
4046 static const char unnamed_struct[] = "<unnamed-tag>";
4048 name_len = sizeof (unnamed_struct);
4049 ASM_OUTPUT_ASCII (asm_out_file, unnamed_struct, name_len);
4052 leaf_len += name_len;
4053 write_cv_padding (4 - (leaf_len % 4));
4055 free (t->lf_structure.name);
4057 asm_fprintf (asm_out_file, "%LLcv_type%x_end:\n", t->num);
4060 /* Write an LF_ARRAY type. */
4062 static void
4063 write_lf_array (codeview_custom_type *t)
4065 size_t leaf_len;
4067 /* This is lf_array in binutils and lfArray in Microsoft's cvinfo.h:
4069 struct lf_array
4071 uint16_t size;
4072 uint16_t kind;
4073 uint32_t element_type;
4074 uint32_t index_type;
4075 uint16_t length_in_bytes;
4076 char name[];
4077 } ATTRIBUTE_PACKED;
4080 fputs (integer_asm_op (2, false), asm_out_file);
4081 asm_fprintf (asm_out_file, "%LLcv_type%x_end - %LLcv_type%x_start\n",
4082 t->num, t->num);
4084 asm_fprintf (asm_out_file, "%LLcv_type%x_start:\n", t->num);
4086 fputs (integer_asm_op (2, false), asm_out_file);
4087 fprint_whex (asm_out_file, t->kind);
4088 putc ('\n', asm_out_file);
4090 fputs (integer_asm_op (4, false), asm_out_file);
4091 fprint_whex (asm_out_file, t->lf_array.element_type);
4092 putc ('\n', asm_out_file);
4094 fputs (integer_asm_op (4, false), asm_out_file);
4095 fprint_whex (asm_out_file, t->lf_array.index_type);
4096 putc ('\n', asm_out_file);
4098 leaf_len = 13 + write_cv_integer (&t->lf_array.length_in_bytes);
4100 ASM_OUTPUT_ASCII (asm_out_file, "", 1);
4102 write_cv_padding (4 - (leaf_len % 4));
4104 asm_fprintf (asm_out_file, "%LLcv_type%x_end:\n", t->num);
4107 /* Write an LF_BITFIELD type. */
4109 static void
4110 write_lf_bitfield (codeview_custom_type *t)
4112 /* This is lf_bitfield in binutils and lfBitfield in Microsoft's cvinfo.h:
4114 struct lf_bitfield
4116 uint16_t size;
4117 uint16_t kind;
4118 uint32_t base_type;
4119 uint8_t length;
4120 uint8_t position;
4121 } ATTRIBUTE_PACKED;
4124 fputs (integer_asm_op (2, false), asm_out_file);
4125 asm_fprintf (asm_out_file, "%LLcv_type%x_end - %LLcv_type%x_start\n",
4126 t->num, t->num);
4128 asm_fprintf (asm_out_file, "%LLcv_type%x_start:\n", t->num);
4130 fputs (integer_asm_op (2, false), asm_out_file);
4131 fprint_whex (asm_out_file, t->kind);
4132 putc ('\n', asm_out_file);
4134 fputs (integer_asm_op (4, false), asm_out_file);
4135 fprint_whex (asm_out_file, t->lf_bitfield.base_type);
4136 putc ('\n', asm_out_file);
4138 fputs (integer_asm_op (1, false), asm_out_file);
4139 fprint_whex (asm_out_file, t->lf_bitfield.length);
4140 putc ('\n', asm_out_file);
4142 fputs (integer_asm_op (1, false), asm_out_file);
4143 fprint_whex (asm_out_file, t->lf_bitfield.position);
4144 putc ('\n', asm_out_file);
4146 write_cv_padding (2);
4148 asm_fprintf (asm_out_file, "%LLcv_type%x_end:\n", t->num);
4151 /* Write an LF_PROCEDURE type. Function pointers are implemented as pointers
4152 to one of these. */
4154 static void
4155 write_lf_procedure (codeview_custom_type *t)
4157 /* This is lf_procedure in binutils and lfProc in Microsoft's cvinfo.h:
4159 struct lf_procedure
4161 uint16_t size;
4162 uint16_t kind;
4163 uint32_t return_type;
4164 uint8_t calling_convention;
4165 uint8_t attributes;
4166 uint16_t num_parameters;
4167 uint32_t arglist;
4168 } ATTRIBUTE_PACKED;
4171 fputs (integer_asm_op (2, false), asm_out_file);
4172 asm_fprintf (asm_out_file, "%LLcv_type%x_end - %LLcv_type%x_start\n",
4173 t->num, t->num);
4175 asm_fprintf (asm_out_file, "%LLcv_type%x_start:\n", t->num);
4177 fputs (integer_asm_op (2, false), asm_out_file);
4178 fprint_whex (asm_out_file, t->kind);
4179 putc ('\n', asm_out_file);
4181 fputs (integer_asm_op (4, false), asm_out_file);
4182 fprint_whex (asm_out_file, t->lf_procedure.return_type);
4183 putc ('\n', asm_out_file);
4185 fputs (integer_asm_op (1, false), asm_out_file);
4186 fprint_whex (asm_out_file, t->lf_procedure.calling_convention);
4187 putc ('\n', asm_out_file);
4189 fputs (integer_asm_op (1, false), asm_out_file);
4190 fprint_whex (asm_out_file, t->lf_procedure.attributes);
4191 putc ('\n', asm_out_file);
4193 fputs (integer_asm_op (2, false), asm_out_file);
4194 fprint_whex (asm_out_file, t->lf_procedure.num_parameters);
4195 putc ('\n', asm_out_file);
4197 fputs (integer_asm_op (4, false), asm_out_file);
4198 fprint_whex (asm_out_file, t->lf_procedure.arglist);
4199 putc ('\n', asm_out_file);
4201 asm_fprintf (asm_out_file, "%LLcv_type%x_end:\n", t->num);
4204 /* Write an LF_ARGLIST type. This is just a list of other types. LF_PROCEDURE
4205 entries point to one of these. */
4207 static void
4208 write_lf_arglist (codeview_custom_type *t)
4210 /* This is lf_arglist in binutils and lfArgList in Microsoft's cvinfo.h:
4212 struct lf_arglist
4214 uint16_t size;
4215 uint16_t kind;
4216 uint32_t num_entries;
4217 uint32_t args[];
4218 } ATTRIBUTE_PACKED;
4221 fputs (integer_asm_op (2, false), asm_out_file);
4222 asm_fprintf (asm_out_file, "%LLcv_type%x_end - %LLcv_type%x_start\n",
4223 t->num, t->num);
4225 asm_fprintf (asm_out_file, "%LLcv_type%x_start:\n", t->num);
4227 fputs (integer_asm_op (2, false), asm_out_file);
4228 fprint_whex (asm_out_file, t->kind);
4229 putc ('\n', asm_out_file);
4231 fputs (integer_asm_op (4, false), asm_out_file);
4232 fprint_whex (asm_out_file, t->lf_arglist.num_entries);
4233 putc ('\n', asm_out_file);
4235 for (uint32_t i = 0; i < t->lf_arglist.num_entries; i++)
4237 fputs (integer_asm_op (4, false), asm_out_file);
4238 fprint_whex (asm_out_file, t->lf_arglist.args[i]);
4239 putc ('\n', asm_out_file);
4242 free (t->lf_arglist.args);
4244 asm_fprintf (asm_out_file, "%LLcv_type%x_end:\n", t->num);
4247 /* Write an LF_FUNC_ID type, which marries together a function type with its
4248 name. This will end up in the alternative types stream in the final PDB,
4249 but we can just stick it in the normal .debug$T section. */
4251 static void
4252 write_lf_func_id (codeview_custom_type *t)
4254 size_t name_len;
4256 /* This is lf_func_id in binutils and lfFuncId in Microsoft's cvinfo.h:
4258 struct lf_func_id
4260 uint16_t size;
4261 uint16_t kind;
4262 uint32_t parent_scope;
4263 uint32_t function_type;
4264 char name[];
4265 } ATTRIBUTE_PACKED;
4268 fputs (integer_asm_op (2, false), asm_out_file);
4269 asm_fprintf (asm_out_file, "%LLcv_type%x_end - %LLcv_type%x_start\n",
4270 t->num, t->num);
4272 asm_fprintf (asm_out_file, "%LLcv_type%x_start:\n", t->num);
4274 fputs (integer_asm_op (2, false), asm_out_file);
4275 fprint_whex (asm_out_file, t->kind);
4276 putc ('\n', asm_out_file);
4278 fputs (integer_asm_op (4, false), asm_out_file);
4279 fprint_whex (asm_out_file, t->lf_func_id.parent_scope);
4280 putc ('\n', asm_out_file);
4282 fputs (integer_asm_op (4, false), asm_out_file);
4283 fprint_whex (asm_out_file, t->lf_func_id.function_type);
4284 putc ('\n', asm_out_file);
4286 name_len = strlen (t->lf_func_id.name) + 1;
4288 ASM_OUTPUT_ASCII (asm_out_file, t->lf_func_id.name, name_len);
4290 write_cv_padding (4 - (name_len % 4));
4292 free (t->lf_func_id.name);
4294 asm_fprintf (asm_out_file, "%LLcv_type%x_end:\n", t->num);
4297 /* Write an LF_MFUNC_ID type, which is the version of LF_FUNC_ID for struct
4298 functions. Instead of an LF_STRING_ID for the parent scope, we write the
4299 type number of the parent struct. */
4301 static void
4302 write_lf_mfunc_id (codeview_custom_type *t)
4304 size_t name_len;
4306 /* This is lf_mfunc_id in binutils and lfMFuncId in Microsoft's cvinfo.h:
4308 struct lf_mfunc_id
4310 uint16_t size;
4311 uint16_t kind;
4312 uint32_t parent_type;
4313 uint32_t function_type;
4314 char name[];
4315 } ATTRIBUTE_PACKED
4318 fputs (integer_asm_op (2, false), asm_out_file);
4319 asm_fprintf (asm_out_file, "%LLcv_type%x_end - %LLcv_type%x_start\n",
4320 t->num, t->num);
4322 asm_fprintf (asm_out_file, "%LLcv_type%x_start:\n", t->num);
4324 fputs (integer_asm_op (2, false), asm_out_file);
4325 fprint_whex (asm_out_file, t->kind);
4326 putc ('\n', asm_out_file);
4328 fputs (integer_asm_op (4, false), asm_out_file);
4329 fprint_whex (asm_out_file, t->lf_mfunc_id.parent_type);
4330 putc ('\n', asm_out_file);
4332 fputs (integer_asm_op (4, false), asm_out_file);
4333 fprint_whex (asm_out_file, t->lf_mfunc_id.function_type);
4334 putc ('\n', asm_out_file);
4336 name_len = strlen (t->lf_mfunc_id.name) + 1;
4338 ASM_OUTPUT_ASCII (asm_out_file, t->lf_mfunc_id.name, name_len);
4340 write_cv_padding (4 - (name_len % 4));
4342 free (t->lf_mfunc_id.name);
4344 asm_fprintf (asm_out_file, "%LLcv_type%x_end:\n", t->num);
4347 /* Write an LF_STRING_ID type, which provides a deduplicated string that other
4348 types can reference. */
4350 static void
4351 write_lf_string_id (codeview_custom_type *t)
4353 size_t string_len;
4355 /* This is lf_string_id in binutils and lfStringId in Microsoft's cvinfo.h:
4357 struct lf_string_id
4359 uint16_t size;
4360 uint16_t kind;
4361 uint32_t substring;
4362 char string[];
4363 } ATTRIBUTE_PACKED;
4366 fputs (integer_asm_op (2, false), asm_out_file);
4367 asm_fprintf (asm_out_file, "%LLcv_type%x_end - %LLcv_type%x_start\n",
4368 t->num, t->num);
4370 asm_fprintf (asm_out_file, "%LLcv_type%x_start:\n", t->num);
4372 fputs (integer_asm_op (2, false), asm_out_file);
4373 fprint_whex (asm_out_file, t->kind);
4374 putc ('\n', asm_out_file);
4376 fputs (integer_asm_op (4, false), asm_out_file);
4377 fprint_whex (asm_out_file, t->lf_string_id.substring);
4378 putc ('\n', asm_out_file);
4380 string_len = strlen (t->lf_string_id.string) + 1;
4382 ASM_OUTPUT_ASCII (asm_out_file, t->lf_string_id.string, string_len);
4384 write_cv_padding (4 - (string_len % 4));
4386 free (t->lf_string_id.string);
4388 asm_fprintf (asm_out_file, "%LLcv_type%x_end:\n", t->num);
4391 /* Write an LF_MFUNCTION type, representing a member function. This is the
4392 struct-scoped equivalent of the LF_PROCEDURE type. */
4394 static void
4395 write_lf_mfunction (codeview_custom_type *t)
4397 /* This is lf_mfunction in binutils and lfMFunc in Microsoft's cvinfo.h:
4399 struct lf_mfunction
4401 uint16_t size;
4402 uint16_t kind;
4403 uint32_t return_type;
4404 uint32_t containing_class_type;
4405 uint32_t this_type;
4406 uint8_t calling_convention;
4407 uint8_t attributes;
4408 uint16_t num_parameters;
4409 uint32_t arglist;
4410 int32_t this_adjustment;
4411 } ATTRIBUTE_PACKED;
4414 fputs (integer_asm_op (2, false), asm_out_file);
4415 asm_fprintf (asm_out_file, "%LLcv_type%x_end - %LLcv_type%x_start\n",
4416 t->num, t->num);
4418 asm_fprintf (asm_out_file, "%LLcv_type%x_start:\n", t->num);
4420 fputs (integer_asm_op (2, false), asm_out_file);
4421 fprint_whex (asm_out_file, t->kind);
4422 putc ('\n', asm_out_file);
4424 fputs (integer_asm_op (4, false), asm_out_file);
4425 fprint_whex (asm_out_file, t->lf_mfunction.return_type);
4426 putc ('\n', asm_out_file);
4428 fputs (integer_asm_op (4, false), asm_out_file);
4429 fprint_whex (asm_out_file, t->lf_mfunction.containing_class_type);
4430 putc ('\n', asm_out_file);
4432 fputs (integer_asm_op (4, false), asm_out_file);
4433 fprint_whex (asm_out_file, t->lf_mfunction.this_type);
4434 putc ('\n', asm_out_file);
4436 fputs (integer_asm_op (1, false), asm_out_file);
4437 fprint_whex (asm_out_file, t->lf_mfunction.calling_convention);
4438 putc ('\n', asm_out_file);
4440 fputs (integer_asm_op (1, false), asm_out_file);
4441 fprint_whex (asm_out_file, t->lf_mfunction.attributes);
4442 putc ('\n', asm_out_file);
4444 fputs (integer_asm_op (2, false), asm_out_file);
4445 fprint_whex (asm_out_file, t->lf_mfunction.num_parameters);
4446 putc ('\n', asm_out_file);
4448 fputs (integer_asm_op (4, false), asm_out_file);
4449 fprint_whex (asm_out_file, t->lf_mfunction.arglist);
4450 putc ('\n', asm_out_file);
4452 fputs (integer_asm_op (4, false), asm_out_file);
4453 fprint_whex (asm_out_file, t->lf_mfunction.this_adjustment);
4454 putc ('\n', asm_out_file);
4456 asm_fprintf (asm_out_file, "%LLcv_type%x_end:\n", t->num);
4459 /* Write an LF_METHODLIST type, which is an array of type numbers for
4460 LF_MFUNCTION types. Overloaded functions are represented by a LF_METHOD
4461 subtype in the field list, which points to a LF_METHODLIST type for the
4462 function's various forms. */
4464 static void
4465 write_lf_methodlist (codeview_custom_type *t)
4467 /* This is lf_methodlist in binutils and lMethodList in Microsoft's cvinfo.h:
4469 struct lf_methodlist_entry
4471 uint16_t method_attribute;
4472 uint16_t padding;
4473 uint32_t method_type;
4474 } ATTRIBUTE_PACKED;
4476 struct lf_methodlist
4478 uint16_t size;
4479 uint16_t kind;
4480 struct lf_methodlist_entry entries[];
4481 } ATTRIBUTE_PACKED;
4484 fputs (integer_asm_op (2, false), asm_out_file);
4485 asm_fprintf (asm_out_file, "%LLcv_type%x_end - %LLcv_type%x_start\n",
4486 t->num, t->num);
4488 asm_fprintf (asm_out_file, "%LLcv_type%x_start:\n", t->num);
4490 fputs (integer_asm_op (2, false), asm_out_file);
4491 fprint_whex (asm_out_file, t->kind);
4492 putc ('\n', asm_out_file);
4494 for (unsigned int i = 0; i < t->lf_methodlist.count; i++)
4496 fputs (integer_asm_op (2, false), asm_out_file);
4497 fprint_whex (asm_out_file, t->lf_methodlist.entries[i].method_attribute);
4498 putc ('\n', asm_out_file);
4500 fputs (integer_asm_op (2, false), asm_out_file);
4501 fprint_whex (asm_out_file, 0);
4502 putc ('\n', asm_out_file);
4504 fputs (integer_asm_op (4, false), asm_out_file);
4505 fprint_whex (asm_out_file, t->lf_methodlist.entries[i].method_type);
4506 putc ('\n', asm_out_file);
4509 free (t->lf_methodlist.entries);
4511 asm_fprintf (asm_out_file, "%LLcv_type%x_end:\n", t->num);
4514 /* Write the .debug$T section, which contains all of our custom type
4515 definitions. */
4517 static void
4518 write_custom_types (void)
4520 targetm.asm_out.named_section (".debug$T", SECTION_DEBUG, NULL);
4522 fputs (integer_asm_op (4, false), asm_out_file);
4523 fprint_whex (asm_out_file, CV_SIGNATURE_C13);
4524 putc ('\n', asm_out_file);
4526 while (custom_types)
4528 codeview_custom_type *n = custom_types->next;
4530 switch (custom_types->kind)
4532 case LF_POINTER:
4533 write_lf_pointer (custom_types);
4534 break;
4536 case LF_MODIFIER:
4537 write_lf_modifier (custom_types);
4538 break;
4540 case LF_FIELDLIST:
4541 write_lf_fieldlist (custom_types);
4542 break;
4544 case LF_ENUM:
4545 write_lf_enum (custom_types);
4546 break;
4548 case LF_STRUCTURE:
4549 case LF_CLASS:
4550 write_lf_structure (custom_types);
4551 break;
4553 case LF_UNION:
4554 write_lf_union (custom_types);
4555 break;
4557 case LF_ARRAY:
4558 write_lf_array (custom_types);
4559 break;
4561 case LF_BITFIELD:
4562 write_lf_bitfield (custom_types);
4563 break;
4565 case LF_PROCEDURE:
4566 write_lf_procedure (custom_types);
4567 break;
4569 case LF_ARGLIST:
4570 write_lf_arglist (custom_types);
4571 break;
4573 case LF_FUNC_ID:
4574 write_lf_func_id (custom_types);
4575 break;
4577 case LF_MFUNC_ID:
4578 write_lf_mfunc_id (custom_types);
4579 break;
4581 case LF_STRING_ID:
4582 write_lf_string_id (custom_types);
4583 break;
4585 case LF_MFUNCTION:
4586 write_lf_mfunction (custom_types);
4587 break;
4589 case LF_METHODLIST:
4590 write_lf_methodlist (custom_types);
4591 break;
4593 default:
4594 break;
4597 free (custom_types);
4598 custom_types = n;
4602 /* Finish CodeView debug info emission. */
4604 void
4605 codeview_debug_finish (void)
4607 targetm.asm_out.named_section (".debug$S", SECTION_DEBUG, NULL);
4609 fputs (integer_asm_op (4, false), asm_out_file);
4610 fprint_whex (asm_out_file, CV_SIGNATURE_C13);
4611 putc ('\n', asm_out_file);
4613 write_strings_table ();
4614 write_source_files ();
4615 write_line_numbers ();
4616 write_codeview_symbols ();
4618 if (custom_types)
4619 write_custom_types ();
4621 if (types_htab)
4622 delete types_htab;
4624 if (string_id_htab)
4625 delete string_id_htab;
4628 /* Translate a DWARF base type (DW_TAG_base_type) into its CodeView
4629 equivalent. */
4631 static uint32_t
4632 get_type_num_base_type (dw_die_ref type)
4634 unsigned int size = get_AT_unsigned (type, DW_AT_byte_size);
4636 switch (get_AT_unsigned (type, DW_AT_encoding))
4638 case DW_ATE_signed_char:
4640 const char *name = get_AT_string (type, DW_AT_name);
4642 if (size != 1)
4643 return 0;
4645 if (name && !strcmp (name, "signed char"))
4646 return T_CHAR;
4647 else
4648 return T_RCHAR;
4651 case DW_ATE_unsigned_char:
4652 if (size != 1)
4653 return 0;
4655 return T_UCHAR;
4657 case DW_ATE_signed:
4658 switch (size)
4660 case 2:
4661 return T_SHORT;
4663 case 4:
4665 const char *name = get_AT_string (type, DW_AT_name);
4667 if (name && !strcmp (name, "int"))
4668 return T_INT4;
4669 else
4670 return T_LONG;
4673 case 8:
4674 return T_QUAD;
4676 default:
4677 return 0;
4680 case DW_ATE_unsigned:
4681 switch (size)
4683 case 2:
4685 const char *name = get_AT_string (type, DW_AT_name);
4687 if (name && !strcmp (name, "wchar_t"))
4688 return T_WCHAR;
4689 else
4690 return T_USHORT;
4693 case 4:
4695 const char *name = get_AT_string (type, DW_AT_name);
4697 if (name && !strcmp (name, "unsigned int"))
4698 return T_UINT4;
4699 else
4700 return T_ULONG;
4703 case 8:
4704 return T_UQUAD;
4706 default:
4707 return 0;
4710 case DW_ATE_UTF:
4711 switch (size)
4713 case 1:
4714 return T_CHAR8;
4716 case 2:
4717 return T_CHAR16;
4719 case 4:
4720 return T_CHAR32;
4722 default:
4723 return 0;
4726 case DW_ATE_float:
4727 switch (size)
4729 case 4:
4730 return T_REAL32;
4732 case 8:
4733 return T_REAL64;
4735 case 12:
4736 return T_REAL80;
4738 case 16:
4739 return T_REAL128;
4741 default:
4742 return 0;
4745 case DW_ATE_boolean:
4746 if (size == 1)
4747 return T_BOOL08;
4748 else
4749 return 0;
4751 default:
4752 return 0;
4756 /* Add a new codeview_custom_type to our singly-linked custom_types list. */
4758 static void
4759 add_custom_type (codeview_custom_type *ct)
4761 uint32_t num;
4763 if (last_custom_type)
4765 num = last_custom_type->num + 1;
4766 last_custom_type->next = ct;
4768 else
4770 num = FIRST_TYPE;
4771 custom_types = ct;
4774 last_custom_type = ct;
4776 ct->num = num;
4779 /* Process a DW_TAG_pointer_type DIE. If this is a pointer to a builtin
4780 type, return the predefined constant for this. Otherwise, add a new
4781 LF_POINTER type and return its number. */
4783 static uint32_t
4784 get_type_num_pointer_type (dw_die_ref type, bool in_struct)
4786 uint32_t base_type_num, byte_size;
4787 dw_die_ref base_type;
4788 codeview_custom_type *ct;
4790 byte_size = get_AT_unsigned (type, DW_AT_byte_size);
4791 if (byte_size != 4 && byte_size != 8)
4792 return 0;
4794 base_type = get_AT_ref (type, DW_AT_type);
4796 /* If DW_AT_type is not set, this must be a void pointer. */
4797 if (!base_type)
4798 return byte_size == 4 ? T_32PVOID : T_64PVOID;
4800 base_type_num = get_type_num (base_type, in_struct, false);
4801 if (base_type_num == 0)
4802 return 0;
4804 /* Pointers to builtin types have predefined type numbers, with the top byte
4805 determining the pointer size - 0x0400 for a 32-bit pointer and 0x0600
4806 for 64-bit. */
4807 if (base_type_num < FIRST_TYPE && !(base_type_num & 0xff00))
4809 if (byte_size == 4)
4810 return CV_POINTER_32 | base_type_num;
4811 else
4812 return CV_POINTER_64 | base_type_num;
4815 ct = (codeview_custom_type *) xmalloc (sizeof (codeview_custom_type));
4817 ct->next = NULL;
4818 ct->kind = LF_POINTER;
4819 ct->lf_pointer.base_type = base_type_num;
4821 if (byte_size == 4)
4822 ct->lf_pointer.attributes = CV_PTR_NEAR32;
4823 else
4824 ct->lf_pointer.attributes = CV_PTR_64;
4826 ct->lf_pointer.attributes |= byte_size << 13;
4828 add_custom_type (ct);
4830 return ct->num;
4833 /* Process a DW_TAG_reference_type or DW_TAG_rvalue_reference_type DIE, add a
4834 new LF_POINTER type, and return its number. */
4836 static uint32_t
4837 get_type_num_reference_type (dw_die_ref type, bool in_struct, bool rvref)
4839 uint32_t base_type_num, byte_size;
4840 dw_die_ref base_type;
4841 codeview_custom_type *ct;
4843 byte_size = get_AT_unsigned (type, DW_AT_byte_size);
4844 if (byte_size != 4 && byte_size != 8)
4845 return 0;
4847 base_type = get_AT_ref (type, DW_AT_type);
4849 base_type_num = get_type_num (base_type, in_struct, false);
4850 if (base_type_num == 0)
4851 return 0;
4853 ct = (codeview_custom_type *) xmalloc (sizeof (codeview_custom_type));
4855 ct->next = NULL;
4856 ct->kind = LF_POINTER;
4857 ct->lf_pointer.base_type = base_type_num;
4858 ct->lf_pointer.attributes = rvref ? CV_PTR_MODE_RVREF : CV_PTR_MODE_LVREF;
4860 if (byte_size == 4)
4861 ct->lf_pointer.attributes |= CV_PTR_NEAR32;
4862 else
4863 ct->lf_pointer.attributes |= CV_PTR_64;
4865 ct->lf_pointer.attributes |= byte_size << 13;
4867 add_custom_type (ct);
4869 return ct->num;
4872 /* Process a DW_TAG_const_type DIE, adding an LF_MODIFIER type and returning
4873 its number. */
4875 static uint32_t
4876 get_type_num_const_type (dw_die_ref type, bool in_struct)
4878 dw_die_ref base_type;
4879 uint32_t base_type_num;
4880 codeview_custom_type *ct;
4881 bool is_volatile = false;
4883 base_type = get_AT_ref (type, DW_AT_type);
4885 /* Handle case when this is a const volatile type - we only need one
4886 LF_MODIFIER for this. */
4887 if (base_type && dw_get_die_tag (base_type) == DW_TAG_volatile_type)
4889 is_volatile = true;
4891 base_type = get_AT_ref (base_type, DW_AT_type);
4894 if (!base_type)
4896 base_type_num = T_VOID;
4898 else
4900 base_type_num = get_type_num (base_type, in_struct, false);
4901 if (base_type_num == 0)
4902 return 0;
4905 ct = (codeview_custom_type *) xmalloc (sizeof (codeview_custom_type));
4907 ct->next = NULL;
4908 ct->kind = LF_MODIFIER;
4909 ct->lf_modifier.base_type = base_type_num;
4910 ct->lf_modifier.modifier = MOD_const;
4912 if (is_volatile)
4913 ct->lf_modifier.modifier |= MOD_volatile;
4915 add_custom_type (ct);
4917 return ct->num;
4920 /* Process a DW_TAG_volatile_type DIE, adding an LF_MODIFIER type and
4921 returning its number. */
4923 static uint32_t
4924 get_type_num_volatile_type (dw_die_ref type, bool in_struct)
4926 dw_die_ref base_type;
4927 uint32_t base_type_num;
4928 codeview_custom_type *ct;
4930 base_type = get_AT_ref (type, DW_AT_type);
4932 if (base_type)
4934 base_type_num = get_type_num (base_type, in_struct, false);
4935 if (base_type_num == 0)
4936 return 0;
4938 else
4940 base_type_num = T_VOID;
4943 ct = (codeview_custom_type *) xmalloc (sizeof (codeview_custom_type));
4945 ct->next = NULL;
4946 ct->kind = LF_MODIFIER;
4947 ct->lf_modifier.base_type = base_type_num;
4948 ct->lf_modifier.modifier = MOD_volatile;
4950 add_custom_type (ct);
4952 return ct->num;
4955 /* Return the name of a DIE, traversing its parents in order to construct a
4956 C++-style name if necessary. */
4957 static char *
4958 get_name (dw_die_ref die)
4960 dw_die_ref decl = get_AT_ref (die, DW_AT_specification);
4961 dw_die_ref parent;
4962 const char *name;
4963 char *str;
4964 size_t len;
4966 static const char anon[] = "<unnamed-tag>";
4967 static const char sep[] = "::";
4969 if (decl)
4970 die = decl;
4972 name = get_AT_string (die, DW_AT_name);
4974 if (!name)
4975 return NULL;
4977 parent = dw_get_die_parent (die);
4979 if (!parent || dw_get_die_tag (parent) == DW_TAG_compile_unit)
4980 return xstrdup (name);
4982 len = strlen (name);
4983 while (parent && dw_get_die_tag (parent) != DW_TAG_compile_unit)
4985 const char *ns_name = get_AT_string (parent, DW_AT_name);
4987 len += sizeof (sep) - 1;
4989 if (ns_name)
4990 len += strlen (ns_name);
4991 else
4992 len += sizeof (anon) - 1;
4994 parent = dw_get_die_parent (parent);
4997 str = (char *) xmalloc (len + 1);
4998 str[len] = 0;
5000 len -= strlen (name);
5001 memcpy (str + len, name, strlen (name));
5003 parent = dw_get_die_parent (die);
5004 while (parent && dw_get_die_tag (parent) != DW_TAG_compile_unit)
5006 const char *ns_name = get_AT_string (parent, DW_AT_name);
5008 len -= sizeof (sep) - 1;
5009 memcpy (str + len, sep, sizeof (sep) - 1);
5011 if (ns_name)
5013 len -= strlen (ns_name);
5014 memcpy (str + len, ns_name, strlen (ns_name));
5016 else
5018 len -= sizeof (anon) - 1;
5019 memcpy (str + len, anon, sizeof (anon) - 1);
5022 parent = dw_get_die_parent (parent);
5025 return str;
5028 /* Add a forward declaration for an enum. This is legal from C++11 onwards. */
5030 static uint32_t
5031 add_enum_forward_def (dw_die_ref type)
5033 codeview_custom_type *ct;
5035 ct = (codeview_custom_type *) xmalloc (sizeof (codeview_custom_type));
5037 ct->next = NULL;
5038 ct->kind = LF_ENUM;
5040 ct->lf_enum.count = 0;
5041 ct->lf_enum.properties = CV_PROP_FWDREF;
5042 ct->lf_enum.underlying_type = get_type_num (get_AT_ref (type, DW_AT_type),
5043 false, false);
5044 ct->lf_enum.fieldlist = 0;
5045 ct->lf_enum.name = get_name (type);
5047 add_custom_type (ct);
5049 return ct->num;
5052 /* Process a DW_TAG_enumeration_type DIE, adding an LF_FIELDLIST and an LF_ENUM
5053 type, returning the number of the latter. */
5055 static uint32_t
5056 get_type_num_enumeration_type (dw_die_ref type, bool in_struct)
5058 dw_die_ref first_child;
5059 codeview_custom_type *ct;
5060 uint16_t count = 0;
5061 uint32_t last_type = 0;
5063 if (get_AT_flag (type, DW_AT_declaration))
5064 return add_enum_forward_def (type);
5066 /* First, add an LF_FIELDLIST for the enum's values. We don't need to worry
5067 about deduplication here, as ld will take care of that for us. If there's
5068 a lot of entries, add more LF_FIELDLISTs with LF_INDEXes pointing to
5069 the overflow lists. */
5071 first_child = dw_get_die_child (type);
5073 ct = (codeview_custom_type *) xmalloc (sizeof (codeview_custom_type));
5075 ct->next = NULL;
5076 ct->kind = LF_FIELDLIST;
5077 ct->lf_fieldlist.length = 0;
5078 ct->lf_fieldlist.subtypes = NULL;
5079 ct->lf_fieldlist.last_subtype = NULL;
5081 if (first_child)
5083 dw_die_ref c;
5085 c = first_child;
5088 dw_attr_node *att;
5089 codeview_subtype *el;
5090 size_t el_len;
5092 c = dw_get_die_sib (c);
5094 if (dw_get_die_tag (c) != DW_TAG_enumerator)
5095 continue;
5097 att = get_AT (c, DW_AT_const_value);
5098 if (!att)
5099 continue;
5101 el = (codeview_subtype *) xmalloc (sizeof (*el));
5102 el->next = NULL;
5103 el->kind = LF_ENUMERATE;
5105 switch (AT_class (att))
5107 case dw_val_class_unsigned_const:
5108 case dw_val_class_unsigned_const_implicit:
5109 el->lf_enumerate.value.neg = false;
5110 el->lf_enumerate.value.num = att->dw_attr_val.v.val_unsigned;
5111 break;
5113 case dw_val_class_const:
5114 case dw_val_class_const_implicit:
5115 if (att->dw_attr_val.v.val_int < 0)
5117 el->lf_enumerate.value.neg = true;
5118 el->lf_enumerate.value.num = -att->dw_attr_val.v.val_int;
5120 else
5122 el->lf_enumerate.value.neg = false;
5123 el->lf_enumerate.value.num = att->dw_attr_val.v.val_int;
5125 break;
5127 default:
5128 free (el);
5129 continue;
5132 el->lf_enumerate.name = xstrdup (get_AT_string (c, DW_AT_name));
5134 el_len = 7 + strlen (el->lf_enumerate.name);
5135 el_len += cv_integer_len (&el->lf_enumerate.value);
5137 if (el_len % 4)
5138 el_len += 4 - (el_len % 4);
5140 if (ct->lf_fieldlist.length + el_len > MAX_FIELDLIST_SIZE)
5142 codeview_subtype *idx;
5143 codeview_custom_type *ct2;
5145 idx = (codeview_subtype *) xmalloc (sizeof (*idx));
5146 idx->next = NULL;
5147 idx->kind = LF_INDEX;
5148 idx->lf_index.type_num = 0;
5150 ct->lf_fieldlist.last_subtype->next = idx;
5151 ct->lf_fieldlist.last_subtype = idx;
5153 ct2 = (codeview_custom_type *)
5154 xmalloc (sizeof (codeview_custom_type));
5156 ct2->next = ct;
5157 ct2->kind = LF_FIELDLIST;
5158 ct2->lf_fieldlist.length = 0;
5159 ct2->lf_fieldlist.subtypes = NULL;
5160 ct2->lf_fieldlist.last_subtype = NULL;
5162 ct = ct2;
5165 ct->lf_fieldlist.length += el_len;
5167 if (ct->lf_fieldlist.last_subtype)
5168 ct->lf_fieldlist.last_subtype->next = el;
5169 else
5170 ct->lf_fieldlist.subtypes = el;
5172 ct->lf_fieldlist.last_subtype = el;
5173 count++;
5175 while (c != first_child);
5178 while (ct)
5180 codeview_custom_type *ct2;
5182 ct2 = ct->next;
5183 ct->next = NULL;
5185 if (ct->lf_fieldlist.last_subtype->kind == LF_INDEX)
5186 ct->lf_fieldlist.last_subtype->lf_index.type_num = last_type;
5188 add_custom_type (ct);
5189 last_type = ct->num;
5191 ct = ct2;
5194 /* Now add an LF_ENUM, pointing to the LF_FIELDLIST we just added. */
5196 ct = (codeview_custom_type *) xmalloc (sizeof (codeview_custom_type));
5198 ct->next = NULL;
5199 ct->kind = LF_ENUM;
5200 ct->lf_enum.count = count;
5201 ct->lf_enum.properties = 0;
5202 ct->lf_enum.underlying_type = get_type_num (get_AT_ref (type, DW_AT_type),
5203 in_struct, false);
5204 ct->lf_enum.fieldlist = last_type;
5205 ct->lf_enum.name = get_name (type);
5207 add_custom_type (ct);
5209 return ct->num;
5212 /* Add a DIE to our deferred_types list. This happens when we have a struct
5213 with a pointer to a type that hasn't been defined yet, but which gets
5214 defined later on. */
5216 static void
5217 add_deferred_type (dw_die_ref type)
5219 codeview_deferred_type *def;
5221 def = (codeview_deferred_type *) xmalloc (sizeof (codeview_deferred_type));
5223 def->next = NULL;
5224 def->type = type;
5226 if (!deferred_types)
5227 deferred_types = def;
5228 else
5229 last_deferred_type->next = def;
5231 last_deferred_type = def;
5234 /* Flush the contents of our deferred_types list. This happens after everything
5235 else has been written. We call get_type_num to ensure that a type gets
5236 added to custom_types, if it hasn't been already. */
5238 static void
5239 flush_deferred_types (void)
5241 while (deferred_types)
5243 codeview_deferred_type *next;
5245 next = deferred_types->next;
5247 get_type_num (deferred_types->type, false, true);
5249 free (deferred_types);
5250 deferred_types = next;
5253 last_deferred_type = NULL;
5256 /* Add a forward definition for a struct, class, or union. */
5258 static uint32_t
5259 add_struct_forward_def (dw_die_ref type)
5261 codeview_custom_type *ct;
5263 ct = (codeview_custom_type *) xmalloc (sizeof (codeview_custom_type));
5265 ct->next = NULL;
5267 switch (dw_get_die_tag (type))
5269 case DW_TAG_class_type:
5270 ct->kind = LF_CLASS;
5271 break;
5273 case DW_TAG_structure_type:
5274 ct->kind = LF_STRUCTURE;
5275 break;
5277 case DW_TAG_union_type:
5278 ct->kind = LF_UNION;
5279 break;
5281 default:
5282 break;
5285 ct->lf_structure.num_members = 0;
5286 ct->lf_structure.properties = CV_PROP_FWDREF;
5287 ct->lf_structure.field_list = 0;
5288 ct->lf_structure.derived_from = 0;
5289 ct->lf_structure.vshape = 0;
5290 ct->lf_structure.length.neg = false;
5291 ct->lf_structure.length.num = 0;
5292 ct->lf_structure.name = get_name (type);
5294 add_custom_type (ct);
5296 if (!get_AT_flag (type, DW_AT_declaration))
5297 add_deferred_type (type);
5299 return ct->num;
5302 /* Add an LF_BITFIELD type, returning its number. DWARF represents bitfields
5303 as members in a struct with a DW_AT_data_bit_offset attribute, whereas in
5304 CodeView they're a distinct type. */
5306 static uint32_t
5307 create_bitfield (dw_die_ref c)
5309 codeview_custom_type *ct;
5310 uint32_t base_type;
5312 base_type = get_type_num (get_AT_ref (c, DW_AT_type), true, false);
5313 if (base_type == 0)
5314 return 0;
5316 ct = (codeview_custom_type *) xmalloc (sizeof (codeview_custom_type));
5318 ct->next = NULL;
5319 ct->kind = LF_BITFIELD;
5320 ct->lf_bitfield.base_type = base_type;
5321 ct->lf_bitfield.length = get_AT_unsigned (c, DW_AT_bit_size);
5322 ct->lf_bitfield.position = get_AT_unsigned (c, DW_AT_data_bit_offset);
5324 add_custom_type (ct);
5326 return ct->num;
5329 /* Create an LF_MEMBER field list subtype for a struct member, returning its
5330 pointer in el and its size in el_len. */
5332 static void
5333 add_struct_member (dw_die_ref c, uint16_t accessibility,
5334 codeview_subtype **el, size_t *el_len)
5336 *el = (codeview_subtype *) xmalloc (sizeof (**el));
5337 (*el)->next = NULL;
5338 (*el)->kind = LF_MEMBER;
5339 (*el)->lf_member.attributes = accessibility;
5341 if (get_AT (c, DW_AT_data_bit_offset))
5342 (*el)->lf_member.type = create_bitfield (c);
5343 else
5344 (*el)->lf_member.type = get_type_num (get_AT_ref (c, DW_AT_type),
5345 true, false);
5347 (*el)->lf_member.offset.neg = false;
5348 (*el)->lf_member.offset.num = get_AT_unsigned (c, DW_AT_data_member_location);
5350 *el_len = 11 + cv_integer_len (&(*el)->lf_member.offset);
5352 if (get_AT_string (c, DW_AT_name))
5354 (*el)->lf_member.name = xstrdup (get_AT_string (c, DW_AT_name));
5355 *el_len += strlen ((*el)->lf_member.name);
5357 else
5359 (*el)->lf_member.name = NULL;
5362 if (*el_len % 4)
5363 *el_len += 4 - (*el_len % 4);
5366 /* Create an LF_STMEMBER field list subtype for a static struct member,
5367 returning its pointer in el and its size in el_len. */
5369 static void
5370 add_struct_static_member (dw_die_ref c, uint16_t accessibility,
5371 codeview_subtype **el, size_t *el_len)
5373 *el = (codeview_subtype *) xmalloc (sizeof (**el));
5374 (*el)->next = NULL;
5375 (*el)->kind = LF_STMEMBER;
5376 (*el)->lf_static_member.attributes = accessibility;
5377 (*el)->lf_static_member.type = get_type_num (get_AT_ref (c, DW_AT_type),
5378 true, false);
5379 (*el)->lf_static_member.name = xstrdup (get_AT_string (c, DW_AT_name));
5381 *el_len = 9 + strlen ((*el)->lf_static_member.name);
5383 if (*el_len % 4)
5384 *el_len += 4 - (*el_len % 4);
5387 /* Create a field list subtype for a struct function, returning its pointer in
5388 el and its size in el_len. If the function is not overloaded, create an
5389 LF_ONEMETHOD subtype pointing to the LF_MFUNCTION. Otherwise, add an
5390 LF_METHODLIST type of the function's forms, and create an LF_METHOD subtype
5391 pointing to this. */
5393 static void
5394 add_struct_function (dw_die_ref c, hash_table<method_hasher> *method_htab,
5395 codeview_subtype **el, size_t *el_len)
5397 const char *name = get_AT_string (c, DW_AT_name);
5398 codeview_method **slot, *meth;
5400 slot = method_htab->find_slot_with_hash (name, htab_hash_string (name),
5401 NO_INSERT);
5402 if (!slot)
5403 return;
5405 meth = *slot;
5407 *el = (codeview_subtype *) xmalloc (sizeof (**el));
5408 (*el)->next = NULL;
5410 if (meth->count == 1)
5412 (*el)->kind = LF_ONEMETHOD;
5413 (*el)->lf_onemethod.method_attribute = meth->attribute;
5414 (*el)->lf_onemethod.method_type = meth->type;
5415 (*el)->lf_onemethod.name = xstrdup (name);
5417 *el_len = 9 + strlen ((*el)->lf_onemethod.name);
5419 else
5421 codeview_custom_type *ct;
5422 lf_methodlist_entry *ent;
5424 ct = (codeview_custom_type *) xmalloc (sizeof (codeview_custom_type));
5426 ct->next = NULL;
5427 ct->kind = LF_METHODLIST;
5428 ct->lf_methodlist.count = meth->count;
5429 ct->lf_methodlist.entries = (lf_methodlist_entry *)
5430 xmalloc (meth->count * sizeof (lf_methodlist_entry));
5432 ent = ct->lf_methodlist.entries;
5433 for (codeview_method *m = meth; m; m = m->next)
5435 ent->method_attribute = m->attribute;
5436 ent->method_type = m->type;
5437 ent++;
5440 add_custom_type (ct);
5442 (*el)->kind = LF_METHOD;
5443 (*el)->lf_method.count = meth->count;
5444 (*el)->lf_method.method_list = ct->num;
5445 (*el)->lf_method.name = xstrdup (name);
5447 *el_len = 9 + strlen ((*el)->lf_method.name);
5450 if (*el_len % 4)
5451 *el_len += 4 - (*el_len % 4);
5453 method_htab->remove_elt_with_hash (name, htab_hash_string (name));
5455 while (meth)
5457 codeview_method *next = meth->next;
5459 free (meth->name);
5460 free (meth);
5461 meth = next;
5465 /* Create a new LF_MFUNCTION type for a struct function, add it to the
5466 types_htab hash table, and return its type number. */
5468 static uint32_t
5469 get_mfunction_type (dw_die_ref c)
5471 uint32_t containing_class_type, this_type, mfunction_type;
5472 dw_die_ref obj_pointer;
5473 codeview_type **slot, *t;
5475 containing_class_type = get_type_num (dw_get_die_parent (c), true, false);
5477 obj_pointer = get_AT_ref (c, DW_AT_object_pointer);
5478 if (obj_pointer && dw_get_die_tag (obj_pointer) == DW_TAG_formal_parameter)
5480 this_type = get_type_num (get_AT_ref (obj_pointer, DW_AT_type),
5481 true, false);
5483 else
5485 this_type = 0;
5488 mfunction_type = get_type_num_subroutine_type (c, true, containing_class_type,
5489 this_type, 0);
5491 slot = types_htab->find_slot_with_hash (c, htab_hash_pointer (c), INSERT);
5493 t = (codeview_type *) xmalloc (sizeof (codeview_type));
5495 t->die = c;
5496 t->num = mfunction_type;
5497 t->is_fwd_ref = false;
5499 *slot = t;
5501 return mfunction_type;
5504 /* Translate a DWARF DW_AT_accessibility constant into its CodeView
5505 equivalent. If implicit, follow the C++ rules. */
5507 static uint16_t
5508 get_accessibility (dw_die_ref c)
5510 switch (get_AT_unsigned (c, DW_AT_accessibility))
5512 case DW_ACCESS_private:
5513 return CV_ACCESS_PRIVATE;
5515 case DW_ACCESS_protected:
5516 return CV_ACCESS_PROTECTED;
5518 case DW_ACCESS_public:
5519 return CV_ACCESS_PUBLIC;
5521 /* Members in a C++ struct or union are public by default, members
5522 in a class are private. */
5523 default:
5524 if (dw_get_die_tag (dw_get_die_parent (c)) == DW_TAG_class_type)
5525 return CV_ACCESS_PRIVATE;
5526 else
5527 return CV_ACCESS_PUBLIC;
5531 /* Returns true if the struct function pointed to by die is an instantiated
5532 template function. These are skipped in CodeView struct definitions, as
5533 otherwise the same type might not be deduplicated across different TUs. */
5535 static bool
5536 is_templated_func (dw_die_ref die)
5538 dw_die_ref c = dw_get_die_child (die);
5540 if (!c)
5541 return false;
5545 c = dw_get_die_sib (c);
5547 if (dw_get_die_tag (c) == DW_TAG_template_type_param)
5548 return true;
5550 while (c != dw_get_die_child (die));
5552 return false;
5555 /* Process a DW_TAG_structure_type, DW_TAG_class_type, or DW_TAG_union_type
5556 DIE, add an LF_FIELDLIST and an LF_STRUCTURE / LF_CLASS / LF_UNION type,
5557 and return the number of the latter. */
5559 static uint32_t
5560 get_type_num_struct (dw_die_ref type, bool in_struct, bool *is_fwd_ref)
5562 dw_die_ref first_child;
5563 codeview_custom_type *ct;
5564 uint16_t num_members = 0;
5565 uint32_t last_type = 0;
5567 if ((in_struct && get_AT_string (type, DW_AT_name))
5568 || get_AT_flag (type, DW_AT_declaration))
5570 *is_fwd_ref = true;
5571 return add_struct_forward_def (type);
5574 *is_fwd_ref = false;
5576 /* First, add an LF_FIELDLIST for the structure's members. We don't need to
5577 worry about deduplication here, as ld will take care of that for us.
5578 If there's a lot of entries, add more LF_FIELDLISTs with LF_INDEXes
5579 pointing to the overflow lists. */
5581 first_child = dw_get_die_child (type);
5583 ct = (codeview_custom_type *) xmalloc (sizeof (codeview_custom_type));
5585 ct->next = NULL;
5586 ct->kind = LF_FIELDLIST;
5587 ct->lf_fieldlist.length = 0;
5588 ct->lf_fieldlist.subtypes = NULL;
5589 ct->lf_fieldlist.last_subtype = NULL;
5591 if (first_child)
5593 hash_table<method_hasher> *method_htab = NULL;
5594 dw_die_ref c;
5596 /* First, loop through and record any non-templated member functions.
5597 This is because overloaded and non-overloaded functions are expressed
5598 differently in CodeView, so we need to have a hash table on the name
5599 to know how to record it later on. */
5601 c = first_child;
5604 c = dw_get_die_sib (c);
5606 if (dw_get_die_tag (c) == DW_TAG_subprogram)
5608 const char *name = get_AT_string (c, DW_AT_name);
5609 codeview_method *meth, **slot;
5611 if (is_templated_func (c))
5612 continue;
5614 if (!method_htab)
5615 method_htab = new hash_table<method_hasher> (10);
5617 meth = (codeview_method *) xmalloc (sizeof (*meth));
5619 slot = method_htab->find_slot_with_hash (name,
5620 htab_hash_string (name),
5621 INSERT);
5623 meth->attribute = get_accessibility (c);
5625 if (!get_AT_ref (c, DW_AT_object_pointer))
5626 meth->attribute |= CV_METHOD_STATIC;
5628 meth->type = get_mfunction_type (c);
5629 meth->next = NULL;
5631 if (*slot)
5633 if ((*slot)->last)
5634 (*slot)->last->next = meth;
5635 else
5636 (*slot)->next = meth;
5638 (*slot)->last = meth;
5639 (*slot)->count++;
5641 meth->name = NULL;
5643 else
5645 meth->name = xstrdup (name);
5646 meth->last = NULL;
5647 meth->count = 1;
5648 *slot = meth;
5652 while (c != first_child);
5654 /* Now loop through again and record the actual members. */
5656 c = first_child;
5659 codeview_subtype *el;
5660 size_t el_len = 0;
5661 uint16_t accessibility;
5663 c = dw_get_die_sib (c);
5665 accessibility = get_accessibility (c);
5667 switch (dw_get_die_tag (c))
5669 case DW_TAG_member:
5670 add_struct_member (c, accessibility, &el, &el_len);
5671 break;
5673 case DW_TAG_variable:
5674 add_struct_static_member (c, accessibility, &el, &el_len);
5675 break;
5677 case DW_TAG_subprogram:
5678 if (!is_templated_func (c))
5679 add_struct_function (c, method_htab, &el, &el_len);
5680 break;
5682 default:
5683 break;
5686 if (el_len == 0)
5687 continue;
5689 /* Add an LF_INDEX subtype if everything's too big for one
5690 LF_FIELDLIST. */
5692 if (ct->lf_fieldlist.length + el_len > MAX_FIELDLIST_SIZE)
5694 codeview_subtype *idx;
5695 codeview_custom_type *ct2;
5697 idx = (codeview_subtype *) xmalloc (sizeof (*idx));
5698 idx->next = NULL;
5699 idx->kind = LF_INDEX;
5700 idx->lf_index.type_num = 0;
5702 ct->lf_fieldlist.last_subtype->next = idx;
5703 ct->lf_fieldlist.last_subtype = idx;
5705 ct2 = (codeview_custom_type *)
5706 xmalloc (sizeof (codeview_custom_type));
5708 ct2->next = ct;
5709 ct2->kind = LF_FIELDLIST;
5710 ct2->lf_fieldlist.length = 0;
5711 ct2->lf_fieldlist.subtypes = NULL;
5712 ct2->lf_fieldlist.last_subtype = NULL;
5714 ct = ct2;
5717 ct->lf_fieldlist.length += el_len;
5719 if (ct->lf_fieldlist.last_subtype)
5720 ct->lf_fieldlist.last_subtype->next = el;
5721 else
5722 ct->lf_fieldlist.subtypes = el;
5724 ct->lf_fieldlist.last_subtype = el;
5725 num_members++;
5727 while (c != first_child);
5729 if (method_htab)
5730 delete method_htab;
5733 while (ct)
5735 codeview_custom_type *ct2;
5737 ct2 = ct->next;
5738 ct->next = NULL;
5740 if (ct->lf_fieldlist.last_subtype
5741 && ct->lf_fieldlist.last_subtype->kind == LF_INDEX)
5743 ct->lf_fieldlist.last_subtype->lf_index.type_num = last_type;
5746 add_custom_type (ct);
5747 last_type = ct->num;
5749 ct = ct2;
5752 /* Now add an LF_STRUCTURE / LF_CLASS / LF_UNION, pointing to the
5753 LF_FIELDLIST we just added. */
5755 ct = (codeview_custom_type *) xmalloc (sizeof (codeview_custom_type));
5757 ct->next = NULL;
5759 switch (dw_get_die_tag (type))
5761 case DW_TAG_class_type:
5762 ct->kind = LF_CLASS;
5763 break;
5765 case DW_TAG_structure_type:
5766 ct->kind = LF_STRUCTURE;
5767 break;
5769 case DW_TAG_union_type:
5770 ct->kind = LF_UNION;
5771 break;
5773 default:
5774 break;
5777 ct->lf_structure.num_members = num_members;
5778 ct->lf_structure.properties = 0;
5779 ct->lf_structure.field_list = last_type;
5780 ct->lf_structure.derived_from = 0;
5781 ct->lf_structure.vshape = 0;
5782 ct->lf_structure.length.neg = false;
5783 ct->lf_structure.length.num = get_AT_unsigned (type, DW_AT_byte_size);
5784 ct->lf_structure.name = get_name (type);
5786 add_custom_type (ct);
5788 return ct->num;
5791 /* Process a DW_TAG_subroutine_type DIE, adding an LF_ARGLIST and an
5792 LF_PROCEDURE or LF_MFUNCTION type, and returning the number of the
5793 latter. */
5795 static uint32_t
5796 get_type_num_subroutine_type (dw_die_ref type, bool in_struct,
5797 uint32_t containing_class_type,
5798 uint32_t this_type, int32_t this_adjustment)
5800 codeview_custom_type *ct;
5801 uint32_t return_type, arglist_type;
5802 uint16_t num_args;
5803 dw_die_ref first_child;
5805 /* Find the return type. */
5807 if (get_AT_ref (type, DW_AT_type))
5809 return_type = get_type_num (get_AT_ref (type, DW_AT_type), in_struct,
5810 false);
5811 if (return_type == 0)
5812 return 0;
5814 else
5816 return_type = T_VOID;
5819 /* Count the arguments. */
5821 first_child = dw_get_die_child (type);
5822 num_args = 0;
5824 if (first_child)
5826 dw_die_ref c;
5828 c = first_child;
5831 c = dw_get_die_sib (c);
5833 if (dw_get_die_tag (c) != DW_TAG_formal_parameter
5834 && dw_get_die_tag (c) != DW_TAG_unspecified_parameters)
5835 continue;
5837 /* We ignore "this" params here. */
5838 if (get_AT_flag (c, DW_AT_artificial) != 0)
5839 continue;
5841 num_args++;
5843 while (c != first_child);
5846 /* Create an LF_ARGLIST for the arguments. If this is a duplicate, ld
5847 will take care of this for us. */
5849 first_child = dw_get_die_child (type);
5851 ct = (codeview_custom_type *) xmalloc (sizeof (codeview_custom_type));
5853 ct->next = NULL;
5854 ct->kind = LF_ARGLIST;
5855 ct->lf_arglist.num_entries = num_args;
5857 if (num_args > 0)
5859 dw_die_ref c;
5860 uint32_t *argptr;
5862 ct->lf_arglist.args = (uint32_t *) xmalloc (sizeof (uint32_t) * num_args);
5863 argptr = ct->lf_arglist.args;
5865 c = first_child;
5868 c = dw_get_die_sib (c);
5870 if (get_AT_flag (c, DW_AT_artificial) != 0)
5871 continue;
5873 switch (dw_get_die_tag (c))
5875 case DW_TAG_formal_parameter:
5876 *argptr = get_type_num (get_AT_ref (c, DW_AT_type), in_struct,
5877 false);
5878 argptr++;
5879 break;
5881 case DW_TAG_unspecified_parameters:
5882 *argptr = 0;
5883 argptr++;
5884 break;
5886 default:
5887 break;
5890 while (c != first_child);
5892 else
5894 ct->lf_arglist.args = NULL;
5897 add_custom_type (ct);
5899 arglist_type = ct->num;
5901 /* Finally, create an LF_PROCEDURE or LF_MFUNCTION type. */
5903 ct = (codeview_custom_type *) xmalloc (sizeof (codeview_custom_type));
5905 ct->next = NULL;
5907 if (containing_class_type != 0)
5909 ct->kind = LF_MFUNCTION;
5910 ct->lf_mfunction.return_type = return_type;
5911 ct->lf_mfunction.containing_class_type = containing_class_type;
5912 ct->lf_mfunction.this_type = this_type;
5913 ct->lf_mfunction.calling_convention = 0;
5914 ct->lf_mfunction.attributes = 0;
5915 ct->lf_mfunction.num_parameters = num_args;
5916 ct->lf_mfunction.arglist = arglist_type;
5917 ct->lf_mfunction.this_adjustment = this_adjustment;
5919 else
5921 ct->kind = LF_PROCEDURE;
5922 ct->lf_procedure.return_type = return_type;
5923 ct->lf_procedure.calling_convention = 0;
5924 ct->lf_procedure.attributes = 0;
5925 ct->lf_procedure.num_parameters = num_args;
5926 ct->lf_procedure.arglist = arglist_type;
5929 add_custom_type (ct);
5931 return ct->num;
5934 /* Process a DW_TAG_array_type DIE, adding an LF_ARRAY type and returning its
5935 number. */
5937 static uint32_t
5938 get_type_num_array_type (dw_die_ref type, bool in_struct)
5940 dw_die_ref base_type, t, first_child, c, *dimension_arr;
5941 uint64_t size = 0;
5942 unsigned int dimensions, i;
5943 uint32_t element_type;
5945 base_type = get_AT_ref (type, DW_AT_type);
5946 if (!base_type)
5947 return 0;
5949 /* We need to know the size of our base type. Loop through until we find
5950 it. */
5951 t = base_type;
5952 while (t && size == 0)
5954 switch (dw_get_die_tag (t))
5956 case DW_TAG_const_type:
5957 case DW_TAG_volatile_type:
5958 case DW_TAG_typedef:
5959 case DW_TAG_enumeration_type:
5960 t = get_AT_ref (t, DW_AT_type);
5961 break;
5963 case DW_TAG_base_type:
5964 case DW_TAG_structure_type:
5965 case DW_TAG_class_type:
5966 case DW_TAG_union_type:
5967 case DW_TAG_pointer_type:
5968 case DW_TAG_reference_type:
5969 case DW_TAG_rvalue_reference_type:
5970 size = get_AT_unsigned (t, DW_AT_byte_size);
5971 break;
5973 default:
5974 return 0;
5978 if (size == 0)
5979 return 0;
5981 first_child = dw_get_die_child (type);
5982 if (!first_child)
5983 return 0;
5985 element_type = get_type_num (base_type, in_struct, false);
5986 if (element_type == 0)
5987 return 0;
5989 /* Create an array of our DW_TAG_subrange_type children, in reverse order.
5990 We have to do this because unlike DWARF CodeView doesn't have
5991 multidimensional arrays, so instead we do arrays of arrays. */
5993 dimensions = 0;
5994 c = first_child;
5997 c = dw_get_die_sib (c);
5998 if (dw_get_die_tag (c) != DW_TAG_subrange_type)
5999 continue;
6001 dimensions++;
6003 while (c != first_child);
6005 if (dimensions == 0)
6006 return 0;
6008 dimension_arr = (dw_die_ref *) xmalloc (sizeof (dw_die_ref) * dimensions);
6010 c = first_child;
6011 i = 0;
6014 c = dw_get_die_sib (c);
6015 if (dw_get_die_tag (c) != DW_TAG_subrange_type)
6016 continue;
6018 dimension_arr[dimensions - i - 1] = c;
6019 i++;
6021 while (c != first_child);
6023 /* Record an LF_ARRAY entry for each array dimension. If this leads to
6024 duplicate types, ld will take care of it for us. */
6026 for (i = 0; i < dimensions; i++)
6028 codeview_custom_type *ct;
6029 dw_die_ref index;
6031 ct = (codeview_custom_type *) xmalloc (sizeof (codeview_custom_type));
6033 size *= get_AT_unsigned (dimension_arr[i], DW_AT_upper_bound) + 1;
6035 index = get_AT_ref (dimension_arr[i], DW_AT_type);
6037 ct->next = NULL;
6038 ct->kind = LF_ARRAY;
6039 ct->lf_array.element_type = element_type;
6040 ct->lf_array.index_type = get_type_num (index, in_struct, false);
6041 ct->lf_array.length_in_bytes.neg = false;
6042 ct->lf_array.length_in_bytes.num = size;
6044 add_custom_type (ct);
6046 element_type = ct->num;
6049 free (dimension_arr);
6051 return element_type;
6054 /* Process a DIE representing a type definition, add a CodeView type if
6055 necessary, and return its number. If it's something we can't handle, return
6056 0. We keep a hash table so that we're not adding the same type multiple
6057 times - though if we do it's not disastrous, as ld will deduplicate
6058 everything for us. */
6060 static uint32_t
6061 get_type_num (dw_die_ref type, bool in_struct, bool no_fwd_ref)
6063 codeview_type **slot, *t;
6064 uint32_t num;
6065 bool is_fwd_ref;
6067 if (!type)
6068 return 0;
6070 if (!types_htab)
6071 types_htab = new hash_table<die_hasher> (10);
6073 slot = types_htab->find_slot_with_hash (type, htab_hash_pointer (type),
6074 NO_INSERT);
6076 if (slot && *slot && (!no_fwd_ref || !(*slot)->is_fwd_ref))
6077 return (*slot)->num;
6079 is_fwd_ref = false;
6081 switch (dw_get_die_tag (type))
6083 case DW_TAG_base_type:
6084 num = get_type_num_base_type (type);
6085 break;
6087 case DW_TAG_typedef:
6088 /* FIXME - signed longs typedef'd as "HRESULT" should get their
6089 own type (T_HRESULT) */
6090 num = get_type_num (get_AT_ref (type, DW_AT_type), in_struct, false);
6091 break;
6093 case DW_TAG_pointer_type:
6094 num = get_type_num_pointer_type (type, in_struct);
6095 break;
6097 case DW_TAG_reference_type:
6098 num = get_type_num_reference_type (type, in_struct, false);
6099 break;
6101 case DW_TAG_rvalue_reference_type:
6102 num = get_type_num_reference_type (type, in_struct, true);
6103 break;
6105 case DW_TAG_const_type:
6106 num = get_type_num_const_type (type, in_struct);
6107 break;
6109 case DW_TAG_volatile_type:
6110 num = get_type_num_volatile_type (type, in_struct);
6111 break;
6113 case DW_TAG_enumeration_type:
6114 num = get_type_num_enumeration_type (type, in_struct);
6115 break;
6117 case DW_TAG_structure_type:
6118 case DW_TAG_class_type:
6119 case DW_TAG_union_type:
6120 num = get_type_num_struct (type, in_struct, &is_fwd_ref);
6121 break;
6123 case DW_TAG_array_type:
6124 num = get_type_num_array_type (type, in_struct);
6125 break;
6127 case DW_TAG_subroutine_type:
6128 num = get_type_num_subroutine_type (type, in_struct, 0, 0, 0);
6129 break;
6131 default:
6132 num = 0;
6133 break;
6136 /* Check hash table again, and account for the fact that self-referential
6137 structs will have created a forward reference to themselves. */
6139 slot = types_htab->find_slot_with_hash (type, htab_hash_pointer (type),
6140 INSERT);
6142 if (*slot && (*slot)->is_fwd_ref && !is_fwd_ref)
6144 (*slot)->num = num;
6145 (*slot)->is_fwd_ref = false;
6146 return num;
6149 t = (codeview_type *) xmalloc (sizeof (codeview_type));
6150 t->die = type;
6151 t->num = num;
6152 t->is_fwd_ref = is_fwd_ref;
6154 *slot = t;
6156 return t->num;
6159 /* Process a DW_TAG_variable DIE, and add an S_GDATA32 or S_LDATA32 symbol for
6160 this. */
6162 static void
6163 add_variable (dw_die_ref die)
6165 codeview_symbol *s;
6166 const char *name;
6168 name = get_AT_string (die, DW_AT_name);
6169 if (!name)
6170 return;
6172 s = (codeview_symbol *) xmalloc (sizeof (codeview_symbol));
6174 s->next = NULL;
6175 s->kind = get_AT (die, DW_AT_external) ? S_GDATA32 : S_LDATA32;
6176 s->data_symbol.type = get_type_num (get_AT_ref (die, DW_AT_type), false,
6177 false);
6178 s->data_symbol.name = get_name (die);
6179 s->data_symbol.die = die;
6181 if (last_sym)
6182 last_sym->next = s;
6183 else
6184 sym = s;
6186 last_sym = s;
6189 /* Return the type number of the LF_STRING_ID entry corresponding to the given
6190 string, creating a new one if necessary. */
6192 static uint32_t
6193 add_string_id (const char *s)
6195 codeview_custom_type **slot;
6196 codeview_custom_type *ct;
6198 if (!string_id_htab)
6199 string_id_htab = new hash_table<string_id_hasher> (10);
6201 slot = string_id_htab->find_slot_with_hash (s, htab_hash_string (s),
6202 INSERT);
6203 if (*slot)
6204 return (*slot)->num;
6206 ct = (codeview_custom_type *) xmalloc (sizeof (codeview_custom_type));
6208 ct->next = NULL;
6209 ct->kind = LF_STRING_ID;
6210 ct->lf_string_id.substring = 0;
6211 ct->lf_string_id.string = xstrdup (s);
6213 add_custom_type (ct);
6215 *slot = ct;
6217 return ct->num;
6220 /* Return the type number of the LF_STRING_ID corresponding to the given DIE's
6221 parent, or 0 if it is in the global scope. */
6223 static uint32_t
6224 get_scope_string_id (dw_die_ref die)
6226 dw_die_ref decl = get_AT_ref (die, DW_AT_specification);
6227 char *name;
6228 uint32_t ret;
6230 if (decl)
6231 die = decl;
6233 die = dw_get_die_parent (die);
6234 if (!die)
6235 return 0;
6237 if (dw_get_die_tag (die) == DW_TAG_compile_unit)
6238 return 0;
6240 name = get_name (die);
6241 if (!name)
6242 return 0;
6244 ret = add_string_id (name);
6245 free (name);
6247 return ret;
6250 /* Add an LF_FUNC_ID type and return its number (see write_lf_func_id). */
6252 static uint32_t
6253 add_lf_func_id (dw_die_ref die, const char *name)
6255 uint32_t function_type, scope_type;
6256 codeview_custom_type *ct;
6258 function_type = get_type_num_subroutine_type (die, false, 0, 0, 0);
6259 scope_type = get_scope_string_id (die);
6261 ct = (codeview_custom_type *) xmalloc (sizeof (codeview_custom_type));
6263 ct->next = NULL;
6264 ct->kind = LF_FUNC_ID;
6265 ct->lf_func_id.parent_scope = scope_type;
6266 ct->lf_func_id.function_type = function_type;
6267 ct->lf_func_id.name = xstrdup (name);
6269 add_custom_type (ct);
6271 return ct->num;
6274 /* Add an LF_MFUNC_ID type and return its number (see write_lf_mfunc_id). */
6276 static uint32_t
6277 add_lf_mfunc_id (dw_die_ref die, const char *name)
6279 uint32_t function_type = 0, parent_type;
6280 codeview_custom_type *ct;
6281 dw_die_ref spec = get_AT_ref (die, DW_AT_specification);
6283 parent_type = get_type_num (dw_get_die_parent (spec), false, false);
6285 if (types_htab)
6287 codeview_type **slot;
6289 slot = types_htab->find_slot_with_hash (spec, htab_hash_pointer (spec),
6290 NO_INSERT);
6292 if (slot && *slot)
6293 function_type = (*slot)->num;
6296 if (function_type == 0)
6298 function_type = get_type_num_subroutine_type (die, false, parent_type,
6299 0, 0);
6302 ct = (codeview_custom_type *) xmalloc (sizeof (codeview_custom_type));
6304 ct->next = NULL;
6305 ct->kind = LF_MFUNC_ID;
6306 ct->lf_mfunc_id.parent_type = parent_type;
6307 ct->lf_mfunc_id.function_type = function_type;
6308 ct->lf_mfunc_id.name = xstrdup (name);
6310 add_custom_type (ct);
6312 return ct->num;
6315 /* Process a DW_TAG_subprogram DIE, and add an S_GPROC32_ID or S_LPROC32_ID
6316 symbol for this. */
6318 static void
6319 add_function (dw_die_ref die)
6321 const char *name = get_AT_string (die, DW_AT_name);
6322 uint32_t func_id_type;
6323 codeview_symbol *s;
6324 dw_die_ref spec = get_AT_ref (die, DW_AT_specification);
6325 bool do_mfunc_id = false;
6327 if (!name)
6328 return;
6330 if (spec && dw_get_die_parent (spec))
6332 switch (dw_get_die_tag (dw_get_die_parent (spec)))
6334 case DW_TAG_class_type:
6335 case DW_TAG_structure_type:
6336 case DW_TAG_union_type:
6337 do_mfunc_id = true;
6338 break;
6340 default:
6341 break;
6345 if (do_mfunc_id)
6346 func_id_type = add_lf_mfunc_id (die, name);
6347 else
6348 func_id_type = add_lf_func_id (die, name);
6350 /* Add an S_GPROC32_ID / S_LPROC32_ID symbol. */
6352 s = (codeview_symbol *) xmalloc (sizeof (codeview_symbol));
6354 s->next = NULL;
6355 s->kind = get_AT (die, DW_AT_external) ? S_GPROC32_ID : S_LPROC32_ID;
6356 s->function.parent = 0;
6357 s->function.end = 0;
6358 s->function.next = 0;
6359 s->function.type = func_id_type;
6360 s->function.flags = 0;
6361 s->function.name = get_name (die);
6362 s->function.die = die;
6364 if (last_sym)
6365 last_sym->next = s;
6366 else
6367 sym = s;
6369 last_sym = s;
6372 /* Loop through the DIEs that have been output for our TU, and add CodeView
6373 symbols for them. */
6375 void
6376 codeview_debug_early_finish (dw_die_ref die)
6378 dw_die_ref first_child, c;
6380 first_child = dw_get_die_child (die);
6382 if (!first_child)
6383 return;
6385 c = first_child;
6389 switch (dw_get_die_tag (c))
6391 case DW_TAG_variable:
6392 add_variable (c);
6393 break;
6394 case DW_TAG_subprogram:
6395 add_function (c);
6396 break;
6397 default:
6398 break;
6401 c = dw_get_die_sib (c);
6403 while (c != first_child);
6405 flush_deferred_types ();
6408 #endif