190075Sobrien/* Dwarf2 assembler output helper routines. 2169689Skan Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. 390075Sobrien 490075SobrienThis file is part of GCC. 590075Sobrien 690075SobrienGCC is free software; you can redistribute it and/or modify it under 790075Sobrienthe terms of the GNU General Public License as published by the Free 890075SobrienSoftware Foundation; either version 2, or (at your option) any later 990075Sobrienversion. 1090075Sobrien 1190075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY 1290075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or 1390075SobrienFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1490075Sobrienfor more details. 1590075Sobrien 1690075SobrienYou should have received a copy of the GNU General Public License 1790075Sobrienalong with GCC; see the file COPYING. If not, write to the Free 18169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 19169689Skan02110-1301, USA. */ 2090075Sobrien 2190075Sobrien 2290075Sobrien#include "config.h" 2390075Sobrien#include "system.h" 24132718Skan#include "coretypes.h" 25132718Skan#include "tm.h" 2690075Sobrien#include "flags.h" 2790075Sobrien#include "tree.h" 2890075Sobrien#include "rtl.h" 2990075Sobrien#include "output.h" 3090075Sobrien#include "target.h" 3190075Sobrien#include "dwarf2asm.h" 3290075Sobrien#include "dwarf2.h" 3390075Sobrien#include "splay-tree.h" 3490075Sobrien#include "ggc.h" 3590075Sobrien#include "tm_p.h" 3690075Sobrien 3790075Sobrien 3890075Sobrien/* How to start an assembler comment. */ 3990075Sobrien#ifndef ASM_COMMENT_START 4090075Sobrien#define ASM_COMMENT_START ";#" 4190075Sobrien#endif 4290075Sobrien 4390075Sobrien 4490075Sobrien/* Output an unaligned integer with the given value and size. Prefer not 4590075Sobrien to print a newline, since the caller may want to add a comment. */ 4690075Sobrien 4790075Sobrienvoid 48132718Skandw2_assemble_integer (int size, rtx x) 4990075Sobrien{ 5090075Sobrien const char *op = integer_asm_op (size, FALSE); 5190075Sobrien 5290075Sobrien if (op) 5390075Sobrien { 5490075Sobrien fputs (op, asm_out_file); 5590075Sobrien if (GET_CODE (x) == CONST_INT) 5690075Sobrien fprintf (asm_out_file, HOST_WIDE_INT_PRINT_HEX, INTVAL (x)); 5790075Sobrien else 5890075Sobrien output_addr_const (asm_out_file, x); 5990075Sobrien } 6090075Sobrien else 6190075Sobrien assemble_integer (x, size, BITS_PER_UNIT, 1); 6290075Sobrien} 6390075Sobrien 64117395Skan 6590075Sobrien/* Output an immediate constant in a given size. */ 6690075Sobrien 6790075Sobrienvoid 68132718Skandw2_asm_output_data (int size, unsigned HOST_WIDE_INT value, 69132718Skan const char *comment, ...) 7090075Sobrien{ 71132718Skan va_list ap; 72169689Skan const char *op = integer_asm_op (size, FALSE); 7390075Sobrien 74132718Skan va_start (ap, comment); 75132718Skan 7690075Sobrien if (size * 8 < HOST_BITS_PER_WIDE_INT) 7790075Sobrien value &= ~(~(unsigned HOST_WIDE_INT) 0 << (size * 8)); 7890075Sobrien 79169689Skan if (op) 80169689Skan fprintf (asm_out_file, "%s" HOST_WIDE_INT_PRINT_HEX, op, value); 81169689Skan else 82169689Skan assemble_integer (GEN_INT (value), size, BITS_PER_UNIT, 1); 8390075Sobrien 8490075Sobrien if (flag_debug_asm && comment) 8590075Sobrien { 8690075Sobrien fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START); 8790075Sobrien vfprintf (asm_out_file, comment, ap); 8890075Sobrien } 8990075Sobrien fputc ('\n', asm_out_file); 9090075Sobrien 91132718Skan va_end (ap); 9290075Sobrien} 9390075Sobrien 9490075Sobrien/* Output the difference between two symbols in a given size. */ 9590075Sobrien/* ??? There appear to be assemblers that do not like such 9690075Sobrien subtraction, but do support ASM_SET_OP. It's unfortunately 9790075Sobrien impossible to do here, since the ASM_SET_OP for the difference 9890075Sobrien symbol must appear after both symbols are defined. */ 9990075Sobrien 10090075Sobrienvoid 101132718Skandw2_asm_output_delta (int size, const char *lab1, const char *lab2, 102132718Skan const char *comment, ...) 10390075Sobrien{ 104132718Skan va_list ap; 10590075Sobrien 106132718Skan va_start (ap, comment); 107132718Skan 108117395Skan#ifdef ASM_OUTPUT_DWARF_DELTA 109117395Skan ASM_OUTPUT_DWARF_DELTA (asm_out_file, size, lab1, lab2); 110117395Skan#else 11190075Sobrien dw2_assemble_integer (size, 11290075Sobrien gen_rtx_MINUS (Pmode, 11390075Sobrien gen_rtx_SYMBOL_REF (Pmode, lab1), 11490075Sobrien gen_rtx_SYMBOL_REF (Pmode, lab2))); 115117395Skan#endif 11690075Sobrien if (flag_debug_asm && comment) 11790075Sobrien { 11890075Sobrien fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START); 11990075Sobrien vfprintf (asm_out_file, comment, ap); 12090075Sobrien } 12190075Sobrien fputc ('\n', asm_out_file); 12290075Sobrien 123132718Skan va_end (ap); 12490075Sobrien} 12590075Sobrien 126169689Skan/* Output a section-relative reference to a LABEL, which was placed in 127169689Skan BASE. In general this can only be done for debugging symbols. 128169689Skan E.g. on most targets with the GNU linker, this is accomplished with 129169689Skan a direct reference and the knowledge that the debugging section 130169689Skan will be placed at VMA 0. Some targets have special relocations for 131169689Skan this that we must use. */ 13290075Sobrien 13390075Sobrienvoid 134132718Skandw2_asm_output_offset (int size, const char *label, 135169689Skan section *base ATTRIBUTE_UNUSED, 136132718Skan const char *comment, ...) 13790075Sobrien{ 138132718Skan va_list ap; 13990075Sobrien 140132718Skan va_start (ap, comment); 141132718Skan 14290075Sobrien#ifdef ASM_OUTPUT_DWARF_OFFSET 143169689Skan ASM_OUTPUT_DWARF_OFFSET (asm_out_file, size, label, base); 14490075Sobrien#else 14590075Sobrien dw2_assemble_integer (size, gen_rtx_SYMBOL_REF (Pmode, label)); 14690075Sobrien#endif 14790075Sobrien 14890075Sobrien if (flag_debug_asm && comment) 14990075Sobrien { 15090075Sobrien fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START); 15190075Sobrien vfprintf (asm_out_file, comment, ap); 15290075Sobrien } 15390075Sobrien fputc ('\n', asm_out_file); 15490075Sobrien 155132718Skan va_end (ap); 15690075Sobrien} 15790075Sobrien 158169689Skan#if 0 159169689Skan 16090075Sobrien/* Output a self-relative reference to a label, possibly in a 16190075Sobrien different section or object file. */ 16290075Sobrien 16390075Sobrienvoid 164132718Skandw2_asm_output_pcrel (int size ATTRIBUTE_UNUSED, 165132718Skan const char *label ATTRIBUTE_UNUSED, 166132718Skan const char *comment, ...) 16790075Sobrien{ 168132718Skan va_list ap; 16990075Sobrien 170132718Skan va_start (ap, comment); 171132718Skan 17290075Sobrien#ifdef ASM_OUTPUT_DWARF_PCREL 17390075Sobrien ASM_OUTPUT_DWARF_PCREL (asm_out_file, size, label); 17490075Sobrien#else 17590075Sobrien dw2_assemble_integer (size, 17690075Sobrien gen_rtx_MINUS (Pmode, 17790075Sobrien gen_rtx_SYMBOL_REF (Pmode, label), 17890075Sobrien pc_rtx)); 17990075Sobrien#endif 18090075Sobrien 18190075Sobrien if (flag_debug_asm && comment) 18290075Sobrien { 18390075Sobrien fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START); 18490075Sobrien vfprintf (asm_out_file, comment, ap); 18590075Sobrien } 18690075Sobrien fputc ('\n', asm_out_file); 18790075Sobrien 188132718Skan va_end (ap); 18990075Sobrien} 190169689Skan#endif /* 0 */ 19190075Sobrien 19290075Sobrien/* Output an absolute reference to a label. */ 19390075Sobrien 19490075Sobrienvoid 195132718Skandw2_asm_output_addr (int size, const char *label, 196132718Skan const char *comment, ...) 19790075Sobrien{ 198132718Skan va_list ap; 19990075Sobrien 200132718Skan va_start (ap, comment); 201132718Skan 20290075Sobrien dw2_assemble_integer (size, gen_rtx_SYMBOL_REF (Pmode, label)); 20390075Sobrien 20490075Sobrien if (flag_debug_asm && comment) 20590075Sobrien { 20690075Sobrien fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START); 20790075Sobrien vfprintf (asm_out_file, comment, ap); 20890075Sobrien } 20990075Sobrien fputc ('\n', asm_out_file); 21090075Sobrien 211132718Skan va_end (ap); 21290075Sobrien} 21390075Sobrien 21490075Sobrien/* Similar, but use an RTX expression instead of a text label. */ 21590075Sobrien 21690075Sobrienvoid 217132718Skandw2_asm_output_addr_rtx (int size, rtx addr, 218132718Skan const char *comment, ...) 21990075Sobrien{ 220132718Skan va_list ap; 22190075Sobrien 222132718Skan va_start (ap, comment); 223132718Skan 22490075Sobrien dw2_assemble_integer (size, addr); 22590075Sobrien 22690075Sobrien if (flag_debug_asm && comment) 22790075Sobrien { 22890075Sobrien fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START); 22990075Sobrien vfprintf (asm_out_file, comment, ap); 23090075Sobrien } 23190075Sobrien fputc ('\n', asm_out_file); 23290075Sobrien 233132718Skan va_end (ap); 23490075Sobrien} 23590075Sobrien 236132718Skan/* Output the first ORIG_LEN characters of STR as a string. 237132718Skan If ORIG_LEN is equal to -1, ignore this parameter and output 238132718Skan the entire STR instead. 239132718Skan If COMMENT is not NULL and comments in the debug information 240132718Skan have been requested by the user, append the given COMMENT 241132718Skan to the generated output. */ 242132718Skan 24390075Sobrienvoid 244132718Skandw2_asm_output_nstring (const char *str, size_t orig_len, 245132718Skan const char *comment, ...) 24690075Sobrien{ 24790075Sobrien size_t i, len; 248132718Skan va_list ap; 24990075Sobrien 250132718Skan va_start (ap, comment); 25190075Sobrien 25290075Sobrien len = orig_len; 25390075Sobrien 25490075Sobrien if (len == (size_t) -1) 25590075Sobrien len = strlen (str); 25690075Sobrien 25790075Sobrien if (flag_debug_asm && comment) 25890075Sobrien { 25990075Sobrien fputs ("\t.ascii \"", asm_out_file); 26090075Sobrien for (i = 0; i < len; i++) 26190075Sobrien { 26290075Sobrien int c = str[i]; 26390075Sobrien if (c == '\"' || c == '\\') 26490075Sobrien fputc ('\\', asm_out_file); 26590075Sobrien if (ISPRINT(c)) 26690075Sobrien fputc (c, asm_out_file); 26790075Sobrien else 26890075Sobrien fprintf (asm_out_file, "\\%o", c); 26990075Sobrien } 27090075Sobrien fprintf (asm_out_file, "\\0\"\t%s ", ASM_COMMENT_START); 27190075Sobrien vfprintf (asm_out_file, comment, ap); 27290075Sobrien fputc ('\n', asm_out_file); 27390075Sobrien } 27490075Sobrien else 27590075Sobrien { 27690075Sobrien /* If an explicit length was given, we can't assume there 27790075Sobrien is a null termination in the string buffer. */ 27890075Sobrien if (orig_len == (size_t) -1) 27990075Sobrien len += 1; 28090075Sobrien ASM_OUTPUT_ASCII (asm_out_file, str, len); 28190075Sobrien if (orig_len != (size_t) -1) 28290075Sobrien assemble_integer (const0_rtx, 1, BITS_PER_UNIT, 1); 28390075Sobrien } 28490075Sobrien 285132718Skan va_end (ap); 28690075Sobrien} 28790075Sobrien 28890075Sobrien 28990075Sobrien/* Return the size of an unsigned LEB128 quantity. */ 29090075Sobrien 29190075Sobrienint 292132718Skansize_of_uleb128 (unsigned HOST_WIDE_INT value) 29390075Sobrien{ 294132718Skan int size = 0; 29590075Sobrien 29690075Sobrien do 29790075Sobrien { 29890075Sobrien value >>= 7; 29990075Sobrien size += 1; 30090075Sobrien } 30190075Sobrien while (value != 0); 30290075Sobrien 30390075Sobrien return size; 30490075Sobrien} 30590075Sobrien 30690075Sobrien/* Return the size of a signed LEB128 quantity. */ 30790075Sobrien 30890075Sobrienint 309132718Skansize_of_sleb128 (HOST_WIDE_INT value) 31090075Sobrien{ 31190075Sobrien int size = 0, byte; 31290075Sobrien 31390075Sobrien do 31490075Sobrien { 31590075Sobrien byte = (value & 0x7f); 31690075Sobrien value >>= 7; 31790075Sobrien size += 1; 31890075Sobrien } 31990075Sobrien while (!((value == 0 && (byte & 0x40) == 0) 32090075Sobrien || (value == -1 && (byte & 0x40) != 0))); 32190075Sobrien 32290075Sobrien return size; 32390075Sobrien} 32490075Sobrien 32590075Sobrien/* Given an encoding, return the number of bytes the format occupies. 326117395Skan This is only defined for fixed-size encodings, and so does not 32790075Sobrien include leb128. */ 32890075Sobrien 32990075Sobrienint 330132718Skansize_of_encoded_value (int encoding) 33190075Sobrien{ 33290075Sobrien if (encoding == DW_EH_PE_omit) 33390075Sobrien return 0; 33490075Sobrien 33590075Sobrien switch (encoding & 0x07) 33690075Sobrien { 33790075Sobrien case DW_EH_PE_absptr: 33890075Sobrien return POINTER_SIZE / BITS_PER_UNIT; 33990075Sobrien case DW_EH_PE_udata2: 34090075Sobrien return 2; 34190075Sobrien case DW_EH_PE_udata4: 34290075Sobrien return 4; 34390075Sobrien case DW_EH_PE_udata8: 34490075Sobrien return 8; 345169689Skan default: 346169689Skan gcc_unreachable (); 34790075Sobrien } 34890075Sobrien} 34990075Sobrien 35090075Sobrien/* Yield a name for a given pointer encoding. */ 35190075Sobrien 35290075Sobrienconst char * 353132718Skaneh_data_format_name (int format) 35490075Sobrien{ 35590075Sobrien#if HAVE_DESIGNATED_INITIALIZERS 35690075Sobrien#define S(p, v) [p] = v, 35790075Sobrien#else 35890075Sobrien#define S(p, v) case p: return v; 35990075Sobrien#endif 36090075Sobrien 36190075Sobrien#if HAVE_DESIGNATED_INITIALIZERS 36290075Sobrien __extension__ static const char * const format_names[256] = { 36390075Sobrien#else 36490075Sobrien switch (format) { 36590075Sobrien#endif 36690075Sobrien 36790075Sobrien S(DW_EH_PE_absptr, "absolute") 36890075Sobrien S(DW_EH_PE_omit, "omit") 36990075Sobrien S(DW_EH_PE_aligned, "aligned absolute") 37090075Sobrien 37190075Sobrien S(DW_EH_PE_uleb128, "uleb128") 37290075Sobrien S(DW_EH_PE_udata2, "udata2") 37390075Sobrien S(DW_EH_PE_udata4, "udata4") 37490075Sobrien S(DW_EH_PE_udata8, "udata8") 37590075Sobrien S(DW_EH_PE_sleb128, "sleb128") 37690075Sobrien S(DW_EH_PE_sdata2, "sdata2") 37790075Sobrien S(DW_EH_PE_sdata4, "sdata4") 37890075Sobrien S(DW_EH_PE_sdata8, "sdata8") 37990075Sobrien 38090075Sobrien S(DW_EH_PE_absptr | DW_EH_PE_pcrel, "pcrel") 38190075Sobrien S(DW_EH_PE_uleb128 | DW_EH_PE_pcrel, "pcrel uleb128") 38290075Sobrien S(DW_EH_PE_udata2 | DW_EH_PE_pcrel, "pcrel udata2") 38390075Sobrien S(DW_EH_PE_udata4 | DW_EH_PE_pcrel, "pcrel udata4") 38490075Sobrien S(DW_EH_PE_udata8 | DW_EH_PE_pcrel, "pcrel udata8") 38590075Sobrien S(DW_EH_PE_sleb128 | DW_EH_PE_pcrel, "pcrel sleb128") 38690075Sobrien S(DW_EH_PE_sdata2 | DW_EH_PE_pcrel, "pcrel sdata2") 38790075Sobrien S(DW_EH_PE_sdata4 | DW_EH_PE_pcrel, "pcrel sdata4") 38890075Sobrien S(DW_EH_PE_sdata8 | DW_EH_PE_pcrel, "pcrel sdata8") 38990075Sobrien 39090075Sobrien S(DW_EH_PE_absptr | DW_EH_PE_textrel, "textrel") 39190075Sobrien S(DW_EH_PE_uleb128 | DW_EH_PE_textrel, "textrel uleb128") 39290075Sobrien S(DW_EH_PE_udata2 | DW_EH_PE_textrel, "textrel udata2") 39390075Sobrien S(DW_EH_PE_udata4 | DW_EH_PE_textrel, "textrel udata4") 39490075Sobrien S(DW_EH_PE_udata8 | DW_EH_PE_textrel, "textrel udata8") 39590075Sobrien S(DW_EH_PE_sleb128 | DW_EH_PE_textrel, "textrel sleb128") 39690075Sobrien S(DW_EH_PE_sdata2 | DW_EH_PE_textrel, "textrel sdata2") 39790075Sobrien S(DW_EH_PE_sdata4 | DW_EH_PE_textrel, "textrel sdata4") 39890075Sobrien S(DW_EH_PE_sdata8 | DW_EH_PE_textrel, "textrel sdata8") 39990075Sobrien 40090075Sobrien S(DW_EH_PE_absptr | DW_EH_PE_datarel, "datarel") 40190075Sobrien S(DW_EH_PE_uleb128 | DW_EH_PE_datarel, "datarel uleb128") 40290075Sobrien S(DW_EH_PE_udata2 | DW_EH_PE_datarel, "datarel udata2") 40390075Sobrien S(DW_EH_PE_udata4 | DW_EH_PE_datarel, "datarel udata4") 40490075Sobrien S(DW_EH_PE_udata8 | DW_EH_PE_datarel, "datarel udata8") 40590075Sobrien S(DW_EH_PE_sleb128 | DW_EH_PE_datarel, "datarel sleb128") 40690075Sobrien S(DW_EH_PE_sdata2 | DW_EH_PE_datarel, "datarel sdata2") 40790075Sobrien S(DW_EH_PE_sdata4 | DW_EH_PE_datarel, "datarel sdata4") 40890075Sobrien S(DW_EH_PE_sdata8 | DW_EH_PE_datarel, "datarel sdata8") 40990075Sobrien 41090075Sobrien S(DW_EH_PE_absptr | DW_EH_PE_funcrel, "funcrel") 41190075Sobrien S(DW_EH_PE_uleb128 | DW_EH_PE_funcrel, "funcrel uleb128") 41290075Sobrien S(DW_EH_PE_udata2 | DW_EH_PE_funcrel, "funcrel udata2") 41390075Sobrien S(DW_EH_PE_udata4 | DW_EH_PE_funcrel, "funcrel udata4") 41490075Sobrien S(DW_EH_PE_udata8 | DW_EH_PE_funcrel, "funcrel udata8") 41590075Sobrien S(DW_EH_PE_sleb128 | DW_EH_PE_funcrel, "funcrel sleb128") 41690075Sobrien S(DW_EH_PE_sdata2 | DW_EH_PE_funcrel, "funcrel sdata2") 41790075Sobrien S(DW_EH_PE_sdata4 | DW_EH_PE_funcrel, "funcrel sdata4") 41890075Sobrien S(DW_EH_PE_sdata8 | DW_EH_PE_funcrel, "funcrel sdata8") 41990075Sobrien 42090075Sobrien S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_pcrel, 42190075Sobrien "indirect pcrel") 42290075Sobrien S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_pcrel, 42390075Sobrien "indirect pcrel uleb128") 42490075Sobrien S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_pcrel, 42590075Sobrien "indirect pcrel udata2") 42690075Sobrien S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_pcrel, 42790075Sobrien "indirect pcrel udata4") 42890075Sobrien S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_pcrel, 42990075Sobrien "indirect pcrel udata8") 43090075Sobrien S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_pcrel, 43190075Sobrien "indirect pcrel sleb128") 43290075Sobrien S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_pcrel, 43390075Sobrien "indirect pcrel sdata2") 43490075Sobrien S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_pcrel, 43590075Sobrien "indirect pcrel sdata4") 43690075Sobrien S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_pcrel, 43790075Sobrien "indirect pcrel sdata8") 43890075Sobrien 43990075Sobrien S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_textrel, 44090075Sobrien "indirect textrel") 44190075Sobrien S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_textrel, 44290075Sobrien "indirect textrel uleb128") 44390075Sobrien S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_textrel, 44490075Sobrien "indirect textrel udata2") 44590075Sobrien S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_textrel, 44690075Sobrien "indirect textrel udata4") 44790075Sobrien S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_textrel, 44890075Sobrien "indirect textrel udata8") 44990075Sobrien S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_textrel, 45090075Sobrien "indirect textrel sleb128") 45190075Sobrien S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_textrel, 45290075Sobrien "indirect textrel sdata2") 45390075Sobrien S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_textrel, 45490075Sobrien "indirect textrel sdata4") 45590075Sobrien S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_textrel, 45690075Sobrien "indirect textrel sdata8") 45790075Sobrien 45890075Sobrien S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_datarel, 45990075Sobrien "indirect datarel") 46090075Sobrien S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_datarel, 46190075Sobrien "indirect datarel uleb128") 46290075Sobrien S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_datarel, 46390075Sobrien "indirect datarel udata2") 46490075Sobrien S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_datarel, 46590075Sobrien "indirect datarel udata4") 46690075Sobrien S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_datarel, 46790075Sobrien "indirect datarel udata8") 46890075Sobrien S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_datarel, 46990075Sobrien "indirect datarel sleb128") 47090075Sobrien S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_datarel, 47190075Sobrien "indirect datarel sdata2") 47290075Sobrien S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_datarel, 47390075Sobrien "indirect datarel sdata4") 47490075Sobrien S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_datarel, 47590075Sobrien "indirect datarel sdata8") 47690075Sobrien 47790075Sobrien S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_funcrel, 47890075Sobrien "indirect funcrel") 47990075Sobrien S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_funcrel, 48090075Sobrien "indirect funcrel uleb128") 48190075Sobrien S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_funcrel, 48290075Sobrien "indirect funcrel udata2") 48390075Sobrien S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_funcrel, 48490075Sobrien "indirect funcrel udata4") 48590075Sobrien S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_funcrel, 48690075Sobrien "indirect funcrel udata8") 48790075Sobrien S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_funcrel, 48890075Sobrien "indirect funcrel sleb128") 48990075Sobrien S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_funcrel, 49090075Sobrien "indirect funcrel sdata2") 49190075Sobrien S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_funcrel, 49290075Sobrien "indirect funcrel sdata4") 49390075Sobrien S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_funcrel, 49490075Sobrien "indirect funcrel sdata8") 49590075Sobrien 49690075Sobrien#if HAVE_DESIGNATED_INITIALIZERS 49790075Sobrien }; 49890075Sobrien 499169689Skan gcc_assert (format >= 0 && format < 0x100 && format_names[format]); 500169689Skan 50190075Sobrien return format_names[format]; 50290075Sobrien#else 50390075Sobrien } 504169689Skan gcc_unreachable (); 50590075Sobrien#endif 50690075Sobrien} 50790075Sobrien 50890075Sobrien/* Output an unsigned LEB128 quantity. */ 50990075Sobrien 51090075Sobrienvoid 511132718Skandw2_asm_output_data_uleb128 (unsigned HOST_WIDE_INT value, 512132718Skan const char *comment, ...) 51390075Sobrien{ 514132718Skan va_list ap; 51590075Sobrien 516132718Skan va_start (ap, comment); 517132718Skan 51890075Sobrien#ifdef HAVE_AS_LEB128 519132718Skan fprintf (asm_out_file, "\t.uleb128 " HOST_WIDE_INT_PRINT_HEX , value); 52090075Sobrien 52190075Sobrien if (flag_debug_asm && comment) 52290075Sobrien { 52390075Sobrien fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START); 52490075Sobrien vfprintf (asm_out_file, comment, ap); 52590075Sobrien } 52690075Sobrien#else 52790075Sobrien { 52890075Sobrien unsigned HOST_WIDE_INT work = value; 52990075Sobrien const char *byte_op = targetm.asm_out.byte_op; 53090075Sobrien 53190075Sobrien if (byte_op) 53290075Sobrien fputs (byte_op, asm_out_file); 53390075Sobrien do 53490075Sobrien { 53590075Sobrien int byte = (work & 0x7f); 53690075Sobrien work >>= 7; 53790075Sobrien if (work != 0) 53890075Sobrien /* More bytes to follow. */ 53990075Sobrien byte |= 0x80; 54090075Sobrien 54190075Sobrien if (byte_op) 54290075Sobrien { 54390075Sobrien fprintf (asm_out_file, "0x%x", byte); 54490075Sobrien if (work != 0) 54590075Sobrien fputc (',', asm_out_file); 54690075Sobrien } 54790075Sobrien else 54890075Sobrien assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1); 54990075Sobrien } 55090075Sobrien while (work != 0); 55190075Sobrien 55290075Sobrien if (flag_debug_asm) 55390075Sobrien { 554132718Skan fprintf (asm_out_file, "\t%s uleb128 " HOST_WIDE_INT_PRINT_HEX, 555132718Skan ASM_COMMENT_START, value); 55690075Sobrien if (comment) 55790075Sobrien { 55890075Sobrien fputs ("; ", asm_out_file); 55990075Sobrien vfprintf (asm_out_file, comment, ap); 56090075Sobrien } 56190075Sobrien } 56290075Sobrien } 56390075Sobrien#endif 56490075Sobrien fputc ('\n', asm_out_file); 56590075Sobrien 566132718Skan va_end (ap); 56790075Sobrien} 56890075Sobrien 569117395Skan/* Output a signed LEB128 quantity. */ 57090075Sobrien 57190075Sobrienvoid 572132718Skandw2_asm_output_data_sleb128 (HOST_WIDE_INT value, 573132718Skan const char *comment, ...) 57490075Sobrien{ 575132718Skan va_list ap; 57690075Sobrien 577132718Skan va_start (ap, comment); 578132718Skan 57990075Sobrien#ifdef HAVE_AS_LEB128 580132718Skan fprintf (asm_out_file, "\t.sleb128 " HOST_WIDE_INT_PRINT_DEC, value); 58190075Sobrien 58290075Sobrien if (flag_debug_asm && comment) 58390075Sobrien { 58490075Sobrien fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START); 58590075Sobrien vfprintf (asm_out_file, comment, ap); 58690075Sobrien } 58790075Sobrien#else 58890075Sobrien { 58990075Sobrien HOST_WIDE_INT work = value; 59090075Sobrien int more, byte; 59190075Sobrien const char *byte_op = targetm.asm_out.byte_op; 59290075Sobrien 59390075Sobrien if (byte_op) 59490075Sobrien fputs (byte_op, asm_out_file); 59590075Sobrien do 59690075Sobrien { 59790075Sobrien byte = (work & 0x7f); 59890075Sobrien /* arithmetic shift */ 59990075Sobrien work >>= 7; 60090075Sobrien more = !((work == 0 && (byte & 0x40) == 0) 60190075Sobrien || (work == -1 && (byte & 0x40) != 0)); 60290075Sobrien if (more) 60390075Sobrien byte |= 0x80; 60490075Sobrien 60590075Sobrien if (byte_op) 60690075Sobrien { 60790075Sobrien fprintf (asm_out_file, "0x%x", byte); 60890075Sobrien if (more) 60990075Sobrien fputc (',', asm_out_file); 61090075Sobrien } 61190075Sobrien else 61290075Sobrien assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1); 61390075Sobrien } 61490075Sobrien while (more); 61590075Sobrien 61690075Sobrien if (flag_debug_asm) 61790075Sobrien { 618132718Skan fprintf (asm_out_file, "\t%s sleb128 " HOST_WIDE_INT_PRINT_DEC, 619132718Skan ASM_COMMENT_START, value); 62090075Sobrien if (comment) 62190075Sobrien { 62290075Sobrien fputs ("; ", asm_out_file); 62390075Sobrien vfprintf (asm_out_file, comment, ap); 62490075Sobrien } 62590075Sobrien } 62690075Sobrien } 62790075Sobrien#endif 62890075Sobrien fputc ('\n', asm_out_file); 62990075Sobrien 630132718Skan va_end (ap); 63190075Sobrien} 63290075Sobrien 63390075Sobrienvoid 634132718Skandw2_asm_output_delta_uleb128 (const char *lab1 ATTRIBUTE_UNUSED, 635132718Skan const char *lab2 ATTRIBUTE_UNUSED, 636132718Skan const char *comment, ...) 63790075Sobrien{ 638132718Skan va_list ap; 63990075Sobrien 640132718Skan va_start (ap, comment); 641132718Skan 64290075Sobrien#ifdef HAVE_AS_LEB128 64390075Sobrien fputs ("\t.uleb128 ", asm_out_file); 64490075Sobrien assemble_name (asm_out_file, lab1); 64590075Sobrien fputc ('-', asm_out_file); 64690075Sobrien assemble_name (asm_out_file, lab2); 64790075Sobrien#else 648169689Skan gcc_unreachable (); 64990075Sobrien#endif 65090075Sobrien 65190075Sobrien if (flag_debug_asm && comment) 65290075Sobrien { 65390075Sobrien fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START); 65490075Sobrien vfprintf (asm_out_file, comment, ap); 65590075Sobrien } 65690075Sobrien fputc ('\n', asm_out_file); 65790075Sobrien 658132718Skan va_end (ap); 65990075Sobrien} 66090075Sobrien 661169689Skan#if 0 662169689Skan 66390075Sobrienvoid 664132718Skandw2_asm_output_delta_sleb128 (const char *lab1 ATTRIBUTE_UNUSED, 665132718Skan const char *lab2 ATTRIBUTE_UNUSED, 666132718Skan const char *comment, ...) 66790075Sobrien{ 668132718Skan va_list ap; 66990075Sobrien 670132718Skan va_start (ap, comment); 671132718Skan 67290075Sobrien#ifdef HAVE_AS_LEB128 67390075Sobrien fputs ("\t.sleb128 ", asm_out_file); 67490075Sobrien assemble_name (asm_out_file, lab1); 67590075Sobrien fputc ('-', asm_out_file); 67690075Sobrien assemble_name (asm_out_file, lab2); 67790075Sobrien#else 678169689Skan gcc_unreachable (); 67990075Sobrien#endif 68090075Sobrien 68190075Sobrien if (flag_debug_asm && comment) 68290075Sobrien { 68390075Sobrien fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START); 68490075Sobrien vfprintf (asm_out_file, comment, ap); 68590075Sobrien } 68690075Sobrien fputc ('\n', asm_out_file); 68790075Sobrien 688132718Skan va_end (ap); 68990075Sobrien} 690169689Skan#endif /* 0 */ 69190075Sobrien 692169689Skanstatic rtx dw2_force_const_mem (rtx, bool); 693132718Skanstatic int dw2_output_indirect_constant_1 (splay_tree_node, void *); 69490075Sobrien 695132718Skanstatic GTY((param1_is (char *), param2_is (tree))) splay_tree indirect_pool; 69690075Sobrien 697132718Skanstatic GTY(()) int dw2_const_labelno; 698132718Skan 69990075Sobrien#if defined(HAVE_GAS_HIDDEN) && defined(SUPPORTS_ONE_ONLY) 70090075Sobrien# define USE_LINKONCE_INDIRECT 1 70190075Sobrien#else 70290075Sobrien# define USE_LINKONCE_INDIRECT 0 70390075Sobrien#endif 70490075Sobrien 70590075Sobrien/* Put X, a SYMBOL_REF, in memory. Return a SYMBOL_REF to the allocated 70690075Sobrien memory. Differs from force_const_mem in that a single pool is used for 70790075Sobrien the entire unit of translation, and the memory is not guaranteed to be 708169689Skan "near" the function in any interesting sense. PUBLIC controls whether 709169689Skan the symbol can be shared across the entire application (or DSO). */ 71090075Sobrien 71190075Sobrienstatic rtx 712169689Skandw2_force_const_mem (rtx x, bool public) 71390075Sobrien{ 71490075Sobrien splay_tree_node node; 71590075Sobrien const char *str; 71690075Sobrien tree decl; 71790075Sobrien 71890075Sobrien if (! indirect_pool) 719132718Skan indirect_pool = splay_tree_new_ggc (splay_tree_compare_pointers); 72090075Sobrien 721169689Skan gcc_assert (GET_CODE (x) == SYMBOL_REF); 72290075Sobrien 723169689Skan str = targetm.strip_name_encoding (XSTR (x, 0)); 72490075Sobrien node = splay_tree_lookup (indirect_pool, (splay_tree_key) str); 72590075Sobrien if (node) 72690075Sobrien decl = (tree) node->value; 72790075Sobrien else 72890075Sobrien { 72990075Sobrien tree id; 73090075Sobrien 731169689Skan if (public && USE_LINKONCE_INDIRECT) 73290075Sobrien { 73390075Sobrien char *ref_name = alloca (strlen (str) + sizeof "DW.ref."); 73490075Sobrien 73590075Sobrien sprintf (ref_name, "DW.ref.%s", str); 73690075Sobrien id = get_identifier (ref_name); 73790075Sobrien decl = build_decl (VAR_DECL, id, ptr_type_node); 73890075Sobrien DECL_ARTIFICIAL (decl) = 1; 739169689Skan DECL_IGNORED_P (decl) = 1; 74090075Sobrien TREE_PUBLIC (decl) = 1; 74190075Sobrien DECL_INITIAL (decl) = decl; 74290075Sobrien make_decl_one_only (decl); 74390075Sobrien } 74490075Sobrien else 74590075Sobrien { 74690075Sobrien char label[32]; 74790075Sobrien 748132718Skan ASM_GENERATE_INTERNAL_LABEL (label, "LDFCM", dw2_const_labelno); 749132718Skan ++dw2_const_labelno; 75090075Sobrien id = get_identifier (label); 75190075Sobrien decl = build_decl (VAR_DECL, id, ptr_type_node); 75290075Sobrien DECL_ARTIFICIAL (decl) = 1; 753169689Skan DECL_IGNORED_P (decl) = 1; 75490075Sobrien TREE_STATIC (decl) = 1; 75590075Sobrien DECL_INITIAL (decl) = decl; 75690075Sobrien } 75790075Sobrien 75890075Sobrien id = maybe_get_identifier (str); 75990075Sobrien if (id) 76090075Sobrien TREE_SYMBOL_REFERENCED (id) = 1; 76190075Sobrien 76290075Sobrien splay_tree_insert (indirect_pool, (splay_tree_key) str, 76390075Sobrien (splay_tree_value) decl); 76490075Sobrien } 76590075Sobrien 76690075Sobrien return XEXP (DECL_RTL (decl), 0); 76790075Sobrien} 76890075Sobrien 76990075Sobrien/* A helper function for dw2_output_indirect_constants called through 77090075Sobrien splay_tree_foreach. Emit one queued constant to memory. */ 77190075Sobrien 77290075Sobrienstatic int 773132718Skandw2_output_indirect_constant_1 (splay_tree_node node, 774132718Skan void *data ATTRIBUTE_UNUSED) 77590075Sobrien{ 77690075Sobrien const char *sym; 77790075Sobrien rtx sym_ref; 778169689Skan tree decl; 77990075Sobrien 78090075Sobrien sym = (const char *) node->key; 781169689Skan decl = (tree) node->value; 78290075Sobrien sym_ref = gen_rtx_SYMBOL_REF (Pmode, sym); 783169689Skan if (TREE_PUBLIC (decl) && USE_LINKONCE_INDIRECT) 784132718Skan fprintf (asm_out_file, "\t.hidden %sDW.ref.%s\n", user_label_prefix, sym); 785169689Skan assemble_variable (decl, 1, 1, 1); 78690075Sobrien assemble_integer (sym_ref, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1); 78790075Sobrien 78890075Sobrien return 0; 78990075Sobrien} 79090075Sobrien 79190075Sobrien/* Emit the constants queued through dw2_force_const_mem. */ 79290075Sobrien 79390075Sobrienvoid 794132718Skandw2_output_indirect_constants (void) 79590075Sobrien{ 79690075Sobrien if (indirect_pool) 79790075Sobrien splay_tree_foreach (indirect_pool, dw2_output_indirect_constant_1, NULL); 79890075Sobrien} 79990075Sobrien 800169689Skan/* Like dw2_asm_output_addr_rtx, but encode the pointer as directed. 801169689Skan If PUBLIC is set and the encoding is DW_EH_PE_indirect, the indirect 802169689Skan reference is shared across the entire application (or DSO). */ 80390075Sobrien 80490075Sobrienvoid 805169689Skandw2_asm_output_encoded_addr_rtx (int encoding, rtx addr, bool public, 806132718Skan const char *comment, ...) 80790075Sobrien{ 80890075Sobrien int size; 809132718Skan va_list ap; 81090075Sobrien 811132718Skan va_start (ap, comment); 81290075Sobrien 81390075Sobrien size = size_of_encoded_value (encoding); 81490075Sobrien 81590075Sobrien if (encoding == DW_EH_PE_aligned) 81690075Sobrien { 81790075Sobrien assemble_align (POINTER_SIZE); 81890075Sobrien assemble_integer (addr, size, POINTER_SIZE, 1); 81990075Sobrien return; 82090075Sobrien } 82190075Sobrien 82290075Sobrien /* NULL is _always_ represented as a plain zero, as is 1 for Ada's 82390075Sobrien "all others". */ 82490075Sobrien if (addr == const0_rtx || addr == const1_rtx) 82590075Sobrien assemble_integer (addr, size, BITS_PER_UNIT, 1); 82690075Sobrien else 82790075Sobrien { 82890075Sobrien restart: 82990075Sobrien /* Allow the target first crack at emitting this. Some of the 830117395Skan special relocations require special directives instead of 83190075Sobrien just ".4byte" or whatever. */ 83290075Sobrien#ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX 83390075Sobrien ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX (asm_out_file, encoding, size, 83490075Sobrien addr, done); 83590075Sobrien#endif 83690075Sobrien 83790075Sobrien /* Indirection is used to get dynamic relocations out of a 83890075Sobrien read-only section. */ 83990075Sobrien if (encoding & DW_EH_PE_indirect) 84090075Sobrien { 84190075Sobrien /* It is very tempting to use force_const_mem so that we share data 84290075Sobrien with the normal constant pool. However, we've already emitted 84390075Sobrien the constant pool for this function. Moreover, we'd like to 844169689Skan share these constants across the entire unit of translation and 845169689Skan even, if possible, across the entire application (or DSO). */ 846169689Skan addr = dw2_force_const_mem (addr, public); 84790075Sobrien encoding &= ~DW_EH_PE_indirect; 84890075Sobrien goto restart; 84990075Sobrien } 85090075Sobrien 85190075Sobrien switch (encoding & 0xF0) 85290075Sobrien { 85390075Sobrien case DW_EH_PE_absptr: 85490075Sobrien dw2_assemble_integer (size, addr); 85590075Sobrien break; 85690075Sobrien 85790075Sobrien case DW_EH_PE_pcrel: 858169689Skan gcc_assert (GET_CODE (addr) == SYMBOL_REF); 85990075Sobrien#ifdef ASM_OUTPUT_DWARF_PCREL 86090075Sobrien ASM_OUTPUT_DWARF_PCREL (asm_out_file, size, XSTR (addr, 0)); 86190075Sobrien#else 86290075Sobrien dw2_assemble_integer (size, gen_rtx_MINUS (Pmode, addr, pc_rtx)); 86390075Sobrien#endif 86490075Sobrien break; 86590075Sobrien 86690075Sobrien default: 867117395Skan /* Other encodings should have been handled by 86890075Sobrien ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX. */ 869169689Skan gcc_unreachable (); 87090075Sobrien } 87190075Sobrien 87290075Sobrien#ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX 87390075Sobrien done:; 87490075Sobrien#endif 87590075Sobrien } 87690075Sobrien 87790075Sobrien if (flag_debug_asm && comment) 87890075Sobrien { 87990075Sobrien fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START); 88090075Sobrien vfprintf (asm_out_file, comment, ap); 88190075Sobrien } 88290075Sobrien fputc ('\n', asm_out_file); 88390075Sobrien 884132718Skan va_end (ap); 88590075Sobrien} 886132718Skan 887132718Skan#include "gt-dwarf2asm.h" 888