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:
Richard Henderson 2008-08-05 10:24:37 -07:00 committed by Richard Henderson
parent cdaf871beb
commit d4ea462245
11 changed files with 519 additions and 10 deletions

View File

@ -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.

View File

@ -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)

View File

@ -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__");

View File

@ -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

View File

@ -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
View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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;

View File

@ -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. */

View File

@ -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 = &current_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. */