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