mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-21 02:50:27 +08:00
Makefile.in (c-cppbuiltin.o): Depend on debug.h.
* Makefile.in (c-cppbuiltin.o): Depend on debug.h. * c-cppbuiltin.c (c_cpp_builtins): Define __GCC_HAVE_DWARF2_CFI_ASM. * doc/cpp.texi (__GCC_HAVE_DWARF2_CFI_ASM): Document it. * common.opt (fdwarf2-cfi-asm): New. * configure.ac (HAVE_GAS_CFI_DIRECTIVE): New. * config.in, configure: Rebuild. * dwarf2asm.c (dw2_asm_output_data_raw): New. (dw2_asm_output_data_uleb128_raw, dw2_asm_output_data_sleb128_raw): New. (dw2_force_const_mem): Externalize. * dwarf2asm.h: Update. * dwarf2out.c (dwarf2out_cfi_label): If flag_dwarf2_cfi_asm, don't generate a real label. (output_cfi_directive): New. (add_fde_cfi): If flag_dwarf2_cfi_asm, use it. (output_call_frame_info): Do nothing if flag_dwarf2_cfi_asm. (dwarf2out_begin_prologue): Emit .cfi_startproc, .cfi_personality, and .cfi_lsda. (dwarf2out_end_epilogue): Emit .cfi_endproc. (output_loc_operands_raw, output_loc_sequence_raw): New. (output_cfa_loc_raw): New. From-SVN: r138733
This commit is contained in:
parent
cdaf871beb
commit
d4ea462245
@ -1,3 +1,26 @@
|
||||
2008-08-05 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* Makefile.in (c-cppbuiltin.o): Depend on debug.h.
|
||||
* c-cppbuiltin.c (c_cpp_builtins): Define __GCC_HAVE_DWARF2_CFI_ASM.
|
||||
* doc/cpp.texi (__GCC_HAVE_DWARF2_CFI_ASM): Document it.
|
||||
* common.opt (fdwarf2-cfi-asm): New.
|
||||
* configure.ac (HAVE_GAS_CFI_DIRECTIVE): New.
|
||||
* config.in, configure: Rebuild.
|
||||
* dwarf2asm.c (dw2_asm_output_data_raw): New.
|
||||
(dw2_asm_output_data_uleb128_raw, dw2_asm_output_data_sleb128_raw): New.
|
||||
(dw2_force_const_mem): Externalize.
|
||||
* dwarf2asm.h: Update.
|
||||
* dwarf2out.c (dwarf2out_cfi_label): If flag_dwarf2_cfi_asm, don't
|
||||
generate a real label.
|
||||
(output_cfi_directive): New.
|
||||
(add_fde_cfi): If flag_dwarf2_cfi_asm, use it.
|
||||
(output_call_frame_info): Do nothing if flag_dwarf2_cfi_asm.
|
||||
(dwarf2out_begin_prologue): Emit .cfi_startproc, .cfi_personality,
|
||||
and .cfi_lsda.
|
||||
(dwarf2out_end_epilogue): Emit .cfi_endproc.
|
||||
(output_loc_operands_raw, output_loc_sequence_raw): New.
|
||||
(output_cfa_loc_raw): New.
|
||||
|
||||
2008-08-05 Paul Brook <paul@codesourcery.com>
|
||||
|
||||
* doc/invoke.texi: Document new ARM -mfpu= and -mcpu= options.
|
||||
|
@ -1870,8 +1870,9 @@ c-opts.o : c-opts.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
|
||||
$< $(OUTPUT_OPTION) @TARGET_SYSTEM_ROOT_DEFINE@
|
||||
|
||||
c-cppbuiltin.o : c-cppbuiltin.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
|
||||
$(TREE_H) version.h $(C_COMMON_H) $(C_PRAGMA_H) $(FLAGS_H) $(TOPLEV_H) \
|
||||
output.h except.h $(REAL_H) $(TARGET_H) $(TM_P_H) $(BASEVER)
|
||||
$(TREE_H) version.h $(C_COMMON_H) $(C_PRAGMA_H) $(FLAGS_H) \
|
||||
$(TOPLEV_H) output.h except.h $(REAL_H) $(TARGET_H) $(TM_P_H) \
|
||||
$(BASEVER) debug.h
|
||||
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) -DBASEVER=$(BASEVER_s) \
|
||||
$< $(OUTPUT_OPTION)
|
||||
|
||||
|
@ -30,6 +30,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "c-pragma.h"
|
||||
#include "output.h"
|
||||
#include "except.h" /* For USING_SJLJ_EXCEPTIONS. */
|
||||
#include "debug.h" /* For dwarf2out_do_frame. */
|
||||
#include "toplev.h"
|
||||
#include "tm_p.h" /* Target prototypes. */
|
||||
#include "target.h"
|
||||
@ -691,6 +692,11 @@ c_cpp_builtins (cpp_reader *pfile)
|
||||
cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16");
|
||||
#endif
|
||||
|
||||
#ifdef DWARF2_UNWIND_INFO
|
||||
if (flag_dwarf2_cfi_asm && dwarf2out_do_frame ())
|
||||
cpp_define (pfile, "__GCC_HAVE_DWARF2_CFI_ASM");
|
||||
#endif
|
||||
|
||||
/* Make the choice of ObjC runtime visible to source code. */
|
||||
if (c_dialect_objc () && flag_next_runtime)
|
||||
cpp_define (pfile, "__NEXT_RUNTIME__");
|
||||
|
@ -459,6 +459,10 @@ fdump-unnumbered
|
||||
Common Report Var(flag_dump_unnumbered) VarExists
|
||||
Suppress output of instruction numbers, line number notes and addresses in debugging dumps
|
||||
|
||||
fdwarf2-cfi-asm
|
||||
Common Report Var(flag_dwarf2_cfi_asm) Init(HAVE_GAS_CFI_DIRECTIVE)
|
||||
Enable CFI tables via GAS assembler directives.
|
||||
|
||||
fearly-inlining
|
||||
Common Report Var(flag_early_inlining) Init(1) Optimization
|
||||
Perform early inlining
|
||||
|
@ -821,6 +821,12 @@
|
||||
#endif
|
||||
|
||||
|
||||
/* Define 0/1 if your assembler supports CFI directives. */
|
||||
#ifndef USED_FOR_TARGET
|
||||
#undef HAVE_GAS_CFI_DIRECTIVE
|
||||
#endif
|
||||
|
||||
|
||||
/* Define if your assembler uses the new HImode fild and fist notation. */
|
||||
#ifndef USED_FOR_TARGET
|
||||
#undef HAVE_GAS_FILDS_FISTS
|
||||
|
44
gcc/configure
vendored
44
gcc/configure
vendored
@ -20832,6 +20832,50 @@ _ACEOF
|
||||
|
||||
fi
|
||||
|
||||
# Check if we have assembler support for unwind directives.
|
||||
echo "$as_me:$LINENO: checking assembler for cfi directives" >&5
|
||||
echo $ECHO_N "checking assembler for cfi directives... $ECHO_C" >&6
|
||||
if test "${gcc_cv_as_cfi_directive+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
gcc_cv_as_cfi_directive=no
|
||||
if test $in_tree_gas = yes; then
|
||||
if test $in_tree_gas_is_elf = yes \
|
||||
&& test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 17 \) \* 1000 + 0`
|
||||
then gcc_cv_as_cfi_directive=yes
|
||||
fi
|
||||
elif test x$gcc_cv_as != x; then
|
||||
echo ' .text
|
||||
.cfi_startproc
|
||||
.cfi_offset 0, 0
|
||||
.cfi_same_value 1
|
||||
.cfi_def_cfa 1, 2
|
||||
.cfi_escape 1, 2, 3, 4, 5
|
||||
.cfi_endproc' > conftest.s
|
||||
if { ac_try='$gcc_cv_as -o conftest.o conftest.s >&5'
|
||||
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); }; }
|
||||
then
|
||||
gcc_cv_as_cfi_directive=yes
|
||||
else
|
||||
echo "configure: failed program was" >&5
|
||||
cat conftest.s >&5
|
||||
fi
|
||||
rm -f conftest.o conftest.s
|
||||
fi
|
||||
fi
|
||||
echo "$as_me:$LINENO: result: $gcc_cv_as_cfi_directive" >&5
|
||||
echo "${ECHO_T}$gcc_cv_as_cfi_directive" >&6
|
||||
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE_GAS_CFI_DIRECTIVE `if test $gcc_cv_as_cfi_directive = yes; then echo 1; else echo 0; fi`
|
||||
_ACEOF
|
||||
|
||||
|
||||
# GAS versions up to and including 2.11.0 may mis-optimize
|
||||
# .eh_frame data.
|
||||
echo "$as_me:$LINENO: checking assembler for eh_frame optimization" >&5
|
||||
|
@ -2180,6 +2180,20 @@ changequote([,])dnl
|
||||
[AC_DEFINE(HAVE_AS_LEB128, 1,
|
||||
[Define if your assembler supports .sleb128 and .uleb128.])])
|
||||
|
||||
# Check if we have assembler support for unwind directives.
|
||||
gcc_GAS_CHECK_FEATURE([cfi directives], gcc_cv_as_cfi_directive,
|
||||
[elf,2,17,0],,
|
||||
[ .text
|
||||
.cfi_startproc
|
||||
.cfi_offset 0, 0
|
||||
.cfi_same_value 1
|
||||
.cfi_def_cfa 1, 2
|
||||
.cfi_escape 1, 2, 3, 4, 5
|
||||
.cfi_endproc])
|
||||
AC_DEFINE_UNQUOTED(HAVE_GAS_CFI_DIRECTIVE,
|
||||
[`if test $gcc_cv_as_cfi_directive = yes; then echo 1; else echo 0; fi`],
|
||||
[Define 0/1 if your assembler supports CFI directives.])
|
||||
|
||||
# GAS versions up to and including 2.11.0 may mis-optimize
|
||||
# .eh_frame data.
|
||||
gcc_GAS_CHECK_FEATURE(eh_frame optimization, gcc_cv_as_eh_frame,
|
||||
|
@ -2239,6 +2239,10 @@ If GCC cannot determine the current date, it will emit a warning message
|
||||
These macros are defined when the target processor supports atomic compare
|
||||
and swap operations on operands 1, 2, 4, 8 or 16 bytes in length, respectively.
|
||||
|
||||
@item __GCC_HAVE_DWARF2_CFI_ASM
|
||||
This macro is defined when the compiler is emitting Dwarf2 CFI directives
|
||||
to the assembler. When this is defined, it is possible to emit those same
|
||||
directives in inline assembly.
|
||||
@end table
|
||||
|
||||
@node System-specific Predefined Macros
|
||||
|
@ -62,6 +62,34 @@ dw2_assemble_integer (int size, rtx x)
|
||||
}
|
||||
|
||||
|
||||
/* Output a value of a given size in target byte order. */
|
||||
|
||||
void
|
||||
dw2_asm_output_data_raw (int size, unsigned HOST_WIDE_INT value)
|
||||
{
|
||||
unsigned char bytes[8];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 8; ++i)
|
||||
{
|
||||
bytes[i] = value & 0xff;
|
||||
value >>= 8;
|
||||
}
|
||||
|
||||
if (BYTES_BIG_ENDIAN)
|
||||
{
|
||||
for (i = size - 1; i > 0; --i)
|
||||
fprintf (asm_out_file, "0x%x,", bytes[i]);
|
||||
fprintf (asm_out_file, "0x%x", bytes[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < size - 1; ++i)
|
||||
fprintf (asm_out_file, "0x%x,", bytes[i]);
|
||||
fprintf (asm_out_file, "0x%x", bytes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Output an immediate constant in a given SIZE in bytes. */
|
||||
|
||||
void
|
||||
@ -505,6 +533,26 @@ eh_data_format_name (int format)
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Output an unsigned LEB128 quantity, but only the byte values. */
|
||||
|
||||
void
|
||||
dw2_asm_output_data_uleb128_raw (unsigned HOST_WIDE_INT value)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
int byte = (value & 0x7f);
|
||||
value >>= 7;
|
||||
if (value != 0)
|
||||
/* More bytes to follow. */
|
||||
byte |= 0x80;
|
||||
|
||||
fprintf (asm_out_file, "0x%x", byte);
|
||||
if (value == 0)
|
||||
break;
|
||||
fputc (',', asm_out_file);
|
||||
}
|
||||
}
|
||||
|
||||
/* Output an unsigned LEB128 quantity. */
|
||||
|
||||
void
|
||||
@ -566,6 +614,29 @@ dw2_asm_output_data_uleb128 (unsigned HOST_WIDE_INT value,
|
||||
va_end (ap);
|
||||
}
|
||||
|
||||
/* Output an signed LEB128 quantity, but only the byte values. */
|
||||
|
||||
void
|
||||
dw2_asm_output_data_sleb128_raw (HOST_WIDE_INT value)
|
||||
{
|
||||
int byte, more;
|
||||
|
||||
while (1)
|
||||
{
|
||||
byte = (value & 0x7f);
|
||||
value >>= 7;
|
||||
more = !((value == 0 && (byte & 0x40) == 0)
|
||||
|| (value == -1 && (byte & 0x40) != 0));
|
||||
if (more)
|
||||
byte |= 0x80;
|
||||
|
||||
fprintf (asm_out_file, "0x%x", byte);
|
||||
if (!more)
|
||||
break;
|
||||
fputc (',', asm_out_file);
|
||||
}
|
||||
}
|
||||
|
||||
/* Output a signed LEB128 quantity. */
|
||||
|
||||
void
|
||||
@ -689,7 +760,6 @@ dw2_asm_output_delta_sleb128 (const char *lab1 ATTRIBUTE_UNUSED,
|
||||
}
|
||||
#endif /* 0 */
|
||||
|
||||
static rtx dw2_force_const_mem (rtx, bool);
|
||||
static int dw2_output_indirect_constant_1 (splay_tree_node, void *);
|
||||
|
||||
static GTY((param1_is (char *), param2_is (tree))) splay_tree indirect_pool;
|
||||
@ -733,7 +803,7 @@ splay_tree_compare_strings (splay_tree_key k1, splay_tree_key k2)
|
||||
"near" the function in any interesting sense. IS_PUBLIC controls whether
|
||||
the symbol can be shared across the entire application (or DSO). */
|
||||
|
||||
static rtx
|
||||
rtx
|
||||
dw2_force_const_mem (rtx x, bool is_public)
|
||||
{
|
||||
splay_tree_node node;
|
||||
|
@ -20,6 +20,8 @@ along with GCC; see the file COPYING3. If not see
|
||||
|
||||
extern void dw2_assemble_integer (int, rtx);
|
||||
|
||||
extern void dw2_asm_output_data_raw (int, unsigned HOST_WIDE_INT);
|
||||
|
||||
extern void dw2_asm_output_data (int, unsigned HOST_WIDE_INT,
|
||||
const char *, ...)
|
||||
ATTRIBUTE_NULL_PRINTF_3;
|
||||
@ -46,10 +48,14 @@ extern void dw2_asm_output_nstring (const char *, size_t,
|
||||
const char *, ...)
|
||||
ATTRIBUTE_NULL_PRINTF_3;
|
||||
|
||||
extern void dw2_asm_output_data_uleb128_raw (unsigned HOST_WIDE_INT);
|
||||
|
||||
extern void dw2_asm_output_data_uleb128 (unsigned HOST_WIDE_INT,
|
||||
const char *, ...)
|
||||
ATTRIBUTE_NULL_PRINTF_2;
|
||||
|
||||
extern void dw2_asm_output_data_sleb128_raw (HOST_WIDE_INT);
|
||||
|
||||
extern void dw2_asm_output_data_sleb128 (HOST_WIDE_INT,
|
||||
const char *, ...)
|
||||
ATTRIBUTE_NULL_PRINTF_2;
|
||||
@ -63,6 +69,7 @@ extern int size_of_sleb128 (HOST_WIDE_INT);
|
||||
extern int size_of_encoded_value (int);
|
||||
extern const char *eh_data_format_name (int);
|
||||
|
||||
extern rtx dw2_force_const_mem (rtx, bool);
|
||||
extern void dw2_output_indirect_constants (void);
|
||||
|
||||
/* These are currently unused. */
|
||||
|
342
gcc/dwarf2out.c
342
gcc/dwarf2out.c
@ -384,6 +384,7 @@ static void initial_return_save (rtx);
|
||||
#endif
|
||||
static HOST_WIDE_INT stack_adjust_offset (const_rtx);
|
||||
static void output_cfi (dw_cfi_ref, dw_fde_ref, int);
|
||||
static void output_cfi_directive (dw_cfi_ref);
|
||||
static void output_call_frame_info (int);
|
||||
static void dwarf2out_note_section_used (void);
|
||||
static void dwarf2out_stack_adjust (rtx, bool);
|
||||
@ -394,6 +395,7 @@ static void dwarf2out_frame_debug_expr (rtx, const char *);
|
||||
|
||||
/* Support for complex CFA locations. */
|
||||
static void output_cfa_loc (dw_cfi_ref);
|
||||
static void output_cfa_loc_raw (dw_cfi_ref);
|
||||
static void get_cfa_from_loc_descr (dw_cfa_location *,
|
||||
struct dw_loc_descr_struct *);
|
||||
static struct dw_loc_descr_struct *build_cfa_loc
|
||||
@ -665,8 +667,19 @@ dwarf2out_cfi_label (void)
|
||||
{
|
||||
static char label[20];
|
||||
|
||||
ASM_GENERATE_INTERNAL_LABEL (label, "LCFI", dwarf2out_cfi_label_num++);
|
||||
ASM_OUTPUT_LABEL (asm_out_file, label);
|
||||
if (flag_dwarf2_cfi_asm)
|
||||
{
|
||||
/* In this case, we will be emitting the asm directive instead of
|
||||
the label, so just return a placeholder to keep the rest of the
|
||||
interfaces happy. */
|
||||
strcpy (label, "<do not output>");
|
||||
}
|
||||
else
|
||||
{
|
||||
ASM_GENERATE_INTERNAL_LABEL (label, "LCFI", dwarf2out_cfi_label_num++);
|
||||
ASM_OUTPUT_LABEL (asm_out_file, label);
|
||||
}
|
||||
|
||||
return label;
|
||||
}
|
||||
|
||||
@ -676,7 +689,25 @@ dwarf2out_cfi_label (void)
|
||||
static void
|
||||
add_fde_cfi (const char *label, dw_cfi_ref cfi)
|
||||
{
|
||||
if (label)
|
||||
dw_cfi_ref *list_head = &cie_cfi_head;
|
||||
|
||||
if (flag_dwarf2_cfi_asm)
|
||||
{
|
||||
if (label)
|
||||
{
|
||||
output_cfi_directive (cfi);
|
||||
|
||||
/* We still have to add the cfi to the list so that
|
||||
lookup_cfa works later on. */
|
||||
list_head = ¤t_fde ()->dw_fde_cfi;
|
||||
}
|
||||
/* ??? If this is a CFI for the CIE, we don't emit. This
|
||||
assumes that the standard CIE contents that the assembler
|
||||
uses matches the standard CIE contents that the compiler
|
||||
uses. This is probably a bad assumption. I'm not quite
|
||||
sure how to address this for now. */
|
||||
}
|
||||
else if (label)
|
||||
{
|
||||
dw_fde_ref fde = current_fde ();
|
||||
|
||||
@ -705,11 +736,10 @@ add_fde_cfi (const char *label, dw_cfi_ref cfi)
|
||||
fde->dw_fde_current_label = label;
|
||||
}
|
||||
|
||||
add_cfi (&fde->dw_fde_cfi, cfi);
|
||||
list_head = &fde->dw_fde_cfi;
|
||||
}
|
||||
|
||||
else
|
||||
add_cfi (&cie_cfi_head, cfi);
|
||||
add_cfi (list_head, cfi);
|
||||
}
|
||||
|
||||
/* Subroutine of lookup_cfa. */
|
||||
@ -2619,6 +2649,100 @@ output_cfi (dw_cfi_ref cfi, dw_fde_ref fde, int for_eh)
|
||||
}
|
||||
}
|
||||
|
||||
/* Similar, but do it via assembler directives instead. */
|
||||
|
||||
static void
|
||||
output_cfi_directive (dw_cfi_ref cfi)
|
||||
{
|
||||
unsigned long r, r2;
|
||||
|
||||
switch (cfi->dw_cfi_opc)
|
||||
{
|
||||
case DW_CFA_advance_loc:
|
||||
case DW_CFA_advance_loc1:
|
||||
case DW_CFA_advance_loc2:
|
||||
case DW_CFA_advance_loc4:
|
||||
case DW_CFA_MIPS_advance_loc8:
|
||||
case DW_CFA_set_loc:
|
||||
/* Should only be created by add_fde_cfi in a code path not
|
||||
followed when emitting via directives. The assembler is
|
||||
going to take care of this for us. */
|
||||
gcc_unreachable ();
|
||||
|
||||
case DW_CFA_offset:
|
||||
case DW_CFA_offset_extended:
|
||||
case DW_CFA_offset_extended_sf:
|
||||
r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 0);
|
||||
fprintf (asm_out_file, "\t.cfi_offset %lu, "HOST_WIDE_INT_PRINT_DEC"\n",
|
||||
r, cfi->dw_cfi_oprnd2.dw_cfi_offset * DWARF_CIE_DATA_ALIGNMENT);
|
||||
break;
|
||||
|
||||
case DW_CFA_restore:
|
||||
case DW_CFA_restore_extended:
|
||||
r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 0);
|
||||
fprintf (asm_out_file, "\t.cfi_restore %lu\n", r);
|
||||
break;
|
||||
|
||||
case DW_CFA_undefined:
|
||||
r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 0);
|
||||
fprintf (asm_out_file, "\t.cfi_undefined %lu\n", r);
|
||||
break;
|
||||
|
||||
case DW_CFA_same_value:
|
||||
r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 0);
|
||||
fprintf (asm_out_file, "\t.cfi_same_value %lu\n", r);
|
||||
break;
|
||||
|
||||
case DW_CFA_def_cfa:
|
||||
case DW_CFA_def_cfa_sf:
|
||||
r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 0);
|
||||
fprintf (asm_out_file, "\t.cfi_def_cfa %lu, "HOST_WIDE_INT_PRINT_DEC"\n",
|
||||
r, cfi->dw_cfi_oprnd2.dw_cfi_offset);
|
||||
break;
|
||||
|
||||
case DW_CFA_def_cfa_register:
|
||||
r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 0);
|
||||
fprintf (asm_out_file, "\t.cfi_def_cfa_register %lu\n", r);
|
||||
break;
|
||||
|
||||
case DW_CFA_register:
|
||||
r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 0);
|
||||
r2 = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd2.dw_cfi_reg_num, 0);
|
||||
fprintf (asm_out_file, "\t.cfi_register %lu, %lu\n", r, r2);
|
||||
break;
|
||||
|
||||
case DW_CFA_def_cfa_offset:
|
||||
case DW_CFA_def_cfa_offset_sf:
|
||||
fprintf (asm_out_file, "\t.cfi_def_cfa_offset "
|
||||
HOST_WIDE_INT_PRINT_DEC"\n",
|
||||
cfi->dw_cfi_oprnd1.dw_cfi_offset);
|
||||
break;
|
||||
|
||||
case DW_CFA_GNU_args_size:
|
||||
fprintf (asm_out_file, "\t.cfi_escape 0x%x,", DW_CFA_GNU_args_size);
|
||||
dw2_asm_output_data_uleb128_raw (cfi->dw_cfi_oprnd1.dw_cfi_offset);
|
||||
if (flag_debug_asm)
|
||||
fprintf (asm_out_file, "\t%s args_size "HOST_WIDE_INT_PRINT_DEC,
|
||||
ASM_COMMENT_START, cfi->dw_cfi_oprnd1.dw_cfi_offset);
|
||||
fputc ('\n', asm_out_file);
|
||||
break;
|
||||
|
||||
case DW_CFA_GNU_window_save:
|
||||
fprintf (asm_out_file, "\t.cfi_window_save\n");
|
||||
break;
|
||||
|
||||
case DW_CFA_def_cfa_expression:
|
||||
case DW_CFA_expression:
|
||||
fprintf (asm_out_file, "\t.cfi_escape 0x%x,", cfi->dw_cfi_opc);
|
||||
output_cfa_loc_raw (cfi);
|
||||
fputc ('\n', asm_out_file);
|
||||
break;
|
||||
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
}
|
||||
|
||||
/* Output the call frame information used to record information
|
||||
that relates to calculating the frame pointer, and records the
|
||||
location of saved registers. */
|
||||
@ -2642,6 +2766,10 @@ output_call_frame_info (int for_eh)
|
||||
if (fde_table_in_use == 0)
|
||||
return;
|
||||
|
||||
/* Nothing to do if the assembler's doing it all. */
|
||||
if (flag_dwarf2_cfi_asm)
|
||||
return;
|
||||
|
||||
/* If we make FDEs linkonce, we may have to emit an empty label for
|
||||
an FDE that wouldn't otherwise be emitted. We want to avoid
|
||||
having an FDE kept around when the function it refers to is
|
||||
@ -3058,6 +3186,49 @@ dwarf2out_begin_prologue (unsigned int line ATTRIBUTE_UNUSED,
|
||||
if (file)
|
||||
dwarf2out_source_line (line, file);
|
||||
#endif
|
||||
|
||||
if (flag_dwarf2_cfi_asm)
|
||||
{
|
||||
int enc;
|
||||
rtx ref;
|
||||
|
||||
fprintf (asm_out_file, "\t.cfi_startproc\n");
|
||||
|
||||
if (eh_personality_libfunc)
|
||||
{
|
||||
enc = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/2, /*global=*/1);
|
||||
ref = eh_personality_libfunc;
|
||||
|
||||
/* ??? The GAS support isn't entirely consistent. We have to
|
||||
handle indirect support ourselves, but PC-relative is done
|
||||
in the assembler. Further, the assembler can't handle any
|
||||
of the weirder relocation types. */
|
||||
if (enc & DW_EH_PE_indirect)
|
||||
ref = dw2_force_const_mem (ref, true);
|
||||
|
||||
fprintf (asm_out_file, "\t.cfi_personality 0x%x,", enc);
|
||||
output_addr_const (asm_out_file, ref);
|
||||
fputc ('\n', asm_out_file);
|
||||
}
|
||||
|
||||
if (crtl->uses_eh_lsda)
|
||||
{
|
||||
char lab[20];
|
||||
|
||||
enc = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/0);
|
||||
ASM_GENERATE_INTERNAL_LABEL (lab, "LLSDA",
|
||||
current_function_funcdef_no);
|
||||
ref = gen_rtx_SYMBOL_REF (Pmode, lab);
|
||||
SYMBOL_REF_FLAGS (ref) = SYMBOL_FLAG_LOCAL;
|
||||
|
||||
if (enc & DW_EH_PE_indirect)
|
||||
ref = dw2_force_const_mem (ref, true);
|
||||
|
||||
fprintf (asm_out_file, "\t.cfi_lsda 0x%x,", enc);
|
||||
output_addr_const (asm_out_file, ref);
|
||||
fputc ('\n', asm_out_file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Output a marker (i.e. a label) for the absolute end of the generated code
|
||||
@ -3071,6 +3242,9 @@ dwarf2out_end_epilogue (unsigned int line ATTRIBUTE_UNUSED,
|
||||
dw_fde_ref fde;
|
||||
char label[MAX_ARTIFICIAL_LABEL_BYTES];
|
||||
|
||||
if (flag_dwarf2_cfi_asm)
|
||||
fprintf (asm_out_file, "\t.cfi_endproc\n");
|
||||
|
||||
/* Output a label to mark the endpoint of the code generated for this
|
||||
function. */
|
||||
ASM_GENERATE_INTERNAL_LABEL (label, FUNC_END_LABEL,
|
||||
@ -3931,6 +4105,141 @@ output_loc_sequence (dw_loc_descr_ref loc)
|
||||
}
|
||||
}
|
||||
|
||||
/* Output location description stack opcode's operands (if any).
|
||||
The output is single bytes on a line, suitable for .cfi_escape. */
|
||||
|
||||
static void
|
||||
output_loc_operands_raw (dw_loc_descr_ref loc)
|
||||
{
|
||||
dw_val_ref val1 = &loc->dw_loc_oprnd1;
|
||||
dw_val_ref val2 = &loc->dw_loc_oprnd2;
|
||||
|
||||
switch (loc->dw_loc_opc)
|
||||
{
|
||||
case DW_OP_addr:
|
||||
/* We cannot output addresses in .cfi_escape, only bytes. */
|
||||
gcc_unreachable ();
|
||||
|
||||
case DW_OP_const1u:
|
||||
case DW_OP_const1s:
|
||||
case DW_OP_pick:
|
||||
case DW_OP_deref_size:
|
||||
case DW_OP_xderef_size:
|
||||
fputc (',', asm_out_file);
|
||||
dw2_asm_output_data_raw (1, val1->v.val_int);
|
||||
break;
|
||||
|
||||
case DW_OP_const2u:
|
||||
case DW_OP_const2s:
|
||||
fputc (',', asm_out_file);
|
||||
dw2_asm_output_data_raw (2, val1->v.val_int);
|
||||
break;
|
||||
|
||||
case DW_OP_const4u:
|
||||
case DW_OP_const4s:
|
||||
fputc (',', asm_out_file);
|
||||
dw2_asm_output_data_raw (4, val1->v.val_int);
|
||||
break;
|
||||
|
||||
case DW_OP_const8u:
|
||||
case DW_OP_const8s:
|
||||
gcc_assert (HOST_BITS_PER_LONG >= 64);
|
||||
fputc (',', asm_out_file);
|
||||
dw2_asm_output_data_raw (8, val1->v.val_int);
|
||||
break;
|
||||
|
||||
case DW_OP_skip:
|
||||
case DW_OP_bra:
|
||||
{
|
||||
int offset;
|
||||
|
||||
gcc_assert (val1->val_class == dw_val_class_loc);
|
||||
offset = val1->v.val_loc->dw_loc_addr - (loc->dw_loc_addr + 3);
|
||||
|
||||
fputc (',', asm_out_file);
|
||||
dw2_asm_output_data_raw (2, offset);
|
||||
}
|
||||
break;
|
||||
|
||||
case DW_OP_constu:
|
||||
case DW_OP_plus_uconst:
|
||||
case DW_OP_regx:
|
||||
case DW_OP_piece:
|
||||
fputc (',', asm_out_file);
|
||||
dw2_asm_output_data_uleb128_raw (val1->v.val_unsigned);
|
||||
break;
|
||||
|
||||
case DW_OP_consts:
|
||||
case DW_OP_breg0:
|
||||
case DW_OP_breg1:
|
||||
case DW_OP_breg2:
|
||||
case DW_OP_breg3:
|
||||
case DW_OP_breg4:
|
||||
case DW_OP_breg5:
|
||||
case DW_OP_breg6:
|
||||
case DW_OP_breg7:
|
||||
case DW_OP_breg8:
|
||||
case DW_OP_breg9:
|
||||
case DW_OP_breg10:
|
||||
case DW_OP_breg11:
|
||||
case DW_OP_breg12:
|
||||
case DW_OP_breg13:
|
||||
case DW_OP_breg14:
|
||||
case DW_OP_breg15:
|
||||
case DW_OP_breg16:
|
||||
case DW_OP_breg17:
|
||||
case DW_OP_breg18:
|
||||
case DW_OP_breg19:
|
||||
case DW_OP_breg20:
|
||||
case DW_OP_breg21:
|
||||
case DW_OP_breg22:
|
||||
case DW_OP_breg23:
|
||||
case DW_OP_breg24:
|
||||
case DW_OP_breg25:
|
||||
case DW_OP_breg26:
|
||||
case DW_OP_breg27:
|
||||
case DW_OP_breg28:
|
||||
case DW_OP_breg29:
|
||||
case DW_OP_breg30:
|
||||
case DW_OP_breg31:
|
||||
case DW_OP_fbreg:
|
||||
fputc (',', asm_out_file);
|
||||
dw2_asm_output_data_sleb128_raw (val1->v.val_int);
|
||||
break;
|
||||
|
||||
case DW_OP_bregx:
|
||||
fputc (',', asm_out_file);
|
||||
dw2_asm_output_data_uleb128_raw (val1->v.val_unsigned);
|
||||
fputc (',', asm_out_file);
|
||||
dw2_asm_output_data_sleb128_raw (val2->v.val_int);
|
||||
break;
|
||||
|
||||
case INTERNAL_DW_OP_tls_addr:
|
||||
gcc_unreachable ();
|
||||
|
||||
default:
|
||||
/* Other codes have no operands. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
output_loc_sequence_raw (dw_loc_descr_ref loc)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
/* Output the opcode. */
|
||||
fprintf (asm_out_file, "0x%x", loc->dw_loc_opc);
|
||||
output_loc_operands_raw (loc);
|
||||
|
||||
if (!loc->dw_loc_next)
|
||||
break;
|
||||
loc = loc->dw_loc_next;
|
||||
|
||||
fputc (',', asm_out_file);
|
||||
}
|
||||
}
|
||||
|
||||
/* This routine will generate the correct assembly data for a location
|
||||
description based on a cfi entry with a complex address. */
|
||||
|
||||
@ -3952,6 +4261,27 @@ output_cfa_loc (dw_cfi_ref cfi)
|
||||
output_loc_sequence (loc);
|
||||
}
|
||||
|
||||
/* Similar, but used for .cfi_escape. */
|
||||
|
||||
static void
|
||||
output_cfa_loc_raw (dw_cfi_ref cfi)
|
||||
{
|
||||
dw_loc_descr_ref loc;
|
||||
unsigned long size;
|
||||
|
||||
if (cfi->dw_cfi_opc == DW_CFA_expression)
|
||||
fprintf (asm_out_file, "0x%x,", cfi->dw_cfi_oprnd2.dw_cfi_reg_num);
|
||||
|
||||
/* Output the size of the block. */
|
||||
loc = cfi->dw_cfi_oprnd1.dw_cfi_loc;
|
||||
size = size_of_locs (loc);
|
||||
dw2_asm_output_data_uleb128_raw (size);
|
||||
fputc (',', asm_out_file);
|
||||
|
||||
/* Now output the operations themselves. */
|
||||
output_loc_sequence_raw (loc);
|
||||
}
|
||||
|
||||
/* This function builds a dwarf location descriptor sequence from a
|
||||
dw_cfa_location, adding the given OFFSET to the result of the
|
||||
expression. */
|
||||
|
Loading…
x
Reference in New Issue
Block a user