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