1 /* Dwarf2 assembler output helper routines. 2 Copyright (C) 2001-2016 Free Software Foundation, Inc. 3 4 This file is part of GCC. 5 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. 10 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. 15 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/>. */ 19 20 21 #include "config.h" 22 #include "system.h" 23 #include "coretypes.h" 24 #include "target.h" 25 #include "rtl.h" 26 #include "tree.h" 27 #include "tm_p.h" 28 #include "stringpool.h" 29 #include "varasm.h" 30 #include "output.h" 31 #include "dwarf2asm.h" 32 #include "dwarf2.h" 33 34 #ifndef XCOFF_DEBUGGING_INFO 35 #define XCOFF_DEBUGGING_INFO 0 36 #endif 37 38 39 /* Output an unaligned integer with the given value and size. Prefer not 40 to print a newline, since the caller may want to add a comment. */ 41 42 void 43 dw2_assemble_integer (int size, rtx x) 44 { 45 const char *op = integer_asm_op (size, FALSE); 46 47 if (op) 48 { 49 fputs (op, asm_out_file); 50 if (CONST_INT_P (x)) 51 fprint_whex (asm_out_file, (unsigned HOST_WIDE_INT) INTVAL (x)); 52 else 53 output_addr_const (asm_out_file, x); 54 } 55 else 56 assemble_integer (x, size, BITS_PER_UNIT, 1); 57 } 58 59 60 /* Output a value of a given size in target byte order. */ 61 62 void 63 dw2_asm_output_data_raw (int size, unsigned HOST_WIDE_INT value) 64 { 65 unsigned char bytes[8]; 66 int i; 67 68 for (i = 0; i < 8; ++i) 69 { 70 bytes[i] = value & 0xff; 71 value >>= 8; 72 } 73 74 if (BYTES_BIG_ENDIAN) 75 { 76 for (i = size - 1; i > 0; --i) 77 fprintf (asm_out_file, "%#x,", bytes[i]); 78 fprintf (asm_out_file, "%#x", bytes[0]); 79 } 80 else 81 { 82 for (i = 0; i < size - 1; ++i) 83 fprintf (asm_out_file, "%#x,", bytes[i]); 84 fprintf (asm_out_file, "%#x", bytes[i]); 85 } 86 } 87 88 /* Output an immediate constant in a given SIZE in bytes. */ 89 90 void 91 dw2_asm_output_data (int size, unsigned HOST_WIDE_INT value, 92 const char *comment, ...) 93 { 94 va_list ap; 95 const char *op = integer_asm_op (size, FALSE); 96 97 va_start (ap, comment); 98 99 if (size * 8 < HOST_BITS_PER_WIDE_INT) 100 value &= ~(~(unsigned HOST_WIDE_INT) 0 << (size * 8)); 101 102 if (op) 103 { 104 fputs (op, asm_out_file); 105 fprint_whex (asm_out_file, value); 106 } 107 else 108 assemble_integer (GEN_INT (value), size, BITS_PER_UNIT, 1); 109 110 if (flag_debug_asm && comment) 111 { 112 fputs ("\t" ASM_COMMENT_START " ", asm_out_file); 113 vfprintf (asm_out_file, comment, ap); 114 } 115 putc ('\n', asm_out_file); 116 117 va_end (ap); 118 } 119 120 /* Output the difference between two symbols in a given size. */ 121 /* ??? There appear to be assemblers that do not like such 122 subtraction, but do support ASM_SET_OP. It's unfortunately 123 impossible to do here, since the ASM_SET_OP for the difference 124 symbol must appear after both symbols are defined. */ 125 126 void 127 dw2_asm_output_delta (int size, const char *lab1, const char *lab2, 128 const char *comment, ...) 129 { 130 va_list ap; 131 132 va_start (ap, comment); 133 134 #ifdef ASM_OUTPUT_DWARF_DELTA 135 ASM_OUTPUT_DWARF_DELTA (asm_out_file, size, lab1, lab2); 136 #else 137 dw2_assemble_integer (size, 138 gen_rtx_MINUS (Pmode, 139 gen_rtx_SYMBOL_REF (Pmode, lab1), 140 gen_rtx_SYMBOL_REF (Pmode, lab2))); 141 #endif 142 if (flag_debug_asm && comment) 143 { 144 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START); 145 vfprintf (asm_out_file, comment, ap); 146 } 147 fputc ('\n', asm_out_file); 148 149 va_end (ap); 150 } 151 152 #ifdef ASM_OUTPUT_DWARF_VMS_DELTA 153 /* Output the difference between two symbols in instruction units 154 in a given size. */ 155 156 void 157 dw2_asm_output_vms_delta (int size ATTRIBUTE_UNUSED, 158 const char *lab1, const char *lab2, 159 const char *comment, ...) 160 { 161 va_list ap; 162 163 va_start (ap, comment); 164 165 ASM_OUTPUT_DWARF_VMS_DELTA (asm_out_file, size, lab1, lab2); 166 if (flag_debug_asm && comment) 167 { 168 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START); 169 vfprintf (asm_out_file, comment, ap); 170 } 171 fputc ('\n', asm_out_file); 172 173 va_end (ap); 174 } 175 #endif 176 177 /* Output a section-relative reference to a LABEL, which was placed in 178 BASE. In general this can only be done for debugging symbols. 179 E.g. on most targets with the GNU linker, this is accomplished with 180 a direct reference and the knowledge that the debugging section 181 will be placed at VMA 0. Some targets have special relocations for 182 this that we must use. */ 183 184 void 185 dw2_asm_output_offset (int size, const char *label, 186 section *base ATTRIBUTE_UNUSED, 187 const char *comment, ...) 188 { 189 va_list ap; 190 191 va_start (ap, comment); 192 193 #ifdef ASM_OUTPUT_DWARF_OFFSET 194 ASM_OUTPUT_DWARF_OFFSET (asm_out_file, size, label, base); 195 #else 196 dw2_assemble_integer (size, gen_rtx_SYMBOL_REF (Pmode, label)); 197 #endif 198 199 if (flag_debug_asm && comment) 200 { 201 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START); 202 vfprintf (asm_out_file, comment, ap); 203 } 204 fputc ('\n', asm_out_file); 205 206 va_end (ap); 207 } 208 209 #if 0 210 211 /* Output a self-relative reference to a label, possibly in a 212 different section or object file. */ 213 214 void 215 dw2_asm_output_pcrel (int size ATTRIBUTE_UNUSED, 216 const char *label ATTRIBUTE_UNUSED, 217 const char *comment, ...) 218 { 219 va_list ap; 220 221 va_start (ap, comment); 222 223 #ifdef ASM_OUTPUT_DWARF_PCREL 224 ASM_OUTPUT_DWARF_PCREL (asm_out_file, size, label); 225 #else 226 dw2_assemble_integer (size, 227 gen_rtx_MINUS (Pmode, 228 gen_rtx_SYMBOL_REF (Pmode, label), 229 pc_rtx)); 230 #endif 231 232 if (flag_debug_asm && comment) 233 { 234 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START); 235 vfprintf (asm_out_file, comment, ap); 236 } 237 fputc ('\n', asm_out_file); 238 239 va_end (ap); 240 } 241 #endif /* 0 */ 242 243 /* Output an absolute reference to a label. */ 244 245 void 246 dw2_asm_output_addr (int size, const char *label, 247 const char *comment, ...) 248 { 249 va_list ap; 250 251 va_start (ap, comment); 252 253 dw2_assemble_integer (size, gen_rtx_SYMBOL_REF (Pmode, label)); 254 255 if (flag_debug_asm && comment) 256 { 257 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START); 258 vfprintf (asm_out_file, comment, ap); 259 } 260 fputc ('\n', asm_out_file); 261 262 va_end (ap); 263 } 264 265 /* Similar, but use an RTX expression instead of a text label. */ 266 267 void 268 dw2_asm_output_addr_rtx (int size, rtx addr, 269 const char *comment, ...) 270 { 271 va_list ap; 272 273 va_start (ap, comment); 274 275 dw2_assemble_integer (size, addr); 276 277 if (flag_debug_asm && comment) 278 { 279 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START); 280 vfprintf (asm_out_file, comment, ap); 281 } 282 fputc ('\n', asm_out_file); 283 284 va_end (ap); 285 } 286 287 /* Output the first ORIG_LEN characters of STR as a string. 288 If ORIG_LEN is equal to -1, ignore this parameter and output 289 the entire STR instead. 290 If COMMENT is not NULL and comments in the debug information 291 have been requested by the user, append the given COMMENT 292 to the generated output. */ 293 294 void 295 dw2_asm_output_nstring (const char *str, size_t orig_len, 296 const char *comment, ...) 297 { 298 size_t i, len; 299 va_list ap; 300 301 va_start (ap, comment); 302 303 len = orig_len; 304 305 if (len == (size_t) -1) 306 len = strlen (str); 307 308 if (flag_debug_asm && comment) 309 { 310 if (XCOFF_DEBUGGING_INFO) 311 fputs ("\t.byte \"", asm_out_file); 312 else 313 fputs ("\t.ascii \"", asm_out_file); 314 315 for (i = 0; i < len; i++) 316 { 317 int c = str[i]; 318 if (c == '\"' || c == '\\') 319 fputc ('\\', asm_out_file); 320 if (ISPRINT (c)) 321 fputc (c, asm_out_file); 322 else 323 fprintf (asm_out_file, "\\%o", c); 324 } 325 fprintf (asm_out_file, "\\0\"\t%s ", ASM_COMMENT_START); 326 vfprintf (asm_out_file, comment, ap); 327 fputc ('\n', asm_out_file); 328 } 329 else 330 { 331 /* If an explicit length was given, we can't assume there 332 is a null termination in the string buffer. */ 333 if (orig_len == (size_t) -1) 334 len += 1; 335 ASM_OUTPUT_ASCII (asm_out_file, str, len); 336 if (orig_len != (size_t) -1) 337 assemble_integer (const0_rtx, 1, BITS_PER_UNIT, 1); 338 } 339 340 va_end (ap); 341 } 342 343 344 /* Return the size of an unsigned LEB128 quantity. */ 345 346 int 347 size_of_uleb128 (unsigned HOST_WIDE_INT value) 348 { 349 int size = 0; 350 351 do 352 { 353 value >>= 7; 354 size += 1; 355 } 356 while (value != 0); 357 358 return size; 359 } 360 361 /* Return the size of a signed LEB128 quantity. */ 362 363 int 364 size_of_sleb128 (HOST_WIDE_INT value) 365 { 366 int size = 0, byte; 367 368 do 369 { 370 byte = (value & 0x7f); 371 value >>= 7; 372 size += 1; 373 } 374 while (!((value == 0 && (byte & 0x40) == 0) 375 || (value == -1 && (byte & 0x40) != 0))); 376 377 return size; 378 } 379 380 /* Given an encoding, return the number of bytes the format occupies. 381 This is only defined for fixed-size encodings, and so does not 382 include leb128. */ 383 384 int 385 size_of_encoded_value (int encoding) 386 { 387 if (encoding == DW_EH_PE_omit) 388 return 0; 389 390 switch (encoding & 0x07) 391 { 392 case DW_EH_PE_absptr: 393 return POINTER_SIZE_UNITS; 394 case DW_EH_PE_udata2: 395 return 2; 396 case DW_EH_PE_udata4: 397 return 4; 398 case DW_EH_PE_udata8: 399 return 8; 400 default: 401 gcc_unreachable (); 402 } 403 } 404 405 /* Yield a name for a given pointer encoding. */ 406 407 const char * 408 eh_data_format_name (int format) 409 { 410 #if HAVE_DESIGNATED_INITIALIZERS 411 #define S(p, v) [p] = v, 412 #else 413 #define S(p, v) case p: return v; 414 #endif 415 416 #if HAVE_DESIGNATED_INITIALIZERS 417 __extension__ static const char * const format_names[256] = { 418 #else 419 switch (format) { 420 #endif 421 422 S(DW_EH_PE_absptr, "absolute") 423 S(DW_EH_PE_omit, "omit") 424 S(DW_EH_PE_aligned, "aligned absolute") 425 426 S(DW_EH_PE_uleb128, "uleb128") 427 S(DW_EH_PE_udata2, "udata2") 428 S(DW_EH_PE_udata4, "udata4") 429 S(DW_EH_PE_udata8, "udata8") 430 S(DW_EH_PE_sleb128, "sleb128") 431 S(DW_EH_PE_sdata2, "sdata2") 432 S(DW_EH_PE_sdata4, "sdata4") 433 S(DW_EH_PE_sdata8, "sdata8") 434 435 S(DW_EH_PE_absptr | DW_EH_PE_pcrel, "pcrel") 436 S(DW_EH_PE_uleb128 | DW_EH_PE_pcrel, "pcrel uleb128") 437 S(DW_EH_PE_udata2 | DW_EH_PE_pcrel, "pcrel udata2") 438 S(DW_EH_PE_udata4 | DW_EH_PE_pcrel, "pcrel udata4") 439 S(DW_EH_PE_udata8 | DW_EH_PE_pcrel, "pcrel udata8") 440 S(DW_EH_PE_sleb128 | DW_EH_PE_pcrel, "pcrel sleb128") 441 S(DW_EH_PE_sdata2 | DW_EH_PE_pcrel, "pcrel sdata2") 442 S(DW_EH_PE_sdata4 | DW_EH_PE_pcrel, "pcrel sdata4") 443 S(DW_EH_PE_sdata8 | DW_EH_PE_pcrel, "pcrel sdata8") 444 445 S(DW_EH_PE_absptr | DW_EH_PE_textrel, "textrel") 446 S(DW_EH_PE_uleb128 | DW_EH_PE_textrel, "textrel uleb128") 447 S(DW_EH_PE_udata2 | DW_EH_PE_textrel, "textrel udata2") 448 S(DW_EH_PE_udata4 | DW_EH_PE_textrel, "textrel udata4") 449 S(DW_EH_PE_udata8 | DW_EH_PE_textrel, "textrel udata8") 450 S(DW_EH_PE_sleb128 | DW_EH_PE_textrel, "textrel sleb128") 451 S(DW_EH_PE_sdata2 | DW_EH_PE_textrel, "textrel sdata2") 452 S(DW_EH_PE_sdata4 | DW_EH_PE_textrel, "textrel sdata4") 453 S(DW_EH_PE_sdata8 | DW_EH_PE_textrel, "textrel sdata8") 454 455 S(DW_EH_PE_absptr | DW_EH_PE_datarel, "datarel") 456 S(DW_EH_PE_uleb128 | DW_EH_PE_datarel, "datarel uleb128") 457 S(DW_EH_PE_udata2 | DW_EH_PE_datarel, "datarel udata2") 458 S(DW_EH_PE_udata4 | DW_EH_PE_datarel, "datarel udata4") 459 S(DW_EH_PE_udata8 | DW_EH_PE_datarel, "datarel udata8") 460 S(DW_EH_PE_sleb128 | DW_EH_PE_datarel, "datarel sleb128") 461 S(DW_EH_PE_sdata2 | DW_EH_PE_datarel, "datarel sdata2") 462 S(DW_EH_PE_sdata4 | DW_EH_PE_datarel, "datarel sdata4") 463 S(DW_EH_PE_sdata8 | DW_EH_PE_datarel, "datarel sdata8") 464 465 S(DW_EH_PE_absptr | DW_EH_PE_funcrel, "funcrel") 466 S(DW_EH_PE_uleb128 | DW_EH_PE_funcrel, "funcrel uleb128") 467 S(DW_EH_PE_udata2 | DW_EH_PE_funcrel, "funcrel udata2") 468 S(DW_EH_PE_udata4 | DW_EH_PE_funcrel, "funcrel udata4") 469 S(DW_EH_PE_udata8 | DW_EH_PE_funcrel, "funcrel udata8") 470 S(DW_EH_PE_sleb128 | DW_EH_PE_funcrel, "funcrel sleb128") 471 S(DW_EH_PE_sdata2 | DW_EH_PE_funcrel, "funcrel sdata2") 472 S(DW_EH_PE_sdata4 | DW_EH_PE_funcrel, "funcrel sdata4") 473 S(DW_EH_PE_sdata8 | DW_EH_PE_funcrel, "funcrel sdata8") 474 475 S(DW_EH_PE_indirect | DW_EH_PE_absptr, "indirect absolute") 476 477 S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_pcrel, 478 "indirect pcrel") 479 S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_pcrel, 480 "indirect pcrel uleb128") 481 S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_pcrel, 482 "indirect pcrel udata2") 483 S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_pcrel, 484 "indirect pcrel udata4") 485 S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_pcrel, 486 "indirect pcrel udata8") 487 S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_pcrel, 488 "indirect pcrel sleb128") 489 S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_pcrel, 490 "indirect pcrel sdata2") 491 S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_pcrel, 492 "indirect pcrel sdata4") 493 S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_pcrel, 494 "indirect pcrel sdata8") 495 496 S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_textrel, 497 "indirect textrel") 498 S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_textrel, 499 "indirect textrel uleb128") 500 S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_textrel, 501 "indirect textrel udata2") 502 S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_textrel, 503 "indirect textrel udata4") 504 S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_textrel, 505 "indirect textrel udata8") 506 S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_textrel, 507 "indirect textrel sleb128") 508 S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_textrel, 509 "indirect textrel sdata2") 510 S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_textrel, 511 "indirect textrel sdata4") 512 S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_textrel, 513 "indirect textrel sdata8") 514 515 S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_datarel, 516 "indirect datarel") 517 S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_datarel, 518 "indirect datarel uleb128") 519 S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_datarel, 520 "indirect datarel udata2") 521 S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_datarel, 522 "indirect datarel udata4") 523 S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_datarel, 524 "indirect datarel udata8") 525 S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_datarel, 526 "indirect datarel sleb128") 527 S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_datarel, 528 "indirect datarel sdata2") 529 S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_datarel, 530 "indirect datarel sdata4") 531 S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_datarel, 532 "indirect datarel sdata8") 533 534 S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_funcrel, 535 "indirect funcrel") 536 S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_funcrel, 537 "indirect funcrel uleb128") 538 S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_funcrel, 539 "indirect funcrel udata2") 540 S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_funcrel, 541 "indirect funcrel udata4") 542 S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_funcrel, 543 "indirect funcrel udata8") 544 S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_funcrel, 545 "indirect funcrel sleb128") 546 S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_funcrel, 547 "indirect funcrel sdata2") 548 S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_funcrel, 549 "indirect funcrel sdata4") 550 S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_funcrel, 551 "indirect funcrel sdata8") 552 553 #if HAVE_DESIGNATED_INITIALIZERS 554 }; 555 556 gcc_assert (format >= 0 && format < 0x100 && format_names[format]); 557 558 return format_names[format]; 559 #else 560 } 561 gcc_unreachable (); 562 #endif 563 } 564 565 /* Output an unsigned LEB128 quantity, but only the byte values. */ 566 567 void 568 dw2_asm_output_data_uleb128_raw (unsigned HOST_WIDE_INT value) 569 { 570 while (1) 571 { 572 int byte = (value & 0x7f); 573 value >>= 7; 574 if (value != 0) 575 /* More bytes to follow. */ 576 byte |= 0x80; 577 578 fprintf (asm_out_file, "%#x", byte); 579 if (value == 0) 580 break; 581 fputc (',', asm_out_file); 582 } 583 } 584 585 /* Output an unsigned LEB128 quantity. */ 586 587 void 588 dw2_asm_output_data_uleb128 (unsigned HOST_WIDE_INT value, 589 const char *comment, ...) 590 { 591 va_list ap; 592 593 va_start (ap, comment); 594 595 #ifdef HAVE_AS_LEB128 596 fputs ("\t.uleb128 ", asm_out_file); 597 fprint_whex (asm_out_file, value); 598 599 if (flag_debug_asm && comment) 600 { 601 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START); 602 vfprintf (asm_out_file, comment, ap); 603 } 604 #else 605 { 606 unsigned HOST_WIDE_INT work = value; 607 const char *byte_op = targetm.asm_out.byte_op; 608 609 if (byte_op) 610 fputs (byte_op, asm_out_file); 611 do 612 { 613 int byte = (work & 0x7f); 614 work >>= 7; 615 if (work != 0) 616 /* More bytes to follow. */ 617 byte |= 0x80; 618 619 if (byte_op) 620 { 621 fprintf (asm_out_file, "%#x", byte); 622 if (work != 0) 623 fputc (',', asm_out_file); 624 } 625 else 626 assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1); 627 } 628 while (work != 0); 629 630 if (flag_debug_asm) 631 { 632 fprintf (asm_out_file, "\t%s uleb128 " HOST_WIDE_INT_PRINT_HEX, 633 ASM_COMMENT_START, value); 634 if (comment) 635 { 636 fputs ("; ", asm_out_file); 637 vfprintf (asm_out_file, comment, ap); 638 } 639 } 640 } 641 #endif 642 putc ('\n', asm_out_file); 643 644 va_end (ap); 645 } 646 647 /* Output an signed LEB128 quantity, but only the byte values. */ 648 649 void 650 dw2_asm_output_data_sleb128_raw (HOST_WIDE_INT value) 651 { 652 int byte, more; 653 654 while (1) 655 { 656 byte = (value & 0x7f); 657 value >>= 7; 658 more = !((value == 0 && (byte & 0x40) == 0) 659 || (value == -1 && (byte & 0x40) != 0)); 660 if (more) 661 byte |= 0x80; 662 663 fprintf (asm_out_file, "%#x", byte); 664 if (!more) 665 break; 666 fputc (',', asm_out_file); 667 } 668 } 669 670 /* Output a signed LEB128 quantity. */ 671 672 void 673 dw2_asm_output_data_sleb128 (HOST_WIDE_INT value, 674 const char *comment, ...) 675 { 676 va_list ap; 677 678 va_start (ap, comment); 679 680 #ifdef HAVE_AS_LEB128 681 fprintf (asm_out_file, "\t.sleb128 " HOST_WIDE_INT_PRINT_DEC, value); 682 683 if (flag_debug_asm && comment) 684 { 685 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START); 686 vfprintf (asm_out_file, comment, ap); 687 } 688 #else 689 { 690 HOST_WIDE_INT work = value; 691 int more, byte; 692 const char *byte_op = targetm.asm_out.byte_op; 693 694 if (byte_op) 695 fputs (byte_op, asm_out_file); 696 do 697 { 698 byte = (work & 0x7f); 699 /* arithmetic shift */ 700 work >>= 7; 701 more = !((work == 0 && (byte & 0x40) == 0) 702 || (work == -1 && (byte & 0x40) != 0)); 703 if (more) 704 byte |= 0x80; 705 706 if (byte_op) 707 { 708 fprintf (asm_out_file, "%#x", byte); 709 if (more) 710 fputc (',', asm_out_file); 711 } 712 else 713 assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1); 714 } 715 while (more); 716 717 if (flag_debug_asm) 718 { 719 fprintf (asm_out_file, "\t%s sleb128 " HOST_WIDE_INT_PRINT_DEC, 720 ASM_COMMENT_START, value); 721 if (comment) 722 { 723 fputs ("; ", asm_out_file); 724 vfprintf (asm_out_file, comment, ap); 725 } 726 } 727 } 728 #endif 729 fputc ('\n', asm_out_file); 730 731 va_end (ap); 732 } 733 734 void 735 dw2_asm_output_delta_uleb128 (const char *lab1 ATTRIBUTE_UNUSED, 736 const char *lab2 ATTRIBUTE_UNUSED, 737 const char *comment, ...) 738 { 739 va_list ap; 740 741 va_start (ap, comment); 742 743 #ifdef HAVE_AS_LEB128 744 fputs ("\t.uleb128 ", asm_out_file); 745 assemble_name (asm_out_file, lab1); 746 putc ('-', asm_out_file); 747 assemble_name (asm_out_file, lab2); 748 #else 749 gcc_unreachable (); 750 #endif 751 752 if (flag_debug_asm && comment) 753 { 754 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START); 755 vfprintf (asm_out_file, comment, ap); 756 } 757 fputc ('\n', asm_out_file); 758 759 va_end (ap); 760 } 761 762 #if 0 763 764 void 765 dw2_asm_output_delta_sleb128 (const char *lab1 ATTRIBUTE_UNUSED, 766 const char *lab2 ATTRIBUTE_UNUSED, 767 const char *comment, ...) 768 { 769 va_list ap; 770 771 va_start (ap, comment); 772 773 #ifdef HAVE_AS_LEB128 774 fputs ("\t.sleb128 ", asm_out_file); 775 assemble_name (asm_out_file, lab1); 776 putc ('-', asm_out_file); 777 assemble_name (asm_out_file, lab2); 778 #else 779 gcc_unreachable (); 780 #endif 781 782 if (flag_debug_asm && comment) 783 { 784 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START); 785 vfprintf (asm_out_file, comment, ap); 786 } 787 fputc ('\n', asm_out_file); 788 789 va_end (ap); 790 } 791 #endif /* 0 */ 792 793 static GTY(()) hash_map<const char *, tree> *indirect_pool; 794 795 static GTY(()) int dw2_const_labelno; 796 797 #if defined(HAVE_GAS_HIDDEN) 798 # define USE_LINKONCE_INDIRECT (SUPPORTS_ONE_ONLY) 799 #else 800 # define USE_LINKONCE_INDIRECT 0 801 #endif 802 803 /* Compare two std::pair<const char *, tree> by their first element. 804 Returns <0, 0, or 805 >0 to indicate whether K1 is less than, equal to, or greater than 806 K2, respectively. */ 807 808 static int 809 compare_strings (const void *a, const void *b) 810 { 811 const char *s1 = ((const std::pair<const char *, tree> *) a)->first; 812 const char *s2 = ((const std::pair<const char *, tree> *) b)->first; 813 int ret; 814 815 if (s1 == s2) 816 return 0; 817 818 ret = strcmp (s1, s2); 819 820 /* The strings are always those from IDENTIFIER_NODEs, and, 821 therefore, we should never have two copies of the same 822 string. */ 823 gcc_assert (ret); 824 825 return ret; 826 } 827 828 /* Put X, a SYMBOL_REF, in memory. Return a SYMBOL_REF to the allocated 829 memory. Differs from force_const_mem in that a single pool is used for 830 the entire unit of translation, and the memory is not guaranteed to be 831 "near" the function in any interesting sense. IS_PUBLIC controls whether 832 the symbol can be shared across the entire application (or DSO). */ 833 834 rtx 835 dw2_force_const_mem (rtx x, bool is_public) 836 { 837 const char *key; 838 tree decl_id; 839 840 if (! indirect_pool) 841 indirect_pool = hash_map<const char *, tree>::create_ggc (64); 842 843 gcc_assert (GET_CODE (x) == SYMBOL_REF); 844 845 key = XSTR (x, 0); 846 tree *slot = indirect_pool->get (key); 847 if (slot) 848 decl_id = *slot; 849 else 850 { 851 tree id; 852 const char *str = targetm.strip_name_encoding (key); 853 854 if (is_public && USE_LINKONCE_INDIRECT) 855 { 856 char *ref_name = XALLOCAVEC (char, strlen (str) + sizeof "DW.ref."); 857 858 sprintf (ref_name, "DW.ref.%s", str); 859 gcc_assert (!maybe_get_identifier (ref_name)); 860 decl_id = get_identifier (ref_name); 861 TREE_PUBLIC (decl_id) = 1; 862 } 863 else 864 { 865 char label[32]; 866 867 ASM_GENERATE_INTERNAL_LABEL (label, "LDFCM", dw2_const_labelno); 868 ++dw2_const_labelno; 869 gcc_assert (!maybe_get_identifier (label)); 870 decl_id = get_identifier (label); 871 } 872 873 id = maybe_get_identifier (str); 874 if (id) 875 TREE_SYMBOL_REFERENCED (id) = 1; 876 877 indirect_pool->put (key, decl_id); 878 } 879 880 return gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (decl_id)); 881 } 882 883 /* A helper function for dw2_output_indirect_constants. Emit one queued 884 constant to memory. */ 885 886 static int 887 dw2_output_indirect_constant_1 (const char *sym, tree id) 888 { 889 rtx sym_ref; 890 tree decl; 891 892 decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, id, ptr_type_node); 893 SET_DECL_ASSEMBLER_NAME (decl, id); 894 DECL_ARTIFICIAL (decl) = 1; 895 DECL_IGNORED_P (decl) = 1; 896 DECL_INITIAL (decl) = decl; 897 TREE_READONLY (decl) = 1; 898 TREE_STATIC (decl) = 1; 899 900 if (TREE_PUBLIC (id)) 901 { 902 TREE_PUBLIC (decl) = 1; 903 make_decl_one_only (decl, DECL_ASSEMBLER_NAME (decl)); 904 if (USE_LINKONCE_INDIRECT) 905 DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN; 906 } 907 908 sym_ref = gen_rtx_SYMBOL_REF (Pmode, sym); 909 assemble_variable (decl, 1, 1, 1); 910 assemble_integer (sym_ref, POINTER_SIZE_UNITS, POINTER_SIZE, 1); 911 912 return 0; 913 } 914 915 /* Emit the constants queued through dw2_force_const_mem. */ 916 917 void 918 dw2_output_indirect_constants (void) 919 { 920 if (!indirect_pool) 921 return; 922 923 auto_vec<std::pair<const char *, tree> > temp (indirect_pool->elements ()); 924 for (hash_map<const char *, tree>::iterator iter = indirect_pool->begin (); 925 iter != indirect_pool->end (); ++iter) 926 temp.quick_push (*iter); 927 928 temp.qsort (compare_strings); 929 930 for (unsigned int i = 0; i < temp.length (); i++) 931 dw2_output_indirect_constant_1 (temp[i].first, temp[i].second); 932 } 933 934 /* Like dw2_asm_output_addr_rtx, but encode the pointer as directed. 935 If PUBLIC is set and the encoding is DW_EH_PE_indirect, the indirect 936 reference is shared across the entire application (or DSO). */ 937 938 void 939 dw2_asm_output_encoded_addr_rtx (int encoding, rtx addr, bool is_public, 940 const char *comment, ...) 941 { 942 int size; 943 va_list ap; 944 945 va_start (ap, comment); 946 947 size = size_of_encoded_value (encoding); 948 949 if (encoding == DW_EH_PE_aligned) 950 { 951 assemble_align (POINTER_SIZE); 952 assemble_integer (addr, size, POINTER_SIZE, 1); 953 va_end (ap); 954 return; 955 } 956 957 /* NULL is _always_ represented as a plain zero, as is 1 for Ada's 958 "all others". */ 959 if (addr == const0_rtx || addr == const1_rtx) 960 assemble_integer (addr, size, BITS_PER_UNIT, 1); 961 else 962 { 963 restart: 964 /* Allow the target first crack at emitting this. Some of the 965 special relocations require special directives instead of 966 just ".4byte" or whatever. */ 967 #ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX 968 ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX (asm_out_file, encoding, size, 969 addr, done); 970 #endif 971 972 /* Indirection is used to get dynamic relocations out of a 973 read-only section. */ 974 if (encoding & DW_EH_PE_indirect) 975 { 976 /* It is very tempting to use force_const_mem so that we share data 977 with the normal constant pool. However, we've already emitted 978 the constant pool for this function. Moreover, we'd like to 979 share these constants across the entire unit of translation and 980 even, if possible, across the entire application (or DSO). */ 981 addr = dw2_force_const_mem (addr, is_public); 982 encoding &= ~DW_EH_PE_indirect; 983 goto restart; 984 } 985 986 switch (encoding & 0xF0) 987 { 988 case DW_EH_PE_absptr: 989 dw2_assemble_integer (size, addr); 990 break; 991 992 #ifdef ASM_OUTPUT_DWARF_DATAREL 993 case DW_EH_PE_datarel: 994 gcc_assert (GET_CODE (addr) == SYMBOL_REF); 995 ASM_OUTPUT_DWARF_DATAREL (asm_out_file, size, XSTR (addr, 0)); 996 break; 997 #endif 998 999 case DW_EH_PE_pcrel: 1000 gcc_assert (GET_CODE (addr) == SYMBOL_REF); 1001 #ifdef ASM_OUTPUT_DWARF_PCREL 1002 ASM_OUTPUT_DWARF_PCREL (asm_out_file, size, XSTR (addr, 0)); 1003 #else 1004 dw2_assemble_integer (size, gen_rtx_MINUS (Pmode, addr, pc_rtx)); 1005 #endif 1006 break; 1007 1008 default: 1009 /* Other encodings should have been handled by 1010 ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX. */ 1011 gcc_unreachable (); 1012 } 1013 1014 #ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX 1015 done:; 1016 #endif 1017 } 1018 1019 if (flag_debug_asm && comment) 1020 { 1021 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START); 1022 vfprintf (asm_out_file, comment, ap); 1023 } 1024 fputc ('\n', asm_out_file); 1025 1026 va_end (ap); 1027 } 1028 1029 #include "gt-dwarf2asm.h" 1030