1 # DP: The Dwarf EH patch for powerpc, from Andrew Macleod, via Franz Sirl
2 # DP: (Revised for gcc 2.95)
5 --- collect2.c 1999/05/17 22:56:24 1.72
6 +++ gcc/collect2.c 1999/06/12 18:55:22
7 @@ -2955,6 +2955,21 @@ scan_prog_file (prog_name, which_pass)
8 add_to_list (&destructors, name);
12 + add_to_list (&frame_tables, name);
13 +#ifdef COLLECT_EXPORT_LIST
14 + if (which_pass == PASS_OBJ)
15 + add_to_list (&exports, name);
16 + /* If this symbol was undefined and we are building
17 + an import list, we should add a symbol to this
21 + && is_in_list (name, undefined.first))
22 + add_to_list (&imports, name);
27 default: /* not a constructor or destructor */
28 #ifdef COLLECT_EXPORT_LIST
30 --- dwarf2.h 1999/01/11 13:43:21 1.11
31 +++ gcc/dwarf2.h 1999/06/12 18:55:25
32 @@ -501,7 +501,8 @@ enum dwarf_call_frame_info
35 DW_CFA_GNU_window_save = 0x2d,
36 - DW_CFA_GNU_args_size = 0x2e
37 + DW_CFA_GNU_args_size = 0x2e,
38 + DW_CFA_GNU_negative_offset_extended = 0x2f
41 #define DW_CIE_ID 0xffffffff
42 Index: gcc/dwarf2out.c
43 --- dwarf2out.c 1999/06/03 02:30:03 1.91.4.2
44 +++ gcc/dwarf2out.c 1999/06/12 18:55:27
45 @@ -415,38 +415,54 @@ static void dwarf2out_stack_adjust PROTO
46 /* We don't have unaligned support, let's hope the normal output works for
49 +#ifndef ASM_OUTPUT_DWARF_ADDR
50 #define ASM_OUTPUT_DWARF_ADDR(FILE,LABEL) \
51 assemble_integer (gen_rtx_SYMBOL_REF (Pmode, LABEL), PTR_SIZE, 1)
54 +#ifndef ASM_OUTPUT_DWARF_OFFSET4
55 #define ASM_OUTPUT_DWARF_OFFSET4(FILE,LABEL) \
56 assemble_integer (gen_rtx_SYMBOL_REF (SImode, LABEL), 4, 1)
59 +#ifndef ASM_OUTPUT_DWARF_OFFSET
60 #define ASM_OUTPUT_DWARF_OFFSET(FILE,LABEL) \
61 assemble_integer (gen_rtx_SYMBOL_REF (SImode, LABEL), 4, 1)
64 +#ifndef ASM_OUTPUT_DWARF_DELTA2
65 #define ASM_OUTPUT_DWARF_DELTA2(FILE,LABEL1,LABEL2) \
66 assemble_integer (gen_rtx_MINUS (HImode, \
67 gen_rtx_SYMBOL_REF (Pmode, LABEL1), \
68 gen_rtx_SYMBOL_REF (Pmode, LABEL2)), \
72 +#ifndef ASM_OUTPUT_DWARF_DELTA4
73 #define ASM_OUTPUT_DWARF_DELTA4(FILE,LABEL1,LABEL2) \
74 assemble_integer (gen_rtx_MINUS (SImode, \
75 gen_rtx_SYMBOL_REF (Pmode, LABEL1), \
76 gen_rtx_SYMBOL_REF (Pmode, LABEL2)), \
80 +#ifndef ASM_OUTPUT_DWARF_ADDR_DELTA
81 #define ASM_OUTPUT_DWARF_ADDR_DELTA(FILE,LABEL1,LABEL2) \
82 assemble_integer (gen_rtx_MINUS (Pmode, \
83 gen_rtx_SYMBOL_REF (Pmode, LABEL1), \
84 gen_rtx_SYMBOL_REF (Pmode, LABEL2)), \
88 +#ifndef ASM_OUTPUT_DWARF_DELTA
89 #define ASM_OUTPUT_DWARF_DELTA(FILE,LABEL1,LABEL2) \
90 ASM_OUTPUT_DWARF_DELTA4 (FILE,LABEL1,LABEL2)
93 +#ifndef ASM_OUTPUT_DWARF_DATA4
94 #define ASM_OUTPUT_DWARF_DATA4(FILE,VALUE) \
95 assemble_integer (GEN_INT (VALUE), 4, 1)
98 #endif /* UNALIGNED_INT_ASM_OP */
100 @@ -719,6 +735,8 @@ dwarf_cfi_name (cfi_opc)
101 return "DW_CFA_GNU_window_save";
102 case DW_CFA_GNU_args_size:
103 return "DW_CFA_GNU_args_size";
104 + case DW_CFA_GNU_negative_offset_extended:
105 + return "DW_CFA_GNU_negative_offset_extended";
108 return "DW_CFA_<unknown>";
109 @@ -948,7 +966,10 @@ reg_save (label, reg, sreg, offset)
111 offset /= DWARF_CIE_DATA_ALIGNMENT;
115 + cfi->dw_cfi_opc = DW_CFA_GNU_negative_offset_extended;
118 cfi->dw_cfi_oprnd2.dw_cfi_offset = offset;
121 @@ -1421,6 +1442,10 @@ dwarf2out_frame_debug (insn)
125 + /* A temporary register used in adjusting SP or setting up the store_reg. */
126 + static unsigned cfa_temp_reg;
127 + static long cfa_temp_value;
129 if (insn == NULL_RTX)
131 /* Set up state for generating call frame debug info. */
132 @@ -1635,6 +1660,7 @@ output_cfi (cfi, fde)
135 case DW_CFA_offset_extended:
136 + case DW_CFA_GNU_negative_offset_extended:
138 output_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
139 fputc ('\n', asm_out_file);
140 @@ -5862,6 +5888,14 @@ output_line_info ()
141 /* We used to set the address register to the first location in the text
142 section here, but that didn't accomplish anything since we already
143 have a line note for the opening brace of the first function. */
145 + fputc ('\n', asm_out_file);
146 + output_uleb128 (1 + PTR_SIZE);
147 + fputc ('\n', asm_out_file);
148 + ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNE_set_address);
149 + fputc ('\n', asm_out_file);
150 + ASM_OUTPUT_DWARF_ADDR (asm_out_file, text_section_label);
151 + fputc ('\n', asm_out_file);
153 /* Generate the line number to PC correspondence table, encoded as
154 a series of state machine operations. */
155 Index: gcc/dwarfout.c
156 --- dwarfout.c 1999/04/18 13:09:27 1.35
157 +++ gcc/dwarfout.c 1999/06/12 18:55:29
158 @@ -864,7 +864,7 @@ static int is_redundant_typedef PROTO((
159 ASM_OUTPUT_ASCII ((FILE), P, strlen (P)+1)
161 #define ASM_OUTPUT_DWARF_STRING_NEWLINE(FILE,P) \
162 - ASM_OUTPUT_DWARF_STRING (FILE,P), ASM_OUTPUT_DWARF_STRING (FILE,"\n")
163 + do { ASM_OUTPUT_DWARF_STRING (FILE,P); ASM_OUTPUT_DWARF_STRING (FILE,"\n"); } while (0)
168 --- except.c 1999/04/15 19:54:09 1.82
169 +++ gcc/except.c 1999/06/12 18:55:30
170 @@ -2706,7 +2706,7 @@ eh_regs (pcontext, psp, pra, outgoing)
171 rtx *pcontext, *psp, *pra;
174 - rtx rcontext, rsp, rra;
175 + rtx rcontext, rsp, rra = NULL_RTX;
178 #ifdef FUNCTION_OUTGOING_VALUE
179 @@ -2718,6 +2718,16 @@ eh_regs (pcontext, psp, pra, outgoing)
180 rcontext = FUNCTION_VALUE (build_pointer_type (void_type_node),
181 current_function_decl);
183 +/* If we've specified the register to communicate the stack offset or
184 + return address, use it instead of picking one */
186 +#ifdef DWARF2_EH_RA_REG
187 + rra = gen_rtx_REG (Pmode, DWARF2_EH_RA_REG);
190 +#ifdef DWARF2_EH_SP_REG
191 + rsp = gen_rtx_REG (Pmode, DWARF2_EH_SP_REG);
193 #ifdef STATIC_CHAIN_REGNUM
195 rsp = static_chain_incoming_rtx;
196 @@ -2726,6 +2736,7 @@ eh_regs (pcontext, psp, pra, outgoing)
197 if (REGNO (rsp) == REGNO (rcontext))
198 #endif /* STATIC_CHAIN_REGNUM */
204 @@ -2738,14 +2749,16 @@ eh_regs (pcontext, psp, pra, outgoing)
205 rsp = gen_rtx_REG (Pmode, i);
208 - for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
209 - if (call_used_regs[i] && ! fixed_regs[i]
210 - && i != REGNO (rcontext) && i != REGNO (rsp))
212 - if (i == FIRST_PSEUDO_REGISTER)
215 - rra = gen_rtx_REG (Pmode, i);
216 + if (rra == NULL_RTX)
218 + for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
219 + if (call_used_regs[i] && ! fixed_regs[i]
220 + && i != REGNO (rcontext) && i != REGNO (rsp))
222 + if (i == FIRST_PSEUDO_REGISTER)
224 + rra = gen_rtx_REG (Pmode, i);
227 *pcontext = rcontext;
229 @@ -2808,7 +2821,8 @@ expand_eh_return ()
230 #ifdef HAVE_eh_epilogue
231 if (HAVE_eh_epilogue)
233 - emit_insn (gen_eh_epilogue (reg1, reg2, reg3));
234 + emit_insn (gen_eh_epilogue (eh_return_context, eh_return_stack_adjust,
235 + eh_return_handler));
239 @@ -2833,6 +2847,12 @@ expand_eh_return ()
241 emit_move_insn (ra, tmp);
243 + eh_regs (®1, ®2, ®3, 1);
245 + emit_move_insn (reg1, eh_return_context);
246 + emit_move_insn (reg2, eh_return_stack_adjust);
247 + emit_move_insn (reg3, eh_return_handler);
249 /* Indicate that the registers are in fact used. */
250 emit_insn (gen_rtx_USE (VOIDmode, reg1));
251 emit_insn (gen_rtx_USE (VOIDmode, reg2));
253 --- frame.c 1998/12/16 20:55:48 1.25
254 +++ gcc/frame.c 1999/06/12 18:55:30
255 @@ -714,6 +714,14 @@ execute_cfa_insn (void *p, struct frame_
256 state->s.args_size = offset;
259 + case DW_CFA_GNU_negative_offset_extended:
260 + p = decode_uleb128 (p, ®);
261 + p = decode_uleb128 (p, &offset);
262 + offset *= info->data_align;
263 + state->s.saved[reg] = REG_SAVED_OFFSET;
264 + state->s.reg_or_offset[reg] = -offset;
270 Index: gcc/config/rs6000/aix31.h
271 --- aix31.h 1998/12/16 21:11:43 1.2
272 +++ gcc/config/rs6000/aix31.h 1999/06/12 18:55:33
273 @@ -22,6 +22,7 @@ Boston, MA 02111-1307, USA. */
276 #include "rs6000/rs6000.h"
277 +#include "aix-dwarf.h"
279 /* AIX 3.2 defined _AIX32, but older versions do not. */
280 #undef CPP_PREDEFINES
281 Index: gcc/config/rs6000/aix3newas.h
282 --- aix3newas.h 1998/12/16 21:11:44 1.2
283 +++ gcc/config/rs6000/aix3newas.h 1999/06/12 18:55:33
284 @@ -30,6 +30,7 @@ Boston, MA 02111-1307, USA. */
285 {"no-xl-call", - MASK_XL_CALL},
287 #include "rs6000/rs6000.h"
288 +#include "aix-dwarf.h"
290 /* Tell the assembler to assume that all undefined names are external. */
292 Index: gcc/config/rs6000/aix41.h
293 --- aix41.h 1999/03/27 18:21:29 1.6
294 +++ gcc/config/rs6000/aix41.h 1999/06/12 18:55:33
295 @@ -32,6 +32,7 @@ Boston, MA 02111-1307, USA. */
298 #include "rs6000/rs6000.h"
299 +#include "aix-dwarf.h"
302 #define ASM_SPEC "-u %(asm_cpu)"
303 Index: gcc/config/rs6000/aix43.h
304 --- aix43.h 1999/05/03 20:10:05 1.5
305 +++ gcc/config/rs6000/aix43.h 1999/06/12 18:55:33
306 @@ -58,6 +58,7 @@ do { \
309 #include "rs6000/rs6000.h"
310 +#include "aix-dwarf.h"
313 #define ASM_SPEC "-u %{maix64:-a64 -mppc64} %(asm_cpu)"
314 Index: gcc/config/rs6000/eabi-ci.asm
315 --- eabi-ci.asm 1998/12/16 21:11:50 1.2
316 +++ gcc/config/rs6000/eabi-ci.asm 1999/06/12 18:55:33
317 @@ -102,6 +102,11 @@ __SBSS2_START__:
318 .type __EXCEPT_START__,@object
321 + .section ".eh_frame","aw"
322 + .globl __EH_FRAME_BEGIN__
323 + .type __EH_FRAME_BEGIN__,@object
326 # Head of __init function used for static constructors in Solaris
327 .section ".init","ax"
329 Index: gcc/config/rs6000/eabi-cn.asm
330 --- eabi-cn.asm 1998/12/16 21:11:51 1.2
331 +++ gcc/config/rs6000/eabi-cn.asm 1999/06/12 18:55:33
332 @@ -94,6 +94,12 @@ __SBSS2_END__:
333 .type __EXCEPT_END__,@object
336 + .section ".eh_frame","aw"
337 + .globl __EH_FRAME_END__
338 + .type __EH_FRAME_END__,@object
342 # Tail of __init used for static constructors in Solaris
343 .section ".init","ax"
345 Index: gcc/config/rs6000/eabi-ctors.c
346 --- eabi-ctors.c 1998/12/16 21:11:52 1.2
347 +++ gcc/config/rs6000/eabi-ctors.c 1999/06/12 18:55:33
348 @@ -40,7 +40,24 @@ extern func_ptr __CTOR_LIST__[];
349 extern func_ptr __CTOR_END__ [];
350 extern func_ptr __DTOR_LIST__[];
351 extern func_ptr __DTOR_END__ [];
352 +extern char __EH_FRAME_BEGIN__ [];
357 + struct dwarf_fde *fde_begin;
358 + struct dwarf_fde **fde_array;
360 + struct object *next;
363 +extern void __register_frame_info (void *, struct object *);
364 +extern void __register_frame_info_table (void *, struct object *);
365 +extern void __deregister_frame_info (void *);
368 +#define EH_FRAME_SECTION_ASM_OP ".section\t.eh_frame,\"aw\""
370 extern void __do_global_ctors (void);
371 extern void __do_global_dtors (void);
373 @@ -61,6 +78,11 @@ __do_global_ctors (void)
374 func_ptr *ptr = &__CTOR_LIST__[0];
375 func_ptr *end = &__CTOR_END__[0];
377 +#ifdef EH_FRAME_SECTION_ASM_OP
378 + static struct object object;
379 + __register_frame_info (__EH_FRAME_BEGIN__, &object);
383 __atexit (__do_global_dtors);
385 @@ -88,5 +110,8 @@ __do_global_dtors (void)
386 for ( ; ptr >= start; ptr--)
391 +#ifdef EH_FRAME_SECTION_ASM_OP
392 + __deregister_frame_info (__EH_FRAME_BEGIN__);
395 Index: gcc/config/rs6000/rs6000.c
396 --- rs6000.c 1999/06/09 15:59:36 1.70.4.2
397 +++ gcc/config/rs6000/rs6000.c 1999/06/12 18:55:34
398 @@ -77,6 +77,11 @@ static int common_mode_defined;
399 rtx rs6000_compare_op0, rs6000_compare_op1;
400 int rs6000_compare_fp_p;
402 +/* If we've defined this, we need a counter for the fixup labels */
403 +#ifdef ASM_OUTPUT_DWARF_ADDR
404 +int dwarflabelno = 0;
408 /* Label number of label created for -mrelocatable, to call to so we can
409 get the address of the GOT section */
410 @@ -3860,6 +3874,9 @@ rs6000_allocate_stack_space (file, size,
414 +#define SET_DWARF_LABEL(X) (X = ((X == NULL) ? \
415 + (char *) dwarf2out_cfi_label () : X ))
418 /* Write function prologue. */
420 @@ -3873,6 +3890,7 @@ output_prolog (file, size)
421 const char *load_reg;
424 + char *dw2_label = NULL;
428 @@ -3948,6 +3966,19 @@ output_prolog (file, size)
429 asm_fprintf (file, "\tbl %s%d%s\n", SAVE_FP_PREFIX,
430 info->first_fp_reg_save - 32, SAVE_FP_SUFFIX);
432 + /* Regardless of whether its inlined or not, the net effect at this point
433 + is that the FPRs have been saved from first to the end.*/
434 + if (dwarf2out_do_frame () && info->first_fp_reg_save != 64)
436 + int regno = info->first_fp_reg_save;
437 + int loc = info->fp_save_offset;
438 + SET_DWARF_LABEL (dw2_label);
439 + for ( ; regno < 64; regno++, loc += 8)
441 + dwarf2out_reg_save (dw2_label, regno, loc);
445 /* Now save gpr's. */
446 if (! TARGET_MULTIPLE || info->first_gp_reg_save == 31 || TARGET_64BIT)
448 @@ -3964,6 +3995,19 @@ output_prolog (file, size)
449 info->gp_save_offset + sp_offset,
452 + /* Regardless of whether its inlined or not, the net effect at this point
453 + is that the GPRs have been saved from first to the end.*/
454 + if (dwarf2out_do_frame () && info->first_gp_reg_save != 32)
456 + int regno = info->first_gp_reg_save;
457 + int loc = info->gp_save_offset;
458 + SET_DWARF_LABEL (dw2_label);
459 + for ( ; regno < 32; regno++, loc += reg_size)
461 + dwarf2out_reg_save (dw2_label, regno, loc);
465 /* Save main's arguments if we need to call a function */
467 if (info->main_save_p)
468 @@ -3982,6 +4026,11 @@ output_prolog (file, size)
469 asm_fprintf (file, store_reg, reg_names[0], info->lr_save_offset + sp_offset,
472 + if (dwarf2out_do_frame () && info->lr_save_p)
474 + SET_DWARF_LABEL (dw2_label);
475 + dwarf2out_return_save (dw2_label, info->lr_save_offset);
477 /* Save CR if we use any that must be preserved. */
480 @@ -3995,6 +4044,13 @@ output_prolog (file, size)
482 asm_fprintf (file, store_reg, reg_names[12], info->cr_save_offset + sp_offset,
484 + /* we save all the condition registers as if they are a single
485 + register. The are physically, so this should work fine. */
486 + if (dwarf2out_do_frame ())
488 + SET_DWARF_LABEL (dw2_label);
489 + dwarf2out_reg_save (dw2_label, 70, info->cr_save_offset);
493 /* If we need PIC_OFFSET_TABLE_REGNUM, initialize it now */
494 @@ -4054,6 +4110,14 @@ output_prolog (file, size)
495 if (info->push_p && DEFAULT_ABI != ABI_V4 && DEFAULT_ABI != ABI_SOLARIS)
496 rs6000_allocate_stack_space (file, info->total_size, FALSE);
498 + /* Update the stack frame by size, We update it for all targets here
499 + at the end since we saved everything relative to the incoming value. */
501 + if (dwarf2out_do_frame () && info->push_p)
503 + SET_DWARF_LABEL (dw2_label);
504 + dwarf2out_def_cfa (dw2_label, 1 , info->total_size);
506 /* Set frame pointer, if needed. */
507 if (frame_pointer_needed)
508 asm_fprintf (file, "\tmr %s,%s\n", reg_names[31], reg_names[1]);
509 Index: gcc/config/rs6000/rs6000.h
510 --- rs6000.h 1999/06/09 15:59:37 1.49.4.1
511 +++ gcc/config/rs6000/rs6000.h 1999/06/12 18:55:36
512 @@ -3139,6 +3175,54 @@ do { \
514 #define ASM_OPEN_PAREN "("
515 #define ASM_CLOSE_PAREN ")"
517 +#define ASM_OUTPUT_DWARF_STRING(FILE,P) \
519 + register int slen = strlen(P); \
520 + register char *p = (P); \
522 + fprintf (FILE, "\t.asciz \""); \
523 + for (i = 0; i < slen; i++) \
525 + register int c = p[i]; \
526 + if (c == '\"' || c == '\\') \
527 + putc ('\\', FILE); \
528 + if (c >= ' ' && c < 0177) \
532 + fprintf (FILE, "\\%o", c); \
535 + fprintf (FILE, "\""); \
540 +/* We can't communicate with the epilogue directly via the eh_epilogue
541 + pattern, because we need to adjust the stack pointer JUST before
542 + returning. If the floating point registers are restored via a
543 + function call (instead of being inlined), we can't adjust the stack
544 + before the callor the floating point registers will be restored from
545 + the wrong address (its based of the SP.) Control never returns
546 + from these routines since the return address is adjusted such that
547 + when they return, they go to the target location. We leave the stub
548 + mechanism in place, let the function or FP routines return to the stub
549 + and do things the normal way. We have to tell the stub mechanism
550 + whiuch registers to use however, since the general mechanism
551 + in eh_regs (except.c) will end up choosing r0 (which is overwritten
552 + by the epilogue, and R11, which is used by the epilogue for system V
553 + targets. We'll just always use R4 and R5. Thats good for all targets. */
555 +#define DWARF2_EH_SP_REG 4
556 +#define DWARF2_EH_RA_REG 5
559 +/* Pick up the return address upon entry to a procedure. Used for
560 + dwarf2 unwind information. This also enables the table driven mechanism. */
562 +#define INCOMING_RETURN_ADDR_RTX gen_rtx (REG, Pmode, 65)
565 /* Define results of standard character escape sequences. */
566 #define TARGET_BELL 007
567 Index: gcc/config/rs6000/rs6000.md
568 --- rs6000.md 1999/06/09 15:59:39 1.55.4.1
569 +++ gcc/config/rs6000/rs6000.md 1999/06/12 18:55:37
570 @@ -7738,7 +7738,7 @@
572 (define_insn "nonlocal_goto_receiver"
573 [(unspec_volatile [(const_int 0)] 1)]
574 - "TARGET_TOC && TARGET_MINIMAL_TOC"
575 + "TARGET_TOC && TARGET_MINIMAL_TOC && get_pool_size () != 0"
578 rs6000_output_load_toc_table (asm_out_file, 30);
579 Index: gcc/config/rs6000/sysv4.h
580 --- sysv4.h 1999/05/28 02:46:56 1.19.4.1
581 +++ gcc/config/rs6000/sysv4.h 1999/06/12 18:55:38
582 @@ -803,6 +803,40 @@ do { \
583 fprintf (FILE, "\t.long "); \
584 output_addr_const (FILE, (VALUE)); \
585 fprintf (FILE, "\n"); \
590 +/* This is how to output an assembler line defining an address
591 + constant for the dwarf call unwinding information.
592 + For -mrelocatable, we mark all addresses that need to be fixed up
593 + in the .fixup section. */
595 +extern int dwarflabelno;
597 +#undef ASM_OUTPUT_DWARF_ADDR
598 +#define ASM_OUTPUT_DWARF_ADDR(FILE,LABEL) \
600 + if ((TARGET_RELOCATABLE || flag_pic)) \
602 + char buf[256], *p; \
604 + ASM_GENERATE_INTERNAL_LABEL (buf, "LCDW", dwarflabelno++); \
605 + STRIP_NAME_ENCODING (p, buf); \
606 + fprintf (FILE, "%s:\n", p); \
607 + fprintf (FILE, "\t.4byte\t"); \
608 + assemble_name (FILE, LABEL); \
609 + fprintf (FILE, "\n"); \
610 + fprintf (FILE, "\t.section \".fixup\",\"aw\"\n"); \
611 + ASM_OUTPUT_ALIGN (FILE, 2); \
612 + fprintf (FILE, "\t.long\t%s\n", p); \
613 + fprintf (FILE, "\t.previous\n"); \
617 + fprintf (FILE, "\t.4byte\t"); \
618 + assemble_name (FILE, LABEL); \
619 + fprintf (FILE, "\n"); \