Commit ad5818ae authored by rth's avatar rth
Browse files

* defaults.h (ASM_PREFERRED_EH_DATA_FORMAT): New.

	* dwarf2asm.c (dw2_force_const_mem, dw2_output_indirect_constant_1,
	dw2_output_indirect_constants, dw2_asm_output_encoded_addr_rtx): New.
	* dwarf2asm.h (dw2_asm_output_encoded_addr_rtx): Prototype.
	(dw2_output_indirect_constants): Prototype.
	* dwarf2out.c (dwarf2out_begin_prologue): Generate
	current_function_func_begin_label if we'll need it for EH.  Exit
	early for IA64_UNWIND_INFO.
	* except.c: Get DW_EH_PE_* defines from dwarf2.h.
	(eh_data_format_name): Update for indirect references.
	(output_function_exception_table): Care for IA64_UNWIND_INFO.
	Handle ASM_PREFERRED_EH_DATA_FORMAT.
	* except.h (MUST_USE_SJLJ_EXCEPTIONS): IA64_UNWIND_INFO needn't
	define HAVE_eh_return etc.
	* final.c (final_start_function): Always call dwarf2out_begin_prologue.
	(final_end_function): Don't call output_function_exception_table.
	* toplev.c (compile_file): Call dw2_output_indirect_constants.
	(rest_of_compilation): Invoke output_function_exception_table
	for ia64 before assemble_end_function.
	* tm.texi (ASM_PREFERRED_EH_DATA_FORMAT): Document.
	(ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX): Document.

	* unwind-dw2.c (_Unwind_GetTextRelBase, _Unwind_GetDataRelBase): New.
	* unwind.h: Declare them.
	* libgcc-std.ver: Export them.
	* unwind-pe.h: New file.

	* config/alpha/elf.h (ASM_PREFERRED_EH_DATA_FORMAT): New.

	* config/ia64/fde-glibc.c: Use "struct unw_table_entry"
	instead of "fde".
	(find_fde_for_dso): Extract DT_PLTGOT.
	(_Unwind_FindTableEntry): Rename from __ia64_find_fde; return
	the segment and gp as well.
	* config/ia64/frame-ia64.c: Remove file.
	* config/ia64/frame-ia64.h: Remove file.
	* config/ia64/unwind-ia64.c: New file.
	* config/ia64/unwind-ia64.h: New file.
	* config/ia64/ia64.h (ASM_OUTPUT_EH_CHAR): Remove.
	(ASM_OUTPUT_EH_SHORT, ASM_OUTPUT_EH_INT): Remove.
	(ASM_OUTPUT_EH_DOUBLE_INT): Remove.
	(ASM_PREFERRED_EH_DATA_FORMAT): New.
	(ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX): New.
	(IA64_UNWIND_INFO): Re-enable.
	(HANDLER_SECTION): Remove.
	(EH_RETURN_DATA_REGNO): New.
	* config/ia64/ia64.md (exception_receiver): Remove.
	* config/ia64/t-glibc (LIB2ADDEH): Re-enable.
	* config/ia64/t-ia64 (LIB2ADDEH): Re-enable.


git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@41981 138bc75d-0d04-0410-961f-82ee72b054a4
parent b69208e6
2001-05-11 Richard Henderson <rth@redhat.com>
* defaults.h (ASM_PREFERRED_EH_DATA_FORMAT): New.
* dwarf2asm.c (dw2_force_const_mem, dw2_output_indirect_constant_1,
dw2_output_indirect_constants, dw2_asm_output_encoded_addr_rtx): New.
* dwarf2asm.h (dw2_asm_output_encoded_addr_rtx): Prototype.
(dw2_output_indirect_constants): Prototype.
* dwarf2out.c (dwarf2out_begin_prologue): Generate
current_function_func_begin_label if we'll need it for EH. Exit
early for IA64_UNWIND_INFO.
* except.c: Get DW_EH_PE_* defines from dwarf2.h.
(eh_data_format_name): Update for indirect references.
(output_function_exception_table): Care for IA64_UNWIND_INFO.
Handle ASM_PREFERRED_EH_DATA_FORMAT.
* except.h (MUST_USE_SJLJ_EXCEPTIONS): IA64_UNWIND_INFO needn't
define HAVE_eh_return etc.
* final.c (final_start_function): Always call dwarf2out_begin_prologue.
(final_end_function): Don't call output_function_exception_table.
* toplev.c (compile_file): Call dw2_output_indirect_constants.
(rest_of_compilation): Invoke output_function_exception_table
for ia64 before assemble_end_function.
* tm.texi (ASM_PREFERRED_EH_DATA_FORMAT): Document.
(ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX): Document.
* unwind-dw2.c (_Unwind_GetTextRelBase, _Unwind_GetDataRelBase): New.
* unwind.h: Declare them.
* libgcc-std.ver: Export them.
* unwind-pe.h: New file.
* config/alpha/elf.h (ASM_PREFERRED_EH_DATA_FORMAT): New.
* config/ia64/fde-glibc.c: Use "struct unw_table_entry"
instead of "fde".
(find_fde_for_dso): Extract DT_PLTGOT.
(_Unwind_FindTableEntry): Rename from __ia64_find_fde; return
the segment and gp as well.
* config/ia64/frame-ia64.c: Remove file.
* config/ia64/frame-ia64.h: Remove file.
* config/ia64/unwind-ia64.c: New file.
* config/ia64/unwind-ia64.h: New file.
* config/ia64/ia64.h (ASM_OUTPUT_EH_CHAR): Remove.
(ASM_OUTPUT_EH_SHORT, ASM_OUTPUT_EH_INT): Remove.
(ASM_OUTPUT_EH_DOUBLE_INT): Remove.
(ASM_PREFERRED_EH_DATA_FORMAT): New.
(ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX): New.
(IA64_UNWIND_INFO): Re-enable.
(HANDLER_SECTION): Remove.
(EH_RETURN_DATA_REGNO): New.
* config/ia64/ia64.md (exception_receiver): Remove.
* config/ia64/t-glibc (LIB2ADDEH): Re-enable.
* config/ia64/t-ia64 (LIB2ADDEH): Re-enable.
2001-05-11 Richard Henderson <rth@redhat.com>
* config/ia64/ia64.c (group_barrier_needed_p): Don't allow
......
......@@ -685,3 +685,16 @@ void FN () \
#undef UNALIGNED_SHORT_ASM_OP
#undef UNALIGNED_INT_ASM_OP
#undef UNALIGNED_DOUBLE_INT_ASM_OP
/* ??? This should be possible for ECOFF as well, since the relocations
exist. But the assembler doesn't seem to create them. */
/* Select a format to encode pointers in exception handling data. CODE
is 0 for data, 1 for code labels, 2 for function pointers. GLOBAL is
true if the symbol may be affected by dynamic relocations.
Since application size is already constrained to <2GB by the form of
the ldgp relocation, we can use a 32-bit pc-relative relocation to
static data. Dynamic data is accessed indirectly to allow for read
only EH sections. */
#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) \
(((GLOBAL) ? DW_EH_PE_indirect : 0) | DW_EH_PE_pcrel | DW_EH_PE_sdata4)
......@@ -31,7 +31,7 @@
#include <stdlib.h>
#include <link.h>
#include <bits/libc-lock.h>
#include "frame-ia64.h"
#include "unwind-ia64.h"
/* Initialized by crtbegin from the main application. */
......@@ -41,20 +41,17 @@ extern Elf64_Ehdr *__ia64_app_header;
appear in <link.h> in a new glibc version. */
__libc_lock_define (extern, _dl_load_lock)
/* ??? _dl_load_lock is not exported from glibc 2.1, but it is
from glibc 2.2. Remove this when folks have migrated. */
#pragma weak _dl_load_lock
/* This always exists, even in a static application. */
extern struct link_map *_dl_loaded;
static fde *
find_fde_for_dso (Elf64_Addr pc, Elf64_Ehdr *ehdr)
static struct unw_table_entry *
find_fde_for_dso (Elf64_Addr pc, Elf64_Ehdr *ehdr,
unsigned long *pseg_base, unsigned long *pgp)
{
Elf64_Phdr *phdr, *p_unwind;
Elf64_Phdr *phdr, *p_unwind, *p_dynamic;
long n, match;
Elf64_Addr load_base, seg_base;
fde *f_base;
struct unw_table_entry *f_base, *f;
size_t lo, hi;
/* Verify that we are looking at an ELF header. */
......@@ -71,6 +68,7 @@ find_fde_for_dso (Elf64_Addr pc, Elf64_Ehdr *ehdr)
phdr = (Elf64_Phdr *)((char *)ehdr + ehdr->e_phoff);
load_base = (ehdr->e_type == ET_DYN ? (Elf64_Addr)ehdr : 0);
p_unwind = NULL;
p_dynamic = NULL;
/* See if PC falls into one of the loaded segments. Find the unwind
segment at the same time. */
......@@ -84,69 +82,96 @@ find_fde_for_dso (Elf64_Addr pc, Elf64_Ehdr *ehdr)
}
else if (phdr->p_type == PT_IA_64_UNWIND)
p_unwind = phdr;
else if (phdr->p_type == PT_DYNAMIC)
p_dynamic = phdr;
}
if (!match || !p_unwind)
return NULL;
/* Search for the FDE within the unwind segment. */
f_base = (fde *) (p_unwind->p_vaddr + load_base);
f_base = (struct unw_table_entry *) (p_unwind->p_vaddr + load_base);
seg_base = (Elf64_Addr) ehdr;
lo = 0;
hi = p_unwind->p_memsz / sizeof (fde);
hi = p_unwind->p_memsz / sizeof (struct unw_table_entry);
while (lo < hi)
{
size_t mid = (lo + hi) / 2;
fde *f = f_base + mid;
f = f_base + mid;
if (pc < f->start_offset + seg_base)
hi = mid;
else if (pc >= f->end_offset + seg_base)
lo = mid + 1;
else
return f;
goto found;
}
return NULL;
found:
*pseg_base = seg_base;
*pgp = 0;
if (p_dynamic)
{
/* For dynamicly linked executables and shared libraries,
DT_PLTGOT is the gp value for that object. */
Elf64_Dyn *dyn = (Elf64_Dyn *)(p_dynamic->p_vaddr + load_base);
for (; dyn->d_tag != DT_NULL ; dyn++)
if (dyn->d_tag == DT_PLTGOT)
{
/* ??? Glibc seems to have relocated this already. */
*pgp = dyn->d_un.d_ptr;
break;
}
}
else
{
/* Otherwise this is a static executable with no _DYNAMIC.
The gp is constant program-wide. */
register unsigned long gp __asm__("gp");
*pgp = gp;
}
return f;
}
/* Return a pointer to the FDE for the function containing PC. */
fde *
__ia64_find_fde (void *pc, void **pc_base)
/* Return a pointer to the unwind table entry for the function
containing PC. */
struct unw_table_entry *
_Unwind_FindTableEntry (void *pc, unsigned long *segment_base,
unsigned long *gp)
{
fde *ret;
struct unw_table_entry *ret;
struct link_map *map;
/* Check the main application first, hoping that most of the user's
code is there instead of in some library. */
ret = find_fde_for_dso ((Elf64_Addr)pc, __ia64_app_header);
ret = find_fde_for_dso ((Elf64_Addr)pc, __ia64_app_header,
segment_base, gp);
if (ret)
{
*pc_base = __ia64_app_header;
return ret;
}
return ret;
/* Glibc is probably unique in that we can (with certain restrictions)
dynamicly load libraries into staticly linked applications. Thus
we _always_ check _dl_loaded. */
if (&_dl_load_lock)
__libc_lock_lock (_dl_load_lock);
__libc_lock_lock (_dl_load_lock);
for (map = _dl_loaded; map ; map = map->l_next)
{
/* Skip the main application's entry. */
if (map->l_name[0] == 0)
continue;
ret = find_fde_for_dso ((Elf64_Addr)pc, (Elf64_Ehdr *)map->l_addr);
ret = find_fde_for_dso ((Elf64_Addr)pc, (Elf64_Ehdr *)map->l_addr,
segment_base, gp);
if (ret)
break;
}
if (&_dl_load_lock)
__libc_lock_unlock (_dl_load_lock);
__libc_lock_unlock (_dl_load_lock);
*pc_base = (void *)(map ? map->l_addr : 0);
return ret;
}
This diff is collapsed.
......@@ -2149,19 +2149,6 @@ do { \
} while (0)
/* Output EH data to the unwind segment. */
#define ASM_OUTPUT_EH_CHAR(FILE, VALUE) \
ASM_OUTPUT_XDATA_CHAR(FILE, ".IA_64.unwind_info", VALUE)
#define ASM_OUTPUT_EH_SHORT(FILE, VALUE) \
ASM_OUTPUT_XDATA_SHORT(FILE, ".IA_64.unwind_info", VALUE)
#define ASM_OUTPUT_EH_INT(FILE, VALUE) \
ASM_OUTPUT_XDATA_INT(FILE, ".IA_64.unwind_info", VALUE)
#define ASM_OUTPUT_EH_DOUBLE_INT(FILE, VALUE) \
ASM_OUTPUT_XDATA_DOUBLE_INT(FILE, ".IA_64.unwind_info", VALUE)
/* A C statement to output to the stdio stream STREAM an assembler instruction
to assemble a single byte containing the number VALUE. */
......@@ -2473,26 +2460,6 @@ do { \
/* Assembler Commands for Exception Regions. */
/* ??? This entire section of ia64.h needs to be implemented and then cleaned
up. */
/* A C expression to output text to mark the start of an exception region.
This macro need not be defined on most platforms. */
/* #define ASM_OUTPUT_EH_REGION_BEG() */
/* A C expression to output text to mark the end of an exception region.
This macro need not be defined on most platforms. */
/* #define ASM_OUTPUT_EH_REGION_END() */
/* A C expression to switch to the section in which the main exception table is
to be placed. The default is a section named `.gcc_except_table' on machines
that support named sections via `ASM_OUTPUT_SECTION_NAME', otherwise if `-fpic'
or `-fPIC' is in effect, the `data_section', otherwise the
`readonly_data_section'. */
/* #define EXCEPTION_SECTION() */
/* If defined, a C string constant for the assembler operation to switch to the
section for exception handling frame unwind information. If not defined,
GNU CC will provide a default definition if the target supports named
......@@ -2503,26 +2470,34 @@ do { \
information and the default definition does not work. */
#define EH_FRAME_SECTION_ASM_OP "\t.section\t.IA_64.unwind,\"aw\""
/* A C expression that is nonzero if the normal exception table output should
be omitted.
This macro need not be defined on most platforms. */
/* #define OMIT_EH_TABLE() */
/* Alternate runtime support for looking up an exception at runtime and finding
the associated handler, if the default method won't work.
This macro need not be defined on most platforms. */
/* #define EH_TABLE_LOOKUP() */
/* A C expression that decides whether or not the current function needs to
have a function unwinder generated for it. See the file `except.c' for
details on when to define this, and how. */
/* #define DOESNT_NEED_UNWINDER */
/* Select a format to encode pointers in exception handling data. CODE
is 0 for data, 1 for code labels, 2 for function pointers. GLOBAL is
true if the symbol may be affected by dynamic relocations. */
#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) \
(((CODE) == 1 ? DW_EH_PE_textrel : DW_EH_PE_datarel) \
| ((GLOBAL) ? DW_EH_PE_indirect : 0) | DW_EH_PE_udata8)
/* Handle special EH pointer encodings. Absolute, pc-relative, and
indirect are handled automatically. */
#define ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX(FILE, ENCODING, SIZE, ADDR, DONE) \
do { \
const char *reltag = NULL; \
if (((ENCODING) & 0xF0) == DW_EH_PE_textrel) \
reltag = "@segrel("; \
else if (((ENCODING) & 0xF0) == DW_EH_PE_datarel) \
reltag = "@gprel("; \
if (reltag) \
{ \
fputs (((SIZE) == 4 ? UNALIGNED_INT_ASM_OP \
: (SIZE) == 8 ? UNALIGNED_DOUBLE_INT_ASM_OP \
: (abort (), "")), FILE); \
fputs (reltag, FILE); \
assemble_name (FILE, XSTR (ADDR, 0)); \
fputc (')', FILE); \
goto DONE; \
} \
} while (0)
/* An rtx used to mask the return address found via RETURN_ADDR_RTX, so that it
does not contain any extraneous set bits in it. */
/* #define MASK_RETURN_ADDR */
/* Assembler Commands for Alignment. */
......@@ -2846,13 +2821,11 @@ do { \
extern int ia64_final_schedule;
/* ??? Hack until frame-ia64.c is updated.
#define IA64_UNWIND_INFO 1
*/
#define HANDLER_SECTION fprintf (asm_out_file, "\t.personality\t__ia64_personality_v1\n\t.handlerdata\n");
#define IA64_UNWIND_EMIT(f,i) process_for_unwind_directive (f,i)
#define EH_RETURN_DATA_REGNO(N) ((N) < 4 ? (N) + 15 : INVALID_REGNUM)
/* This function contains machine specific function data. */
struct machine_function
{
......
......@@ -4979,13 +4979,6 @@
DONE;
}")
;; Restore the GP after the exception/longjmp. The preceeding call will
;; have tucked it away.
(define_expand "exception_receiver"
[(set (reg:DI 1) (match_dup 0))]
""
"operands[0] = ia64_gp_save_reg (0);")
;; The rest of the setjmp processing happens with the nonlocal_goto expander.
;; ??? This is not tested.
(define_expand "builtin_setjmp_setup"
......
# LIB2ADDEH += $(srcdir)/config/ia64/fde-glibc.c
LIB2ADDEH += $(srcdir)/config/ia64/fde-glibc.c
......@@ -41,4 +41,4 @@ crtendS.o: $(srcdir)/config/ia64/crtend.asm $(GCC_PASSES)
$(GCC_FOR_TARGET) -DSHARED -c -o crtendS.o -x assembler-with-cpp $(srcdir)/config/ia64/crtend.asm
EXTRA_HEADERS = $(srcdir)/config/ia64/ia64intrin.h
# LIB2ADDEH = $(srcdir)/config/ia64/frame-ia64.c
LIB2ADDEH = $(srcdir)/config/ia64/unwind-ia64.c $(srcdir)/unwind-sjlj.c
This diff is collapsed.
/* Copyright (C) 1999, 2000 Free Software Foundation, Inc.
/* Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
Contributed by Andrew MacLeod <amacleod@cygnus.com>
Andrew Haley <aph@cygnus.com>
......@@ -19,18 +19,13 @@
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* This structure represents a single unwind table entry. We lie and say
its the dwarf_fde structure to use the common object in frame.h */
typedef struct dwarf_fde
struct unw_table_entry
{
long start_offset;
long end_offset;
long unwind_offset;
} unwind_table_entry;
/* Defining dwarf_fde allows us to use the common object registration. */
typedef unwind_table_entry dwarf_fde;
typedef unwind_table_entry fde;
unsigned long start_offset;
unsigned long end_offset;
unsigned long info_offset;
};
extern fde *__ia64_find_fde (void *, void **);
extern struct unw_table_entry *
_Unwind_FindTableEntry (void *pc, unsigned long *segment_base,
unsigned long *gp);
......@@ -318,5 +318,12 @@ do { \
#endif
#endif
/* Select a format to encode pointers in exception handling data. We
prefer those that result in fewer dynamic relocations. Assume no
special support here and encode direct references. */
#ifndef ASM_PREFERRED_EH_DATA_FORMAT
#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) DW_EH_PE_absptr
#endif
#endif /* GCC_DEFAULTS_H */
......@@ -22,9 +22,13 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
#include "flags.h"
#include "tree.h"
#include "rtl.h"
#include "output.h"
#include "dwarf2asm.h"
#include "dwarf2.h"
#include "splay-tree.h"
#include "ggc.h"
#include "tm_p.h"
......@@ -647,3 +651,175 @@ dw2_asm_output_delta_sleb128 VPARAMS ((const char *lab1 ATTRIBUTE_UNUSED,
va_end (ap);
}
static rtx dw2_force_const_mem PARAMS ((rtx));
static int dw2_output_indirect_constant_1 PARAMS ((splay_tree_node, void *));
static splay_tree indirect_pool;
static rtx
dw2_force_const_mem (x)
rtx x;
{
splay_tree_node node;
const char *const_sym;
if (! indirect_pool)
indirect_pool = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
if (GET_CODE (x) != SYMBOL_REF)
abort ();
node = splay_tree_lookup (indirect_pool, (splay_tree_key) XSTR (x, 0));
if (node)
const_sym = (const char *) node->value;
else
{
extern int const_labelno;
char label[32];
tree id;
ASM_GENERATE_INTERNAL_LABEL (label, "LC", const_labelno);
++const_labelno;
const_sym = ggc_strdup (label);
id = maybe_get_identifier (XSTR (x, 0));
if (id)
TREE_SYMBOL_REFERENCED (id) = 1;
splay_tree_insert (indirect_pool, (splay_tree_key) XSTR (x, 0),
(splay_tree_value) const_sym);
}
return gen_rtx_SYMBOL_REF (Pmode, const_sym);
}
static int
dw2_output_indirect_constant_1 (node, data)
splay_tree_node node;
void* data ATTRIBUTE_UNUSED;
{
const char *label, *sym;
rtx sym_ref;
label = (const char *) node->value;
sym = (const char *) node->key;
sym_ref = gen_rtx_SYMBOL_REF (Pmode, sym);
ASM_OUTPUT_LABEL (asm_out_file, label);
assemble_integer (sym_ref, POINTER_SIZE / BITS_PER_UNIT, 1);
return 0;
}
void
dw2_output_indirect_constants ()
{
if (! indirect_pool)
return;
/* Assume that the whole reason we're emitting these symbol references
indirectly is that they contain dynamic relocations, and are thus
read-write. If there was no possibility of a dynamic relocation, we
might as well have used a direct relocation. */
data_section ();
/* Everything we're emitting is a pointer. Align appropriately. */
assemble_align (POINTER_SIZE);
splay_tree_foreach (indirect_pool, dw2_output_indirect_constant_1, NULL);
}
void
dw2_asm_output_encoded_addr_rtx (encoding, addr)
int encoding;
rtx addr;
{
int size;
switch (encoding & 0x07)
{
case DW_EH_PE_absptr:
size = POINTER_SIZE / BITS_PER_UNIT;
break;
case DW_EH_PE_udata2:
size = 2;
break;
case DW_EH_PE_udata4:
size = 4;
break;
case DW_EH_PE_udata8:
size = 8;
break;
default:
abort ();
}
/* NULL is _always_ represented as a plain zero. */
if (addr == const0_rtx)
{
assemble_integer (addr, size, 1);
return;
}
restart:
/* Allow the target first crack at emitting this. Some of the
special relocations require special directives instead of
just ".4byte" or whatever. */
#ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX(asm_out_file, encoding, size, addr, done);
#endif
/* Indirection is used to get dynamic relocations out of a read-only
section. */
if (encoding & DW_EH_PE_indirect)
{
/* It is very tempting to use force_const_mem so that we share data
with the normal constant pool. However, we've already emitted
the constant pool for this function. Moreover, we'd like to share
these constants across the entire unit of translation, or better,
across the entire application (or DSO). */
addr = dw2_force_const_mem (addr);
encoding &= ~DW_EH_PE_indirect;
goto restart;
}
switch (encoding & 0xF0)
{
case DW_EH_PE_absptr:
#ifdef UNALIGNED_INT_ASM_OP
fputs (unaligned_integer_asm_op (size), asm_out_file);
output_addr_const (asm_out_file, addr);
#else
assemble_integer (addr, size, 1);
#endif
break;
case DW_EH_PE_pcrel:
if (GET_CODE (addr) != SYMBOL_REF)
abort ();
#ifdef ASM_OUTPUT_DWARF_PCREL
ASM_OUTPUT_DWARF_PCREL (asm_out_file, size, XSTR (addr, 0));
#else
#ifdef UNALIGNED_INT_ASM_OP
fputs (unaligned_integer_asm_op (size), asm_out_file);
assemble_name (asm_out_file, XSTR (addr, 0));
fputc ('-', asm_out_file);
fputc ('.', asm_out_file);
#else
abort ();
#endif
#endif
break;
default:
/* Other encodings should have been handled by
ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX. */
abort ();
}
#ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
done:
#endif
fputc ('\n', asm_out_file);
}
......@@ -48,6 +48,8 @@ extern void dw2_asm_output_addr_rtx PARAMS ((int, rtx,
const char *, ...))
/* ATTRIBUTE_PRINTF_3 */;
extern void dw2_asm_output_encoded_addr_rtx PARAMS ((int, rtx));
extern void dw2_asm_output_nstring PARAMS ((const char *, size_t,
const char *, ...))
/* ATTRIBUTE_PRINTF_3 */;
......@@ -70,3 +72,5 @@ extern void dw2_asm_output_delta_sleb128 PARAMS ((const char *, const char *,
extern int size_of_uleb128 PARAMS ((unsigned HOST_WIDE_INT));
extern int size_of_sleb128 PARAMS ((HOST_WIDE_INT));
extern void dw2_output_indirect_constants PARAMS ((void));
......@@ -1904,14 +1904,35 @@ dwarf2out_begin_prologue ()
char label[MAX_ARTIFICIAL_LABEL_BYTES];
register dw_fde_ref fde;
current_function_func_begin_label = 0;
#ifdef IA64_UNWIND_INFO
/* ??? current_function_func_begin_label is also used by except.c
for call-site information. We must emit this label if it might
be used. */
if ((! flag_exceptions || USING_SJLJ_EXCEPTIONS)
&& ! dwarf2out_do_frame ())
return;
#else
if (! dwarf2out_do_frame ())
return;
#endif
++current_funcdef_number;
function_section (current_function_decl);
ASM_GENERATE_INTERNAL_LABEL (label, FUNC_BEGIN_LABEL,
current_funcdef_number);
ASM_OUTPUT_LABEL (asm_out_file, label);
ASM_OUTPUT_DEBUG_LABEL (asm_out_file, FUNC_BEGIN_LABEL,
current_funcdef_number);
current_function_func_begin_label = get_identifier (label);
#ifdef IA64_UNWIND_INFO
/* We can elide the fde allocation if we're not emitting debug info. */
if (! dwarf2out_do_frame ())
return;
#endif
/* Expand the fde table if necessary. */
if (fde_table_in_use == fde_table_allocated)
{
......
......@@ -62,6 +62,7 @@ Boston, MA 02111-1307, USA. */
#include "output.h"
#include "dwarf2asm.h"
#include "dwarf2out.h"
#include "dwarf2.h"
#include "toplev.h"
#include "hashtab.h"
#include "intl.h"
......@@ -3366,24 +3367,6 @@ push_sleb128 (data_area, value)
}
#define DW_EH_PE_absptr 0x00
#define DW_EH_PE_omit 0xff
#define DW_EH_PE_uleb128 0x01
#define DW_EH_PE_udata2 0x02
#define DW_EH_PE_udata4 0x03
#define DW_EH_PE_udata8 0x04
#define DW_EH_PE_sleb128 0x09
#define DW_EH_PE_sdata2 0x0A
#define DW_EH_PE_sdata4 0x0B
#define DW_EH_PE_sdata8 0x0C
#define DW_EH_PE_signed 0x08
#define DW_EH_PE_pcrel 0x10
#define DW_EH_PE_textrel 0x20
#define DW_EH_PE_datarel 0x30
#define DW_EH_PE_funcrel 0x40
static const char *
eh_data_format_name (format)
int format;
......@@ -3438,6 +3421,74 @@ eh_data_format_name (format)
case DW_EH_PE_sdata4 | DW_EH_PE_funcrel: return "funcrel sdata4";
case DW_EH_PE_sdata8 | DW_EH_PE_funcrel: return "funcrel sdata8";
case DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_pcrel:
return "indirect pcrel uleb128";
case DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_pcrel:
return "indirect pcrel udata2";
case DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_pcrel:
return "indirect pcrel udata4";
case DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_pcrel:
return "indirect pcrel udata8";
case DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_pcrel:
return "indirect pcrel sleb128";
case DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_pcrel:
return "indirect pcrel sdata2";
case DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_pcrel:
return "indirect pcrel sdata4";
case DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_pcrel:
return "indirect pcrel sdata8";
case DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_textrel:
return "indirect textrel uleb128";
case DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_textrel:
return "indirect textrel udata2";
case DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_textrel:
return "indirect textrel udata4";
case DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_textrel:
return "indirect textrel udata8";
case DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_textrel:
return "indirect textrel sleb128";
case DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_textrel:
return "indirect textrel sdata2";
case DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_textrel:
return "indirect textrel sdata4";
case DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_textrel:
return "indirect textrel sdata8";
case DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_datarel:
return "indirect datarel uleb128";
case DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_datarel:
return "indirect datarel udata2";
case DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_datarel:
return "indirect datarel udata4";
case DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_datarel:
return "indirect datarel udata8";
case DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_datarel:
return "indirect datarel sleb128";
case DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_datarel:
return "indirect datarel sdata2";
case DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_datarel:
return "indirect datarel sdata4";
case DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_datarel:
return "indirect datarel sdata8";
case DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_funcrel:
return "indirect funcrel uleb128";
case DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_funcrel:
return "indirect funcrel udata2";
case DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_funcrel:
return "indirect funcrel udata4";
case DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_funcrel:
return "indirect funcrel udata8";
case DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_funcrel:
return "indirect funcrel sleb128";
case DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_funcrel:
return "indirect funcrel sdata2";
case DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_funcrel:
return "indirect funcrel sdata4";
case DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_funcrel:
return "indirect funcrel sdata8";
default:
abort ();
}
......@@ -3551,7 +3602,7 @@ sjlj_output_call_site_table ()
void
output_function_exception_table ()
{
int format, i, n;
int tt_format, cs_format, lp_format, i, n;
#ifdef HAVE_AS_LEB128
char ttype_label[32];
char cs_after_size_label[32];
......@@ -3570,7 +3621,15 @@ output_function_exception_table ()
? sjlj_funcdef_number
: current_funcdef_number);
#ifdef IA64_UNWIND_INFO
fputs ("\t.personality\t", asm_out_file);
output_addr_const (asm_out_file, eh_personality_libfunc);
fputs ("\n\t.handlerdata\n", asm_out_file);
/* Note that varasm still thinks we're in the function's code section.
The ".endp" directive that will immediately follow will take us back. */
#else
exception_section ();
#endif
have_tt_data = (VARRAY_ACTIVE_SIZE (cfun->eh->ttype_data) > 0
|| VARRAY_ACTIVE_SIZE (cfun->eh->ehspec_data) > 0);
......@@ -3588,26 +3647,24 @@ output_function_exception_table ()
be most useful in moving the landing pads completely out of
line to another section, but it could also be used to minimize
the size of uleb128 landing pad offsets. */
format = DW_EH_PE_omit;
dw2_asm_output_data (1, format, "@LPStart format (%s)",
eh_data_format_name (format));
lp_format = DW_EH_PE_omit;
dw2_asm_output_data (1, lp_format, "@LPStart format (%s)",
eh_data_format_name (lp_format));
/* @LPStart pointer would go here. */
/* Indicate the format of the @TType entries. */
if (! have_tt_data)
format = DW_EH_PE_omit;
tt_format = DW_EH_PE_omit;
else
{
/* ??? Define a ASM_PREFERRED_DATA_FORMAT to say what
sort of dynamic-relocation-free reference to emit. */
format = 0;
tt_format = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/1);
#ifdef HAVE_AS_LEB128
ASM_GENERATE_INTERNAL_LABEL (ttype_label, "LLSDATT", funcdef_number);
#endif
}
dw2_asm_output_data (1, format, "@TType format (%s)",
eh_data_format_name (format));
dw2_asm_output_data (1, tt_format, "@TType format (%s)",
eh_data_format_name (tt_format));
#ifndef HAVE_AS_LEB128
if (USING_SJLJ_EXCEPTIONS)
......@@ -3659,12 +3716,12 @@ output_function_exception_table ()
/* Indicate the format of the call-site offsets. */
#ifdef HAVE_AS_LEB128
format = DW_EH_PE_uleb128;
cs_format = DW_EH_PE_uleb128;
#else
format = DW_EH_PE_udata4;
cs_format = DW_EH_PE_udata4;
#endif
dw2_asm_output_data (1, format, "call-site format (%s)",
eh_data_format_name (format));
dw2_asm_output_data (1, cs_format, "call-site format (%s)",
eh_data_format_name (cs_format));
#ifdef HAVE_AS_LEB128
ASM_GENERATE_INTERNAL_LABEL (cs_after_size_label, "LLSDACSB",
......@@ -3706,8 +3763,9 @@ output_function_exception_table ()
else
type = lookup_type_for_runtime (type);
/* ??? Handle ASM_PREFERRED_DATA_FORMAT. */
output_constant (type, GET_MODE_SIZE (ptr_mode));
dw2_asm_output_encoded_addr_rtx (tt_format,
expand_expr (type, NULL_RTX, VOIDmode,
EXPAND_INITIALIZER));
}
#ifdef HAVE_AS_LEB128
......
......@@ -173,12 +173,12 @@ extern tree (*lang_eh_runtime_type) PARAMS ((tree));
mean that we can use call frame exceptions. Detect that the target
has appropriate support. */
#if !defined (EH_RETURN_DATA_REGNO) \
|| !defined(EH_RETURN_STACKADJ_RTX) \
|| ! (defined(EH_RETURN_HANDLER_RTX) \
|| defined(HAVE_eh_return)) \
|| ! (defined(DWARF2_UNWIND_INFO) \
|| defined(IA64_UNWIND_INFO))
#if ! (defined (EH_RETURN_DATA_REGNO) \
&& (defined (IA64_UNWIND_INFO) \
|| (defined (DWARF2_UNWIND_INFO) \
&& defined (EH_RETURN_STACKADJ_RTX) \
&& (defined (EH_RETURN_HANDLER_RTX) \
|| defined (HAVE_eh_return)))))
#define MUST_USE_SJLJ_EXCEPTIONS 1
#else
#define MUST_USE_SJLJ_EXCEPTIONS 0
......
......@@ -1583,12 +1583,9 @@ final_start_function (first, file, optimize)
last_linenum = high_block_linenum = high_function_linenum
= NOTE_LINE_NUMBER (first);
#if defined (DWARF2_UNWIND_INFO) || defined (DWARF2_DEBUGGING_INFO)
/* Output DWARF definition of the function. */
if (dwarf2out_do_frame ())
dwarf2out_begin_prologue ();
else
current_function_func_begin_label = 0;
#if defined (DWARF2_UNWIND_INFO) || defined (IA64_UNWIND_INFO) \
|| defined (DWARF2_DEBUGGING_INFO)
dwarf2out_begin_prologue ();
#endif
/* For SDB and XCOFF, the function beginning must be marked between
......@@ -1811,10 +1808,6 @@ final_end_function (first, file, optimize)
bb_func_label_num = -1; /* not in function, nuke label # */
#ifdef IA64_UNWIND_INFO
output_function_exception_table ();
#endif
/* If FUNCTION_EPILOGUE is not defined, then the function body
itself contains return instructions wherever needed. */
}
......
......@@ -116,6 +116,8 @@ GCC_3.0 {
_Unwind_GetIP
_Unwind_GetLanguageSpecificData
_Unwind_GetRegionStart
_Unwind_GetTextRelBase
_Unwind_GetDataRelBase
_Unwind_RaiseException
_Unwind_Resume
_Unwind_SetGR
......
......@@ -2553,6 +2553,33 @@ the @code{eh_return} instruction pattern should be used instead.
If you want to support call frame exception handling, you must
define either this macro or the @code{eh_return} instruction pattern.
@findex ASM_PREFERRED_EH_DATA_FORMAT
@item ASM_PREFERRED_EH_DATA_FORMAT(@var{CODE}, @var{GLOBAL})
This macro chooses the encoding of pointers embedded in the exception
handling sections. If at all possible, this should be defined such
that the exception handling section will not require dynamic relocations,
and so may be read-only.
@var{CODE} is 0 for data, 1 for code labels, 2 for function pointers.
@var{GLOBAL} is true if the symbol may be affected by dynamic relocations.
The macro should return a combination of the @code{DW_EH_PE_*} defines
as found in @file{dwarf2.h}.
If this macro is not defined, pointers will not be encoded but
represented directly.
@findex ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
@item ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX(@var{FILE}, @var{ENCODING}, @var{SIZE}, @var{ADDR}, @var{DONE})
This macro allows the target to emit whatever special magic is required
to represent the encoding chosen by @code{ASM_PREFERRED_EH_DATA_FORMAT}.
Generic code takes care of pc-relative and indirect encodings; this must
be defined if the target uses text-relative or data-relative encodings.
This is a C statement that branches to @var{DONE} if the format was
handled. @var{ENCODING} is the format chosen, @var{SIZE} is the number
of bytes that the format occupies, @var{ADDR} is the @code{SYMBOL_REF}
to be emitted.
@findex SMALL_STACK
@item SMALL_STACK
Define this macro if the stack size for the target is very small. This
......
......@@ -2404,6 +2404,8 @@ compile_file (name)
/* Output some stuff at end of file if nec. */
dw2_output_indirect_constants ();
end_final (dump_base_name);
if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
......@@ -3721,9 +3723,19 @@ rest_of_compilation (decl)
final_start_function (insns, asm_out_file, optimize);
final (insns, asm_out_file, optimize, 0);
final_end_function (insns, asm_out_file, optimize);
#ifdef IA64_UNWIND_INFO
/* ??? The IA-64 ".handlerdata" directive must be issued before
the ".endp" directive that closes the procedure descriptor. */
output_function_exception_table ();
#endif
assemble_end_function (decl, fnname);
#ifndef IA64_UNWIND_INFO
/* Otherwise, it feels unclean to switch sections in the middle. */
output_function_exception_table ();
#endif
if (! quiet_flag)
fflush (asm_out_file);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment